feat(bid): 完成物料管理模块全功能开发

1. 新增物料详情页路由、菜单与接口,支持查看物料报价与信息
2. 重构物料列表页面,新增品牌筛选、表格样式优化与详情跳转
3. 扩展物料实体与数据库字段,新增材质、用途、性能参数等字段
4. 新增供应商/甲方报价查询、批量对比、同名称物料匹配接口
5. 新增物料详情组件,包含基础信息、供应商报价、甲方报价标签页
6. 修复比价路由跳转路径错误,调整数据库密码配置
7. 新增物料相关SQL脚本与初始化数据
This commit is contained in:
2026-05-29 08:58:58 +08:00
parent c718ec4076
commit e521b0dfeb
26 changed files with 4871 additions and 41 deletions

View File

@@ -9,7 +9,6 @@
<result property="materialCode" column="material_code"/>
<result property="materialName" column="material_name"/>
<result property="spec" column="spec"/>
<result property="modelNo" column="model_no"/>
<result property="unit" column="unit"/>
<result property="brand" column="brand"/>
<result property="description" column="description"/>
@@ -18,27 +17,40 @@
<result property="createTime" column="create_time"/>
<result property="updateBy" column="update_by"/>
<result property="updateTime" column="update_time"/>
<result property="performanceParams" column="performance_params"/>
<result property="material" column="material"/>
<result property="purpose" column="purpose"/>
<result property="imageUrl" column="image_url"/>
</resultMap>
<select id="selectBizMaterialList" resultMap="BaseRM">
SELECT m.* FROM biz_material m
SELECT m.*, c.category_name AS category_name
FROM biz_material m
LEFT JOIN biz_material_category c ON m.category_id = c.category_id
<where>
<if test="tenantId != null"> AND m.tenant_id = #{tenantId}</if>
<if test="categoryId != null"> AND m.category_id = #{categoryId}</if>
<if test="materialCode != null and materialCode != &apos;&apos;"> AND m.material_code LIKE CONCAT(&apos;%&apos;,#{materialCode},&apos;%&apos;)</if>
<if test="materialName != null and materialName != &apos;&apos;"> AND m.material_name LIKE CONCAT(&apos;%&apos;,#{materialName},&apos;%&apos;)</if>
<if test="status != null and status != &apos;&apos;"> AND m.status = #{status}</if>
<if test="materialCode != null and materialCode != ''"> AND m.material_code LIKE CONCAT('%',#{materialCode},'%')</if>
<if test="materialName != null and materialName != ''"> AND m.material_name LIKE CONCAT('%',#{materialName},'%')</if>
<if test="brand != null and brand != ''"> AND m.brand LIKE CONCAT('%',#{brand},'%')</if>
<if test="spec != null and spec != ''"> AND m.spec LIKE CONCAT('%',#{spec},'%')</if>
<if test="status != null and status != ''"> AND m.status = #{status}</if>
</where>
ORDER BY m.material_id DESC
</select>
<select id="selectBizMaterialById" resultMap="BaseRM">
SELECT * FROM biz_material WHERE material_id=#{id}
SELECT m.*, c.category_name AS category_name
FROM biz_material m
LEFT JOIN biz_material_category c ON m.category_id = c.category_id
WHERE m.material_id=#{id}
</select>
<insert id="insertBizMaterial" useGeneratedKeys="true" keyProperty="materialId">
INSERT INTO biz_material(tenant_id,category_id,material_code,material_name,spec,model_no,unit,brand,description,status,create_by,create_time)
VALUES(#{tenantId},#{categoryId},#{materialCode},#{materialName},#{spec},#{modelNo},#{unit},#{brand},#{description},#{status},#{createBy},NOW())
INSERT INTO biz_material(tenant_id,category_id,material_code,material_name,spec,unit,brand,
description,status,performance_params,material,purpose,image_url,create_by,create_time)
VALUES(#{tenantId},#{categoryId},#{materialCode},#{materialName},#{spec},#{unit},#{brand},
#{description},#{status},#{performanceParams},#{material},#{purpose},#{imageUrl},#{createBy},NOW())
</insert>
<update id="updateBizMaterial">
@@ -47,12 +59,15 @@
<if test="materialName != null">material_name=#{materialName},</if>
<if test="materialCode != null">material_code=#{materialCode},</if>
<if test="spec != null">spec=#{spec},</if>
<if test="modelNo != null">model_no=#{modelNo},</if>
<if test="unit != null">unit=#{unit},</if>
<if test="brand != null">brand=#{brand},</if>
<if test="description != null">description=#{description},</if>
<if test="categoryId != null">category_id=#{categoryId},</if>
<if test="status != null">status=#{status},</if>
<if test="performanceParams != null">performance_params=#{performanceParams},</if>
<if test="material != null">material=#{material},</if>
<if test="purpose != null">purpose=#{purpose},</if>
<if test="imageUrl != null">image_url=#{imageUrl},</if>
update_by=#{updateBy}, update_time=NOW()
</set>
WHERE material_id=#{materialId}
@@ -63,4 +78,129 @@
DELETE FROM biz_material WHERE material_id IN
<foreach collection="array" item="id" open="(" separator="," close=")">#{id}</foreach>
</delete>
<!-- 供应商报价历史:通过 rfq_item 关联物料 -->
<select id="selectSupplierQuotesByMaterialId" resultType="java.util.Map">
SELECT qi.item_id, qi.unit_price, qi.total_price, qi.delivery_days,
q.quotation_id, q.quote_no, q.submit_time, q.status AS quote_status,
s.supplier_id, s.supplier_name
FROM biz_quotation_item qi
JOIN biz_quotation q ON qi.quotation_id = q.quotation_id
JOIN biz_supplier s ON q.supplier_id = s.supplier_id
JOIN biz_rfq_item ri ON qi.rfq_item_id = ri.item_id
WHERE ri.material_id = #{materialId}
ORDER BY q.submit_time DESC
</select>
<!-- 甲方报价历史:通过物料名称关联 -->
<select id="selectClientQuotesByMaterialId" resultType="java.util.Map">
SELECT cqi.item_id, cqi.spec, cqi.model_no, cqi.unit, cqi.quantity,
cqi.cost_price, cqi.unit_price, cqi.total_price, cqi.delivery_days,
cq.quote_id, cq.quote_no, cq.client_name, cq.status AS quote_status, cq.create_time
FROM biz_client_quote_item cqi
JOIN biz_client_quote cq ON cqi.quote_id = cq.quote_id
WHERE cqi.material_name = (SELECT material_name FROM biz_material WHERE material_id = #{materialId})
ORDER BY cq.create_time DESC
</select>
<!-- ========== 批量物料对比 ========== -->
<select id="selectBizMaterialByIds" resultMap="BaseRM">
SELECT m.*, c.category_name AS category_name
FROM biz_material m
LEFT JOIN biz_material_category c ON m.category_id = c.category_id
WHERE m.material_id IN
<foreach collection="list" item="id" open="(" separator="," close=")">#{id}</foreach>
ORDER BY m.material_id
</select>
<!-- 按物料分组统计供应商报价汇总 -->
<select id="selectSupplierPriceSummaryByMaterialIds" resultType="java.util.Map">
SELECT ri.material_id,
MIN(qi.unit_price) AS min_price,
MAX(qi.unit_price) AS max_price,
ROUND(AVG(qi.unit_price), 2) AS avg_price,
COUNT(DISTINCT q.supplier_id) AS supplier_count
FROM biz_quotation_item qi
JOIN biz_quotation q ON qi.quotation_id = q.quotation_id
JOIN biz_rfq_item ri ON qi.rfq_item_id = ri.item_id
WHERE ri.material_id IN
<foreach collection="list" item="id" open="(" separator="," close=")">#{id}</foreach>
GROUP BY ri.material_id
</select>
<!-- 每个物料最低价对应的供应商详情 -->
<select id="selectBestSupplierOfferByMaterialIds" resultType="java.util.Map">
SELECT t.material_id, t.unit_price, t.delivery_days, s.supplier_name, s.contact, s.phone
FROM (
SELECT ri.material_id, qi.unit_price, qi.delivery_days, qi.quotation_id,
ROW_NUMBER() OVER (PARTITION BY ri.material_id ORDER BY qi.unit_price ASC, qi.delivery_days ASC) AS rn
FROM biz_quotation_item qi
JOIN biz_quotation q ON qi.quotation_id = q.quotation_id
JOIN biz_rfq_item ri ON qi.rfq_item_id = ri.item_id
WHERE ri.material_id IN
<foreach collection="list" item="id" open="(" separator="," close=")">#{id}</foreach>
AND qi.unit_price IS NOT NULL
) t
JOIN biz_quotation q ON t.quotation_id = q.quotation_id
JOIN biz_supplier s ON q.supplier_id = s.supplier_id
WHERE t.rn = 1
</select>
<!-- 获取厂家/品牌列表(去重) -->
<select id="selectManufacturerList" resultType="java.lang.String">
SELECT DISTINCT brand FROM biz_material
WHERE brand IS NOT NULL AND brand != ''
ORDER BY brand
</select>
<!-- 根据物料名称精确匹配查询(用于同名称不同规格/品牌对比) -->
<select id="selectMaterialsByExactName" resultMap="BaseRM">
SELECT m.*, c.category_name AS category_name
FROM biz_material m
LEFT JOIN biz_material_category c ON m.category_id = c.category_id
WHERE m.material_name = #{materialName}
AND m.material_id != #{excludeId}
ORDER BY m.material_id DESC
</select>
<!-- ========== 同类型物料横向对比 ========== -->
<!-- 获取所有有供应商报价记录的物料列表(用于对比选择框) -->
<select id="selectMaterialsWithSupplierQuotes" resultMap="BaseRM">
SELECT DISTINCT m.*, c.category_name AS category_name
FROM biz_material m
LEFT JOIN biz_material_category c ON m.category_id = c.category_id
WHERE EXISTS (
SELECT 1 FROM biz_quotation_item qi
JOIN biz_quotation q ON qi.quotation_id = q.quotation_id
JOIN biz_rfq_item ri ON qi.rfq_item_id = ri.item_id
WHERE ri.material_id = m.material_id
)
ORDER BY m.material_name, m.material_id DESC
</select>
<!-- 根据物料ID列表获取各供应商的详细报价明细用于对比展示 -->
<select id="selectSupplierQuoteComparison" resultType="java.util.Map">
SELECT
ri.material_id,
qi.unit_price,
qi.total_price,
qi.delivery_days,
q.quotation_id,
q.quote_no,
q.submit_time,
q.status AS quote_status,
s.supplier_id,
s.supplier_name,
s.contact AS supplier_contact,
s.phone AS supplier_phone
FROM biz_quotation_item qi
JOIN biz_quotation q ON qi.quotation_id = q.quotation_id
JOIN biz_supplier s ON q.supplier_id = s.supplier_id
JOIN biz_rfq_item ri ON qi.rfq_item_id = ri.item_id
WHERE ri.material_id IN
<foreach collection="list" item="id" open="(" separator="," close=")">#{id}</foreach>
ORDER BY ri.material_id, qi.unit_price ASC, q.submit_time DESC
</select>
</mapper>