From ab0ad84b5c577036f9ed5b53d2e90e81e5ba3de9 Mon Sep 17 00:00:00 2001
From: mitao <2763622819@qq.com>
Date: 星期一, 15 九月 2025 20:32:13 +0800
Subject: [PATCH] Merge branch 'feature_asset'

---
 ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java                   |    7 
 ruoyi-system/src/main/java/com/ruoyi/system/service/AssetTypeService.java               |   28 ++
 ruoyi-system/src/main/java/com/ruoyi/system/model/AssetInventoryRecord.java             |   25 ++
 ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/AssetTypeTreeVO.java               |   57 ++++
 ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/AssetTypeDTO.java                 |   37 +++
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/AssetTypeController.java         |   52 ++++
 pom.xml                                                                                 |    1 
 ruoyi-system/src/main/java/com/ruoyi/system/service/AssetWarehouseService.java          |   26 ++
 ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml                         |   17 +
 ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/AssetWarehouseDTO.java            |   47 +++
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AssetTypeServiceImpl.java      |  189 +++++++++++++++
 ruoyi-system/src/main/java/com/ruoyi/system/model/AssetType.java                        |    2 
 ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/AssetWarehouseController.java    |   50 ++++
 ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/AssetWarehouseVO.java              |   49 ++++
 ruoyi-system/src/main/java/com/ruoyi/system/query/AssetWarehousePageQuery.java          |   20 +
 ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AssetWarehouseServiceImpl.java |  102 ++++++++
 16 files changed, 702 insertions(+), 7 deletions(-)

diff --git a/pom.xml b/pom.xml
index 1bceba9..0e23835 100644
--- a/pom.xml
+++ b/pom.xml
@@ -166,7 +166,6 @@
         <module>ruoyi-quartz</module>
         <module>ruoyi-generator</module>
         <module>ruoyi-common</module>
-        <module>ruoyi-applet</module>
     </modules>
     <packaging>pom</packaging>
 
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/AssetTypeController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/AssetTypeController.java
index 34f52b3..59df24a 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/AssetTypeController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/AssetTypeController.java
@@ -1,8 +1,25 @@
 package com.ruoyi.web.controller.api;
 
-
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.system.dto.asset.AssetTypeDTO;
+import com.ruoyi.system.service.AssetTypeService;
+import com.ruoyi.system.vo.asset.AssetTypeTreeVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+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 javax.validation.Valid;
+import java.util.List;
 
 /**
  * <p>
@@ -12,9 +29,42 @@
  * @author WuGuanFengYue
  * @since 2025-09-15
  */
+@Api(tags = {"资产-资产类型管理相关接口"})
+@Validated
 @RestController
 @RequestMapping("/asset-type")
+@RequiredArgsConstructor
 public class AssetTypeController {
 
+    private final AssetTypeService assetTypeService;
+
+    @ApiOperation("获取资产类型树形数据")
+    @GetMapping("/tree")
+    public R<List<AssetTypeTreeVO>> getAssetTypeTree() {
+        List<AssetTypeTreeVO> treeData = assetTypeService.getAssetTypeTree();
+        return R.ok(treeData);
+    }
+
+    @ApiOperation("新增资产类型")
+    @PostMapping("/add")
+    public R<Void> addAssetType(@Valid @RequestBody AssetTypeDTO dto) {
+        assetTypeService.addAssetType(dto);
+        return R.ok();
+    }
+
+    @ApiOperation("编辑资产类型")
+    @PutMapping("/edit")
+    public R<Void> editAssetType(@Valid @RequestBody AssetTypeDTO dto) {
+        assetTypeService.editAssetType(dto);
+        return R.ok();
+    }
+
+    @ApiOperation("删除资产类型")
+    @DeleteMapping("/{id}")
+    public R<Void> deleteAssetType(@ApiParam(name = "id", value = "资产类型ID", required = true) @PathVariable Integer id) {
+        assetTypeService.deleteAssetType(id);
+        return R.ok();
+    }
+    
 }
 
diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/AssetWarehouseController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/AssetWarehouseController.java
index a12aa88..071962b 100644
--- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/AssetWarehouseController.java
+++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/AssetWarehouseController.java
@@ -1,8 +1,26 @@
 package com.ruoyi.web.controller.api;
 
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.ruoyi.common.core.domain.R;
+import com.ruoyi.system.dto.asset.AssetWarehouseDTO;
+import com.ruoyi.system.query.AssetWarehousePageQuery;
+import com.ruoyi.system.service.AssetWarehouseService;
+import com.ruoyi.system.vo.asset.AssetWarehouseVO;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import lombok.RequiredArgsConstructor;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
+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 javax.validation.Valid;
 
 /**
  * <p>
@@ -12,9 +30,41 @@
  * @author WuGuanFengYue
  * @since 2025-09-15
  */
+@Api(tags = {"资产-仓库管理相关接口"})
+@Validated
 @RestController
 @RequestMapping("/asset-warehouse")
+@RequiredArgsConstructor
 public class AssetWarehouseController {
+    private final AssetWarehouseService assetWarehouseService;
+
+    @ApiOperation("获取仓库分页列表")
+    @PostMapping("/page-list")
+    public R<IPage<AssetWarehouseVO>> getPageList(@RequestBody AssetWarehousePageQuery pageQuery) {
+        IPage<AssetWarehouseVO> page = assetWarehouseService.getPageList(pageQuery);
+        return R.ok(page);
+    }
+
+    @ApiOperation("新增仓库")
+    @PostMapping("/add")
+    public R<Void> addWarehouse(@Valid @RequestBody AssetWarehouseDTO dto) {
+        assetWarehouseService.add(dto);
+        return R.ok();
+    }
+
+    @ApiOperation("编辑仓库")
+    @PutMapping("/add")
+    public R<Void> editWarehouse(@Valid @RequestBody AssetWarehouseDTO dto) {
+        assetWarehouseService.edit(dto);
+        return R.ok();
+    }
+
+    @ApiOperation("删除仓库")
+    @DeleteMapping("/{id}")
+    public R<Void> deleteWarehouse(@ApiParam(name = "id", value = "仓库ID", required = true) @PathVariable Integer id) {
+        assetWarehouseService.delete(id);
+        return R.ok();
+    }
 
 }
 
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/AssetTypeDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/AssetTypeDTO.java
new file mode 100644
index 0000000..9c95616
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/AssetTypeDTO.java
@@ -0,0 +1,37 @@
+package com.ruoyi.system.dto.asset;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+
+/**
+ * 资产类型数据传输对象
+ *
+ * @author WuGuanFengYue
+ * @date 2025/9/15
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@ApiModel("资产类型数据传输对象")
+public class AssetTypeDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "资产类型ID,编辑时必填")
+    private Integer id;
+
+    @ApiModelProperty(value = "父级资产类型ID,为空则添加一级资产类型")
+    private Integer parentId;
+
+    @ApiModelProperty(value = "资产类型名称", required = true)
+    @NotBlank(message = "资产类型名称不能为空")
+    private String typeName;
+
+    @ApiModelProperty(value = "资产简写", required = true)
+    @NotBlank(message = "资产简写不能为空")
+    private String typeCode;
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/AssetWarehouseDTO.java b/ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/AssetWarehouseDTO.java
new file mode 100644
index 0000000..5d3b5bb
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/dto/asset/AssetWarehouseDTO.java
@@ -0,0 +1,47 @@
+package com.ruoyi.system.dto.asset;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import javax.validation.constraints.NotBlank;
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @author mitao
+ * @date 2025/9/15
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@ApiModel("仓库数据传输对象")
+public class AssetWarehouseDTO implements Serializable {
+
+    private static final long serialVersionUID = -64233615037814733L;
+
+    @ApiModelProperty(value = "主键")
+    private Integer id;
+
+    @ApiModelProperty(value = "仓库名称")
+    @NotBlank(message = "仓库名称不能为空")
+    private String warehouseName;
+
+    @ApiModelProperty(value = "权属部门ID")
+    private Integer deptId;
+
+    @ApiModelProperty(value = "面积(平方米)")
+    private BigDecimal area;
+
+    @ApiModelProperty(value = "位置")
+    private String location;
+
+    @ApiModelProperty(value = "负责人姓名")
+    @NotBlank(message = "负责人姓名不能为空")
+    private String managerName;
+
+    @ApiModelProperty(value = "联系电话")
+    @NotBlank(message = "联系电话不能为空")
+    private String managerPhone;
+
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
index 384a9b6..f1944e6 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/SysDeptMapper.java
@@ -1,8 +1,9 @@
 package com.ruoyi.system.mapper;
 
-import java.util.List;
-import org.apache.ibatis.annotations.Param;
 import com.ruoyi.common.core.domain.entity.SysDept;
+import org.apache.ibatis.annotations.Param;
+
+import java.util.List;
 
 /**
  * 部门管理 数据层
@@ -115,4 +116,6 @@
      * @return 结果
      */
     public int deleteDeptById(Long deptId);
+
+    public List<SysDept> selectByIds(@Param("deptIds") List<Integer> deptIds);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/model/AssetInventoryRecord.java b/ruoyi-system/src/main/java/com/ruoyi/system/model/AssetInventoryRecord.java
index 80682ab..2df7126 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/model/AssetInventoryRecord.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/model/AssetInventoryRecord.java
@@ -10,6 +10,7 @@
 import lombok.EqualsAndHashCode;
 
 import java.io.Serializable;
+import java.time.LocalDateTime;
 
 /**
  * <p>
@@ -35,13 +36,35 @@
     @TableField("asset_main_id")
     private Integer assetMainId;
 
+    @ApiModelProperty(value = "仓库ID")
+    @TableField("warehouse_id")
+    private Integer warehouseId;
+
     @ApiModelProperty(value = "出入库类型 0-入库,1-出库")
     @TableField("type")
-    private Boolean type;
+    private Integer type;
 
     @ApiModelProperty(value = "备注(记录出入库类型,如资产入库、借用、借用归还、资产变更、领用、盘点、处置等)")
     @TableField("remarks")
     private String remarks;
 
+    @ApiModelProperty(value = "创建时间")
+    @TableField("create_time")
+    private LocalDateTime createTime;
 
+    @ApiModelProperty(value = "创建人")
+    @TableField("create_by")
+    private String createBy;
+
+    @ApiModelProperty(value = "更新时间")
+    @TableField("update_time")
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty(value = "更新人")
+    @TableField("update_by")
+    private String updateBy;
+
+    @ApiModelProperty(value = "是否删除 0-否,1-是")
+    @TableField("disabled")
+    private Boolean disabled;
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/model/AssetType.java b/ruoyi-system/src/main/java/com/ruoyi/system/model/AssetType.java
index 278dfff..24fb685 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/model/AssetType.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/model/AssetType.java
@@ -66,7 +66,7 @@
 
     @ApiModelProperty(value = "是否删除 0-否,1-是")
     @TableField("disabled")
-    private Boolean disabled;
+    private Integer disabled;
 
 
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/query/AssetWarehousePageQuery.java b/ruoyi-system/src/main/java/com/ruoyi/system/query/AssetWarehousePageQuery.java
new file mode 100644
index 0000000..5d0f834
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/query/AssetWarehousePageQuery.java
@@ -0,0 +1,20 @@
+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;
+
+/**
+ * @author mitao
+ * @date 2025/9/15
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ApiModel("仓库分页查询对象")
+public class AssetWarehousePageQuery extends BasePage {
+    private static final long serialVersionUID = -2968978743484299082L;
+    @ApiModelProperty("关键字" )
+    private String keyword;
+}
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/AssetTypeService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/AssetTypeService.java
index ef81f11..65c62d6 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/AssetTypeService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/AssetTypeService.java
@@ -1,7 +1,11 @@
 package com.ruoyi.system.service;
 
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.system.dto.asset.AssetTypeDTO;
 import com.ruoyi.system.model.AssetType;
+import com.ruoyi.system.vo.asset.AssetTypeTreeVO;
+
+import java.util.List;
 
 /**
  * <p>
@@ -13,4 +17,28 @@
  */
 public interface AssetTypeService extends IService<AssetType> {
 
+    /**
+     * 获取资产类型树形数据
+     * @return 资产类型树形列表
+     */
+    List<AssetTypeTreeVO> getAssetTypeTree();
+
+    /**
+     * 新增资产类型
+     * @param dto 资产类型数据传输对象
+     */
+    void addAssetType(AssetTypeDTO dto);
+
+    /**
+     * 编辑资产类型
+     * @param dto 资产类型数据传输对象
+     */
+    void editAssetType(AssetTypeDTO dto);
+
+    /**
+     * 删除资产类型
+     * @param id 资产类型ID
+     */
+    void deleteAssetType(Integer id);
+
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/AssetWarehouseService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/AssetWarehouseService.java
index be89f95..ba42580 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/AssetWarehouseService.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/AssetWarehouseService.java
@@ -1,7 +1,11 @@
 package com.ruoyi.system.service;
 
+import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ruoyi.system.dto.asset.AssetWarehouseDTO;
 import com.ruoyi.system.model.AssetWarehouse;
+import com.ruoyi.system.query.AssetWarehousePageQuery;
+import com.ruoyi.system.vo.asset.AssetWarehouseVO;
 
 /**
  * <p>
@@ -12,5 +16,27 @@
  * @since 2025-09-15
  */
 public interface AssetWarehouseService extends IService<AssetWarehouse> {
+    /**
+     * 获取仓库分页列表
+     * @param pageQuery
+     * @return
+     */
+    IPage<AssetWarehouseVO> getPageList(AssetWarehousePageQuery pageQuery);
 
+    /**
+     * 添加仓库
+     * @param dto
+     */
+    void add(AssetWarehouseDTO dto);
+
+    /**
+     * 编辑仓库
+     * @param dto
+     */
+    void edit(AssetWarehouseDTO dto);
+    /**
+     * 删除仓库
+     * @param id
+     */
+    void delete(Integer id);
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AssetTypeServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AssetTypeServiceImpl.java
index 38a793d..7c928c0 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AssetTypeServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AssetTypeServiceImpl.java
@@ -1,10 +1,26 @@
 package com.ruoyi.system.service.impl;
 
+import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.system.dto.asset.AssetTypeDTO;
 import com.ruoyi.system.mapper.AssetTypeMapper;
+import com.ruoyi.system.model.AssetMain;
 import com.ruoyi.system.model.AssetType;
+import com.ruoyi.system.service.AssetMainService;
 import com.ruoyi.system.service.AssetTypeService;
+import com.ruoyi.system.vo.asset.AssetTypeTreeVO;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -15,6 +31,179 @@
  * @since 2025-09-15
  */
 @Service
+@RequiredArgsConstructor
 public class AssetTypeServiceImpl extends ServiceImpl<AssetTypeMapper, AssetType> implements AssetTypeService {
 
+    private final AssetMainService assetMainService;
+
+    @Override
+    public List<AssetTypeTreeVO> getAssetTypeTree() {
+        // 查询所有未删除的资产类型数据
+        LambdaQueryWrapper<AssetType> queryWrapper = new LambdaQueryWrapper<>();
+        queryWrapper.orderByAsc(AssetType::getLevel)
+                .orderByAsc(AssetType::getId);
+        
+        List<AssetType> allAssetTypes = this.list(queryWrapper);
+        
+        if (CollUtil.isEmpty(allAssetTypes)) {
+            return new ArrayList<>();
+        }
+        
+        // 转换为VO对象
+        List<AssetTypeTreeVO> assetTypeVOs = BeanUtil.copyToList(allAssetTypes, AssetTypeTreeVO.class);
+        
+        // 按父级ID分组
+        Map<Integer, List<AssetTypeTreeVO>> parentIdMap = assetTypeVOs.stream()
+                .collect(Collectors.groupingBy(AssetTypeTreeVO::getParentId));
+        
+        // 构建树形结构
+        List<AssetTypeTreeVO> rootNodes = parentIdMap.get(0);
+        if (CollUtil.isEmpty(rootNodes)) {
+            return new ArrayList<>();
+        }
+        
+        // 为每个根节点设置子节点
+        for (AssetTypeTreeVO rootNode : rootNodes) {
+            List<AssetTypeTreeVO> children = parentIdMap.get(rootNode.getId());
+            rootNode.setChildren(children != null ? children : new ArrayList<>());
+        }
+        
+        return rootNodes;
+    }
+
+    @Override
+    public void addAssetType(AssetTypeDTO dto) {
+        // 校验资产类型名称是否重复
+        LambdaQueryWrapper<AssetType> nameQueryWrapper = new LambdaQueryWrapper<>();
+        nameQueryWrapper.eq(AssetType::getTypeName, dto.getTypeName());
+        AssetType existingByName = this.getOne(nameQueryWrapper);
+        if (Objects.nonNull(existingByName)) {
+            throw new ServiceException("资产类型名称已存在");
+        }
+
+        // 校验资产简写是否重复
+        LambdaQueryWrapper<AssetType> codeQueryWrapper = new LambdaQueryWrapper<>();
+        codeQueryWrapper.eq(AssetType::getTypeCode, dto.getTypeCode());
+        AssetType existingByCode = this.getOne(codeQueryWrapper);
+        if (Objects.nonNull(existingByCode)) {
+            throw new ServiceException("资产类型简写已存在");
+        }
+
+        // 创建资产类型对象
+        AssetType assetType = new AssetType();
+        assetType.setTypeName(dto.getTypeName());
+        assetType.setTypeCode(dto.getTypeCode());
+        
+        // 处理层级逻辑
+        if (Objects.isNull(dto.getParentId()) || dto.getParentId().equals(0)) {
+            // 添加一级资产类型
+            assetType.setParentId(0);
+            assetType.setLevel(1);
+        } else {
+            // 添加二级资产类型,先校验父级是否存在
+            AssetType parentAssetType = this.getById(dto.getParentId());
+            if (Objects.isNull(parentAssetType)) {
+                throw new ServiceException("父级资产类型不存在");
+            }
+            if (!parentAssetType.getLevel().equals(1)) {
+                throw new ServiceException("只能在一级资产类型下添加二级资产类型");
+            }
+            assetType.setParentId(dto.getParentId());
+            assetType.setLevel(2);
+        }
+
+        // 设置创建信息
+        String username = SecurityUtils.getUsername();
+        assetType.setCreateBy(username);
+        
+        // 保存资产类型
+        this.save(assetType);
+    }
+
+    @Override
+    public void editAssetType(AssetTypeDTO dto) {
+        // 校验资产类型ID是否为空
+        if (Objects.isNull(dto.getId())) {
+            throw new ServiceException("资产类型ID不能为空");
+        }
+
+        // 校验资产类型是否存在
+        AssetType existingAssetType = this.getById(dto.getId());
+        if (Objects.isNull(existingAssetType)) {
+            throw new ServiceException("资产类型不存在");
+        }
+
+        // 校验是否有关联的资产记录
+        LambdaQueryWrapper<AssetMain> assetMainQueryWrapper = new LambdaQueryWrapper<>();
+        assetMainQueryWrapper.eq(AssetMain::getAssetTypeId, dto.getId());
+        long assetMainCount = assetMainService.count(assetMainQueryWrapper);
+        if (assetMainCount > 0) {
+            throw new ServiceException("该资产类型已关联资产记录,不能编辑");
+        }
+
+        // 校验资产类型名称是否重复(排除自身)
+        LambdaQueryWrapper<AssetType> nameQueryWrapper = new LambdaQueryWrapper<>();
+        nameQueryWrapper.eq(AssetType::getTypeName, dto.getTypeName())
+                       .ne(AssetType::getId, dto.getId());
+        AssetType existingByName = this.getOne(nameQueryWrapper);
+        if (Objects.nonNull(existingByName)) {
+            throw new ServiceException("资产类型名称已存在");
+        }
+        
+        // 校验资产简写是否重复(排除自身)
+        LambdaQueryWrapper<AssetType> codeQueryWrapper = new LambdaQueryWrapper<>();
+        codeQueryWrapper.eq(AssetType::getTypeCode, dto.getTypeCode())
+                       .ne(AssetType::getId, dto.getId());
+        AssetType existingByCode = this.getOne(codeQueryWrapper);
+        if (Objects.nonNull(existingByCode)) {
+            throw new ServiceException("资产简写已存在");
+        }
+
+        // 更新资产类型信息
+        AssetType assetType = new AssetType();
+        assetType.setId(dto.getId());
+        assetType.setTypeName(dto.getTypeName());
+        assetType.setTypeCode(dto.getTypeCode());
+        
+        // 设置更新信息
+        String username = SecurityUtils.getUsername();
+        assetType.setUpdateBy(username);
+        
+        // 更新资产类型
+        this.updateById(assetType);
+    }
+
+    @Override
+    public void deleteAssetType(Integer id) {
+        // 校验资产类型ID是否为空
+        if (Objects.isNull(id)) {
+            throw new ServiceException("资产类型ID不能为空");
+        }
+
+        // 校验资产类型是否存在
+        AssetType existingAssetType = this.getById(id);
+        if (Objects.isNull(existingAssetType)) {
+            throw new ServiceException("资产类型不存在");
+        }
+
+        // 校验是否有子类型
+        LambdaQueryWrapper<AssetType> childQueryWrapper = new LambdaQueryWrapper<>();
+        childQueryWrapper.eq(AssetType::getParentId, id);
+        long childCount = this.count(childQueryWrapper);
+        if (childCount > 0) {
+            throw new ServiceException("该资产类型存在子类型,不能删除");
+        }
+
+        // 校验是否有关联的资产记录
+        LambdaQueryWrapper<AssetMain> assetMainQueryWrapper = new LambdaQueryWrapper<>();
+        assetMainQueryWrapper.eq(AssetMain::getAssetTypeId, id);
+        long assetMainCount = assetMainService.count(assetMainQueryWrapper);
+        if (assetMainCount > 0) {
+            throw new ServiceException("该资产类型已关联资产记录,不能删除");
+        }
+
+        // 删除资产类型
+        this.removeById(id);
+    }
+
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AssetWarehouseServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AssetWarehouseServiceImpl.java
index c50fb16..0d0db98 100644
--- a/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AssetWarehouseServiceImpl.java
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/impl/AssetWarehouseServiceImpl.java
@@ -1,10 +1,31 @@
 package com.ruoyi.system.service.impl;
 
+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.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.ruoyi.common.core.domain.entity.SysDept;
+import com.ruoyi.common.exception.ServiceException;
+import com.ruoyi.common.utils.SecurityUtils;
+import com.ruoyi.common.utils.StringUtils;
+import com.ruoyi.system.dto.asset.AssetWarehouseDTO;
 import com.ruoyi.system.mapper.AssetWarehouseMapper;
+import com.ruoyi.system.mapper.SysDeptMapper;
+import com.ruoyi.system.model.AssetInventoryRecord;
 import com.ruoyi.system.model.AssetWarehouse;
+import com.ruoyi.system.query.AssetWarehousePageQuery;
+import com.ruoyi.system.service.AssetInventoryRecordService;
 import com.ruoyi.system.service.AssetWarehouseService;
+import com.ruoyi.system.vo.asset.AssetWarehouseVO;
+import lombok.RequiredArgsConstructor;
 import org.springframework.stereotype.Service;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -15,6 +36,87 @@
  * @since 2025-09-15
  */
 @Service
+@RequiredArgsConstructor
 public class AssetWarehouseServiceImpl extends ServiceImpl<AssetWarehouseMapper, AssetWarehouse> implements AssetWarehouseService {
 
+    private final AssetInventoryRecordService assetInventoryRecordService;
+    private final SysDeptMapper sysDeptMapper;
+
+    @Override
+    public IPage<AssetWarehouseVO> getPageList(AssetWarehousePageQuery pageQuery) {
+        LambdaQueryWrapper<AssetWarehouse> queryWrapper = new LambdaQueryWrapper<>();
+        if (StringUtils.isNotBlank(pageQuery.getKeyword())) {
+            queryWrapper.like(AssetWarehouse::getWarehouseName, pageQuery.getKeyword())
+                    .or()
+                    .like(AssetWarehouse::getManagerName, pageQuery.getKeyword());
+        }
+        Page<AssetWarehouse> page = this.page(new Page<>(pageQuery.getPageNum(), pageQuery.getPageSize()), queryWrapper);
+        Page<AssetWarehouseVO> pageVO = new Page<>();
+        BeanUtil.copyProperties(page, pageVO, "records");
+        List<AssetWarehouseVO> assetWarehouseVOS = BeanUtil.copyToList(page.getRecords(), AssetWarehouseVO.class);
+        if (CollUtil.isEmpty(assetWarehouseVOS)) {
+            return pageVO;
+        }
+        List<Integer> warehouseIds = assetWarehouseVOS.stream().map(AssetWarehouseVO::getId).collect(Collectors.toList());
+        List<Integer> deptIds = assetWarehouseVOS.stream().map(AssetWarehouseVO::getDeptId).distinct().collect(Collectors.toList());
+
+        List<SysDept> sysDepts = sysDeptMapper.selectByIds(deptIds);
+        Map<Integer, String> deptMap = sysDepts.stream()
+                .collect(Collectors.toMap(item->item.getDeptId().intValue(), SysDept::getDeptName));
+        //查询库存数量
+        Map<Integer, List<AssetInventoryRecord>> inventoryRecordMap = assetInventoryRecordService.lambdaQuery()
+                .in(AssetInventoryRecord::getWarehouseId, warehouseIds)
+                .list().stream().collect(Collectors.groupingBy(AssetInventoryRecord::getWarehouseId));
+        //计算当前库存
+        assetWarehouseVOS.forEach(warehouseVO -> {
+            List<AssetInventoryRecord> assetInventoryRecords = inventoryRecordMap.get(warehouseVO.getId());
+            if (CollUtil.isEmpty(assetInventoryRecords)) {
+                warehouseVO.setCurrentStock(0);
+            }
+            long inStock = assetInventoryRecords.stream().filter(item -> item.getType().equals(0)).count();
+            long outStock = assetInventoryRecords.stream().filter(item -> item.getType().equals(1)).count();
+            warehouseVO.setCurrentStock((int) (inStock - outStock));
+            //设置部门名称
+            warehouseVO.setDeptName(deptMap.getOrDefault(warehouseVO.getDeptId(), ""));
+        });
+        pageVO.setRecords(assetWarehouseVOS);
+        return pageVO;
+    }
+
+    @Override
+    public void add(AssetWarehouseDTO dto) {
+        AssetWarehouse assetWarehouse = BeanUtil.copyProperties(dto, AssetWarehouse.class);
+        String username = SecurityUtils.getUsername();
+        assetWarehouse.setCreateBy(username);
+        this.save(assetWarehouse);
+    }
+
+    @Override
+    public void edit(AssetWarehouseDTO dto) {
+        if (Objects.isNull(dto.getId())) {
+            throw new ServiceException("仓库ID不能为空");
+        }
+        AssetWarehouse assetWarehouse = BeanUtil.copyProperties(dto, AssetWarehouse.class);
+        String username = SecurityUtils.getUsername();
+        assetWarehouse.setUpdateBy(username);
+        this.updateById(assetWarehouse);
+    }
+
+    @Override
+    public void delete(Integer id) {
+        if (Objects.isNull(id)) {
+            throw new ServiceException("仓库ID不能为空");
+        }
+        List<AssetInventoryRecord> list = assetInventoryRecordService.lambdaQuery().eq(AssetInventoryRecord::getWarehouseId, id).list();
+        if (CollUtil.isNotEmpty(list)) {
+            List<Integer> inStockIds = list.stream().filter(item -> item.getType().equals(0)).map(AssetInventoryRecord::getAssetMainId).collect(Collectors.toList());
+            list.stream().filter(item -> item.getType().equals(1)).forEach(item -> {
+                inStockIds.remove(item.getAssetMainId());
+            });
+            if (CollUtil.isNotEmpty(inStockIds)) {
+                throw new ServiceException("该仓库存在库存记录,不能删除");
+            }
+        }
+        this.removeById(id);
+    }
 }
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/AssetTypeTreeVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/AssetTypeTreeVO.java
new file mode 100644
index 0000000..8d9c135
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/AssetTypeTreeVO.java
@@ -0,0 +1,57 @@
+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 lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.List;
+
+/**
+ * 资产类型树形视图对象
+ *
+ * @author WuGuanFengYue
+ * @date 2025/9/15
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@ApiModel("资产类型树形视图对象")
+public class AssetTypeTreeVO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @ApiModelProperty(value = "主键")
+    private Integer id;
+
+    @ApiModelProperty(value = "资产类型名称")
+    private String typeName;
+
+    @ApiModelProperty(value = "资产简写")
+    private String typeCode;
+
+    @ApiModelProperty(value = "父级ID,0表示一级分类")
+    private Integer parentId;
+
+    @ApiModelProperty(value = "层级:1-一级分类,2-二级分类")
+    private Integer level;
+
+    @ApiModelProperty(value = "创建时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime createTime;
+
+    @ApiModelProperty(value = "创建人")
+    private String createBy;
+
+    @ApiModelProperty(value = "更新时间")
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private LocalDateTime updateTime;
+
+    @ApiModelProperty(value = "更新人")
+    private String updateBy;
+
+    @ApiModelProperty(value = "子节点列表")
+    private List<AssetTypeTreeVO> children;
+}
\ No newline at end of file
diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/AssetWarehouseVO.java b/ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/AssetWarehouseVO.java
new file mode 100644
index 0000000..45d6ec0
--- /dev/null
+++ b/ruoyi-system/src/main/java/com/ruoyi/system/vo/asset/AssetWarehouseVO.java
@@ -0,0 +1,49 @@
+package com.ruoyi.system.vo.asset;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+import java.math.BigDecimal;
+
+/**
+ * @author mitao
+ * @date 2025/9/15
+ */
+@Data
+@EqualsAndHashCode(callSuper = false)
+@ApiModel("仓库视图对象")
+public class AssetWarehouseVO implements Serializable {
+
+    private static final long serialVersionUID = 6352690221179631751L;
+
+    @ApiModelProperty(value = "主键")
+    private Integer id;
+
+    @ApiModelProperty(value = "仓库名称")
+    private String warehouseName;
+
+    @ApiModelProperty(value = "权属部门ID")
+    private Integer deptId;
+
+    @ApiModelProperty(value = "权属部门名称")
+    private String deptName;
+
+    @ApiModelProperty(value = "面积(平方米)")
+    private BigDecimal area;
+
+    @ApiModelProperty(value = "位置")
+    private String location;
+
+    @ApiModelProperty(value = "负责人姓名")
+    private String managerName;
+
+    @ApiModelProperty(value = "联系电话")
+    private String managerPhone;
+
+    @ApiModelProperty(value = "当前库存数量" )
+    private Integer currentStock;
+
+}
diff --git a/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
index cf439f6..bcf65cd 100644
--- a/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
+++ b/ruoyi-system/src/main/resources/mapper/system/SysDeptMapper.xml
@@ -86,7 +86,22 @@
 	    <include refid="selectDeptVo"/>
 		where dept_name=#{deptName} and parent_id = #{parentId} and del_flag = '0' limit 1
 	</select>
-    
+
+    <select id="selectByIds" resultType="com.ruoyi.common.core.domain.entity.SysDept"
+            parameterType="java.util.List">
+		select * from sys_dept
+		<where>
+			del_flag = '0'
+			<if test="deptIds !=null and deptIds.size() != 0">
+				and dept_id in
+				<foreach collection="deptIds" item="item" open="(" separator="," close=")">
+					#{item}
+				</foreach>
+			</if>
+		</where>
+		order by id desc
+	</select>
+
     <insert id="insertDept" parameterType="SysDept">
  		insert into sys_dept(
  			<if test="deptId != null and deptId != 0">dept_id,</if>

--
Gitblit v1.7.1