refactor(heli): 重构物料编码管理功能

- 将物料大类编码字段从 matCatCode 统一改为 matTypeCode
- 移除前端界面中的删除按钮功能
- 更新表单验证逻辑,对最大流水号进行数字格式和长度校验
- 修改物料编码生成算法,优化流水号递增逻辑
- 在物料更新时自动同步更新对应物料大类的最大流水号
This commit is contained in:
zxy 2026-03-20 11:56:28 +08:00
parent dad15fb31e
commit 7f269c516f
9 changed files with 68 additions and 42 deletions

View File

@ -14,9 +14,6 @@ import static com.chanko.yunxi.mes.framework.common.util.date.DateUtils.FORMAT_Y
@ToString(callSuper = true) @ToString(callSuper = true)
public class MatCodePageReqVO extends PageParam { public class MatCodePageReqVO extends PageParam {
@Schema(description = "物料大类编码")
private String matCatCode;
@Schema(description = "物料物料大类名称", example = "芋艿") @Schema(description = "物料物料大类名称", example = "芋艿")
private String matCatName; private String matCatName;

View File

@ -13,10 +13,6 @@ public class MatCodeSaveReqVO {
@Schema(description = "自增字段,唯一", requiredMode = Schema.RequiredMode.REQUIRED, example = "20351") @Schema(description = "自增字段,唯一", requiredMode = Schema.RequiredMode.REQUIRED, example = "20351")
private Long id; private Long id;
@Schema(description = "物料大类编码", requiredMode = Schema.RequiredMode.REQUIRED)
// @NotEmpty(message = "物料大类编码不能为空")
private String matCatCode;
@Schema(description = "物料大类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "刚材") @Schema(description = "物料大类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "刚材")
// @NotEmpty(message = "大类名称不能为空") // @NotEmpty(message = "大类名称不能为空")
private String matCatName; private String matCatName;

View File

@ -24,10 +24,6 @@ public class MatCodeDO extends BaseDO {
*/ */
@TableId @TableId
private Long id; private Long id;
/**
* 物料大类编码
*/
private String matCatCode;
/** /**
* 物料物料大类名称 * 物料物料大类名称
*/ */

View File

@ -19,7 +19,7 @@ public interface MatCodeMapper extends BaseMapperX<MatCodeDO> {
default PageResult<MatCodeDO> selectPage(MatCodePageReqVO reqVO) { default PageResult<MatCodeDO> selectPage(MatCodePageReqVO reqVO) {
return selectPage(reqVO, new LambdaQueryWrapperX<MatCodeDO>() return selectPage(reqVO, new LambdaQueryWrapperX<MatCodeDO>()
.eqIfPresent(MatCodeDO::getMatCatCode, reqVO.getMatCatCode()) .eqIfPresent(MatCodeDO::getMatTypeCode, reqVO.getMatTypeCode())
.likeIfPresent(MatCodeDO::getMatCatName, reqVO.getMatCatName()) .likeIfPresent(MatCodeDO::getMatCatName, reqVO.getMatCatName())
.eqIfPresent(MatCodeDO::getMatTypeCode, reqVO.getMatTypeCode()) .eqIfPresent(MatCodeDO::getMatTypeCode, reqVO.getMatTypeCode())
.eqIfPresent(MatCodeDO::getCurMaxSeq, reqVO.getCurMaxSeq()) .eqIfPresent(MatCodeDO::getCurMaxSeq, reqVO.getCurMaxSeq())
@ -30,12 +30,12 @@ public interface MatCodeMapper extends BaseMapperX<MatCodeDO> {
default MatCodeDO selectByMatCatCode(String matCatCode) { default MatCodeDO selectByMatCatCode(String matCatCode) {
return selectOne(new LambdaQueryWrapperX<MatCodeDO>() return selectOne(new LambdaQueryWrapperX<MatCodeDO>()
.eq(MatCodeDO::getMatCatCode, matCatCode)); .eq(MatCodeDO::getMatTypeCode, matCatCode));
} }
default MatCodeDO selectByMatCatCodeAndIdNot(String matCatCode, Long id) { default MatCodeDO selectByMatCatCodeAndIdNot(String matCatCode, Long id) {
return selectOne(new LambdaQueryWrapperX<MatCodeDO>() return selectOne(new LambdaQueryWrapperX<MatCodeDO>()
.eq(MatCodeDO::getMatCatCode, matCatCode) .eq(MatCodeDO::getMatTypeCode, matCatCode)
.ne(MatCodeDO::getId, id)); .ne(MatCodeDO::getId, id));
} }

View File

@ -30,6 +30,9 @@ public interface MatCodeService {
*/ */
void updateMatCode(@Valid MatCodeSaveReqVO updateReqVO); void updateMatCode(@Valid MatCodeSaveReqVO updateReqVO);
void updateCurMaxSeq(String matTypeCode);
/** /**
* 删除物料大类编码维护 * 删除物料大类编码维护
* *

View File

@ -35,23 +35,24 @@ public class MatCodeServiceImpl implements MatCodeService {
public static String generateMaterialCode(String matTypeCode, String curMaxSeq) { public static String generateMaterialCode(String matTypeCode, String curMaxSeq) {
try { try {
int matCode = Integer.parseInt(matTypeCode); String curMax = getString(curMaxSeq);
// curMaxSeq 转换为数字 return matTypeCode + curMax;
int curMaxSeqNum = Integer.parseInt(curMaxSeq) + 1;
int ss = matCode + curMaxSeqNum;
// ss 转为字符串不足 5 位补 前面补充0
return String.format("%05d", ss);
} catch (Exception e) { } catch (Exception e) {
throw exception(ErrorCodeConstants.MAT_CAT_CODE_ERROR); throw exception(ErrorCodeConstants.MAT_CAT_CODE_ERROR);
} }
} }
private static String getString(String curMaxSeq) {
int length = curMaxSeq.length();
int curMaxSeqNum = Integer.parseInt(curMaxSeq) + 1;
return String.format("%0" + length + "d", curMaxSeqNum);
}
@Override @Override
public Long createMatCode(MatCodeSaveReqVO createReqVO) { public Long createMatCode(MatCodeSaveReqVO createReqVO) {
// 校验 matCatCode 唯一性 // 校验 matCatCode 唯一性
validateMatCatCodeUnique(null, createReqVO.getMatCatCode()); validateMatCatCodeUnique(null, createReqVO.getMatTypeCode());
// 插入 // 插入
MatCodeDO matCode = BeanUtils.toBean(createReqVO, MatCodeDO.class); MatCodeDO matCode = BeanUtils.toBean(createReqVO, MatCodeDO.class);
matCodeMapper.insert(matCode); matCodeMapper.insert(matCode);
@ -64,12 +65,21 @@ public class MatCodeServiceImpl implements MatCodeService {
// 校验存在 // 校验存在
validateMatCodeExists(updateReqVO.getId()); validateMatCodeExists(updateReqVO.getId());
// 校验 matCatCode 唯一性更新时允许更新自己 // 校验 matCatCode 唯一性更新时允许更新自己
validateMatCatCodeUnique(updateReqVO.getId(), updateReqVO.getMatCatCode()); validateMatCatCodeUnique(updateReqVO.getId(), updateReqVO.getMatTypeCode());
// 更新 // 更新
MatCodeDO updateObj = BeanUtils.toBean(updateReqVO, MatCodeDO.class); MatCodeDO updateObj = BeanUtils.toBean(updateReqVO, MatCodeDO.class);
matCodeMapper.updateById(updateObj); matCodeMapper.updateById(updateObj);
} }
@Override
public void updateCurMaxSeq(String matTypeCode) {
MatCodeDO matCode = getByMatCatCode(matTypeCode);
String string = getString(matCode.getCurMaxSeq());
matCode.setCurMaxSeq(string);
matCodeMapper.updateById(matCode);
}
/** /**
* 校验物料大类编码唯一性 * 校验物料大类编码唯一性
* *

View File

@ -23,6 +23,7 @@ import com.chanko.yunxi.mes.module.heli.dal.mysql.material.MaterialMapper;
import com.chanko.yunxi.mes.module.heli.dal.mysql.storageinventory.StorageInventoryMapper; import com.chanko.yunxi.mes.module.heli.dal.mysql.storageinventory.StorageInventoryMapper;
import com.chanko.yunxi.mes.module.heli.enums.CodeEnum; import com.chanko.yunxi.mes.module.heli.enums.CodeEnum;
import com.chanko.yunxi.mes.module.heli.enums.MaterialTypeEnum; import com.chanko.yunxi.mes.module.heli.enums.MaterialTypeEnum;
import com.chanko.yunxi.mes.module.heli.service.matcode.MatCodeService;
import com.chanko.yunxi.mes.module.heli.service.serialnumber.SerialNumberService; import com.chanko.yunxi.mes.module.heli.service.serialnumber.SerialNumberService;
import com.chanko.yunxi.mes.module.heli.service.storage.StorageService; import com.chanko.yunxi.mes.module.heli.service.storage.StorageService;
import com.chanko.yunxi.mes.module.heli.service.storagelog.StorageLogService; import com.chanko.yunxi.mes.module.heli.service.storagelog.StorageLogService;
@ -65,6 +66,9 @@ public class MaterialServiceImpl implements MaterialService {
@Resource @Resource
private StorageInventoryMapper storageInventoryMapper; private StorageInventoryMapper storageInventoryMapper;
@Resource
private MatCodeService matCodeService;
@PostConstruct @PostConstruct
public void init(){ public void init(){
@ -131,6 +135,7 @@ public class MaterialServiceImpl implements MaterialService {
} }
} }
@Transactional(rollbackFor = Exception.class)
@Override @Override
public void updateMaterial(MaterialSaveReqVO updateReqVO) { public void updateMaterial(MaterialSaveReqVO updateReqVO) {
// 校验存在 // 校验存在
@ -140,6 +145,8 @@ public class MaterialServiceImpl implements MaterialService {
// 重复性判断 // 重复性判断
validateMaterialRepeat(updateObj.getCode(), updateReqVO.getId()); validateMaterialRepeat(updateObj.getCode(), updateReqVO.getId());
materialMapper.updateById(updateObj); materialMapper.updateById(updateObj);
// 更新物料大类最大流水
matCodeService.updateCurMaxSeq(updateObj.getMatCate());
} }
@Override @Override

View File

@ -8,8 +8,8 @@
label-width="180px" label-width="180px"
v-loading="formLoading" v-loading="formLoading"
> >
<el-form-item label="物料大类" prop="matCatCode"> <el-form-item label="物料大类" prop="matTypeCode">
<el-select v-model="formData.matCatCode" clearable placeholder="请选择物料大类" @change="handleMatCatChange" > <el-select v-model="formData.matTypeCode" clearable placeholder="请选择物料大类" @change="handleMatCatChange" >
<el-option <el-option
v-for="dict in getStrDictOptions(DICT_TYPE.HELI_MATERIAL_CODE)" v-for="dict in getStrDictOptions(DICT_TYPE.HELI_MATERIAL_CODE)"
:key="dict.value" :key="dict.value"
@ -18,11 +18,12 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item label="物料分类编码" prop="matTypeCode" > <el-form-item label="物料分类编码" prop="matTypeCode" >
<el-input v-model="formData.matTypeCode" placeholder="请输入物料分类编码" maxlength="10" show-word-limit/> <el-input v-model="formData.matTypeCode" placeholder="请输入物料分类编码" show-word-limit disabled/>
</el-form-item> </el-form-item>
<el-form-item label="最大流水号" prop="curMaxSeq" > <el-form-item label="最大流水号" prop="curMaxSeq" >
<el-input v-model="formData.curMaxSeq" placeholder="请输入当前最大流水号" maxlength="5" show-word-limit/> <el-input v-model="formData.curMaxSeq" placeholder="请输入当前最大流水号" maxlength="6" show-word-limit/>
</el-form-item> </el-form-item>
<el-form-item label="状态" prop="status"> <el-form-item label="状态" prop="status">
<el-radio-group v-model="formData.status"> <el-radio-group v-model="formData.status">
@ -38,6 +39,7 @@
</Dialog> </Dialog>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { nextTick } from 'vue'
import * as MatCodeApi from '@/api/heli/matcode' import * as MatCodeApi from '@/api/heli/matcode'
import {DICT_TYPE, getStrDictOptions} from "@/utils/dict"; import {DICT_TYPE, getStrDictOptions} from "@/utils/dict";
@ -64,7 +66,28 @@ const formRules = reactive({
], ],
curMaxSeq: [ curMaxSeq: [
{ required: true, message: '最大流水号不能为空', trigger: 'blur' }, { required: true, message: '最大流水号不能为空', trigger: 'blur' },
{ max: 5, message: '最大流水号最多5个字符', trigger: 'blur' } {
validator: (rule, value, callback) => {
if (value === '' || value === null || value === undefined) {
callback()
return
}
//
if (!/^\d+$/.test(value)) {
callback(new Error('最大流水号只能输入数字'))
return
}
// + = 8
const matTypeCode = formData.value.matTypeCode || ''
const curMaxSeqStr = String(value)
if (matTypeCode.length + curMaxSeqStr.length !== 8) {
callback(new Error('最大流水号格式不正确!'))
return
}
callback()
},
trigger: 'blur'
}
], ],
status: [{ required: true, message: '状态不能为空', trigger: 'blur' }], status: [{ required: true, message: '状态不能为空', trigger: 'blur' }],
}) })
@ -116,7 +139,6 @@ const submitForm = async () => {
const resetForm = () => { const resetForm = () => {
formData.value = { formData.value = {
id: undefined, id: undefined,
matCatCode: undefined,
matCatName: undefined, matCatName: undefined,
matTypeCode: undefined, matTypeCode: undefined,
curMaxSeq: undefined, curMaxSeq: undefined,
@ -134,8 +156,12 @@ const handleMatCatChange = (value) => {
const dictOptions = getStrDictOptions(DICT_TYPE.HELI_MATERIAL_CODE) const dictOptions = getStrDictOptions(DICT_TYPE.HELI_MATERIAL_CODE)
const selected = dictOptions.find(dict => dict.value === value) const selected = dictOptions.find(dict => dict.value === value)
if (selected) { if (selected) {
formData.value.matCatCode = selected.value formData.value.matTypeCode = selected.value
formData.value.matCatName = selected.label formData.value.matCatName = selected.label
} }
//
nextTick(() => {
formRef.value?.validateField('curMaxSeq')
})
} }
</script> </script>

View File

@ -8,8 +8,8 @@
:inline="true" :inline="true"
label-width="90px" label-width="90px"
> >
<el-form-item label="物料大类" prop="matCatCode"> <el-form-item label="物料大类" prop="matTypeCode">
<el-select v-model="queryParams.matCatCode" clearable placeholder="请选择物料大类" class="!w-250px"> <el-select v-model="queryParams.matTypeCode" clearable placeholder="请选择物料大类" class="!w-250px">
<el-option <el-option
v-for="dict in getStrDictOptions(DICT_TYPE.HELI_MATERIAL_CODE)" v-for="dict in getStrDictOptions(DICT_TYPE.HELI_MATERIAL_CODE)"
:key="dict.value" :key="dict.value"
@ -49,7 +49,6 @@
<ContentWrap> <ContentWrap>
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true"> <el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
<el-table-column label="序号" type="index" align="center" width="60px"/> <el-table-column label="序号" type="index" align="center" width="60px"/>
<el-table-column label="物料大类编码" align="center" prop="matCatCode" />
<el-table-column label="物料大类名称" align="center" prop="matCatName" /> <el-table-column label="物料大类名称" align="center" prop="matCatName" />
<el-table-column label="物料分类编码" align="center" prop="matTypeCode" /> <el-table-column label="物料分类编码" align="center" prop="matTypeCode" />
<el-table-column label="当前最大流水号" align="center" prop="curMaxSeq" /> <el-table-column label="当前最大流水号" align="center" prop="curMaxSeq" />
@ -78,14 +77,7 @@
> >
编辑 编辑
</el-button> </el-button>
<el-button
link
type="danger"
@click="handleDelete(scope.row.id)"
v-hasPermi="['heli:mat-code:delete']"
>
删除
</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -120,7 +112,6 @@ const total = ref(0) // 列表的总页数
const queryParams = reactive({ const queryParams = reactive({
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 10,
matCatCode: undefined,
matCatName: undefined, matCatName: undefined,
matTypeCode: undefined, matTypeCode: undefined,
curMaxSeq: undefined, curMaxSeq: undefined,