Skip to content
切换导航条
切换导航条
当前项目
正在载入...
登录
孙克
/
smf-core
转到一个项目
切换导航栏
切换导航栏固定状态
项目
群组
代码片段
帮助
项目
活动
版本库
流水线
图表
问题
0
合并请求
0
维基
网络
创建新的问题
作业
提交
问题看板
文件
提交
网络
比较
分支
标签
Commit aea41fc3
由
LN
编写于
2022-03-15 14:05:21 +0800
浏览文件
选项
浏览文件
标签
下载
电子邮件补丁
差异文件
NLM料架扫码入库功能。合并库位可配置。
1 个父辈
8d8ec34d
显示空白字符变更
内嵌
并排
正在显示
5 个修改的文件
包含
417 行增加
和
4 行删除
src/main/java/com/neotel/smfcore/common/init/DataInitManager.java
src/main/java/com/neotel/smfcore/core/device/handler/impl/NLMShelfHandler.java
src/main/java/com/neotel/smfcore/core/storage/service/manager/IStoragePosManager.java
src/main/java/com/neotel/smfcore/core/storage/service/manager/impl/StoragePosManagerImpl.java
修改记录.txt
src/main/java/com/neotel/smfcore/common/init/DataInitManager.java
查看文件 @
aea41fc
...
...
@@ -217,8 +217,8 @@ public class DataInitManager {
materialBox
.
setHidden
(
true
);
outSet
.
setHidden
(
true
);
posOut
.
setHidden
(
true
);
//
zhuanruMenu.setHidden(true);
//
singleMenu.setHidden(true);
zhuanruMenu
.
setHidden
(
true
);
singleMenu
.
setHidden
(
true
);
// orderSet.setHidden(true);
menus
.
addAll
(
createMenus
(
poutOut
,
menuOrder
,
out
,
posOut
,
groupOut
,
materialBox
,
outSet
,
inOrderMenu
,
putinMenu
,
zhuanruMenu
,
singleMenu
));
...
...
@@ -257,6 +257,7 @@ public class DataInitManager {
Menu
menuLog
=
new
Menu
(
new
ArrayList
<
Menu
>(),
1
,
"taskLog"
,
"物料日志"
,
1
,
"taskLog"
,
"neolight/taskLog/index"
,
""
,
0
,
"education"
);
Menu
msgLog
=
new
Menu
(
new
ArrayList
<
Menu
>(),
1
,
"message"
,
"消息查询"
,
1
,
"message"
,
"neolight/message/index"
,
""
,
0
,
"messagefind"
);
Menu
exceptionLog
=
new
Menu
(
new
ArrayList
<
Menu
>(),
1
,
"interfaceException"
,
"接口异常"
,
1
,
"interfaceException"
,
"neolight/interfaceException/index"
,
""
,
0
,
"messagefind"
);
exceptionLog
.
setHidden
(
true
);
menus
.
addAll
(
createMenus
(
pMenuLog
,
menuLog
,
msgLog
,
exceptionLog
));
//报表:出入库、库存
...
...
src/main/java/com/neotel/smfcore/core/device/handler/impl/NLMShelfHandler.java
0 → 100644
查看文件 @
aea41fc
package
com
.
neotel
.
smfcore
.
core
.
device
.
handler
.
impl
;
import
cn.hutool.core.util.ObjectUtil
;
import
com.google.common.base.Strings
;
import
com.google.common.collect.Lists
;
import
com.neotel.smfcore.common.bean.ResultBean
;
import
com.neotel.smfcore.common.exception.ValidateException
;
import
com.neotel.smfcore.core.barcode.bean.CodeBean
;
import
com.neotel.smfcore.core.barcode.service.po.Barcode
;
import
com.neotel.smfcore.core.device.api.IOpAuthApi
;
import
com.neotel.smfcore.core.device.bean.StatusBean
;
import
com.neotel.smfcore.core.inList.util.InListCache
;
import
com.neotel.smfcore.core.order.service.manager.ILiteOrderManager
;
import
com.neotel.smfcore.core.storage.enums.DeviceType
;
import
com.neotel.smfcore.core.storage.service.po.Storage
;
import
com.neotel.smfcore.core.storage.service.po.StoragePos
;
import
com.neotel.smfcore.core.system.util.DevicesStatusUtil
;
import
com.neotel.smfcore.security.TokenProvider
;
import
com.neotel.smfcore.security.annotation.AnonymousAccess
;
import
io.swagger.annotations.Api
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.util.ObjectUtils
;
import
org.springframework.web.bind.annotation.*
;
import
javax.servlet.http.HttpServletRequest
;
import
java.awt.*
;
import
java.util.*
;
import
java.util.List
;
import
java.util.concurrent.ConcurrentHashMap
;
@Api
(
tags
=
"SHELF: NLM(移动料架/自动推荐库位/合并库位)"
)
@RestController
@Slf4j
public
class
NLMShelfHandler
extends
BaseDeviceHandler
{
public
NLMShelfHandler
(
List
<
IOpAuthApi
>
apiList
)
{
super
(
apiList
);
}
@Autowired
private
TokenProvider
tokenProvider
;
@Autowired
private
ILiteOrderManager
liteOrderManager
;
@Autowired
private
InListCache
inListCache
;
@Override
public
StatusBean
handleClientRequest
(
StatusBean
statusBean
,
HttpServletRequest
request
)
{
statusBean
.
setClientIp
(
request
.
getRemoteHost
());
handleMsg
(
statusBean
);
statusBean
=
saveAlarmAndHumidity
(
statusBean
);
if
(
statusBean
!=
null
){
Map
<
String
,
String
>
opMap
=
DevicesStatusUtil
.
getAndRemoveOp
(
statusBean
.
getCid
());
statusBean
.
addOp
(
opMap
);
}
return
statusBean
;
}
/**
* 操作库位灯(开灯,或关灯),如果有关联的合并库位,一起开关灯
* @param opKey
* @param storage
* @param pos
* @param colorStr
*/
private
void
opPosLight
(
String
opKey
,
Storage
storage
,
StoragePos
pos
,
String
colorStr
){
List
<
String
>
relatedPosNames
=
pos
.
getMergePosList
();
if
(
relatedPosNames
==
null
||
relatedPosNames
.
isEmpty
()){
relatedPosNames
=
new
ArrayList
<>();
relatedPosNames
.
add
(
pos
.
getPosName
());
log
.
info
(
"操作库位["
+
pos
.
getPosName
()+
"]"
+
opKey
);
}
else
{
log
.
info
(
"操作合并库位["
+
pos
.
getPosName
()+
"]"
+
opKey
);
}
for
(
String
posName
:
relatedPosNames
){
String
opStr
=
posName
;
if
(!
Strings
.
isNullOrEmpty
(
colorStr
)){
opStr
=
opStr
+
"="
+
colorStr
;
}
DevicesStatusUtil
.
appendOp
(
storage
.
getCid
(),
opKey
,
opStr
);
log
.
info
(
opKey
+
" : "
+
opStr
);
}
}
/**
* 开灯, 等6秒后关闭
*/
private
void
openAndCloseLights
(
final
Storage
storage
,
final
List
<
String
>
posNameList
,
final
long
delayCloseTime
,
String
color
){
final
String
cid
=
storage
.
getCid
();
if
(
posNameList
==
null
){
return
;
}
for
(
final
String
posName
:
posNameList
)
{
String
lightOnStr
=
posName
+
"="
+
color
;
DevicesStatusUtil
.
appendOp
(
cid
,
"open"
,
lightOnStr
);
log
.
info
(
"点亮库位:"
+
lightOnStr
);
//5秒后灭灯
Thread
closeTask
=
new
Thread
(
new
Runnable
()
{
@Override
public
void
run
()
{
try
{
Thread
.
sleep
(
delayCloseTime
);
log
.
info
(
storage
.
getName
()+
"["
+
cid
+
"]库位["
+
posName
+
"]灭灯"
);
DevicesStatusUtil
.
appendOp
(
cid
,
"close"
,
posName
);
}
catch
(
Exception
e
){
}
}
});
closeTask
.
start
();
}
}
//上一次入库的库位,用于扫下一条码时灭灯,key=storageId
private
static
Map
<
String
,
StoragePos
>
lastPutinPosMap
=
new
ConcurrentHashMap
<>();
/**
* 查找下一个空位,并且点亮灯
*/
@RequestMapping
(
"/api/nlmShelf/putInCode"
)
@ResponseBody
public
ResultBean
putInCode
(
@RequestBody
Map
<
String
,
String
>
mapValues
,
HttpServletRequest
request
)
{
String
code
=
mapValues
.
get
(
"code"
).
trim
();
String
groupId
=
mapValues
.
get
(
"group"
);
String
storageId
=
mapValues
.
get
(
"storageId"
);
if
(
ObjectUtils
.
isEmpty
(
code
))
{
throw
new
ValidateException
(
"smfcore.valueCanotNull"
,
"{0}不能为空"
,
new
String
[]{
"code"
});
}
if
(
groupId
==
null
&&
storageId
==
null
)
{
throw
new
ValidateException
(
"smfcore.valueCanotNull"
,
"{0}不能为空"
,
new
String
[]{
"group"
});
}
Storage
currentStorage
=
null
;
if
(
groupId
==
null
&&
storageId
!=
null
)
{
currentStorage
=
dataCache
.
getStorageById
(
storageId
);
if
(
currentStorage
==
null
||
!
currentStorage
.
isNLMShelf
())
{
return
ResultBean
.
newErrorResult
(
1
,
"smfcore.shelf.nlm.notFound"
,
"未找到移动料架{0}"
,
new
String
[]{
storageId
});
}
StoragePos
lastPutinPos
=
lastPutinPosMap
.
get
(
currentStorage
.
getId
());
if
(
lastPutinPos
!=
null
)
{
log
.
info
(
"扫码时关闭上一个库位:"
+
lastPutinPos
.
getPosName
());
opPosLight
(
"close"
,
currentStorage
,
lastPutinPos
,
""
);
}
groupId
=
currentStorage
.
getGroupId
();
}
if
(
groupId
!=
null
&&
groupId
.
equals
(
"-1"
))
{
groupId
=
""
;
}
if
(!
Strings
.
isNullOrEmpty
(
code
))
{
code
=
code
.
replace
(
"。"
,
"."
);
}
CodeBean
codeBean
=
codeResolve
.
resolveSingleCode
(
code
);
if
(!
codeBean
.
isValid
())
{
throw
new
ValidateException
(
"smfcore.error.barcode.invalid"
,
"{0}不是有效的条码"
,
new
String
[]{
code
});
}
Barcode
barcode
=
codeBean
.
getBarcode
();
Date
expireDate
=
barcode
.
getExpireDate
();
if
(
expireDate
!=
null
&&
System
.
currentTimeMillis
()
>
expireDate
.
getTime
())
{
throw
new
ValidateException
(
"smfcore.error.barcode.expired"
,
"物料已过期,无法入库."
);
}
if
(
barcode
.
getPlateSize
()
<=
1
)
{
//长宽为1的需要弹框设置尺寸
throw
new
ValidateException
(
"smfcore.error.barcode.errorSize"
,
"条码未设置尺寸"
);
}
try
{
StoragePos
inPos
=
storagePosManager
.
getByBarcodeId
(
barcode
.
getId
());
if
(
inPos
!=
null
)
{
String
posName
=
inPos
.
getPosName
();
List
<
String
>
mergePosList
=
inPos
.
getMergePosList
();
if
(
mergePosList
!=
null
&&
!
mergePosList
.
isEmpty
())
{
posName
=
""
;
for
(
String
posStr
:
mergePosList
)
{
posName
=
posName
+
","
+
posStr
;
}
posName
=
posName
.
substring
(
1
);
}
return
ResultBean
.
newErrorResult
(
99
,
"smfcore.shelf.msg.alreadyInPos"
,
"该物料已在库位["
+
posName
+
"]中"
,
new
String
[]{
posName
});
}
List
<
Storage
>
storages
=
new
ArrayList
<>();
//料仓是否为空
StoragePos
pos
=
null
;
if
(
currentStorage
!=
null
)
{
storages
.
add
(
currentStorage
);
pos
=
storagePosManager
.
getEmptyPosByStorage
(
currentStorage
,
barcode
,
taskService
.
excludePosIds
());
}
else
{
List
<
String
>
cids
=
dataCache
.
getCidsByGroupId
(
groupId
,
true
);
for
(
String
cid
:
cids
)
{
Storage
storage
=
dataCache
.
getStorage
(
cid
);
if
(
storage
.
isNLMShelf
())
{
storages
.
add
(
storage
);
pos
=
storagePosManager
.
getEmptyPosByStorage
(
storage
,
barcode
,
taskService
.
excludePosIds
());
if
(
pos
!=
null
)
{
currentStorage
=
storage
;
break
;
}
}
}
}
int
delayCloseTime
=
8000
;
String
color
=
"red"
;
if
(
pos
!=
null
)
{
log
.
info
(
barcode
.
getPartNumber
()
+
" [ "
+
barcode
.
getBarcode
()
+
" ] "
+
"入库到:"
+
currentStorage
.
getName
()
+
"["
+
currentStorage
.
getCid
()
+
"] "
+
pos
.
getPosName
());
taskService
.
addTaskToFinished
(
pos
,
barcode
,
currentStorage
.
getName
()
+
"-op"
);
openAndCloseLights
(
currentStorage
,
Lists
.<
String
>
newArrayList
(
pos
.
getPosName
()),
delayCloseTime
,
color
);
lastPutinPosMap
.
put
(
currentStorage
.
getCid
(),
pos
);
pos
.
setCanCheckOutTime
(
System
.
currentTimeMillis
()
+
delayCloseTime
);
log
.
info
(
":条码["
+
code
+
"]入库操作成功,请放入库位 ["
+
pos
.
getPosName
()
+
"]"
);
return
ResultBean
.
newOkResult
(
"smfcore.shelf.msg.inOk"
,
"操作成功,请放入库位["
+
pos
.
getPosName
()
+
"]"
,
new
String
[]{
pos
.
getPosName
()}
);
}
else
{
//库位没找到,查找同尺寸空的库位进行合并
List
<
StoragePos
>
continuitEmptyPosList
=
null
;
for
(
Storage
storage
:
storages
)
{
continuitEmptyPosList
=
storagePosManager
.
getSameSizeContinuityEmptyPosList
(
storage
,
barcode
);
if
(
continuitEmptyPosList
!=
null
&&
(
continuitEmptyPosList
.
size
()
>
0
))
{
currentStorage
=
storage
;
break
;
}
}
if
(
continuitEmptyPosList
!=
null
&&
(
continuitEmptyPosList
.
size
()>
0
)
)
{
//将第一个库位作为主库位,其他库位合并入此库位中
StoragePos
mainPos
=
continuitEmptyPosList
.
get
(
0
);
List
<
String
>
mergePosNameList
=
new
ArrayList
<>();
String
mergePosStr
=
""
;
for
(
StoragePos
storagePos
:
continuitEmptyPosList
)
{
log
.
info
(
"设置库位["
+
storagePos
.
getPosName
()
+
"]使用状态为:true"
);
storagePos
.
setUsed
(
true
);
storagePosManager
.
save
(
storagePos
);
mergePosNameList
.
add
(
storagePos
.
getPosName
());
mergePosStr
=
mergePosStr
+
" , "
+
storagePos
.
getPosName
();
}
mainPos
.
setUsed
(
true
);
mainPos
.
setMergePosList
(
mergePosNameList
);
storagePosManager
.
save
(
mainPos
);
pos
=
mainPos
;
lastPutinPosMap
.
put
(
currentStorage
.
getCid
(),
pos
);
log
.
info
(
"合并库位["
+
mergePosStr
+
"]到"
+
pos
.
getPosName
()
+
"中"
);
log
.
info
(
barcode
.
getPartNumber
()
+
" [ "
+
barcode
.
getBarcode
()
+
" ] "
+
"入库到:"
+
currentStorage
.
getName
()
+
"["
+
currentStorage
.
getCid
()
+
"] "
+
pos
.
getPosName
());
taskService
.
addTaskToFinished
(
pos
,
barcode
,
currentStorage
.
getName
()
+
"-op"
);
openAndCloseLights
(
currentStorage
,
mergePosNameList
,
delayCloseTime
,
color
);
return
ResultBean
.
newOkResult
(
"smfcore.shelf.msg.inMergeOk"
,
"操作成功,请合并库位[{0}]并放入料盘"
,
new
String
[]{
pos
.
getPosName
()},
""
);
}
else
{
String
sizeInfo
=
barcode
.
getPlateSize
()
+
" x "
+
barcode
.
getHeight
();
String
msg
=
"未找到适合["
+
sizeInfo
+
"]的库位"
;
log
.
info
(
msg
);
return
ResultBean
.
newErrorResult
(
99
,
"smfcore.shelf.msg.inError"
,
"未找到适合["
+
sizeInfo
+
"]的库位"
,
new
String
[]{
sizeInfo
}
);
}
}
}
catch
(
ValidateException
e
)
{
log
.
error
(
"入库出错:"
+
e
.
getMessage
());
return
ResultBean
.
newErrorResult
(
1
,
e
.
getMessage
(),
e
.
getMessage
(),
e
.
getMsgParam
());
}
}
/**
* 获取料架的库位占用情况
*/
@RequestMapping
(
"/service/store/nlmShelf/hasReelPosList"
)
@ResponseBody
@AnonymousAccess
public
ResultBean
checkAll
(
HttpServletRequest
request
){
String
cid
=
request
.
getParameter
(
"cid"
);
Storage
storage
=
dataCache
.
getStorage
(
cid
);
List
<
StoragePos
>
allPos
=
storagePosManager
.
findNotEmptyByStorageId
(
storage
.
getId
());
List
<
String
>
posList
=
new
ArrayList
<>();
for
(
StoragePos
pos
:
allPos
)
{
posList
.
add
(
pos
.
getPosName
());
}
return
ResultBean
.
newOkResult
(
posList
);
}
@Override
public
DeviceType
getDeviceType
()
{
return
DeviceType
.
NLM
;
}
}
src/main/java/com/neotel/smfcore/core/storage/service/manager/IStoragePosManager.java
查看文件 @
aea41fc
...
...
@@ -60,4 +60,8 @@ public interface IStoragePosManager extends IBaseManager<StoragePos> {
public
void
updateBarcodeMsd
(
String
pn
,
String
msl
,
String
thickness
);
void
download
(
List
<
StoragePos
>
storagePos
,
HttpServletResponse
response
,
Locale
locale
)
throws
IOException
;
List
<
StoragePos
>
findPosList
(
String
storageId
,
List
<
String
>
posNames
);
List
<
StoragePos
>
getSameSizeContinuityEmptyPosList
(
Storage
storage
,
Barcode
barcode
)
throws
ValidateException
;
}
src/main/java/com/neotel/smfcore/core/storage/service/manager/impl/StoragePosManagerImpl.java
查看文件 @
aea41fc
...
...
@@ -2,6 +2,7 @@ package com.neotel.smfcore.core.storage.service.manager.impl;
import
cn.hutool.core.util.ObjectUtil
;
import
com.google.common.base.Strings
;
import
com.google.common.collect.Lists
;
import
com.google.common.collect.Maps
;
import
com.neotel.smfcore.common.bean.PageData
;
import
com.neotel.smfcore.common.exception.ValidateException
;
...
...
@@ -37,6 +38,7 @@ import java.io.IOException;
import
java.text.DateFormat
;
import
java.text.SimpleDateFormat
;
import
java.util.*
;
import
java.util.concurrent.ConcurrentHashMap
;
@Service
@Slf4j
...
...
@@ -179,8 +181,34 @@ public class StoragePosManagerImpl implements IStoragePosManager {
}
@Override
public
StoragePos
save
(
StoragePos
object
)
throws
ValidateException
{
return
storagePosDao
.
save
(
object
);
public
List
<
StoragePos
>
findPosList
(
String
storageId
,
List
<
String
>
posNames
){
if
(
posNames
==
null
||
posNames
.
isEmpty
()){
return
Lists
.
newArrayList
();
}
Criteria
c
=
Criteria
.
where
(
"storageId"
).
is
(
storageId
)
.
and
(
"posName"
).
in
(
posNames
);
Query
q
=
new
Query
(
c
);
return
storagePosDao
.
findByQuery
(
q
);
}
@Override
public
StoragePos
save
(
StoragePos
storagePos
)
throws
ValidateException
{
if
(!
storagePos
.
isUsed
()){
//出库
List
<
String
>
mergePosNames
=
storagePos
.
getMergePosList
();
List
<
StoragePos
>
mergePosList
=
findPosList
(
storagePos
.
getStorageId
(),
mergePosNames
);
//解除相关合并库位的占用状态
for
(
StoragePos
mergePos
:
mergePosList
){
mergePos
.
setUsed
(
false
);
mergePos
.
setMergePosList
(
null
);
storagePosDao
.
save
(
mergePos
);
log
.
info
(
"设置合并的关联库位["
+
mergePos
.
getPosName
()+
"]使用状态为:false"
);
}
storagePos
.
setMergePosList
(
null
);
}
storagePos
=
storagePosDao
.
save
(
storagePos
);
//reSortStoragePosList(storage.getId());
log
.
debug
(
"Storage "
+
storagePos
.
getId
()
+
" was added new slot with id: "
+
storagePos
.
getId
());
return
storagePos
;
}
@Override
...
...
@@ -499,5 +527,84 @@ public class StoragePosManagerImpl implements IStoragePosManager {
}
FileUtil
.
downloadExcel
(
list
,
response
);
}
/**
* 查找同尺寸连续的库位,合并库位放置料盘,仅用于智能料架
* @param storage
* @param barcode
* @return
*/
@Override
public
List
<
StoragePos
>
getSameSizeContinuityEmptyPosList
(
Storage
storage
,
Barcode
barcode
)
throws
ValidateException
{
if
(
storage
==
null
||(!
storage
.
isNLMShelf
())){
//只适合移动料架NLM
throw
new
ValidateException
(
"smfcore.shelf.nlm.notFound"
,
"未找到移动料架{0}"
,
new
String
[]{
storage
.
getId
()});
}
if
(!
storage
.
isMergePos
()){
return
new
ArrayList
<>();
}
Criteria
c
=
Criteria
.
where
(
"storageId"
).
is
(
storage
.
getId
());
if
(
barcode
.
getPlateSize
()
>
7
){
c
=
c
.
and
(
"w"
).
gte
(
barcode
.
getPlateSize
());
}
else
{
c
=
c
.
and
(
"w"
).
is
(
barcode
.
getPlateSize
());
}
c
=
c
.
and
(
"h"
).
gte
(
0
);
//宽度大于等于料盘宽度,高度大于等于料盘高度
c
=
c
.
and
(
"enabled"
).
is
(
true
)
//可用
.
and
(
"used"
).
is
(
false
);
//未使用
Query
query
=
new
Query
(
c
);
//优先放入最合适的位置(根据尺寸),相同尺寸按优先级排序
query
.
with
(
Sort
.
by
(
Sort
.
Direction
.
ASC
,
"posName"
));
List
<
StoragePos
>
posList
=
storagePosDao
.
findByQuery
(
query
);
//把不连续的过滤掉
Map
<
String
,
StoragePos
>
posMap
=
new
ConcurrentHashMap
<>();
for
(
StoragePos
pos
:
posList
){
posMap
.
put
(
pos
.
getPosName
(),
pos
);
}
Set
<
String
>
posNames
=
posMap
.
keySet
();
for
(
String
posName
:
posNames
)
{
StoragePos
currentPos
=
posMap
.
get
(
posName
);
int
totalHeight
=
currentPos
.
getH
();
List
<
StoragePos
>
emptyPosList
=
new
ArrayList
<>();
emptyPosList
.
add
(
currentPos
);
String
nextPosName
=
posName
;
while
(
true
){
if
(
totalHeight
>=
barcode
.
getHeight
()){
return
emptyPosList
;
}
nextPosName
=
getNextPosName
(
nextPosName
);
StoragePos
nextPos
=
posMap
.
get
(
nextPosName
);
if
(
nextPos
==
null
){
break
;
}
emptyPosList
.
add
(
nextPos
);
totalHeight
=
totalHeight
+
currentPos
.
getH
();
}
}
return
new
ArrayList
<>();
}
/**
* 获取下一库位的库位名(后缀数字+1)
*/
private
String
getNextPosName
(
String
posName
){
String
posIndexStr
=
""
;
String
prefixStr
=
""
;
for
(
int
i
=
1
;
i
<=
posName
.
length
();
i
++){
char
c
=
posName
.
charAt
(
posName
.
length
()
-
i
);
if
(!
Character
.
isDigit
(
c
)){
prefixStr
=
posName
.
substring
(
0
,
posName
.
length
()
-
i
+
1
);
break
;
}
posIndexStr
=
c
+
posIndexStr
;
}
if
(
posIndexStr
.
isEmpty
()){
return
""
;
}
int
posIndex
=
Integer
.
valueOf
(
posIndexStr
);
int
nextPosIndex
=
posIndex
+
1
;
return
prefixStr
+
String
.
format
(
"%0"
+
posIndexStr
.
length
()+
"d"
,
nextPosIndex
);
}
}
修改记录.txt
查看文件 @
aea41fc
...
...
@@ -17,3 +17,13 @@
2.库位页面调整。
3.登录页面增加语言切换。
4.共享文件夹页面调整。
20220304:
个人中心增加进入调试模式功能。
20220307:
启用禁用库位增加操作日志。
20220314:
增加移动料架:NLM,入库时自动推荐库位,无合适库位时自动合并库位。
编写
预览
支持
Markdown
格式
附加文件
你添加了
0
人
到此讨论。请谨慎行事。
Finish editing this message first!
Cancel
请
注册
或
登录
后发表评论