소스 검색

1.添加图书分类管理模块

1 1 개월 전
부모
커밋
2e674de927
29개의 변경된 파일2720개의 추가작업 그리고 23개의 파일을 삭제
  1. 4 0
      imwork-commons/imwork-commons-core/pom.xml
  2. 32 14
      imwork-commons/imwork-commons-core/src/main/java/top/imwork/commons/core/base/BaseController.java
  3. 41 7
      imwork-commons/imwork-commons-core/src/main/java/top/imwork/commons/core/pojo/ResponseMsg.java
  4. 2 0
      imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/SilosStart.java
  5. 28 0
      imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/controller/cms/books/BookCategoryController.java
  6. 79 0
      imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/controller/cms/books/CategoriesServiceController.java
  7. 213 0
      imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/convert/CategoriesConvert.java
  8. 14 0
      imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/dao/CategoriesDao.java
  9. 300 0
      imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/entity/Categories.java
  10. 100 0
      imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/pojo/bo/CategoriesBO.java
  11. 19 0
      imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/pojo/bo/CategoriesResultBO.java
  12. 100 0
      imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/pojo/dto/CategoriesDTO.java
  13. 18 0
      imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/pojo/dto/CategoriesListDTO.java
  14. 18 0
      imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/pojo/po/CategoriesListParamVO.java
  15. 100 0
      imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/pojo/po/CategoriesParamVO.java
  16. 19 0
      imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/pojo/vo/CategoriesResultVO.java
  17. 101 0
      imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/pojo/vo/CategoriesVO.java
  18. 52 0
      imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/service/ICategoriesService.java
  19. 112 0
      imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/service/impl/CategoriesServiceImpl.java
  20. 1 1
      imwork-windows/imwork-silos/src/main/resources/application.yml
  21. 74 0
      imwork-windows/imwork-silos/src/main/resources/mapper/cms/books/CategoriesDao.xml
  22. 717 0
      imwork-windows/imwork-silos/src/main/resources/static/business/cms/books/category/category.css
  23. 49 0
      imwork-windows/imwork-silos/src/main/resources/static/business/cms/books/category/edit.js
  24. 50 0
      imwork-windows/imwork-silos/src/main/resources/static/business/cms/books/category/list.js
  25. 1 1
      imwork-windows/imwork-silos/src/main/resources/static/business/generator/list.js
  26. 155 0
      imwork-windows/imwork-silos/src/main/resources/templates/cms/books/category/edit.html
  27. 305 0
      imwork-windows/imwork-silos/src/main/resources/templates/cms/books/category/list.html
  28. 10 0
      imwork-windows/imwork-silos/src/main/resources/templates/main/index.html
  29. 6 0
      pom.xml

+ 4 - 0
imwork-commons/imwork-commons-core/pom.xml

@@ -23,6 +23,10 @@
     </properties>
 
     <dependencies>
+        <dependency>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
+        </dependency>
         <dependency>
             <groupId>org.projectlombok</groupId>
             <artifactId>lombok</artifactId>

+ 32 - 14
imwork-commons/imwork-commons-core/src/main/java/top/imwork/commons/core/base/BaseController.java

@@ -1,5 +1,6 @@
 package top.imwork.commons.core.base;
 
+import com.google.gson.Gson;
 import jakarta.servlet.http.HttpServletRequest;
 import jakarta.servlet.http.HttpServletResponse;
 import lombok.extern.slf4j.Slf4j;
@@ -13,11 +14,13 @@ import org.springframework.web.bind.annotation.ControllerAdvice;
 import org.springframework.web.bind.annotation.ExceptionHandler;
 import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.client.HttpClientErrorException;
-import top.imwork.commons.core.constants.Constants;
 import top.imwork.commons.core.enums.HttpStatusCodeEnum;
 import top.imwork.commons.core.exception.BusinessException;
 import top.imwork.commons.core.pojo.ResponseMsg;
+import top.imwork.commons.core.utils.StringUtils;
 
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Objects;
 
 /**
@@ -50,13 +53,13 @@ public class BaseController {
      * HTTP请求参数转换异常
      *
      * @param exception HTTP请求参数转换异常
-     * @return
+     * @return 响应错误信息
      */
     @ResponseBody
     @ExceptionHandler({HttpMessageNotReadableException.class})
-    public ResponseMsg httpMessageNotReadableException(Exception exception) {
-        log.error("code:" + HttpStatusCodeEnum.BAD_REQUEST.getCode() + "message:" + HttpStatusCodeEnum.BAD_REQUEST.getZmsg(), "error:HTTP请求参数转换错误!");
-        return ResponseMsg.buildResponse(HttpStatusCodeEnum.BAD_REQUEST.getCode(), HttpStatusCodeEnum.BAD_REQUEST.getZmsg(), "error:HTTP请求参数转换错误!");
+    public ResponseMsg httpMessageNotReadableException(Exception exception, HttpServletRequest request, HttpServletResponse response) {
+        errorMsg(exception, request, response);
+        return ResponseMsg.buildResponse(HttpStatusCodeEnum.BAD_REQUEST.getCode(), HttpStatusCodeEnum.BAD_REQUEST.getZmsg(), null);
     }
 
     /**
@@ -67,14 +70,29 @@ public class BaseController {
     @ResponseBody
     @ExceptionHandler(value = Exception.class)
     protected ResponseMsg exception(Exception exception, HttpServletRequest request, HttpServletResponse response) {
-        Integer statusCode = (Integer) request.getAttribute("javax.servlet.error.status_code");
-        if (statusCode == null) {
-            log.error(HttpStatusCodeEnum.INTERNAL_SERVER_ERROR.getZmsg(), exception.getMessage());
-            return ResponseMsg.buildResponse(HttpStatusCodeEnum.INTERNAL_SERVER_ERROR.getCode(), HttpStatusCodeEnum.INTERNAL_SERVER_ERROR.getZmsg(), Constants.ERROR + exception.getMessage());
-        } else {
-            log.error(Objects.requireNonNull(HttpStatusCodeEnum.fromTypeCode(statusCode)).getZmsg(), exception.getMessage());
-            return ResponseMsg.buildResponse(statusCode, Objects.requireNonNull(HttpStatusCodeEnum.fromTypeCode(statusCode)).getZmsg(), Constants.ERROR + exception.getMessage());
+        int statusCode = response.getStatus();
+        errorMsg(exception, request, response);
+        if (statusCode == 200) {
+            statusCode = HttpStatusCodeEnum.BAD_REQUEST.getCode();
         }
+        return ResponseMsg.buildResponse(statusCode,
+                StringUtils.isEmpty(exception.toString()) ? Objects.requireNonNull(HttpStatusCodeEnum.fromTypeCode(statusCode)).getZmsg() : exception.toString(), null);
+    }
+
+    private void errorMsg(Exception exception, HttpServletRequest request, HttpServletResponse response) {
+        Map<String, Object> details = new HashMap<>();
+        details.put("code", response.getStatus());
+        details.put("msg", exception.getMessage());
+        details.put("url", request.getRequestURI());
+
+        Map<String, String[]> parameterMap = request.getParameterMap();
+        Gson gson = new Gson();
+        String json = gson.toJson(parameterMap);
+        details.put("params", json);
+        if (response.getStatus() == 200) {
+            details.put("code", HttpStatusCodeEnum.BAD_REQUEST.getCode());
+        }
+        log.error(details.toString());
     }
 
     /**
@@ -86,7 +104,7 @@ public class BaseController {
     @ResponseBody
     @ExceptionHandler({BusinessException.class})
     public ResponseMsg exceptionParam(BusinessException exception) {
-        log.error("业务异常:" + exception.getMessage());
+        log.error("业务异常:{}", exception.getMessage());
         return ResponseMsg.error("业务异常:" + exception.getMessage());
     }
 
@@ -116,7 +134,7 @@ public class BaseController {
         if (bindingResult.hasErrors()) {
             FieldError error = bindingResult.getFieldError();
             if (error != null) {
-                log.error(error.getField() + error.getDefaultMessage());
+                log.error("{}{}", error.getField(), error.getDefaultMessage());
                 return ResponseMsg.error(error.getField() + error.getDefaultMessage());
             }
         }

+ 41 - 7
imwork-commons/imwork-commons-core/src/main/java/top/imwork/commons/core/pojo/ResponseMsg.java

@@ -19,6 +19,7 @@ import java.util.Map;
 public class ResponseMsg extends HashMap<String, Object> {
     @Serial
     private static final long serialVersionUID = 1L;
+
     public ResponseMsg() {
         put("code", HttpStatusCodeEnum.OK.getCode());
         put("msg", HttpStatusCodeEnum.OK.getZmsg());
@@ -26,6 +27,7 @@ public class ResponseMsg extends HashMap<String, Object> {
 
     /**
      * 默认响应成功消息
+     *
      * @return ResponseMsg
      */
     public static ResponseMsg ok() {
@@ -34,6 +36,7 @@ public class ResponseMsg extends HashMap<String, Object> {
 
     /**
      * 响应状态码消息
+     *
      * @param code 状态码
      * @return ResponseMsg
      */
@@ -43,15 +46,17 @@ public class ResponseMsg extends HashMap<String, Object> {
 
     /**
      * 响应自定义成功消息
+     *
      * @param message 消息内容
      * @return ResponseMsg
      */
     public static ResponseMsg ok(String message) {
-        return buildResponse(HttpStatusCodeEnum.OK.getCode(),message);
+        return buildResponse(HttpStatusCodeEnum.OK.getCode(), message);
     }
 
     /**
      * 响应失败消息
+     *
      * @return ResponseMsg
      */
     public static ResponseMsg fail() {
@@ -60,14 +65,16 @@ public class ResponseMsg extends HashMap<String, Object> {
 
     /**
      * 响应失败消息
+     *
      * @return ResponseMsg
      */
     public static ResponseMsg fail(Object message) {
-        return buildResponse(HttpStatusCodeEnum.BAD_REQUEST.getCode(), message,null);
+        return buildResponse(HttpStatusCodeEnum.BAD_REQUEST.getCode(), message, null);
     }
 
     /**
      * 响应错误消息
+     *
      * @return ResponseMsg
      */
     public static ResponseMsg error() {
@@ -76,6 +83,7 @@ public class ResponseMsg extends HashMap<String, Object> {
 
     /**
      * 响应自定义错误消息
+     *
      * @return ResponseMsg
      */
     public static ResponseMsg error(Object message) {
@@ -88,7 +96,8 @@ public class ResponseMsg extends HashMap<String, Object> {
 
     /**
      * 响应自定义键-值消息
-     * @param key 键
+     *
+     * @param key   键
      * @param value 值
      * @return ResponseMsg
      */
@@ -100,6 +109,7 @@ public class ResponseMsg extends HashMap<String, Object> {
 
     /**
      * 响应自定义对象消息
+     *
      * @param map 集合
      * @return ResponseMsg
      */
@@ -125,7 +135,8 @@ public class ResponseMsg extends HashMap<String, Object> {
 
     /**
      * 自定义响应消息
-     * @param code 状态码
+     *
+     * @param code    状态码
      * @param message 消息内容
      * @return ResponseMsg
      */
@@ -143,10 +154,33 @@ public class ResponseMsg extends HashMap<String, Object> {
      * @return ResponseMsg
      */
     public static ResponseMsg buildResponse(Integer code, Object message, Object data) {
-        ResponseMsg responseMsg = new ResponseMsg();
-        responseMsg.put("code", code);
-        responseMsg.put("msg", message);
+        ResponseMsg responseMsg = buildResponse(code, message);
+        responseMsg.put("data", data);
+        return responseMsg;
+    }
+
+    /**
+     * 构建返回对象,此为一般返回正常结果集, 一般为REST FUL API所用
+     *
+     * @param data 内容
+     * @return ResponseMsg
+     */
+    public static ResponseMsg buildResponse(Integer code, Object message, Object params, Object data) {
+        ResponseMsg responseMsg = buildResponse(code, message);
+        responseMsg.put("params", params);
         responseMsg.put("data", data);
         return responseMsg;
     }
+
+    /**
+     * 构建返回对象,此为一般返回正常结果集, 一般为REST FUL API所用
+     *
+     * @param data 内容
+     * @return ResponseMsg
+     */
+    public static ResponseMsg buildResponse(Integer code, Object message, Object params, Object data, Object details) {
+        ResponseMsg responseMsg = buildResponse(code, message, params, data);
+        responseMsg.put("details", details);
+        return responseMsg;
+    }
 }

+ 2 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/SilosStart.java

@@ -1,5 +1,6 @@
 package top.imwork.window.silos;
 
+import org.mybatis.spring.annotation.MapperScan;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
 import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
@@ -14,6 +15,7 @@ import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
  * History<历史描述>:
  * Since<版本号>: 1.0.0
  */
+@MapperScan(basePackages = "top.imwork.*.*.dao")
 @EnableDiscoveryClient
 @SpringBootApplication
 public class SilosStart {

+ 28 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/controller/cms/books/BookCategoryController.java

@@ -0,0 +1,28 @@
+package top.imwork.window.silos.controller.cms.books;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * Copyright (C), 2015-2025
+ * FileName: BookCategoryController
+ * Author<作者姓名>:   stars
+ * CreateTime<创建时间>:   2025/11/1 20:05
+ * UpdateTime<修改时间>:   2025/11/1 20:05
+ * Description〈功能简述〉: 图书分类控制器
+ * History<历史描述>:
+ * Since<版本号>: 1.0.0
+ */
+@RequestMapping("/cms/books/category")
+@Controller
+public class BookCategoryController {
+    @GetMapping("/list.html")
+    public String list() {
+        return "/cms/books/category/list";
+    }
+    @GetMapping("/edit.html")
+    public String edit() {
+        return "/cms/books/category/edit";
+    }
+}

+ 79 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/controller/cms/books/CategoriesServiceController.java

@@ -0,0 +1,79 @@
+package top.imwork.window.silos.controller.cms.books;
+
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.web.bind.annotation.*;
+
+import top.imwork.commons.core.base.BaseController;
+import top.imwork.commons.core.pojo.DeleteParams;
+import top.imwork.commons.core.pojo.ResponseMsg;
+import top.imwork.silos.convert.CategoriesConvert;
+import top.imwork.window.silos.pojo.bo.CategoriesBO;
+import top.imwork.window.silos.pojo.bo.CategoriesResultBO;
+import top.imwork.window.silos.pojo.po.CategoriesListParamVO;
+import top.imwork.window.silos.pojo.po.CategoriesParamVO;
+import top.imwork.window.silos.service.ICategoriesService;
+
+/**
+ * 图书分类
+ *
+ * @author jiangxiaowei
+ * email: e-jiangxiaowei@outlook.com
+ * date: 2025-11-01 17:13:36
+ */
+@RestController
+@RequestMapping("/cms/books/categories")
+public class CategoriesServiceController extends BaseController{
+
+    @Resource
+    public ICategoriesService categoriesService;
+
+    /**
+     * 根据id查询数据
+     * @param id long类型的id
+     * @return 返回查询结果
+     */
+    @GetMapping("/info/{id}")
+    public ResponseMsg info(@PathVariable("id") Long id){
+        return ResponseMsg.buildResponse(categoriesService.info(id));
+    }
+
+    /**
+     * 新增/修改info
+     * @param categoriesParamVO 实体信息
+     * @return responseMsg 操作结果
+     */
+    @PostMapping("/save")
+    public ResponseMsg save(@RequestBody @Valid CategoriesParamVO categoriesParamVO){
+        CategoriesBO categoriesBO = categoriesService.save(CategoriesConvert.categoriesParamVoToDto(categoriesParamVO));
+        return ResponseMsg.buildResponse(CategoriesConvert.categoriesBoToVo(categoriesBO));
+    }
+
+    /**
+     * 根据id删除图书分类
+     * @param id id
+     * @return true/false 成功/失败
+     */
+    @DeleteMapping("/delete/{id}")
+    public ResponseMsg delete(@PathVariable("id") Long id){
+        return categoriesService.delete(id)? ResponseMsg.ok() : ResponseMsg.fail();
+    }
+
+    /**
+     * 批量逻辑删除信息
+     *
+     * @param dto 删除条件
+     * @return true/false 是否删除成功
+     */
+    @DeleteMapping("/deleteByIds")
+    public ResponseMsg deleteByIds(@RequestBody DeleteParams dto){
+        String[] idArr = dto.getIds().split(",");
+        return categoriesService.deleteByIds(idArr)? ResponseMsg.ok() : ResponseMsg.fail();
+    }
+
+    @PostMapping("/queryPage")
+    public ResponseMsg queryPage(@RequestBody @Valid CategoriesListParamVO categoriesListParamVO) {
+        CategoriesResultBO categoriesResultBO = categoriesService.queryPage(CategoriesConvert.categoriesListParamVoToDTO(categoriesListParamVO));
+        return ResponseMsg.buildResponse(CategoriesConvert.categoriesResultBoToVo(categoriesResultBO));
+    }
+}

+ 213 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/convert/CategoriesConvert.java

@@ -0,0 +1,213 @@
+package top.imwork.silos.convert;
+
+import org.springframework.util.ObjectUtils;
+import top.imwork.window.silos.entity.Categories;
+import top.imwork.window.silos.pojo.bo.CategoriesBO;
+import top.imwork.window.silos.pojo.bo.CategoriesResultBO;
+import top.imwork.window.silos.pojo.dto.CategoriesDTO;
+import top.imwork.window.silos.pojo.dto.CategoriesListDTO;
+import top.imwork.window.silos.pojo.po.CategoriesListParamVO;
+import top.imwork.window.silos.pojo.po.CategoriesParamVO;
+import top.imwork.window.silos.pojo.vo.CategoriesResultVO;
+import top.imwork.window.silos.pojo.vo.CategoriesVO;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * 图书分类
+ * 实体转换
+ *
+ * @author jiangxiaowei
+ * email: e-jiangxiaowei@outlook.com
+ * date: 2025-11-01 17:13:36
+ */
+public class CategoriesConvert {
+    private CategoriesConvert() {}
+
+    public static Categories categoriesDtoToDo(CategoriesDTO categoriesDTO) {
+        if (categoriesDTO == null) {
+            return null;
+        }
+        Categories categories = new Categories();
+        categories.setId(categoriesDTO.getId());
+        categories.setCategoryCode(categoriesDTO.getCategoryCode());
+        categories.setCategoryName(categoriesDTO.getCategoryName());
+        categories.setEnglishName(categoriesDTO.getEnglishName());
+        categories.setCategoryColor(categoriesDTO.getCategoryColor());
+        categories.setCategoryIcon(categoriesDTO.getCategoryIcon());
+        categories.setParentId(categoriesDTO.getParentId());
+        categories.setLevel(categoriesDTO.getLevel());
+        categories.setPath(categoriesDTO.getPath());
+        categories.setSortOrder(categoriesDTO.getSortOrder());
+        categories.setDescription(categoriesDTO.getDescription());
+        categories.setKeywords(categoriesDTO.getKeywords());
+        categories.setCategoryStatus(categoriesDTO.getCategoryStatus());
+        categories.setIsVisible(categoriesDTO.getIsVisible());
+        categories.setDelFlag(categoriesDTO.getDelFlag());
+        categories.setCreator(categoriesDTO.getCreator());
+        categories.setCreateTime(categoriesDTO.getCreateTime());
+        categories.setModifier(categoriesDTO.getModifier());
+        categories.setUpdateTime(categoriesDTO.getUpdateTime());
+        categories.setRemark(categoriesDTO.getRemark());
+        return categories;
+    }
+
+    public static CategoriesBO categoriesDoToBo(Categories categories) {
+        if (categories == null) {
+            return null;
+        }
+        CategoriesBO categoriesBO = new CategoriesBO();
+        categoriesBO.setId(categories.getId());
+        categoriesBO.setCategoryCode(categories.getCategoryCode());
+        categoriesBO.setCategoryName(categories.getCategoryName());
+        categoriesBO.setEnglishName(categories.getEnglishName());
+        categoriesBO.setCategoryColor(categories.getCategoryColor());
+        categoriesBO.setCategoryIcon(categories.getCategoryIcon());
+        categoriesBO.setParentId(categories.getParentId());
+        categoriesBO.setLevel(categories.getLevel());
+        categoriesBO.setPath(categories.getPath());
+        categoriesBO.setSortOrder(categories.getSortOrder());
+        categoriesBO.setDescription(categories.getDescription());
+        categoriesBO.setKeywords(categories.getKeywords());
+        categoriesBO.setCategoryStatus(categories.getCategoryStatus());
+        categoriesBO.setIsVisible(categories.getIsVisible());
+        categoriesBO.setDelFlag(categories.getDelFlag());
+        categoriesBO.setCreator(categories.getCreator());
+        categoriesBO.setCreateTime(categories.getCreateTime());
+        categoriesBO.setModifier(categories.getModifier());
+        categoriesBO.setUpdateTime(categories.getUpdateTime());
+        categoriesBO.setRemark(categories.getRemark());
+        return categoriesBO;
+    }
+
+    public static CategoriesDTO categoriesParamVoToDto(CategoriesParamVO categoriesParamVO) {
+        if (categoriesParamVO == null) {
+            return null;
+        }
+        CategoriesDTO categoriesDTO = new CategoriesDTO();
+        categoriesDTO.setId(categoriesParamVO.getId());
+        categoriesDTO.setCategoryCode(categoriesParamVO.getCategoryCode());
+        categoriesDTO.setCategoryName(categoriesParamVO.getCategoryName());
+        categoriesDTO.setEnglishName(categoriesParamVO.getEnglishName());
+        categoriesDTO.setCategoryColor(categoriesParamVO.getCategoryColor());
+        categoriesDTO.setCategoryIcon(categoriesParamVO.getCategoryIcon());
+        categoriesDTO.setParentId(categoriesParamVO.getParentId());
+        categoriesDTO.setLevel(categoriesParamVO.getLevel());
+        categoriesDTO.setPath(categoriesParamVO.getPath());
+        categoriesDTO.setSortOrder(categoriesParamVO.getSortOrder());
+        categoriesDTO.setDescription(categoriesParamVO.getDescription());
+        categoriesDTO.setKeywords(categoriesParamVO.getKeywords());
+        categoriesDTO.setCategoryStatus(categoriesParamVO.getCategoryStatus());
+        categoriesDTO.setIsVisible(categoriesParamVO.getIsVisible());
+        categoriesDTO.setDelFlag(categoriesParamVO.getDelFlag());
+        categoriesDTO.setCreator(categoriesParamVO.getCreator());
+        categoriesDTO.setCreateTime(categoriesParamVO.getCreateTime());
+        categoriesDTO.setModifier(categoriesParamVO.getModifier());
+        categoriesDTO.setUpdateTime(categoriesParamVO.getUpdateTime());
+        categoriesDTO.setRemark(categoriesParamVO.getRemark());
+        return categoriesDTO;
+    }
+
+    public static List<CategoriesBO> categoriesListToCategoriesBOList(List<Categories> records) {
+         if (ObjectUtils.isEmpty(records)) {
+             return new ArrayList<>();
+         }
+         List<CategoriesBO> categoriesBOList = new ArrayList<>();
+         for (Categories categories : records) {
+             categoriesBOList.add(categoriesDoToBo(categories));
+         }
+         return categoriesBOList;
+    }
+
+    public static CategoriesVO categoriesBoToVo(CategoriesBO categoriesBO) {
+        if (categoriesBO == null) {
+            return null;
+        }
+        CategoriesVO categoriesVO = new CategoriesVO();
+        categoriesVO.setId(categoriesBO.getId());
+        categoriesVO.setCategoryCode(categoriesBO.getCategoryCode());
+        categoriesVO.setCategoryName(categoriesBO.getCategoryName());
+        categoriesVO.setEnglishName(categoriesBO.getEnglishName());
+        categoriesVO.setCategoryColor(categoriesBO.getCategoryColor());
+        categoriesVO.setCategoryIcon(categoriesBO.getCategoryIcon());
+        categoriesVO.setParentId(categoriesBO.getParentId());
+        categoriesVO.setLevel(categoriesBO.getLevel());
+        categoriesVO.setPath(categoriesBO.getPath());
+        categoriesVO.setSortOrder(categoriesBO.getSortOrder());
+        categoriesVO.setDescription(categoriesBO.getDescription());
+        categoriesVO.setKeywords(categoriesBO.getKeywords());
+        categoriesVO.setCategoryStatus(categoriesBO.getCategoryStatus());
+        categoriesVO.setIsVisible(categoriesBO.getIsVisible());
+        categoriesVO.setDelFlag(categoriesBO.getDelFlag());
+        categoriesVO.setCreator(categoriesBO.getCreator());
+        categoriesVO.setCreateTime(categoriesBO.getCreateTime());
+        categoriesVO.setModifier(categoriesBO.getModifier());
+        categoriesVO.setUpdateTime(categoriesBO.getUpdateTime());
+        categoriesVO.setRemark(categoriesBO.getRemark());
+        return categoriesVO;
+    }
+
+    public static CategoriesListDTO categoriesListParamVoToDTO(CategoriesListParamVO categoriesListParamVO) {
+        if (categoriesListParamVO == null) {
+            return new CategoriesListDTO();
+        }
+        CategoriesListDTO categoriesListDTO = new CategoriesListDTO();
+        categoriesListDTO.setCategoriesName(categoriesListParamVO.getCategoriesName());
+        categoriesListDTO.setPageNo(categoriesListParamVO.getPageNo());
+        categoriesListDTO.setPageRows(categoriesListParamVO.getPageRows());
+        categoriesListDTO.setDelFlag(categoriesListParamVO.getDelFlag());
+        categoriesListDTO.setCreator(categoriesListParamVO.getCreator());
+        categoriesListDTO.setCreateBeginTime(categoriesListParamVO.getCreateBeginTime());
+        categoriesListDTO.setCreateEndTime(categoriesListParamVO.getCreateEndTime());
+        categoriesListDTO.setModifier(categoriesListParamVO.getModifier());
+        categoriesListDTO.setUpdateBeginTime(categoriesListParamVO.getUpdateBeginTime());
+        categoriesListDTO.setUpdateEndTime(categoriesListParamVO.getUpdateEndTime());
+        categoriesListDTO.setRemark(categoriesListParamVO.getRemark());
+        return categoriesListDTO;
+    }
+        
+    public static CategoriesListParamVO categoriesListParamDtoToVo(CategoriesListDTO categoriesListDTO) {
+        if (categoriesListDTO == null) {
+            return new CategoriesListParamVO();
+        }
+        CategoriesListParamVO categoriesListParamVO = new CategoriesListParamVO();
+        categoriesListParamVO.setCategoriesName(categoriesListDTO.getCategoriesName());
+        categoriesListParamVO.setPageNo(categoriesListDTO.getPageNo());
+        categoriesListParamVO.setPageRows(categoriesListDTO.getPageRows());
+        categoriesListParamVO.setDelFlag(categoriesListDTO.getDelFlag());
+        categoriesListParamVO.setCreator(categoriesListDTO.getCreator());
+        categoriesListParamVO.setCreateBeginTime(categoriesListDTO.getCreateBeginTime());
+        categoriesListParamVO.setCreateEndTime(categoriesListDTO.getCreateEndTime());
+        categoriesListParamVO.setModifier(categoriesListDTO.getModifier());
+        categoriesListParamVO.setUpdateBeginTime(categoriesListDTO.getUpdateBeginTime());
+        categoriesListParamVO.setUpdateEndTime(categoriesListDTO.getUpdateEndTime());
+        categoriesListParamVO.setRemark(categoriesListDTO.getRemark());
+        return categoriesListParamVO;
+    }
+
+    private static List<CategoriesVO> categoriesBoListToCategoriesVoList(List<CategoriesBO> dataList) {
+        if (ObjectUtils.isEmpty(dataList)) {
+            return new ArrayList<>();
+        }
+        List<CategoriesVO> categoriesVOList = new ArrayList<>();
+        for (CategoriesBO categoriesBO : dataList) {
+             categoriesVOList.add(categoriesBoToVo(categoriesBO));
+        }
+        return categoriesVOList;
+    }
+
+    public static CategoriesResultVO categoriesResultBoToVo(CategoriesResultBO categoriesResultBO) {
+        if (categoriesResultBO == null) {
+            return new CategoriesResultVO();
+        }
+        CategoriesResultVO categoriesResultVO = new CategoriesResultVO();
+        categoriesResultVO.setPageNo(categoriesResultBO.getPageNo());
+        categoriesResultVO.setPageRows(categoriesResultBO.getPageRows());
+        categoriesResultVO.setPageCount(categoriesResultBO.getPageCount());
+        categoriesResultVO.setTotalRows(categoriesResultBO.getTotalRows());
+        categoriesResultVO.setDataList(categoriesBoListToCategoriesVoList(categoriesResultBO.getDataList()));
+        categoriesResultVO.setParams(categoriesListParamDtoToVo(categoriesResultBO.getParams()));
+        return categoriesResultVO;
+    }
+}

+ 14 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/dao/CategoriesDao.java

@@ -0,0 +1,14 @@
+package top.imwork.window.silos.dao;
+
+import top.imwork.commons.dao.base.BaseDao;
+import top.imwork.window.silos.entity.Categories;
+
+/**
+ * 图书分类
+ *
+ * @author jiangxiaowei
+ * email: e-jiangxiaowei@outlook.com
+ * date: 2025-11-01 17:13:36
+ */
+public interface CategoriesDao extends BaseDao<Categories> {
+}

+ 300 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/entity/Categories.java

@@ -0,0 +1,300 @@
+package top.imwork.window.silos.entity;
+
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+import java.util.Objects;
+
+/**
+ * 图书分类
+ *
+ * @author jiangxiaowei
+ * email: e-jiangxiaowei@outlook.com
+ * date: 2025-11-01 17:13:36
+ */
+@TableName("book_categories")
+public class Categories implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+    /**
+     * 
+     */
+    @TableId
+    private Long id;
+    /**
+     * 分类代码
+     */
+    private String categoryCode;
+    /**
+     * 分类名称
+     */
+    private String categoryName;
+    /**
+     * 英文名称
+     */
+    private String englishName;
+    /**
+     * 分类颜色
+     */
+    private Long categoryColor;
+    /**
+     * 分类图标
+     */
+    private String categoryIcon;
+    /**
+     * 父级分类ID
+     */
+    private Long parentId;
+    /**
+     * 分类层级
+     */
+    private Integer level;
+    /**
+     * 分类路径
+     */
+    private String path;
+    /**
+     * 排序序号
+     */
+    private Long sortOrder;
+    /**
+     * 分类描述
+     */
+    private String description;
+    /**
+     * 关键词
+     */
+    private String keywords;
+    /**
+     * 分类状态0-活跃1归档
+     */
+    private String categoryStatus;
+    /**
+     * 是否可见:Y=是,N=否
+     */
+    private String isVisible;
+    /**
+     * 是否删除默认N.未删除,Y已删除
+     */
+    private String delFlag;
+    /**
+     * 创建人
+     */
+    private String creator;
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+    /**
+     * 修改人
+     */
+    private String modifier;
+    /**
+     * 修改时间
+     */
+    private Date updateTime;
+    /**
+     * 备注
+     */
+    private String remark;
+
+    @Override
+    public String toString() {
+        return "Categories{" +
+                "id=" + id +
+                ", categoryCode='" + categoryCode + '\'' +
+                ", categoryName='" + categoryName + '\'' +
+                ", englishName='" + englishName + '\'' +
+                ", categoryColor=" + categoryColor +
+                ", categoryIcon='" + categoryIcon + '\'' +
+                ", parentId=" + parentId +
+                ", level=" + level +
+                ", path='" + path + '\'' +
+                ", sortOrder=" + sortOrder +
+                ", description='" + description + '\'' +
+                ", keywords='" + keywords + '\'' +
+                ", categoryStatus='" + categoryStatus + '\'' +
+                ", isVisible='" + isVisible + '\'' +
+                ", delFlag='" + delFlag + '\'' +
+                ", creator='" + creator + '\'' +
+                ", createTime=" + createTime +
+                ", modifier='" + modifier + '\'' +
+                ", updateTime=" + updateTime +
+                ", remark='" + remark + '\'' +
+                '}';
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (!(o instanceof Categories that)) return false;
+        return Objects.equals(id, that.id) && Objects.equals(categoryCode, that.categoryCode) && Objects.equals(categoryName, that.categoryName) && Objects.equals(englishName, that.englishName) && Objects.equals(categoryColor, that.categoryColor) && Objects.equals(categoryIcon, that.categoryIcon) && Objects.equals(parentId, that.parentId) && Objects.equals(level, that.level) && Objects.equals(path, that.path) && Objects.equals(sortOrder, that.sortOrder) && Objects.equals(description, that.description) && Objects.equals(keywords, that.keywords) && Objects.equals(categoryStatus, that.categoryStatus) && Objects.equals(isVisible, that.isVisible) && Objects.equals(delFlag, that.delFlag) && Objects.equals(creator, that.creator) && Objects.equals(createTime, that.createTime) && Objects.equals(modifier, that.modifier) && Objects.equals(updateTime, that.updateTime) && Objects.equals(remark, that.remark);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(id, categoryCode, categoryName, englishName, categoryColor, categoryIcon, parentId, level, path, sortOrder, description, keywords, categoryStatus, isVisible, delFlag, creator, createTime, modifier, updateTime, remark);
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getCategoryCode() {
+        return categoryCode;
+    }
+
+    public void setCategoryCode(String categoryCode) {
+        this.categoryCode = categoryCode;
+    }
+
+    public String getCategoryName() {
+        return categoryName;
+    }
+
+    public void setCategoryName(String categoryName) {
+        this.categoryName = categoryName;
+    }
+
+    public String getEnglishName() {
+        return englishName;
+    }
+
+    public void setEnglishName(String englishName) {
+        this.englishName = englishName;
+    }
+
+    public Long getCategoryColor() {
+        return categoryColor;
+    }
+
+    public void setCategoryColor(Long categoryColor) {
+        this.categoryColor = categoryColor;
+    }
+
+    public String getCategoryIcon() {
+        return categoryIcon;
+    }
+
+    public void setCategoryIcon(String categoryIcon) {
+        this.categoryIcon = categoryIcon;
+    }
+
+    public Long getParentId() {
+        return parentId;
+    }
+
+    public void setParentId(Long parentId) {
+        this.parentId = parentId;
+    }
+
+    public Integer getLevel() {
+        return level;
+    }
+
+    public void setLevel(Integer level) {
+        this.level = level;
+    }
+
+    public String getPath() {
+        return path;
+    }
+
+    public void setPath(String path) {
+        this.path = path;
+    }
+
+    public Long getSortOrder() {
+        return sortOrder;
+    }
+
+    public void setSortOrder(Long sortOrder) {
+        this.sortOrder = sortOrder;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getKeywords() {
+        return keywords;
+    }
+
+    public void setKeywords(String keywords) {
+        this.keywords = keywords;
+    }
+
+    public String getCategoryStatus() {
+        return categoryStatus;
+    }
+
+    public void setCategoryStatus(String categoryStatus) {
+        this.categoryStatus = categoryStatus;
+    }
+
+    public String getIsVisible() {
+        return isVisible;
+    }
+
+    public void setIsVisible(String isVisible) {
+        this.isVisible = isVisible;
+    }
+
+    public String getDelFlag() {
+        return delFlag;
+    }
+
+    public void setDelFlag(String delFlag) {
+        this.delFlag = delFlag;
+    }
+
+    public String getCreator() {
+        return creator;
+    }
+
+    public void setCreator(String creator) {
+        this.creator = creator;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public String getModifier() {
+        return modifier;
+    }
+
+    public void setModifier(String modifier) {
+        this.modifier = modifier;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getRemark() {
+        return remark;
+    }
+
+    public void setRemark(String remark) {
+        this.remark = remark;
+    }
+}

+ 100 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/pojo/bo/CategoriesBO.java

@@ -0,0 +1,100 @@
+package top.imwork.window.silos.pojo.bo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 图书分类
+ *
+ * @author jiangxiaowei
+ * email: e-jiangxiaowei@outlook.com
+ * date: 2025-11-01 17:13:36
+ */
+@Data
+public class CategoriesBO implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+    /**
+     * 
+     */
+    private Long id;
+    /**
+     * 分类代码
+     */
+    private String categoryCode;
+    /**
+     * 分类名称
+     */
+    private String categoryName;
+    /**
+     * 英文名称
+     */
+    private String englishName;
+    /**
+     * 分类颜色
+     */
+    private Long categoryColor;
+    /**
+     * 分类图标
+     */
+    private String categoryIcon;
+    /**
+     * 父级分类ID
+     */
+    private Long parentId;
+    /**
+     * 分类层级
+     */
+    private Integer level;
+    /**
+     * 分类路径
+     */
+    private String path;
+    /**
+     * 排序序号
+     */
+    private Long sortOrder;
+    /**
+     * 分类描述
+     */
+    private String description;
+    /**
+     * 关键词
+     */
+    private String keywords;
+    /**
+     * 分类状态0-活跃1归档
+     */
+    private String categoryStatus;
+    /**
+     * 是否可见:Y=是,N=否
+     */
+    private String isVisible;
+    /**
+     * 是否删除默认N.未删除,Y已删除
+     */
+    private String delFlag;
+    /**
+     * 创建人
+     */
+    private String creator;
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+    /**
+     * 修改人
+     */
+    private String modifier;
+    /**
+     * 修改时间
+     */
+    private Date updateTime;
+    /**
+     * 备注
+     */
+    private String remark;
+}

+ 19 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/pojo/bo/CategoriesResultBO.java

@@ -0,0 +1,19 @@
+package top.imwork.window.silos.pojo.bo;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import top.imwork.commons.core.pojo.BaseResult;
+import top.imwork.window.silos.pojo.dto.CategoriesListDTO;
+
+/**
+ * 图书分类
+ *
+ * @author jiangxiaowei
+ * email: e-jiangxiaowei@outlook.com
+ * date: 2025-11-01 17:13:36
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CategoriesResultBO extends BaseResult<CategoriesBO, CategoriesListDTO> {
+
+}

+ 100 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/pojo/dto/CategoriesDTO.java

@@ -0,0 +1,100 @@
+package top.imwork.window.silos.pojo.dto;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 图书分类
+ *
+ * @author jiangxiaowei
+ * email: e-jiangxiaowei@outlook.com
+ * date: 2025-11-01 17:13:36
+ */
+@Data
+public class CategoriesDTO implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+    /**
+     * 
+     */
+    private Long id;
+    /**
+     * 分类代码
+     */
+    private String categoryCode;
+    /**
+     * 分类名称
+     */
+    private String categoryName;
+    /**
+     * 英文名称
+     */
+    private String englishName;
+    /**
+     * 分类颜色
+     */
+    private Long categoryColor;
+    /**
+     * 分类图标
+     */
+    private String categoryIcon;
+    /**
+     * 父级分类ID
+     */
+    private Long parentId;
+    /**
+     * 分类层级
+     */
+    private Integer level;
+    /**
+     * 分类路径
+     */
+    private String path;
+    /**
+     * 排序序号
+     */
+    private Long sortOrder;
+    /**
+     * 分类描述
+     */
+    private String description;
+    /**
+     * 关键词
+     */
+    private String keywords;
+    /**
+     * 分类状态0-活跃1归档
+     */
+    private String categoryStatus;
+    /**
+     * 是否可见:Y=是,N=否
+     */
+    private String isVisible;
+    /**
+     * 是否删除默认N.未删除,Y已删除
+     */
+    private String delFlag;
+    /**
+     * 创建人
+     */
+    private String creator;
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+    /**
+     * 修改人
+     */
+    private String modifier;
+    /**
+     * 修改时间
+     */
+    private Date updateTime;
+    /**
+     * 备注
+     */
+    private String remark;
+}

+ 18 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/pojo/dto/CategoriesListDTO.java

@@ -0,0 +1,18 @@
+package top.imwork.window.silos.pojo.dto;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import top.imwork.commons.core.pojo.BaseParams;
+
+/**
+ * 图书分类
+ *
+ * @author jiangxiaowei
+ * email: e-jiangxiaowei@outlook.com
+ * date: 2025-11-01 17:13:36
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CategoriesListDTO extends BaseParams {
+    private String categoriesName;
+}

+ 18 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/pojo/po/CategoriesListParamVO.java

@@ -0,0 +1,18 @@
+package top.imwork.window.silos.pojo.po;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import top.imwork.commons.core.pojo.BaseParams;
+
+/**
+ * 图书分类
+ *
+ * @author jiangxiaowei
+ * email: e-jiangxiaowei@outlook.com
+ * date: 2025-11-01 17:13:36
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CategoriesListParamVO extends BaseParams {
+    private String CategoriesName;
+}

+ 100 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/pojo/po/CategoriesParamVO.java

@@ -0,0 +1,100 @@
+package top.imwork.window.silos.pojo.po;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ * 图书分类
+ *
+ * @author jiangxiaowei
+ * email: e-jiangxiaowei@outlook.com
+ * date: 2025-11-01 17:13:36
+ */
+@Data
+public class CategoriesParamVO implements Serializable {
+    @Serial
+    private static final long serialVersionUID = 1L;
+    /**
+     * 
+     */
+    private Long id;
+    /**
+     * 分类代码
+     */
+    private String categoryCode;
+    /**
+     * 分类名称
+     */
+    private String categoryName;
+    /**
+     * 英文名称
+     */
+    private String englishName;
+    /**
+     * 分类颜色
+     */
+    private Long categoryColor;
+    /**
+     * 分类图标
+     */
+    private String categoryIcon;
+    /**
+     * 父级分类ID
+     */
+    private Long parentId;
+    /**
+     * 分类层级
+     */
+    private Integer level;
+    /**
+     * 分类路径
+     */
+    private String path;
+    /**
+     * 排序序号
+     */
+    private Long sortOrder;
+    /**
+     * 分类描述
+     */
+    private String description;
+    /**
+     * 关键词
+     */
+    private String keywords;
+    /**
+     * 分类状态0-活跃1归档
+     */
+    private String categoryStatus;
+    /**
+     * 是否可见:Y=是,N=否
+     */
+    private String isVisible;
+    /**
+     * 是否删除默认N.未删除,Y已删除
+     */
+    private String delFlag;
+    /**
+     * 创建人
+     */
+    private String creator;
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+    /**
+     * 修改人
+     */
+    private String modifier;
+    /**
+     * 修改时间
+     */
+    private Date updateTime;
+    /**
+     * 备注
+     */
+    private String remark;
+}

+ 19 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/pojo/vo/CategoriesResultVO.java

@@ -0,0 +1,19 @@
+package top.imwork.window.silos.pojo.vo;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import top.imwork.commons.core.pojo.BaseResult;
+import top.imwork.window.silos.pojo.po.CategoriesListParamVO;
+
+/**
+ * 图书分类
+ *
+ * @author jiangxiaowei
+ * email: e-jiangxiaowei@outlook.com
+ * date: 2025-11-01 17:13:36
+ */
+@EqualsAndHashCode(callSuper = true)
+@Data
+public class CategoriesResultVO extends BaseResult<CategoriesVO, CategoriesListParamVO> {
+
+}

+ 101 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/pojo/vo/CategoriesVO.java

@@ -0,0 +1,101 @@
+package top.imwork.window.silos.pojo.vo;
+
+import lombok.Data;
+
+import java.io.Serial;
+import java.io.Serializable;
+import java.util.Date;
+
+/**
+ *〈功能简述〉
+ * 图书分类响应消息体
+ *
+ * @author jiangxiaowei
+ * email: e-jiangxiaowei@outlook.com
+ * date: 2025-11-01 17:13:36
+ */
+@Data
+public class CategoriesVO implements Serializable{
+    @Serial
+    private static final long serialVersionUID = 1L;
+    /**
+     * 
+     */
+    private Long id;
+    /**
+     * 分类代码
+     */
+    private String categoryCode;
+    /**
+     * 分类名称
+     */
+    private String categoryName;
+    /**
+     * 英文名称
+     */
+    private String englishName;
+    /**
+     * 分类颜色
+     */
+    private Long categoryColor;
+    /**
+     * 分类图标
+     */
+    private String categoryIcon;
+    /**
+     * 父级分类ID
+     */
+    private Long parentId;
+    /**
+     * 分类层级
+     */
+    private Integer level;
+    /**
+     * 分类路径
+     */
+    private String path;
+    /**
+     * 排序序号
+     */
+    private Long sortOrder;
+    /**
+     * 分类描述
+     */
+    private String description;
+    /**
+     * 关键词
+     */
+    private String keywords;
+    /**
+     * 分类状态0-活跃1归档
+     */
+    private String categoryStatus;
+    /**
+     * 是否可见:Y=是,N=否
+     */
+    private String isVisible;
+    /**
+     * 是否删除默认N.未删除,Y已删除
+     */
+    private String delFlag;
+    /**
+     * 创建人
+     */
+    private String creator;
+    /**
+     * 创建时间
+     */
+    private Date createTime;
+    /**
+     * 修改人
+     */
+    private String modifier;
+    /**
+     * 修改时间
+     */
+    private Date updateTime;
+    /**
+     * 备注
+     */
+    private String remark;
+}

+ 52 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/service/ICategoriesService.java

@@ -0,0 +1,52 @@
+package top.imwork.window.silos.service;
+
+import top.imwork.window.silos.pojo.bo.CategoriesBO;
+import top.imwork.window.silos.pojo.bo.CategoriesResultBO;
+import top.imwork.window.silos.pojo.dto.CategoriesDTO;
+import top.imwork.window.silos.pojo.dto.CategoriesListDTO;
+
+/**
+ * 图书分类
+ *
+ * @author jiangxiaowei
+ * email: e-jiangxiaowei@outlook.com
+ * date: 2025-11-01 17:13:36
+ */
+public interface ICategoriesService{
+
+    /**
+     * 根据图书分类id获取图书分类详情
+     * @param id 图书分类id
+     * @return CategoriesBO 图书分类详情
+     */
+    CategoriesBO info(Long id);
+
+    /**
+     * 新增/修改 信息
+     * @param categoriesDTO 要保存的信息
+     * @return CategoriesBO 保存后的信息
+     */
+    CategoriesBO save(CategoriesDTO categoriesDTO);
+
+    /**
+     * 根据id删除信息
+     * @param id id
+     * @return true/false 是否删除成功
+     */
+    Boolean delete(Long id);
+
+    /**
+     * 根据ids删除信息
+     * @param ids ids
+     * @return true/false 是否删除成功
+     */
+    Boolean deleteByIds(String[] ids);
+
+    /**
+     * 分页查询信息
+     * @param categoriesListDTO 分页信息
+     * @return CategoriesResultBO 查询结果
+     */
+    CategoriesResultBO queryPage(CategoriesListDTO categoriesListDTO);
+}
+

+ 112 - 0
imwork-windows/imwork-silos/src/main/java/top/imwork/window/silos/service/impl/CategoriesServiceImpl.java

@@ -0,0 +1,112 @@
+package top.imwork.window.silos.service.impl;
+
+import org.springframework.stereotype.Service;
+import org.springframework.util.ObjectUtils;
+import jakarta.annotation.Resource;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+
+import top.imwork.commons.core.utils.StringUtils;
+import top.imwork.silos.convert.CategoriesConvert;
+import top.imwork.window.silos.dao.CategoriesDao;
+import top.imwork.window.silos.entity.Categories;
+import top.imwork.window.silos.pojo.bo.CategoriesBO;
+import top.imwork.window.silos.pojo.bo.CategoriesResultBO;
+import top.imwork.window.silos.pojo.dto.CategoriesDTO;
+import top.imwork.window.silos.pojo.dto.CategoriesListDTO;
+import top.imwork.window.silos.service.ICategoriesService;
+
+import java.util.Date;
+
+@Service("categoriesService")
+public class CategoriesServiceImpl extends ServiceImpl<CategoriesDao, Categories> implements ICategoriesService {
+    @Resource
+    private CategoriesDao categoriesDao;
+
+    /**
+     * 根据id获取信息
+     * @param id 用户id
+     * @return CategoriesBO 响应信息
+     */
+    @Override
+    public CategoriesBO info(Long id) {
+        Categories categories = categoriesDao.info(id);
+        return CategoriesConvert.categoriesDoToBo(categories);
+    }
+
+    /**
+     * 新增/更新信息
+     * @param categoriesDTO 信息
+     * @return categoriesBO 更新后信息
+     */
+    @Override
+    public CategoriesBO save(CategoriesDTO categoriesDTO) {
+        Categories categories = CategoriesConvert.categoriesDtoToDo(categoriesDTO);
+        if (ObjectUtils.isEmpty(categories.getId())) {
+            categories.setCategoryStatus("0");
+            categories.setIsVisible("Y");
+            categories.setDelFlag("N");
+            categories.setCreateTime(new Date());
+            categoriesDao.insert(categories);
+        } else {
+            categoriesDao.updateById(categories);
+        }
+        return CategoriesConvert.categoriesDoToBo(categories);
+    }
+
+    /**
+     * 根据id删除信息
+     * @param id id
+     * @return true/false 是否删除成功
+     */
+    @Override
+    public Boolean delete(Long id) {
+        return categoriesDao.deleteById(id) == 1 ? Boolean.TRUE : Boolean.FALSE;
+    }
+
+    @Override
+    public Boolean deleteByIds(String[] ids) {
+        return categoriesDao.deleteByIds(ids) > 0 ? Boolean.TRUE : Boolean.FALSE;
+    }
+
+    @Override
+    public CategoriesResultBO queryPage(CategoriesListDTO categoriesListDTO) {
+        QueryWrapper<Categories> queryWrapper = new QueryWrapper<>();
+
+        if (!StringUtils.isEmpty(categoriesListDTO.getCategoriesName())) {
+            queryWrapper.like("categories_name", categoriesListDTO.getCategoriesName());
+        }
+
+        if (!StringUtils.isEmpty(categoriesListDTO.getCreateBeginTime())) {
+            queryWrapper.apply("create_time >= '" + categoriesListDTO.getCreateBeginTime() + "'");
+        }
+
+        if (!StringUtils.isEmpty(categoriesListDTO.getCreateEndTime())) {
+            queryWrapper.apply("create_time <= '" + categoriesListDTO.getCreateEndTime() + "'");
+        }
+
+        if (!StringUtils.isEmpty(categoriesListDTO.getUpdateBeginTime())) {
+            queryWrapper.apply("update_time >= '" + categoriesListDTO.getUpdateBeginTime() + "'");
+        }
+
+        if (!StringUtils.isEmpty(categoriesListDTO.getUpdateEndTime())) {
+            queryWrapper.apply("update_time <= '" + categoriesListDTO.getUpdateEndTime() + "'");
+        }
+
+        Page<Categories> page = new Page<>(categoriesListDTO.getPageNo(), categoriesListDTO.getPageRows());
+        IPage<Categories> iPage = categoriesDao.queryPage(page, queryWrapper);
+
+        CategoriesResultBO resultBO = new CategoriesResultBO();
+        resultBO.setPageNo(categoriesListDTO.getPageNo());
+        resultBO.setPageRows(categoriesListDTO.getPageRows());
+        resultBO.setPageCount((int) iPage.getPages());
+        resultBO.setTotalRows((int) iPage.getTotal());
+        resultBO.setDataList(CategoriesConvert.categoriesListToCategoriesBOList(iPage.getRecords()));
+        resultBO.setParams(categoriesListDTO);
+
+        return resultBO;
+    }
+}

+ 1 - 1
imwork-windows/imwork-silos/src/main/resources/application.yml

@@ -38,7 +38,7 @@ spring:
     password: zh.3417.JXW
     #driver-class-name: org.postgresql.Driver
     driver-class-name: com.mysql.cj.jdbc.Driver
-    url: jdbc:mysql://mysql.imwork.top:3306/imwork_silos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
+    url: jdbc:mysql://mysql.imwork.top:63306/imwork_silos?characterEncoding=utf8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true&useUnicode=true&useSSL=false&serverTimezone=UTC
     #Hikari 连接池配置
     type: com.zaxxer.hikari.HikariDataSource
     hikari:

+ 74 - 0
imwork-windows/imwork-silos/src/main/resources/mapper/cms/books/CategoriesDao.xml

@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+
+<mapper namespace="top.imwork.window.silos.dao.CategoriesDao">
+    <resultMap type="top.imwork.window.silos.entity.Categories" id="BaseResultMap">
+            <result property="id" column="id"/>
+            <result property="categoryCode" column="category_code"/>
+            <result property="categoryName" column="category_name"/>
+            <result property="englishName" column="english_name"/>
+            <result property="categoryColor" column="category_color"/>
+            <result property="categoryIcon" column="category_icon"/>
+            <result property="parentId" column="parent_id"/>
+            <result property="level" column="level"/>
+            <result property="path" column="path"/>
+            <result property="sortOrder" column="sort_order"/>
+            <result property="description" column="description"/>
+            <result property="keywords" column="keywords"/>
+            <result property="categoryStatus" column="category_status"/>
+            <result property="isVisible" column="is_visible"/>
+            <result property="delFlag" column="del_flag"/>
+            <result property="creator" column="creator"/>
+            <result property="createTime" column="create_time"/>
+            <result property="modifier" column="modifier"/>
+            <result property="updateTime" column="update_time"/>
+            <result property="remark" column="remark"/>
+    </resultMap>
+
+    <sql id="Base_Column_List">
+        id,
+        category_code,
+        category_name,
+        english_name,
+        category_color,
+        category_icon,
+        parent_id,
+        level,
+        path,
+        sort_order,
+        description,
+        keywords,
+        category_status,
+        is_visible,
+        del_flag,
+        creator,
+        create_time,
+        modifier,
+        update_time,
+        remark
+    </sql>
+
+    <!--根据ids批量删除-->
+    <update id="deleteByIds" parameterType="ArrayList">
+        update book_categories
+        set del_flag = 'Y'
+        where id in
+        <foreach item="ids" collection="array" open="(" separator=","  close=")">
+            #{ids}
+        </foreach>
+    </update>
+
+    <!--根据id查询信息-->
+    <select id="info" resultMap="BaseResultMap" parameterType="long">
+        select *
+        from book_categories
+        where 1 = 1
+        and id = #{id}
+    </select>
+
+    <!--分页查询-->
+    <select id="queryPage" resultType="top.imwork.window.silos.entity.Categories">
+        select *
+        from book_categories ${ew.customSqlSegment}
+    </select>
+</mapper>

+ 717 - 0
imwork-windows/imwork-silos/src/main/resources/static/business/cms/books/category/category.css

@@ -0,0 +1,717 @@
+:root {
+    --primary-color: #4f46e5;
+    --primary-hover: #4338ca;
+    --secondary-color: #f1f5f9;
+    --secondary-hover: #e2e8f0;
+    --success-color: #10b981;
+    --danger-color: #ef4444;
+    --warning-color: #f59e0b;
+    --text-primary: #1e293b;
+    --text-secondary: #64748b;
+    --text-light: #94a3b8;
+    --bg-white: #ffffff;
+    --bg-light: #f8fafc;
+    --border-color: #e2e8f0;
+    --shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
+    --shadow-hover: 0 10px 20px rgba(0, 0, 0, 0.1);
+    --radius: 8px;
+    --radius-lg: 12px;
+}
+
+* {
+    margin: 0;
+    padding: 0;
+    box-sizing: border-box;
+    font-family: 'Segoe UI', 'Microsoft YaHei', sans-serif;
+}
+
+body {
+    background-color: var(--bg-light);
+    color: var(--text-primary);
+    line-height: 1.6;
+}
+
+.container {
+    max-width: 100%;
+    margin: 0 auto;
+    padding: 15px;
+}
+
+
+header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 30px;
+    padding: 20px;
+    background: var(--bg-white);
+    border-radius: var(--radius-lg);
+    box-shadow: var(--shadow);
+}
+
+.logo {
+    display: flex;
+    align-items: center;
+    gap: 15px;
+}
+
+.logo-icon {
+    font-size: 2.2rem;
+    color: var(--primary-color);
+}
+
+.logo-text h1 {
+    font-size: 1.8rem;
+    color: var(--text-primary);
+    margin-bottom: 5px;
+}
+
+.logo-text p {
+    color: var(--text-secondary);
+    font-size: 0.9rem;
+}
+
+.user-actions {
+    display: flex;
+    gap: 15px;
+}
+
+.btn {
+    padding: 10px 20px;
+    border-radius: var(--radius);
+    font-weight: 600;
+    cursor: pointer;
+    transition: all 0.3s;
+    border: none;
+    display: flex;
+    align-items: center;
+    gap: 8px;
+}
+
+.btn-primary {
+    background-color: var(--primary-color);
+    color: white;
+}
+
+.btn-primary:hover {
+    background-color: var(--primary-hover);
+    transform: translateY(-2px);
+    box-shadow: 0 4px 12px rgba(79, 70, 229, 0.3);
+}
+
+.btn-secondary {
+    background-color: var(--secondary-color);
+    color: var(--text-secondary);
+}
+
+.btn-secondary:hover {
+    background-color: var(--secondary-hover);
+}
+
+.btn-sm {
+    padding: 6px 12px;
+    font-size: 0.85rem;
+}
+
+.stats-section {
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
+    gap: 20px;
+    margin-bottom: 30px;
+}
+
+.stat-card {
+    background-color: var(--bg-white);
+    padding: 25px;
+    border-radius: var(--radius-lg);
+    box-shadow: var(--shadow);
+    display: flex;
+    align-items: center;
+    gap: 15px;
+}
+
+.stat-icon {
+    width: 60px;
+    height: 60px;
+    border-radius: var(--radius-lg);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 1.5rem;
+}
+
+.stat-info h3 {
+    font-size: 1.8rem;
+    font-weight: 700;
+    color: var(--text-primary);
+    margin-bottom: 5px;
+}
+
+.stat-info p {
+    color: var(--text-secondary);
+    font-size: 0.9rem;
+}
+
+.add-category-section {
+    background-color: var(--bg-white);
+    padding: 25px;
+    border-radius: var(--radius-lg);
+    box-shadow: var(--shadow);
+    margin-bottom: 30px;
+}
+
+.section-title {
+    font-size: 1.4rem;
+    font-weight: 700;
+    color: var(--text-primary);
+    margin-bottom: 20px;
+    padding-bottom: 10px;
+    border-bottom: 1px solid var(--secondary-color);
+}
+
+.form-row {
+    display: grid;
+    grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+    gap: 20px;
+    margin-bottom: 20px;
+}
+
+.form-group {
+    display: flex;
+    flex-direction: column;
+    gap: 8px;
+}
+
+.form-group.full-width {
+    grid-column: 1 / -1;
+}
+
+.form-group label {
+    font-size: 0.9rem;
+    font-weight: 600;
+    color: var(--text-secondary);
+}
+
+.form-group input, .form-group select, .form-group textarea {
+    padding: 12px 15px;
+    border: 1px solid var(--border-color);
+    border-radius: var(--radius);
+    font-size: 1rem;
+    transition: all 0.3s;
+}
+
+.form-group input:focus, .form-group select:focus, .form-group textarea:focus {
+    outline: none;
+    border-color: var(--primary-color);
+    box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
+}
+
+.color-preview {
+    display: flex;
+    align-items: center;
+    gap: 10px;
+}
+
+.color-option {
+    width: 30px;
+    height: 30px;
+    border-radius: 50%;
+    cursor: pointer;
+    transition: all 0.3s;
+    border: 2px solid transparent;
+}
+
+.color-option:hover {
+    transform: scale(1.1);
+}
+
+.color-option.selected {
+    border-color: var(--text-primary);
+    transform: scale(1.1);
+}
+
+.icon-options {
+    display: grid;
+    grid-template-columns: repeat(auto-fill, minmax(40px, 1fr));
+    gap: 10px;
+}
+
+.icon-option {
+    width: 40px;
+    height: 40px;
+    border-radius: var(--radius);
+    background-color: var(--secondary-color);
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+    transition: all 0.3s;
+    border: 2px solid transparent;
+    font-size: 1.2rem;
+    color: var(--text-secondary);
+}
+
+.icon-option:hover {
+    background-color: var(--secondary-hover);
+    transform: translateY(-2px);
+}
+
+.icon-option.selected {
+    background-color: #e0e7ff;
+    border-color: var(--primary-color);
+    color: var(--primary-color);
+}
+
+.form-actions {
+    display: flex;
+    gap: 15px;
+    margin-top: 10px;
+}
+
+.categories-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 20px;
+}
+
+.categories-count {
+    font-size: 1.1rem;
+    color: var(--text-secondary);
+}
+
+.view-options {
+    display: flex;
+    gap: 10px;
+}
+
+.view-btn {
+    padding: 8px 12px;
+    border-radius: 6px;
+    background-color: var(--secondary-color);
+    color: var(--text-secondary);
+    cursor: pointer;
+    transition: all 0.3s;
+}
+
+.view-btn.active {
+    background-color: var(--primary-color);
+    color: white;
+}
+
+/* 网格视图样式 */
+.categories-grid {
+    display: grid;
+    grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
+    gap: 25px;
+}
+
+.category-card {
+    background-color: var(--bg-white);
+    border-radius: var(--radius-lg);
+    overflow: hidden;
+    box-shadow: var(--shadow);
+    transition: all 0.3s;
+    display: flex;
+    flex-direction: column;
+}
+
+.category-card:hover {
+    transform: translateY(-5px);
+    box-shadow: var(--shadow-hover);
+}
+
+.category-header {
+    padding: 20px 20px 15px;
+    display: flex;
+    justify-content: space-between;
+    align-items: flex-start;
+}
+
+.category-icon {
+    width: 50px;
+    height: 50px;
+    border-radius: 10px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 1.3rem;
+    color: white;
+}
+
+.category-actions {
+    display: flex;
+    gap: 8px;
+}
+
+.action-btn {
+    width: 32px;
+    height: 32px;
+    border-radius: 6px;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    cursor: pointer;
+    transition: all 0.3s;
+    background-color: var(--bg-light);
+    color: var(--text-light);
+    border: none;
+}
+
+.action-btn:hover {
+    background-color: var(--secondary-color);
+}
+
+.edit-btn:hover {
+    color: var(--primary-color);
+}
+
+.delete-btn:hover {
+    color: var(--danger-color);
+}
+
+.category-info {
+    padding: 0 20px 20px;
+    flex-grow: 1;
+}
+
+.category-name {
+    font-size: 1.3rem;
+    font-weight: 700;
+    color: var(--text-primary);
+    margin-bottom: 8px;
+}
+
+.category-code {
+    font-size: 0.85rem;
+    color: var(--text-secondary);
+    margin-bottom: 5px;
+}
+
+.category-description {
+    color: var(--text-secondary);
+    margin-bottom: 15px;
+    font-size: 0.95rem;
+    line-height: 1.5;
+}
+
+.category-meta {
+    display: flex;
+    justify-content: space-between;
+    margin-top: auto;
+    padding-top: 15px;
+    border-top: 1px solid var(--secondary-color);
+    font-size: 0.85rem;
+    color: var(--text-secondary);
+}
+
+/* 列表视图样式 */
+.categories-table {
+    width: 100%;
+    background-color: var(--bg-white);
+    border-radius: var(--radius-lg);
+    box-shadow: var(--shadow);
+    overflow: hidden;
+    display: none;
+}
+
+.categories-table.active {
+    display: table;
+}
+
+.categories-grid.active {
+    display: grid;
+}
+
+.categories-grid:not(.active) {
+    display: none;
+}
+
+.table-header {
+    display: grid;
+    grid-template-columns: 60px 120px 1fr 1fr 120px 80px 80px 80px 80px 100px 120px;
+    gap: 15px;
+    padding: 15px 20px;
+    background-color: var(--bg-light);
+    font-weight: 600;
+    color: var(--text-secondary);
+    border-bottom: 1px solid var(--border-color);
+}
+
+.table-row {
+    display: grid;
+    grid-template-columns: 60px 120px 1fr 1fr 120px 80px 80px 80px 80px 100px 120px;
+    gap: 15px;
+    padding: 15px 20px;
+    border-bottom: 1px solid var(--secondary-color);
+    transition: all 0.3s;
+}
+
+.table-row:hover {
+    background-color: var(--bg-light);
+}
+
+.table-cell {
+    display: flex;
+    align-items: center;
+    overflow: hidden;
+    text-overflow: ellipsis;
+    white-space: nowrap;
+}
+
+.status-badge {
+    padding: 4px 8px;
+    border-radius: 20px;
+    font-size: 0.8rem;
+    font-weight: 600;
+}
+
+.status-active {
+    background-color: #d1fae5;
+    color: #065f46;
+}
+
+.status-inactive {
+    background-color: #fef3c7;
+    color: #92400e;
+}
+
+.visibility-badge {
+    padding: 4px 8px;
+    border-radius: 20px;
+    font-size: 0.8rem;
+    font-weight: 600;
+}
+
+.visibility-visible {
+    background-color: #dbeafe;
+    color: #1e40af;
+}
+
+.visibility-hidden {
+    background-color: #f3f4f6;
+    color: #6b7280;
+}
+
+.empty-state {
+    grid-column: 1 / -1;
+    text-align: center;
+    padding: 60px 20px;
+    color: var(--text-secondary);
+}
+
+.empty-state i {
+    font-size: 3rem;
+    margin-bottom: 20px;
+    color: #cbd5e1;
+}
+
+.empty-state h3 {
+    font-size: 1.5rem;
+    margin-bottom: 10px;
+    color: var(--text-secondary);
+}
+
+.modal {
+    display: none;
+    position: fixed;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(0, 0, 0, 0.5);
+    z-index: 1000;
+    align-items: center;
+    justify-content: center;
+    padding: 20px;
+}
+
+.modal-content {
+    background-color: var(--bg-white);
+    border-radius: var(--radius-lg);
+    width: 100%;
+    max-width: 900px;
+    max-height: 90vh;
+    overflow-y: auto;
+    padding: 30px;
+    box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
+}
+
+.modal-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    margin-bottom: 20px;
+}
+
+.modal-title {
+    font-size: 1.4rem;
+    font-weight: 700;
+    color: var(--text-primary);
+}
+
+.close-btn {
+    background: none;
+    border: none;
+    font-size: 1.5rem;
+    cursor: pointer;
+    color: var(--text-secondary);
+}
+
+.modal-actions {
+    display: flex;
+    gap: 15px;
+    margin-top: 25px;
+    justify-content: flex-end;
+}
+
+/* 响应式设计 */
+@media (max-width: 1400px) {
+    .table-header, .table-row {
+        grid-template-columns: 60px 120px 1fr 1fr 120px 80px 80px 100px 120px;
+    }
+
+    .table-header .hide-on-large,
+    .table-row .hide-on-large {
+        display: none;
+    }
+}
+
+@media (max-width: 1200px) {
+    .table-header, .table-row {
+        grid-template-columns: 60px 120px 1fr 120px 80px 80px 100px 120px;
+    }
+
+    .table-header .hide-on-medium,
+    .table-row .hide-on-medium {
+        display: none;
+    }
+}
+
+@media (max-width: 992px) {
+    .table-header, .table-row {
+        grid-template-columns: 60px 1fr 120px 80px 100px 120px;
+    }
+
+    .table-header .hide-on-small,
+    .table-row .hide-on-small {
+        display: none;
+    }
+
+    .form-row {
+        grid-template-columns: 1fr;
+    }
+}
+
+@media (max-width: 768px) {
+    header {
+        flex-direction: column;
+        align-items: flex-start;
+        gap: 20px;
+    }
+
+    .categories-grid {
+        grid-template-columns: 1fr;
+    }
+
+    .table-header, .table-row {
+        grid-template-columns: 1fr 1fr 1fr;
+        gap: 10px;
+    }
+
+    .table-header .hide-on-mobile,
+    .table-row .hide-on-mobile {
+        display: none;
+    }
+
+    .user-actions {
+        width: 100%;
+        justify-content: space-between;
+    }
+
+    .modal-content {
+        padding: 20px;
+    }
+}
+
+@media (max-width: 576px) {
+    .container {
+        padding: 10px;
+    }
+
+    .table-header, .table-row {
+        grid-template-columns: 1fr 1fr;
+    }
+
+    .view-options {
+        flex-direction: column;
+    }
+}
+
+.search-section {
+    background-color: white;
+    padding: 25px;
+    border-radius: 12px;
+    box-shadow: 0 4px 6px rgba(0, 0, 0, 0.05);
+    margin-bottom: 30px;
+}
+
+.search-bar {
+    display: flex;
+    gap: 15px;
+    margin-bottom: 20px;
+}
+
+.search-input {
+    flex: 1;
+    position: relative;
+}
+
+.search-input input {
+    width: 100%;
+    padding: 14px 20px 14px 45px;
+    border: 1px solid #e2e8f0;
+    border-radius: 8px;
+    font-size: 1rem;
+    transition: all 0.3s;
+}
+
+.search-input input:focus {
+    outline: none;
+    border-color: #4f46e5;
+    box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.1);
+}
+
+.search-icon {
+    position: absolute;
+    left: 15px;
+    top: 50%;
+    transform: translateY(-50%);
+    color: #94a3b8;
+}
+
+.filters {
+    display: flex;
+    flex-wrap: wrap;
+    gap: 15px;
+}
+
+.filter-group {
+    display: flex;
+    flex-direction: column;
+    gap: 8px;
+}
+
+.filter-group label {
+    font-size: 0.9rem;
+    font-weight: 600;
+    color: #475569;
+}
+
+.filter-group select {
+    padding: 10px 15px;
+    border: 1px solid #e2e8f0;
+    border-radius: 8px;
+    background-color: white;
+    min-width: 150px;
+}

+ 49 - 0
imwork-windows/imwork-silos/src/main/resources/static/business/cms/books/category/edit.js

@@ -0,0 +1,49 @@
+layui.use(['form', 'layer'], function () {
+    var form = layui.form
+    layer = parent.layer === undefined ? layui.layer : top.layer,
+        $ = layui.jquery;
+
+    form.on("submit(save)", function (data) {
+        //弹出loading
+        const index = top.layer.msg('数据提交中,请稍候', {icon: 16, time: false, shade: 0.8});
+        //实际使用时的提交信息
+        $.ajax( {
+            url : "/silos/cms/books/categories/save",
+            type : "POST",
+            dataType:"json",
+            contentType:'application/json;charset=UTF-8',
+            data:JSON.stringify({id:$("#id").val(),
+                categoryCode:$("#categoryCode").val(),
+                categoryName:$("#categoryName").val(),
+                englishName: $("#englishName").val(),
+                categoryColor: 1,
+                categoryIcon: 1,
+                parentId: $("#parentId").val(),
+                level: $("#level").val(),
+                path: $("#path").val(),
+                sortOrder: $("#sortOrder").val(),
+                description: $("#description").val(),
+                keywords: $("#keywords").val(),
+                categoryStatus: $("#categoryStatus").val(),
+                isVisible: $("#isVisible").val(),
+                remark: $("#remark").val(),
+            }),
+            success : function(res) {
+                console.log(res);
+                layer.close(index);
+                layer.msg(res.msg);
+                layer.closeAll("iframe");
+                //刷新父页面
+                parent.location.reload();
+            },
+            error:function(e){
+                layer.close(index);
+                layer.msg("信息提交异常!");
+                layer.closeAll("iframe");
+                //刷新父页面
+                parent.location.reload();
+            }
+        })
+        return false;
+    })
+})

+ 50 - 0
imwork-windows/imwork-silos/src/main/resources/static/business/cms/books/category/list.js

@@ -0,0 +1,50 @@
+layui.config({
+    base: '/assets/lib/jplus/treeTable/'
+}).use(['form', 'layer', 'table', 'laytpl', 'treeTable'], function () {
+    $(".add_btn").click(function () {
+        edit();
+    })
+    // 添加/修改
+    function edit(edit) {
+        let title = "添加分类";
+        if (edit != null) {
+            title = "修改分类";
+        }
+        const index = layui.layer.open({
+            title: title,
+            type: 2,
+            content: "/silos/cms/books/category/edit.html",
+            scrollbar: false,
+            success: function (layero, index) {
+                var body = layui.layer.getChildFrame('body', index);
+                if (edit) {
+                    body.find(".uid").val(BigInt(edit.id).toString());
+                    body.find(".userName").val(edit.userName);  //用户名
+                    body.find(".loginName").val(edit.loginName);  //登录名
+                    body.find(".userMobilePhone").val(edit.userMobilePhone);
+                    body.find(".userNickName").val(edit.userNickName);
+                    body.find(".userAddress").val(edit.userAddress);
+                    body.find(".userEmail").val(edit.userEmail);  //邮箱
+                    body.find(".userSex input[value=" + edit.userSex + "]").prop("checked", "checked");  //性别
+                    body.find(".allowedNetworkType").val(edit.allowedNetworkType);
+                    body.find(".userType").val(edit.userType);  //会员等级
+                    body.find(".userStatus").val(edit.userStatus);    //用户状态
+                    body.find(".userDescription").text(edit.userDescription);    //用户简介
+                    body.find(".remark").text(edit.remark);
+                    form.render();
+                }
+                setTimeout(function () {
+                    layui.layer.tips('点击此处返回分类列表', '.layui-layer-setwin .layui-layer-close', {
+                        tips: 3
+                    });
+                }, 500)
+            }
+        });
+        layui.layer.full(index);
+        window.sessionStorage.setItem("index", index);
+        //改变窗口大小时,重置弹窗的宽高,防止超出可视区域(如F12调出debug的操作)
+        $(window).on("resize", function () {
+            layui.layer.full(window.sessionStorage.getItem("index"));
+        })
+    }
+})

+ 1 - 1
imwork-windows/imwork-silos/src/main/resources/static/business/generator/list.js

@@ -8,7 +8,7 @@ layui.use(['form', 'layer', 'table', 'laytpl'], function () {
     //列表
     var tableIns = table.render({
         elem: '#list',
-        url: '/generator/generator/list',
+        url: '/generator/list',
         cellMinWidth: 95,
         page: true,
         height: "full-125",

+ 155 - 0
imwork-windows/imwork-silos/src/main/resources/templates/cms/books/category/edit.html

@@ -0,0 +1,155 @@
+<!DOCTYPE html>
+<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="UTF-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <title>添加图书分类</title>
+    <!-- 公共样式 开始 -->
+    <link rel="shortcut icon" href="../../../../static/assets/silos/images/logo/logo.png" th:href="@{/assets/silos/images/logo/logo.png}"/>
+    <link rel="bookmark" href="../../../../static/assets/silos/images/logo/logo.png" th:href="@{/assets/silos/images/logo/logo.png}"/>
+    <link rel="stylesheet" href="../../../../static/assets/lib/layui/css/layui.css" th:href="@{/assets/lib/layui/css/layui.css}"/>
+    <link rel="stylesheet" href="../../../../static/assets/lib/fonts/fontawesome4/css/font-awesome.css" th:href="@{/assets/lib/fonts/fontawesome4/css/font-awesome.css}"/>
+    <link rel="stylesheet" href="../../../../static/assets/lib/fonts/fontawesome6/css/all.min.css" th:href="@{/assets/lib/fonts/fontawesome6/css/all.min.css}"/>
+    <link rel="stylesheet" href="../../../../static/business/cms/books/category/category.css" th:href="@{/business/cms/books/category/category.css}"/>
+
+</head>
+<body>
+<div class="container">
+    <div class="form-container">
+        <section class="add-category-section">
+            <h2 class="section-title">添加图书分类</h2>
+            <form class="add-category-form" id="addCategoryForm">
+                <div class="form-row">
+                    <div class="form-group">
+                        <label for="categoryCode">分类代码 *</label>
+                        <input type="text" id="categoryCode" placeholder="如: CAT001" required>
+                    </div>
+                    <div class="form-group">
+                        <label for="categoryName">分类名称 *</label>
+                        <input type="text" id="categoryName" placeholder="请输入分类名称" required>
+                    </div>
+                    <div class="form-group">
+                        <label for="englishName">英文名称</label>
+                        <input type="text" id="englishName" placeholder="请输入英文名称">
+                    </div>
+                </div>
+
+                <div class="form-row">
+                    <div class="form-group">
+                        <label for="parentId">父级分类</label>
+                        <select id="parentId">
+                            <option value="0">无(顶级分类)</option>
+                            <option value="1">文学小说</option>
+                            <option value="2">科学技术</option>
+                            <option value="3">历史传记</option>
+                        </select>
+                    </div>
+                    <div class="form-group">
+                        <label for="level">分类层级</label>
+                        <select id="level">
+                            <option value="1">一级分类</option>
+                            <option value="2">二级分类</option>
+                            <option value="3">三级分类</option>
+                        </select>
+                    </div>
+                    <div class="form-group">
+                        <label for="sortOrder">排序序号</label>
+                        <input type="number" id="sortOrder" value="1" min="1">
+                    </div>
+                </div>
+
+                <div class="form-row">
+                    <div class="form-group">
+                        <label for="keywords">关键词</label>
+                        <input type="text" id="keywords" placeholder="多个关键词用逗号分隔">
+                    </div>
+                    <div class="form-group">
+                        <label for="categoryStatus">分类状态</label>
+                        <select id="categoryStatus">
+                            <option value="active">活跃</option>
+                            <option value="inactive">未激活</option>
+                        </select>
+                    </div>
+                    <div class="form-group">
+                        <label for="isVisible">是否可见</label>
+                        <select id="isVisible">
+                            <option value="1">可见</option>
+                            <option value="0">隐藏</option>
+                        </select>
+                    </div>
+                </div>
+
+                <div class="form-row">
+                    <div class="form-group">
+                        <label>分类颜色</label>
+                        <div class="color-preview">
+                            <div class="color-option selected" style="background-color: #4f46e5;" data-color="#4f46e5"></div>
+                            <div class="color-option" style="background-color: #ef4444;" data-color="#ef4444"></div>
+                            <div class="color-option" style="background-color: #10b981;" data-color="#10b981"></div>
+                            <div class="color-option" style="background-color: #f59e0b;" data-color="#f59e0b"></div>
+                            <div class="color-option" style="background-color: #8b5cf6;" data-color="#8b5cf6"></div>
+                            <div class="color-option" style="background-color: #ec4899;" data-color="#ec4899"></div>
+                        </div>
+                        <input type="hidden" id="categoryColor" name="categoryColor" value="#4f46e5">
+                    </div>
+                    <div class="form-group">
+                        <label>分类图标</label>
+                        <div class="icon-options">
+                            <div class="icon-option selected" data-icon="book">
+                                <i class="fas fa-book"></i>
+                            </div>
+                            <div class="icon-option" data-icon="laptop">
+                                <i class="fas fa-laptop"></i>
+                            </div>
+                            <div class="icon-option" data-icon="history">
+                                <i class="fas fa-history"></i>
+                            </div>
+                            <div class="icon-option" data-icon="chart-line">
+                                <i class="fas fa-chart-line"></i>
+                            </div>
+                            <div class="icon-option" data-icon="graduation-cap">
+                                <i class="fas fa-graduation-cap"></i>
+                            </div>
+                            <div class="icon-option" data-icon="palette">
+                                <i class="fas fa-palette"></i>
+                            </div>
+                        </div>
+                        <input type="hidden" id="categoryIcon" name="categoryIcon" value="book">
+                    </div>
+                    <div class="form-group">
+                        <label for="categoryPath">分类路径</label>
+                        <input type="text" id="categoryPath" placeholder="如: /文学/小说">
+                    </div>
+                </div>
+
+                <div class="form-row">
+                    <div class="form-group full-width">
+                        <label for="categoryDescription">分类描述</label>
+                        <textarea id="categoryDescription" rows="3" placeholder="请输入分类描述"></textarea>
+                    </div>
+                </div>
+
+                <div class="form-row">
+                    <div class="form-group full-width">
+                        <label for="categoryNotes">备注</label>
+                        <textarea id="categoryNotes" rows="2" placeholder="请输入备注信息"></textarea>
+                    </div>
+                </div>
+
+                <div class="form-actions">
+                    <button type="submit" class="btn btn-primary" lay-submit="" lay-filter="save">
+                        <i class="fas fa-plus"></i> 添加分类
+                    </button>
+                    <button type="reset" class="btn btn-secondary">
+                        <i class="fas fa-redo"></i> 重置表单
+                    </button>
+                </div>
+            </form>
+        </section>
+    </div>
+</div>
+<script src="../../../../static/assets/lib/jquery/jquery.js" th:src="@{/assets/lib/jquery/jquery.js}"></script>
+<script src="../../../../static/assets/lib/layui/layui.js" th:src="@{/assets/lib/layui/layui.js}"></script>
+<script src="../../../../static/business/cms/books/category/edit.js" th:src="@{/business/cms/books/category/edit.js}"></script>
+</body>
+</html>

+ 305 - 0
imwork-windows/imwork-silos/src/main/resources/templates/cms/books/category/list.html

@@ -0,0 +1,305 @@
+<!DOCTYPE html>
+<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
+<head>
+    <meta charset="UTF-8">
+    <meta http-equiv="X-UA-Compatible" content="IE=edge,Chrome=1">
+    <!-- Google Chrome Frame也可以让IE用上Chrome的引擎: -->
+    <meta name="renderer" content="webkit">
+    <!--国产浏览器高速模式-->
+    <meta name="viewport" content="width=device-width, initial-scale=1">
+    <!-- 作者 -->
+    <meta name="author" content="imwork"/>
+    <meta name="revised" content="silos-Admin-v-1.0.0.1"/>
+    <!-- 定义页面的最新版本 -->
+    <meta name="description" content="网站简介"/>
+    <!-- 网站简介 -->
+    <meta name="keywords" content="搜索关键字,以半角英文逗号隔开"/>
+
+    <title>图书分类管理</title>
+    <!-- 公共样式 开始 -->
+    <link rel="shortcut icon" href="../../../../static/assets/silos/images/logo/logo.png" th:href="@{/assets/silos/images/logo/logo.png}"/>
+    <link rel="bookmark" href="../../../../static/assets/silos/images/logo/logo.png" th:href="@{/assets/silos/images/logo/logo.png}"/>
+    <link rel="stylesheet" href="../../../../static/assets/lib/layui/css/layui.css" th:href="@{/assets/lib/layui/css/layui.css}"/>
+    <link rel="stylesheet" href="../../../../static/assets/lib/fonts/fontawesome4/css/font-awesome.css" th:href="@{/assets/lib/fonts/fontawesome4/css/font-awesome.css}"/>
+    <link rel="stylesheet" href="../../../../static/assets/lib/fonts/fontawesome6/css/all.min.css" th:href="@{/assets/lib/fonts/fontawesome6/css/all.min.css}"/>
+    <link rel="stylesheet" href="../../../../static/business/cms/books/category/category.css" th:href="@{/business/cms/books/category/category.css}"/>
+</head>
+<body>
+<div class="container">
+    <section class="stats-section">
+        <div class="stat-card">
+            <div class="stat-icon" style="background-color: #e0e7ff; color: #4f46e5;">
+                <i class="fas fa-tags logo-icon"></i>
+            </div>
+            <div class="stat-info">
+                <h1>图书分类管理</h1>
+                <p>全面管理您的图书分类</p>
+            </div>
+        </div>
+        <div class="stat-card">
+            <div class="stat-icon" style="background-color: #e0e7ff; color: #4f46e5;">
+                <i class="fas fa-tags"></i>
+            </div>
+            <div class="stat-info">
+                <h3>12</h3>
+                <p>分类总数</p>
+            </div>
+        </div>
+        <div class="stat-card">
+            <div class="stat-icon" style="background-color: #fef3c7; color: #d97706;">
+                <i class="fas fa-book"></i>
+            </div>
+            <div class="stat-info">
+                <h3>356</h3>
+                <p>图书总数</p>
+            </div>
+        </div>
+        <div class="stat-card">
+            <div class="stat-icon" style="background-color: #dcfce7; color: #16a34a;">
+                <i class="fas fa-check-circle"></i>
+            </div>
+            <div class="stat-info">
+                <h3>8</h3>
+                <p>活跃分类</p>
+            </div>
+        </div>
+        <div class="stat-card">
+            <div class="stat-icon" style="background-color: #fce7f3; color: #db2777;">
+                <i class="fas fa-archive"></i>
+            </div>
+            <div class="stat-info">
+                <h3>4</h3>
+                <p>归档分类</p>
+            </div>
+        </div>
+    </section>
+
+    <section class="search-section">
+        <div class="search-bar">
+            <div class="search-input">
+                <i class="fas fa-search search-icon"></i>
+                <input type="text" placeholder="搜索书名、作者或ISBN...">
+            </div>
+            <button class="btn btn-primary">
+                <i class="fas fa-search"></i> 搜索
+            </button>
+            <button class="btn btn-secondary">
+                <i class="fas fa-sync-alt"></i> 刷新
+            </button>
+            <button class="btn btn-primary add_btn" id="addCategoryBtn">
+                <i class="fas fa-plus"></i> 添加分类
+            </button>
+        </div>
+
+        <div class="filters">
+            <div class="filter-group">
+                <label>分类</label>
+                <select>
+                    <option>全部</option>
+                    <option>文学</option>
+                    <option>科技</option>
+                    <option>历史</option>
+                    <option>经济</option>
+                    <option>教育</option>
+                </select>
+            </div>
+
+            <div class="filter-group">
+                <label>状态</label>
+                <select>
+                    <option>全部</option>
+                    <option>在库</option>
+                    <option>借出</option>
+                    <option>待归还</option>
+                </select>
+            </div>
+
+            <div class="filter-group">
+                <label>排序</label>
+                <select>
+                    <option>最新添加</option>
+                    <option>书名 A-Z</option>
+                    <option>作者 A-Z</option>
+                    <option>出版日期</option>
+                </select>
+            </div>
+        </div>
+    </section>
+
+    <section class="categories-section">
+        <div class="categories-header">
+            <div class="categories-count">共 12 个分类</div>
+            <div class="view-options">
+                <div class="view-btn active" data-view="grid">
+                    <i class="fas fa-th"></i> 网格视图
+                </div>
+                <div class="view-btn" data-view="table">
+                    <i class="fas fa-list"></i> 列表视图
+                </div>
+            </div>
+        </div>
+
+        <!-- 网格视图 -->
+        <div class="categories-grid active" id="categoriesGrid">
+            <!-- 分类卡片将通过JavaScript动态生成 -->
+        </div>
+
+        <!-- 列表视图 -->
+        <div class="categories-table" id="categoriesTable">
+            <div class="table-header">
+                <div class="table-cell">序号</div>
+                <div class="table-cell">分类代码</div>
+                <div class="table-cell">分类名称</div>
+                <div class="table-cell hide-on-mobile">英文名称</div>
+                <div class="table-cell hide-on-medium">父级分类</div>
+                <div class="table-cell hide-on-large">层级</div>
+                <div class="table-cell">状态</div>
+                <div class="table-cell hide-on-small">可见性</div>
+                <div class="table-cell hide-on-large">排序</div>
+                <div class="table-cell hide-on-medium">路径</div>
+                <div class="table-cell">操作</div>
+            </div>
+            <div id="categoriesTableBody">
+                <!-- 表格行将通过JavaScript动态生成 -->
+            </div>
+        </div>
+    </section>
+</div>
+
+<!-- 编辑分类模态框 -->
+<div class="modal" id="editModal">
+    <div class="modal-content">
+        <div class="modal-header">
+            <h3 class="modal-title">编辑分类</h3>
+            <button class="close-btn" id="closeEditModal">&times;</button>
+        </div>
+        <form id="editCategoryForm">
+            <div class="form-row">
+                <div class="form-group">
+                    <label for="editCategoryCode">分类代码 *</label>
+                    <input type="text" id="editCategoryCode" required>
+                </div>
+                <div class="form-group">
+                    <label for="editCategoryName">分类名称 *</label>
+                    <input type="text" id="editCategoryName" required>
+                </div>
+                <div class="form-group">
+                    <label for="editCategoryEnName">英文名称</label>
+                    <input type="text" id="editCategoryEnName">
+                </div>
+            </div>
+
+            <div class="form-row">
+                <div class="form-group">
+                    <label for="editCategoryParent">父级分类</label>
+                    <select id="editCategoryParent">
+                        <option value="">无(顶级分类)</option>
+                        <option value="1">文学小说</option>
+                        <option value="2">科学技术</option>
+                        <option value="3">历史传记</option>
+                    </select>
+                </div>
+                <div class="form-group">
+                    <label for="editCategoryLevel">分类层级</label>
+                    <select id="editCategoryLevel">
+                        <option value="1">一级分类</option>
+                        <option value="2">二级分类</option>
+                        <option value="3">三级分类</option>
+                    </select>
+                </div>
+                <div class="form-group">
+                    <label for="editCategoryOrder">排序序号</label>
+                    <input type="number" id="editCategoryOrder" min="1">
+                </div>
+            </div>
+
+            <div class="form-row">
+                <div class="form-group">
+                    <label for="editCategoryKeywords">关键词</label>
+                    <input type="text" id="editCategoryKeywords">
+                </div>
+                <div class="form-group">
+                    <label for="editCategoryStatus">分类状态</label>
+                    <select id="editCategoryStatus">
+                        <option value="active">活跃</option>
+                        <option value="inactive">未激活</option>
+                    </select>
+                </div>
+                <div class="form-group">
+                    <label for="editCategoryVisible">是否可见</label>
+                    <select id="editCategoryVisible">
+                        <option value="1">可见</option>
+                        <option value="0">隐藏</option>
+                    </select>
+                </div>
+            </div>
+
+            <div class="form-row">
+                <div class="form-group">
+                    <label>分类颜色</label>
+                    <div class="color-preview">
+                        <div class="color-option" style="background-color: #4f46e5;" data-color="#4f46e5"></div>
+                        <div class="color-option" style="background-color: #ef4444;" data-color="#ef4444"></div>
+                        <div class="color-option" style="background-color: #10b981;" data-color="#10b981"></div>
+                        <div class="color-option" style="background-color: #f59e0b;" data-color="#f59e0b"></div>
+                        <div class="color-option" style="background-color: #8b5cf6;" data-color="#8b5cf6"></div>
+                        <div class="color-option" style="background-color: #ec4899;" data-color="#ec4899"></div>
+                    </div>
+                    <input type="hidden" id="editCategoryColor" name="editCategoryColor" value="#4f46e5">
+                </div>
+                <div class="form-group">
+                    <label>分类图标</label>
+                    <div class="icon-options">
+                        <div class="icon-option" data-icon="book">
+                            <i class="fas fa-book"></i>
+                        </div>
+                        <div class="icon-option" data-icon="laptop">
+                            <i class="fas fa-laptop"></i>
+                        </div>
+                        <div class="icon-option" data-icon="history">
+                            <i class="fas fa-history"></i>
+                        </div>
+                        <div class="icon-option" data-icon="chart-line">
+                            <i class="fas fa-chart-line"></i>
+                        </div>
+                        <div class="icon-option" data-icon="graduation-cap">
+                            <i class="fas fa-graduation-cap"></i>
+                        </div>
+                        <div class="icon-option" data-icon="palette">
+                            <i class="fas fa-palette"></i>
+                        </div>
+                    </div>
+                    <input type="hidden" id="editCategoryIcon" name="editCategoryIcon" value="book">
+                </div>
+                <div class="form-group">
+                    <label for="editCategoryPath">分类路径</label>
+                    <input type="text" id="editCategoryPath">
+                </div>
+            </div>
+
+            <div class="form-row">
+                <div class="form-group full-width">
+                    <label for="editCategoryDescription">分类描述</label>
+                    <textarea id="editCategoryDescription" rows="3"></textarea>
+                </div>
+            </div>
+
+            <div class="form-row">
+                <div class="form-group full-width">
+                    <label for="editCategoryNotes">备注</label>
+                    <textarea id="editCategoryNotes" rows="2"></textarea>
+                </div>
+            </div>
+
+            <div class="modal-actions">
+                <button type="button" class="btn btn-secondary" id="cancelEdit">取消</button>
+                <button type="submit" class="btn btn-primary">保存更改</button>
+            </div>
+        </form>
+    </div>
+</div>
+<script src="../../../../static/assets/lib/jquery/jquery.js" th:src="@{/assets/lib/jquery/jquery.js}"></script>
+<script src="../../../../static/assets/lib/layui/layui.js" th:src="@{/assets/lib/layui/layui.js}"></script>
+<script src="../../../../static/business/cms/books/category/list.js" th:src="@{/business/cms/books/category/list.js}"></script>
+</body>
+</html>

+ 10 - 0
imwork-windows/imwork-silos/src/main/resources/templates/main/index.html

@@ -52,6 +52,16 @@
                     <li><a href="/admin/upms/role/list.html" class="tabs" id="5"><span>角色管理</span></a></li>
                 </ul>
             </li>
+            <li class="canvas-nav-item">
+                <a href="javascript:;"><i class="fa fa-database icons"></i><span>内容管理</span><i class="layui-icon layui-icon-right icon-right"></i></a>
+                <ul>
+                    <li><a href="../cms/books/list.html" class="tabs" id="6"><span>图书管理</span></a></li>
+                    <li><a href="../cms/books/chapter_list.html" class="tabs" id="10"><span>章节管理</span></a></li>
+                    <li><a href="/silos/cms/books/category/list.html" class="tabs" id="7"><span>分类管理</span></a></li>
+                    <li><a href="../cms/books/add_category.html" class="tabs" id="9"><span>添加分类</span></a></li>
+                    <li><a href="../cms/books/add.html" class="tabs" id="8"><span>图书录入</span></a></li>
+                </ul>
+            </li>
             <li class="canvas-nav-item">
                 <a href="javascript:;" id="hah"><i class="fa fa-database icons"></i><span>数据管理</span><i class="layui-icon layui-icon-right icon-right"></i></a>
                 <ul>

+ 6 - 0
pom.xml

@@ -98,6 +98,7 @@
         <fastjson.version>2.0.60</fastjson.version>
         <easyexcel.version>4.0.3</easyexcel.version>
         <jasypt.version>3.0.5</jasypt.version>
+        <gson.version>2.13.2</gson.version>
 
         <!--imwork-commons-->
         <imwork-commons.version>${project.version}</imwork-commons.version>
@@ -105,6 +106,11 @@
 
     <dependencyManagement>
         <dependencies>
+            <dependency>
+                <groupId>com.google.code.gson</groupId>
+                <artifactId>gson</artifactId>
+                <version>${gson.version}</version>
+            </dependency>
             <!--imwork-commons-->
             <dependency>
                 <groupId>top.imwork</groupId>