| | |
| | | DATA_PROVIDER_SPRING, |
| | | } from "./config/setting"; |
| | | import ResourceContent from "./page/ResourceContent"; |
| | | import RcsTestStandalonePage from "./page/rcsTest/RcsTestStandalonePage"; |
| | | import { getSystemInfo, getSystemDicts, tenants } from "@/api/auth"; |
| | | import chineseMessages from 'ra-language-chinese'; |
| | | import { createTheme, ThemeProvider } from '@mui/material/styles'; |
| | |
| | | <CustomRoutes> |
| | | <Route path="/dashboard" element={<Dashboard />} /> |
| | | <Route path="/settings" element={<Settings />} /> |
| | | <Route path="/rcsTest-page" element={<RcsTestStandalonePage />} /> |
| | | </CustomRoutes> |
| | | </Admin> |
| | | </> |
| | |
| | | maktx: "物料名称", |
| | | matnrCode: "物料编码", |
| | | locCode: '库位', |
| | | barcode: '托盘码', |
| | | barcode: '料箱码', |
| | | count: "总次数", |
| | | batch: "批次", |
| | | anfme: "数量", |
| | |
| | | matnrCode: "物料编码", |
| | | spec: "规格", |
| | | model: "型号", |
| | | barcode: "托盘码", |
| | | barcode: "料箱码", |
| | | batch: "批次", |
| | | anfme: "库存数量", |
| | | checkQty: "实盘数量", |
| | |
| | | orgSite: "源站点", |
| | | targLoc: "目标库位", |
| | | targSite: "目标站点", |
| | | barcode: "托盘码", |
| | | barcode: "料箱码", |
| | | robotCode: "机器编码", |
| | | exceStatus: "执行状态", |
| | | expDesc: "异常说明", |
| | |
| | | orgSite: "源站点", |
| | | targLoc: "目标库位", |
| | | targSite: "目标站点", |
| | | barcode: "托盘码", |
| | | barcode: "料箱码", |
| | | robotCode: "机器编码", |
| | | exceStatus: "执行状态", |
| | | expDesc: "异常说明", |
| | |
| | | ); |
| | | } else { |
| | | if (node.component) { |
| | | // RCS测试:指向独立页路由,可单独打开一整页(无侧边栏/标签栏) |
| | | const to = node.component === 'rcsTest' ? '/rcsTest-page' : node.component; |
| | | return ( |
| | | <MenuItemLink |
| | | key={node.id} |
| | | to={node.component} // correspond to Resource.name |
| | | to={to} |
| | | state={{ _scrollToTop: true }} |
| | | // primaryText={translate(`resources.orders.name`, { |
| | | // smart_count: 2, |
| | | // })} |
| | | primaryText={node.name} |
| | | leftIcon={getIcon(node.icon)} |
| | | dense={dense} |
| | | // sx={{ '& .RaMenuItemLink-icon': { visibility: 'hidden' } }} |
| | | /> |
| | | ); |
| | | } |
| | |
| | | import { createPortal } from 'react-dom'; |
| | | import { useLocation } from 'react-router-dom'; |
| | | import { Layout as RALayout, CheckForApplicationUpdate, useSidebarState } from "react-admin"; |
| | | import AppBar from './AppBar'; |
| | | import { MyMenu } from './MyMenu'; |
| | |
| | | import { Box } from '@mui/material'; |
| | | import { TabDialogStateProvider } from '@/context/TabDialogStateContext'; |
| | | |
| | | /** RCS测试独立页路由:不显示侧边栏和标签栏,整页只显示RCS测试内容 */ |
| | | const RCS_TEST_STANDALONE_PATH = '/rcsTest-page'; |
| | | |
| | | const LayoutContent = ({ children }) => { |
| | | const location = useLocation(); |
| | | const [sidebarIsOpen] = useSidebarState(); |
| | | const sidebarWidth = sidebarIsOpen ? 200 : 50; |
| | | |
| | | if (location.pathname === RCS_TEST_STANDALONE_PATH) { |
| | | return ( |
| | | <Box sx={{ width: '100%', height: '100vh', overflow: 'hidden' }}> |
| | | {children} |
| | | <CheckForApplicationUpdate /> |
| | | </Box> |
| | | ); |
| | | } |
| | | |
| | | const tabsBarEl = ( |
| | | <Box sx={{ |
| | | position: 'fixed', |
| | |
| | | }); |
| | | } |
| | | |
| | | // 如果没有指定托盘码,尝试从变量中获取 |
| | | // 如果没有指定料箱码,尝试从变量中获取 |
| | | if (!inboundBarcode && currentVariables.barcode) { |
| | | inboundBarcode = currentVariables.barcode; |
| | | addLog('info', `从变量获取托盘码: ${inboundBarcode}`); |
| | | addLog('info', `从变量获取料箱码: ${inboundBarcode}`); |
| | | } |
| | | |
| | | const inboundRequestData = { |
| | |
| | | </Select> |
| | | </FormControl> |
| | | <TextField |
| | | label="托盘码" |
| | | label="料箱码" |
| | | fullWidth |
| | | value={config.barcode || ''} |
| | | onChange={(e) => |
| | |
| | | <Typography variant="subtitle2">关键信息:</Typography> |
| | | <Stack direction="row" spacing={2} sx={{ mt: 1 }}> |
| | | {testResult.barcode && ( |
| | | <Chip label={`托盘码: ${testResult.barcode}`} /> |
| | | <Chip label={`料箱码: ${testResult.barcode}`} /> |
| | | )} |
| | | {testResult.locNo && ( |
| | | <Chip label={`库位号: ${testResult.locNo}`} /> |
| | |
| | | <Typography variant="subtitle2">关键信息:</Typography> |
| | | <Stack direction="row" spacing={2} sx={{ mt: 1 }}> |
| | | {testResult.barcode && ( |
| | | <Chip label={`托盘码: ${testResult.barcode}`} /> |
| | | <Chip label={`料箱码: ${testResult.barcode}`} /> |
| | | )} |
| | | {testResult.locNo && ( |
| | | <Chip label={`库位号: ${testResult.locNo}`} /> |
| New file |
| | |
| | | import React from "react"; |
| | | import { useNavigate } from "react-router-dom"; |
| | | import { Box, IconButton, Typography } from "@mui/material"; |
| | | import ArrowBackIcon from "@mui/icons-material/ArrowBack"; |
| | | import RcsTestList from "./RcsTestList"; |
| | | |
| | | /** |
| | | * RCS测试独立页面:无侧边栏、无标签栏,可单独打开或在新标签页打开 |
| | | */ |
| | | const RcsTestStandalonePage = () => { |
| | | const navigate = useNavigate(); |
| | | |
| | | return ( |
| | | <Box sx={{ display: "flex", flexDirection: "column", height: "100vh" }}> |
| | | <Box |
| | | sx={{ |
| | | display: "flex", |
| | | alignItems: "center", |
| | | px: 1, |
| | | py: 0.5, |
| | | borderBottom: 1, |
| | | borderColor: "divider", |
| | | backgroundColor: "background.paper", |
| | | }} |
| | | > |
| | | <IconButton |
| | | onClick={() => navigate("/dashboard")} |
| | | size="small" |
| | | title="返回系统" |
| | | sx={{ mr: 1 }} |
| | | > |
| | | <ArrowBackIcon /> |
| | | </IconButton> |
| | | <Typography variant="subtitle1" component="span"> |
| | | RCS全流程自动测试(独立页) |
| | | </Typography> |
| | | </Box> |
| | | <Box sx={{ flex: 1, overflow: "auto" }}> |
| | | <RcsTestList /> |
| | | </Box> |
| | | </Box> |
| | | ); |
| | | }; |
| | | |
| | | export default RcsTestStandalonePage; |
| | |
| | | const renderPalletizeTaskConfig = () => ( |
| | | <Stack spacing={2}> |
| | | <TextField |
| | | label="托盘码(可选,不填则自动生成,支持变量)" |
| | | label="料箱码(可选,不填则自动生成,支持变量)" |
| | | value={config.barcode || ''} |
| | | onChange={(e) => handleConfigChange('barcode', e.target.value)} |
| | | fullWidth |
| | |
| | | </Select> |
| | | </FormControl> |
| | | <TextField |
| | | label="托盘码(支持变量,如:${barcode})" |
| | | label="料箱码(支持变量,如:${barcode})" |
| | | value={config.barcode || ''} |
| | | onChange={(e) => handleConfigChange('barcode', e.target.value)} |
| | | fullWidth |
| | |
| | | @TableField(exist = false) |
| | | private Map<String, String> extendFields; |
| | | |
| | | @ApiModelProperty("托盘码") |
| | | @ApiModelProperty("料箱码") |
| | | @TableField(exist = false) |
| | | private String barcode; |
| | | |
| | |
| | | @ApiModelProperty("目标站点") |
| | | private String destSta; |
| | | |
| | | @ApiModelProperty("托盘码") |
| | | @ApiModelProperty("料箱码") |
| | | private String zpallet; |
| | | |
| | | @ApiModelProperty("优先级") |
| | |
| | | @ApiModelProperty("库位编码") |
| | | private String locCode; |
| | | |
| | | @ApiModelProperty("托盘码") |
| | | @ApiModelProperty("料箱码") |
| | | private String barcode; |
| | | |
| | | @ApiModelProperty("单据明细") |
| | |
| | | return R.error("参数不能为空!!"); |
| | | } |
| | | if (org.apache.commons.lang3.StringUtils.isBlank(waitPakin.getBarcode())) { |
| | | return R.error("托盘码不能为空!!"); |
| | | return R.error("料箱码不能为空!!"); |
| | | } |
| | | if (Objects.isNull(waitPakin.getItems()) || waitPakin.getItems().isEmpty()) { |
| | | return R.error("跟踪码不能为空!!"); |
| | |
| | | return R.error("参数不能为空!!"); |
| | | } |
| | | if (org.apache.commons.lang3.StringUtils.isBlank(param.getBarcode())) { |
| | | return R.error("托盘码不能为空!!"); |
| | | return R.error("料箱码不能为空!!"); |
| | | } |
| | | if (Objects.isNull(param.getItems()) || param.getItems().isEmpty()) { |
| | | return R.error("解绑明细不能为空!!"); |
| | |
| | | } |
| | | |
| | | |
| | | @ApiOperation("获取不良托盘物料") |
| | | @ApiOperation("获取不良料箱物料") |
| | | @PostMapping("/defect/matnrs") |
| | | @PreAuthorize("hasAuthority('manager:asnOrder:list')") |
| | | public R getAsnDefectItemByCode(@RequestBody Map<String, Object> map) { |
| | |
| | | @ApiOperation("查询出库任务拣货明细") |
| | | public R getTaskItem(@RequestBody Map<String, String> params) { |
| | | if (Objects.isNull(params.get("barcode"))) { |
| | | return R.error("托盘码不能为空"); |
| | | return R.error("料箱码不能为空"); |
| | | } |
| | | return pdaOutStockService.getTaskItems(params); |
| | | } |
| | |
| | | @ApiModelProperty("目标站点") |
| | | private String destSta; |
| | | |
| | | @ApiModelProperty("托盘码") |
| | | @ApiModelProperty("料箱码") |
| | | private String zpallet; |
| | | |
| | | @ApiModelProperty("优先级") |
| | |
| | | @ApiModel(value = "WavePickItemsParams", description = "波次拣货明细") |
| | | public class WavePickItemsParams { |
| | | |
| | | @ApiModelProperty("托盘码") |
| | | @ApiModelProperty("料箱码") |
| | | private String barcode; |
| | | |
| | | @ApiModelProperty("订单ID") |
| | |
| | | @Override |
| | | public R operateToStock(OpStockParams params) { |
| | | if (org.apache.commons.lang3.StringUtils.isBlank(params.getBarcode())) { |
| | | throw new CoolException("托盘码不能为空!!"); |
| | | throw new CoolException("料箱码不能为空!!"); |
| | | } |
| | | WaitPakin waitPakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>() |
| | | .eq(WaitPakin::getBarcode, params.getBarcode()) |
| | |
| | | .eq(WaitPakin::getFlagDefect, flagDefect) |
| | | .in(WaitPakin::getIoStatus, asList)); |
| | | // if (!Cools.isEmpty(waitPakin)) { |
| | | // throw new CoolException("托盘不可用,在组托中已存在"); |
| | | // throw new CoolException("料箱不可用,在组托中已存在"); |
| | | // } |
| | | List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, params.get("barcode").toString())); |
| | | if (!tasks.isEmpty()) { |
| | | throw new CoolException("托盘码已在任务档执行!!"); |
| | | throw new CoolException("料箱码已在任务档执行!!"); |
| | | } |
| | | List<Loc> locs = locService.list(new LambdaQueryWrapper<Loc>().eq(Loc::getBarcode, params.get("barcode").toString())); |
| | | if (!Cools.isEmpty(locs)) { |
| | | throw new CoolException("托盘不可用,在库位中已存在"); |
| | | throw new CoolException("料箱不可用,在库位中已存在"); |
| | | } |
| | | // List<WaitPakinItem> items = waitPakinItemService.list(new LambdaQueryWrapper<WaitPakinItem>().eq(WaitPakinItem::getPakinId, waitPakin.getId())); |
| | | // items.forEach(item -> { |
| | |
| | | throw new CoolException("参数不能为空!!"); |
| | | } |
| | | if (Objects.isNull(map.get("barcode"))) { |
| | | throw new CoolException("托盘码不能为空!!"); |
| | | throw new CoolException("料箱码不能为空!!"); |
| | | } |
| | | if (Objects.isNull(map.get("matnrs"))) { |
| | | throw new CoolException("新增物料不能为空!!"); |
| | |
| | | throw new CoolException("参数不能为空!!"); |
| | | } |
| | | if (Objects.isNull(map.get("barcode"))) { |
| | | throw new CoolException("托盘码不能为空!!"); |
| | | throw new CoolException("料箱码不能为空!!"); |
| | | } |
| | | if (Objects.isNull(map.get("items"))) { |
| | | throw new CoolException("新增物料不能为空!!"); |
| | |
| | | ReportParams params = new ReportParams(); |
| | | List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getTaskId, task.getId())); |
| | | if (Objects.isNull(taskItems) || taskItems.isEmpty()) { |
| | | throw new CoolException("托盘明细为空!1"); |
| | | throw new CoolException("料箱明细为空!1"); |
| | | } |
| | | List<ReportDataParam> reportDataParams = new ArrayList<>(); |
| | | taskItems.forEach(taskItem -> { |
| | |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public synchronized R wavePickItems(WavePickItemsParams params) { |
| | | if (Objects.isNull(params.getBarcode())) { |
| | | return R.error("托盘码不能为空!!"); |
| | | return R.error("料箱码不能为空!!"); |
| | | } |
| | | if (Objects.isNull(params.getOrderId())) { |
| | | return R.error("订单ID不能为空!!"); |
| | |
| | | .orderByDesc(Task::getId) |
| | | .last("limit 1")); |
| | | if (null == task) { |
| | | return R.error("未找到托盘对应的任务"); |
| | | return R.error("未找到料箱对应的任务"); |
| | | } |
| | | if (!task.getTaskStatus().equals(TaskStsType.WAVE_SEED.id)) { |
| | | return R.error("任务状态不是揀料狀態"); |
| | |
| | | .in(Task::getTaskType, integers) |
| | | .eq(Task::getBarcode, params.get("barcode")), false); |
| | | if (Objects.isNull(task)) { |
| | | return R.error("托盘所在任务不存在!!"); |
| | | return R.error("料箱所在任务不存在!!"); |
| | | } |
| | | List<TaskItem> taskItems = taskItemService.list(new LambdaQueryWrapper<TaskItem>().eq(TaskItem::getTaskId, task.getId())); |
| | | taskItems.forEach(taskItem -> { |
| | |
| | | .orderByDesc(Task::getId) |
| | | .last("limit 1")); |
| | | if (null == task) { |
| | | return R.error("未找到托盘对应的任务"); |
| | | return R.error("未找到料箱对应的任务"); |
| | | } |
| | | if (!task.getTaskStatus().equals(TaskStsType.WAVE_SEED.id)) { |
| | | return R.error("任务状态不是待揀狀態"); |
| | |
| | | @ApiModelProperty("库位ID") |
| | | private String locId; |
| | | |
| | | @ApiModelProperty("托盘码") |
| | | @ApiModelProperty("料箱码") |
| | | private String barcode; |
| | | |
| | | @ApiModelProperty("物料名称") |
| | |
| | | @ApiModelProperty("库位明细ID") |
| | | private Long id; |
| | | |
| | | @ApiModelProperty("托盘码") |
| | | @ApiModelProperty("料箱码") |
| | | private String barcode; |
| | | |
| | | @ApiModelProperty("批次") |
| | |
| | | @ApiModelProperty("库位明细ID") |
| | | private Long id; |
| | | |
| | | @ApiModelProperty("托盘码") |
| | | @ApiModelProperty("料箱码") |
| | | private String barcode; |
| | | |
| | | @ApiModelProperty("批次") |
| | |
| | | private String model; |
| | | |
| | | /** |
| | | * 托盘码 |
| | | * 料箱码 |
| | | */ |
| | | @ApiModelProperty(value= "托盘码") |
| | | @ApiModelProperty(value= "料箱码") |
| | | private String barcode; |
| | | |
| | | /** |
| | |
| | | @TableField(exist = false) |
| | | private Map<String, String> extendFields; |
| | | |
| | | @ApiModelProperty("托盘码") |
| | | @ApiModelProperty("料箱码") |
| | | @TableField(exist = false) |
| | | private String barcode; |
| | | |
| | |
| | | @JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone = "GMT+8") |
| | | private String updateBy; |
| | | |
| | | @ApiModelProperty("托盘码") |
| | | @ApiModelProperty("料箱码") |
| | | private String barcode; |
| | | |
| | | @ApiModelProperty("库位") |
| | |
| | | private String targSite; |
| | | |
| | | /** |
| | | * 托盘码 |
| | | * 料箱码 |
| | | */ |
| | | @ApiModelProperty(value= "托盘码") |
| | | @ApiModelProperty(value= "料箱码") |
| | | private String barcode; |
| | | |
| | | /** |
| | |
| | | // null, // 任务类型 |
| | | // null, // 源库位 |
| | | // null, // 目标库位 |
| | | // null, // 托盘码 |
| | | // null, // 料箱码 |
| | | // null, // 机器人编码 |
| | | // null, // 执行状态 |
| | | // null, // 异常描述 |
| | |
| | | private String targLoc; |
| | | |
| | | /** |
| | | * 托盘码 |
| | | * 料箱码 |
| | | */ |
| | | @ApiModelProperty(value= "托盘码") |
| | | @ApiModelProperty(value= "料箱码") |
| | | private String barcode; |
| | | |
| | | /** |
| | |
| | | // null, // 任务类型 |
| | | // null, // 源库位 |
| | | // null, // 目标库位 |
| | | // null, // 托盘码 |
| | | // null, // 料箱码 |
| | | // null, // 机器人编码 |
| | | // null, // 执行状态 |
| | | // null, // 异常描述 |
| | |
| | | |
| | | /** |
| | | * 每五秒校验深库位是否为空,如果浅库位有货,将浅库位移至深库位 |
| | | *///TODO 生成移库任务前,需要检查是否有任务前往当前托盘 |
| | | *///TODO 生成移库任务前,需要检查是否有任务前往当前料箱 |
| | | // @Scheduled(cron = "0/35 * * * * ? ") |
| | | // @Transactional(rollbackFor = Exception.class) |
| | | // public void shallocToDeep() throws Exception { |
| | |
| | | } |
| | | Task task1 = taskService.getOne(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, key)); |
| | | if (!Objects.isNull(task1)) { |
| | | throw new CoolException("托盘任务已存在!!"); |
| | | throw new CoolException("料箱任务已存在!!"); |
| | | } |
| | | List<CheckOrderItemParams> itemParams = listMap.get(key); |
| | | CheckOrderItemParams checkItem = itemParams.stream().findFirst().get(); |
| | |
| | | } |
| | | steps.add("查询到物料数量:" + matnrs.size()); |
| | | |
| | | // 3.3 生成随机托盘码 |
| | | // 3.3 生成随机料箱码 |
| | | barcode = generateBarcode(); |
| | | steps.add("生成托盘码:" + barcode); |
| | | log.info("生成的托盘码:{}", barcode); |
| | | steps.add("生成料箱码:" + barcode); |
| | | log.info("生成的料箱码:{}", barcode); |
| | | |
| | | // 3.4 自动组托 |
| | | WaitPakinParam waitPakinParam = new WaitPakinParam(); |
| | |
| | | throw new CoolException("组托失败,返回结果为空!"); |
| | | } |
| | | steps.add("组托成功,组托编码:" + waitPakin.getCode()); |
| | | log.info("组托成功,组托编码:{},托盘码:{}", waitPakin.getCode(), barcode); |
| | | log.info("组托成功,组托编码:{},料箱码:{}", waitPakin.getCode(), barcode); |
| | | |
| | | // 3.5 自动入库 |
| | | String inboundStation = params.getInboundStation(); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 生成随机托盘码 |
| | | * 生成随机料箱码 |
| | | */ |
| | | private String generateBarcode() { |
| | | return "TEST_" + System.currentTimeMillis() + "_" + (int)(Math.random() * 10000); |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void moveToDeep(Long loginUserId, String curLoc) throws Exception { |
| | | //浅库位,判断深对应深库位是否为空,如果为空生成一个移库任务,将托盘送入深库位 |
| | | //浅库位,判断深对应深库位是否为空,如果为空生成一个移库任务,将料箱送入深库位 |
| | | String deepLoc = LocUtils.getDeepLoc(curLoc); |
| | | if (StringUtils.isBlank(deepLoc)) { |
| | | throw new CoolException("数据异常,请联系管理员!"); |
| | |
| | | batchNo = task.getTaskCode(); |
| | | } |
| | | } |
| | | log.info("任务已下发到RCS,需要取消RCS任务 - 任务ID:{},任务编号:{},任务状态:{},托盘码:{}", |
| | | log.info("任务已下发到RCS,需要取消RCS任务 - 任务ID:{},任务编号:{},任务状态:{},料箱码:{}", |
| | | task.getId(), task.getTaskCode(), task.getTaskStatus(), task.getBarcode()); |
| | | } |
| | | } |
| | |
| | | throw new CoolException("参数错误:物料跟踪码为空!"); |
| | | } |
| | | if (StringUtils.isBlank(waitPakin.getBarcode())) { |
| | | throw new CoolException("参数错误:托盘码为空!!"); |
| | | throw new CoolException("参数错误:料箱码为空!!"); |
| | | } |
| | | WaitPakin pakin = waitPakinService.getOne(new LambdaQueryWrapper<WaitPakin>() |
| | | .eq(WaitPakin::getBarcode, waitPakin.getBarcode())); |
| | |
| | | |
| | | List<Task> tasks = taskService.list(new LambdaQueryWrapper<Task>().eq(Task::getBarcode, waitPakin.getBarcode())); |
| | | if (!tasks.isEmpty()) { |
| | | throw new CoolException("当前托盘已有任务档在执行,不能再次组托!!"); |
| | | throw new CoolException("当前料箱已有任务档在执行,不能再次组托!!"); |
| | | } |
| | | |
| | | // 检查容器号是否在库存中存在(通过库位表查询) |