feat(bid): 完成批量业务优化与功能完善

1.  统一所有表格操作列样式,移除固定宽度避免布局溢出
2.  新增报价单自动编号与脏数据清理功能
3.  优化订单状态筛选与展示逻辑,新增closed状态支持
4.  完善操作日志管理,新增统计分析与详情查看功能
5.  优化报价单流程,调整提交审批逻辑与权限控制
6.  修复客户端订单查询SQL,优化关联查询逻辑
7.  新增报价单提交时自动更新提交时间的功能
This commit is contained in:
2026-06-18 20:17:02 +08:00
parent 7b71822a32
commit 41b2e3e772
31 changed files with 1146 additions and 205 deletions

View File

@@ -7,6 +7,7 @@ import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.system.mapper.bid.BizApprovalPendingMapper;
import com.ruoyi.system.service.bid.IBizApprovalActionService;
import com.ruoyi.system.service.bid.IBizQuotationService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@@ -18,6 +19,7 @@ public class BizApprovalActionController extends BaseController {
@Autowired private IBizApprovalActionService service;
@Autowired private BizApprovalPendingMapper pendingMapper;
@Autowired private IBizQuotationService quotationService;
@GetMapping("/pending")
public AjaxResult pending() {
@@ -27,7 +29,12 @@ public class BizApprovalActionController extends BaseController {
@Log(title = "提交审批", businessType = BusinessType.UPDATE)
@PostMapping("/submit/{bizType}/{id}")
public AjaxResult submit(@PathVariable String bizType, @PathVariable Long id) {
return toAjax(service.submit(bizType, id, getUsername()));
int rows = service.submit(bizType, id, getUsername());
// 报价单提交审批时同步更新 submit_time
if ("QUOTATION".equals(bizType) && rows > 0) {
quotationService.updateSubmitTime(id);
}
return toAjax(rows);
}
@Log(title = "审批通过", businessType = BusinessType.UPDATE)

View File

@@ -1,10 +1,19 @@
package com.ruoyi.web.controller.bid;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.SysOperLog;
import com.ruoyi.system.service.ISysOperLogService;
@@ -18,6 +27,67 @@ public class BizOperationLogController extends BaseController {
@GetMapping("/list")
public TableDataInfo list(SysOperLog log) {
startPage();
return getDataTable(operLogService.selectOperLogList(log));
List<SysOperLog> list = operLogService.selectOperLogList(log);
return getDataTable(list);
}
@PreAuthorize("@ss.hasPermi('bid:operationlog:query')")
@GetMapping("/{operId}")
public AjaxResult getInfo(@PathVariable("operId") Long operId) {
return success(operLogService.selectOperLogById(operId));
}
@PreAuthorize("@ss.hasPermi('bid:operationlog:remove')")
@Log(title = "操作日志", businessType = BusinessType.DELETE)
@DeleteMapping("/{operIds}")
public AjaxResult remove(@PathVariable Long[] operIds) {
return toAjax(operLogService.deleteOperLogByIds(operIds));
}
@PreAuthorize("@ss.hasPermi('bid:operationlog:remove')")
@Log(title = "操作日志", businessType = BusinessType.CLEAN)
@DeleteMapping("/clean")
public AjaxResult clean() {
operLogService.cleanOperLog();
return success();
}
@PreAuthorize("@ss.hasPermi('bid:operationlog:export')")
@Log(title = "操作日志", businessType = BusinessType.EXPORT)
@PostMapping("/export")
public void export(HttpServletResponse response, SysOperLog operLog) {
List<SysOperLog> list = operLogService.selectOperLogList(operLog);
ExcelUtil<SysOperLog> util = new ExcelUtil<SysOperLog>(SysOperLog.class);
util.exportExcel(response, list, "操作日志");
}
@PreAuthorize("@ss.hasPermi('bid:operationlog:list')")
@GetMapping("/stats")
public AjaxResult stats(SysOperLog log) {
Map<String, Object> result = new HashMap<>();
Map<String, Object> basic = operLogService.selectOperLogStats(log);
if (basic != null) {
result.put("basic", basic);
} else {
Map<String, Object> empty = new HashMap<>();
empty.put("total_count", 0);
empty.put("error_count", 0);
empty.put("today_count", 0);
empty.put("user_count", 0);
empty.put("avg_cost_time", 0);
empty.put("module_count", 0);
result.put("basic", empty);
}
result.put("modules", operLogService.selectModuleStats(log));
result.put("businessTypes", operLogService.selectBusinessTypeStats(log));
result.put("trend", operLogService.selectDailyTrend(log));
result.put("errors", operLogService.selectErrorStats(log));
return success(result);
}
@PreAuthorize("@ss.hasPermi('bid:operationlog:list')")
@GetMapping("/modules")
public AjaxResult getModules() {
return success(operLogService.selectModuleStats(new SysOperLog()));
}
}

View File

@@ -50,6 +50,8 @@ public class BizQuotationController extends BaseController {
@PostMapping
public AjaxResult add(@RequestBody BizQuotation q) {
q.setCreateBy(getUsername());
Long tenantId = getDeptId();
q.setTenantId(tenantId != null ? tenantId : 1L);
// 供应商新建报价时自动设置 supplier_id
if (SecurityUtils.hasRole("supplier")) {
BizSupplier supplier = supplierService.selectBizSupplierByUserId(SecurityUtils.getUserId());
@@ -86,13 +88,24 @@ public class BizQuotationController extends BaseController {
return toAjax(service.rejectQuotation(quotationId));
}
@PreAuthorize("@ss.hasPermi('bid:quotation:remove') || @ss.hasRole('supplier')")
@PreAuthorize("@ss.hasPermi('bid:quotation:remove')")
@Log(title = "报价单", businessType = BusinessType.DELETE)
@DeleteMapping("/{quotationIds}")
public AjaxResult remove(@PathVariable Long[] quotationIds) {
return toAjax(service.deleteBizQuotationByIds(quotationIds));
}
/**
* 清理无编号的脏数据历史遗留数据quote_no IS NULL 或空字符串)
*/
@PreAuthorize("@ss.hasPermi('bid:quotation:remove')")
@Log(title = "报价单", businessType = BusinessType.CLEAN)
@DeleteMapping("/clean-null-quote")
public AjaxResult cleanNullQuote() {
int n = service.deleteBizQuotationByNoQuoteNo();
return success(n > 0 ? "已清理 " + n + " 条无编号报价单" : "没有需要清理的无编号报价单");
}
/**
* 按供应商ID查询报价明细展开为每行一条物料支持搜索过滤
* 用于供应商管理页面的"报价历史"Tab