xiongwanxiong 1 месяц назад
Родитель
Сommit
98042735f0
24 измененных файлов с 1668 добавлено и 27 удалено
  1. 3 0
      wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/analyze/controller/ChemicalsEntryController.java
  2. 18 15
      wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/analyze/controller/GoodsEntryController.java
  3. 3 0
      wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/statReport/controller/CustomMStatFController.java
  4. 126 0
      wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/system/controller/BusLogController.java
  5. 72 0
      wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/system/dao/BusLogMapper.java
  6. 53 0
      wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/system/pojo/BusLog.java
  7. 52 0
      wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/system/pojo/BusLogQuery.java
  8. 89 0
      wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/system/service/IBusLogService.java
  9. 172 0
      wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/system/service/impl/BusLogServiceImpl.java
  10. 152 0
      wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/utils/SysBusLogUtil.java
  11. 6 6
      wxjy-wxjy-service/src/main/resources/application.properties
  12. 168 0
      wxjy-wxjy-service/src/main/resources/mapper/system/BusLogMapper.xml
  13. 2 2
      wxjy-wxjy-web/public/config.js
  14. 23 0
      wxjy-wxjy-web/src/App.vue
  15. 57 0
      wxjy-wxjy-web/src/apis/accessory.ts
  16. 46 0
      wxjy-wxjy-web/src/apis/system/BusLog.ts
  17. 3 2
      wxjy-wxjy-web/src/components/accessory/AccessoryUploader.vue
  18. 1 1
      wxjy-wxjy-web/src/main.ts
  19. 18 0
      wxjy-wxjy-web/src/router/app-router.ts
  20. 4 0
      wxjy-wxjy-web/src/router/index.ts
  21. 29 0
      wxjy-wxjy-web/src/types/system/BusLog.ts
  22. 288 0
      wxjy-wxjy-web/src/views/system/BusOperaLog.vue
  23. 282 0
      wxjy-wxjy-web/src/views/system/BusQueryLog.vue
  24. 1 1
      wxjy-wxjy-web/vite.config.ts

+ 3 - 0
wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/analyze/controller/ChemicalsEntryController.java

@@ -10,6 +10,7 @@ import cn.gov.customs.wxjy.common.utils.StringUtils;
 import cn.gov.customs.wxjy.common.utils.poi.DynamicExcelUtil;
 import cn.gov.customs.wxjy.base.service.BaseCodeService;
 import cn.gov.customs.wxjy.system.service.DictDataService;
+import cn.gov.customs.wxjy.utils.SysBusLogUtil;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
 import lombok.RequiredArgsConstructor;
@@ -32,6 +33,7 @@ public class ChemicalsEntryController extends BaseController {
     private final IGoodsEntryService service;
     private final BaseCodeService baseCodeService;
     private final DictDataService dictDataService;
+    private final String subject = "可视化分析-危险品组合查询";
 
     @GetMapping("/get-entry")
     public Result<EntryInfo> getEntryHead(@RequestParam String entryId) {
@@ -85,5 +87,6 @@ public class ChemicalsEntryController extends BaseController {
         // 使用动态Excel工具类
         DynamicExcelUtil<Entry> util = new DynamicExcelUtil<>(Entry.class);
         util.exportExcel(response, list, "危化品组合查询数据","",exportHeadList);
+        SysBusLogUtil.log(subject, true,null, SysBusLogUtil.ACT_TYPE_EXPORT);
     }
 }

+ 18 - 15
wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/analyze/controller/GoodsEntryController.java

@@ -1,28 +1,26 @@
 package cn.gov.customs.wxjy.analyze.controller;
 
-import java.io.IOException;
-import java.util.List;
-import javax.servlet.http.HttpServletResponse;
-
 import cn.gov.customs.cacp.sdks.core.result.Result;
 import cn.gov.customs.cacp.sdks.core.user.annotation.LogonUser;
 import cn.gov.customs.cacp.sdks.core.user.pojo.CacpLogonUser;
-import cn.gov.customs.wxjy.analyze.pojo.EntryInfo;
-import cn.gov.customs.wxjy.analyze.pojo.EntryList;
+import cn.gov.customs.wxjy.analyze.pojo.*;
+import cn.gov.customs.wxjy.analyze.service.IGoodsEntryService;
 import cn.gov.customs.wxjy.base.service.BaseCodeService;
-import cn.gov.customs.wxjy.common.utils.DictUtils;
+import cn.gov.customs.wxjy.common.annotation.Log;
+import cn.gov.customs.wxjy.common.core.controller.BaseController;
+import cn.gov.customs.wxjy.common.enums.BusinessType;
+import cn.gov.customs.wxjy.common.utils.StringUtils;
 import cn.gov.customs.wxjy.common.utils.poi.DynamicExcelUtil;
 import cn.gov.customs.wxjy.system.service.DictDataService;
-import lombok.RequiredArgsConstructor;
-import org.springframework.web.bind.annotation.*;
-import cn.gov.customs.wxjy.common.core.controller.BaseController;
+import cn.gov.customs.wxjy.utils.SysBusLogUtil;
 import com.github.pagehelper.PageHelper;
 import com.github.pagehelper.PageInfo;
-import cn.gov.customs.wxjy.analyze.pojo.Entry;
-import cn.gov.customs.wxjy.analyze.pojo.EntryHead;
-import cn.gov.customs.wxjy.analyze.pojo.EntryQuery;
-import cn.gov.customs.wxjy.analyze.service.IGoodsEntryService;
-import cn.gov.customs.wxjy.common.utils.StringUtils;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.util.List;
 
 /**
  * 危险品报关单头Controller
@@ -38,6 +36,8 @@ public class GoodsEntryController extends BaseController {
     private final BaseCodeService baseCodeService;
     private final DictDataService dictDataService;
 
+    private final String subject = "可视化分析-危险货物组合查询";
+
     @GetMapping("/get-entry")
     public Result<EntryInfo> getEntryHead(@RequestParam String entryId) {
         EntryHead head = this.service.selectByEntryId(entryId);
@@ -52,6 +52,7 @@ public class GoodsEntryController extends BaseController {
      * 查询危险品报关单头列表
      */
     @PostMapping("/get-list")
+
     public Result<PageInfo<Entry>> list(@LogonUser CacpLogonUser user, @RequestBody EntryQuery query) {
         PageHelper.startPage(query.getPageIndex(), query.getPageSize());
         String customsCode = user.getCustomsCode();
@@ -69,6 +70,7 @@ public class GoodsEntryController extends BaseController {
      * 导出危险品报关单头列表
      */
     @PostMapping("/goods-export")
+    @Log(title = "欧盟不合格商品展示", businessType = BusinessType.EXPORT)
     public void export(@LogonUser CacpLogonUser user, HttpServletResponse response, @RequestBody EntryQuery query) throws IOException {
         String customsCode = user.getCustomsCode();
         // 获取前端传递的动态列配置
@@ -90,5 +92,6 @@ public class GoodsEntryController extends BaseController {
         // 使用动态Excel工具类
         DynamicExcelUtil<Entry> util = new DynamicExcelUtil<>(Entry.class);
         util.exportExcel(response, list, "危险货物组合查询数据","",exportHeadList);
+        SysBusLogUtil.log(subject, true,null, SysBusLogUtil.ACT_TYPE_EXPORT);
     }
 }

+ 3 - 0
wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/statReport/controller/CustomMStatFController.java

@@ -8,6 +8,7 @@ import cn.gov.customs.cacp.sdks.core.result.Result;
 import cn.gov.customs.cacp.sdks.core.user.trans.CacpTransUser;
 import cn.gov.customs.cacp.sdks.core.user.trans.UserContextHolder;
 import cn.gov.customs.wxjy.common.utils.StringUtils;
+import cn.gov.customs.wxjy.utils.SysBusLogUtil;
 import lombok.RequiredArgsConstructor;
 import org.springframework.web.bind.annotation.*;
 import cn.gov.customs.wxjy.common.core.controller.BaseController;
@@ -32,6 +33,7 @@ import cn.gov.customs.wxjy.common.core.page.TableDataInfo;
 public class CustomMStatFController extends BaseController {
 
     private final ICustomMStatFService customMStatFService;
+    private final String subject = "统计报表-申报地海关报表";
 
     /**
      * 查询按业务现场关区分类列表
@@ -106,6 +108,7 @@ public class CustomMStatFController extends BaseController {
         List<CustomMStatF> list = customMStatFService.selectList(query);
         ExcelUtil<CustomMStatF> util = new ExcelUtil<CustomMStatF>(CustomMStatF.class);
         util.exportExcel(response, list, "按业务现场关区分类数据");
+        SysBusLogUtil.log(subject, true,null, SysBusLogUtil.ACT_TYPE_EXPORT);
     }
 
     /**

+ 126 - 0
wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/system/controller/BusLogController.java

@@ -0,0 +1,126 @@
+package cn.gov.customs.wxjy.system.controller;
+
+import java.io.UnsupportedEncodingException;
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import cn.gov.customs.cacp.sdks.core.result.Result;
+import cn.gov.customs.cacp.sdks.core.user.trans.CacpTransUser;
+import cn.gov.customs.cacp.sdks.core.user.trans.UserContextHolder;
+import cn.gov.customs.wxjy.common.utils.StringUtils;
+import cn.gov.customs.wxjy.utils.SysBusLogUtil;
+import lombok.RequiredArgsConstructor;
+import org.springframework.web.bind.annotation.*;
+import cn.gov.customs.wxjy.common.core.controller.BaseController;
+import org.springframework.web.multipart.MultipartFile;
+import com.github.pagehelper.PageHelper;
+import com.github.pagehelper.PageInfo;
+import cn.gov.customs.wxjy.system.pojo.BusLog;
+import cn.gov.customs.wxjy.system.pojo.BusLogQuery;
+import cn.gov.customs.wxjy.system.service.IBusLogService;
+import cn.gov.customs.wxjy.common.utils.poi.ExcelUtil;
+import cn.gov.customs.wxjy.common.core.page.TableDataInfo;
+
+/**
+ * 操作日志Controller
+ *
+ * @author xiong
+ * @date 2025-12-30
+ */
+@RestController
+@RequestMapping("/system/BusLog")
+@RequiredArgsConstructor
+public class BusLogController extends BaseController {
+
+    private final IBusLogService busLogService;
+
+    /**
+     * 查询操作日志列表
+     */
+    @PostMapping("/get-list")
+    public Result<PageInfo<BusLog>> list(@RequestBody BusLogQuery query) {
+        PageHelper.startPage(query.getPageIndex(), query.getPageSize());
+        PageInfo<BusLog> list = busLogService.selectPageList(query);
+        return Result.success(list);
+    }
+
+    /**
+     * 获取操作日志详细信息
+     */
+    @GetMapping(value = "/get-detail")
+    public Result<BusLog> getInfo(@RequestParam String id) {
+        return Result.success(busLogService.selectById(id));
+    }
+
+    /**
+     * 新增操作日志
+     */
+    @PostMapping("/insert-busLog")
+    public Result<Integer> add(@RequestBody BusLog busLog) {
+        return Result.success(busLogService.insert(busLog));
+    }
+
+    /**
+     * 修改操作日志
+     */
+    @PostMapping("/update-busLog")
+    public Result<Integer> edit(@RequestBody BusLog busLog) {
+        return Result.success(busLogService.update(busLog));
+    }
+
+    /**
+     * 删除操作日志
+     */
+    @PostMapping("/delete-busLog")
+    public Result<Integer> remove(@RequestBody String[] ids) {
+        return Result.success(busLogService.deleteByIds(ids));
+    }
+
+    /**
+    * 导入 操作日志
+    * @param file
+    * @param updateSupport
+    * @return
+    * @throws Exception
+    */
+    @PostMapping("/import-busLog")
+    public Result<String> importData(MultipartFile file, boolean updateSupport) throws Exception
+    {
+        CacpTransUser user = UserContextHolder.currentUser();
+        ExcelUtil<BusLog> util = new ExcelUtil<BusLog>(BusLog.class);
+        List<BusLog> busLogList = util.importExcel(file.getInputStream());
+        String message = busLogService.importBusLog(busLogList, updateSupport, user);
+        return Result.success(message);
+    }
+
+    /**
+     * 导出操作日志列表
+     */
+    @PostMapping("/get-busLog-export")
+    public void export(HttpServletResponse response, @RequestBody BusLogQuery query) {
+        List<BusLog> list = busLogService.selectList(query);
+        ExcelUtil<BusLog> util = new ExcelUtil<BusLog>(BusLog. class);
+        util.exportExcel(response, list, "操作日志数据");
+    }
+
+    /**
+    * 获取导入模板
+    * @param response
+    */
+    @PostMapping("/template-busLog")
+    public void importTemplate(HttpServletResponse response)
+    {
+        ExcelUtil<BusLog> util = new ExcelUtil<BusLog>(BusLog.class);
+        util.importTemplateExcel(response, "操作日志");
+    }
+
+    /**
+     * 获取操作日志详细信息
+     */
+    @GetMapping(value = "/query-log")
+    public void queryLog(@RequestParam String modelName) throws UnsupportedEncodingException {
+        SysBusLogUtil.log(modelName, true,null, SysBusLogUtil.ACT_TYPE_RETRIEVE);
+    }
+
+
+}

+ 72 - 0
wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/system/dao/BusLogMapper.java

@@ -0,0 +1,72 @@
+package cn.gov.customs.wxjy.system.dao;
+
+import java.util.List;
+
+import org.apache.ibatis.annotations.Mapper;
+import cn.gov.customs.wxjy.system.pojo.BusLog;
+import cn.gov.customs.wxjy.system.pojo.BusLogQuery;
+
+/**
+ * 操作日志Mapper接口
+ *
+ * @author xiong
+ * @date 2025-12-30
+ */
+@Mapper
+public interface BusLogMapper {
+    /**
+     * 查询操作日志
+     *
+     * @param id 操作日志主键
+     * @return 操作日志
+     */
+    public BusLog selectById(String id);
+
+    /**
+     * 查询操作日志列表
+     *
+     * @param busLog 操作日志
+     * @return 操作日志集合
+     */
+    public List<BusLog> selectList(BusLogQuery busLog);
+
+    /**
+     * 新增操作日志
+     *
+     * @param busLog 操作日志
+     * @return 结果
+     */
+    public int insert(BusLog busLog);
+
+    /**
+     * 修改操作日志
+     *
+     * @param busLog 操作日志
+     * @return 结果
+     */
+    public int update(BusLog busLog);
+
+    /**
+     * 删除操作日志
+     *
+     * @param id 操作日志主键
+     * @return 结果
+     */
+    public int deleteById(String id);
+
+    /**
+     * 批量删除操作日志
+     *
+     * @param ids 需要删除的数据主键集合
+     * @return 结果
+     */
+    public int deleteByIds(String[] ids);
+
+    /**
+     * 逻辑删除操作日志
+     *
+     * @param id 操作日志主键
+     * @return 结果
+     */
+    public int logicDelete(String id);
+}

+ 53 - 0
wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/system/pojo/BusLog.java

@@ -0,0 +1,53 @@
+package cn.gov.customs.wxjy.system.pojo;
+
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
+import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
+import lombok.Data;
+import cn.gov.customs.wxjy.common.annotation.Excel;
+import cn.gov.customs.wxjy.common.core.domain.BaseEntity;
+
+/**
+ * 操作日志对象 SYS_BUS_LOG
+ *
+ * @author xiong
+ * @date 2025-12-30
+ */
+@Data
+public class BusLog extends BaseEntity {
+private static final long serialVersionUID = 1L;
+
+    /** 主键 */
+    private String id;
+
+    /** 日志类型:1-登录日志,2-操作日志(如模块内的增删改查),3-查询日志, */
+    @Excel(name = "日志类型:1-登录日志,2-操作日志", readConverterExp = "如=模块内的增删改查")
+    private String type;
+
+    /** 日志主题 */
+    @Excel(name = "日志主题")
+    private String subject;
+
+    /** 日志详细内容,通常作为补充描述 */
+    @Excel(name = "日志详细内容,通常作为补充描述")
+    private String content;
+
+    /** 操作用户ID,如果ID<=0,则认为是系统用户(如
+SYSTEM) */
+    @Excel(name = "操作用户ID,如果ID<=0,则认为是系统用户", readConverterExp = "如= SYSTEM")
+    private String operUserId;
+
+    /** 操作用户所在机构ID */
+    @Excel(name = "操作用户所在机构ID")
+    private String operDeptId;
+
+    /** 客户端IP
+ */
+    @Excel(name = "客户端IP ")
+    private String clientIp;
+
+    /** 登录日志类型时:1-登录,2-登出;
+操作日志类型时,具体动作:C-新增,R-检索/查询,U-更新,D-删除 */
+    @Excel(name = "登录日志类型时:1-登录,2-登出; 操作日志类型时,具体动作:C-新增,R-检索/查询,U-更新,D-删除")
+    private String actType;
+
+}

+ 52 - 0
wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/system/pojo/BusLogQuery.java

@@ -0,0 +1,52 @@
+package cn.gov.customs.wxjy.system.pojo;
+
+import cn.gov.customs.wxjy.common.core.domain.BaseEntity;
+import lombok.Data;
+import java.io.Serializable;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import java.util.Date;
+
+/**
+ * 操作日志对象 SYS_BUS_LOG
+ *
+ * @author xiong
+ * @date 2025-12-30
+ */
+@Data
+public class BusLogQuery extends BaseEntity {
+
+    private static final long serialVersionUID = 1L;
+
+    /** 主键 */
+    private String id;
+
+    /** 日志类型:1-登录日志,2-操作日志(如模块内的增删改查),3-查询日志, */
+    private String type;
+
+    /** 日志主题 */
+    private String subject;
+
+    /** 日志详细内容,通常作为补充描述 */
+    private String content;
+
+    /** 操作用户ID,如果ID<=0,则认为是系统用户(如
+     SYSTEM) */
+    private String operUserId;
+
+    /** 操作用户所在机构ID */
+    private String operDeptId;
+
+    /** 客户端IP
+     */
+    private String clientIp;
+
+    /** 登录日志类型时:1-登录,2-登出;
+     操作日志类型时,具体动作:C-新增,R-检索/查询,U-更新,D-删除 */
+    private String actType;
+
+
+    private String beginDate;
+    private String endDate;
+    private int pageIndex;
+    private int pageSize;
+}

+ 89 - 0
wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/system/service/IBusLogService.java

@@ -0,0 +1,89 @@
+package cn.gov.customs.wxjy.system.service;
+
+import java.util.List;
+import cn.gov.customs.cacp.sdks.core.user.trans.CacpTransUser;
+import cn.gov.customs.wxjy.system.pojo.BusLog;
+import cn.gov.customs.wxjy.system.pojo.BusLogQuery;
+import com.github.pagehelper.PageInfo;
+
+/**
+ * 操作日志Service接口
+ *
+ * @author xiong
+ * @date 2025-12-30
+ */
+public interface IBusLogService {
+    /**
+     * 查询操作日志
+     *
+     * @param id 操作日志主键
+     * @return 操作日志
+     */
+    public BusLog selectById(String id);
+
+    /**
+     * 分页查询操作日志列表
+     *
+     * @param query
+     * @return 操作日志集合
+     */
+    public PageInfo<BusLog> selectPageList(BusLogQuery query);
+
+    /**
+     * 查询操作日志列表
+     *
+     * @param query
+     * @return 操作日志集合
+     */
+    public List<BusLog> selectList(BusLogQuery query);
+
+    /**
+     * 新增操作日志
+     *
+     * @param busLog 操作日志
+     * @return 结果
+     */
+    public int insert(BusLog busLog);
+
+    /**
+     * 修改操作日志
+     *
+     * @param busLog 操作日志
+     * @return 结果
+     */
+    public int update(BusLog busLog);
+
+    /**
+     * 批量删除操作日志
+     *
+     * @param ids 需要删除的ids主键集合
+     * @return 结果
+     */
+    public int deleteByIds(String[] ids);
+
+    /**
+     * 删除操作日志信息
+     *
+     * @param id 操作日志主键
+     * @return 结果
+     */
+    public int deleteById(String id);
+
+    /**
+     * 逻辑删除操作日志信息
+     *
+     * @param id 操作日志主键
+     * @return 结果
+     */
+    public int logicDelete(String id);
+
+    /**
+     * 导入操作日志数据
+     *
+     * @param busLogList 操作日志数据列表
+     * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据
+     * @param cacpTransUser 操作用户
+     * @return 结果
+     */
+    public String importBusLog(List<BusLog> busLogList, Boolean isUpdateSupport, CacpTransUser cacpTransUser);
+}

+ 172 - 0
wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/system/service/impl/BusLogServiceImpl.java

@@ -0,0 +1,172 @@
+package cn.gov.customs.wxjy.system.service.impl;
+
+import cn.gov.customs.cacp.sdks.core.user.trans.CacpTransUser;
+import cn.gov.customs.wxjy.common.exception.ServiceException;
+import cn.gov.customs.wxjy.common.utils.StringUtils;
+import cn.gov.customs.wxjy.common.utils.bean.BeanValidators;
+import cn.gov.customs.wxjy.common.utils.uuid.SnowflakeIdWorker;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.stereotype.Service;
+import javax.validation.Validator;
+import java.util.List;
+import org.apache.commons.collections4.CollectionUtils;
+import cn.gov.customs.wxjy.common.utils.DateUtils;
+import com.github.pagehelper.PageInfo;
+import cn.gov.customs.wxjy.common.utils.DateUtils;
+import cn.gov.customs.wxjy.system.dao.BusLogMapper;
+import cn.gov.customs.wxjy.system.pojo.BusLog;
+import cn.gov.customs.wxjy.system.pojo.BusLogQuery;
+import cn.gov.customs.wxjy.system.service.IBusLogService;
+
+/**
+ * 操作日志Service业务层处理
+ *
+ * @author xiong
+ * @date 2025-12-30
+ */
+@Service
+@Slf4j
+@RequiredArgsConstructor
+public class BusLogServiceImpl implements IBusLogService {
+
+    private final BusLogMapper busLogMapper;
+
+    private final Validator validator;
+
+    /**
+     * 查询操作日志
+     *
+     * @param id 操作日志主键
+     * @return 操作日志
+     */
+    @Override
+    public BusLog selectById(String id) {
+        return busLogMapper.selectById(id);
+    }
+
+    /**
+     * 分页查询操作日志列表
+     *
+     * @param query
+     * @return 操作日志
+     */
+    @Override
+    public PageInfo<BusLog> selectPageList(BusLogQuery query) {
+        return PageInfo.of(busLogMapper.selectList(query));
+    }
+
+    /**
+     * 查询操作日志列表
+     *
+     * @param query
+     * @return 操作日志
+     */
+    @Override
+    public List<BusLog> selectList(BusLogQuery query) {
+        return busLogMapper.selectList(query);
+    }
+
+    /**
+     * 新增操作日志
+     *
+     * @param busLog 操作日志
+     * @return 结果
+     */
+    @Override
+    public int insert(BusLog busLog) {
+            return busLogMapper.insert(busLog);
+    }
+
+    /**
+     * 修改操作日志
+     *
+     * @param busLog 操作日志
+     * @return 结果
+     */
+    @Override
+    public int update(BusLog busLog) {
+        return busLogMapper.update(busLog);
+    }
+
+    /**
+     * 批量删除操作日志
+     *
+     * @param ids 需要删除的操作日志主键
+     * @return 结果
+     */
+    @Override
+    public int deleteByIds(String[] ids) {
+        return busLogMapper.deleteByIds(ids);
+    }
+
+    /**
+     * 删除操作日志信息
+     *
+     * @param id 操作日志主键
+     * @return 结果
+     */
+    @Override
+    public int deleteById(String id) {
+        return busLogMapper.deleteById(id);
+    }
+
+    /**
+     * 逻辑删除操作日志信息
+     *
+     * @param id 操作日志主键
+     * @return 结果
+     */
+    @Override
+    public int logicDelete(String id) {
+
+        return busLogMapper.logicDelete(id);
+    }
+
+    /**
+     * 导入操作日志数据
+     *
+     * @param busLogList 操作日志数据列表
+     * @param isUpdateSupport 是否更新支持,如果已存在,则进行更新数据
+     * @param cacpTransUser 操作用户
+     * @return 结果
+     */
+    @Override
+    public String importBusLog(List<BusLog> busLogList, Boolean isUpdateSupport, CacpTransUser cacpTransUser) {
+        if (CollectionUtils.isEmpty(busLogList)) {
+            throw new ServiceException("导入数据不能为空!");
+        }
+        int successNum = 0;
+        int failureNum = 0;
+        StringBuilder successMsg = new StringBuilder();
+        StringBuilder failureMsg = new StringBuilder();
+        for (BusLog busLog : busLogList) {
+            try {
+
+                BeanValidators.validateWithException(validator, busLog);
+                //id名称不统一,自行处理
+                busLog.setCreateTime(DateUtils.getNowDate());
+                busLog.setUpdateTime(DateUtils.getNowDate());
+                busLog.setCreateUser(cacpTransUser.getUserId());
+                busLog.setCreateDept(cacpTransUser.getParentGuid());
+
+                busLogMapper.insert(busLog);
+                successNum++;
+                successMsg.append("<br/>" + successNum + "、 " + cacpTransUser.getUserName() + " 导入成功");
+
+            } catch (Exception e) {
+                failureNum++;
+                String msg = "<br/>" + failureNum + "、" + cacpTransUser.getUserName() + " 导入失败:";
+                failureMsg.append(msg + e.getMessage());
+                log.error(msg, e);
+            }
+        }
+        if (failureNum > 0) {
+            failureMsg.insert(0, "很抱歉,导入失败!共 " + failureNum + " 条数据格式不正确,错误如下:");
+            throw new ServiceException(failureMsg.toString());
+        } else {
+            successMsg.insert(0, "恭喜您,数据已全部导入成功!共 " + successNum + " 条,数据如下:");
+        }
+        return successMsg.toString();
+    }
+}

+ 152 - 0
wxjy-wxjy-service/src/main/java/cn/gov/customs/wxjy/utils/SysBusLogUtil.java

@@ -0,0 +1,152 @@
+package cn.gov.customs.wxjy.utils;
+
+import cn.gov.customs.cacp.sdks.core.user.trans.CacpTransUser;
+import cn.gov.customs.cacp.sdks.core.user.trans.UserContextHolder;
+import cn.gov.customs.cacp.sdks.hgid.HgidGenerator;
+import cn.gov.customs.wxjy.common.utils.StringUtils;
+import cn.gov.customs.wxjy.system.pojo.BusLog;
+import cn.gov.customs.wxjy.system.service.IBusLogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.io.UnsupportedEncodingException;
+import java.util.Date;
+
+@Component
+public class SysBusLogUtil {
+    public static final String TYPE_LOGIN = "1";
+    public static final String TYPE_OPER = "2";
+    public static final String TYPE_QUERY = "3";
+    public static final String STATUS_SUCCESS = "1";
+    public static final String STATUS_FAILURE = "0";
+    public static final String ACT_TYPE_LOGIN = "1";
+    public static final String ACT_TYPE_LOGOUT = "2";
+    /**
+     * @param: 操作指令
+     */
+    public static final String ACT_TYPE_CREATE = "C";//发起申请
+    public static final String ACT_TYPE_UPDATE = "U";//修改申请
+    public static final String ACT_TYPE_SUBMIT = "S";//发布申请
+    public static final String ACT_TYPE_RETRIEVE = "R";//撤回申请
+    public static final String ACT_TYPE_DELETE = "D";//删除申请
+    public static final String ACT_TYPE_QUERY = "Q" ;//查询
+    public static final String ACT_TYPE_IMPORT = "I"; //导入
+    public static final String ACT_TYPE_EXPORT = "E"; //导出
+    
+    private final IBusLogService service;
+    @Autowired
+    private final HgidGenerator idHelper;
+    // 静态实例引用
+    private static SysBusLogUtil instance;
+
+    // 使用构造器注入,避免循环依赖
+    @Autowired
+    public SysBusLogUtil(IBusLogService service,HgidGenerator idHelper) {
+        this.service = service;
+        this.idHelper = idHelper;
+        // 设置静态实例
+        instance = this;
+    }
+
+    /**
+     * 登陆日志
+     * @param subject 模块名称
+     * @param content
+     * @param status
+     */
+    public static void addLoginLog(String subject, String content, String status) {
+        BusLog log = handLogInfo(TYPE_LOGIN,subject,content);
+        if (StringUtils.isNotEmpty(status)) {
+            log.setStatus(status);
+        } else {
+            log.setStatus(STATUS_SUCCESS);
+        }
+        instance.service.insert(log);
+    }
+
+    /**
+     *  操作日志
+     * @param subject 日志主题
+     * @param content
+     * @param actType  见常量注释
+     * @param status 操作状态:1-成功,0-失败
+     */
+    public static void addBusLog(String subject, String content, String actType, String status) {
+        BusLog operaLog = handLogInfo(TYPE_OPER,subject,content);
+        if (StringUtils.isNotEmpty(actType)) {
+            operaLog.setActType(actType);
+        } else {
+            operaLog.setActType(ACT_TYPE_QUERY);
+        }
+        if (StringUtils.isNotEmpty(status)) {
+            operaLog.setStatus(status);
+        } else {
+            operaLog.setStatus(STATUS_SUCCESS);
+        }
+        instance.service.insert(operaLog);
+    }
+
+    public static void addQueryLog(String subject, String content, String actType, String status) {
+        BusLog queryLog = handLogInfo(TYPE_QUERY,subject,content);
+        if (StringUtils.isNotEmpty(actType)) {
+            queryLog.setActType(actType);
+        } else {
+            queryLog.setActType(ACT_TYPE_QUERY);
+        }
+        if (StringUtils.isNotEmpty(status)) {
+            queryLog.setStatus(status);
+        } else {
+            queryLog.setStatus(STATUS_SUCCESS);
+        }
+        instance.service.insert(queryLog);
+    }
+
+    public static BusLog handLogInfo(String type, String subject, String content){
+        CacpTransUser user = UserContextHolder.currentUser();
+        BusLog log = new BusLog();
+        log.setId(instance.idHelper.nextId());
+        log.setType(type);
+        log.setSubject(subject);
+        log.setContent(content);
+        log.setOperUserId(user.getUserName());
+        log.setOperDeptId(user.getAllPath());
+        log.setClientIp(user.getUserIp());
+        log.setCreateTime(new Date());
+        return log;
+    }
+
+    /**
+     * 保存日志信息
+     * @param subject  模块名称
+     * @param isSession  是否操作成功
+     * @param targetId   操作数据id
+     * @param actType    操作类型
+     */
+    public static void log(String subject, boolean isSession, String targetId, String actType) throws UnsupportedEncodingException {
+        String flag = isSession? SysBusLogUtil.STATUS_SUCCESS: SysBusLogUtil.STATUS_FAILURE;
+        String content = "";  //操作说明
+        if(SysBusLogUtil.ACT_TYPE_RETRIEVE.equals(actType)){//查询
+            content = "查询-"+subject;
+        }else if(SysBusLogUtil.ACT_TYPE_UPDATE.equals(actType)){//修改
+            content = "修改-"+subject+": "+targetId;
+        }else if(SysBusLogUtil.ACT_TYPE_DELETE.equals(actType)){//删除
+            content = "删除-"+subject+": "+targetId;
+        }else if(SysBusLogUtil.ACT_TYPE_CREATE.equals(actType)){//新增
+            content = "新增-"+subject+": "+targetId;
+        }else if(SysBusLogUtil.ACT_TYPE_EXPORT.equals(actType)){// 导出
+            content = "导出-"+subject;
+        }else if(SysBusLogUtil.ACT_TYPE_IMPORT.equals(actType)){// 导入
+            content = "导入-"+subject;
+        }else{
+            //自定义日志标题/
+            content = actType;
+            actType = SysBusLogUtil.ACT_TYPE_UPDATE;
+        }
+        if(SysBusLogUtil.ACT_TYPE_RETRIEVE.equals(actType)){
+            SysBusLogUtil.addQueryLog(subject,content,actType,flag);
+        } else {
+            // 添加操作日志
+            SysBusLogUtil.addBusLog(subject, content, actType, flag);
+        }
+    }
+}

+ 6 - 6
wxjy-wxjy-service/src/main/resources/application.properties

@@ -1,5 +1,5 @@
 ## \u5F00\u53D1\u73AF\u5883\u914D\u7F6E
-# IBM MQ \u914D\u7F6E
+## IBM MQ \u914D\u7F6E
 ibm.mq.host=43.137.18.189
 ibm.mq.port=1414
 ibm.mq.user=admin
@@ -15,7 +15,7 @@ ibm.mq.channel=DEV.ADMIN.SVRCONN
 ibm.mq.send-queue=FZX.RECE.ENT.ZYZF
 # \u672C\u5730\u961F\u5217 \u63A5\u6536\u6D88\u606F
 ibm.mq.receive-queue=ENT.RECE.MNG.ZYZF
-#\u6D88\u606F\u53D1\u9001\u65B9\u6807\u8BC6
+\u6D88\u606F\u53D1\u9001\u65B9\u6807\u8BC6
 msg.sender-id=ZYZFCUST00000001
 # \u6D88\u606F\u63A5\u6536\u65B9\u6807\u8BC6(\u5982\u679C\u6709\u591A\u4E2A\uFF0C\u7528\u9017\u53F7\u5206\u9694)
 msg.receiver-id=ZYZFPLAT00000001
@@ -34,13 +34,13 @@ ibm.mq.file-upload-path=/data/swfzsb/files/uploadPath
 ### \u670D\u52A1\u5668\u8FDE\u63A5\u901A\u9053\u540D\u79F0
 #ibm.mq.channel=JAVA.CONN
 ## \u4F01\u4E1A\u7AEF\u53D1\u9001\u6D88\u606F\u961F\u5217\uFF08\u6D77\u5173\u7AEF\u63A5\u6536\u6D88\u606F\u961F\u5217-\u672C\u5730\u961F\u5217\uFF09
-#ibm.mq.send-queue=QL.ZHSJ_61_TO_173
+#ibm.mq.send-queue=QL.WXJY_61_TO_173
 ## \u4F01\u4E1A\u7AEF\u63A5\u6536\u6D88\u606F\u961F\u5217\uFF08\u6D77\u5173\u7AEF\u53D1\u9001\u6D88\u606F\u961F\u5217-\u8FDC\u7A0B\u961F\u5217\uFF09
-#ibm.mq.receive-queue=QR.ZHSJ_173_TO_61
+#ibm.mq.receive-queue=QR.WXJY_173_TO_61
 ## \u6D88\u606F\u53D1\u9001\u65B9\u6807\u8BC6
-#msg.sender-id=DXPSDC4700100070
+#msg.sender-id=DXPSDC4700100071
 ## \u6D88\u606F\u63A5\u6536\u65B9\u6807\u8BC6(\u5982\u679C\u6709\u591A\u4E2A\uFF0C\u7528\u9017\u53F7\u5206\u9694)
-#msg.receiver-id=DXPSDC4700ENT272
+#msg.receiver-id=DXPSDC4700ENT273
 ## \u63A8\u9001\u9644\u4EF6\u5730\u5740(\u6D77\u5173\u7AEFLinux\u670D\u52A1\u5668\u8DEF\u5F84)
 #ibm.mq.file-upload-path=/data/swfzsb/files/uploadPath
 

+ 168 - 0
wxjy-wxjy-service/src/main/resources/mapper/system/BusLogMapper.xml

@@ -0,0 +1,168 @@
+<?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="cn.gov.customs.wxjy.system.dao.BusLogMapper">
+
+    <resultMap type="BusLog" id="BusLogResult">
+        <result property="id" column="ID"/>
+        <result property="type" column="TYPE"/>
+        <result property="subject" column="SUBJECT"/>
+        <result property="content" column="CONTENT"/>
+        <result property="operUserId" column="OPER_USER_ID"/>
+        <result property="operDeptId" column="OPER_DEPT_ID"/>
+        <result property="status" column="STATUS"/>
+        <result property="createTime" column="CREATE_TIME"/>
+        <result property="clientIp" column="CLIENT_IP"/>
+        <result property="actType" column="ACT_TYPE"/>
+    </resultMap>
+
+    <sql id="baseVo">
+        select ID, TYPE, SUBJECT, CONTENT, OPER_USER_ID, OPER_DEPT_ID, STATUS, CREATE_TIME, CLIENT_IP, ACT_TYPE
+        from SYS_BUS_LOG
+    </sql>
+
+    <select id="selectList" parameterType="BusLogQuery" resultMap="BusLogResult">
+        <include refid="baseVo"/>
+        <where>
+            <if test="type != null  and type != ''">
+                and TYPE = #{type}
+            </if>
+            <if test="subject != null  and subject != ''">
+                and SUBJECT = #{subject}
+            </if>
+            <if test="content != null  and content != ''">
+                and CONTENT = #{content}
+            </if>
+            <if test="operUserId != null  and operUserId != ''">
+                and OPER_USER_ID like concat(concat('%', #{operUserId} ),'%')
+            </if>
+            <if test="operDeptId != null  and operDeptId != ''">
+                and OPER_DEPT_ID = #{operDeptId}
+            </if>
+            <if test="status != null  and status != ''">
+                and STATUS = #{status}
+            </if>
+            <if test="createTime != null  and createTime != ''">
+                and CREATE_TIME = #{createTime}
+            </if>
+            <if test="clientIp != null  and clientIp != ''">
+                and CLIENT_IP = #{clientIp}
+            </if>
+            <if test="actType != null  and actType != ''">
+                and ACT_TYPE = #{actType}
+            </if>
+            <if test="beginDate != null and beginDate != ''">
+                and date_format(CREATE_TIME,'%y%m%d') &gt;= date_format(#{beginDate},'%y%m%d')
+            </if>
+            <if test="endDate != null and endDate != ''">
+                and date_format(CREATE_TIME,'%y%m%d') &lt;= date_format(#{endDate},'%y%m%d')
+            </if>
+        </where>
+        order by CREATE_TIME desc
+    </select>
+
+    <select id="selectById" parameterType="String"
+            resultMap="BusLogResult">
+        <include refid="baseVo"/>
+        where ID = #{id}
+    </select>
+
+    <insert id="insert" parameterType="BusLog">
+        insert into SYS_BUS_LOG
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="id != null and id != ''">ID,
+            </if>
+            <if test="type != null and type != ''">TYPE,
+            </if>
+            <if test="subject != null and subject != ''">SUBJECT,
+            </if>
+            <if test="content != null">CONTENT,
+            </if>
+            <if test="operUserId != null and operUserId != ''">OPER_USER_ID,
+            </if>
+            <if test="operDeptId != null">OPER_DEPT_ID,
+            </if>
+            <if test="status != null">STATUS,
+            </if>
+            <if test="createTime != null ">CREATE_TIME,
+            </if>
+            <if test="clientIp != null">CLIENT_IP,
+            </if>
+            <if test="actType != null">ACT_TYPE,
+            </if>
+        </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="id != null and id != ''">#{id},
+            </if>
+            <if test="type != null and type != ''">#{type},
+            </if>
+            <if test="subject != null and subject != ''">#{subject},
+            </if>
+            <if test="content != null">#{content},
+            </if>
+            <if test="operUserId != null and operUserId != ''">#{operUserId},
+            </if>
+            <if test="operDeptId != null">#{operDeptId},
+            </if>
+            <if test="status != null">#{status},
+            </if>
+            <if test="createTime != null">#{createTime},
+            </if>
+            <if test="clientIp != null">#{clientIp},
+            </if>
+            <if test="actType != null">#{actType},
+            </if>
+        </trim>
+    </insert>
+
+    <update id="update" parameterType="BusLog">
+        update SYS_BUS_LOG
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="type != null and type != ''">TYPE =
+                #{type},
+            </if>
+            <if test="subject != null and subject != ''">SUBJECT =
+                #{subject},
+            </if>
+            <if test="content != null">CONTENT =
+                #{content},
+            </if>
+            <if test="operUserId != null and operUserId != ''">OPER_USER_ID =
+                #{operUserId},
+            </if>
+            <if test="operDeptId != null">OPER_DEPT_ID =
+                #{operDeptId},
+            </if>
+            <if test="status != null">STATUS =
+                #{status},
+            </if>
+            <if test="createTime != null and createTime != ''">CREATE_TIME =
+                #{createTime},
+            </if>
+            <if test="clientIp != null">CLIENT_IP =
+                #{clientIp},
+            </if>
+            <if test="actType != null">ACT_TYPE =
+                #{actType},
+            </if>
+        </trim>
+        where ID = #{id}
+    </update>
+
+    <delete id="deleteById" parameterType="String">
+        delete
+        from SYS_BUS_LOG where ID = #{id}
+    </delete>
+
+    <delete id="deleteByIds" parameterType="String">
+        delete from SYS_BUS_LOG where ID in
+        <foreach item="id" collection="array" open="(" separator="," close=")">
+            #{id}
+        </foreach>
+    </delete>
+
+    <delete id="logicDelete" parameterType="String">
+        update  SYS_BUS_LOG set is_del = 1  where ID = #{id}
+    </delete>
+</mapper>

+ 2 - 2
wxjy-wxjy-web/public/config.js

@@ -1,7 +1,7 @@
 //项目部署上线后使用此配置
 window.$config = {
-  SERVICE_ID: 'WXJY-WXJY-WEB', //应用服务Id,同CACPAppCode
-  SERVICE_NAME: 'wxjy-wxjy-web', //应用服务名
+  SERVICE_ID: 'wxjy-wxjy-service', //应用服务Id,同CACPAppCode
+  SERVICE_NAME: 'wxjy-wxjy-service', //应用服务名
   SERVICE_PAGESIZE: 20,
   SERVICE_API: '/api/wxjy-wxjy-service',//当前应用api地址,上线需要修改
   SERVICE_TIMEOUT: 300000, //请求超时时间

+ 23 - 0
wxjy-wxjy-web/src/App.vue

@@ -87,6 +87,29 @@
           </router-link>
         </el-sub-menu>
 
+        <el-sub-menu index="busLog">  <!-- index 为父菜单唯一标识(非路由路径) -->
+          <template #title>
+            <el-icon><Setting /></el-icon>  <!-- 父菜单图标 -->
+            <span>日志管理</span>  <!-- 父菜单名称 -->
+          </template>
+          <router-link to="/bus-operaLog">
+            <el-menu-item index="BusOperaLog" class="menu-item">
+              <el-icon>
+                <ScaleToOriginal />
+              </el-icon>
+              <span>操作日志</span>
+            </el-menu-item>
+          </router-link>
+          <router-link to="/bus-queryLog">
+            <el-menu-item index="BusQueryLog" class="menu-item">
+              <el-icon>
+                <ScaleToOriginal />
+              </el-icon>
+              <span>查询日志</span>
+            </el-menu-item>
+          </router-link>
+        </el-sub-menu>
+
         <router-link to="/user-info">
           <el-menu-item index="UserInfo">
             <el-icon><User /></el-icon>

+ 57 - 0
wxjy-wxjy-web/src/apis/accessory.ts

@@ -0,0 +1,57 @@
+import type { AxiosResponse } from 'axios'
+import download from 'js-file-download'
+import config from '@/config'
+
+import request from '@/utils/request'
+import type { Accessory } from '@/types/accessory'
+import { SuccessResultCode, type Result } from '@cacp/ui'
+
+const contextPath = '/accessory'
+
+export function getUploadUrl(): string {
+  if (config.SERVICE_API.endsWith('/')) {
+    return `${config.SERVICE_API.substring(0, config.SERVICE_API.length - 1)}${contextPath}/upload-file`
+  } else {
+    return `${config.SERVICE_API}/${contextPath}/upload-file`
+  }
+}
+
+export function getDownloadUrl(accessoryId: string): string {
+  if (config.SERVICE_API.endsWith('/')) {
+    return `${config.SERVICE_API.substring(0, config.SERVICE_API.length - 1)}${contextPath}/download-file?accessoryId=${accessoryId}`
+  } else {
+    return `${config.SERVICE_API}${contextPath}/download-file?accessoryId=${accessoryId}`
+  }
+}
+
+export async function downloadFile(accessoryId: string, fileName: string): Promise<void> {
+  const res: AxiosResponse<Result<any>> = await request.get(`${contextPath}/download-file`, {
+    params: { accessoryId: accessoryId },
+    responseType: 'arraybuffer'
+  })
+
+  if (res.data.code === SuccessResultCode) {
+    download(res.data.data, fileName, 'application/octet-stream')
+  }
+}
+
+export async function deleteFile(accessoryId: string): Promise<Result<number>> {
+  const res: AxiosResponse<Result<number>> = await request.post(`${contextPath}/delete-file`, {
+    params: { accessoryId: accessoryId }
+  })
+  return res.data
+}
+
+export async function getPersistListByBizId(bizId: string): Promise<Result<Array<Accessory>>> {
+  const res: AxiosResponse<Result<Array<Accessory>>> = await request.get(`${contextPath}/get-persist-list-by-biz-id`, {
+    params: { bizId: bizId }
+  })
+  return res.data
+}
+
+export async function getPersistListByRelId(bizId: string, relId: string): Promise<Result<Array<Accessory>>> {
+  const res: AxiosResponse<Result<Array<Accessory>>> = await request.get(`${contextPath}/get-persist-list-by-rel-id`, {
+    params: { bizId: bizId, relId: relId }
+  })
+  return res.data
+}

+ 46 - 0
wxjy-wxjy-web/src/apis/system/BusLog.ts

@@ -0,0 +1,46 @@
+import type { AxiosResponse } from 'axios'
+import type { PageInfo, Result } from '@cacp/ui'
+import request from '@/utils/request'
+
+import type {BusLog,BusLogQuery}  from '@/types/system/BusLog'
+
+const contextPath = '/system/BusLog'
+
+// 查询操作日志列表
+export async function getList(query: BusLogQuery): Promise<Result<PageInfo<BusLog>>> {
+  const res: AxiosResponse<Result<PageInfo<BusLog>>> = await request.post(`${contextPath}/get-list`, query)
+  return res.data
+}
+
+// 获取操作日志详情
+export async function getDetail(id: string): Promise<Result<BusLog>> {
+  const res: AxiosResponse<Result<BusLog>> = await request.get(`${contextPath}/get-detail?id=${id}`)
+  return res.data
+}
+
+// 新增操作日志
+export async function insert(row: BusLog): Promise<Result<number>> {
+  const res: AxiosResponse<Result<number>> = await request.post(`${contextPath}/insert-busLog`, row)
+  return res.data
+}
+
+// 更新操作日志
+export async function update(row: BusLog): Promise<Result<number>> {
+  const res: AxiosResponse<Result<number>> = await request.post(`${contextPath}/update-busLog`, row)
+  return res.data
+}
+
+// 删除操作日志
+export async function remove(busLogs: string | string[]): Promise<Result<number>> {
+  // 统一转换为数组格式
+  const ids = Array.isArray(busLogs) ? busLogs : [busLogs];
+  const res: AxiosResponse<Result<number>> = await request.post(
+          `${contextPath}/delete-busLog?ids`,ids
+  )
+  return res.data
+}
+
+// 查询日志
+export async function recordQueryLog(modelName: string): Promise<void> {
+   await request.get(`${contextPath}/query-log?modelName=${modelName}`)
+}

+ 3 - 2
wxjy-wxjy-web/src/components/accessory/AccessoryUploader.vue

@@ -55,7 +55,7 @@
 import { ref, computed, provide } from 'vue'
 import {
   type UploadFile,
-  type UploadFiles,
+  // type UploadFiles,
   type UploadUserFile,
   type UploadProps,
   type UploadContentInstance,
@@ -181,7 +181,8 @@ function onAbort(file: UploadUserFile): void {
   uploadingFiles.value = uploadingFiles.value.filter((uploadFile) => uploadFile !== file)
 }
 
-const onUploadChange: UploadProps['onChange'] = (file: UploadFile, files: UploadFiles): void => {
+//, files: UploadFiles
+const onUploadChange: UploadProps['onChange'] = (file: UploadFile): void => {
   if (file.status === 'ready') {
     uploadData.value.fileName = file.name
   } else if (file.status === 'success' || file.status === 'fail') {

+ 1 - 1
wxjy-wxjy-web/src/main.ts

@@ -49,7 +49,7 @@ app.use(router)
 app.use(plugins)
 app.use(directives)
 app.use(pinia)
-app.use(DynamicColumnDialog)
+app.component('DynamicColumnDialog',DynamicColumnDialog)
 app.component('DictTag', DictTag)
 // 绑定message监听,addEventListener中调用了store,所以需要放在app.use(pinia)之后调用。
 addEventListener(bridge)

+ 18 - 0
wxjy-wxjy-web/src/router/app-router.ts

@@ -125,6 +125,24 @@ const routers: Array<RouteRecordRaw> = [
       permissions:"CHEMICALS_CATALOG_VIEW_BT"
     }
   },
+  {
+    path: '/bus-operaLog',
+    name: 'BusOperaLog',
+    component: () => import('@/views/system/BusOperaLog.vue'),
+    meta: {
+      title: '操作日志',
+      permissions:"BUS_OPERA_LOG_VIEW_BT"
+    }
+  },
+  {
+    path: '/bus-queryLog',
+    name: 'BusQueryLog',
+    component: () => import('@/views/system/BusQueryLog.vue'),
+    meta: {
+      title: '危化品目录',
+      permissions:"BUS_QUERY_LOG_VIEW_BT"
+    }
+  },
 ]
 
 export default routers

+ 4 - 0
wxjy-wxjy-web/src/router/index.ts

@@ -1,6 +1,7 @@
 import { createRouter, createWebHashHistory, RouterView } from 'vue-router'
 import { useCoreStore } from '@/stores'
 import appRouter from './app-router'
+import { recordQueryLog } from '@/apis/system/BusLog'
 
 const { DEV } = import.meta.env
 
@@ -70,12 +71,15 @@ router.beforeEach(async (to, from, next) => {
   }
   if (DEV || !to.meta?.permissions) {
     next()
+    //本地不记录查询日志
+    // await recordQueryLog(to.meta.title as string)
     return
   }
   const permissions: Array<string> = (to.meta.permissions as string).split(',')
   const authorities = coreStore.userAuthority?.permissions ?? []
   if (authorities.some((a) => permissions.includes(a.code))) {
     next()
+    await recordQueryLog(to.meta.title as string)
   } else {
     next({
       path: '/error'

+ 29 - 0
wxjy-wxjy-web/src/types/system/BusLog.ts

@@ -0,0 +1,29 @@
+// 操作日志
+export interface BusLog {
+  id?: string
+  type?: string
+  subject?: string
+  content?: string
+  operUserId?: string
+  operDeptId?: string
+  clientIp?: string
+  actType?: string
+  createTime?: string
+}
+
+// 操作日志查询参数
+export interface BusLogQuery {
+  type?: string
+  subject?: string
+  content?: string
+  operUserId?: string
+  operDeptId?: string
+  clientIp?: string
+  actType?: string
+  createTime?: string
+  beginDate?: string
+  endDate?: string
+  pageIndex?: number
+  pageSize?: number
+
+}

+ 288 - 0
wxjy-wxjy-web/src/views/system/BusOperaLog.vue

@@ -0,0 +1,288 @@
+<template>
+  <cacp-search-layout>
+    <template #search>
+      <cacp-search-panel-layout
+        :model="state.queryData"
+        ref="queryFormRef"
+        label-position="left"
+        label-width="auto"
+        :gutter="30"
+        :colSpan="6"
+      >
+        <el-form-item label="操作用户" prop="operUserId">
+          <el-input v-model="state.queryData.operUserId" clearable />
+        </el-form-item>
+        <el-form-item label="操作类型" prop="actType">
+          <el-select v-model="state.queryData.actType" clearable>
+            <el-option v-for="item in dict.bus_log" :key="item.dictValue" :label="item.dictLabel"
+                       :value="item.dictValue" />
+          </el-select>
+        </el-form-item>
+        <el-form-item label="操作时间">
+          <el-date-picker
+            type="date"
+            value-format="YYYY-MM-DD"
+            v-model="state.queryData.beginDate"
+            placeholder="开始时间"
+          />
+        </el-form-item>
+        <el-form-item label="到">
+          <el-date-picker
+            type="date"
+            value-format="YYYY-MM-DD"
+            v-model="state.queryData.endDate"
+            placeholder="结束时间"
+          />
+        </el-form-item>
+        <template #buttonGroup>
+          <el-button type="primary" @click="onSearch">查询</el-button>
+          <el-button type="info" @click="onReset">重置</el-button>
+        </template>
+      </cacp-search-panel-layout>
+    </template>
+
+    <cacp-complex-table
+      :actions="actions"
+      :data="tableData"
+      :pagination="tablePagination"
+      :actionsWidth="120"
+      @selection-change="handleSelectionChange"
+      @on-page-change="onPageChange"
+      @on-size-change="onSizeChange"
+      :loading="loading"
+    >
+      <el-table-column label="序号" property="index" width="60" align="center" >
+        <template #default="scope">
+          {{scope.$index + 1}}
+        </template>
+      </el-table-column>
+      <el-table-column property="subject" label="操作模块"  :show-overflow-tooltip="true" />
+      <el-table-column property="content" label="日志详情"  :show-overflow-tooltip="true" />
+      <el-table-column property="operUserId" label="操作用户"  :show-overflow-tooltip="true" />
+      <el-table-column property="operDeptId" label="操作用户机构" :show-overflow-tooltip="true" />
+<!--      <el-table-column property="status" label="操作状态:1-成功,0-失败" width="120" :show-overflow-tooltip="true" />-->
+      <el-table-column property="clientIp" label="客户端IP" width="180" :show-overflow-tooltip="true" />
+      <el-table-column property="createTime" label="操作时间" width="180" :show-overflow-tooltip="true" />
+      <el-table-column property="actType" label="操作类型" width="120" :show-overflow-tooltip="true" >
+        <template #default="scope">
+          <dict-tag :options="dict.bus_log" :dict-value="scope.row.actType" />
+        </template>
+      </el-table-column>
+    </cacp-complex-table>
+  </cacp-search-layout>
+
+  <!--查看弹框-->
+  <cacp-dialog
+    v-model="state.viewDialogVisible"
+    :resizable="false"
+    :title="state.viewTitle"
+    width="50%"
+  >
+    <el-form
+      :model="state.viewForm"
+      label-width="auto"
+      label-position="left"
+      :disabled="true"
+    >
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="操作模块:" prop="subject">
+            <span>{{ state.viewForm.subject || '-' }}</span>
+          </el-form-item>
+        </el-col>
+      <el-col :span="12">
+        <el-form-item label="操作详情:" prop="content">
+          <span>{{ state.viewForm.content || '-' }}</span>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="操作用户:" prop="operUserId">
+          <span>{{ state.viewForm.operUserId || '-' }}</span>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="操作用户机构:" prop="operDeptId">
+          <span>{{ state.viewForm.operDeptId || '-' }}</span>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="操作时间:" prop="createTime">
+          <span>{{ state.viewForm.createTime || '-' }}</span>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="客户端IP:" prop="clientIp">
+          <span>{{ state.viewForm.clientIp || '-' }}</span>
+        </el-form-item>
+      </el-col>
+      <el-col :span="12">
+        <el-form-item label="操作类型:" prop="actType">
+          <dict-tag :options="dict.bus_log" :dict-value="state.viewForm.actType" />
+        </el-form-item>
+      </el-col>
+    </el-row>
+    </el-form>
+  </cacp-dialog>
+</template>
+
+<script lang="ts" setup>
+import { onMounted, reactive, ref } from 'vue'
+import { ElMessage } from 'element-plus'
+import config from '@/config'
+import {
+  SuccessResultCode,
+  useComplexTable,
+  type SearchPanelLayoutInstance,
+  type TableAction,
+  useLoading
+} from '@cacp/ui'
+import type { BusLog, BusLogQuery } from '@/types/system/BusLog'
+import {  getList} from '@/apis/system/BusLog'
+import { permissionStatus } from '@/utils/globalPermission'
+import DictTag from '@/components/DictTag/dictTag.vue'
+import { useDictType } from '@/components/useDict'
+const { dict } = useDictType('bus_log')
+
+// 表单引用
+const queryFormRef = ref<SearchPanelLayoutInstance>()
+
+// 加载状态
+const { loading, setLoading } = useLoading()
+
+// 表格 Hook
+const tableHooks = useComplexTable<BusLog>(config)
+const { tableData, tablePagination, setPagination, setPageIndex, setPageSizes } = tableHooks
+
+// 响应式数据
+interface State {
+  queryData: BusLogQuery
+  formData: BusLog
+  viewForm: BusLog
+  viewTitle: string
+  viewDialogVisible: boolean
+  title: string
+  isEdit: boolean
+  dialogVisible: boolean
+}
+
+const state = reactive<State>({
+  queryData: {
+    type: '2',
+    subject: '',
+    content: '',
+    operUserId: '',
+    operDeptId: '',
+    createTime: '',
+    clientIp: '',
+    actType: '',
+    pageIndex: tablePagination.currentPage,
+    pageSize: tablePagination.pageSize
+  },
+  formData: {
+    id: '',
+    type: '',
+    subject: '',
+    content: '',
+    operUserId: '',
+    operDeptId: '',
+    status: '',
+    createTime: '',
+    clientIp: '',
+    actType: '',
+  } as BusLog,
+  viewForm: {} as BusLog,
+  viewTitle: '',
+  viewDialogVisible: false,
+  title: '',
+  isEdit: false,
+  dialogVisible: false,
+})
+
+// 表格操作按钮配置
+const actions = <Array<TableAction>>[
+  {
+    key: 'view',
+    text: '查看',
+    onclick: onView,
+    limit: 'one',
+    // limit: permissionStatus('one', 'BUS_OPERA_LOG_VIEW_BT'),
+    type: 'primary'
+  },
+]
+
+// 选中项的 ID 数组
+const ids = ref<string[]>([])
+
+// 多选框选中数据
+function handleSelectionChange(selection: BusLog[]) {
+  ids.value = selection
+    .map(item => item.id)
+    .filter((id): id is string => id != null && id !== undefined)
+}
+
+// 搜索方法
+const onSearch = () => {
+  setPageIndex(1)
+  onLoadData()
+}
+
+// 重置方法
+const onReset = () => {
+  queryFormRef.value?.resetFields()
+  state.queryData.beginDate = ''
+  state.queryData.endDate = ''
+  onPageChange(1)
+}
+
+// 每页显示条数变化
+const onSizeChange = (size: number) => {
+  setPageSizes(size)
+  onLoadData()
+}
+
+// 翻页查询
+const onPageChange = (currentPage: number) => {
+  setPageIndex(currentPage)
+  onLoadData()
+}
+
+// 查看
+function onView(row: BusLog) {
+  state.viewForm = { ...row }
+  state.viewDialogVisible = true
+  state.viewTitle = '查看操作日志详情'
+}
+
+// 数据查询
+async function onLoadData() {
+  setLoading(true)
+  try {
+    const query = {
+      ...state.queryData,
+      pageIndex: tablePagination.currentPage,
+      pageSize: tablePagination.pageSize
+    }
+    const res = await getList(query)
+    if (res.code === SuccessResultCode) {
+      setPagination(res.data)
+    } else {
+      ElMessage.error(res.message || '查询失败')
+    }
+  } catch (error) {
+    console.error('查询失败:', error)
+    ElMessage.error('查询失败')
+  } finally {
+    setLoading(false)
+  }
+}
+
+
+// 组件挂载时加载数据
+onMounted(() => {
+  onLoadData()
+})
+</script>
+
+<style scoped>
+/* 自定义样式 */
+</style>

+ 282 - 0
wxjy-wxjy-web/src/views/system/BusQueryLog.vue

@@ -0,0 +1,282 @@
+<template>
+  <cacp-search-layout>
+    <template #search>
+      <cacp-search-panel-layout
+        :model="state.queryData"
+        ref="queryFormRef"
+        label-position="left"
+        label-width="auto"
+        :gutter="30"
+        :colSpan="6"
+      >
+        <el-form-item label="操作用户" prop="operUserId">
+          <el-input v-model="state.queryData.operUserId" clearable />
+        </el-form-item>
+        <el-form-item label="操作时间">
+          <el-date-picker
+            type="date"
+            value-format="YYYY-MM-DD"
+            v-model="state.queryData.beginDate"
+            placeholder="开始时间"
+          />
+        </el-form-item>
+        <el-form-item label="到">
+          <el-date-picker
+            type="date"
+            value-format="YYYY-MM-DD"
+            v-model="state.queryData.endDate"
+            placeholder="结束时间"
+          />
+        </el-form-item>
+        <template #buttonGroup>
+          <el-button type="primary" @click="onSearch">查询</el-button>
+          <el-button type="info" @click="onReset">重置</el-button>
+        </template>
+      </cacp-search-panel-layout>
+    </template>
+
+    <cacp-complex-table
+      :actions="actions"
+      :data="tableData"
+      :pagination="tablePagination"
+      :actionsWidth="120"
+      @selection-change="handleSelectionChange"
+      @on-page-change="onPageChange"
+      @on-size-change="onSizeChange"
+      :loading="loading"
+    >
+      <el-table-column label="序号" property="index" width="60" align="center" >
+        <template #default="scope">
+          {{scope.$index + 1}}
+        </template>
+      </el-table-column>
+      <el-table-column property="subject" label="操作模块"  :show-overflow-tooltip="true" />
+      <el-table-column property="content" label="日志详情"  :show-overflow-tooltip="true" />
+      <el-table-column property="operUserId" label="操作用户"  :show-overflow-tooltip="true" />
+      <el-table-column property="operDeptId" label="操作用户机构" :show-overflow-tooltip="true" />
+      <!--      <el-table-column property="status" label="操作状态:1-成功,0-失败" width="120" :show-overflow-tooltip="true" />-->
+      <el-table-column property="clientIp" label="客户端IP" width="180" :show-overflow-tooltip="true" />
+      <el-table-column property="createTime" label="操作时间" width="180" :show-overflow-tooltip="true" />
+<!--      <el-table-column property="actType" label="操作类型" width="120" :show-overflow-tooltip="true" >-->
+<!--        <template #default="scope">-->
+<!--          <dict-tag :options="dict.bus_log" :dict-value="scope.row.actType" />-->
+<!--        </template>-->
+<!--      </el-table-column>-->
+    </cacp-complex-table>
+  </cacp-search-layout>
+
+  <!--查看弹框-->
+  <cacp-dialog
+    v-model="state.viewDialogVisible"
+    :resizable="false"
+    :title="state.viewTitle"
+    width="50%"
+  >
+    <el-form
+      :model="state.viewForm"
+      label-width="auto"
+      label-position="left"
+      :disabled="true"
+    >
+      <el-row :gutter="20">
+        <el-col :span="12">
+          <el-form-item label="操作模块:" prop="subject">
+            <span>{{ state.viewForm.subject || '-' }}</span>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="操作详情:" prop="content">
+            <span>{{ state.viewForm.content || '-' }}</span>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="操作用户:" prop="operUserId">
+            <span>{{ state.viewForm.operUserId || '-' }}</span>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="操作用户机构:" prop="operDeptId">
+            <span>{{ state.viewForm.operDeptId || '-' }}</span>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="操作时间:" prop="createTime">
+            <span>{{ state.viewForm.createTime || '-' }}</span>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="客户端IP:" prop="clientIp">
+            <span>{{ state.viewForm.clientIp || '-' }}</span>
+          </el-form-item>
+        </el-col>
+        <el-col :span="12">
+          <el-form-item label="操作类型:" prop="actType">
+            <dict-tag :options="dict.bus_log" :dict-value="state.viewForm.actType" />
+          </el-form-item>
+        </el-col>
+      </el-row>
+    </el-form>
+  </cacp-dialog>
+</template>
+
+<script lang="ts" setup>
+import { onMounted, reactive, ref } from 'vue'
+import { ElMessage } from 'element-plus'
+import config from '@/config'
+import {
+  SuccessResultCode,
+  useComplexTable,
+  type SearchPanelLayoutInstance,
+  type TableAction,
+  useLoading
+} from '@cacp/ui'
+import type { BusLog, BusLogQuery } from '@/types/system/BusLog'
+import {  getList} from '@/apis/system/BusLog'
+import { permissionStatus } from '@/utils/globalPermission'
+import DictTag from '@/components/DictTag/dictTag.vue'
+import { useDictType } from '@/components/useDict'
+const { dict } = useDictType('bus_log')
+
+// 表单引用
+const queryFormRef = ref<SearchPanelLayoutInstance>()
+
+// 加载状态
+const { loading, setLoading } = useLoading()
+
+// 表格 Hook
+const tableHooks = useComplexTable<BusLog>(config)
+const { tableData, tablePagination, setPagination, setPageIndex, setPageSizes } = tableHooks
+
+// 响应式数据
+interface State {
+  queryData: BusLogQuery
+  formData: BusLog
+  viewForm: BusLog
+  viewTitle: string
+  viewDialogVisible: boolean
+  title: string
+  isEdit: boolean
+  dialogVisible: boolean
+}
+
+const state = reactive<State>({
+  queryData: {
+    type: '3',
+    subject: '',
+    content: '',
+    operUserId: '',
+    operDeptId: '',
+    createTime: '',
+    clientIp: '',
+    actType: '',
+    pageIndex: tablePagination.currentPage,
+    pageSize: tablePagination.pageSize
+  },
+  formData: {
+    id: '',
+    type: '',
+    subject: '',
+    content: '',
+    operUserId: '',
+    operDeptId: '',
+    status: '',
+    createTime: '',
+    clientIp: '',
+    actType: '',
+  } as BusLog,
+  viewForm: {} as BusLog,
+  viewTitle: '',
+  viewDialogVisible: false,
+  title: '',
+  isEdit: false,
+  dialogVisible: false,
+})
+
+// 表格操作按钮配置
+const actions = <Array<TableAction>>[
+  {
+    key: 'view',
+    text: '查看',
+    onclick: onView,
+    limit: 'one',
+    // limit: permissionStatus('one', 'BUS_OPERA_LOG_VIEW_BT'),
+    type: 'primary'
+  },
+]
+
+// 选中项的 ID 数组
+const ids = ref<string[]>([])
+
+// 多选框选中数据
+function handleSelectionChange(selection: BusLog[]) {
+  ids.value = selection
+    .map(item => item.id)
+    .filter((id): id is string => id != null && id !== undefined)
+}
+
+// 搜索方法
+const onSearch = () => {
+  setPageIndex(1)
+  onLoadData()
+}
+
+// 重置方法
+const onReset = () => {
+  queryFormRef.value?.resetFields()
+  state.queryData.beginDate = ''
+  state.queryData.endDate = ''
+  onPageChange(1)
+}
+
+// 每页显示条数变化
+const onSizeChange = (size: number) => {
+  setPageSizes(size)
+  onLoadData()
+}
+
+// 翻页查询
+const onPageChange = (currentPage: number) => {
+  setPageIndex(currentPage)
+  onLoadData()
+}
+
+// 查看
+function onView(row: BusLog) {
+  state.viewForm = { ...row }
+  state.viewDialogVisible = true
+  state.viewTitle = '查看操作日志详情'
+}
+
+// 数据查询
+async function onLoadData() {
+  setLoading(true)
+  try {
+    const query = {
+      ...state.queryData,
+      pageIndex: tablePagination.currentPage,
+      pageSize: tablePagination.pageSize
+    }
+    const res = await getList(query)
+    if (res.code === SuccessResultCode) {
+      setPagination(res.data)
+    } else {
+      ElMessage.error(res.message || '查询失败')
+    }
+  } catch (error) {
+    console.error('查询失败:', error)
+    ElMessage.error('查询失败')
+  } finally {
+    setLoading(false)
+  }
+}
+
+
+// 组件挂载时加载数据
+onMounted(() => {
+  onLoadData()
+})
+</script>
+
+<style scoped>
+/* 自定义样式 */
+</style>

+ 1 - 1
wxjy-wxjy-web/vite.config.ts

@@ -20,7 +20,7 @@ export default defineConfig({
     open: true,
     proxy: {
       '/api': {
-        target: "http://apigw.dev-nb.com/",
+        target: "http://apigw:11000",
         changeOrigin: true,
         rewrite: (path) => path.replace(/^\/api/, '')
       }