无关风月
4 天以前 b84fc1807a6ce71f4d10cdb10da186abc5dcc173
Merge remote-tracking branch 'origin/master'

# Conflicts:
# ruoyi-system/src/main/java/com/ruoyi/system/service/OaApprovalApplicationStorageService.java
# ruoyi-system/src/main/java/com/ruoyi/system/service/impl/OaApprovalApplicationStorageServiceImpl.java
29个文件已修改
10个文件已添加
1640 ■■■■■ 已修改文件
pom.xml 7 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/OaApprovalApplicationAssetController.java 33 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/OaApprovalApplicationStorageController.java 63 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/OaApprovalApplicationsController.java 61 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/FileUploadController.java 43 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-prod.yml 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-admin/src/main/resources/application-test.yml 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/pom.xml 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/config/OssConfig.java 59 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-common/src/main/java/com/ruoyi/common/core/controller/FileController.java 7 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationAssetReceiveDTO.java 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationPurchaseDTO.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationStorageDTO.java 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationStorageGeneralDTO.java 48 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationStoragePropertyDTO.java 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationStorageVehicleDTO.java 10 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/mapper/OaApprovalApplicationAssetMapper.java 9 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/AssetGeneralExt.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/AssetMain.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/AssetPropertyExt.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/OaApprovalApplicationAsset.java 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/model/OaApprovalApplications.java 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/query/OaApprovalApplicationAssetPageQuery.java 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/OaApprovalApplicationAssetService.java 15 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/OaApprovalApplicationStorageService.java 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/OssService.java 28 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AssetTypeServiceImpl.java 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/OaApprovalApplicationAssetServiceImpl.java 32 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/OaApprovalApplicationPurchaseServiceImpl.java 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/OaApprovalApplicationStorageServiceImpl.java 361 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/OssServiceImpl.java 119 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/AssetTypeTreeVO.java 5 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/OaApprovalApplicationAssetDetailVO.java 78 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/OaApprovalApplicationAssetPageVO.java 47 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/OaApprovalApplicationStorageGeneralDetailVO.java 118 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/OaApprovalApplicationStoragePropertyDetailVO.java 170 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/OaApprovalApplicationStorageVehicleDetailVO.java 143 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/OaApprovalApplicationAssetMapper.xml 36 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml 8 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
pom.xml
@@ -30,6 +30,7 @@
        <poi.version>4.1.2</poi.version>
        <velocity.version>2.3</velocity.version>
        <jwt.version>0.9.1</jwt.version>
        <aliyun-oss.version>3.17.4</aliyun-oss.version>
    </properties>
    <!-- 依赖声明 -->
@@ -156,6 +157,12 @@
                <version>${ruoyi.version}</version>
            </dependency>
            <!--阿里云oss-->
            <dependency>
                <groupId>com.aliyun.oss</groupId>
                <artifactId>aliyun-sdk-oss</artifactId>
                <version>${aliyun-oss.version}</version>
            </dependency>
        </dependencies>
    </dependencyManagement>
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/OaApprovalApplicationAssetController.java
@@ -1,16 +1,23 @@
package com.ruoyi.web.controller.api;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.dto.asset.OaApprovalApplicationAssetReceiveDTO;
import com.ruoyi.system.query.OaApprovalApplicationAssetPageQuery;
import com.ruoyi.system.service.OaApprovalApplicationAssetService;
import com.ruoyi.system.vo.asset.OaApprovalApplicationAssetPageVO;
import com.ruoyi.system.vo.asset.OaApprovalApplicationAssetDetailVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@@ -38,5 +45,29 @@
        oaApprovalApplicationAssetService.submitReceive(dto);
        return R.ok();
    }
}
    @ApiOperation("获取资产领用申请分页列表")
    @PostMapping("/page-list")
    public R<IPage<OaApprovalApplicationAssetPageVO>> getReceivePageList(@RequestBody OaApprovalApplicationAssetPageQuery pageQuery) {
        // 数据权限:非管理员仅能查看本部门
        Long userId = SecurityUtils.getUserId();
        boolean isAdmin = SecurityUtils.isAdmin(userId);
        if (!isAdmin) {
            try {
                pageQuery.setDeptId(Integer.valueOf(SecurityUtils.getDeptId()));
            } catch (Exception e) {
                // ignore parse, leave null if cannot parse
            }
        }
        IPage<OaApprovalApplicationAssetPageVO> page = oaApprovalApplicationAssetService.getReceivePageList(pageQuery);
        return R.ok(page);
    }
    @ApiOperation("获取资产领用详情")
    @GetMapping("/detail/receive/{id}")
    public R<OaApprovalApplicationAssetDetailVO> getReceiveDetail(@PathVariable Integer id) {
        OaApprovalApplicationAssetDetailVO detail = oaApprovalApplicationAssetService.getDetail(id);
        return R.ok(detail);
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/OaApprovalApplicationStorageController.java
@@ -17,14 +17,20 @@
import com.ruoyi.system.service.OaApprovalApplicationStorageService;
import com.ruoyi.system.service.TDeptService;
import com.ruoyi.system.vo.asset.OaApprovalApplicationStoragePageVO;
import com.ruoyi.system.vo.asset.OaApprovalApplicationStorageGeneralDetailVO;
import com.ruoyi.system.vo.asset.OaApprovalApplicationStoragePropertyDetailVO;
import com.ruoyi.system.vo.asset.OaApprovalApplicationStorageVehicleDetailVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.GetMapping;
import javax.validation.Valid;
@@ -52,6 +58,16 @@
    @Log(title = "通用资产入库申请-提交", businessType = BusinessType.INSERT)
    public R<Void> submitGeneralAssetStorage(@Valid @RequestBody OaApprovalApplicationStorageGeneralDTO dto) {
        validateAddress(dto);
        // 校验每条明细的权属单位/部门名称是否存在
        for (OaApprovalApplicationStorageGeneralDTO.GeneralAssetItemDTO item : dto.getAssetItems()) {
            if (StringUtils.isEmpty(item.getOwnershipDeptName())) {
                throw new ServiceException("权属单位/部门名称不能为空");
            }
            TDept owner = deptService.lambdaQuery().eq(TDept::getDeptName, item.getOwnershipDeptName()).one();
            if (owner == null) {
                throw new ServiceException("权属单位/部门不存在: " + item.getOwnershipDeptName());
            }
        }
        oaApprovalApplicationStorageService.submitGeneralAssetStorage(dto);
        return R.ok();
    }
@@ -61,6 +77,15 @@
    @Log(title = "房产资产入库申请-提交", businessType = BusinessType.INSERT)
    public R<Void> submitPropertyAssetStorage(@Valid @RequestBody OaApprovalApplicationStoragePropertyDTO dto) {
        validateAddress(dto);
        for (OaApprovalApplicationStoragePropertyDTO.PropertyAssetItemDTO item : dto.getAssetItems()) {
            if (StringUtils.isEmpty(item.getOwnershipDeptName())) {
                throw new ServiceException("权属单位/部门名称不能为空");
            }
            TDept owner = deptService.lambdaQuery().eq(TDept::getDeptName, item.getOwnershipDeptName()).one();
            if (owner == null) {
                throw new ServiceException("权属单位/部门不存在: " + item.getOwnershipDeptName());
            }
        }
        oaApprovalApplicationStorageService.submitPropertyAssetStorage(dto);
        return R.ok();
    }
@@ -70,6 +95,15 @@
    @Log(title = "车辆资产入库申请-提交", businessType = BusinessType.INSERT)
    public R<Void> submitVehicleAssetStorage(@Valid @RequestBody OaApprovalApplicationStorageVehicleDTO dto) {
        validateAddress(dto);
        for (OaApprovalApplicationStorageVehicleDTO.VehicleAssetItemDTO item : dto.getAssetItems()) {
            if (StringUtils.isEmpty(item.getOwnershipDeptName())) {
                throw new ServiceException("权属单位/部门名称不能为空");
            }
            TDept owner = deptService.lambdaQuery().eq(TDept::getDeptName, item.getOwnershipDeptName()).one();
            if (owner == null) {
                throw new ServiceException("权属单位/部门不存在: " + item.getOwnershipDeptName());
            }
        }
        oaApprovalApplicationStorageService.submitVehicleAssetStorage(dto);
        return R.ok();
    }
@@ -81,6 +115,35 @@
        return R.ok(page);
    }
    @ApiOperation("删除资产入库申请")
    @DeleteMapping("/{id}")
    @Log(title = "资产入库申请-删除", businessType = BusinessType.DELETE)
    public R<Void> delete(@PathVariable Integer id) {
        oaApprovalApplicationStorageService.removeById(id);
        return R.ok();
    }
    @ApiOperation("获取通用资产入库申请详情")
    @GetMapping("/detail/general/{id}")
    public R<OaApprovalApplicationStorageGeneralDetailVO> getGeneralDetail(@PathVariable Integer id) {
        OaApprovalApplicationStorageGeneralDetailVO detail = oaApprovalApplicationStorageService.getGeneralDetail(id);
        return R.ok(detail);
    }
    @ApiOperation("获取房产资产入库申请详情")
    @GetMapping("/detail/property/{id}")
    public R<OaApprovalApplicationStoragePropertyDetailVO> getPropertyDetail(@PathVariable Integer id) {
        OaApprovalApplicationStoragePropertyDetailVO detail = oaApprovalApplicationStorageService.getPropertyDetail(id);
        return R.ok(detail);
    }
    @ApiOperation("获取车辆资产入库申请详情")
    @GetMapping("/detail/vehicle/{id}")
    public R<OaApprovalApplicationStorageVehicleDetailVO> getVehicleDetail(@PathVariable Integer id) {
        OaApprovalApplicationStorageVehicleDetailVO detail = oaApprovalApplicationStorageService.getVehicleDetail(id);
        return R.ok(detail);
    }
    /**
     * 校验位置类型与相关名称/地址
     */
ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/OaApprovalApplicationsController.java
@@ -6,21 +6,54 @@
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.entity.TDept;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.bean.BeanUtils;
import com.ruoyi.framework.web.service.TokenService;
import com.ruoyi.system.dto.*;
import com.ruoyi.system.emums.ApprovalFlowNodeEnum;
import com.ruoyi.system.dto.AddAdvertisementDTO;
import com.ruoyi.system.dto.AddBusinessTripDTO;
import com.ruoyi.system.dto.AddContactDTO;
import com.ruoyi.system.dto.AddContractDTO;
import com.ruoyi.system.dto.AddLeaveDTO;
import com.ruoyi.system.dto.AddLeaveDestroyDTO;
import com.ruoyi.system.dto.AddMoneyDTO;
import com.ruoyi.system.dto.AddOutDTO;
import com.ruoyi.system.dto.AddPaymentDTO;
import com.ruoyi.system.dto.AddReimbursementDTO;
import com.ruoyi.system.emums.ApprovalStatusEnum;
import com.ruoyi.system.emums.ApprovalTypeEnum;
import com.ruoyi.system.model.*;
import com.ruoyi.system.service.*;
import com.ruoyi.system.model.OaApprovalApplicationAdvertisement;
import com.ruoyi.system.model.OaApprovalApplicationAttendance;
import com.ruoyi.system.model.OaApprovalApplicationContact;
import com.ruoyi.system.model.OaApprovalApplicationContract;
import com.ruoyi.system.model.OaApprovalApplicationMoney;
import com.ruoyi.system.model.OaApprovalApplicationPayment;
import com.ruoyi.system.model.OaApprovalApplicationReimbursement;
import com.ruoyi.system.model.OaApprovalApplicationReimbursementItem;
import com.ruoyi.system.model.OaApprovalApplications;
import com.ruoyi.system.model.OaApprovalFlowNode;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.OaApprovalApplicationAdvertisementService;
import com.ruoyi.system.service.OaApprovalApplicationAttendanceService;
import com.ruoyi.system.service.OaApprovalApplicationContactService;
import com.ruoyi.system.service.OaApprovalApplicationContractService;
import com.ruoyi.system.service.OaApprovalApplicationMoneyService;
import com.ruoyi.system.service.OaApprovalApplicationPaymentService;
import com.ruoyi.system.service.OaApprovalApplicationReimbursementItemService;
import com.ruoyi.system.service.OaApprovalApplicationReimbursementService;
import com.ruoyi.system.service.OaApprovalApplicationsService;
import com.ruoyi.system.service.OaApprovalFlowNodeService;
import com.ruoyi.system.service.OaApprovalService;
import com.ruoyi.system.service.OaApprovalTodoService;
import com.ruoyi.system.service.TDeptService;
import com.ruoyi.system.utils.UUIDUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import oshi.driver.mac.net.NetStat;
import javax.annotation.Resource;
import java.math.BigDecimal;
@@ -561,5 +594,23 @@
                Integer.valueOf(sysUser.getDeptId()));
        return R.ok();
    }
    @Log(title = "审批-撤回通用审批单", businessType = BusinessType.UPDATE)
    @ApiOperation(value = "撤回审批单(通用接口)")
    @PutMapping(value = "/withdraw/{id}")
    public R<?> withdraw(@PathVariable Integer id) {
        OaApprovalApplications current = approvalApplicationsService.getById(id);
        if (current == null) {
            throw new ServiceException("审批单不存在");
        }
        if (!ApprovalStatusEnum.PENDING.getCode().equals(current.getApprovalStatus())) {
            throw new ServiceException("仅待审批状态可撤回");
        }
        OaApprovalApplications update = new OaApprovalApplications();
        update.setId(id);
        update.setApprovalStatus(ApprovalStatusEnum.CANCELED.getCode());
        approvalApplicationsService.updateById(update);
        return R.ok();
    }
}
ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/FileUploadController.java
New file
@@ -0,0 +1,43 @@
package com.ruoyi.web.controller.system;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.system.service.OssService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestPart;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
/**
 * @author mitao
 * @date 2025/9/19
 */
@Api(tags = {"文件上传接口"})
@RestController
@RequestMapping("/file-upload/")
public class FileUploadController {
    @Autowired
    private OssService ossService;
    /**
     * 上传文件
     *
     * @param file
     * @return
     */
    @ApiOperation(value = "OSS文件上传")
    @PostMapping("/upload-oss")
    public R<String> upload(@RequestPart("file") MultipartFile file) {
        String fileUrl;
        try {
            fileUrl = ossService.uploadFile(file);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return R.ok(fileUrl);
    }
}
ruoyi-admin/src/main/resources/application-prod.yml
@@ -220,3 +220,12 @@
    bucketAddr:
    rootSrc:
    location: /clean
# 阿里云对象存储
oss:
  accessKeyId: LTAI5tNW8B4CYP1WK7yS3bfW
  accessKeySecret: 9RrPDLd7wh4VGCjXxD8ULIdKiuY5Ly
  upload-endpoint: https://oss-cn-chengdu.aliyuncs.com
  download-endpoint: https://zhpt-oss.oss-cn-chengdu.aliyuncs.com
  bucketName: zhpt
  folder: shehongchengtou
ruoyi-admin/src/main/resources/application-test.yml
@@ -65,7 +65,7 @@
  devtools:
    restart:
      # 热部署开关
      enabled: true
      enabled: false
  # redis 配置
  redis:
    # 地址
@@ -221,6 +221,15 @@
    bucketAddr:
    rootSrc:
    location: /clean
# 阿里云对象存储
oss:
  accessKeyId: LTAI5tNW8B4CYP1WK7yS3bfW
  accessKeySecret: 9RrPDLd7wh4VGCjXxD8ULIdKiuY5Ly
  upload-endpoint: https://oss-cn-chengdu.aliyuncs.com
  download-endpoint: https://zhpt-oss.oss-cn-chengdu.aliyuncs.com
  bucketName: zhpt
  folder: shehongchengtou
sms:
  enable: true
  appId: 1400957506
ruoyi-common/pom.xml
@@ -210,6 +210,11 @@
            <artifactId>javax.mail</artifactId>
            <version>1.6.2</version> <!-- 请检查是否有更新的版本 -->
        </dependency>
        <!--阿里云oss-->
        <dependency>
            <groupId>com.aliyun.oss</groupId>
            <artifactId>aliyun-sdk-oss</artifactId>
        </dependency>
    </dependencies>
</project>
ruoyi-common/src/main/java/com/ruoyi/common/config/OssConfig.java
New file
@@ -0,0 +1,59 @@
package com.ruoyi.common.config;
import com.alibaba.fastjson2.JSONObject;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
/**
 * 存储-配置
 *
 * @author mitao
 */
@ConfigurationProperties(prefix = "oss")
@Component
@Slf4j
@Data
public class OssConfig {
    private String folder = "dev";
    private String accessKeyId;
    private String accessKeySecret;
    private String uploadEndpoint;
    private String downloadEndpoint;
    private String bucketName;
    public static String FOLDER;
    public static String ACCESS_KEY_ID;
    public static String ACCESS_KEY_SECRET;
    public static String UPLOAD_ENDPOINT;
    public static String DOWNLOAD_ENDPOINT;
    public static String BUCKET_NAME;
    @PostConstruct
    public void init() {
        log.debug("OSS配置信息:" + JSONObject.toJSONString(this));
        FOLDER = folder;
        ACCESS_KEY_ID = accessKeyId;
        ACCESS_KEY_SECRET = accessKeySecret;
        UPLOAD_ENDPOINT = uploadEndpoint;
        DOWNLOAD_ENDPOINT = downloadEndpoint;
        BUCKET_NAME = bucketName;
    }
    public String getStoreFolder() {
        return getFolder();
    }
}
ruoyi-common/src/main/java/com/ruoyi/common/core/controller/FileController.java
@@ -5,10 +5,13 @@
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationAssetReceiveDTO.java
@@ -3,6 +3,7 @@
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
@@ -48,6 +49,7 @@
    @ApiModelProperty("领用日期")
    @NotNull(message = "领用日期不能为空")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate operateTime;
    @ApiModelProperty("资产类型ID")
@@ -55,6 +57,7 @@
    private Integer assetTypeId;
    @ApiModelProperty("预计退还日期,可为空")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate expectReturnDate;
    @ApiModelProperty("领用资产列表")
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationPurchaseDTO.java
@@ -23,10 +23,6 @@
@ApiModel(value = "OaApprovalApplicationPurchaseDTO", description = "采购申请DTO")
public class OaApprovalApplicationPurchaseDTO {
    @ApiModelProperty(value = "审批ID")
    @NotNull(message = "审批ID不能为空")
    private Integer approvalId;
    @ApiModelProperty(value = "申请部门ID")
    @NotNull(message = "申请部门不能为空")
    private Integer deptId;
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationStorageDTO.java
@@ -36,11 +36,6 @@
    @NotBlank(message = "申请人姓名不能为空")
    private String applicantName;
    @ApiModelProperty(value = "申请日期")
    @NotNull(message = "申请日期不能为空")
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    private LocalDate applicationDate;
    @ApiModelProperty(value = "入库备注")
    @Size(max = 500, message = "入库备注不能超过500字符")
    private String applicationReason;
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationStorageGeneralDTO.java
@@ -42,6 +42,10 @@
        @NotBlank(message = "资产名称不能为空")
        private String assetName;
        @ApiModelProperty(value = "类别")
        @NotBlank(message = "类别不能为空")
        private String category;
        @ApiModelProperty(value = "规格型号")
        private String specificationModel;
@@ -60,13 +64,16 @@
        @ApiModelProperty(value = "使用年限(年)")
        private Integer usefulLife;
        @ApiModelProperty(value = "权属单位/部门ID")
        private Integer ownershipDeptId;
        @ApiModelProperty(value = "总金额")
        private BigDecimal totalValue;
        @ApiModelProperty(value = "权属单位/部门名称")
        private String ownershipDeptName;
        @ApiModelProperty(value = "使用人")
        private String userName;
        @ApiModelProperty(value = "位置类型 0-部门,1-仓库,2-录入地址")
        @ApiModelProperty(value = "使用/位置类型 0-部门,1-仓库,2-录入地址")
        private Integer addressType;
        @ApiModelProperty(value = "使用部门/位置名称")
@@ -99,40 +106,5 @@
        @ApiModelProperty(value = "入账金额")
        private BigDecimal accountingAmount;
        // 通用资产扩展表字段
        @ApiModelProperty(value = "供应商名称")
        private String supplierName;
        @ApiModelProperty(value = "采购日期")
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate purchaseDate;
        @ApiModelProperty(value = "保修期(月)")
        private Integer warrantyPeriod;
        @ApiModelProperty(value = "保修到期日期")
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate warrantyExpireDate;
        @ApiModelProperty(value = "折旧方法")
        private String depreciationMethod;
        @ApiModelProperty(value = "折旧率")
        private BigDecimal depreciationRate;
        @ApiModelProperty(value = "净值")
        private BigDecimal netValue;
        @ApiModelProperty(value = "维护周期(月)")
        private Integer maintenanceCycle;
        @ApiModelProperty(value = "上次维护日期")
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate lastMaintenanceDate;
        @ApiModelProperty(value = "下次维护日期")
        @DateTimeFormat(pattern = "yyyy-MM-dd")
        private LocalDate nextMaintenanceDate;
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationStoragePropertyDTO.java
@@ -42,6 +42,10 @@
        @NotBlank(message = "资产名称不能为空")
        private String assetName;
        @ApiModelProperty(value = "类别")
        @NotBlank(message = "类别不能为空")
        private String category;
        @ApiModelProperty(value = "规格型号")
        private String specificationModel;
@@ -60,13 +64,13 @@
        @ApiModelProperty(value = "使用年限(年)")
        private Integer usefulLife;
        @ApiModelProperty(value = "权属单位/部门ID")
        private Integer ownershipDeptId;
        @ApiModelProperty(value = "权属单位/部门名称")
        private String ownershipDeptName;
        @ApiModelProperty(value = "使用人")
        private String userName;
        @ApiModelProperty(value = "位置类型 0-部门,1-仓库,2-录入地址")
        @ApiModelProperty(value = "使用/位置类型 0-部门,1-仓库,2-录入地址")
        private Integer addressType;
        @ApiModelProperty(value = "使用部门/位置名称")
@@ -136,7 +140,7 @@
        private String resettlementSituation;
        @ApiModelProperty(value = "是否抵押:0-否,1-是")
        private Boolean isMortgaged;
        private Integer mortgaged;
        @ApiModelProperty(value = "承租方")
        private String tenantName;
ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/OaApprovalApplicationStorageVehicleDTO.java
@@ -42,6 +42,10 @@
        @NotBlank(message = "资产名称不能为空")
        private String assetName;
        @ApiModelProperty(value = "类别")
        @NotBlank(message = "类别不能为空")
        private String category;
        @ApiModelProperty(value = "规格型号")
        private String specificationModel;
@@ -60,13 +64,13 @@
        @ApiModelProperty(value = "使用年限(年)")
        private Integer usefulLife;
        @ApiModelProperty(value = "权属单位/部门ID")
        private Integer ownershipDeptId;
        @ApiModelProperty(value = "权属单位/部门名称")
        private String ownershipDeptName;
        @ApiModelProperty(value = "使用人")
        private String userName;
        @ApiModelProperty(value = "位置类型 0-部门,1-仓库,2-录入地址")
        @ApiModelProperty(value = "使用/位置类型 0-部门,1-仓库,2-录入地址")
        private Integer addressType;
        @ApiModelProperty(value = "使用部门/位置名称")
ruoyi-system/src/main/java/com/ruoyi/system/mapper/OaApprovalApplicationAssetMapper.java
@@ -1,7 +1,12 @@
package com.ruoyi.system.mapper;
import com.ruoyi.system.model.OaApprovalApplicationAsset;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.ruoyi.system.model.OaApprovalApplicationAsset;
import com.ruoyi.system.query.OaApprovalApplicationAssetPageQuery;
import com.ruoyi.system.vo.asset.OaApprovalApplicationAssetPageVO;
import org.apache.ibatis.annotations.Param;
/**
 * <p>
@@ -13,4 +18,6 @@
 */
public interface OaApprovalApplicationAssetMapper extends BaseMapper<OaApprovalApplicationAsset> {
    IPage<OaApprovalApplicationAssetPageVO> selectReceivePage(Page<OaApprovalApplicationAssetPageVO> page,
                                                             @Param("query") OaApprovalApplicationAssetPageQuery query);
}
ruoyi-system/src/main/java/com/ruoyi/system/model/AssetGeneralExt.java
@@ -18,7 +18,7 @@
 * <p>
 * 通用资产扩展表
 * </p>
 *
 * 已弃用
 * @author WuGuanFengYue
 * @since 2025-09-15
 */
ruoyi-system/src/main/java/com/ruoyi/system/model/AssetMain.java
@@ -54,6 +54,10 @@
    @TableField("specification_model")
    private String specificationModel;
    @ApiModelProperty(value = "类别")
    @TableField("category")
    private String category;
    @ApiModelProperty(value = "资产类别ID,关联asset_type表")
    @TableField("asset_type_id")
    private Integer assetTypeId;
ruoyi-system/src/main/java/com/ruoyi/system/model/AssetPropertyExt.java
@@ -84,7 +84,7 @@
    @ApiModelProperty(value = "是否抵押:0-否,1-是")
    @TableField("is_mortgaged")
    private Boolean isMortgaged;
    private Integer mortgaged;
    @ApiModelProperty(value = "承租方")
    @TableField("tenant_name")
ruoyi-system/src/main/java/com/ruoyi/system/model/OaApprovalApplicationAsset.java
@@ -54,7 +54,7 @@
    @ApiModelProperty(value = "操作类型 0-领用,1-借用,2-归还")
    @TableField("type")
    private Boolean type;
    private Integer type;
    @ApiModelProperty(value = "借用审批ID,类型为归还时使用。")
    @TableField("borrow_application_id")
ruoyi-system/src/main/java/com/ruoyi/system/model/OaApprovalApplications.java
@@ -48,14 +48,14 @@
    @ApiModelProperty(value = "申请人")
    @TableField("applicant_name")
    private String applicantName;
    @ApiModelProperty(value = "所属部门")
    @TableField("dept_name")
    private String deptName;
    @ApiModelProperty(value = "部门ID")
    @TableField("dept_id")
    private Integer deptId;
    @ApiModelProperty(value = "申请日期")
    @TableField("application_date")
ruoyi-system/src/main/java/com/ruoyi/system/query/OaApprovalApplicationAssetPageQuery.java
New file
@@ -0,0 +1,24 @@
package com.ruoyi.system.query;
import com.ruoyi.common.core.domain.BasePage;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
/**
 * 资产领用申请分页查询对象
 */
@Data
@EqualsAndHashCode(callSuper = true)
@ApiModel("资产领用申请分页查询对象")
public class OaApprovalApplicationAssetPageQuery extends BasePage {
    private static final long serialVersionUID = 5202319182345234524L;
    @ApiModelProperty("关键词(标题/单据号/部门/领用人)")
    private String keyword;
    @ApiModelProperty("部门ID(非管理员时作为数据权限过滤)")
    private Integer deptId;
}
ruoyi-system/src/main/java/com/ruoyi/system/service/OaApprovalApplicationAssetService.java
@@ -1,8 +1,12 @@
package com.ruoyi.system.service;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import com.ruoyi.system.model.OaApprovalApplicationAsset;
import com.ruoyi.system.dto.asset.OaApprovalApplicationAssetReceiveDTO;
import com.ruoyi.system.query.OaApprovalApplicationAssetPageQuery;
import com.ruoyi.system.vo.asset.OaApprovalApplicationAssetPageVO;
import com.ruoyi.system.vo.asset.OaApprovalApplicationAssetDetailVO;
/**
 * <p>
@@ -19,4 +23,15 @@
     * @param dto 领用申请DTO
     */
    void submitReceive(OaApprovalApplicationAssetReceiveDTO dto);
    /**
     * 获取资产领用申请分页列表
     */
    IPage<OaApprovalApplicationAssetPageVO> getReceivePageList(OaApprovalApplicationAssetPageQuery pageQuery);
    /**
     * 获取资产领用/借用/归还详情
     * @param id 领用/借用/归还明细表ID(oa_approval_application_asset.id)
     */
    OaApprovalApplicationAssetDetailVO getDetail(Integer id);
}
ruoyi-system/src/main/java/com/ruoyi/system/service/OaApprovalApplicationStorageService.java
@@ -11,6 +11,9 @@
import com.ruoyi.system.query.OaApprovalApplicationStoragePageQuery;
import com.ruoyi.system.vo.StorageListVO;
import com.ruoyi.system.vo.asset.OaApprovalApplicationStoragePageVO;
import com.ruoyi.system.vo.asset.OaApprovalApplicationStorageGeneralDetailVO;
import com.ruoyi.system.vo.asset.OaApprovalApplicationStoragePropertyDetailVO;
import com.ruoyi.system.vo.asset.OaApprovalApplicationStorageVehicleDetailVO;
/**
 * <p>
@@ -50,5 +53,23 @@
     */
    IPage<OaApprovalApplicationStoragePageVO> getPageList(OaApprovalApplicationStoragePageQuery pageQuery);
    /**
     * 获取通用资产入库申请详情
     * @param storageId 入库申请存储表ID
     */
    OaApprovalApplicationStorageGeneralDetailVO getGeneralDetail(Integer storageId);
    /**
     * 获取房产资产入库申请详情
     * @param storageId 入库申请存储表ID
     */
    OaApprovalApplicationStoragePropertyDetailVO getPropertyDetail(Integer storageId);
    /**
     * 获取车辆资产入库申请详情
     * @param storageId 入库申请存储表ID
     */
    OaApprovalApplicationStorageVehicleDetailVO getVehicleDetail(Integer storageId);
    PageInfo<StorageListVO> pageList(ApprovalDetailQuery query);
}
ruoyi-system/src/main/java/com/ruoyi/system/service/OssService.java
New file
@@ -0,0 +1,28 @@
package com.ruoyi.system.service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
/**
 * @author mitao
 * @date 2024/12/23
 */
public interface OssService {
    /**
     * 文件上传
     *
     * @param file
     * @return
     */
    String uploadFile(MultipartFile file) throws IOException;
    /**
     * 文件上传,指定上传路径
     *
     * @param storagePath
     * @param file
     * @return
     */
    String upload(String storagePath, MultipartFile file) throws IOException;
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AssetTypeServiceImpl.java
@@ -3,6 +3,7 @@
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.utils.SecurityUtils;
@@ -21,6 +22,7 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
/**
@@ -53,10 +55,31 @@
        // 转换为VO对象
        List<AssetTypeTreeVO> assetTypeVOs = BeanUtil.copyToList(allAssetTypes, AssetTypeTreeVO.class);
        
        // 预查询:找出存在资产关联的资产类型ID集合(去重)
        List<Integer> allTypeIds = allAssetTypes.stream().map(AssetType::getId).collect(Collectors.toList());
        QueryWrapper<AssetMain> usedTypeQuery = new QueryWrapper<>();
        usedTypeQuery.select("distinct asset_type_id").in("asset_type_id", allTypeIds);
        List<AssetMain> usedTypeRows = assetMainService.list(usedTypeQuery);
        Set<Integer> usedTypeIdSet = usedTypeRows.stream()
                .map(AssetMain::getAssetTypeId)
                .filter(Objects::nonNull)
                .collect(Collectors.toSet());
        // 按父级ID分组
        Map<Integer, List<AssetTypeTreeVO>> parentIdMap = assetTypeVOs.stream()
                .collect(Collectors.groupingBy(AssetTypeTreeVO::getParentId));
        
        // 计算可删除标记:一级仅判断是否有子分类;二级仅判断是否有关联资产
        for (AssetTypeTreeVO vo : assetTypeVOs) {
            if (Objects.equals(vo.getLevel(), 1)) {
                boolean hasChildren = parentIdMap.containsKey(vo.getId()) && CollUtil.isNotEmpty(parentIdMap.get(vo.getId()));
                vo.setCanDelete(!hasChildren);
            } else {
                boolean hasAssets = usedTypeIdSet.contains(vo.getId());
                vo.setCanDelete(!hasAssets);
            }
        }
        // 构建树形结构
        List<AssetTypeTreeVO> rootNodes = parentIdMap.get(0);
        if (CollUtil.isEmpty(rootNodes)) {
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/OaApprovalApplicationAssetServiceImpl.java
@@ -1,5 +1,7 @@
package com.ruoyi.system.service.impl;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.dto.asset.OaApprovalApplicationAssetReceiveDTO;
@@ -10,11 +12,14 @@
import com.ruoyi.system.model.OaApprovalApplicationAssetItem;
import com.ruoyi.system.model.OaApprovalApplications;
import com.ruoyi.system.model.OaApprovalFlowNode;
import com.ruoyi.system.query.OaApprovalApplicationAssetPageQuery;
import com.ruoyi.system.service.OaApprovalApplicationAssetItemService;
import com.ruoyi.system.service.OaApprovalApplicationAssetService;
import com.ruoyi.system.service.OaApprovalApplicationsService;
import com.ruoyi.system.service.OaApprovalFlowNodeService;
import com.ruoyi.system.service.OaApprovalTodoService;
import com.ruoyi.system.vo.asset.OaApprovalApplicationAssetPageVO;
import com.ruoyi.system.vo.asset.OaApprovalApplicationAssetDetailVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -111,7 +116,7 @@
        asset.setAssetTypeId(dto.getAssetTypeId());
        asset.setOperateTime(dto.getOperateTime());
        asset.setExpectReturnDate(dto.getExpectReturnDate());
        asset.setType(Boolean.FALSE); // 0-领用
        asset.setType(0); // 0-领用
        return asset;
    }
@@ -130,4 +135,29 @@
        String sequenceStr = String.format("%03d", sequence);
        return prefix + sequenceStr;
    }
    @Override
    public IPage<OaApprovalApplicationAssetPageVO> getReceivePageList(OaApprovalApplicationAssetPageQuery pageQuery) {
        Page<OaApprovalApplicationAssetPageVO> page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
        return this.baseMapper.selectReceivePage(page, pageQuery);
    }
    @Override
    public OaApprovalApplicationAssetDetailVO getDetail(Integer id) {
        OaApprovalApplicationAsset detail = this.getById(id);
        if (detail == null) {
            throw new ServiceException("记录不存在");
        }
        OaApprovalApplications app = oaApprovalApplicationsService.getById(detail.getApprovalApplicationId());
        if (app == null) {
            throw new ServiceException("审批主记录不存在");
        }
        List<OaApprovalApplicationAssetItem> items = oaApprovalApplicationAssetItemService.lambdaQuery()
                .eq(OaApprovalApplicationAssetItem::getApprovalApplicationId, app.getId())
                .list();
        OaApprovalApplicationAssetDetailVO vo = new OaApprovalApplicationAssetDetailVO();
        vo.setItems(items);
        return vo;
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/OaApprovalApplicationPurchaseServiceImpl.java
@@ -4,13 +4,12 @@
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.dto.asset.OaApprovalApplicationPurchaseDTO;
import com.ruoyi.system.emums.ApprovalStatusEnum;
import com.ruoyi.system.emums.ApprovalTypeEnum;
import com.ruoyi.system.mapper.OaApprovalApplicationPurchaseMapper;
import com.ruoyi.system.model.OaApprovalApplicationPurchase;
import com.ruoyi.system.model.OaApprovalApplicationPurchaseItem;
import com.ruoyi.system.model.OaApprovalApplications;
import com.ruoyi.system.model.OaApprovalFlowNode;
import com.ruoyi.system.service.ISysDeptService;
import com.ruoyi.system.service.ISysUserService;
import com.ruoyi.system.service.OaApprovalApplicationPurchaseItemService;
import com.ruoyi.system.service.OaApprovalApplicationPurchaseService;
import com.ruoyi.system.service.OaApprovalApplicationsService;
@@ -41,8 +40,6 @@
    private final OaApprovalApplicationPurchaseItemService oaApprovalApplicationPurchaseItemService;
    private final OaApprovalFlowNodeService oaApprovalFlowNodeService;
    private final OaApprovalTodoService oaApprovalTodoService;
    private final ISysUserService sysUserService;
    private final ISysDeptService sysDeptService;
    @Override
    @Transactional(rollbackFor = Exception.class)
@@ -51,7 +48,7 @@
        OaApprovalApplications applications = buildOaApprovalApplications(dto);
        
        // 2. 如果是提交操作,获取流程节点并创建待办
        OaApprovalFlowNode firstFlowNode = getFirstFlowNode(dto.getApprovalId());
        OaApprovalFlowNode firstFlowNode = getFirstFlowNode(ApprovalTypeEnum.PURCHASE.getCode());
        applications.setCurrentFlowNodeId(firstFlowNode.getId());
        oaApprovalApplicationsService.save(applications);
@@ -91,7 +88,7 @@
    private OaApprovalApplications buildOaApprovalApplications(OaApprovalApplicationPurchaseDTO dto) {
        OaApprovalApplications applications = new OaApprovalApplications();
        applications.setApplicationCode(generateApplicationCode());
        applications.setApprovalId(dto.getApprovalId());
        applications.setApprovalId(ApprovalTypeEnum.PURCHASE.getCode());
        applications.setApplicantUserId(dto.getApplicantUserId());
        applications.setApplicantName(dto.getApplicantName());
        applications.setDeptId(dto.getDeptId());
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/OaApprovalApplicationStorageServiceImpl.java
@@ -22,6 +22,7 @@
import com.ruoyi.system.model.OaApprovalApplications;
import com.ruoyi.system.model.OaApprovalFlowNode;
import com.ruoyi.system.query.ApprovalDetailQuery;
import com.ruoyi.system.query.OaApprovalApplicationStoragePageQuery;
import com.ruoyi.system.service.AssetGeneralExtService;
import com.ruoyi.system.service.AssetMainService;
import com.ruoyi.system.service.AssetPropertyExtService;
@@ -37,7 +38,10 @@
import com.ruoyi.system.service.TDeptService;
import com.ruoyi.system.vo.PurchaseListVO;
import com.ruoyi.system.vo.StorageListVO;
import com.ruoyi.system.vo.asset.OaApprovalApplicationStorageGeneralDetailVO;
import com.ruoyi.system.vo.asset.OaApprovalApplicationStoragePageVO;
import com.ruoyi.system.vo.asset.OaApprovalApplicationStoragePropertyDetailVO;
import com.ruoyi.system.vo.asset.OaApprovalApplicationStorageVehicleDetailVO;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -48,6 +52,8 @@
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * <p>
@@ -145,8 +151,7 @@
     */
    private void saveGeneralAssets(List<OaApprovalApplicationStorageGeneralDTO.GeneralAssetItemDTO> assetItems, Integer applicationId, Integer assetTypeId, LocalDate storageDate, OaApprovalApplicationStorageGeneralDTO baseDto) {
        List<AssetMain> allAssetMains = new ArrayList<>();
        List<AssetGeneralExt> allGeneralExts = new ArrayList<>();
        for (OaApprovalApplicationStorageGeneralDTO.GeneralAssetItemDTO item : assetItems) {
            // 根据数量创建对应数量的资产记录
            int quantity = item.getQuantity().intValue();
@@ -161,19 +166,6 @@
        
        // 批量保存资产主表数据
        assetMainService.saveBatch(allAssetMains);
        // 为每个资产主表记录创建对应的扩展信息
        int assetMainIndex = 0;
        for (OaApprovalApplicationStorageGeneralDTO.GeneralAssetItemDTO item : assetItems) {
            int quantity = item.getQuantity().intValue();
            for (int i = 0; i < quantity; i++) {
                AssetGeneralExt generalExt = buildAssetGeneralExt(item, allAssetMains.get(assetMainIndex).getId());
                allGeneralExts.add(generalExt);
                assetMainIndex++;
            }
        }
        assetGeneralExtService.saveBatch(allGeneralExts);
    }
    /**
@@ -257,12 +249,21 @@
        assetMain.setAssetOriginalCode(item.getAssetOriginalCode());
        assetMain.setAssetCode(generateAssetCode(assetTypeId, storageDate)); // 系统生成资产编码
        assetMain.setAssetName(item.getAssetName());
        assetMain.setCategory(item.getCategory());
        assetMain.setSpecificationModel(item.getSpecificationModel());
        assetMain.setAssetTypeId(assetTypeId);
        assetMain.setMeasurementUnit(item.getMeasurementUnit());
        assetMain.setUnitPrice(item.getUnitPrice());
        assetMain.setUsefulLife(item.getUsefulLife());
        assetMain.setOwnershipDeptId(item.getOwnershipDeptId());
        // 根据权属单位/部门名称填充ID
        if (item.getOwnershipDeptName() != null && !item.getOwnershipDeptName().isEmpty()) {
            TDept ownerDept = tDeptService.lambdaQuery()
                    .eq(TDept::getDeptName, item.getOwnershipDeptName())
                    .one();
            if (ownerDept != null) {
                assetMain.setOwnershipDeptId(ownerDept.getId());
            }
        }
        assetMain.setUserName(item.getUserName());
        // 根据整单 addressType 写入使用部门ID或仓库ID
        applyAddressToAssetMain(assetMain, baseDto.getAddressType(), baseDto.getUseDeptName(), baseDto.getWarehouseName(), baseDto.getAddress());
@@ -287,12 +288,20 @@
        assetMain.setAssetOriginalCode(item.getAssetOriginalCode());
        assetMain.setAssetCode(generateAssetCode(assetTypeId, storageDate));
        assetMain.setAssetName(item.getAssetName());
        assetMain.setCategory(item.getCategory());
        assetMain.setSpecificationModel(item.getSpecificationModel());
        assetMain.setAssetTypeId(assetTypeId);
        assetMain.setMeasurementUnit(item.getMeasurementUnit());
        assetMain.setUnitPrice(item.getUnitPrice());
        assetMain.setUsefulLife(item.getUsefulLife());
        assetMain.setOwnershipDeptId(item.getOwnershipDeptId());
        if (item.getOwnershipDeptName() != null && !item.getOwnershipDeptName().isEmpty()) {
            TDept ownerDept = tDeptService.lambdaQuery()
                    .eq(TDept::getDeptName, item.getOwnershipDeptName())
                    .one();
            if (ownerDept != null) {
                assetMain.setOwnershipDeptId(ownerDept.getId());
            }
        }
        assetMain.setUserName(item.getUserName());
        applyAddressToAssetMain(assetMain, baseDto.getAddressType(), baseDto.getUseDeptName(), baseDto.getWarehouseName(), baseDto.getAddress());
        assetMain.setAssetMainType(baseDto.getAddressType());
@@ -316,12 +325,20 @@
        assetMain.setAssetOriginalCode(item.getAssetOriginalCode());
        assetMain.setAssetCode(generateAssetCode(assetTypeId, storageDate));
        assetMain.setAssetName(item.getAssetName());
        assetMain.setCategory(item.getCategory());
        assetMain.setSpecificationModel(item.getSpecificationModel());
        assetMain.setAssetTypeId(assetTypeId);
        assetMain.setMeasurementUnit(item.getMeasurementUnit());
        assetMain.setUnitPrice(item.getUnitPrice());
        assetMain.setUsefulLife(item.getUsefulLife());
        assetMain.setOwnershipDeptId(item.getOwnershipDeptId());
        if (item.getOwnershipDeptName() != null && !item.getOwnershipDeptName().isEmpty()) {
            TDept ownerDept = tDeptService.lambdaQuery()
                    .eq(TDept::getDeptName, item.getOwnershipDeptName())
                    .one();
            if (ownerDept != null) {
                assetMain.setOwnershipDeptId(ownerDept.getId());
            }
        }
        assetMain.setUserName(item.getUserName());
        applyAddressToAssetMain(assetMain, baseDto.getAddressType(), baseDto.getUseDeptName(), baseDto.getWarehouseName(), baseDto.getAddress());
        assetMain.setAssetMainType(baseDto.getAddressType());
@@ -382,16 +399,6 @@
    private AssetGeneralExt buildAssetGeneralExt(OaApprovalApplicationStorageGeneralDTO.GeneralAssetItemDTO item, Integer assetMainId) {
        AssetGeneralExt generalExt = new AssetGeneralExt();
        generalExt.setAssetMainId(assetMainId);
        generalExt.setSupplierName(item.getSupplierName());
        generalExt.setPurchaseDate(item.getPurchaseDate());
        generalExt.setWarrantyPeriod(item.getWarrantyPeriod());
        generalExt.setWarrantyExpireDate(item.getWarrantyExpireDate());
        generalExt.setDepreciationMethod(item.getDepreciationMethod());
        generalExt.setDepreciationRate(item.getDepreciationRate());
        generalExt.setNetValue(item.getNetValue());
        generalExt.setMaintenanceCycle(item.getMaintenanceCycle());
        generalExt.setLastMaintenanceDate(item.getLastMaintenanceDate());
        generalExt.setNextMaintenanceDate(item.getNextMaintenanceDate());
        generalExt.setDisabled(false);
        return generalExt;
    }
@@ -413,7 +420,7 @@
        propertyExt.setDetailedLocation(item.getDetailedLocation());
        propertyExt.setProvincialPlatformValue(item.getProvincialPlatformValue());
        propertyExt.setResettlementSituation(item.getResettlementSituation());
        propertyExt.setIsMortgaged(item.getIsMortgaged());
        propertyExt.setMortgaged(item.getMortgaged());
        propertyExt.setTenantName(item.getTenantName());
        propertyExt.setRentalAmount(item.getRentalAmount());
        propertyExt.setLeaseStartDate(item.getLeaseStartDate());
@@ -471,7 +478,7 @@
            applications.setApplicantName(generalDTO.getApplicantName());
            applications.setDeptId(generalDTO.getDeptId());
            applications.setDeptName(generalDTO.getDeptName());
            applications.setApplicationDate(generalDTO.getApplicationDate());
            applications.setApplicationDate(LocalDate.now());
            applications.setApplicationReason(generalDTO.getApplicationReason());
            applications.setAttachmentUrl(generalDTO.getAttachmentUrl());
        } else if (dto instanceof OaApprovalApplicationStoragePropertyDTO) {
@@ -480,7 +487,7 @@
            applications.setApplicantName(propertyDTO.getApplicantName());
            applications.setDeptId(propertyDTO.getDeptId());
            applications.setDeptName(propertyDTO.getDeptName());
            applications.setApplicationDate(propertyDTO.getApplicationDate());
            applications.setApplicationDate(LocalDate.now());
            applications.setApplicationReason(propertyDTO.getApplicationReason());
            applications.setAttachmentUrl(propertyDTO.getAttachmentUrl());
        } else if (dto instanceof OaApprovalApplicationStorageVehicleDTO) {
@@ -489,7 +496,7 @@
            applications.setApplicantName(vehicleDTO.getApplicantName());
            applications.setDeptId(vehicleDTO.getDeptId());
            applications.setDeptName(vehicleDTO.getDeptName());
            applications.setApplicationDate(vehicleDTO.getApplicationDate());
            applications.setApplicationDate(LocalDate.now());
            applications.setApplicationReason(vehicleDTO.getApplicationReason());
            applications.setAttachmentUrl(vehicleDTO.getAttachmentUrl());
        }
@@ -576,12 +583,300 @@
    }
    
    @Override
    public IPage<OaApprovalApplicationStoragePageVO> getPageList(com.ruoyi.system.query.OaApprovalApplicationStoragePageQuery pageQuery) {
    public IPage<OaApprovalApplicationStoragePageVO> getPageList(OaApprovalApplicationStoragePageQuery pageQuery) {
        Page<OaApprovalApplicationStoragePageVO> page = new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize());
        return this.baseMapper.selectApplicationStoragePage(page, pageQuery);
    }
    @Override
    public OaApprovalApplicationStorageGeneralDetailVO getGeneralDetail(Integer storageId) {
        OaApprovalApplicationStorage storage = this.getById(storageId);
        if (storage == null) {
            throw new ServiceException("入库申请不存在");
        }
        OaApprovalApplications app = oaApprovalApplicationsService.getById(storage.getApprovalApplicationId());
        if (app == null) {
            throw new ServiceException("审批主记录不存在");
        }
        OaApprovalApplicationStorageGeneralDetailVO vo = new OaApprovalApplicationStorageGeneralDetailVO();
        fillBaseFields(vo, app, storage);
        List<AssetMain> mains = assetMainService.lambdaQuery()
                .eq(AssetMain::getApprovalApplicationId, app.getId())
                .eq(AssetMain::getAssetTypeId, storage.getAssetTypeId())
                .list();
        setAddressInfo(vo, mains);
        if (!CollectionUtils.isEmpty(mains)) {
            List<Integer> mainIds = mains.stream().map(AssetMain::getId).collect(Collectors.toList());
            // 批量查询权属部门,避免循环内查询
            List<Integer> ownerIds = mains.stream().map(AssetMain::getOwnershipDeptId)
                    .filter(id -> id != null).distinct().collect(Collectors.toList());
            Map<Integer, TDept> ownerDeptMap = ownerIds.isEmpty() ? java.util.Collections.emptyMap()
                    : tDeptService.listByIds(ownerIds).stream().collect(Collectors.toMap(TDept::getId, d -> d));
            List<OaApprovalApplicationStorageGeneralDetailVO.GeneralAssetItemVO> items = mains.stream().map(m -> {
                OaApprovalApplicationStorageGeneralDetailVO.GeneralAssetItemVO item = new OaApprovalApplicationStorageGeneralDetailVO.GeneralAssetItemVO();
                item.setAssetOriginalCode(m.getAssetOriginalCode());
                item.setAssetName(m.getAssetName());
                item.setSpecificationModel(m.getSpecificationModel());
                item.setMeasurementUnit(m.getMeasurementUnit());
                item.setQuantity(m.getQuantity());
                item.setUnitPrice(m.getUnitPrice());
                item.setUsefulLife(m.getUsefulLife());
                if (m.getOwnershipDeptId() != null) {
                    TDept dept = ownerDeptMap.get(m.getOwnershipDeptId());
                    item.setOwnerShipDeptName(dept != null ? dept.getDeptName() : null);
                }
                item.setUserName(m.getUserName());
                item.setAssetStatus(m.getAssetStatus());
                item.setRemarks(m.getRemarks());
                item.setAccountingStatus(m.getAccountingStatus());
                item.setAccountingDate(m.getAccountingDate());
                item.setAccountingVoucherNo(m.getAccountingVoucherNo());
                item.setAccountingSubject(m.getAccountingSubject());
                item.setAccountingAmount(m.getAccountingAmount());
                return item;
            }).collect(Collectors.toList());
            vo.setAssetItems(items);
        }
        return vo;
    }
    @Override
    public OaApprovalApplicationStoragePropertyDetailVO getPropertyDetail(Integer storageId) {
        OaApprovalApplicationStorage storage = this.getById(storageId);
        if (storage == null) {
            throw new ServiceException("入库申请不存在");
        }
        OaApprovalApplications app = oaApprovalApplicationsService.getById(storage.getApprovalApplicationId());
        if (app == null) {
            throw new ServiceException("审批主记录不存在");
        }
        OaApprovalApplicationStoragePropertyDetailVO vo = new OaApprovalApplicationStoragePropertyDetailVO();
        fillBaseFields(vo, app, storage);
        List<AssetMain> mains = assetMainService.lambdaQuery()
                .eq(AssetMain::getApprovalApplicationId, app.getId())
                .eq(AssetMain::getAssetTypeId, storage.getAssetTypeId())
                .list();
        setAddressInfo(vo, mains);
        if (!CollectionUtils.isEmpty(mains)) {
            List<Integer> mainIds = mains.stream().map(AssetMain::getId).collect(Collectors.toList());
            List<AssetPropertyExt> exts = assetPropertyExtService.lambdaQuery().in(AssetPropertyExt::getAssetMainId, mainIds).list();
            Map<Integer, AssetPropertyExt> extMap = exts.stream().collect(Collectors.toMap(AssetPropertyExt::getAssetMainId, e -> e));
            // 批量查询权属部门
            List<Integer> ownerIds = mains.stream().map(AssetMain::getOwnershipDeptId)
                    .filter(id -> id != null).distinct().collect(Collectors.toList());
            Map<Integer, TDept> ownerDeptMap = ownerIds.isEmpty() ? java.util.Collections.emptyMap()
                    : tDeptService.listByIds(ownerIds).stream().collect(Collectors.toMap(TDept::getId, d -> d));
            List<OaApprovalApplicationStoragePropertyDetailVO.PropertyAssetItemVO> items = mains.stream().map(m -> {
                OaApprovalApplicationStoragePropertyDetailVO.PropertyAssetItemVO item = new OaApprovalApplicationStoragePropertyDetailVO.PropertyAssetItemVO();
                item.setAssetOriginalCode(m.getAssetOriginalCode());
                item.setAssetName(m.getAssetName());
                item.setSpecificationModel(m.getSpecificationModel());
                item.setMeasurementUnit(m.getMeasurementUnit());
                item.setQuantity(m.getQuantity());
                item.setUnitPrice(m.getUnitPrice());
                item.setUsefulLife(m.getUsefulLife());
                if (m.getOwnershipDeptId() != null) {
                    TDept dept = ownerDeptMap.get(m.getOwnershipDeptId());
                    item.setOwnerShipDeptName(dept != null ? dept.getDeptName() : null);
                }
                item.setUserName(m.getUserName());
                item.setAssetStatus(m.getAssetStatus());
                item.setRemarks(m.getRemarks());
                item.setAccountingStatus(m.getAccountingStatus());
                item.setAccountingDate(m.getAccountingDate());
                item.setAccountingVoucherNo(m.getAccountingVoucherNo());
                item.setAccountingSubject(m.getAccountingSubject());
                item.setAccountingAmount(m.getAccountingAmount());
                AssetPropertyExt ext = extMap.get(m.getId());
                if (ext != null) {
                    item.setRegion(ext.getRegion());
                    item.setDesignPurpose(ext.getDesignPurpose());
                    item.setBuilding(ext.getBuilding());
                    item.setRoomNumber(ext.getRoomNumber());
                    item.setConstructionArea(ext.getConstructionArea());
                    item.setStructureType(ext.getStructureType());
                    item.setCertificateNumber(ext.getCertificateNumber());
                    item.setCompletionDate(ext.getCompletionDate());
                    item.setDetailedLocation(ext.getDetailedLocation());
                    item.setProvincialPlatformValue(ext.getProvincialPlatformValue());
                    item.setResettlementSituation(ext.getResettlementSituation());
                    item.setMortgaged(ext.getMortgaged());
                    item.setTenantName(ext.getTenantName());
                    item.setRentalAmount(ext.getRentalAmount());
                    item.setLeaseStartDate(ext.getLeaseStartDate());
                    item.setLeaseEndDate(ext.getLeaseEndDate());
                }
                return item;
            }).collect(Collectors.toList());
            vo.setAssetItems(items);
        }
        return vo;
    }
    @Override
    public OaApprovalApplicationStorageVehicleDetailVO getVehicleDetail(Integer storageId) {
        OaApprovalApplicationStorage storage = this.getById(storageId);
        if (storage == null) {
            throw new ServiceException("入库申请不存在");
        }
        OaApprovalApplications app = oaApprovalApplicationsService.getById(storage.getApprovalApplicationId());
        if (app == null) {
            throw new ServiceException("审批主记录不存在");
        }
        OaApprovalApplicationStorageVehicleDetailVO vo = new OaApprovalApplicationStorageVehicleDetailVO();
        fillBaseFields(vo, app, storage);
        List<AssetMain> mains = assetMainService.lambdaQuery()
                .eq(AssetMain::getApprovalApplicationId, app.getId())
                .eq(AssetMain::getAssetTypeId, storage.getAssetTypeId())
                .list();
        setAddressInfo(vo, mains);
        if (!CollectionUtils.isEmpty(mains)) {
            List<Integer> mainIds = mains.stream().map(AssetMain::getId).collect(Collectors.toList());
            List<AssetVehicleExt> exts = assetVehicleExtService.lambdaQuery().in(AssetVehicleExt::getAssetMainId, mainIds).list();
            Map<Integer, AssetVehicleExt> extMap = exts.stream().collect(Collectors.toMap(AssetVehicleExt::getAssetMainId, e -> e));
            // 批量查询权属部门
            List<Integer> ownerIds = mains.stream().map(AssetMain::getOwnershipDeptId)
                    .filter(id -> id != null).distinct().collect(Collectors.toList());
            Map<Integer, TDept> ownerDeptMap = ownerIds.isEmpty() ? java.util.Collections.emptyMap()
                    : tDeptService.listByIds(ownerIds).stream().collect(Collectors.toMap(TDept::getId, d -> d));
            List<OaApprovalApplicationStorageVehicleDetailVO.VehicleAssetItemVO> items = mains.stream().map(m -> {
                OaApprovalApplicationStorageVehicleDetailVO.VehicleAssetItemVO item = new OaApprovalApplicationStorageVehicleDetailVO.VehicleAssetItemVO();
                item.setAssetOriginalCode(m.getAssetOriginalCode());
                item.setAssetName(m.getAssetName());
                item.setSpecificationModel(m.getSpecificationModel());
                item.setMeasurementUnit(m.getMeasurementUnit());
                item.setQuantity(m.getQuantity());
                item.setUnitPrice(m.getUnitPrice());
                item.setUsefulLife(m.getUsefulLife());
                if (m.getOwnershipDeptId() != null) {
                    TDept dept = ownerDeptMap.get(m.getOwnershipDeptId());
                    item.setOwnerShipDeptName(dept != null ? dept.getDeptName() : null);
                }
                item.setUserName(m.getUserName());
                item.setAssetStatus(m.getAssetStatus());
                item.setRemarks(m.getRemarks());
                item.setAccountingStatus(m.getAccountingStatus());
                item.setAccountingDate(m.getAccountingDate());
                item.setAccountingVoucherNo(m.getAccountingVoucherNo());
                item.setAccountingSubject(m.getAccountingSubject());
                item.setAccountingAmount(m.getAccountingAmount());
                AssetVehicleExt ext = extMap.get(m.getId());
                if (ext != null) {
                    item.setLicensePlate(ext.getLicensePlate());
                    item.setVinCode(ext.getVinCode());
                    item.setEngineNumber(ext.getEngineNumber());
                    item.setDisplacement(ext.getDisplacement());
                    item.setStaffingSituation(ext.getStaffingSituation());
                    item.setOrigin(ext.getOrigin());
                    item.setAcquisitionDate(ext.getAcquisitionDate());
                    item.setPropertyRightForm(ext.getPropertyRightForm());
                }
                return item;
            }).collect(Collectors.toList());
            vo.setAssetItems(items);
        }
        return vo;
    }
    private void fillBaseFields(Object vo, OaApprovalApplications app, OaApprovalApplicationStorage storage) {
        if (vo instanceof OaApprovalApplicationStorageGeneralDetailVO) {
            OaApprovalApplicationStorageGeneralDetailVO v = (OaApprovalApplicationStorageGeneralDetailVO) vo;
            v.setDeptId(app.getDeptId());
            v.setDeptName(app.getDeptName());
            v.setApplicantUserId(app.getApplicantUserId());
            v.setApplicantName(app.getApplicantName());
            v.setApplicationDate(app.getApplicationDate());
            v.setApplicationReason(app.getApplicationReason());
            v.setAttachmentUrl(app.getAttachmentUrl());
            v.setTitle(storage.getTitle());
            v.setAssetTypeId(storage.getAssetTypeId());
            v.setStorageType(storage.getStorageType());
            v.setStorageTime(storage.getStorageTime());
        } else if (vo instanceof OaApprovalApplicationStoragePropertyDetailVO) {
            OaApprovalApplicationStoragePropertyDetailVO v = (OaApprovalApplicationStoragePropertyDetailVO) vo;
            v.setDeptId(app.getDeptId());
            v.setDeptName(app.getDeptName());
            v.setApplicantUserId(app.getApplicantUserId());
            v.setApplicantName(app.getApplicantName());
            v.setApplicationDate(app.getApplicationDate());
            v.setApplicationReason(app.getApplicationReason());
            v.setAttachmentUrl(app.getAttachmentUrl());
            v.setTitle(storage.getTitle());
            v.setAssetTypeId(storage.getAssetTypeId());
            v.setStorageType(storage.getStorageType());
            v.setStorageTime(storage.getStorageTime());
        } else if (vo instanceof OaApprovalApplicationStorageVehicleDetailVO) {
            OaApprovalApplicationStorageVehicleDetailVO v = (OaApprovalApplicationStorageVehicleDetailVO) vo;
            v.setDeptId(app.getDeptId());
            v.setDeptName(app.getDeptName());
            v.setApplicantUserId(app.getApplicantUserId());
            v.setApplicantName(app.getApplicantName());
            v.setApplicationDate(app.getApplicationDate());
            v.setApplicationReason(app.getApplicationReason());
            v.setAttachmentUrl(app.getAttachmentUrl());
            v.setTitle(storage.getTitle());
            v.setAssetTypeId(storage.getAssetTypeId());
            v.setStorageType(storage.getStorageType());
            v.setStorageTime(storage.getStorageTime());
        }
    }
    private void setAddressInfo(Object vo, List<AssetMain> mains) {
        if (CollectionUtils.isEmpty(mains)) {
            return;
        }
        AssetMain sample = mains.get(0);
        Integer addressType = null;
        String useDeptName = null;
        String warehouseName = null;
        String address = null;
        if (sample.getUseDeptId() != null) {
            addressType = 0;
            TDept dept = tDeptService.getById(sample.getUseDeptId());
            useDeptName = dept != null ? dept.getDeptName() : null;
        } else if (sample.getWarehouseId() != null) {
            addressType = 1;
            AssetWarehouse wh = assetWarehouseService.getById(sample.getWarehouseId());
            warehouseName = wh != null ? wh.getWarehouseName() : null;
        } else if (sample.getAddress() != null && !sample.getAddress().isEmpty()) {
            addressType = 2;
            address = sample.getAddress();
        }
        if (vo instanceof OaApprovalApplicationStorageGeneralDetailVO) {
            OaApprovalApplicationStorageGeneralDetailVO v = (OaApprovalApplicationStorageGeneralDetailVO) vo;
            v.setAddressType(addressType);
            v.setUseDeptName(useDeptName);
            v.setWarehouseName(warehouseName);
            v.setAddress(address);
        } else if (vo instanceof OaApprovalApplicationStoragePropertyDetailVO) {
            OaApprovalApplicationStoragePropertyDetailVO v = (OaApprovalApplicationStoragePropertyDetailVO) vo;
            v.setAddressType(addressType);
            v.setUseDeptName(useDeptName);
            v.setWarehouseName(warehouseName);
            v.setAddress(address);
        } else if (vo instanceof OaApprovalApplicationStorageVehicleDetailVO) {
            OaApprovalApplicationStorageVehicleDetailVO v = (OaApprovalApplicationStorageVehicleDetailVO) vo;
            v.setAddressType(addressType);
            v.setUseDeptName(useDeptName);
            v.setWarehouseName(warehouseName);
            v.setAddress(address);
        }
    }
    @Override
    public PageInfo<StorageListVO> pageList(ApprovalDetailQuery query) {
        PageInfo<StorageListVO> pageInfo = new PageInfo<>(query.getPageNum(), query.getPageSize());
        List<StorageListVO> list = this.baseMapper.pageList(query,pageInfo);
ruoyi-system/src/main/java/com/ruoyi/system/service/impl/OssServiceImpl.java
New file
@@ -0,0 +1,119 @@
package com.ruoyi.system.service.impl;
import com.aliyun.oss.ClientBuilderConfiguration;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.common.auth.CredentialsProvider;
import com.aliyun.oss.common.auth.DefaultCredentialProvider;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.PutObjectRequest;
import com.aliyun.oss.model.PutObjectResult;
import com.ruoyi.common.config.FileUploadConfig;
import com.ruoyi.common.config.OssConfig;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.system.service.OssService;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Objects;
import java.util.UUID;
/**
 * @author mitao
 * @date 2024/12/23
 */
@Service
public class OssServiceImpl implements OssService {
    @Autowired
    private FileUploadConfig fileUploadConfig;
    /**
     * 文件上传
     *
     * @param file
     * @return
     */
    @Override
    public String uploadFile(MultipartFile file) throws IOException {
        if (Objects.isNull(file)) {
            throw new ServiceException("文件不能为空");
        }
        // 获取文件名称
        String filename = file.getOriginalFilename();
        // 获取文件后缀
        String ext = filename.substring(filename.lastIndexOf("."), filename.length());
        // 检查文件类型
        if (!fileUploadConfig.getAllowExt().contains(ext)) {
            throw new ServiceException("上传文件格式不正确,仅支持"+ fileUploadConfig.getAllowExt());
        }
        return upload(OssConfig.FOLDER, file);
    }
    /**
     * 文件上传,指定上传路径
     *
     * @param storagePath
     * @param file
     * @return
     */
    @Override
    public String upload(String storagePath, MultipartFile file) throws IOException {
        CredentialsProvider credentialsProvider = new DefaultCredentialProvider(OssConfig.ACCESS_KEY_ID, OssConfig.ACCESS_KEY_SECRET);
        String region = "cn-chengdu";
        // 创建OSSClient实例。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);
        OSS ossClient = OSSClientBuilder.create()
                .endpoint(OssConfig.UPLOAD_ENDPOINT)
                .credentialsProvider(credentialsProvider)
                .clientConfiguration(clientBuilderConfiguration)
                .region(region)
                .build();
        InputStream inputStream = file.getInputStream();
        String originFileName = file.getOriginalFilename();
        String fileExt = Objects.requireNonNull(originFileName).substring(originFileName.lastIndexOf(".") + 1);
        String fileName = originFileName.substring(0, originFileName.lastIndexOf("."));
        // 设置文件名
        String filePathName = generateRelativeStoragePath(storagePath, fileExt, fileName);
        // 创建PutObjectRequest对象。
        PutObjectRequest putObjectRequest = new PutObjectRequest(OssConfig.BUCKET_NAME, filePathName, inputStream);
        // 创建PutObject请求。
        PutObjectResult result = ossClient.putObject(putObjectRequest);
        return OssConfig.DOWNLOAD_ENDPOINT + filePathName;
    }
    /**
     * <pre>
     * 获取存储的相对路径
     * 规则path + / + yyyyMMddHH  + uuid
     * </pre>
     *
     * @param storagePath
     * @return
     */
    private static String generateRelativeStoragePath(String storagePath, String fileType, String fileName) {
        String time = DateFormatUtils.format(new Date(), "yyyyMMddHHmmss");
        String uuid = UUID.randomUUID().toString();
        StringBuilder sb = new StringBuilder();
        if (StringUtils.isNotBlank(storagePath)) {
            sb.append(storagePath).append("/");
        }
        if (fileName == null) {
            sb.append(time).append(uuid);
        } else {
            sb.append(fileName).append(time);
        }
        if (StringUtils.isNotBlank(fileType)) {
            sb.append(".").append(fileType);
        }
        return sb.toString();
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/AssetTypeTreeVO.java
@@ -52,6 +52,9 @@
    @ApiModelProperty(value = "更新人")
    private String updateBy;
    @ApiModelProperty(value = "是否可删除:无子类型且无资产关联时为true")
    private Boolean canDelete;
    @ApiModelProperty(value = "子节点列表")
    private List<AssetTypeTreeVO> children;
}
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/OaApprovalApplicationAssetDetailVO.java
New file
@@ -0,0 +1,78 @@
package com.ruoyi.system.vo.asset;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.ruoyi.system.model.OaApprovalApplicationAssetItem;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDate;
import java.util.List;
/**
 * 资产领用/借用/归还 详情VO
 */
@Data
@ApiModel("资产领用/借用/归还 详情VO")
public class OaApprovalApplicationAssetDetailVO implements Serializable {
    @ApiModelProperty(value = "主键")
    private Integer id;
    @ApiModelProperty(value = "申请单号")
    private String applicationCode;
    @ApiModelProperty(value = "审批ID")
    private Integer approvalId;
    @ApiModelProperty(value = "申请人ID")
    private Integer applicantUserId;
    @ApiModelProperty(value = "申请人")
    private String applicantName;
    @ApiModelProperty(value = "所属部门")
    private String deptName;
    @ApiModelProperty(value = "部门ID")
    private Integer deptId;
    @ApiModelProperty(value = "申请日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate applicationDate;
    @ApiModelProperty(value = "事由/原因/说明")
    private String applicationReason;
    @ApiModelProperty(value = "审批状态 0-草稿,1-待审批,2-审批通过,3-审批拒绝 ,4-已撤回")
    private Integer approvalStatus;
    @ApiModelProperty(value = "附件地址,多个使用英文逗号拼接")
    private String attachmentUrl;
    @ApiModelProperty(value = "当前流程id")
    private Integer currentFlowNodeId;
    @ApiModelProperty(value = "事项标题")
    private String title;
    @ApiModelProperty(value = "资产类型")
    private Integer assetTypeId;
    @ApiModelProperty(value = "领用/借用日期")
    private LocalDate operateTime;
    @ApiModelProperty(value = "预计退还日期")
    private LocalDate expectReturnDate;
    @ApiModelProperty(value = "操作类型 0-领用,1-借用,2-归还")
    private Integer type;
    @ApiModelProperty(value = "借用审批ID,类型为归还时使用。")
    private Integer borrowApplicationId;
    @ApiModelProperty("关联资产项列表")
    private List<OaApprovalApplicationAssetItem> items;
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/OaApprovalApplicationAssetPageVO.java
New file
@@ -0,0 +1,47 @@
package com.ruoyi.system.vo.asset;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.time.LocalDate;
/**
 * 资产领用申请分页列表返回对象
 */
@Data
@ApiModel("资产领用申请分页列表返回对象")
public class OaApprovalApplicationAssetPageVO implements Serializable {
    private static final long serialVersionUID = 4352345234523452346L;
    @ApiModelProperty("主键ID")
    private Integer id;
    @ApiModelProperty("单据号")
    private String applicationCode;
    @ApiModelProperty("标题")
    private String title;
    @ApiModelProperty("领用部门")
    private String deptName;
    @ApiModelProperty("领用人")
    private String applicantName;
    @ApiModelProperty("资产一级类型名称")
    private String firstAssetTypeName;
    @ApiModelProperty("资产二级类型名称")
    private String secondAssetTypeName;
    @ApiModelProperty("领用日期")
    @JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDate operateTime;
    @ApiModelProperty("状态 0-草稿,1-待审批,2-通过,3-拒绝,4-撤回")
    private Integer approvalStatus;
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/OaApprovalApplicationStorageGeneralDetailVO.java
New file
@@ -0,0 +1,118 @@
package com.ruoyi.system.vo.asset;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
/**
 * 通用资产入库申请详情VO(返回新增时填写的所有字段)
 */
@Data
@ApiModel("通用资产入库申请详情VO")
public class OaApprovalApplicationStorageGeneralDetailVO implements Serializable {
    @ApiModelProperty(value = "申请部门ID")
    private Integer deptId;
    @ApiModelProperty(value = "申请部门名称")
    private String deptName;
    @ApiModelProperty(value = "申请人ID")
    private Integer applicantUserId;
    @ApiModelProperty(value = "申请人姓名")
    private String applicantName;
    @ApiModelProperty(value = "申请日期")
    private LocalDate applicationDate;
    @ApiModelProperty(value = "入库备注")
    private String applicationReason;
    @ApiModelProperty(value = "附件地址,多个使用英文逗号拼接")
    private String attachmentUrl;
    @ApiModelProperty(value = "事项标题")
    private String title;
    @ApiModelProperty(value = "资产类型ID")
    private Integer assetTypeId;
    @ApiModelProperty(value = "入库类型 0-正常入库")
    private Boolean storageType;
    @ApiModelProperty(value = "入库日期")
    private LocalDate storageTime;
    @ApiModelProperty(value = "位置类型 0-部门,1-仓库,2-录入地址")
    private Integer addressType;
    @ApiModelProperty(value = "使用部门/位置名称")
    private String useDeptName;
    @ApiModelProperty(value = "仓库名称")
    private String warehouseName;
    @ApiModelProperty(value = "所在位置")
    private String address;
    @ApiModelProperty(value = "通用资产明细列表(按保存展开后的一条资产记录对应一条明细)")
    private List<GeneralAssetItemVO> assetItems;
    @Data
    @ApiModel("通用资产明细VO")
    public static class GeneralAssetItemVO implements Serializable {
        @ApiModelProperty(value = "资产原编码")
        private String assetOriginalCode;
        @ApiModelProperty(value = "资产名称")
        private String assetName;
        @ApiModelProperty(value = "规格型号")
        private String specificationModel;
        @ApiModelProperty(value = "计量单位")
        private String measurementUnit;
        @ApiModelProperty(value = "数量")
        private BigDecimal quantity;
        @ApiModelProperty(value = "单价")
        private BigDecimal unitPrice;
        @ApiModelProperty(value = "使用年限(年)")
        private Integer usefulLife;
        @ApiModelProperty(value = "权属单位/部门名称")
        private String ownerShipDeptName;
        @ApiModelProperty(value = "使用人")
        private String userName;
        @ApiModelProperty(value = "资产状态")
        private String assetStatus;
        @ApiModelProperty(value = "备注")
        private String remarks;
        @ApiModelProperty(value = "入账状态")
        private String accountingStatus;
        @ApiModelProperty(value = "入账时间")
        private LocalDate accountingDate;
        @ApiModelProperty(value = "会计凭证号")
        private String accountingVoucherNo;
        @ApiModelProperty(value = "会计科目")
        private String accountingSubject;
        @ApiModelProperty(value = "入账金额")
        private BigDecimal accountingAmount;
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/OaApprovalApplicationStoragePropertyDetailVO.java
New file
@@ -0,0 +1,170 @@
package com.ruoyi.system.vo.asset;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
/**
 * 房产资产入库申请详情VO(返回新增时填写的所有字段)
 */
@Data
@ApiModel("房产资产入库申请详情VO")
public class OaApprovalApplicationStoragePropertyDetailVO implements Serializable {
    @ApiModelProperty(value = "申请部门ID")
    private Integer deptId;
    @ApiModelProperty(value = "申请部门名称")
    private String deptName;
    @ApiModelProperty(value = "申请人ID")
    private Integer applicantUserId;
    @ApiModelProperty(value = "申请人姓名")
    private String applicantName;
    @ApiModelProperty(value = "申请日期")
    private LocalDate applicationDate;
    @ApiModelProperty(value = "入库备注")
    private String applicationReason;
    @ApiModelProperty(value = "附件地址,多个使用英文逗号拼接")
    private String attachmentUrl;
    @ApiModelProperty(value = "事项标题")
    private String title;
    @ApiModelProperty(value = "资产类型ID")
    private Integer assetTypeId;
    @ApiModelProperty(value = "入库类型 0-正常入库")
    private Boolean storageType;
    @ApiModelProperty(value = "入库日期")
    private LocalDate storageTime;
    @ApiModelProperty(value = "位置类型 0-部门,1-仓库,2-录入地址")
    private Integer addressType;
    @ApiModelProperty(value = "使用部门/位置名称")
    private String useDeptName;
    @ApiModelProperty(value = "仓库名称")
    private String warehouseName;
    @ApiModelProperty(value = "所在位置")
    private String address;
    @ApiModelProperty(value = "房产资产明细列表(按保存展开后的一条资产记录对应一条明细)")
    private List<PropertyAssetItemVO> assetItems;
    @Data
    @ApiModel("房产资产明细VO")
    public static class PropertyAssetItemVO implements Serializable {
        @ApiModelProperty(value = "资产原编码")
        private String assetOriginalCode;
        @ApiModelProperty(value = "资产名称")
        private String assetName;
        @ApiModelProperty(value = "规格型号")
        private String specificationModel;
        @ApiModelProperty(value = "计量单位")
        private String measurementUnit;
        @ApiModelProperty(value = "数量")
        private BigDecimal quantity;
        @ApiModelProperty(value = "单价")
        private BigDecimal unitPrice;
        @ApiModelProperty(value = "使用年限(年)")
        private Integer usefulLife;
        @ApiModelProperty(value = "权属单位/部门名称")
        private String ownerShipDeptName;
        @ApiModelProperty(value = "使用人")
        private String userName;
        @ApiModelProperty(value = "资产状态")
        private String assetStatus;
        @ApiModelProperty(value = "备注")
        private String remarks;
        @ApiModelProperty(value = "入账状态")
        private String accountingStatus;
        @ApiModelProperty(value = "入账时间")
        private LocalDate accountingDate;
        @ApiModelProperty(value = "会计凭证号")
        private String accountingVoucherNo;
        @ApiModelProperty(value = "会计科目")
        private String accountingSubject;
        @ApiModelProperty(value = "入账金额")
        private BigDecimal accountingAmount;
        // 房产资产扩展表字段
        @ApiModelProperty(value = "所在区域")
        private String region;
        @ApiModelProperty(value = "设计用途")
        private String designPurpose;
        @ApiModelProperty(value = "楼栋")
        private String building;
        @ApiModelProperty(value = "房间号")
        private String roomNumber;
        @ApiModelProperty(value = "建筑面积(平方米)")
        private BigDecimal constructionArea;
        @ApiModelProperty(value = "结构")
        private String structureType;
        @ApiModelProperty(value = "权证编号")
        private String certificateNumber;
        @ApiModelProperty(value = "建成年月")
        private LocalDate completionDate;
        @ApiModelProperty(value = "详细位置")
        private String detailedLocation;
        @ApiModelProperty(value = "省资产平台填报价值")
        private BigDecimal provincialPlatformValue;
        @ApiModelProperty(value = "安置情况")
        private String resettlementSituation;
        @ApiModelProperty(value = "是否抵押:0-否,1-是")
        private Integer mortgaged;
        @ApiModelProperty(value = "承租方")
        private String tenantName;
        @ApiModelProperty(value = "租金")
        private BigDecimal rentalAmount;
        @ApiModelProperty(value = "租赁期限起")
        @JsonFormat(pattern = "yyyy-MM-dd")
        private LocalDate leaseStartDate;
        @ApiModelProperty(value = "租赁期限止")
        @JsonFormat(pattern = "yyyy-MM-dd")
        private LocalDate leaseEndDate;
    }
}
ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/OaApprovalApplicationStorageVehicleDetailVO.java
New file
@@ -0,0 +1,143 @@
package com.ruoyi.system.vo.asset;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.util.List;
/**
 * 车辆资产入库申请详情VO(返回新增时填写的所有字段)
 */
@Data
@ApiModel("车辆资产入库申请详情VO")
public class OaApprovalApplicationStorageVehicleDetailVO implements Serializable {
    @ApiModelProperty(value = "申请部门ID")
    private Integer deptId;
    @ApiModelProperty(value = "申请部门名称")
    private String deptName;
    @ApiModelProperty(value = "申请人ID")
    private Integer applicantUserId;
    @ApiModelProperty(value = "申请人姓名")
    private String applicantName;
    @ApiModelProperty(value = "申请日期")
    private LocalDate applicationDate;
    @ApiModelProperty(value = "入库备注")
    private String applicationReason;
    @ApiModelProperty(value = "附件地址,多个使用英文逗号拼接")
    private String attachmentUrl;
    @ApiModelProperty(value = "事项标题")
    private String title;
    @ApiModelProperty(value = "资产类型ID")
    private Integer assetTypeId;
    @ApiModelProperty(value = "入库类型 0-正常入库")
    private Boolean storageType;
    @ApiModelProperty(value = "入库日期")
    private LocalDate storageTime;
    @ApiModelProperty(value = "位置类型 0-部门,1-仓库,2-录入地址")
    private Integer addressType;
    @ApiModelProperty(value = "使用部门/位置名称")
    private String useDeptName;
    @ApiModelProperty(value = "仓库名称")
    private String warehouseName;
    @ApiModelProperty(value = "所在位置")
    private String address;
    @ApiModelProperty(value = "车辆资产明细列表(按保存展开后的一条资产记录对应一条明细)")
    private List<VehicleAssetItemVO> assetItems;
    @Data
    @ApiModel("车辆资产明细VO")
    public static class VehicleAssetItemVO implements Serializable {
        @ApiModelProperty(value = "资产原编码")
        private String assetOriginalCode;
        @ApiModelProperty(value = "资产名称")
        private String assetName;
        @ApiModelProperty(value = "规格型号")
        private String specificationModel;
        @ApiModelProperty(value = "计量单位")
        private String measurementUnit;
        @ApiModelProperty(value = "数量")
        private BigDecimal quantity;
        @ApiModelProperty(value = "单价")
        private BigDecimal unitPrice;
        @ApiModelProperty(value = "使用年限(年)")
        private Integer usefulLife;
        @ApiModelProperty(value = "权属单位/部门名称")
        private String ownerShipDeptName;
        @ApiModelProperty(value = "使用人")
        private String userName;
        @ApiModelProperty(value = "资产状态")
        private String assetStatus;
        @ApiModelProperty(value = "备注")
        private String remarks;
        @ApiModelProperty(value = "入账状态")
        private String accountingStatus;
        @ApiModelProperty(value = "入账时间")
        private LocalDate accountingDate;
        @ApiModelProperty(value = "会计凭证号")
        private String accountingVoucherNo;
        @ApiModelProperty(value = "会计科目")
        private String accountingSubject;
        @ApiModelProperty(value = "入账金额")
        private BigDecimal accountingAmount;
        // 车辆资产扩展表字段
        @ApiModelProperty(value = "车牌号")
        private String licensePlate;
        @ApiModelProperty(value = "车辆识别代码")
        private String vinCode;
        @ApiModelProperty(value = "发动机号")
        private String engineNumber;
        @ApiModelProperty(value = "排量")
        private String displacement;
        @ApiModelProperty(value = "编制情况")
        private String staffingSituation;
        @ApiModelProperty(value = "产地")
        private String origin;
        @ApiModelProperty(value = "取得日期")
        private LocalDate acquisitionDate;
        @ApiModelProperty(value = "产权形式")
        private String propertyRightForm;
    }
}
ruoyi-system/src/main/resources/mapper/system/OaApprovalApplicationAssetMapper.xml
@@ -17,6 +17,40 @@
    <!-- 通用查询结果列 -->
    <sql id="Base_Column_List">
        id, approval_application_id, title, asset_type_id, operate_time, expect_return_date, type, borrow_application_id
    </sql>
</sql>
    <!-- 分页查询:资产领用申请列表(关联审批记录与资产类型) -->
    <select id="selectReceivePage" resultType="com.ruoyi.system.vo.asset.OaApprovalApplicationAssetPageVO">
        SELECT
            oaa.id                               AS id,
            aaa.application_code                 AS applicationCode,
            oaa.title                            AS title,
            aaa.dept_name                        AS deptName,
            aaa.applicant_name                   AS applicantName,
            CASE WHEN at2.level = 2 THEN at1.type_name ELSE at2.type_name END AS firstAssetTypeName,
            CASE WHEN at2.level = 2 THEN at2.type_name ELSE NULL END         AS secondAssetTypeName,
            oaa.operate_time                     AS operateTime,
            aaa.approval_status                  AS approvalStatus
        FROM oa_approval_application_asset oaa
                 INNER JOIN oa_approval_applications aaa ON aaa.id = oaa.approval_application_id
                 LEFT JOIN asset_type at2 ON at2.id = oaa.asset_type_id
                 LEFT JOIN asset_type at1 ON at1.id = (CASE WHEN at2.level = 2 THEN at2.parent_id ELSE at2.id END)
        <where>
            AND aaa.disabled = 0
            AND oaa.type = 0
            <if test="query != null and query.keyword != null and query.keyword != ''">
                AND (
                    oaa.title LIKE CONCAT('%', #{query.keyword}, '%')
                    OR  aaa.application_code LIKE CONCAT('%', #{query.keyword}, '%')
                    OR  aaa.dept_name LIKE CONCAT('%', #{query.keyword}, '%')
                    OR  aaa.applicant_name LIKE CONCAT('%', #{query.keyword}, '%')
                )
            </if>
            <if test="query != null and query.deptId != null">
                AND aaa.dept_id = #{query.deptId}
            </if>
        </where>
        ORDER BY oaa.operate_time DESC, oaa.id DESC
    </select>
</mapper>
ruoyi-system/src/main/resources/mapper/system/SysUserMapper.xml
@@ -267,7 +267,7 @@
    select  * from sys_user
    where 1=1
        <if test="ids != null and ids.size()>0">
            AND deptId IN
            AND dept_id IN
            <foreach collection="ids" separator="," item="id" open="(" close=")">
                #{id}
            </foreach>
@@ -278,7 +278,7 @@
    <select id="selectListByDeptId" resultType="com.ruoyi.common.core.domain.entity.SysUser">
        select u.*
        from sys_user u where u.deptId = #{deptId} and u.status = 0 and u.del_flag = 0
        from sys_user u where u.dept_id = #{deptId} and u.status = 0 and u.del_flag = 0
    </select>
    <select id="selectListByDeptType" resultType="com.ruoyi.common.core.domain.entity.SysUser">
        select u.*
@@ -288,7 +288,7 @@
        select u.*
        from sys_user u where u.status = 0 and u.del_flag = 0
        <if test="projectIds != null and projectIds.size() > 0">
            and u.deptId in
            and u.dept_id in
            <foreach item="item" collection="projectIds" open="(" separator="," close=")">
                #{item}
            </foreach>
@@ -300,7 +300,7 @@
            and deptType = #{deptType}
        </if>
        <if test="projectIds != null and projectIds.size() > 0">
            and deptId in
            and dept_id in
            <foreach item="item" collection="projectIds" open="(" separator="," close=")">
                #{item}
            </foreach>