Skip to content
切换导航条
切换导航条
当前项目
正在载入...
登录
孙克
/
smf-core
转到一个项目
切换导航栏
切换导航栏固定状态
项目
群组
代码片段
帮助
项目
活动
版本库
流水线
图表
问题
0
合并请求
0
维基
网络
创建新的问题
作业
提交
问题看板
文件
提交
网络
比较
分支
标签
Commit 9c5e4fc6
由
LN
编写于
2025-11-11 15:44:47 +0800
浏览文件
选项
浏览文件
标签
下载
差异文件
Merge remote-tracking branch 'origin/master'
2 个父辈
4ece61d5
4b69d55c
隐藏空白字符变更
内嵌
并排
正在显示
20 个修改的文件
包含
1640 行增加
和
15 行删除
src/main/java/com/neotel/smfcore/common/utils/DateUtil.java
src/main/java/com/neotel/smfcore/core/barcode/bean/BarcodeRule.java
src/main/java/com/neotel/smfcore/core/barcode/service/manager/impl/ComponentManagerImpl.java
src/main/java/com/neotel/smfcore/core/device/handler/impl/NLPShelfHandler.java
src/main/java/com/neotel/smfcore/core/device/handler/impl/TailingMaterialBoxHandler.java
src/main/java/com/neotel/smfcore/core/device/rest/DualPosNameDeviceController.java
src/main/java/com/neotel/smfcore/core/kanban/rest/BoxKanbanController.java
src/main/java/com/neotel/smfcore/core/kanban/rest/utils/NaturalOrderComparator.java
src/main/java/com/neotel/smfcore/core/storage/enums/DeviceType.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
src/main/java/com/neotel/smfcore/core/system/util/TaskService.java
src/main/java/com/neotel/smfcore/custom/neotel/NeotelApi.java
src/main/resources/messages.properties
src/main/resources/messages_de_DE.properties
src/main/resources/messages_en_US.properties
src/main/resources/messages_fr_FR.properties
src/main/resources/messages_ja_JP.properties
src/main/resources/messages_zh_CN.properties
src/main/resources/messages_zh_TW.properties
src/main/java/com/neotel/smfcore/common/utils/DateUtil.java
查看文件 @
9c5e4fc
...
@@ -99,7 +99,18 @@ public class DateUtil {
...
@@ -99,7 +99,18 @@ public class DateUtil {
}
catch
(
Exception
pe
)
{
}
catch
(
Exception
pe
)
{
log
.
error
(
"Parse ["
+
strDate
+
"] to date Exception: "
+
pe
.
getMessage
());
log
.
error
(
"Parse ["
+
strDate
+
"] to date Exception: "
+
pe
.
getMessage
());
//throw new ParseException(pe.getMessage(), pe.getErrorOffset());
//throw new ParseException(pe.getMessage(), pe.getErrorOffset());
return
null
;
date
=
null
;
}
if
(
date
==
null
){
try
{
df
.
setLenient
(
true
);
date
=
df
.
parse
(
strDate
);
}
catch
(
Exception
pe
)
{
log
.
error
(
"Parse ["
+
strDate
+
"] to date Exception: "
+
pe
.
getMessage
());
//throw new ParseException(pe.getMessage(), pe.getErrorOffset());
return
null
;
}
}
}
return
(
date
);
return
(
date
);
...
...
src/main/java/com/neotel/smfcore/core/barcode/bean/BarcodeRule.java
查看文件 @
9c5e4fc
...
@@ -672,6 +672,7 @@ public class BarcodeRule {
...
@@ -672,6 +672,7 @@ public class BarcodeRule {
b
.
setMemo
(
memo
);
b
.
setMemo
(
memo
);
}
}
reelId
=
reelId
.
trim
();
b
.
setBarcode
(
reelId
);
b
.
setBarcode
(
reelId
);
codeBean
.
setCodeStr
(
reelId
);
codeBean
.
setCodeStr
(
reelId
);
partNumber
=
partNumber
.
trim
();
partNumber
=
partNumber
.
trim
();
...
...
src/main/java/com/neotel/smfcore/core/barcode/service/manager/impl/ComponentManagerImpl.java
查看文件 @
9c5e4fc
...
@@ -65,8 +65,9 @@ public class ComponentManagerImpl implements IComponentManager {
...
@@ -65,8 +65,9 @@ public class ComponentManagerImpl implements IComponentManager {
@Override
@Override
public
Component
findByPartNumberAndProvider
(
String
partNumber
,
String
provider
)
{
public
Component
findByPartNumberAndProvider
(
String
partNumber
,
String
provider
)
{
if
(
StringUtils
.
isEmpty
(
partNumber
))
if
(
StringUtils
.
isEmpty
(
partNumber
))
{
return
null
;
return
null
;
}
else
{
else
{
Component
component
=
componentDao
.
findOneByCondition
(
new
String
[]{
"partNumber"
,
"provider"
},
new
String
[]{
partNumber
,
provider
});
Component
component
=
componentDao
.
findOneByCondition
(
new
String
[]{
"partNumber"
,
"provider"
},
new
String
[]{
partNumber
,
provider
});
if
(
component
==
null
)
{
if
(
component
==
null
)
{
...
...
src/main/java/com/neotel/smfcore/core/device/handler/impl/NLPShelfHandler.java
查看文件 @
9c5e4fc
...
@@ -11,6 +11,9 @@ import com.neotel.smfcore.core.barcode.service.po.Barcode;
...
@@ -11,6 +11,9 @@ import com.neotel.smfcore.core.barcode.service.po.Barcode;
import
com.neotel.smfcore.core.device.bean.StatusBean
;
import
com.neotel.smfcore.core.device.bean.StatusBean
;
import
com.neotel.smfcore.core.device.enums.OP
;
import
com.neotel.smfcore.core.device.enums.OP
;
import
com.neotel.smfcore.core.device.enums.OP_STATUS
;
import
com.neotel.smfcore.core.device.enums.OP_STATUS
;
import
com.neotel.smfcore.core.message.enums.MessageType
;
import
com.neotel.smfcore.core.message.service.manager.IMessageManager
;
import
com.neotel.smfcore.core.message.service.po.Message
;
import
com.neotel.smfcore.core.order.enums.ORDER_COLOR
;
import
com.neotel.smfcore.core.order.enums.ORDER_COLOR
;
import
com.neotel.smfcore.core.storage.enums.DeviceType
;
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.Storage
;
...
@@ -18,9 +21,6 @@ import com.neotel.smfcore.core.storage.service.po.StoragePos;
...
@@ -18,9 +21,6 @@ import com.neotel.smfcore.core.storage.service.po.StoragePos;
import
com.neotel.smfcore.core.system.bean.OrderSetting
;
import
com.neotel.smfcore.core.system.bean.OrderSetting
;
import
com.neotel.smfcore.core.system.service.po.DataLog
;
import
com.neotel.smfcore.core.system.service.po.DataLog
;
import
com.neotel.smfcore.core.system.util.DevicesStatusUtil
;
import
com.neotel.smfcore.core.system.util.DevicesStatusUtil
;
import
com.neotel.smfcore.core.system.websocket.MsgType
;
import
com.neotel.smfcore.core.system.websocket.SocketMsg
;
import
com.neotel.smfcore.core.system.websocket.WebSocketServer
;
import
com.neotel.smfcore.security.TokenProvider
;
import
com.neotel.smfcore.security.TokenProvider
;
import
com.neotel.smfcore.security.annotation.AnonymousAccess
;
import
com.neotel.smfcore.security.annotation.AnonymousAccess
;
import
com.neotel.smfcore.security.service.manager.IUserManager
;
import
com.neotel.smfcore.security.service.manager.IUserManager
;
...
@@ -48,6 +48,9 @@ public class NLPShelfHandler extends BaseDeviceHandler {
...
@@ -48,6 +48,9 @@ public class NLPShelfHandler extends BaseDeviceHandler {
@Autowired
@Autowired
private
IUserManager
userManager
;
private
IUserManager
userManager
;
@Autowired
private
IMessageManager
messageManager
;
/**
/**
* 扫码
* 扫码
*/
*/
...
@@ -327,11 +330,24 @@ public class NLPShelfHandler extends BaseDeviceHandler {
...
@@ -327,11 +330,24 @@ public class NLPShelfHandler extends BaseDeviceHandler {
}
}
}
}
//先获取到上一次缓存的信息
List
<
List
<
String
>>
lastDeviceData
=
DevicesStatusUtil
.
getDeviceData
(
cid
);
List
<
String
>
lastHasReelPosErrorList
=
new
ArrayList
<>();
List
<
String
>
lastNoReelPosErrorList
=
new
ArrayList
<>();
if
(
lastDeviceData
!=
null
&&
lastDeviceData
.
size
()
==
2
){
lastHasReelPosErrorList
=
lastDeviceData
.
get
(
0
);
lastNoReelPosErrorList
=
lastDeviceData
.
get
(
1
);
}
List
<
List
<
String
>>
data
=
new
ArrayList
<>();
List
<
List
<
String
>>
data
=
new
ArrayList
<>();
data
.
add
(
Arrays
.
asList
(
hasReelPosErrorList
));
data
.
add
(
Arrays
.
asList
(
hasReelPosErrorList
));
data
.
add
(
Arrays
.
asList
(
noReelPosErrorList
));
data
.
add
(
Arrays
.
asList
(
noReelPosErrorList
));
DevicesStatusUtil
.
updateDeviceData
(
cid
,
data
);
DevicesStatusUtil
.
updateDeviceData
(
cid
,
data
);
//在这里进行对比
compareErrorDataWithMessage
(
cid
,
lastHasReelPosErrorList
,
lastNoReelPosErrorList
,
data
.
get
(
0
),
data
.
get
(
1
));
List
<
String
>
inOkList
=
new
ArrayList
<>();
List
<
String
>
inOkList
=
new
ArrayList
<>();
List
<
String
>
inNgList
=
new
ArrayList
<>();
List
<
String
>
inNgList
=
new
ArrayList
<>();
List
<
String
>
outOkList
=
new
ArrayList
<>();
List
<
String
>
outOkList
=
new
ArrayList
<>();
...
@@ -574,6 +590,95 @@ public class NLPShelfHandler extends BaseDeviceHandler {
...
@@ -574,6 +590,95 @@ public class NLPShelfHandler extends BaseDeviceHandler {
return
ResultBean
.
newOkResult
(
posList
);
return
ResultBean
.
newOkResult
(
posList
);
}
}
private
void
compareErrorDataWithMessage
(
String
cid
,
List
<
String
>
lastHasReelPosErrorList
,
List
<
String
>
lastNoReelPosErrorList
,
List
<
String
>
currentHasReelPosErrorList
,
List
<
String
>
currentNoReelPosErrorList
)
{
Storage
storage
=
dataCache
.
getStorage
(
cid
);
// 处理空值
if
(
lastHasReelPosErrorList
==
null
)
lastHasReelPosErrorList
=
new
ArrayList
<>();
if
(
lastNoReelPosErrorList
==
null
)
lastNoReelPosErrorList
=
new
ArrayList
<>();
if
(
currentHasReelPosErrorList
==
null
)
currentHasReelPosErrorList
=
new
ArrayList
<>();
if
(
currentNoReelPosErrorList
==
null
)
currentNoReelPosErrorList
=
new
ArrayList
<>();
// 对比有料异常数据
List
<
String
>
hasNewErrors
=
new
ArrayList
<>();
List
<
String
>
hasRecoveredErrors
=
new
ArrayList
<>();
List
<
String
>
hasPersistentErrors
=
new
ArrayList
<>();
for
(
String
item
:
currentHasReelPosErrorList
)
{
if
(!
lastHasReelPosErrorList
.
contains
(
item
))
{
hasNewErrors
.
add
(
item
);
}
else
{
hasPersistentErrors
.
add
(
item
);
}
}
for
(
String
item
:
lastHasReelPosErrorList
)
{
if
(!
currentHasReelPosErrorList
.
contains
(
item
))
{
hasRecoveredErrors
.
add
(
item
);
}
}
// 对比无料异常数据
List
<
String
>
noNewErrors
=
new
ArrayList
<>();
List
<
String
>
noRecoveredErrors
=
new
ArrayList
<>();
List
<
String
>
noPersistentErrors
=
new
ArrayList
<>();
for
(
String
item
:
currentNoReelPosErrorList
)
{
if
(!
lastNoReelPosErrorList
.
contains
(
item
))
{
noNewErrors
.
add
(
item
);
}
else
{
noPersistentErrors
.
add
(
item
);
}
}
for
(
String
item
:
lastNoReelPosErrorList
)
{
if
(!
currentNoReelPosErrorList
.
contains
(
item
))
{
noRecoveredErrors
.
add
(
item
);
}
}
// 打印有料异常日志
if
(!
hasNewErrors
.
isEmpty
())
{
log
.
warn
(
"料架[{}] 有料异常(实际有料但数据库无信息) 新增异常库位: {}"
,
cid
,
String
.
join
(
", "
,
hasNewErrors
));
//smfcode.nlp.posHasReelError=库位[{0}]检测到有物料,但系统无库存记录
for
(
String
hasNewError
:
hasNewErrors
)
{
Message
message
=
Message
.
newMsg
(
MessageType
.
ERROR
.
name
(),
storage
.
getName
(),
storage
.
getId
(),
hasNewError
,
"smfcode.nlp.posHasReelError"
,
"库位[{0}]检测到有物料,但系统无库存记录"
,
new
String
[]{
hasNewError
});
messageManager
.
save
(
message
);
}
}
if
(!
hasRecoveredErrors
.
isEmpty
())
{
log
.
info
(
"料架[{}] 有料异常(实际有料但数据库无信息) 恢复正常库位: {}"
,
cid
,
String
.
join
(
", "
,
hasRecoveredErrors
));
for
(
String
hasRecoveredError
:
hasRecoveredErrors
)
{
//smfcode.nlp.posRecovered=库位[{0}]恢复正常
Message
message
=
Message
.
newMsg
(
MessageType
.
INFO
.
name
(),
storage
.
getName
(),
storage
.
getId
(),
hasRecoveredError
,
"smfcode.nlp.posRecovered"
,
"库位[{0}]恢复正常"
,
new
String
[]{
hasRecoveredError
});
messageManager
.
save
(
message
);
}
}
if
(!
hasPersistentErrors
.
isEmpty
())
{
//log.error("⚠️ 料架[{}] 有料异常(实际有料但数据库无信息) 持续异常库位: {}", cid, String.join(", ", hasPersistentErrors));
}
// 打印无料异常日志
if
(!
noNewErrors
.
isEmpty
())
{
log
.
warn
(
"料架[{}] 无料异常(实际无料但数据库有信息) 新增异常库位: {}"
,
cid
,
String
.
join
(
", "
,
noNewErrors
));
for
(
String
noNewError
:
noNewErrors
)
{
//smfcode.nlp.posNoReelError=库位[{0}]检测到没有物料,但系统有库存记录
Message
message
=
Message
.
newMsg
(
MessageType
.
ERROR
.
name
(),
storage
.
getName
(),
storage
.
getId
(),
noNewError
,
"smfcode.nlp.posNoReelError"
,
"库位[{0}]检测到没有物料,但系统有库存记录"
,
new
String
[]{
noNewError
});
messageManager
.
save
(
message
);
}
}
if
(!
noRecoveredErrors
.
isEmpty
())
{
log
.
info
(
"料架[{}] 无料异常(实际无料但数据库有信息) 恢复正常库位: {}"
,
cid
,
String
.
join
(
", "
,
noRecoveredErrors
));
for
(
String
noRecoveredError
:
noRecoveredErrors
)
{
//smfcode.nlp.posRecovered=库位[{0}]恢复正常
Message
message
=
Message
.
newMsg
(
MessageType
.
INFO
.
name
(),
storage
.
getName
(),
storage
.
getId
(),
noRecoveredError
,
"smfcode.nlp.posRecovered"
,
"库位[{0}]恢复正常"
,
new
String
[]{
noRecoveredError
});
messageManager
.
save
(
message
);
}
}
if
(!
noPersistentErrors
.
isEmpty
())
{
//log.error("⚠️ 料架[{}] 无料异常(实际无料但数据库有信息) 持续异常库位: {}", cid, String.join(", ", noPersistentErrors));
}
}
@Override
@Override
public
DeviceType
getDeviceType
()
{
public
DeviceType
getDeviceType
()
{
return
DeviceType
.
NLP
;
return
DeviceType
.
NLP
;
...
...
src/main/java/com/neotel/smfcore/core/device/handler/impl/TailingMaterialBoxHandler.java
0 → 100644
查看文件 @
9c5e4fc
package
com
.
neotel
.
smfcore
.
core
.
device
.
handler
.
impl
;
import
cn.hutool.core.util.ObjectUtil
;
import
com.google.common.base.Strings
;
import
com.neotel.smfcore.common.bean.ReelLockPosInfo
;
import
com.neotel.smfcore.common.bean.ResultBean
;
import
com.neotel.smfcore.common.exception.ValidateException
;
import
com.neotel.smfcore.common.utils.DateUtil
;
import
com.neotel.smfcore.common.utils.ReelLockPosUtil
;
import
com.neotel.smfcore.common.utils.SecurityUtils
;
import
com.neotel.smfcore.common.utils.StringUtils
;
import
com.neotel.smfcore.core.api.bean.CodeValidateParam
;
import
com.neotel.smfcore.core.barcode.service.po.Barcode
;
import
com.neotel.smfcore.core.barcode.service.po.Component
;
import
com.neotel.smfcore.core.barcode.utils.CodeResolve
;
import
com.neotel.smfcore.core.device.bean.NLShelfOperateBean
;
import
com.neotel.smfcore.core.device.bean.StatusBean
;
import
com.neotel.smfcore.core.device.enums.OP
;
import
com.neotel.smfcore.core.device.enums.OP_STATUS
;
import
com.neotel.smfcore.core.device.util.DataCache
;
import
com.neotel.smfcore.core.inList.util.InListCache
;
import
com.neotel.smfcore.core.language.util.MessageUtils
;
import
com.neotel.smfcore.core.order.enums.ORDER_COLOR
;
import
com.neotel.smfcore.core.order.service.manager.ILiteOrderManager
;
import
com.neotel.smfcore.core.order.service.po.LiteOrder
;
import
com.neotel.smfcore.core.storage.enums.DeviceType
;
import
com.neotel.smfcore.core.storage.service.manager.IStoragePosManager
;
import
com.neotel.smfcore.core.storage.service.po.Storage
;
import
com.neotel.smfcore.core.storage.service.po.StoragePos
;
import
com.neotel.smfcore.core.system.bean.OrderSetting
;
import
com.neotel.smfcore.core.system.service.po.DataLog
;
import
com.neotel.smfcore.core.system.util.DevicesStatusUtil
;
import
com.neotel.smfcore.core.system.util.TaskService
;
import
com.neotel.smfcore.security.TokenProvider
;
import
com.neotel.smfcore.security.annotation.AnonymousAccess
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.data.mongodb.core.query.Criteria
;
import
org.springframework.data.mongodb.core.query.Query
;
import
org.springframework.security.access.prepost.PreAuthorize
;
import
org.springframework.util.ObjectUtils
;
import
org.springframework.web.bind.annotation.*
;
import
javax.annotation.PostConstruct
;
import
javax.servlet.http.HttpServletRequest
;
import
java.awt.*
;
import
java.util.*
;
import
java.util.List
;
import
java.util.concurrent.ConcurrentHashMap
;
import
java.util.concurrent.Executors
;
import
java.util.concurrent.ScheduledExecutorService
;
import
java.util.concurrent.TimeUnit
;
@Api
(
tags
=
"尾料仓"
)
@RestController
@Slf4j
@RequestMapping
(
"/tailingMaterialBox"
)
public
class
TailingMaterialBoxHandler
extends
BaseDeviceHandler
{
private
final
String
putInColor
=
"green"
;
private
final
String
expiredColor
=
"red"
;
@Autowired
private
CodeResolve
codeResolve
;
@Autowired
private
IStoragePosManager
storagePosManager
;
@Autowired
private
DataCache
dataCache
;
@Autowired
private
TaskService
taskService
;
private
Map
<
String
,
String
>
expirePosMap
=
new
ConcurrentHashMap
<>();
// 创建定时任务执行器
ScheduledExecutorService
scheduler
=
Executors
.
newScheduledThreadPool
(
1
);
@PostConstruct
public
void
init
()
{
scheduler
.
scheduleAtFixedRate
(()
->
{
for
(
Storage
storage
:
dataCache
.
getAllStorage
().
values
())
{
if
(
storage
.
getType
().
equals
(
DeviceType
.
TAILING_MATERIAL
.
getName
()))
{
//只查询posName和barcode.expireTime的时间
Query
query
=
new
Query
(
Criteria
.
where
(
"storageId"
).
is
(
storage
.
getId
()));
query
.
fields
().
include
(
"posName"
,
"barcode.subCodeList.expireDate"
,
"barcode.subCodeList.barcode"
,
"storageId"
);
List
<
StoragePos
>
storagePosList
=
storagePosManager
.
findByQuery
(
query
);
if
(
storagePosList
!=
null
&&
!
storagePosList
.
isEmpty
())
{
for
(
StoragePos
pos
:
storagePosList
)
{
Barcode
posBarcode
=
pos
.
getBarcode
();
if
(
posBarcode
!=
null
)
{
List
<
Barcode
>
subCodeList
=
posBarcode
.
getSubCodeList
();
if
(
subCodeList
!=
null
&&
!
subCodeList
.
isEmpty
())
{
for
(
Barcode
subCode
:
subCodeList
)
{
if
(
subCode
.
isExpired
())
{
log
.
info
(
"加载到过期物料的库位:"
+
pos
.
getPosName
()+
"需要亮红灯"
);
expirePosMap
.
put
(
pos
.
getPosName
(),
storage
.
getCid
());
break
;
}
}
}
}
}
}
}
}
},
1
,
5
,
TimeUnit
.
MINUTES
);
}
@ApiOperation
(
"寻找柜体"
)
@RequestMapping
(
"/findPosByCode"
)
@AnonymousAccess
public
ResultBean
findPosByCode
(
@RequestBody
Map
<
String
,
String
>
paramMap
)
{
String
id
=
paramMap
.
get
(
"id"
);
String
code
=
paramMap
.
get
(
"code"
);
log
.
info
(
"入库寻找有料的柜体,条码信息为:"
+
code
);
Barcode
codeBarcode
=
codeResolve
.
resolveOneValideBarcode
(
"=2x2="
+
code
);
List
<
StoragePos
>
storagePosList
=
getStoragePosListByPn
(
codeBarcode
.
getPartNumber
(),
id
);
if
(
storagePosList
==
null
||
storagePosList
.
isEmpty
())
{
Storage
storage
=
dataCache
.
getStorageById
(
id
);
StoragePos
pos
=
storagePosManager
.
getEmptyPosByStorage
(
storage
,
codeBarcode
,
taskService
.
excludePosIds
());
if
(
pos
==
null
)
{
return
ResultBean
.
newErrorResult
(-
1
,
"smfcore.tailingmaterial.noPos"
,
"未找到可用的柜体"
);
}
storagePosList
=
new
ArrayList
<>();
storagePosList
.
add
(
pos
);
}
//开始寻找最晚入库的库位
StoragePos
pos
=
null
;
Barcode
barcode
=
null
;
int
amount
=
0
;
for
(
StoragePos
storagePos
:
storagePosList
)
{
if
(
pos
==
null
)
{
pos
=
storagePos
;
}
Barcode
posBarcode
=
storagePos
.
getBarcode
();
if
(
posBarcode
==
null
)
{
continue
;
}
List
<
Barcode
>
subCodeList
=
posBarcode
.
getSubCodeList
();
if
(
subCodeList
==
null
)
{
subCodeList
=
new
ArrayList
<>();
}
for
(
Barcode
subCode
:
subCodeList
)
{
amount
=
subCode
.
getAmount
()
+
amount
;
if
(
barcode
==
null
)
{
barcode
=
subCode
;
}
if
(
barcode
.
getPutInDate
().
getTime
()
<=
subCode
.
getPutInDate
().
getTime
())
{
barcode
=
subCode
;
pos
=
storagePos
;
}
}
}
log
.
info
(
"找到最晚入库的库位为:"
+
pos
.
getPosName
()
+
"开始亮灯"
);
opPosLight
(
"open"
,
pos
,
putInColor
);
Map
<
String
,
Object
>
resultMap
=
new
HashMap
<>();
resultMap
.
put
(
"posName"
,
pos
.
getPosName
());
resultMap
.
put
(
"partNumber"
,
codeBarcode
.
getPartNumber
());
resultMap
.
put
(
"posReelNum"
,
amount
);
return
ResultBean
.
newOkResult
(
resultMap
);
}
@ApiOperation
(
"寻找空柜体"
)
@RequestMapping
(
"/findEmptyPosByCode"
)
@AnonymousAccess
public
ResultBean
findEmptyPosByCode
(
@RequestBody
Map
<
String
,
String
>
paramMap
)
{
String
id
=
paramMap
.
get
(
"id"
);
//判断是不是有效的条码
String
code
=
paramMap
.
get
(
"code"
);
log
.
info
(
"入库寻找新柜体,条码信息为:"
+
code
+
","
);
Barcode
barcode
=
codeResolve
.
resolveOneValideBarcode
(
"=2x2="
+
code
);
Storage
storage
=
dataCache
.
getStorageById
(
id
);
//开始查询空库位
StoragePos
pos
=
storagePosManager
.
getEmptyPosByStorage
(
storage
,
barcode
,
taskService
.
excludePosIds
());
if
(
pos
==
null
)
{
//smfcore.tailingmaterial.noPos=未找到可用的柜体
return
ResultBean
.
newErrorResult
(-
1
,
"smfcore.tailingmaterial.noPos"
,
"未找到可用的柜体"
);
}
//添加到绑定里边
//addLockPos(pos, cid);
//同时亮灯
opPosLight
(
"open"
,
pos
,
putInColor
);
Map
<
String
,
Object
>
resultMap
=
new
HashMap
<>();
resultMap
.
put
(
"posName"
,
pos
.
getPosName
());
resultMap
.
put
(
"partNumber"
,
barcode
.
getPartNumber
());
resultMap
.
put
(
"posReelNum"
,
0
);
return
ResultBean
.
newOkResult
(
resultMap
);
}
@ApiOperation
(
"物料放入柜体中"
)
@RequestMapping
(
"/putInPos"
)
@AnonymousAccess
public
ResultBean
putInPos
(
@RequestBody
Map
<
String
,
String
>
paramMap
)
{
String
posName
=
paramMap
.
get
(
"posName"
);
String
code
=
paramMap
.
get
(
"code"
);
String
num
=
paramMap
.
get
(
"num"
);
log
.
info
(
"物料放入柜体中,库位为:"
+
posName
+
",条码为:"
+
code
+
",数量为:"
+
num
);
//解析条码,同时设置数量
Barcode
barcode
=
codeResolve
.
resolveOneValideBarcode
(
"=2x2="
+
code
);
barcode
.
setBarcode
(
barcode
.
getPartNumber
()+
"_"
+
barcode
.
getBatch
()+
"_"
+
System
.
currentTimeMillis
());
barcode
.
setAmount
(
Integer
.
parseInt
(
num
));
//查询过期天数,看看是不是已经过期了
if
(
barcode
.
getProduceDate
()
!=
null
)
{
Component
component
=
componentManager
.
findByPartNumberAndProvider
(
barcode
.
getPartNumber
(),
barcode
.
getProvider
());
if
(
component
==
null
){
component
=
componentManager
.
findOneByPN
(
barcode
.
getPartNumber
());
}
if
(
component
!=
null
)
{
int
validDay
=
component
.
getValidDay
();
if
(
validDay
>
0
){
Date
date
=
DateUtil
.
addDays
(
barcode
.
getProduceDate
(),
validDay
);
barcode
.
setExpireDate
(
date
);
}
}
}
//判断库位中的物料是否一样
StoragePos
pos
=
storagePosManager
.
getByPosName
(
posName
);
if
(
pos
==
null
)
{
return
ResultBean
.
newErrorResult
(-
1
,
"smfcore.valueNotExist"
,
"{0}[{1}]不存在"
,
new
String
[]{
"柜体"
,
posName
});
}
Barcode
posBarcode
=
getPosBarcode
(
pos
);
posBarcode
.
setPutInTime
(
System
.
currentTimeMillis
());
//判断和放入的是否一样
List
<
Barcode
>
subCodeList
=
posBarcode
.
getSubCodeList
();
if
(
subCodeList
!=
null
&&
!
subCodeList
.
isEmpty
())
{
for
(
Barcode
subCode
:
subCodeList
)
{
if
(!
barcode
.
getPartNumber
().
equals
(
subCode
.
getPartNumber
()))
{
return
ResultBean
.
newErrorResult
(-
1
,
"smfcore.tailingmaterial.pnError"
,
"入库的物料[{0}]与柜体中[{1}]不同"
,
new
String
[]{
barcode
.
getPartNumber
(),
subCode
.
getPartNumber
()});
}
}
}
barcode
.
setPosName
(
pos
.
getPosName
());
barcode
.
setPutInTime
(
System
.
currentTimeMillis
());
barcodeManager
.
saveBarcode
(
barcode
);
posBarcode
.
UpdateSubCode
(
barcode
);
int
amount
=
0
;
for
(
Barcode
subCode
:
posBarcode
.
getSubCodeList
())
{
amount
=
amount
+
subCode
.
getAmount
();
}
posBarcode
.
setAmount
(
amount
);
posBarcode
.
setPartNumber
(
barcode
.
getPartNumber
());
barcodeManager
.
saveBarcode
(
posBarcode
);
pos
.
setBarcode
(
posBarcode
);
pos
.
setUsed
(
true
);
storagePosManager
.
save
(
pos
);
//生成入库任务
Storage
storage
=
dataCache
.
getStorageById
(
pos
.
getStorageId
());
DataLog
dataLog
=
new
DataLog
(
storage
,
barcode
,
pos
);
dataLog
.
setType
(
OP
.
PUT_IN
);
dataLog
.
setNum
(
Integer
.
parseInt
(
num
));
dataLog
.
setOperator
(
SecurityUtils
.
getLoginUsername
());
dataLog
.
setStatus
(
OP_STATUS
.
FINISHED
.
name
());
taskService
.
updateFinishedTask
(
dataLog
);
Map
<
String
,
Object
>
resultMap
=
new
HashMap
<>();
resultMap
.
put
(
"posName"
,
pos
.
getPosName
());
resultMap
.
put
(
"partNumber"
,
barcode
.
getPartNumber
());
resultMap
.
put
(
"posReelNum"
,
amount
);
return
ResultBean
.
newOkResult
(
resultMap
);
}
@ApiOperation
(
"需要要出库的柜体"
)
@RequestMapping
(
"/findOutPosByCode"
)
@AnonymousAccess
public
ResultBean
findOutPosByCode
(
@RequestBody
Map
<
String
,
String
>
paramMap
)
{
String
partNumber
=
paramMap
.
get
(
"partNumber"
);
String
id
=
paramMap
.
get
(
"id"
);
log
.
info
(
"收到物料出库请求,partNumber为:"
+
partNumber
+
"id为:"
+
id
);
List
<
StoragePos
>
storagePosList
=
getStoragePosListByPn
(
partNumber
,
id
);
if
(
storagePosList
==
null
||
storagePosList
.
isEmpty
())
{
return
ResultBean
.
newErrorResult
(-
1
,
"smfcore.label.noReel"
,
"未找到可出库的物料"
);
}
//找到最早入库的物料信息
StoragePos
pos
=
null
;
Barcode
barcode
=
null
;
for
(
StoragePos
storagePos
:
storagePosList
)
{
if
(
pos
==
null
)
{
pos
=
storagePos
;
}
Barcode
posBarcode
=
storagePos
.
getBarcode
();
List
<
Barcode
>
subCodeList
=
posBarcode
.
getSubCodeList
();
for
(
Barcode
subCode
:
subCodeList
)
{
if
(
barcode
==
null
)
{
barcode
=
subCode
;
}
if
(
barcode
.
getPutInDate
().
getTime
()
>=
subCode
.
getPutInDate
().
getTime
())
{
barcode
=
subCode
;
pos
=
storagePos
;
}
}
}
log
.
info
(
"找到最早入库的库位为:"
+
pos
.
getPosName
()
+
",入库日期为:"
+
barcode
.
getPutInDate
(),
"开始亮灯"
);
opPosLight
(
"open"
,
pos
,
putInColor
);
int
amount
=
0
;
Barcode
posBarcode
=
pos
.
getBarcode
();
if
(
posBarcode
!=
null
){
List
<
Barcode
>
subCodeList
=
posBarcode
.
getSubCodeList
();
if
(
subCodeList
!=
null
&&
!
subCodeList
.
isEmpty
()){
for
(
Barcode
subCode
:
subCodeList
)
{
amount
=
subCode
.
getAmount
()
+
amount
;
}
}
}
Map
<
String
,
Object
>
resultMap
=
new
HashMap
<>();
resultMap
.
put
(
"posName"
,
pos
.
getPosName
());
resultMap
.
put
(
"partNumber"
,
partNumber
);
resultMap
.
put
(
"posReelNum"
,
amount
);
return
ResultBean
.
newOkResult
(
resultMap
);
}
@ApiOperation
(
"物料从柜体中出库"
)
@AnonymousAccess
@RequestMapping
(
"/outFromPos"
)
public
ResultBean
outFromPos
(
@RequestBody
Map
<
String
,
String
>
paramMap
)
{
String
posName
=
paramMap
.
get
(
"posName"
);
String
partNumber
=
paramMap
.
get
(
"partNumber"
);
String
numStr
=
paramMap
.
get
(
"num"
);
log
.
info
(
"物料从柜体出库,库位为:"
+
posName
+
",条码为:"
+
posName
+
",数量为:"
+
numStr
+
",partNumber为:"
+
partNumber
);
//判断库位中的物料是否一样
StoragePos
pos
=
storagePosManager
.
getByPosName
(
posName
);
if
(
pos
==
null
)
{
return
ResultBean
.
newErrorResult
(-
1
,
"smfcore.valueNotExist"
,
"{0}[{1}]不存在"
,
new
String
[]{
"柜体"
,
posName
});
}
Storage
storage
=
dataCache
.
getStorageById
(
pos
.
getStorageId
());
Barcode
posBarcode
=
getPosBarcode
(
pos
);
//直到出库物料位置
int
outNum
=
0
;
int
num
=
Integer
.
parseInt
(
numStr
);
while
(
outNum
<
num
)
{
int
remainNum
=
num
-
outNum
;
Barcode
barcode
=
null
;
List
<
Barcode
>
subCodeList
=
posBarcode
.
getSubCodeList
();
for
(
Barcode
subCode
:
subCodeList
)
{
if
(
barcode
==
null
)
{
barcode
=
subCode
;
}
if
(
barcode
.
getPutInDate
().
getTime
()
>=
subCode
.
getPutInDate
().
getTime
())
{
barcode
=
subCode
;
}
}
if
(
barcode
==
null
){
break
;
}
log
.
info
(
"寻找到对应的料盘信息为:"
+
barcode
.
getBarcode
()
+
",对应的入库时间为:"
+
barcode
.
getPutInDate
());
DataLog
dataLog
=
new
DataLog
(
storage
,
barcode
,
pos
);
dataLog
.
setType
(
OP
.
CHECKOUT
);
dataLog
.
setNum
(
remainNum
);
if
(
remainNum
>=
barcode
.
getAmount
())
{
dataLog
.
setNum
(
barcode
.
getAmount
());
outNum
=
outNum
+
barcode
.
getAmount
();
barcode
.
setAmount
(
0
);
barcode
.
setPosName
(
""
);
barcodeManager
.
save
(
barcode
);
}
else
{
outNum
=
outNum
+
remainNum
;
barcode
.
setAmount
(
barcode
.
getAmount
()
-
remainNum
);
barcodeManager
.
saveBarcode
(
barcode
);
}
dataLog
.
setStatus
(
OP_STATUS
.
FINISHED
.
name
());
dataLog
.
setOperator
(
SecurityUtils
.
getLoginUsername
());
taskService
.
updateFinishedTask
(
dataLog
);
posBarcode
.
UpdateSubCode
(
barcode
);
}
int
amount
=
0
;
List
<
Barcode
>
subCodeList
=
posBarcode
.
getSubCodeList
();
if
(
subCodeList
==
null
||
subCodeList
.
isEmpty
())
{
posBarcode
.
setAmount
(
0
);
pos
.
setBarcode
(
null
);
pos
.
setUsed
(
false
);
//如果为空了,就把当前库位的值给清空
expirePosMap
.
remove
(
posName
);
}
else
{
for
(
Barcode
barcode
:
posBarcode
.
getSubCodeList
())
{
amount
=
amount
+
barcode
.
getAmount
();
if
(
barcode
.
isExpired
()){
expirePosMap
.
put
(
posName
,
storage
.
getCid
());
}
}
posBarcode
.
setAmount
(
amount
);
pos
.
setBarcode
(
posBarcode
);
}
barcodeManager
.
save
(
posBarcode
);
storagePosManager
.
save
(
pos
);
Map
<
String
,
Object
>
resultMap
=
new
HashMap
<>();
resultMap
.
put
(
"posName"
,
pos
.
getPosName
());
resultMap
.
put
(
"partNumber"
,
partNumber
);
resultMap
.
put
(
"posReelNum"
,
amount
);
return
ResultBean
.
newOkResult
(
resultMap
);
}
@Override
public
StatusBean
handleClientRequest
(
StatusBean
statusBean
,
HttpServletRequest
request
)
{
if
(
expirePosMap
!=
null
&&
!
expirePosMap
.
isEmpty
()){
for
(
String
key
:
expirePosMap
.
keySet
())
{
log
.
info
(
"添加亮灯执指令,cid为:"
+
expirePosMap
.
get
(
key
)+
",key为openLed"
+
",value为:"
+
key
+
"="
+
expiredColor
);
DevicesStatusUtil
.
appendOp
(
expirePosMap
.
get
(
key
),
"openLed"
,
key
+
"="
+
expiredColor
);
}
}
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
;
}
private
List
<
StoragePos
>
getStoragePosListByPn
(
String
partNumber
,
String
id
)
{
Storage
storage
=
dataCache
.
getStorageById
(
id
);
//查询信息
Criteria
criteria
=
Criteria
.
where
(
"barcode"
).
exists
(
true
)
.
and
(
"enabled"
).
is
(
true
)
.
and
(
"storageId"
).
is
(
storage
.
getId
())
.
and
(
"barcode.partNumber"
).
is
(
partNumber
);
Query
query
=
new
Query
(
criteria
);
return
storagePosManager
.
findByQuery
(
query
);
}
private
Barcode
getPosBarcode
(
StoragePos
pos
)
{
Barcode
barcode
=
pos
.
getBarcode
();
if
(
barcode
==
null
)
{
barcode
=
barcodeManager
.
findByBarcode
(
pos
.
getPosName
());
if
(
barcode
!=
null
){
String
id
=
barcode
.
getId
();
barcode
=
new
Barcode
();
barcode
.
setId
(
id
);
barcode
.
setBarcode
(
pos
.
getPosName
());
barcode
.
setAmount
(
0
);
barcodeManager
.
save
(
barcode
);
}
}
if
(
barcode
==
null
)
{
barcode
=
new
Barcode
();
barcode
.
setBarcode
(
pos
.
getPosName
());
barcode
.
setAmount
(
0
);
barcodeManager
.
save
(
barcode
);
}
return
barcode
;
}
/**
* 操作库位灯(开灯,或关灯)
*
* @param opKey
* @param pos
* @param colorStr
*/
private
void
opPosLight
(
String
opKey
,
StoragePos
pos
,
String
colorStr
)
{
String
opStr
=
pos
.
getPosName
();
if
(!
Strings
.
isNullOrEmpty
(
colorStr
))
{
opStr
=
opStr
+
"="
+
colorStr
;
}
Storage
storage
=
dataCache
.
getStorageById
(
pos
.
getStorageId
());
DevicesStatusUtil
.
appendOp
(
storage
.
getCid
(),
opKey
,
opStr
);
log
.
info
(
"操作库位["
+
pos
.
getPosName
()
+
"]"
+
opKey
+
" : "
+
opStr
);
}
@Override
public
DeviceType
getDeviceType
()
{
return
DeviceType
.
TAILING_MATERIAL
;
}
}
src/main/java/com/neotel/smfcore/core/device/rest/DualPosNameDeviceController.java
0 → 100644
查看文件 @
9c5e4fc
package
com
.
neotel
.
smfcore
.
core
.
device
.
rest
;
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.ReelLockPosInfo
;
import
com.neotel.smfcore.common.bean.ResultBean
;
import
com.neotel.smfcore.common.exception.ValidateException
;
import
com.neotel.smfcore.common.utils.Constants
;
import
com.neotel.smfcore.common.utils.ReelLockPosUtil
;
import
com.neotel.smfcore.common.utils.StringUtils
;
import
com.neotel.smfcore.core.api.SmfApi
;
import
com.neotel.smfcore.core.api.bean.CodeValidateParam
;
import
com.neotel.smfcore.core.barcode.service.manager.IBarcodeManager
;
import
com.neotel.smfcore.core.barcode.service.po.Barcode
;
import
com.neotel.smfcore.core.barcode.utils.CodeResolve
;
import
com.neotel.smfcore.core.device.enums.OP
;
import
com.neotel.smfcore.core.device.enums.OP_STATUS
;
import
com.neotel.smfcore.core.device.util.DataCache
;
import
com.neotel.smfcore.core.language.util.MessageUtils
;
import
com.neotel.smfcore.core.message.util.DeviceMessageUtil
;
import
com.neotel.smfcore.core.storage.service.manager.IStoragePosManager
;
import
com.neotel.smfcore.core.storage.service.po.Storage
;
import
com.neotel.smfcore.core.storage.service.po.StoragePos
;
import
com.neotel.smfcore.core.system.service.dao.IAlarmInfoDao
;
import
com.neotel.smfcore.core.system.service.po.AlarmInfo
;
import
com.neotel.smfcore.core.system.service.po.DataLog
;
import
com.neotel.smfcore.core.system.util.TaskService
;
import
com.neotel.smfcore.security.annotation.AnonymousAccess
;
import
io.swagger.annotations.Api
;
import
io.swagger.annotations.ApiOperation
;
import
lombok.extern.slf4j.Slf4j
;
import
org.springframework.beans.factory.annotation.Autowired
;
import
org.springframework.web.bind.annotation.*
;
import
javax.servlet.http.HttpServletRequest
;
import
java.util.*
;
@Slf4j
@Api
(
tags
=
"双库位设备"
)
@RequestMapping
(
"/dualPosNameDevice"
)
@RestController
public
class
DualPosNameDeviceController
{
@Autowired
private
DataCache
dataCache
;
@Autowired
private
SmfApi
smfApi
;
@Autowired
private
TaskService
taskService
;
@Autowired
private
IStoragePosManager
storagePosManager
;
@Autowired
private
CodeResolve
codeResolve
;
@Autowired
private
IAlarmInfoDao
alarmInfoDao
;
@Autowired
private
IBarcodeManager
barcodeManager
;
/**
* 流水线提示消息
*/
private
static
String
lineMsg
=
""
;
/**
* 流水线入库查找空的料格
*/
@ApiOperation
(
"环行线扫码获取库位号"
)
@PostMapping
(
value
=
"/emptyPosForPutin"
)
@ResponseBody
@AnonymousAccess
public
Map
<
String
,
Object
>
emptyPosForPutin
(
HttpServletRequest
request
)
{
String
code
=
request
.
getParameter
(
"code"
);
String
cids
=
request
.
getParameter
(
"cids"
);
String
rfid
=
request
.
getParameter
(
"rfid"
);
String
rfidLoc
=
request
.
getParameter
(
"rfidLoc"
);
String
lastPosId
=
request
.
getParameter
(
"lastPosId"
);
lineMsg
=
""
;
log
.
info
(
"流水线["
+
cids
+
"]获取["
+
rfid
+
"]["
+
code
+
"]的入库库位"
);
Map
<
String
,
Object
>
resultMap
=
Maps
.
newHashMap
();
if
(
dataCache
.
getCache
(
Constants
.
CACHE_StopOut
))
{
lineMsg
=
"系统更新中,暂停出入库"
;
DeviceMessageUtil
.
updateLineMsg
(
lineMsg
,
code
,
cids
,
""
,
"smfcore.linemsg.update"
,
null
);
resultMap
.
put
(
"result"
,
"100"
);
resultMap
.
put
(
"msg"
,
lineMsg
);
return
resultMap
;
}
String
okMsg
=
""
;
String
errorMsg
=
""
;
// List<String> needRemoveReelLockPosIdList = new ArrayList<>();
if
(
Strings
.
isNullOrEmpty
(
cids
))
{
resultMap
.
put
(
"result"
,
"101"
);
resultMap
.
put
(
"msg"
,
"未指定料仓 cids "
);
}
else
{
List
<
Storage
>
storageList
=
Lists
.
newArrayList
();
List
<
String
>
cidList
=
Lists
.
newArrayList
();
for
(
String
cid
:
cids
.
split
(
","
))
{
String
notIntoCids
=
dataCache
.
getSettings
().
getNotIntoCids
();
if
(
notIntoCids
!=
null
)
{
if
(
notIntoCids
.
contains
(
cid
))
{
log
.
info
(
"料仓["
+
cid
+
"]已被屏蔽入库"
);
continue
;
}
}
Storage
storage
=
dataCache
.
getStorage
(
cid
);
if
(
storage
!=
null
)
{
storageList
.
add
(
storage
);
cidList
.
add
(
cid
);
}
}
if
(
storageList
.
isEmpty
())
{
resultMap
.
put
(
"result"
,
"99"
);
errorMsg
=
"无可用的料仓"
;
resultMap
.
put
(
"msg"
,
errorMsg
);
}
else
{
try
{
CodeValidateParam
params
=
new
CodeValidateParam
(
""
,
""
,
""
,
code
,
""
);
params
.
setStorageList
(
storageList
);
Barcode
barcode
=
resolveBarcodeFromApi
(
params
);
if
(
barcode
==
null
)
{
throw
new
ValidateException
(
"smfcore.error.barcode.invalid"
,
"未找到有效的条码"
);
}
//判断是否有出入库任务
for
(
DataLog
dataLog
:
taskService
.
getAllTasks
())
{
if
(
dataLog
.
getBarcode
().
equals
(
barcode
.
getBarcode
())
&&
!
dataLog
.
isCancel
()
&&
!
dataLog
.
isFinished
())
{
if
(
dataLog
.
isPutInTask
())
{
//已有入库任务
errorMsg
=
"物料["
+
dataLog
.
getBarcode
()
+
"]已有入库任务,需继续执行入库动作"
;
resultMap
.
put
(
"pos"
,
dataLog
.
getPosName
());
resultMap
.
put
(
"barcode"
,
barcode
.
getBarcode
());
resultMap
.
put
(
"cid"
,
dataLog
.
getCid
());
return
resultMap
;
}
else
{
//已有出库任务
errorMsg
=
"物料["
+
dataLog
.
getBarcode
()
+
"]已有出库任务,需继续执行出库动作"
;
resultMap
.
put
(
"result"
,
"98"
);
resultMap
.
put
(
"msg"
,
errorMsg
);
resultMap
.
put
(
"posId"
,
dataLog
.
getPosName
());
resultMap
.
put
(
"plateW"
,
barcode
.
getPlateSize
());
resultMap
.
put
(
"plateH"
,
barcode
.
getHeight
());
resultMap
.
put
(
"singleOut"
,
dataLog
.
isSingleOut
()
+
""
);
//紧急料
resultMap
.
put
(
"urgentReel"
,
dataLog
.
isUrgentReel
()
+
""
);
//需要分盘,进入分盘料
resultMap
.
put
(
"cutReel"
,
dataLog
.
isCutReel
()
+
""
);
resultMap
.
put
(
"rfid"
,
""
);
resultMap
.
put
(
"realRfid"
,
""
);
resultMap
.
put
(
"rfidLoc"
,
""
);
resultMap
.
put
(
"barcode"
,
dataLog
.
getBarcode
());
boolean
smallReel
=
barcode
.
isSmallReel
();
resultMap
.
put
(
"smallReel"
,
smallReel
+
""
);
return
resultMap
;
}
}
}
//判断对应的尺寸,外侧的库位,是否保留5个
List
<
String
>
findCidList
=
new
ArrayList
<>();
List
<
Storage
>
findNewStorageList
=
new
ArrayList
<>();
for
(
Storage
storage
:
storageList
)
{
int
count
=
storagePosManager
.
getRemainPosCountByStorage
(
storage
,
barcode
,
taskService
.
excludePosIds
(),
""
,
"_F"
);
if
(
count
>
5
)
{
findCidList
.
add
(
storage
.
getCid
());
findNewStorageList
.
add
(
storage
);
}
else
{
log
.
info
(
storage
.
getCid
()
+
"对应的尺寸:"
+
barcode
.
getPlateSize
()
+
"x"
+
barcode
.
getHeight
()
+
"外侧库位数量小于等于5个,忽略不入库"
);
}
}
if
(
findNewStorageList
==
null
||
findNewStorageList
.
isEmpty
())
{
throw
new
ValidateException
(
"smfcore.noValidStorage"
,
"[{0}]料仓列表中未找到可用的料仓"
,
new
String
[]{
barcode
.
getBarcode
()});
}
//先移除被锁定的库位
ReelLockPosUtil
.
removeReelLockPosInfo
(
barcode
.
getBarcode
());
log
.
info
(
barcode
.
getBarcode
()
+
"料盘重新入库,先移除被锁定的库位"
);
StoragePos
pos
=
null
;
int
loopCount
=
0
;
List
<
String
>
needRemoveLockPosId
=
new
ArrayList
<>();
String
endStr
=
"B"
;
while
(
pos
==
null
)
{
loopCount
++;
if
(
loopCount
>=
30
)
{
log
.
info
(
barcode
.
getBarcode
()
+
"已循环查找30次 直接跳出循环"
);
break
;
}
if
(
loopCount
>=
15
)
{
endStr
=
"F"
;
}
pos
=
taskService
.
dualPosNameFindEmptyPosForPutIn
(
findNewStorageList
,
barcode
,
rfid
,
lastPosId
,
barcode
.
getBarcode
(),
endStr
);
if
(
pos
==
null
)
{
if
(
"B"
.
equals
(
endStr
))
{
endStr
=
"F"
;
}
else
{
endStr
=
"B"
;
}
pos
=
taskService
.
dualPosNameFindEmptyPosForPutIn
(
findNewStorageList
,
barcode
,
rfid
,
lastPosId
,
barcode
.
getBarcode
(),
endStr
);
}
if
(
pos
==
null
)
{
break
;
}
//如果是以S结尾的,则判断不带S的有没有料
String
posName
=
pos
.
getPosName
();
if
(
posName
.
endsWith
(
"B"
)
||
posName
.
endsWith
(
"b"
))
{
log
.
info
(
posName
+
"以B结尾,需要判断外层有没有物料"
);
posName
=
posName
.
substring
(
0
,
posName
.
length
()
-
1
);
posName
=
posName
+
"F"
;
StoragePos
storagePos
=
storagePosManager
.
getByPosName
(
posName
);
if
(
storagePos
!=
null
)
{
Set
<
String
>
allLockPosIds
=
ReelLockPosUtil
.
getAllLockPosIds
();
boolean
contains
=
allLockPosIds
.
contains
(
storagePos
.
getId
());
if
(
storagePos
.
getBarcode
()
!=
null
||
contains
)
{
log
.
info
(
posName
+
"有物料信息,重新查找库位,清除条码["
+
barcode
.
getBarcode
()
+
"]锁定库位"
);
ReelLockPosUtil
.
removeReelLockPosInfo
(
barcode
.
getBarcode
());
ReelLockPosInfo
reelLocInfo
=
new
ReelLockPosInfo
();
reelLocInfo
.
setBarcode
(
pos
.
getId
());
reelLocInfo
.
setCid
(
dataCache
.
getStorageById
(
pos
.
getStorageId
()).
getCid
());
reelLocInfo
.
setLockPosName
(
pos
.
getPosName
());
reelLocInfo
.
setLockPosId
(
pos
.
getId
());
ReelLockPosUtil
.
addReelLockPosInfo
(
reelLocInfo
,
findCidList
);
needRemoveLockPosId
.
add
(
pos
.
getId
());
pos
=
null
;
}
}
}
}
//判断有没有锁定的异常库位
if
(
needRemoveLockPosId
!=
null
&&
!
needRemoveLockPosId
.
isEmpty
())
{
for
(
String
posId
:
needRemoveLockPosId
)
{
ReelLockPosUtil
.
removeReelLockPosInfo
(
posId
);
}
}
if
(
pos
!=
null
)
{
Storage
theStorage
=
dataCache
.
getStorageById
(
pos
.
getStorageId
());
resultMap
.
put
(
"result"
,
"0"
);
resultMap
.
put
(
"msg"
,
""
);
okMsg
=
"["
+
rfid
+
"]["
+
barcode
.
getBarcode
()
+
"]锁定库位["
+
pos
.
getPosName
()
+
"]优先级["
+
pos
.
getPriority
()
+
"] 上个库位号["
+
lastPosId
+
"]"
;
ReelLockPosInfo
oldLockInfo
=
ReelLockPosUtil
.
getLockPosInfoByCode
(
barcode
.
getBarcode
());
if
(
oldLockInfo
!=
null
)
{
if
(!
oldLockInfo
.
getLockPosId
().
equals
(
pos
.
getId
()))
{
String
result
=
"-1"
;
okMsg
=
rfid
+
"["
+
rfidLoc
+
"]["
+
barcode
.
getBarcode
()
+
"]锁定库位["
+
pos
.
getPosName
()
+
"],清理旧有锁定信息"
;
resultMap
.
put
(
"result"
,
result
);
resultMap
.
put
(
"msg"
,
okMsg
);
//已经锁定过库位,但不是同一个条码,需要把对应位置的锁定信息清理掉
ReelLockPosUtil
.
removeReelLockPosInfo
(
oldLockInfo
.
getBarcode
());
log
.
info
(
"清理锁定库位:库位号["
+
oldLockInfo
.
getLockPosName
()
+
"]上物料["
+
oldLockInfo
.
getBarcode
()
+
"]锁定的库位"
);
}
}
log
.
info
(
okMsg
+
oldLockInfo
);
ReelLockPosInfo
reelLocInfo
=
new
ReelLockPosInfo
();
reelLocInfo
.
setBarcode
(
barcode
.
getBarcode
());
reelLocInfo
.
setCid
(
theStorage
.
getCid
());
reelLocInfo
.
setLockPosName
(
pos
.
getPosName
());
reelLocInfo
.
setLockPosId
(
pos
.
getId
());
reelLocInfo
=
ReelLockPosUtil
.
addReelLockPosInfo
(
reelLocInfo
,
findCidList
);
if
(
reelLocInfo
==
null
)
{
errorMsg
=
"["
+
barcode
.
getBarcode
()
+
"]库位["
+
reelLocInfo
.
getLockPosName
()
+
"]已被锁定,暂停入库"
;
lineMsg
=
errorMsg
;
DeviceMessageUtil
.
updateLineMsg
(
lineMsg
,
code
,
cids
,
reelLocInfo
.
getLockPosName
(),
"smfcore.linemsg.posLock"
,
new
String
[]{
barcode
.
getBarcode
(),
reelLocInfo
.
getLockPosName
()});
resultMap
.
put
(
"result"
,
"99"
);
resultMap
.
put
(
"msg"
,
errorMsg
);
return
resultMap
;
}
else
{
resultMap
.
put
(
"pos"
,
pos
.
getPosName
());
resultMap
.
put
(
"barcode"
,
barcode
.
getBarcode
());
resultMap
.
put
(
"cid"
,
theStorage
.
getCid
());
}
}
else
{
resultMap
.
put
(
"result"
,
"104"
);
errorMsg
=
"["
+
barcode
.
getBarcode
()
+
"]未找到可用的["
+
barcode
.
getPlateSize
()
+
"x"
+
barcode
.
getHeight
()
+
"]仓位"
;
resultMap
.
put
(
"msg"
,
errorMsg
);
}
}
catch
(
ValidateException
ve
)
{
errorMsg
=
ve
.
getMessage
();
errorMsg
=
MessageUtils
.
getText
(
ve
.
getMsgKey
(),
ve
.
getMsgParam
(),
MessageUtils
.
getDefaultLocal
(),
ve
.
getDefaultMsg
());
log
.
info
(
"查找空库位失败:"
+
errorMsg
);
resultMap
.
put
(
"result"
,
"105"
);
resultMap
.
put
(
"msg"
,
errorMsg
);
}
catch
(
Exception
e
)
{
errorMsg
=
e
.
getMessage
();
log
.
info
(
"查找空库位失败,"
,
e
);
resultMap
.
put
(
"result"
,
"105"
);
resultMap
.
put
(
"msg"
,
errorMsg
);
}
}
}
//没入成功
if
(!
errorMsg
.
isEmpty
())
{
//有错误,记录日志
AlarmInfo
alarmInfo
=
new
AlarmInfo
();
alarmInfo
.
setBoxId
(
"0"
);
alarmInfo
.
setStorageName
(
"流水线"
);
alarmInfo
.
setInOutStatus
(
"1"
);
alarmInfo
.
setAlarmType
(
"入库"
);
Date
date
=
new
Date
();
alarmInfo
.
setStartTime
(
date
);
alarmInfo
.
setEndTime
(
date
);
String
msg
=
"["
+
code
+
"]"
+
errorMsg
;
alarmInfo
.
setAlarmMsg
(
msg
);
alarmInfoDao
.
save
(
alarmInfo
);
lineMsg
=
errorMsg
;
DeviceMessageUtil
.
updateLineMsg
(
lineMsg
,
code
,
cids
,
""
,
""
,
null
);
}
else
{
lineMsg
=
okMsg
;
DeviceMessageUtil
.
lastLineMsg
=
null
;
}
return
resultMap
;
}
@ApiOperation
(
"获取需要移动的库位是否有料"
)
@RequestMapping
(
"/needMovePosHasReel"
)
@ResponseBody
@AnonymousAccess
public
ResultBean
needMovePosHasReel
(
@RequestBody
Map
<
String
,
String
>
paramMap
)
{
String
checkOutPosName
=
paramMap
.
get
(
"checkOutPosName"
);
String
needMovePosName
=
paramMap
.
get
(
"needMovePosName"
);
log
.
info
(
"出库的库位为:"
+
checkOutPosName
+
",需要移动的库位为:"
+
needMovePosName
);
StoragePos
checkOutPos
=
storagePosManager
.
getByPosName
(
checkOutPosName
);
if
(
checkOutPos
==
null
)
{
return
ResultBean
.
newErrorResult
(-
1
,
"smfcore.valueNotExist"
,
"{0}[{1}]不存在"
,
new
String
[]{
"posName"
,
checkOutPosName
});
}
StoragePos
needMovePos
=
storagePosManager
.
getByPosName
(
needMovePosName
);
if
(
needMovePos
==
null
)
{
return
ResultBean
.
newErrorResult
(-
1
,
"smfcore.valueNotExist"
,
"{0}[{1}]不存在"
,
new
String
[]{
"posName"
,
needMovePosName
});
}
//如果barcode不为空,则提前锁定目标库位
boolean
hasReel
=
true
;
Barcode
barcode
=
needMovePos
.
getBarcode
();
String
posName
=
""
;
if
(
barcode
!=
null
)
{
log
.
info
(
"需要移动的库位"
+
needMovePosName
+
",对应的barcode为:"
+
barcode
.
getBarcode
()
+
",尺寸为:"
+
barcode
.
getPlateSize
()
+
"x"
+
barcode
.
getHeight
());
//有料,先查找锁定的lockS库位,有的话返回
ReelLockPosInfo
lockPosInfo
=
ReelLockPosUtil
.
getLockPosInfoByCode
(
getLockPosSKey
(
needMovePos
.
getStorageId
()));
if
(
lockPosInfo
!=
null
&&
ObjectUtil
.
isNotEmpty
(
lockPosInfo
.
getLockPosName
()))
{
posName
=
lockPosInfo
.
getLockPosName
();
log
.
info
(
"查找到锁定的内侧库位为目标库位:"
+
posName
+
" "
);
StoragePos
pos
=
storagePosManager
.
getByPosName
(
posName
);
if
(
pos
!=
null
)
{
if
(
pos
.
getW
()
!=
needMovePos
.
getW
()
||
pos
.
getH
()
!=
needMovePos
.
getH
())
{
log
.
info
(
posName
+
"对应的w{},h{}与移动的宽{},高{}不一致,重新找"
,
pos
.
getW
(),
pos
.
getH
(),
needMovePos
.
getW
(),
needMovePos
.
getH
());
posName
=
""
;
}
}
else
{
posName
=
""
;
}
}
if
(
StringUtils
.
isEmpty
(
posName
))
{
ReelLockPosUtil
.
removeReelLockPosInfo
(
getLockPosSKey
(
needMovePos
.
getStorageId
()));
}
if
(
StringUtils
.
isEmpty
(
posName
))
{
//查找一个库位号
StoragePos
pos
=
null
;
int
loopCount
=
0
;
List
<
Storage
>
storageList
=
new
ArrayList
<>();
Storage
storage
=
dataCache
.
getStorageById
(
needMovePos
.
getStorageId
());
storageList
.
add
(
storage
);
List
<
String
>
cidList
=
new
ArrayList
<>();
cidList
.
add
(
storage
.
getCid
());
List
<
String
>
needRemoveLockPosId
=
new
ArrayList
<>();
while
(
pos
==
null
)
{
loopCount
++;
if
(
loopCount
>=
20
)
{
log
.
info
(
barcode
.
getBarcode
()
+
"已循环查找20次 直接跳出循环"
);
break
;
}
//优先找B结束的,如果没有再找F的
String
endStr
=
"B"
;
if
(
loopCount
>=
10
)
{
endStr
=
"F"
;
}
pos
=
taskService
.
dualPosNameFindEmptyPosForPutIn
(
storageList
,
barcode
,
""
,
""
,
needMovePosName
,
endStr
);
if
(
pos
==
null
)
{
if
(
"F"
.
equals
(
endStr
))
{
}
else
{
endStr
=
"F"
;
pos
=
taskService
.
dualPosNameFindEmptyPosForPutIn
(
storageList
,
barcode
,
""
,
""
,
needMovePosName
,
endStr
);
}
}
if
(
pos
==
null
)
{
log
.
info
(
"需要移动的库位"
+
needMovePosName
+
"未找到对应的库位信息"
);
break
;
}
//如果是以S结尾的,则判断不带S的有没有料
posName
=
pos
.
getPosName
();
String
wPosName
=
""
;
if
(
posName
.
endsWith
(
"B"
)
||
posName
.
endsWith
(
"b"
))
{
log
.
info
(
posName
+
"以B结尾,需要判断外层有没有物料"
);
wPosName
=
posName
.
substring
(
0
,
posName
.
length
()
-
1
);
wPosName
=
wPosName
+
"F"
;
StoragePos
storagePos
=
storagePosManager
.
getByPosName
(
wPosName
);
if
(
storagePos
!=
null
)
{
if
(
storagePos
.
getBarcode
()
!=
null
)
{
log
.
info
(
"查找到目标库位:"
+
pos
.
getPosName
()
+
" 的外侧库位"
+
wPosName
+
"有物料信息,重新查找库位 "
);
ReelLockPosInfo
reelLocInfo
=
new
ReelLockPosInfo
();
reelLocInfo
.
setBarcode
(
pos
.
getId
());
reelLocInfo
.
setCid
(
dataCache
.
getStorageById
(
pos
.
getStorageId
()).
getCid
());
reelLocInfo
.
setLockPosName
(
pos
.
getPosName
());
reelLocInfo
.
setLockPosId
(
pos
.
getId
());
ReelLockPosUtil
.
addReelLockPosInfo
(
reelLocInfo
,
cidList
);
needRemoveLockPosId
.
add
(
pos
.
getId
());
pos
=
null
;
posName
=
""
;
}
else
{
log
.
info
(
"查找到目标库位:"
+
pos
.
getPosName
()
+
" 且外侧库位"
+
wPosName
+
"无料,锁定两个库位 :"
+
pos
.
getPosName
()
+
"="
+
getLockPosSKey
(
needMovePos
.
getStorageId
())
+
",wPosName="
+
getLockPosKey
(
needMovePos
.
getStorageId
()));
//是内侧库位,且外侧库位也无料,锁定两个库位
AddLock
(
pos
,
getLockPosSKey
(
needMovePos
.
getStorageId
()),
cidList
);
AddLock
(
storagePos
,
getLockPosKey
(
needMovePos
.
getStorageId
()),
cidList
);
//如果外侧有任务,则改成新库位一样的
DataLog
dataLog
=
null
;
for
(
DataLog
queueTask
:
taskService
.
getQueueTasks
())
{
if
(
barcode
.
getBarcode
().
equals
(
queueTask
))
{
dataLog
=
queueTask
;
break
;
}
}
if
(
dataLog
!=
null
)
{
log
.
info
(
"posName:[{}],barcode为[{}]有任务,需要重新设置任务库位:[{}]"
,
dataLog
.
getPosName
(),
barcode
.
getBarcode
(),
pos
.
getPosName
());
dataLog
.
setPosName
(
pos
.
getPosName
());
dataLog
.
setPosId
(
pos
.
getId
());
if
(
dataLog
.
isExecuting
()
||
dataLog
.
isWait
())
{
dataLog
.
setStatus
(
OP_STATUS
.
WAIT
.
name
());
taskService
.
updateQueueTask
(
dataLog
);
}
else
{
taskService
.
updateFinishedTask
(
dataLog
);
}
}
}
}
}
else
{
//是外侧库位,直接锁定外侧库位
log
.
info
(
"查找到外侧库位作为目标库位,锁定库位 :"
+
pos
.
getPosName
()
+
"="
+
getLockPosKey
(
needMovePos
.
getStorageId
()));
AddLock
(
pos
,
getLockPosKey
(
needMovePos
.
getStorageId
()),
cidList
);
//如果外侧有任务,则改成新库位一样的
DataLog
dataLog
=
null
;
for
(
DataLog
queueTask
:
taskService
.
getQueueTasks
())
{
if
(
barcode
.
getBarcode
().
equals
(
queueTask
))
{
dataLog
=
queueTask
;
break
;
}
}
if
(
dataLog
!=
null
)
{
log
.
info
(
"posName:[{}],barcode为[{}]有任务,需要重新设置任务库位:[{}]"
,
dataLog
.
getPosName
(),
barcode
.
getBarcode
(),
pos
.
getPosName
());
dataLog
.
setPosName
(
pos
.
getPosName
());
dataLog
.
setPosId
(
pos
.
getId
());
if
(
dataLog
.
isExecuting
()
||
dataLog
.
isWait
())
{
dataLog
.
setStatus
(
OP_STATUS
.
WAIT
.
name
());
taskService
.
updateQueueTask
(
dataLog
);
}
else
{
taskService
.
updateFinishedTask
(
dataLog
);
}
}
}
}
//判断有没有锁定的异常库位
if
(
needRemoveLockPosId
!=
null
&&
!
needRemoveLockPosId
.
isEmpty
())
{
for
(
String
posId
:
needRemoveLockPosId
)
{
ReelLockPosUtil
.
removeReelLockPosInfo
(
posId
);
}
}
}
}
else
{
hasReel
=
false
;
}
Map
<
String
,
Object
>
resultMap
=
new
HashMap
<>();
resultMap
.
put
(
"hasReel"
,
hasReel
);
if
(
hasReel
)
{
resultMap
.
put
(
"barcode"
,
barcode
.
getBarcode
());
resultMap
.
put
(
"partNumber"
,
barcode
.
getPartNumber
());
if
(
ObjectUtil
.
isEmpty
(
posName
))
{
return
ResultBean
.
newErrorResult
(-
1
,
"smfcore.shelf.msg.inError"
,
"未找到适合[{0}]的库位"
,
new
String
[]{
needMovePosName
});
}
else
{
resultMap
.
put
(
"posName"
,
posName
);
}
}
return
ResultBean
.
newOkResult
(
resultMap
);
}
@ApiOperation
(
"移动物料到另外一个库位"
)
@RequestMapping
(
"/moveToOtherPos"
)
@ResponseBody
@AnonymousAccess
public
ResultBean
moveToOtherPos
(
@RequestBody
Map
<
String
,
String
>
paramMap
)
{
String
needMovePosName
=
paramMap
.
get
(
"needMovePosName"
);
//需要移动的库位
String
targetPosName
=
paramMap
.
get
(
"targetPosName"
);
//目标库位
log
.
info
(
"需要移动的库位为:"
+
needMovePosName
+
",目标库位为:"
+
targetPosName
);
//判断目标库位是否存在
StoragePos
targetPos
=
storagePosManager
.
getByPosName
(
targetPosName
);
if
(
targetPos
==
null
)
{
return
ResultBean
.
newErrorResult
(-
1
,
"smfcore.valueNotExist"
,
"{0}[{1}]不存在"
,
new
String
[]{
"posName"
,
targetPosName
});
}
Barcode
targetBarcode
=
targetPos
.
getBarcode
();
//判断有没有物料
StoragePos
needMovePos
=
storagePosManager
.
getByPosName
(
needMovePosName
);
Barcode
barcode
=
needMovePos
.
getBarcode
();
//如果目标库位不为空,当前库位为空,直接返回ok
if
(
barcode
==
null
)
{
if
(
targetBarcode
==
null
)
{
return
ResultBean
.
newErrorResult
(-
1
,
"smfcore.valueNotExist"
,
"{0}[{1}]不存在"
,
new
String
[]{
needMovePosName
,
"barcode"
});
}
else
{
return
ResultBean
.
newOkResult
(
""
);
}
}
//把外侧相同的任务给改成内侧的
List
<
DataLog
>
allTasks
=
taskService
.
getAllTasks
();
for
(
DataLog
dataLog
:
allTasks
)
{
if
(
dataLog
.
isCheckOutTask
())
{
if
(!
dataLog
.
isFinished
()
&&
!
dataLog
.
isCancel
())
{
if
(
dataLog
.
getPosId
().
equals
(
needMovePos
.
getId
()))
{
dataLog
.
setPosId
(
targetPos
.
getId
());
dataLog
.
setPosName
(
targetPos
.
getPosName
());
taskService
.
updateQueueTask
(
dataLog
);
log
.
info
(
dataLog
.
getBarcode
()
+
":外测有任务,原始库位为:"
+
dataLog
.
getPosName
()
+
"更改后的库位为:"
+
targetPos
.
getPosName
());
break
;
}
}
}
}
//生成一条出库任务
Storage
storage
=
dataCache
.
getStorageById
(
needMovePos
.
getStorageId
());
DataLog
needMovePosTask
=
new
DataLog
(
storage
,
barcode
,
needMovePos
);
needMovePosTask
.
setOperator
(
"admin-move"
);
needMovePosTask
.
setType
(
OP
.
CHECKOUT
);
needMovePosTask
.
setStatus
(
OP_STATUS
.
FINISHED
.
name
());
taskService
.
updateFinishedTask
(
needMovePosTask
);
needMovePos
.
setBarcode
(
null
);
needMovePos
.
setUsed
(
false
);
storagePosManager
.
save
(
needMovePos
);
log
.
info
(
barcode
.
getBarcode
()
+
"转移库位,清空仓位: "
+
needMovePos
.
getId
()
+
"["
+
needMovePos
.
getPosName
()
+
"]"
);
dataCache
.
updateInventory
(
needMovePos
,
barcode
);
//重新设置barcode的库位
barcode
.
setPosName
(
targetPos
.
getPosName
());
barcodeManager
.
save
(
barcode
);
//生成一条入库任务
DataLog
targetPosTask
=
new
DataLog
(
storage
,
barcode
,
targetPos
);
targetPosTask
.
setOperator
(
"admin-move"
);
targetPosTask
.
setType
(
OP
.
PUT_IN
);
targetPosTask
.
setStatus
(
OP_STATUS
.
FINISHED
.
name
());
taskService
.
updateFinishedTask
(
targetPosTask
);
targetPos
.
setBarcode
(
barcode
);
targetPos
.
setUsed
(
true
);
targetPos
.
setCanCheckOutTime
(
System
.
currentTimeMillis
());
storagePosManager
.
save
(
targetPos
);
log
.
info
(
barcode
.
getBarcode
()
+
"转移库位,入库库位: "
+
targetPos
.
getId
()
+
"["
+
targetPos
.
getPosName
()
+
"]"
);
dataCache
.
updateInventory
(
targetPos
,
barcode
);
//解除库位绑定
ReelLockPosUtil
.
removeReelLockPosInfo
(
barcode
.
getBarcode
());
ReelLockPosInfo
lockS
=
ReelLockPosUtil
.
getLockPosInfoByCode
(
getLockPosSKey
(
needMovePos
.
getStorageId
()));
if
(
lockS
!=
null
&&
ObjectUtil
.
isNotEmpty
(
lockS
.
getLockPosName
())
&&
lockS
.
getLockPosName
().
equals
(
targetPosName
))
{
ReelLockPosUtil
.
removeReelLockPosInfo
(
getLockPosSKey
(
needMovePos
.
getStorageId
()));
}
else
{
ReelLockPosInfo
lock
=
ReelLockPosUtil
.
getLockPosInfoByCode
(
getLockPosKey
(
needMovePos
.
getStorageId
()));
if
(
lock
!=
null
&&
ObjectUtil
.
isNotEmpty
(
lock
.
getLockPosName
())
&&
lock
.
getLockPosName
().
equals
(
targetPosName
))
{
ReelLockPosUtil
.
removeReelLockPosInfo
(
getLockPosKey
(
needMovePos
.
getStorageId
()));
lock
=
null
;
}
if
(
lock
==
null
)
{
if
(
needMovePosName
.
endsWith
(
"F"
)
||
needMovePosName
.
endsWith
(
"f"
))
{
log
.
info
(
"需要移动的库位为:"
+
needMovePosName
+
"是内侧库位,不需要锁定库位"
);
}
else
{
needMovePosName
=
needMovePosName
.
substring
(
0
,
needMovePosName
.
length
()
-
1
);
String
sPosname
=
needMovePosName
+
"B"
;
StoragePos
sPos
=
storagePosManager
.
getByPosName
(
sPosname
);
if
(
sPos
!=
null
)
{
String
cid
=
dataCache
.
getStorageById
(
sPos
.
getStorageId
()).
getCid
();
List
<
String
>
cidList
=
new
ArrayList
<>();
cidList
.
add
(
cid
);
//如果两个库位锁定都为空了,将当前库位锁定为缓存库位
log
.
info
(
"重新锁定两个缓存库位 :"
+
sPos
.
getPosName
()
+
"="
+
getLockPosSKey
(
needMovePos
.
getStorageId
())
+
","
+
needMovePos
.
getPosName
()
+
"="
+
getLockPosKey
(
needMovePos
.
getStorageId
()));
//是内侧库位,且外侧库位也无料,锁定两个库位
AddLock
(
sPos
,
getLockPosSKey
(
needMovePos
.
getStorageId
()),
cidList
);
AddLock
(
needMovePos
,
getLockPosKey
(
needMovePos
.
getStorageId
()),
cidList
);
}
}
}
}
return
ResultBean
.
newOkResult
(
""
);
}
public
Barcode
resolveBarcodeFromApi
(
CodeValidateParam
params
)
{
Barcode
barcodeSave
=
smfApi
.
canPutInBeforeResolve
(
params
);
if
(
barcodeSave
==
null
)
{
barcodeSave
=
codeResolve
.
resolveOneValideBarcode
(
params
.
getCode
());
}
//从API验证
Barcode
barcodeFromApi
=
smfApi
.
canPutInAfterResolve
(
params
,
barcodeSave
);
if
(
barcodeFromApi
!=
null
)
{
barcodeSave
=
barcodeFromApi
;
}
return
barcodeSave
;
}
private
void
AddLock
(
StoragePos
pos
,
String
key
,
List
<
String
>
cidList
)
{
ReelLockPosInfo
lockS
=
new
ReelLockPosInfo
();
lockS
.
setBarcode
(
key
);
lockS
.
setCid
(
dataCache
.
getStorageById
(
pos
.
getStorageId
()).
getCid
());
lockS
.
setLockPosName
(
pos
.
getPosName
());
lockS
.
setLockPosId
(
pos
.
getId
());
ReelLockPosUtil
.
addReelLockPosInfo
(
lockS
,
cidList
);
}
private
String
getLockPosSKey
(
String
storageId
)
{
return
Constants
.
XLR_lockPosS
+
"_"
+
storageId
;
}
private
String
getLockPosKey
(
String
storageId
)
{
return
Constants
.
XLR_lockPos
+
"_"
+
storageId
;
}
}
src/main/java/com/neotel/smfcore/core/kanban/rest/BoxKanbanController.java
查看文件 @
9c5e4fc
...
@@ -17,6 +17,7 @@ import com.neotel.smfcore.core.device.util.DataCache;
...
@@ -17,6 +17,7 @@ import com.neotel.smfcore.core.device.util.DataCache;
import
com.neotel.smfcore.core.kanban.rest.bean.dto.*
;
import
com.neotel.smfcore.core.kanban.rest.bean.dto.*
;
import
com.neotel.smfcore.core.kanban.rest.bean.mapstruct.BoxTaskMapper
;
import
com.neotel.smfcore.core.kanban.rest.bean.mapstruct.BoxTaskMapper
;
import
com.neotel.smfcore.core.kanban.rest.bean.query.BoxTaskQueryCriter
;
import
com.neotel.smfcore.core.kanban.rest.bean.query.BoxTaskQueryCriter
;
import
com.neotel.smfcore.core.kanban.rest.utils.NaturalOrderComparator
;
import
com.neotel.smfcore.core.message.util.DeviceMessageUtil
;
import
com.neotel.smfcore.core.message.util.DeviceMessageUtil
;
import
com.neotel.smfcore.core.msd.bean.MSDSettiings
;
import
com.neotel.smfcore.core.msd.bean.MSDSettiings
;
import
com.neotel.smfcore.core.solder.util.SolderBoxCache
;
import
com.neotel.smfcore.core.solder.util.SolderBoxCache
;
...
@@ -107,7 +108,7 @@ public class BoxKanbanController {
...
@@ -107,7 +108,7 @@ public class BoxKanbanController {
}
}
}
}
if
(
boxStatusDtos
.
size
()>
0
){
if
(
boxStatusDtos
.
size
()>
0
){
boxStatusDtos
=
boxStatusDtos
.
stream
().
sorted
(
Comparator
.
comparing
(
BoxStatusDto
::
getName
)).
collect
(
Collectors
.
toList
());
boxStatusDtos
=
boxStatusDtos
.
stream
().
sorted
(
Comparator
.
comparing
(
BoxStatusDto
::
getName
,
new
NaturalOrderComparator
()
)).
collect
(
Collectors
.
toList
());
GroupStatusDto
groupStatusDto
=
new
GroupStatusDto
(
group
.
getId
(),
group
.
getGroupName
(),
boxStatusDtos
,
groupType
);
GroupStatusDto
groupStatusDto
=
new
GroupStatusDto
(
group
.
getId
(),
group
.
getGroupName
(),
boxStatusDtos
,
groupType
);
groupStatusDtos
.
add
(
groupStatusDto
);
groupStatusDtos
.
add
(
groupStatusDto
);
}
}
...
...
src/main/java/com/neotel/smfcore/core/kanban/rest/utils/NaturalOrderComparator.java
0 → 100644
查看文件 @
9c5e4fc
package
com
.
neotel
.
smfcore
.
core
.
kanban
.
rest
.
utils
;
import
java.util.Comparator
;
import
java.util.regex.Matcher
;
import
java.util.regex.Pattern
;
/**
* 自然排序比较器:字母按字典序,数字按数值大小排序
*/
public
class
NaturalOrderComparator
implements
Comparator
<
String
>
{
// 正则表达式:拆分字符串为"非数字"和"数字"交替的部分
private
static
final
Pattern
PATTERN
=
Pattern
.
compile
(
"(\\D+)|(\\d+)"
);
@Override
public
int
compare
(
String
s1
,
String
s2
)
{
if
(
s1
==
null
&&
s2
==
null
)
return
0
;
if
(
s1
==
null
)
return
-
1
;
// null放前面
if
(
s2
==
null
)
return
1
;
Matcher
m1
=
PATTERN
.
matcher
(
s1
);
Matcher
m2
=
PATTERN
.
matcher
(
s2
);
// 逐个匹配"非数字/数字"片段并比较
while
(
m1
.
find
()
&&
m2
.
find
())
{
String
group1
=
m1
.
group
();
String
group2
=
m2
.
group
();
// 判断当前片段是数字还是非数字
if
(
group1
.
matches
(
"\\d+"
)
&&
group2
.
matches
(
"\\d+"
))
{
// 数字片段:按数值大小比较(避免"10" < "2"的字符串排序问题)
Long
num1
=
Long
.
parseLong
(
group1
);
Long
num2
=
Long
.
parseLong
(
group2
);
int
numCompare
=
num1
.
compareTo
(
num2
);
if
(
numCompare
!=
0
)
{
return
numCompare
;
}
}
else
{
// 非数字片段:按字典序比较
int
strCompare
=
group1
.
compareTo
(
group2
);
if
(
strCompare
!=
0
)
{
return
strCompare
;
}
}
}
// 一个字符串是另一个的前缀,短的放前面
return
Integer
.
compare
(
s1
.
length
(),
s2
.
length
());
}
}
\ No newline at end of file
\ No newline at end of file
src/main/java/com/neotel/smfcore/core/storage/enums/DeviceType.java
查看文件 @
9c5e4fc
...
@@ -159,6 +159,11 @@ public enum DeviceType {
...
@@ -159,6 +159,11 @@ public enum DeviceType {
* 26 smdOne
* 26 smdOne
*/
*/
SMD_ONE
(
"storage.type.smdOne"
),
SMD_ONE
(
"storage.type.smdOne"
),
/**
* 尾料柜
*/
TAILING_MATERIAL
(
"storage.type.tailingMaterial"
),
;
;
private
String
key
;
private
String
key
;
...
@@ -180,6 +185,6 @@ public enum DeviceType {
...
@@ -180,6 +185,6 @@ public enum DeviceType {
}
}
public
static
List
<
DeviceType
>
availableTypeList
(){
public
static
List
<
DeviceType
>
availableTypeList
(){
return
Lists
.
newArrayList
(
AUTO
,
LINE
,
BATCH
,
SOLDERPASTE
,
VERTICALBOX
,
SMD_XL
,
SMD_DUO
,
SMD_XLC
,
SMD_XLR
,
SMD_ONE
,
VIRTUAL
,
NL
,
NLP
,
NLM
,
NLL
,
NLS
,
NLSM
,
SMDBOX_THIRD
,
SMD_MIMO_G2
,
SMD_MIMO_G3
);
return
Lists
.
newArrayList
(
AUTO
,
LINE
,
BATCH
,
SOLDERPASTE
,
VERTICALBOX
,
SMD_XL
,
SMD_DUO
,
SMD_XLC
,
SMD_XLR
,
SMD_ONE
,
VIRTUAL
,
NL
,
NLP
,
NLM
,
NLL
,
NLS
,
NLSM
,
SMDBOX_THIRD
,
SMD_MIMO_G2
,
SMD_MIMO_G3
,
TAILING_MATERIAL
);
}
}
}
}
src/main/java/com/neotel/smfcore/core/storage/service/manager/IStoragePosManager.java
查看文件 @
9c5e4fc
...
@@ -100,4 +100,8 @@ public interface IStoragePosManager extends IBaseManager<StoragePos> {
...
@@ -100,4 +100,8 @@ public interface IStoragePosManager extends IBaseManager<StoragePos> {
List
<
StoragePos
>
findPosListByPartNumber
(
List
<
String
>
storageIdList
,
String
pn
,
Collection
<
String
>
excludePosIds
,
CHECKOUT_TYPE
checkOutType
,
Map
<
String
,
String
>
appendData
);
List
<
StoragePos
>
findPosListByPartNumber
(
List
<
String
>
storageIdList
,
String
pn
,
Collection
<
String
>
excludePosIds
,
CHECKOUT_TYPE
checkOutType
,
Map
<
String
,
String
>
appendData
);
List
<
StoragePos
>
findPosListByMpn
(
List
<
String
>
availableStorageIds
,
String
mpn
,
Collection
<
String
>
excludePosIds
,
CHECKOUT_TYPE
checkoutType
,
Map
<
String
,
String
>
appendDate
);
List
<
StoragePos
>
findPosListByMpn
(
List
<
String
>
availableStorageIds
,
String
mpn
,
Collection
<
String
>
excludePosIds
,
CHECKOUT_TYPE
checkoutType
,
Map
<
String
,
String
>
appendDate
);
int
getRemainPosCountByStorage
(
Storage
storage
,
Barcode
barcode
,
Collection
<
String
>
excludePosIds
,
String
lastPosId
,
String
endStr
)
throws
ValidateException
;
StoragePos
dualPosNameGetEmptyPosByStorage
(
Storage
storage
,
Barcode
barcode
,
Collection
<
String
>
excludePosIds
,
String
lastPosId
,
String
needMovePosName
,
String
endStr
,
List
<
String
>
needExcludePosNameList
)
throws
ValidateException
;
}
}
src/main/java/com/neotel/smfcore/core/storage/service/manager/impl/StoragePosManagerImpl.java
查看文件 @
9c5e4fc
...
@@ -1038,4 +1038,95 @@ public class StoragePosManagerImpl implements IStoragePosManager {
...
@@ -1038,4 +1038,95 @@ public class StoragePosManagerImpl implements IStoragePosManager {
q
.
with
(
sort
);
q
.
with
(
sort
);
return
storagePosDao
.
findByQuery
(
q
);
return
storagePosDao
.
findByQuery
(
q
);
}
}
@Override
public
int
getRemainPosCountByStorage
(
Storage
storage
,
Barcode
barcode
,
Collection
<
String
>
excludePosIds
,
String
lastPosId
,
String
endStr
)
throws
ValidateException
{
Criteria
c
=
Criteria
.
where
(
"storageId"
).
is
(
storage
.
getId
());
COMPATIBLE_TYPE
compatibleType
=
storage
.
getCompatibleType
();
if
(
compatibleType
==
COMPATIBLE_TYPE
.
EXACT_MATCH
)
{
//完全匹配
c
=
c
.
and
(
"w"
).
is
(
barcode
.
getPlateSize
()).
and
(
"h"
).
is
(
barcode
.
getHeight
());
}
else
if
(
compatibleType
==
COMPATIBLE_TYPE
.
FULLY_COMPATIBLE
)
{
//同厚度兼容
c
=
c
.
and
(
"w"
).
gte
(
barcode
.
getPlateSize
()).
and
(
"h"
).
gte
(
barcode
.
getHeight
());
//除7寸外,完全兼容
}
else
if
(
compatibleType
==
COMPATIBLE_TYPE
.
SIZE_COMPATIBLE
)
{
//同尺寸兼容
c
=
c
.
and
(
"w"
).
is
(
barcode
.
getPlateSize
()).
and
(
"h"
).
gte
(
barcode
.
getHeight
());
//宽度等于料盘宽度,高度大于等于料盘高度
}
c
=
c
.
and
(
"enabled"
).
is
(
true
)
//可用
.
and
(
"used"
).
is
(
false
);
//未使用
//去除的仓位
if
(
excludePosIds
!=
null
&&
!
excludePosIds
.
isEmpty
())
{
c
=
c
.
and
(
"id"
).
nin
(
excludePosIds
);
}
if
(
StringUtils
.
isNotEmpty
(
endStr
))
{
String
regex
=
""
+
endStr
+
"$"
;
c
.
and
(
"posName"
).
regex
(
Pattern
.
compile
(
regex
));
}
Query
query
=
new
Query
(
c
);
query
.
with
(
Sort
.
by
(
Sort
.
Direction
.
ASC
,
"w"
).
and
(
Sort
.
by
(
Sort
.
Direction
.
ASC
,
"h"
)).
and
(
Sort
.
by
(
Sort
.
Direction
.
DESC
,
"priority"
)));
return
storagePosDao
.
countByQuery
(
query
);
}
private
static
boolean
max
=
true
;
@Override
public
StoragePos
dualPosNameGetEmptyPosByStorage
(
Storage
storage
,
Barcode
barcode
,
Collection
<
String
>
excludePosIds
,
String
lastPosId
,
String
needMovePosName
,
String
endStr
,
List
<
String
>
needExcludePosNameList
)
throws
ValidateException
{
Criteria
c
=
Criteria
.
where
(
"storageId"
).
is
(
storage
.
getId
());
COMPATIBLE_TYPE
compatibleType
=
storage
.
getCompatibleType
();
if
(
compatibleType
==
COMPATIBLE_TYPE
.
EXACT_MATCH
)
{
//完全匹配
c
=
c
.
and
(
"w"
).
is
(
barcode
.
getPlateSize
()).
and
(
"h"
).
is
(
barcode
.
getHeight
());
}
else
if
(
compatibleType
==
COMPATIBLE_TYPE
.
FULLY_COMPATIBLE
)
{
//同厚度兼容
c
=
c
.
and
(
"w"
).
gte
(
barcode
.
getPlateSize
()).
and
(
"h"
).
gte
(
barcode
.
getHeight
());
//除7寸外,完全兼容
}
else
if
(
compatibleType
==
COMPATIBLE_TYPE
.
SIZE_COMPATIBLE
)
{
//同尺寸兼容
c
=
c
.
and
(
"w"
).
is
(
barcode
.
getPlateSize
()).
and
(
"h"
).
gte
(
barcode
.
getHeight
());
//宽度等于料盘宽度,高度大于等于料盘高度
}
c
=
c
.
and
(
"enabled"
).
is
(
true
)
//可用
.
and
(
"used"
).
is
(
false
);
//未使用
//去除的仓位
if
(
excludePosIds
!=
null
&&
!
excludePosIds
.
isEmpty
())
{
c
=
c
.
and
(
"id"
).
nin
(
excludePosIds
);
}
if
(
StringUtils
.
isNotEmpty
(
needMovePosName
)
&&
StringUtils
.
isNotEmpty
(
endStr
))
{
Criteria
posNameCriteria
=
new
Criteria
();
String
regex
=
""
+
endStr
+
"$"
;
posNameCriteria
.
andOperator
(
Criteria
.
where
(
"posName"
).
ne
(
needMovePosName
),
Criteria
.
where
(
"posName"
).
regex
(
Pattern
.
compile
(
regex
)));
c
.
andOperator
(
posNameCriteria
);
}
if
(
needExcludePosNameList
!=
null
&&
!
needExcludePosNameList
.
isEmpty
()){
c
.
and
(
"posName"
).
nin
(
needExcludePosNameList
);
}
Query
query
=
new
Query
(
c
);
String
msg
=
""
;
// if (lastPosId == null || lastPosId.equals("")) {
//优先放入最合适的位置(根据尺寸),相同尺寸按优先级排序
if
(
max
){
query
.
with
(
Sort
.
by
(
Sort
.
Direction
.
ASC
,
"w"
).
and
(
Sort
.
by
(
Sort
.
Direction
.
ASC
,
"h"
)).
and
(
Sort
.
by
(
Sort
.
Direction
.
DESC
,
"priority"
)));
max
=
true
;
}
else
{
query
.
with
(
Sort
.
by
(
Sort
.
Direction
.
ASC
,
"w"
).
and
(
Sort
.
by
(
Sort
.
Direction
.
ASC
,
"h"
)).
and
(
Sort
.
by
(
Sort
.
Direction
.
ASC
,
"priority"
)));
max
=
false
;
}
StoragePos
pos
=
storagePosDao
.
findOne
(
query
);
if
((!
ObjectUtil
.
isNotEmpty
(
msg
)
)&&
(
pos
!=
null
))
{
Point
targetP
=
PointUtil
.
getPosPoint
(
lastPosId
,
false
);
log
.
debug
(
msg
+
"结果:["
+
pos
.
getPosName
()
+
"]["
+
targetP
.
getX
()
+
","
+
targetP
.
getY
()
+
"]"
);
}
return
pos
;
}
}
}
src/main/java/com/neotel/smfcore/core/system/util/TaskService.java
查看文件 @
9c5e4fc
...
@@ -167,8 +167,8 @@ public class TaskService {
...
@@ -167,8 +167,8 @@ public class TaskService {
* @param task
* @param task
*/
*/
private
void
tiggerTaskChangeListener
(
DataLog
task
)
{
private
void
tiggerTaskChangeListener
(
DataLog
task
)
{
liteOrderCache
.
onTaskStatusChange
(
task
);
smfApi
.
onTaskStatusChange
(
task
);
smfApi
.
onTaskStatusChange
(
task
);
liteOrderCache
.
onTaskStatusChange
(
task
);
selfAuditUtil
.
onTaskStatusChange
(
task
);
selfAuditUtil
.
onTaskStatusChange
(
task
);
materialTraceUtil
.
onTaskStatusChange
(
task
);
materialTraceUtil
.
onTaskStatusChange
(
task
);
}
}
...
@@ -1454,4 +1454,169 @@ public class TaskService {
...
@@ -1454,4 +1454,169 @@ public class TaskService {
}
}
}
}
}
}
public
StoragePos
dualPosNameFindEmptyPosForPutIn
(
List
<
Storage
>
storageList
,
Barcode
barcode
,
String
inRFID
,
String
lastPosId
,
String
needMovePosName
,
String
endStr
)
throws
ValidateException
{
verifyBarcodePutIn
(
storageList
,
barcode
,
inRFID
);
List
<
String
>
storageIds
=
new
ArrayList
<>();
//查找任务数最少的料仓
final
Map
<
String
,
Integer
>
storageTaskCountMap
=
new
HashMap
<>();
for
(
Storage
storage
:
storageList
)
{
storageTaskCountMap
.
put
(
storage
.
getId
(),
0
);
storageIds
.
add
(
storage
.
getId
());
}
Set
<
String
>
hasOutTaskStorageIds
=
new
HashSet
<>();
//如果有正在执行的任务,把库位发过去
Collection
<
DataLog
>
allTasks
=
taskMap
.
values
();
for
(
DataLog
task
:
allTasks
)
{
if
(
barcode
.
getBarcode
().
equals
(
task
.
getBarcode
()))
{
String
posId
=
task
.
getPosId
();
log
.
info
(
barcode
.
getBarcode
()
+
" 已有任务,返回任务中的库位:"
+
task
.
getPosName
());
return
storagePosManager
.
get
(
posId
);
}
String
storageId
=
task
.
getStorageId
();
if
(!
Strings
.
isNullOrEmpty
(
storageId
))
{
Integer
taskCount
=
storageTaskCountMap
.
get
(
storageId
);
if
(
taskCount
!=
null
)
{
taskCount
=
taskCount
+
1
;
storageTaskCountMap
.
put
(
storageId
,
taskCount
);
}
if
(
task
.
isCheckOutTask
())
{
hasOutTaskStorageIds
.
add
(
storageId
);
}
}
}
String
lockPosId
=
ReelLockPosUtil
.
getReelLockPosId
(
barcode
.
getBarcode
());
StoragePos
pos
=
null
;
if
(!
Strings
.
isNullOrEmpty
(
lockPosId
))
{
//已有锁定库位
pos
=
storagePosManager
.
get
(
lockPosId
);
if
(
pos
!=
null
)
{
if
(!
storageIds
.
contains
(
pos
.
getStorageId
())){
log
.
info
(
"条码["
+
barcode
.
getBarcode
()
+
"]已有锁定库位["
+
pos
.
getPosName
()
+
"],料仓ID["
+
pos
.
getStorageId
()+
"]不在请求列表["
+
String
.
join
(
","
,
storageIds
)+
"]中,重新查找库位"
);
pos
=
null
;
}
else
if
(
pos
.
getW
()
!=
barcode
.
getPlateSize
()
||
pos
.
getH
()
!=
barcode
.
getHeight
())
{
log
.
info
(
"条码["
+
barcode
.
getBarcode
()
+
"]尺寸已改变,无法放入已锁定库位["
+
pos
.
getPosName
()
+
"],重新查找库位"
);
pos
=
null
;
}
else
{
Barcode
posBarcode
=
pos
.
getBarcode
();
if
(
posBarcode
==
null
)
{
log
.
info
(
"条码["
+
barcode
.
getBarcode
()
+
"]已锁定库位["
+
pos
.
getPosName
()
+
"],返回锁定中的库位"
);
}
else
{
log
.
info
(
"条码["
+
barcode
.
getBarcode
()
+
"]已锁定库位["
+
pos
.
getPosName
()
+
"]中已有物料["
+
posBarcode
.
getBarcode
()
+
"],重新查找库位"
);
pos
=
null
;
}
}
}
}
if
(
pos
!=
null
)
{
return
pos
;
}
//可用的料仓(在线,且可以放入)
List
<
Storage
>
availbleStorageList
=
new
ArrayList
<>();
for
(
Storage
storage
:
storageList
)
{
if
(
storage
.
canPutIn
(
barcode
.
getPlateSize
(),
barcode
.
getHeight
()))
{
availbleStorageList
.
add
(
storage
);
}
}
if
(
availbleStorageList
.
isEmpty
())
{
throw
new
ValidateException
(
"smfcore.noValidStorage"
,
"[{0}]料仓列表中未找到可用的料仓"
,
new
String
[]{
barcode
.
getBarcode
()});
}
availbleStorageList
.
sort
(
new
Comparator
<
Storage
>()
{
@Override
public
int
compare
(
Storage
o1
,
Storage
o2
)
{
Integer
taskCount1
=
storageTaskCountMap
.
get
(
o1
.
getId
());
Integer
taskCount2
=
storageTaskCountMap
.
get
(
o2
.
getId
());
return
taskCount1
.
compareTo
(
taskCount2
);
}
});
return
dualPosNameFindEmptyPosInStorages
(
barcode
,
availbleStorageList
,
hasOutTaskStorageIds
,
lastPosId
,
needMovePosName
,
endStr
);
}
private
synchronized
StoragePos
dualPosNameFindEmptyPosInStorages
(
Barcode
barcode
,
List
<
Storage
>
availbleStorageList
,
final
Set
<
String
>
hasOutTaskStorageIds
,
String
lastPosId
,
String
needMovePosName
,
String
endStr
)
{
List
<
String
>
needExcludePosName
=
new
ArrayList
<>();
//新增外侧有料,里侧没料,排除里侧的库位信息
List
<
StoragePos
>
allUsePosList
=
new
ArrayList
<>();
for
(
Storage
storage
:
availbleStorageList
)
{
Map
<
String
,
StoragePos
>
usedPosList
=
dataCache
.
getUsedPosList
(
storage
.
getCid
());
for
(
StoragePos
pos
:
usedPosList
.
values
())
{
allUsePosList
.
add
(
pos
);
}
}
for
(
StoragePos
pos
:
allUsePosList
)
{
String
posName
=
pos
.
getPosName
();
if
(
posName
.
endsWith
(
"_F"
))
{
boolean
hasEndBPos
=
false
;
String
posName_B
=
posName
.
substring
(
0
,
posName
.
length
()
-
1
)
+
"B"
;
for
(
StoragePos
usePos
:
allUsePosList
)
{
if
(
posName_B
.
equals
(
usePos
.
getPosName
()))
{
hasEndBPos
=
true
;
break
;
}
}
if
(!
hasEndBPos
)
{
needExcludePosName
.
add
(
posName_B
);
}
}
}
//第一遍查找,先不查找有出库任务的料仓
for
(
Storage
storage
:
availbleStorageList
)
{
if
(!
storage
.
isSmdDuo
()){
//DUO料仓无论是否有出库任务,都可以查找空库位
if
(
hasOutTaskStorageIds
.
contains
(
storage
.
getId
())){
continue
;
}
}
try
{
Collection
<
String
>
operatingPosIds
=
excludePosIds
();
log
.
debug
(
"尝试从["
+
storage
.
getCid
()
+
"]中为["
+
barcode
.
getBarcode
()
+
"]查找空位"
);
StoragePos
pos
=
storagePosManager
.
dualPosNameGetEmptyPosByStorage
(
storage
,
barcode
,
operatingPosIds
,
lastPosId
,
needMovePosName
,
endStr
,
needExcludePosName
);
if
(
pos
!=
null
)
{
return
pos
;
}
}
catch
(
Exception
e
)
{
log
.
error
(
"尝试从["
+
storage
.
getCid
()
+
"]中为["
+
barcode
.
getBarcode
()
+
"]查找空位失败:"
+
e
.
getMessage
());
}
}
//第二遍查找,从所有料仓中查找
for
(
Storage
storage
:
availbleStorageList
)
{
try
{
Collection
<
String
>
operatingPosIds
=
excludePosIds
();
log
.
debug
(
"尝试从["
+
storage
.
getCid
()
+
"]中为["
+
barcode
.
getBarcode
()
+
"]查找空位"
);
StoragePos
pos
=
storagePosManager
.
dualPosNameGetEmptyPosByStorage
(
storage
,
barcode
,
operatingPosIds
,
lastPosId
,
needMovePosName
,
endStr
,
needExcludePosName
);
if
(
pos
!=
null
)
{
return
pos
;
}
}
catch
(
Exception
e
)
{
log
.
error
(
"尝试从["
+
storage
.
getCid
()
+
"]中为["
+
barcode
.
getBarcode
()
+
"]查找空位失败:"
+
e
.
getMessage
());
}
}
try
{
String
cids
=
""
;
for
(
Storage
storage
:
availbleStorageList
)
{
cids
=
cids
+
storage
.
getCid
()
+
","
;
}
log
.
info
(
barcode
.
getBarcode
()
+
" 未找到可用库位,可用料仓:"
+
cids
);
}
catch
(
Exception
e
)
{
log
.
error
(
"打印可用料仓出错"
,
e
);
}
return
null
;
}
}
}
src/main/java/com/neotel/smfcore/custom/neotel/NeotelApi.java
查看文件 @
9c5e4fc
...
@@ -319,6 +319,27 @@ public class NeotelApi extends BaseSmfApiListener {
...
@@ -319,6 +319,27 @@ public class NeotelApi extends BaseSmfApiListener {
*/
*/
@Override
@Override
public
void
onOrderStatusChange
(
String
orderNotifyUrl
,
LiteOrder
liteOrder
)
{
public
void
onOrderStatusChange
(
String
orderNotifyUrl
,
LiteOrder
liteOrder
)
{
Map
<
String
,
Object
>
paramMap
=
new
HashMap
<>();
paramMap
.
put
(
"hSerial"
,
liteOrder
.
getOrderNo
());
String
status
=
"Created"
;
if
(
liteOrder
.
isClosed
()){
status
=
"Closed"
;
}
else
{
if
(
liteOrder
.
isTaskFinished
()){
status
=
"Completed"
;
}
else
if
(
liteOrder
.
isOutBom
()
||
liteOrder
.
isOutTails
()
||
liteOrder
.
isOutOne
()){
status
=
"Executed"
;
}
}
paramMap
.
put
(
"status"
,
status
);
paramMap
.
put
(
"total"
,
liteOrder
.
getTotalTaskReelCount
());
paramMap
.
put
(
"out"
,
liteOrder
.
getTotalFinishedReelCount
());
try
{
log
.
info
(
liteOrder
.
getOrderNo
()
+
"工单状态改变,参数为:"
+
JsonUtil
.
toJsonStr
(
paramMap
));
String
result
=
HttpHelper
.
postJson
(
orderNotifyUrl
,
paramMap
);
log
.
info
(
liteOrder
.
getOrderNo
()
+
"工单状态改变,返回结果为:"
+
result
);
}
catch
(
Exception
e
)
{
log
.
error
(
"入库验证接口出错:"
+
e
.
getMessage
());
}
}
}
}
}
src/main/resources/messages.properties
查看文件 @
9c5e4fc
...
@@ -443,3 +443,8 @@ smf.nexim.getInventoryFaile=\u83B7\u53D6did\u4FE1\u606F\u5931\u8D25:[{0}]
...
@@ -443,3 +443,8 @@ smf.nexim.getInventoryFaile=\u83B7\u53D6did\u4FE1\u606F\u5931\u8D25:[{0}]
smfcore.registerdid.false
=
[{0}]
\u
6CE8
\u
518Cdid
\u5931\u
8D25:[{1}]
smfcore.registerdid.false
=
[{0}]
\u
6CE8
\u
518Cdid
\u5931\u
8D25:[{1}]
smfcore.accessToken.ng
=
\u
83B7
\u
53D6AccessToken
\u5931\u
8D25
smfcore.accessToken.ng
=
\u
83B7
\u
53D6AccessToken
\u5931\u
8D25
smfcore.barcode.hasOutTask
=
\u7269\u6599
[{0}]
\u
5DF2
\u6709\u
51FA
\u
5E93
\u
4EFB
\u
52A1,
\u9700\u
7EE7
\u
7EED
\u6267\u
884C
\u
51FA
\u
5E93
\u
52A8
\u
4F5C
smfcore.barcode.hasOutTask
=
\u7269\u6599
[{0}]
\u
5DF2
\u6709\u
51FA
\u
5E93
\u
4EFB
\u
52A1,
\u9700\u
7EE7
\u
7EED
\u6267\u
884C
\u
51FA
\u
5E93
\u
52A8
\u
4F5C
smfcore.tailingmaterial.noPos
=
\u
672A
\u
627E
\u5230\u
53EF
\u7528\u7684\u
67DC
\u
4F53
smfcore.tailingmaterial.pnError
=
\u5165\u
5E93
\u7684\u7269\u6599
[{0}]
\u
4E0E
\u
67DC
\u
4F53
\u
4E2D[{1}]
\u
4E0D
\u
540C
smfcode.nlp.posRecovered
=
\u
5E93
\u
4F4D[{0}]
\u6062\u
590D
\u
6B63
\u
5E38
smfcode.nlp.posNoReelError
=
\u
5E93
\u
4F4D[{0}]
\u
68C0
\u
6D4B
\u5230\u
6CA1
\u6709\u7269\u6599\u
FF0C
\u
4F46
\u
7CFB
\u
7EDF
\u6709\u
5E93
\u
5B58
\u
8BB0
\u
5F55
smfcode.nlp.posHasReelError
=
\u
5E93
\u
4F4D[{0}]
\u
68C0
\u
6D4B
\u5230\u6709\u7269\u6599\u
FF0C
\u
4F46
\u
7CFB
\u
7EDF
\u
65E0
\u
5E93
\u
5B58
\u
8BB0
\u
5F55
src/main/resources/messages_de_DE.properties
查看文件 @
9c5e4fc
...
@@ -430,4 +430,9 @@ smfcore.order.slotNum=Standnummer
...
@@ -430,4 +430,9 @@ smfcore.order.slotNum=Standnummer
smf.nexim.getInventoryFaile
=
Fehler beim Abrufen der did-Information: [{0}]
smf.nexim.getInventoryFaile
=
Fehler beim Abrufen der did-Information: [{0}]
smfcore.registerdid.false
=
[{0}] Registrierung von did fehlgeschlagen:[{1}]
smfcore.registerdid.false
=
[{0}] Registrierung von did fehlgeschlagen:[{1}]
smfcore.accessToken.ng
=
Fehler beim Abrufen des AccessToken
smfcore.accessToken.ng
=
Fehler beim Abrufen des AccessToken
smfcore.barcode.hasOutTask
=
Material [{0}] hat bereits einen Ausgangsauftrag; die Ausgangsaktion muss fortgesetzt werden
\ No newline at end of file
\ No newline at end of file
smfcore.barcode.hasOutTask
=
Material [{0}] hat bereits einen Ausgangsauftrag; die Ausgangsaktion muss fortgesetzt werden
smfcore.tailingmaterial.noPos
=
Kein verf
\u
00FCgbarer Schrank gefunden
smfcore.tailingmaterial.pnError
=
Das eingelagerte Material [{0}] unterscheidet sich von dem im Schrank [{1}]
smfcode.nlp.posRecovered
=
Position [{0}] wieder normal
smfcode.nlp.posNoReelError
=
Position [{0}] hat kein Material erkannt, aber das System hat einen Bestandsdatensatz
smfcode.nlp.posHasReelError
=
Position [{0}] hat Material erkannt, aber das System hat keinen Bestandsdatensatz
\ No newline at end of file
\ No newline at end of file
src/main/resources/messages_en_US.properties
查看文件 @
9c5e4fc
...
@@ -431,4 +431,9 @@ smfcore.order.slotNum=Station Number
...
@@ -431,4 +431,9 @@ smfcore.order.slotNum=Station Number
smf.nexim.getInventoryFaile
=
Failed to retrieve did information: [{0}]
smf.nexim.getInventoryFaile
=
Failed to retrieve did information: [{0}]
smfcore.registerdid.false
=
[{0}] Failed to register did:[{1}]
smfcore.registerdid.false
=
[{0}] Failed to register did:[{1}]
smfcore.accessToken.ng
=
Failed to obtain AccessToken
smfcore.accessToken.ng
=
Failed to obtain AccessToken
smfcore.barcode.hasOutTask
=
Material [{0}] already has an outbound task; the outbound action needs to be continued.
\ No newline at end of file
\ No newline at end of file
smfcore.barcode.hasOutTask
=
Material [{0}] already has an outbound task; the outbound action needs to be continued.
smfcore.tailingmaterial.noPos
=
No available cabinet found
smfcore.tailingmaterial.pnError
=
The material [{0}] put in is different from the one in the cabinet [{1}]
smfcode.nlp.posRecovered
=
Position [{0}] returned to normal
smfcode.nlp.posNoReelError
=
Position [{0}] detected no material, but system has inventory record
smfcode.nlp.posHasReelError
=
Position [{0}] detected material, but system has no inventory record
\ No newline at end of file
\ No newline at end of file
src/main/resources/messages_fr_FR.properties
查看文件 @
9c5e4fc
...
@@ -430,4 +430,9 @@ smfcore.order.slotNum=num\u00E9ro de position
...
@@ -430,4 +430,9 @@ smfcore.order.slotNum=num\u00E9ro de position
smf.nexim.getInventoryFaile
=
\u
00C9chec de r
\u
00E9cup
\u
00E9ration des informations did:[{0}]
smf.nexim.getInventoryFaile
=
\u
00C9chec de r
\u
00E9cup
\u
00E9ration des informations did:[{0}]
smfcore.registerdid.false
=
[{0}]
\u
00C9chec de l'enregistrement de did:[{1}]
smfcore.registerdid.false
=
[{0}]
\u
00C9chec de l'enregistrement de did:[{1}]
smfcore.accessToken.ng
=
\u
00C9chec de l'obtention de l'AccessToken
smfcore.accessToken.ng
=
\u
00C9chec de l'obtention de l'AccessToken
smfcore.barcode.hasOutTask
=
La mati
\u
00E8re [{0}] a d
\u
00E9j
\u
00E0 une t
\u
00E2che de sortie ; l'action de sortie doit
\u
00EAtre poursuivie
\ No newline at end of file
\ No newline at end of file
smfcore.barcode.hasOutTask
=
La mati
\u
00E8re [{0}] a d
\u
00E9j
\u
00E0 une t
\u
00E2che de sortie ; l'action de sortie doit
\u
00EAtre poursuivie
smfcore.tailingmaterial.noPos
=
Aucun cabinet disponible trouv
\u
00E9
smfcore.tailingmaterial.pnError
=
Le mat
\u
00E9riau [{0}] mis en stock est diff
\u
00E9rent de celui dans le cabinet [{1}]
smfcode.nlp.posRecovered
=
Position [{0}] revenue
\u
00E0 la normale
smfcode.nlp.posNoReelError
=
Position [{0}] n'a d
\u
00E9tect
\u
00E9 aucun mat
\u
00E9riau, mais le syst
\u
00E8me a un enregistrement d'inventaire
smfcode.nlp.posHasReelError
=
Position [{0}] a d
\u
00E9tect
\u
00E9 du mat
\u
00E9riau, mais le syst
\u
00E8me n'a pas d'enregistrement d'inventaire
\ No newline at end of file
\ No newline at end of file
src/main/resources/messages_ja_JP.properties
查看文件 @
9c5e4fc
...
@@ -427,4 +427,9 @@ smfcore.order.slotNum=\u30B9\u30BF\u30F3\u30C9\u756A\u53F7
...
@@ -427,4 +427,9 @@ smfcore.order.slotNum=\u30B9\u30BF\u30F3\u30C9\u756A\u53F7
smf.nexim.getInventoryFaile
=
did
\u
60C5
\u5831\u
306E
\u
53D6
\u
5F97
\u
306B
\u5931\u6557\u3057\u
307E
\u3057\u
305F: [{0}]
smf.nexim.getInventoryFaile
=
did
\u
60C5
\u5831\u
306E
\u
53D6
\u
5F97
\u
306B
\u5931\u6557\u3057\u
307E
\u3057\u
305F: [{0}]
smfcore.registerdid.false
=
[{0}] did
\u
306E
\u
767B
\u9332\u
306B
\u5931\u6557\u3057\u
307E
\u3057\u
305F:[{1}]
smfcore.registerdid.false
=
[{0}] did
\u
306E
\u
767B
\u9332\u
306B
\u5931\u6557\u3057\u
307E
\u3057\u
305F:[{1}]
smfcore.accessToken.ng
=
AccessToken
\u
306E
\u
53D6
\u
5F97
\u
306B
\u5931\u6557\u3057\u
307E
\u3057\u
305F
smfcore.accessToken.ng
=
AccessToken
\u
306E
\u
53D6
\u
5F97
\u
306B
\u5931\u6557\u3057\u
307E
\u3057\u
305F
smfcore.barcode.hasOutTask
=
\u
8CC7
\u6750
[{0}]
\u
306B
\u
306F
\u
65E2
\u
306B
\u
51FA
\u
5EAB
\u
30BF
\u
30B9
\u
30AF
\u
304C
\u3042\u
308A
\u3001\u
51FA
\u
5EAB
\u
30A2
\u
30AF
\u
30B7
\u
30E7
\u
30F3
\u3092\u
7D9A
\u
884C
\u3059\u
308B
\u
5FC5
\u8981\u
304C
\u3042\u
308A
\u
307E
\u3059
\ No newline at end of file
\ No newline at end of file
smfcore.barcode.hasOutTask
=
\u
8CC7
\u6750
[{0}]
\u
306B
\u
306F
\u
65E2
\u
306B
\u
51FA
\u
5EAB
\u
30BF
\u
30B9
\u
30AF
\u
304C
\u3042\u
308A
\u3001\u
51FA
\u
5EAB
\u
30A2
\u
30AF
\u
30B7
\u
30E7
\u
30F3
\u3092\u
7D9A
\u
884C
\u3059\u
308B
\u
5FC5
\u8981\u
304C
\u3042\u
308A
\u
307E
\u3059
smfcore.tailingmaterial.noPos
=
\u5229\u7528\u
53EF
\u
80FD
\u
306A
\u
30AD
\u
30E3
\u
30D3
\u
30CD
\u
30C3
\u
30C8
\u
304C
\u
898B
\u3064\u
304B
\u
308A
\u
307E
\u
305B
\u3093
smfcore.tailingmaterial.pnError
=
\u5165\u
5E93
\u3055\u
308C
\u
305F
\u6750\u6599
[{0}]
\u
306F
\u
30AD
\u
30E3
\u
30D3
\u
30CD
\u
30C3
\u
30C8
\u5185\u
306E[{1}]
\u3068\u7570\u
306A
\u
308A
\u
307E
\u3059
smfcode.nlp.posRecovered
=
\u
5EAB
\u
4F4D[{0}]
\u
304C
\u
6B63
\u
5E38
\u
306B
\u
623B
\u
308A
\u
307E
\u3057\u
305F
smfcode.nlp.posNoReelError
=
\u
5EAB
\u
4F4D[{0}]
\u
306B
\u7269\u6599\u
304C
\u
691C
\u
51FA
\u3055\u
308C
\u
307E
\u
305B
\u3093\u
304C
\u3001\u
30B7
\u
30B9
\u
30C6
\u
30E0
\u
306B
\u
306F
\u5728\u
5EAB
\u
8A18
\u9332\u
304C
\u3042\u
308A
\u
307E
\u3059
smfcode.nlp.posHasReelError
=
\u
5EAB
\u
4F4D[{0}]
\u
306B
\u7269\u6599\u
304C
\u
691C
\u
51FA
\u3055\u
308C
\u
307E
\u3057\u
305F
\u
304C
\u3001\u
30B7
\u
30B9
\u
30C6
\u
30E0
\u
306B
\u
306F
\u5728\u
5EAB
\u
8A18
\u9332\u
304C
\u3042\u
308A
\u
307E
\u
305B
\u3093
\ No newline at end of file
\ No newline at end of file
src/main/resources/messages_zh_CN.properties
查看文件 @
9c5e4fc
...
@@ -427,4 +427,9 @@ smfcore.order.slotNum=\u7AD9\u4F4D\u7F16\u53F7
...
@@ -427,4 +427,9 @@ smfcore.order.slotNum=\u7AD9\u4F4D\u7F16\u53F7
smf.nexim.getInventoryFaile
=
\u
83B7
\u
53D6did
\u
4FE1
\u
606F
\u5931\u
8D25:[{0}]
smf.nexim.getInventoryFaile
=
\u
83B7
\u
53D6did
\u
4FE1
\u
606F
\u5931\u
8D25:[{0}]
smfcore.registerdid.false
=
[{0}]
\u
6CE8
\u
518Cdid
\u5931\u
8D25:[{1}]
smfcore.registerdid.false
=
[{0}]
\u
6CE8
\u
518Cdid
\u5931\u
8D25:[{1}]
smfcore.accessToken.ng
=
\u
83B7
\u
53D6AccessToken
\u5931\u
8D25
smfcore.accessToken.ng
=
\u
83B7
\u
53D6AccessToken
\u5931\u
8D25
smfcore.barcode.hasOutTask
=
\u7269\u6599
[{0}]
\u
5DF2
\u6709\u
51FA
\u
5E93
\u
4EFB
\u
52A1,
\u9700\u
7EE7
\u
7EED
\u6267\u
884C
\u
51FA
\u
5E93
\u
52A8
\u
4F5C
\ No newline at end of file
\ No newline at end of file
smfcore.barcode.hasOutTask
=
\u7269\u6599
[{0}]
\u
5DF2
\u6709\u
51FA
\u
5E93
\u
4EFB
\u
52A1,
\u9700\u
7EE7
\u
7EED
\u6267\u
884C
\u
51FA
\u
5E93
\u
52A8
\u
4F5C
smfcore.tailingmaterial.noPos
=
\u
672A
\u
627E
\u5230\u
53EF
\u7528\u7684\u
67DC
\u
4F53
smfcore.tailingmaterial.pnError
=
\u5165\u
5E93
\u7684\u7269\u6599
[{0}]
\u
4E0E
\u
67DC
\u
4F53
\u
4E2D[{1}]
\u
4E0D
\u
540C
smfcode.nlp.posRecovered
=
\u
5E93
\u
4F4D[{0}]
\u6062\u
590D
\u
6B63
\u
5E38
smfcode.nlp.posNoReelError
=
\u
5E93
\u
4F4D[{0}]
\u
68C0
\u
6D4B
\u5230\u
6CA1
\u6709\u7269\u6599\u
FF0C
\u
4F46
\u
7CFB
\u
7EDF
\u6709\u
5E93
\u
5B58
\u
8BB0
\u
5F55
smfcode.nlp.posHasReelError
=
\u
5E93
\u
4F4D[{0}]
\u
68C0
\u
6D4B
\u5230\u6709\u7269\u6599\u
FF0C
\u
4F46
\u
7CFB
\u
7EDF
\u
65E0
\u
5E93
\u
5B58
\u
8BB0
\u
5F55
\ No newline at end of file
\ No newline at end of file
src/main/resources/messages_zh_TW.properties
查看文件 @
9c5e4fc
...
@@ -427,4 +427,9 @@ smfcore.order.slotNum = \u7AD9\u4F4D\u7DE8\u865F
...
@@ -427,4 +427,9 @@ smfcore.order.slotNum = \u7AD9\u4F4D\u7DE8\u865F
smf.nexim.getInventoryFaile
=
\u
53D6
\u
5F97 did
\u
8CC7
\u
8A0A
\u5931\u6557
:[{0}]
smf.nexim.getInventoryFaile
=
\u
53D6
\u
5F97 did
\u
8CC7
\u
8A0A
\u5931\u6557
:[{0}]
smfcore.registerdid.false
=
[{0}]
\u
8A3B
\u
518Adid
\u5931\u6557
:[{1}]
smfcore.registerdid.false
=
[{0}]
\u
8A3B
\u
518Adid
\u5931\u6557
:[{1}]
smfcore.accessToken.ng
=
\u7372\u
53D6AccessToken
\u5931\u6557
smfcore.accessToken.ng
=
\u7372\u
53D6AccessToken
\u5931\u6557
smfcore.barcode.hasOutTask
=
\u7269\u6599
[{0}]
\u
5DF2
\u6709\u
51FA
\u
5EAB
\u
4EFB
\u
52D9
\u
FF0C
\u9700\u
7E7C
\u
7E8C
\u
57F7
\u
884C
\u
51FA
\u
5EAB
\u
52D5
\u
4F5C
\ No newline at end of file
\ No newline at end of file
smfcore.barcode.hasOutTask
=
\u7269\u6599
[{0}]
\u
5DF2
\u6709\u
51FA
\u
5EAB
\u
4EFB
\u
52D9
\u
FF0C
\u9700\u
7E7C
\u
7E8C
\u
57F7
\u
884C
\u
51FA
\u
5EAB
\u
52D5
\u
4F5C
smfcore.tailingmaterial.noPos
=
\u
672A
\u
627E
\u5230\u
53EF
\u7528\u7684\u
6AC3
\u
9AD4
smfcore.tailingmaterial.pnError
=
\u5165\u
5EAB
\u7684\u7269\u6599
[{0}]
\u8207\u
6AC3
\u
9AD4
\u
4E2D[{1}]
\u
4E0D
\u
540C
smfcode.nlp.posRecovered
=
\u
5EAB
\u
4F4D[{0}]
\u6062\u
5FA9
\u
6B63
\u
5E38
smfcode.nlp.posNoReelError
=
\u
5EAB
\u
4F4D[{0}]
\u
6AA2
\u
6E2C
\u5230\u
6C92
\u6709\u7269\u6599\u
FF0C
\u
4F46
\u
7CFB
\u
7D71
\u6709\u
5EAB
\u
5B58
\u
8A18
\u9304
smfcode.nlp.posHasReelError
=
\u
5EAB
\u
4F4D[{0}]
\u
6AA2
\u
6E2C
\u5230\u6709\u7269\u6599\u
FF0C
\u
4F46
\u
7CFB
\u
7D71
\u7121\u
5EAB
\u
5B58
\u
8A18
\u9304
\ No newline at end of file
\ No newline at end of file
编写
预览
支持
Markdown
格式
附加文件
你添加了
0
人
到此讨论。请谨慎行事。
Finish editing this message first!
Cancel
请
注册
或
登录
后发表评论