diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizClientQuoteController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizClientQuoteController.java index 3d074678..707f57f3 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizClientQuoteController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizClientQuoteController.java @@ -62,6 +62,20 @@ public class BizClientQuoteController extends BaseController { return success(service.selectClientQuotesByMaterialId(materialId)); } + // ========== 按客户+物料查询历史报价(编辑参考用) ========== + + @GetMapping("/history") + public AjaxResult history(@RequestParam String clientName, @RequestParam(required = false) Long materialId) { + return success(service.selectClientQuoteHistory(clientName, materialId)); + } + + // ========== 客户名称自动补全 ========== + + @GetMapping("/client-names") + public AjaxResult clientNames(@RequestParam(required = false) String keyword) { + return success(service.selectDistinctClientNames(keyword)); + } + // ========== 基于历史报价快速新建 ========== @PostMapping("/quick-create/{quoteId}") diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizMaterialController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizMaterialController.java index 50a1e49e..7e87479d 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizMaterialController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizMaterialController.java @@ -75,6 +75,12 @@ public class BizMaterialController extends BaseController { return success(service.selectClientQuotesByMaterialId(id)); } + @PreAuthorize("@ss.hasPermi('bid:material:detail')") + @GetMapping("/{id}/supplier-reference") + public AjaxResult supplierReference(@PathVariable Long id) { + return success(service.selectSupplierQuoteReference(id)); + } + @GetMapping("/manufacturer/list") public AjaxResult manufacturerList() { return success(service.selectManufacturerList()); diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizQuotationController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizQuotationController.java index 59c0fa33..ebeef83c 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizQuotationController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizQuotationController.java @@ -1,5 +1,6 @@ package com.ruoyi.web.controller.bid; +import java.util.HashMap; import java.util.List; import java.util.Map; import org.springframework.beans.factory.annotation.Autowired; @@ -10,45 +11,63 @@ 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.SecurityUtils; import com.ruoyi.system.domain.bid.BizQuotation; +import com.ruoyi.system.domain.bid.BizSupplier; import com.ruoyi.system.service.bid.IBizQuotationService; +import com.ruoyi.system.service.bid.IBizSupplierService; import com.ruoyi.system.mapper.bid.BizQuotationItemMapper; @RestController @RequestMapping("/bid/quotation") public class BizQuotationController extends BaseController { @Autowired private IBizQuotationService service; + @Autowired private IBizSupplierService supplierService; @Autowired private BizQuotationItemMapper quotationItemMapper; - @PreAuthorize("@ss.hasPermi('bid:quotation:list')") + @PreAuthorize("@ss.hasPermi('bid:quotation:list') || @ss.hasRole('supplier')") @GetMapping("/list") public TableDataInfo list(BizQuotation q) { + // 供应商:自动按 supplier_id 过滤,只显示自己的报价 + if (SecurityUtils.hasRole("supplier")) { + BizSupplier supplier = supplierService.selectBizSupplierByUserId(SecurityUtils.getUserId()); + if (supplier != null) { + q.setSupplierId(supplier.getSupplierId()); + } + } startPage(); return getDataTable(service.selectBizQuotationList(q)); } - @PreAuthorize("@ss.hasPermi('bid:quotation:query')") + @PreAuthorize("@ss.hasPermi('bid:quotation:query') || @ss.hasRole('supplier')") @GetMapping("/{quotationId}") public AjaxResult getInfo(@PathVariable Long quotationId) { return success(service.selectBizQuotationById(quotationId)); } - @PreAuthorize("@ss.hasPermi('bid:quotation:add')") + @PreAuthorize("@ss.hasPermi('bid:quotation:add') || @ss.hasRole('supplier')") @Log(title = "报价单", businessType = BusinessType.INSERT) @PostMapping public AjaxResult add(@RequestBody BizQuotation q) { q.setCreateBy(getUsername()); + // 供应商新建报价时自动设置 supplier_id + if (SecurityUtils.hasRole("supplier")) { + BizSupplier supplier = supplierService.selectBizSupplierByUserId(SecurityUtils.getUserId()); + if (supplier != null) { + q.setSupplierId(supplier.getSupplierId()); + } + } return toAjax(service.insertBizQuotation(q)); } - @PreAuthorize("@ss.hasPermi('bid:quotation:edit')") + @PreAuthorize("@ss.hasPermi('bid:quotation:edit') || @ss.hasRole('supplier')") @Log(title = "报价单", businessType = BusinessType.UPDATE) @PutMapping public AjaxResult edit(@RequestBody BizQuotation q) { return toAjax(service.updateBizQuotation(q)); } - @PreAuthorize("@ss.hasPermi('bid:quotation:edit')") + @PreAuthorize("@ss.hasPermi('bid:quotation:edit') || @ss.hasRole('supplier')") @Log(title = "提交报价", businessType = BusinessType.UPDATE) @PutMapping("/submit/{quotationId}") public AjaxResult submit(@PathVariable Long quotationId) { @@ -67,7 +86,7 @@ public class BizQuotationController extends BaseController { return toAjax(service.rejectQuotation(quotationId)); } - @PreAuthorize("@ss.hasPermi('bid:quotation:remove')") + @PreAuthorize("@ss.hasPermi('bid:quotation:remove') || @ss.hasRole('supplier')") @Log(title = "报价单", businessType = BusinessType.DELETE) @DeleteMapping("/{quotationIds}") public AjaxResult remove(@PathVariable Long[] quotationIds) { @@ -75,13 +94,38 @@ public class BizQuotationController extends BaseController { } /** - * 按供应商ID查询报价明细(展开为每行一条物料) + * 按供应商ID查询报价明细(展开为每行一条物料,支持搜索过滤) * 用于供应商管理页面的"报价历史"Tab */ @PreAuthorize("@ss.hasPermi('bid:quotation:list')") @GetMapping("/supplier-items/{supplierId}") - public AjaxResult supplierItems(@PathVariable Long supplierId) { - List> list = quotationItemMapper.selectItemsBySupplierId(supplierId); + public AjaxResult supplierItems(@PathVariable Long supplierId, + @RequestParam(required = false) String materialName, + @RequestParam(required = false) String quoteNo, + @RequestParam(required = false) String quoteStatus, + @RequestParam(required = false) String beginTime, + @RequestParam(required = false) String endTime) { + Map params = new HashMap<>(); + params.put("supplierId", supplierId); + params.put("materialName", materialName); + params.put("quoteNo", quoteNo); + params.put("quoteStatus", quoteStatus); + params.put("beginTime", beginTime); + params.put("endTime", endTime); + List> list = quotationItemMapper.selectItemsBySupplierId(params); + return success(list); + } + + /** + * 根据RFQ ID查询所有供应商报价 + * 用于RFQ列表页的"供应商报价汇总"弹窗 + */ + @PreAuthorize("@ss.hasPermi('bid:quotation:list')") + @GetMapping("/by-rfq/{rfqId}") + public AjaxResult listByRfq(@PathVariable Long rfqId) { + BizQuotation query = new BizQuotation(); + query.setRfqId(rfqId); + List list = service.selectBizQuotationList(query); return success(list); } } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizRfqController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizRfqController.java index ad28ea8a..7e8ff284 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizRfqController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/bid/BizRfqController.java @@ -13,28 +13,39 @@ import com.ruoyi.system.domain.bid.BizClientQuote; import com.ruoyi.system.domain.bid.BizRfq; import com.ruoyi.system.domain.bid.BizRfqItem; import com.ruoyi.system.mapper.bid.BizClientQuoteMapper; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.system.domain.bid.BizSupplier; import com.ruoyi.system.service.bid.IBizRfqService; +import com.ruoyi.system.service.bid.IBizSupplierService; @RestController @RequestMapping("/bid/rfq") public class BizRfqController extends BaseController { @Autowired private IBizRfqService service; + @Autowired private IBizSupplierService supplierService; @Autowired private BizClientQuoteMapper clientQuoteMapper; - @PreAuthorize("@ss.hasPermi('bid:rfq:list')") + @PreAuthorize("@ss.hasPermi('bid:rfq:list') || @ss.hasRole('supplier')") @GetMapping("/list") public TableDataInfo list(BizRfq query) { + // 供应商用户自动过滤:只可见自己被邀请的RFQ + if (SecurityUtils.hasRole("supplier")) { + BizSupplier supplier = supplierService.selectBizSupplierByUserId(SecurityUtils.getUserId()); + if (supplier != null) { + query.setSupplierId(supplier.getSupplierId()); + } + } startPage(); return getDataTable(service.selectBizRfqList(query)); } - @PreAuthorize("@ss.hasPermi('bid:rfq:query')") + @PreAuthorize("@ss.hasPermi('bid:rfq:query') || @ss.hasRole('supplier')") @GetMapping("/{rfqId}") public AjaxResult getInfo(@PathVariable Long rfqId) { return success(service.selectBizRfqById(rfqId)); } - @PreAuthorize("@ss.hasPermi('bid:rfq:query')") + @PreAuthorize("@ss.hasPermi('bid:rfq:query') || @ss.hasRole('supplier')") @GetMapping("/{rfqId}/items") public AjaxResult getItems(@PathVariable Long rfqId) { return success(service.selectItemsByRfqId(rfqId)); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizRfq.java b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizRfq.java index d3416249..f0f0e2f3 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizRfq.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/domain/bid/BizRfq.java @@ -19,6 +19,8 @@ public class BizRfq extends BaseEntity { private String status; private List items; private List supplierIds; + /** 供应商数据过滤(非持久化,仅用于查询时传入当前供应商ID) */ + private Long supplierId; public Long getRfqId() { return rfqId; } public void setRfqId(Long rfqId) { this.rfqId = rfqId; } @@ -44,4 +46,6 @@ public class BizRfq extends BaseEntity { public void setItems(List items) { this.items = items; } public List getSupplierIds() { return supplierIds; } public void setSupplierIds(List supplierIds) { this.supplierIds = supplierIds; } + public Long getSupplierId() { return supplierId; } + public void setSupplierId(Long supplierId) { this.supplierId = supplierId; } } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizClientQuoteMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizClientQuoteMapper.java index a1937699..81d6daa5 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizClientQuoteMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizClientQuoteMapper.java @@ -25,6 +25,12 @@ public interface BizClientQuoteMapper { // ========== 按物料ID关联查询 ========== List> selectClientQuotesByMaterialId(@Param("materialId") Long materialId); + // ========== 按客户+物料查询历史报价(编辑参考) ========== + List> selectClientQuoteHistory(@Param("clientName") String clientName, @Param("materialId") Long materialId); + + // ========== 客户名称自动补全 ========== + List selectDistinctClientNames(@Param("keyword") String keyword); + // ========== 快速复制 ========== List selectItemsByQuoteIdForCopy(@Param("quoteId") Long quoteId); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizMaterialMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizMaterialMapper.java index d7e5a866..f4ad37a5 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizMaterialMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizMaterialMapper.java @@ -16,6 +16,9 @@ public interface BizMaterialMapper { // 物料详情页 List> selectSupplierQuotesByMaterialId(Long materialId); + // 供应商报价参考(编辑参考用,按价格升序,每供应商取最新一条) + List> selectSupplierQuoteReference(Long materialId); + // 批量物料对比 List selectBizMaterialByIds(List materialIds); List> selectSupplierPriceSummaryByMaterialIds(List materialIds); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizQuotationItemMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizQuotationItemMapper.java index 4a4d8fe2..ec23a733 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizQuotationItemMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizQuotationItemMapper.java @@ -7,7 +7,7 @@ import java.util.Map; public interface BizQuotationItemMapper { List selectItemsByQuotationId(Long quotationId); - List> selectItemsBySupplierId(@Param("supplierId") Long supplierId); + List> selectItemsBySupplierId(Map params); int insertBizQuotationItem(BizQuotationItem item); int deleteByQuotationId(Long quotationId); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizSupplierMapper.java b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizSupplierMapper.java index d13d16a7..73ab2a00 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizSupplierMapper.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/mapper/bid/BizSupplierMapper.java @@ -1,11 +1,13 @@ package com.ruoyi.system.mapper.bid; import com.ruoyi.system.domain.bid.BizSupplier; +import org.apache.ibatis.annotations.Param; import java.util.List; public interface BizSupplierMapper { List selectBizSupplierList(BizSupplier query); BizSupplier selectBizSupplierById(Long id); + BizSupplier selectBizSupplierByUserId(@Param("userId") Long userId); int insertBizSupplier(BizSupplier record); int updateBizSupplier(BizSupplier record); int deleteBizSupplierById(Long id); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizClientQuoteService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizClientQuoteService.java index b57eeaa9..3f542437 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizClientQuoteService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizClientQuoteService.java @@ -18,6 +18,12 @@ public interface IBizClientQuoteService { // 按物料ID查询报价历史 List> selectClientQuotesByMaterialId(Long materialId); + // 按客户+物料查询历史报价(编辑参考用) + List> selectClientQuoteHistory(String clientName, Long materialId); + + // 客户名称自动补全 + List selectDistinctClientNames(String keyword); + // 基于历史报价快速新建 BizClientQuote copyFromExisting(Long quoteId); } diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizMaterialService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizMaterialService.java index 3adf125a..139b9ef0 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizMaterialService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizMaterialService.java @@ -14,6 +14,7 @@ public interface IBizMaterialService { List> selectSupplierQuotesByMaterialId(Long materialId); List> selectClientQuotesByMaterialId(Long materialId); + List> selectSupplierQuoteReference(Long materialId); List selectManufacturerList(); // 批量物料对比 diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizSupplierService.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizSupplierService.java index efc73bc5..6cabc3b6 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizSupplierService.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/IBizSupplierService.java @@ -6,6 +6,7 @@ import java.util.List; public interface IBizSupplierService { List selectBizSupplierList(BizSupplier query); BizSupplier selectBizSupplierById(Long id); + BizSupplier selectBizSupplierByUserId(Long userId); int insertBizSupplier(BizSupplier record); int updateBizSupplier(BizSupplier record); int deleteBizSupplierById(Long id); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizClientQuoteServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizClientQuoteServiceImpl.java index 9ca051e3..71aea1d4 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizClientQuoteServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizClientQuoteServiceImpl.java @@ -106,6 +106,20 @@ public class BizClientQuoteServiceImpl implements IBizClientQuoteService { return mapper.selectClientQuotesByMaterialId(materialId); } + // ========== 按客户+物料查询历史报价(编辑参考) ========== + + @Override + public List> selectClientQuoteHistory(String clientName, Long materialId) { + return mapper.selectClientQuoteHistory(clientName, materialId); + } + + // ========== 客户名称自动补全 ========== + + @Override + public List selectDistinctClientNames(String keyword) { + return mapper.selectDistinctClientNames(keyword); + } + // ========== 基于历史报价快速新建 ========== @Override diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizMaterialServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizMaterialServiceImpl.java index 99e88024..fc54f9cc 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizMaterialServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizMaterialServiceImpl.java @@ -53,6 +53,11 @@ public class BizMaterialServiceImpl implements IBizMaterialService { return mapper.selectClientQuotesByMaterialId(materialId); } + @Override + public List> selectSupplierQuoteReference(Long materialId) { + return mapper.selectSupplierQuoteReference(materialId); + } + @Override public List selectManufacturerList() { return mapper.selectManufacturerList(); diff --git a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizSupplierServiceImpl.java b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizSupplierServiceImpl.java index 17107aed..c3df0e8a 100644 --- a/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizSupplierServiceImpl.java +++ b/ruoyi-system/src/main/java/com/ruoyi/system/service/bid/impl/BizSupplierServiceImpl.java @@ -22,6 +22,11 @@ public class BizSupplierServiceImpl implements IBizSupplierService { return mapper.selectBizSupplierById(id); } + @Override + public BizSupplier selectBizSupplierByUserId(Long userId) { + return mapper.selectBizSupplierByUserId(userId); + } + @Override public int insertBizSupplier(BizSupplier record) { return mapper.insertBizSupplier(record); diff --git a/ruoyi-system/src/main/resources/mapper/bid/BizClientQuoteMapper.xml b/ruoyi-system/src/main/resources/mapper/bid/BizClientQuoteMapper.xml index a8a89249..e9262d9b 100644 --- a/ruoyi-system/src/main/resources/mapper/bid/BizClientQuoteMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/bid/BizClientQuoteMapper.xml @@ -99,6 +99,16 @@ + + + + + + + + + + + + - - SELECT qi.item_id AS itemId, qi.quotation_id AS quotationId, qi.material_name AS materialName, qi.spec, qi.unit, qi.quantity, qi.unit_price AS unitPrice, qi.total_price AS totalPrice, @@ -33,6 +33,21 @@ JOIN biz_quotation q ON qi.quotation_id = q.quotation_id LEFT JOIN biz_rfq_item ri ON qi.rfq_item_id = ri.item_id WHERE q.supplier_id = #{supplierId} + + AND qi.material_name LIKE CONCAT('%', #{materialName}, '%') + + + AND q.quote_no LIKE CONCAT('%', #{quoteNo}, '%') + + + AND q.status = #{quoteStatus} + + + AND q.submit_time >= #{beginTime} + + + AND q.submit_time <= #{endTime} + ORDER BY q.submit_time DESC, qi.item_id diff --git a/ruoyi-system/src/main/resources/mapper/bid/BizQuotationMapper.xml b/ruoyi-system/src/main/resources/mapper/bid/BizQuotationMapper.xml index 09744e34..8ed361ad 100644 --- a/ruoyi-system/src/main/resources/mapper/bid/BizQuotationMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/bid/BizQuotationMapper.xml @@ -32,7 +32,14 @@ AND q.tenant_id=#{tenantId} AND q.rfq_id=#{rfqId} AND q.supplier_id=#{supplierId} + + + AND (q.submit_time IS NULL OR DATE_ADD(q.submit_time, INTERVAL q.delivery_days DAY) >= NOW()) + AND q.status=#{status} + AND q.quote_no LIKE CONCAT('%', #{quoteNo}, '%') + AND r.rfq_no LIKE CONCAT('%', #{rfqNo}, '%') + AND s.supplier_name LIKE CONCAT('%', #{supplierName}, '%') ORDER BY q.quotation_id DESC diff --git a/ruoyi-system/src/main/resources/mapper/bid/BizRfqMapper.xml b/ruoyi-system/src/main/resources/mapper/bid/BizRfqMapper.xml index a911a61f..db594897 100644 --- a/ruoyi-system/src/main/resources/mapper/bid/BizRfqMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/bid/BizRfqMapper.xml @@ -36,6 +36,9 @@ AND r.rfq_title LIKE CONCAT('%',#{rfqTitle},'%') AND r.status=#{status} AND r.client_quote_id=#{clientQuoteId} + + AND r.rfq_id IN (SELECT rfq_id FROM biz_rfq_supplier WHERE supplier_id = #{supplierId}) + ORDER BY r.rfq_id DESC diff --git a/ruoyi-system/src/main/resources/mapper/bid/BizSupplierMapper.xml b/ruoyi-system/src/main/resources/mapper/bid/BizSupplierMapper.xml index 3f61c6b0..bedb3e73 100644 --- a/ruoyi-system/src/main/resources/mapper/bid/BizSupplierMapper.xml +++ b/ruoyi-system/src/main/resources/mapper/bid/BizSupplierMapper.xml @@ -30,6 +30,10 @@ + + INSERT INTO biz_supplier(tenant_id,supplier_name,contact,phone,email,address,user_id,status,create_by,create_time) VALUES(#{tenantId},#{supplierName},#{contact},#{phone},#{email},#{address},#{userId},#{status},#{createBy},NOW()) diff --git a/ruoyi-ui/src/api/bid/clientquote.js b/ruoyi-ui/src/api/bid/clientquote.js index ba094b89..d7f751f2 100644 --- a/ruoyi-ui/src/api/bid/clientquote.js +++ b/ruoyi-ui/src/api/bid/clientquote.js @@ -17,3 +17,7 @@ export const getMonthlyTrend = () => request({ url: baseUrl + '/monthly-trend', export const getClientQuoteByMaterial = (materialId) => request({ url: baseUrl + '/by-material/' + materialId, method: 'get' }) // 基于历史报价快速新建 export const quickCreateFromQuote = (quoteId) => request({ url: baseUrl + '/quick-create/' + quoteId, method: 'post' }) +// 按客户+物料查询历史报价(编辑参考用) +export const getClientQuoteHistory = (clientName, materialId) => request({ url: baseUrl + '/history', method: 'get', params: { clientName, materialId } }) +// 客户名称自动补全 +export const getClientNames = (keyword) => request({ url: baseUrl + '/client-names', method: 'get', params: { keyword } }) diff --git a/ruoyi-ui/src/api/bid/material.js b/ruoyi-ui/src/api/bid/material.js index 33548ce8..9c412810 100644 --- a/ruoyi-ui/src/api/bid/material.js +++ b/ruoyi-ui/src/api/bid/material.js @@ -10,6 +10,7 @@ export const delMaterial = (ids) => request({ url: baseUrl + '/' + ids, method: // 物料详情页 export const getSupplierQuotes = (id) => request({ url: baseUrl + '/' + id + '/supplier-quotes', method: 'get' }) export const getClientQuotes = (id) => request({ url: baseUrl + '/' + id + '/client-quotes', method: 'get' }) +export const getSupplierQuoteReference = (id) => request({ url: baseUrl + '/' + id + '/supplier-reference', method: 'get' }) export const listManufacturer = () => request({ url: baseUrl + '/manufacturer/list', method: 'get' }) export const compareMaterials = (data) => request({ url: baseUrl + '/compare', method: 'post', data }) diff --git a/ruoyi-ui/src/api/bid/quotation.js b/ruoyi-ui/src/api/bid/quotation.js index 90af95ce..470f0205 100644 --- a/ruoyi-ui/src/api/bid/quotation.js +++ b/ruoyi-ui/src/api/bid/quotation.js @@ -9,5 +9,11 @@ export const acceptQuotation = (id) => request({ url: baseUrl + '/accept/' + id, export const rejectQuotation = (id) => request({ url: baseUrl + '/reject/' + id, method: 'put' }) export const delQuotation = (ids) => request({ url: baseUrl + '/' + ids, method: 'delete' }) -// 按供应商ID查询报价明细(展开为每行一条物料) -export const getSupplierQuoteItems = (supplierId) => request({ url: baseUrl + '/supplier-items/' + supplierId, method: 'get' }) +// 按供应商ID查询报价明细(展开为每行一条物料,支持搜索过滤参数:materialName, quoteNo, quoteStatus, beginTime, endTime) +export const getSupplierQuoteItems = (params) => { + const { supplierId, ...query } = params; + return request({ url: baseUrl + '/supplier-items/' + supplierId, method: 'get', params: query }); +} + +// 根据RFQ ID查询所有供应商报价(用于RFQ页面的"供应商报价汇总"弹窗) +export const getQuotationsByRfq = (rfqId) => request({ url: baseUrl + '/by-rfq/' + rfqId, method: 'get' }) diff --git a/ruoyi-ui/src/router/index.js b/ruoyi-ui/src/router/index.js index e02c2bab..45dfaaae 100644 --- a/ruoyi-ui/src/router/index.js +++ b/ruoyi-ui/src/router/index.js @@ -108,23 +108,11 @@ export const dynamicRoutes = [ path: '', component: () => import('@/views/bid/material/detail'), name: 'MaterialDetail', - meta: { title: '物料详情', activeMenu: '/bid/material' } - } - ] - }, - { - path: '/quotemgr/clientquote/detail', - component: Layout, - hidden: true, - children: [ - { - path: '', - component: () => import('@/views/bid/clientquote/detail'), - name: 'ClientQuoteDetail', - meta: { title: '甲方报价单详情', activeMenu: '/quotemgr/clientquote' } + meta: { title: '物料详情', activeMenu: '/material' } } ] }, + { path: '/bid/rfq/detail', component: Layout, @@ -135,7 +123,7 @@ export const dynamicRoutes = [ path: '', component: () => import('@/views/bid/rfq/detail'), name: 'RfqDetail', - meta: { title: '报价请求详情', activeMenu: '/bid/rfq' } + meta: { title: '报价请求详情', activeMenu: '/rfq' } } ] }, @@ -149,7 +137,7 @@ export const dynamicRoutes = [ path: '', component: () => import('@/views/bid/report/dashboard'), name: 'ReportDashboard', - meta: { title: '采购总览看板', activeMenu: '/bid/report' } + meta: { title: '采购总览看板', activeMenu: '/report' } }] }, { @@ -161,7 +149,7 @@ export const dynamicRoutes = [ path: '', component: () => import('@/views/bid/report/cost'), name: 'ReportCost', - meta: { title: '采购成本分析', activeMenu: '/bid/report' } + meta: { title: '采购成本分析', activeMenu: '/report' } }] }, { @@ -173,7 +161,31 @@ export const dynamicRoutes = [ path: '', component: () => import('@/views/bid/report/supplier'), name: 'ReportSupplier', - meta: { title: '供应商绩效', activeMenu: '/bid/report' } + meta: { title: '供应商绩效', activeMenu: '/report' } + }] + }, + { + path: '/bid/clientquote/detail', + component: Layout, + hidden: true, + permissions: ['bid:clientquote:add', 'bid:clientquote:edit'], + children: [{ + path: '', + component: () => import('@/views/bid/clientquote/detail'), + name: 'ClientQuoteDetail', + meta: { title: '甲方报价单详情', activeMenu: '/clientquote' } + }] + }, + { + path: '/bid/comparison/detail', + component: Layout, + hidden: true, + permissions: ['bid:comparison:query'], + children: [{ + path: '', + component: () => import('@/views/bid/comparison/detail'), + name: 'ComparisonDetail', + meta: { title: '智慧比价分析', activeMenu: '/bid/comparison' } }] }, { diff --git a/ruoyi-ui/src/views/bid/clientquote/detail.vue b/ruoyi-ui/src/views/bid/clientquote/detail.vue index cb7930fb..f8461767 100644 --- a/ruoyi-ui/src/views/bid/clientquote/detail.vue +++ b/ruoyi-ui/src/views/bid/clientquote/detail.vue @@ -12,21 +12,33 @@ +
+
+
基本信息
- + - - - - + +
+ {{ form.rfqNo }} + {{ form.rfqTitle }} +
+ 保存后点击「生成RFQ」创建
@@ -71,9 +83,9 @@ 添加行
- - - + + + - + - + - + - + - + - + - + - + - + @@ -160,6 +172,62 @@
+
+ +
+ + +
+ 客户历史报价 + 共 {{ refClientHistory.length }} 条 +
+
请先填写客户名称并选择物料
+
加载中...
+
暂无该客户的历史报价
+ + + + + + + + + + +
点击行可快速填入报价
+
+ + + +
+ 供应商报价参考 + 最低 ¥{{ minSupplierPrice }} +
+
请先选择物料
+
加载中...
+
暂无供应商报价
+ + + + + + + + + + +
点击行可快速填入报价,绿色为最低价
+
+
+ + +
@@ -180,7 +248,7 @@ 有效期{{ form.validityDate | dateFmt }} - 关联询价单{{ form.rfqNo || '-' }} + 已生成RFQ{{ form.rfqNo || '未生成' }} 币种{{ form.currency || 'CNY' }} @@ -221,9 +289,9 @@ @@ -292,21 +254,10 @@ export default { .item-qty { margin-left:auto; font-size:12px; color:rgba(255,255,255,.8); } .no-quote { padding:20px; color:#909399; background:#fafafa; border:1px dashed #e4e7ed; border-radius:4px; text-align:center; } .supplier-cards { display:flex; gap:12px; padding:16px 0; overflow-x:auto; } -.supplier-card { flex:0 0 200px; border:1px solid #e4e7ed; border-radius:8px; padding:14px; background:#fff; &:hover { box-shadow:0 4px 16px rgba(0,0,0,.1); } &.best-card { border-color:#67c23a; box-shadow:0 2px 8px rgba(103,194,58,.2); } } -.card-rank { display:flex; align-items:center; gap:6px; margin-bottom:8px; } -.rank-num { width:22px; height:22px; border-radius:50%; display:flex; align-items:center; justify-content:center; font-size:12px; font-weight:700; &.rank-1 { background:#f7ba2a; color:#fff; } &.rank-2 { background:#c0c4cc; color:#fff; } &.rank-3 { background:#a57c52; color:#fff; } } +.supplier-card { flex:0 0 200px; border:1px solid #e4e7ed; border-radius:8px; padding:14px; background:#fff; &:hover { box-shadow:0 4px 16px rgba(0,0,0,.1); } } .card-supplier { font-size:13px; font-weight:600; color:#303133; margin-bottom:6px; } -.card-score-big { font-size:28px; font-weight:700; line-height:1; margin:8px 0; &.score-high { color:#67c23a; } &.score-mid { color:#e6a23c; } &.score-low { color:#f56c6c; } .score-unit { font-size:13px; font-weight:400; } } .card-price { font-size:13px; color:#409EFF; font-weight:600; margin-bottom:10px; } -.dim-bars { display:flex; flex-direction:column; gap:4px; } -.dim-row { display:flex; align-items:center; gap:6px; } -.dim-label { font-size:11px; color:#909399; width:24px; flex-shrink:0; } -.dim-bar { flex:1; } -.dim-val { font-size:11px; color:#606266; width:24px; text-align:right; flex-shrink:0; } .card-meta { font-size:11px; color:#c0c4cc; margin-top:8px; } -.score-high { color:#67c23a; font-weight:700; } -.score-mid { color:#e6a23c; font-weight:600; } -.score-low { color:#f56c6c; } .price-low { color:#67c23a; font-weight:700; } .plan-card { border:1px solid #e4e7ed; border-radius:8px; margin-bottom:24px; overflow:hidden; background:#fff; position:relative; } .plan-header { display:flex; align-items:center; justify-content:space-between; padding:14px 20px; background:linear-gradient(90deg,#f0f7ff,#fff); border-bottom:1px solid #e4e7ed; flex-wrap:wrap; gap:10px; } @@ -329,10 +280,6 @@ export default { .meta-label { background:#f5f7fa; color:#606266; font-weight:600; width:90px; } .meta-val { color:#303133; } .amount-big { color:#409EFF; font-weight:700; font-size:16px; } -.score-good { color:#67c23a; font-weight:700; } -.score-ok { color:#e6a23c; font-weight:600; } -.score-weak { color:#f56c6c; } -.pdf-score-legend { background:#f0f7ff; border:1px solid #c6e2ff; border-radius:4px; padding:8px 14px; font-size:12px; color:#606266; margin-bottom:16px; } .pdf-section-title { font-size:14px; font-weight:700; color:#1a2c4e; margin:0 0 10px; padding-left:8px; border-left:4px solid #1171c4; } .pdf-items-table { width:100%; border-collapse:collapse; margin-bottom:20px; th { background:#1171c4; color:#fff; padding:8px; text-align:center; font-weight:600; font-size:12px; } td { border:1px solid #e4e7ed; padding:7px 8px; text-align:center; font-size:12px; } tbody tr:nth-child(even) td { background:#f9fbff; } } .amount-cell { color:#409EFF; font-weight:600; } diff --git a/ruoyi-ui/src/views/bid/comparison/index.vue b/ruoyi-ui/src/views/bid/comparison/index.vue index 917718fb..5f15c80c 100644 --- a/ruoyi-ui/src/views/bid/comparison/index.vue +++ b/ruoyi-ui/src/views/bid/comparison/index.vue @@ -77,7 +77,7 @@ export default { this.$router.push({ path: "/bid/comparison/detail", query: { rfqId: row.rfqId } }); }, goRfqDetail(row) { - this.$router.push({ path: '/bid/rfq', query: { rfqId: row.rfqId, rfqNo: row.rfqNo, action: 'edit' } }); + this.$router.push({ path: '/rfq', query: { rfqId: row.rfqId, rfqNo: row.rfqNo, action: 'edit' } }); }, statusType(s) { const m = { draft: "info", open: "primary", closed: "success", cancelled: "danger" }; diff --git a/ruoyi-ui/src/views/bid/material/components/ClientQuoteTab.vue b/ruoyi-ui/src/views/bid/material/components/ClientQuoteTab.vue index a6af825d..77b6a3d3 100644 --- a/ruoyi-ui/src/views/bid/material/components/ClientQuoteTab.vue +++ b/ruoyi-ui/src/views/bid/material/components/ClientQuoteTab.vue @@ -4,7 +4,6 @@
甲方报价记录
- 查看全部历史 导出Excel
@@ -90,7 +89,7 @@

暂无甲方报价记录

- 去创建报价 + 去创建报价
@@ -139,11 +138,12 @@ export default { }, viewQuote(row) { if (row.quoteId) { - this.$router.push({ path: "/quotemgr/clientquote/detail", query: { quoteId: row.quoteId } }); + this.$router.push({ path: "/bid/clientquote/detail", query: { quoteId: row.quoteId } }); } }, - goToHistory() { - this.$router.push("/quotemgr/clientquote"); + /** 跳转到甲方报价详情页新建报价 */ + goCreateQuote() { + this.$router.push({ path: '/bid/clientquote/detail' }); }, exportExcel() { this.$message.info('导出功能开发中'); diff --git a/ruoyi-ui/src/views/bid/material/detail.vue b/ruoyi-ui/src/views/bid/material/detail.vue index 2947675f..46de729b 100644 --- a/ruoyi-ui/src/views/bid/material/detail.vue +++ b/ruoyi-ui/src/views/bid/material/detail.vue @@ -235,7 +235,12 @@ export default { }, goBack() { - this.$router.push('/bid/material'); + // 优先返回上一页,如果没有历史记录则返回物料列表 + if (window.history.length > 1) { + this.$router.back(); + } else { + this.$router.push('/bid/material'); + } } } }; diff --git a/ruoyi-ui/src/views/bid/quotation/index.vue b/ruoyi-ui/src/views/bid/quotation/index.vue index d08a9b1f..028a82e1 100644 --- a/ruoyi-ui/src/views/bid/quotation/index.vue +++ b/ruoyi-ui/src/views/bid/quotation/index.vue @@ -35,6 +35,9 @@ + + + @@ -110,9 +113,9 @@ 提交 采纳 + @click="handleAccept(s.row)" v-if="s.row.status==='submitted' && !isSupplier">采纳 拒绝 + @click="handleReject(s.row)" v-if="s.row.status==='submitted' && !isSupplier">拒绝 删除 @@ -375,7 +378,7 @@ export default { rfqItemsLoading: false, rfqOptions: [], supplierOptions: [], logoSrc: logoImg, - queryParams: { pageNum: 1, pageSize: 10, status: null, rfqNo: null, supplierName: null }, + queryParams: { pageNum: 1, pageSize: 10, status: null, rfqNo: null, quoteNo: null, supplierName: null }, form: { items: [], currency: "CNY", validDays: 30, deliveryDays: null }, rules: { rfqId: [{ required: true, message: "请选择询价单", trigger: "change" }], @@ -384,14 +387,26 @@ export default { }; }, computed: { + /** 是否为供应商用户 */ + isSupplier() { + return this.$store.getters.roles && this.$store.getters.roles.includes('supplier'); + }, formTotal() { return (this.form.items || []).reduce((s, i) => s + (parseFloat(i.quantity || 0) * parseFloat(i.unitPrice || 0)), 0).toFixed(2); } }, created() { + // 读取 URL 查询参数,实现跨页面跳转自动搜索 + const query = this.$route.query; + if (query.rfqNo) this.queryParams.rfqNo = query.rfqNo; + if (query.supplierName) this.queryParams.supplierName = query.supplierName; + if (query.quoteNo) this.queryParams.quoteNo = query.quoteNo; this.getList(); + // 供应商只需加载自己可见的RFQ,无需加载全部供应商列表 listRfq({ pageSize: 200 }).then(r => { this.rfqOptions = r.rows || []; }); - listSupplier({ pageSize: 200 }).then(r => { this.supplierOptions = r.rows || []; }); + if (!this.isSupplier) { + listSupplier({ pageSize: 200 }).then(r => { this.supplierOptions = r.rows || []; }); + } }, methods: { getList() { @@ -408,7 +423,11 @@ export default { }).catch(() => { this.loading = false; }); }, handleQuery() { this.queryParams.pageNum = 1; this.getList(); }, - resetQuery() { this.resetForm("queryForm"); this.handleQuery(); }, + resetQuery() { + this.resetForm("queryForm"); + this.queryParams.quoteNo = null; + this.handleQuery(); + }, handleAdd() { this.form = { items: [], currency: "CNY", validDays: 30, deliveryDays: null, status: "draft" }; this.dialogTitle = "新建报价单"; diff --git a/ruoyi-ui/src/views/bid/report/cost.vue b/ruoyi-ui/src/views/bid/report/cost.vue index 6a9d2e28..b68b47c2 100644 --- a/ruoyi-ui/src/views/bid/report/cost.vue +++ b/ruoyi-ui/src/views/bid/report/cost.vue @@ -242,7 +242,7 @@ export default { }) }, goCompare(rfqId) { - this.$router.push({ path: '/bid/comparison/detail', query: { rfqId } }) + this.$router.push({ path: '/comparison/detail', query: { rfqId } }) }, formatMoney(v) { const n = Number(v) diff --git a/ruoyi-ui/src/views/bid/rfq/detail.vue b/ruoyi-ui/src/views/bid/rfq/detail.vue index 2bee5996..9ed56c78 100644 --- a/ruoyi-ui/src/views/bid/rfq/detail.vue +++ b/ruoyi-ui/src/views/bid/rfq/detail.vue @@ -304,7 +304,7 @@ export default { viewClientQuote() { const quoteId = this.rfq ? this.rfq.clientQuoteId : this.editForm.clientQuoteId; if (quoteId) { - this.$router.push({ path: '/quotemgr/clientquote/detail', query: { quoteId } }); + this.$router.push({ path: '/bid/clientquote/detail', query: { quoteId } }); } }, diff --git a/ruoyi-ui/src/views/bid/rfq/index.vue b/ruoyi-ui/src/views/bid/rfq/index.vue index 15c94856..765b0fb0 100644 --- a/ruoyi-ui/src/views/bid/rfq/index.vue +++ b/ruoyi-ui/src/views/bid/rfq/index.vue @@ -23,7 +23,7 @@ - 新建报价请求 + 新建报价请求 @@ -48,12 +48,19 @@ - + @@ -65,20 +72,21 @@ - + - + - + @@ -86,7 +94,7 @@ - + @@ -95,27 +103,29 @@ @@ -123,21 +133,21 @@ 甲方报价 - + - 添加物料行 + 添加物料行 - +
- 取消 - 保存草稿 + {{ viewOnly ? '关闭' : '取消' }} + 保存草稿
@@ -152,6 +162,87 @@ 确认发布
+ + + +
+ +
+ + + RFQ编号 + {{ summaryRfq.rfqNo }} + + + 标题 + {{ summaryRfq.rfqTitle }} + + + 截止日期 + {{ summaryRfq.deadline }} + + +
+ + +
+
+
{{ summaryQuoteList.length }}
+
供应商报价
+
+
+
{{ minPrice }}
+
最低报价
+
+
+
{{ maxPrice }}
+
最高报价
+
+
+
{{ avgPrice }}
+
平均报价
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + +
+
@@ -159,24 +250,38 @@ import { listRfq, getRfq, addRfq, updateRfq, publishRfq, delRfq, getClientQuoteOptions, createRfqFromQuote } from "@/api/bid/rfq"; import { listSupplier } from "@/api/bid/supplier"; import { getClientQuote } from "@/api/bid/clientquote"; +import { getQuotationsByRfq } from "@/api/bid/quotation"; export default { name: "Rfq", + filters: { + money(v) { return v ? Number(v).toFixed(2) : "0.00"; } + }, data() { return { loading: false, total: 0, list: [], open: false, title: "", + viewOnly: false, publishOpen: false, publishRfqId: null, selectedSuppliers: [], supplierOptions: [], clientQuoteOptions: [], queryParams: { pageNum: 1, pageSize: 10, rfqNo: null, rfqTitle: null, status: null }, form: { items: [] }, - rules: { rfqTitle: [{ required: true, message: "标题不能为空", trigger: "blur" }] } + rules: { rfqTitle: [{ required: true, message: "标题不能为空", trigger: "blur" }] }, + + // ---- 供应商报价汇总弹窗 ---- + summaryOpen: false, + summaryLoading: false, + summaryRfq: {}, + summaryQuoteList: [] }; }, created() { this.getList(); - this.loadSuppliers(); - this.loadClientQuoteOptions(); + // 供应商用户不需要加载供应商列表和甲方报价选项 + if (!this.isSupplier) { + this.loadSuppliers(); + this.loadClientQuoteOptions(); + } // 接收外部传入参数:生成RFQ后自动打开编辑弹窗 this.$nextTick(() => { const rfqId = this.$route.query.rfqId; @@ -212,10 +317,20 @@ export default { getRfq(row.rfqId).then(r => { this.form = r.data || {}; if (!this.form.items) this.form.items = []; + this.viewOnly = false; this.open = true; this.title = "编辑报价请求"; }); }, - handleView(row) { this.handleUpdate(row); }, + /** 查看RFQ详情:管理员可编辑,供应商只读 */ + handleView(row) { + getRfq(row.rfqId).then(r => { + this.form = r.data || {}; + if (!this.form.items) this.form.items = []; + this.viewOnly = this.isSupplier; + this.open = true; + this.title = this.isSupplier ? "报价请求详情" : "编辑报价请求"; + }); + }, handlePublish(row) { this.publishRfqId = row.rfqId; this.selectedSuppliers = []; this.publishOpen = true; }, doPublish() { publishRfq(this.publishRfqId, this.selectedSuppliers).then(() => { @@ -260,11 +375,111 @@ export default { /** 查看关联的甲方报价 */ viewClientQuote(row) { if (row.clientQuoteId) { - this.$router.push({ path: '/quotemgr/clientquote/detail', query: { quoteId: row.clientQuoteId } }); + this.$router.push({ path: '/bid/clientquote/detail', query: { quoteId: row.clientQuoteId } }); } }, statusType(s) { return { draft:"info", published:"warning", closed:"", completed:"success" }[s] || ""; }, - statusLabel(s) { return { draft:"草稿", published:"已发布", closed:"已关闭", completed:"已完成" }[s] || s; } + statusLabel(s) { return { draft:"草稿", published:"已发布", closed:"已关闭", completed:"已完成" }[s] || s; }, + + /* ========== 供应商报价汇总 ========== */ + + /** 打开供应商报价汇总弹窗 */ + openQuoteSummary(row) { + this.summaryRfq = { ...row }; + this.summaryOpen = true; + this.summaryLoading = true; + this.summaryQuoteList = []; + getQuotationsByRfq(row.rfqId).then(r => { + this.summaryQuoteList = r.data || []; + this.summaryLoading = false; + }).catch(() => { + this.summaryLoading = false; + }); + }, + + /** 点击报价单号跳转到供应商报价列表,按供应商名称和RFQ单号自动搜索过滤 */ + viewQuotation(row) { + this.summaryOpen = false; + this.$router.push({ path: '/quotation', query: { rfqNo: row.rfqNo, supplierName: row.supplierName, quoteNo: row.quoteNo } }); + }, + + /** 报价状态样式 */ + qStatusType(s) { return { draft: "info", submitted: "warning", accepted: "success", rejected: "danger" }[s] || "info"; }, + qStatusLabel(s) { return { draft: "草稿", submitted: "已提交", accepted: "已采纳", rejected: "已拒绝" }[s] || s; } + }, + computed: { + /** 是否为供应商用户 */ + isSupplier() { + return this.$store.getters.roles && this.$store.getters.roles.includes('supplier'); + }, + /** 最低报价 */ + minPrice() { + if (!this.summaryQuoteList.length) return '¥0.00'; + const vals = this.summaryQuoteList.map(q => Number(q.totalAmount) || 0).filter(v => v > 0); + if (!vals.length) return '¥0.00'; + return '¥' + Math.min(...vals).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }); + }, + /** 最高报价 */ + maxPrice() { + if (!this.summaryQuoteList.length) return '¥0.00'; + const vals = this.summaryQuoteList.map(q => Number(q.totalAmount) || 0).filter(v => v > 0); + if (!vals.length) return '¥0.00'; + return '¥' + Math.max(...vals).toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }); + }, + /** 平均报价 */ + avgPrice() { + if (!this.summaryQuoteList.length) return '¥0.00'; + const vals = this.summaryQuoteList.map(q => Number(q.totalAmount) || 0).filter(v => v > 0); + if (!vals.length) return '¥0.00'; + const avg = vals.reduce((s, v) => s + v, 0) / vals.length; + return '¥' + avg.toLocaleString(undefined, { minimumFractionDigits: 2, maximumFractionDigits: 2 }); + } } }; + + diff --git a/ruoyi-ui/src/views/bid/supplier/index.vue b/ruoyi-ui/src/views/bid/supplier/index.vue index e422d4d1..6bdce5bd 100644 --- a/ruoyi-ui/src/views/bid/supplier/index.vue +++ b/ruoyi-ui/src/views/bid/supplier/index.vue @@ -159,6 +159,36 @@ + +
@@ -203,29 +233,7 @@
- - -
- - - - - - - - - - - -
暂无供货记录
-
-
- - +
@@ -294,7 +302,6 @@