# 计量单位转换业务使用文档

## 一、系统概述

计量单位转换提供统一的计量单位转换服务，支持同一量纲内的单位自动转换。采用**单向配置、双向生效**机制，只需配置"非基准单位 → 基准单位"的转换规则，自动推导反向和间接转换。

**核心特性**：
- 单向配置、双向生效的转换机制
- 支持按单位ID、符号、名称进行转换
- 高精度计算，支持批量操作
- 跨模块统一服务

## 二、内容配置

### 2.1 管理菜单路径
后台管理 → 基础管理 → 计量单位 → 计量单位管理

### 2.2 配置功能

#### 计量量纲管理
- **功能**：创建和管理不同的量纲类型（如重量、长度、体积等）
- **操作**：新增量纲、编辑量纲信息、删除量纲
- **每个量纲只能设置一个基准单位**

#### 计量单位管理
- **功能**：创建和管理具体的计量单位
- **操作**：新增单位、编辑单位信息、删除单位
- **关联量纲**：将单位归属到具体的量纲下

#### 转换规则配置
- **功能**：配置单位间的转换规则
- **配置原则**：只需配置"非基准单位 → 基准单位"
- **自动推导**：系统自动推导反向转换和间接转换

### 2.3 配置建议

1. **量纲规划**：提前规划好业务需要的量纲类型
2. **基准单位选择**：选择业务中最常用、最稳定的单位作为基准
3. **转换规则**：优先使用整数转换系数，提高计算精度
4. **定期校验**：使用转换路径校验功能确保配置正确性
5. **转换完整性校验**：系统提供同一量纲内所有单位能否互相转换的校验功能，确保转换配置的完整性

## 三、API接口清单

### 3.1 单位管理接口

| 接口 | 方法 | 路径 | 说明 | API文档 |
|------|------|------|------|---------|
| 获取量纲树 | GET | `/admin-api/base/unit-management/unit-quantity/tree` | 获取量纲和单位树形结构 | [文档](http://172.16.46.63:30081/doc.html#/base-server/%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%20-%20%E8%AE%A1%E9%87%8F%E5%8D%95%E4%BD%8D%E9%87%8F/getUnitQuantityTree) |
| 获取单位列表 | GET | `/admin-api/base/unit-management/unt-info/page` | 获取单位列表（用于下拉选择） | [文档](http://172.16.46.63:30081/doc.html#/base-server/%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%20-%20%E8%AE%A1%E9%87%8F%E5%8D%95%E4%BD%8D/getUntInfoPage) |

### 3.2 单位转换接口

| 接口 | 方法 | 路径 | 说明 | API文档 |
|------|------|------|------|---------|
| 按ID转换单位 | POST | `/admin-api/base/unit-management/unit-conversion/convert` | 通过单位ID转换 | [文档](http://172.16.46.63:30081/doc.html#/base-server/%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%20-%20%E5%8D%95%E4%BD%8D%E8%BD%AC%E6%8D%A2/convert) |
| 按符号转换单位 | POST | `/admin-api/base/unit-management/unit-conversion/convert-by-symbol` | 通过单位符号转换 | [文档](http://172.16.46.63:30081/doc.html#/base-server/%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%20-%20%E5%8D%95%E4%BD%8D%E8%BD%AC%E6%8D%A2/convertBySymbol) |
| 按名称转换单位 | POST | `/admin-api/base/unit-management/unit-conversion/convert-by-name` | 通过单位名称转换 | [文档](http://172.16.46.63:30081/doc.html#/base-server/%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%20-%20%E5%8D%95%E4%BD%8D%E8%BD%AC%E6%8D%A2/convertByName) |
| 批量ID转换 | POST | `/admin-api/base/unit-management/unit-conversion/batch-convert` | 按ID批量转换 | [文档](http://172.16.46.63:30081/doc.html#/base-server/%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%20-%20%E5%8D%95%E4%BD%8D%E8%BD%AC%E6%8D%A2/batchConvert) |
| 批量符号转换 | POST | `/admin-api/base/unit-management/unit-conversion/batch-convert-by-symbol` | 按符号批量转换 | [文档](http://172.16.46.63:30081/doc.html#/base-server/%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%20-%20%E5%8D%95%E4%BD%8D%E8%BD%AC%E6%8D%A2/batchConvertBySymbol) |
| 批量名称转换 | POST | `/admin-api/base/unit-management/unit-conversion/batch-convert-by-name` | 按名称批量转换 | [文档](http://172.16.46.63:30081/doc.html#/base-server/%E7%AE%A1%E7%90%86%E5%90%8E%E5%8F%B0%20-%20%E5%8D%95%E4%BD%8D%E8%BD%AC%E6%8D%A2/batchConvertByName) |


---

## 三、后端业务调用示例

### base模块内使用

```java
@Service
public class PurchaseOrderServiceImpl {

    @Resource
    private UnitConversionService unitConversionService;

    /**
     * 处理采购订单，统一转换为千克计算
     */
    public void processPurchaseOrder(PurchaseOrderSaveReqVO orderVO) {
        for (PurchaseOrderDetailVO detail : orderVO.getDetails()) {
            // 方式1：按符号转换
            UnitConvertBySymbolReqVO convertReq = new UnitConvertBySymbolReqVO();
            convertReq.setSrcUnitSymbol(detail.getUnt());
            convertReq.setTgtUnitSymbol("kg");
            convertReq.setValue(detail.getQty());
            convertReq.setPrecision(6);

            UnitConvertRespVO result = unitConversionService.convertBySymbol(convertReq);
            BigDecimal standardQuantity = result.getConvertedValue();

            // 方式2：按ID转换（如果有单位ID）
            // UnitConvertReqVO convertReq = new UnitConvertReqVO();
            // convertReq.setSrcUntId(detail.getUntId());
            // convertReq.setTgtUntId(kgUnitId);
            // ...
        }
    }
}
```

---

## 四、跨模块调用

### 4.1 直接Service调用（推荐）

在同一服务内直接注入使用：
```java
@Resource
private UnitConversionService unitConversionService;
```

### 4.2 跨服务调用（按需使用）

**1. 在 API 模块中定义 Feign 接口：**

```java
package com.zt.plat.module.base.api;

import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.module.base.enums.ApiConstants;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

@FeignClient(name = ApiConstants.NAME)
@Tag(name = "RPC 服务 - 单位转换")
public interface UnitConversionApi {

    String PREFIX = ApiConstants.PREFIX + "/unit-conversion";

    @PostMapping(PREFIX + "/convert")
    @Operation(summary = "按ID转换单位")
    CommonResult<UnitConvertRespVO> convert(@RequestBody UnitConvertReqVO reqVO);

    @PostMapping(PREFIX + "/convert-by-symbol")
    @Operation(summary = "按符号转换单位")
    CommonResult<UnitConvertRespVO> convertBySymbol(@RequestBody UnitConvertBySymbolReqVO reqVO);
}
```

**2. 在其他服务中调用：**

```java
@Service
public class PurchaseServiceImpl {

    @Resource
    private UnitConversionApi unitConversionApi;

    public void processPurchase(PurchaseVO purchase) {
        UnitConvertBySymbolReqVO convertReq = new UnitConvertBySymbolReqVO();
        convertReq.setSrcUnitSymbol(purchase.getUnit());
        convertReq.setTgtUnitSymbol("kg");
        convertReq.setValue(purchase.getQuantity());
        convertReq.setPrecision(6);

        CommonResult<UnitConvertRespVO> result = unitConversionApi.convertBySymbol(convertReq);
        if (result.isSuccess()) {
            BigDecimal standardQty = result.getData().getConvertedValue();
            // 业务处理
        }
    }
}
```

---

## 五、前端使用

### 5.1 基本API调用

```typescript
// 获取量纲树
export const getUnitQuantityTree = () => {
  return request.get('/admin-api/base/unit-management/unit-quantity/tree')
}

// 获取单位列表
export const getUntInfoPage = (params: any) => {
  return request.get('/admin-api/base/unit-management/unt-info/page', { params })
}

// 单位转换
export const convertUnitBySymbol = (data: any) => {
  return request.post('/admin-api/base/unit-management/unit-conversion/convert-by-symbol', data)
}
```

---

## 六、常见问题

**Q1: 前端如何获取单位选项？**

A: 使用 `/admin-api/base/unit-management/unit-quantity/tree` 获取量纲树，然后根据选择的量纲调用 `/admin-api/base/unit-management/unt-info/page` 获取单位列表。

**Q2: 按ID转换和按符号转换哪个更好？**

A: 按ID转换更稳定，因为数据库ID不会变化。建议在前端保存单位ID，在业务转换时使用ID调用。

**Q3: 跨服务调用需要特殊配置吗？**

A: 不需要，项目已经统一配置好。所有Feign客户端都使用 `name = "base-server"`，路径使用 `/rpc-api` 前缀。

**Q4: 批量转换性能问题？**

A: 使用批量接口，设置ignoreErrors=true。

