| | |
| | | return r; |
| | | } |
| | | |
| | | @RequestMapping(value = "/order/inspect/list/auth") |
| | | @ManagerAuth |
| | | public R inspectList(@RequestParam(required = false) String orderNo){ |
| | | // 1. 查找包含“检验”或“Inspection”的 DocType IDs |
| | | List<DocType> docTypes = docTypeService.selectList(new EntityWrapper<DocType>() |
| | | .like("doc_name", "检验") |
| | | .or() |
| | | .like("doc_name", "Inspection")); |
| | | |
| | | if (Cools.isEmpty(docTypes)) { |
| | | R r = R.ok(); |
| | | r.put("data", new ArrayList<>()); |
| | | return r; |
| | | } |
| | | |
| | | List<Long> docTypeIds = new ArrayList<>(); |
| | | for (DocType dt : docTypes) { |
| | | docTypeIds.add(dt.getDocId()); |
| | | } |
| | | |
| | | // 2. 查找对应类型的订单 |
| | | EntityWrapper<Order> wrapper = new EntityWrapper<>(); |
| | | if (!Cools.isEmpty(orderNo)) { |
| | | wrapper.like("order_no", orderNo); |
| | | } |
| | | wrapper.in("doc_type", docTypeIds); |
| | | wrapper.le("settle", 2); // 待处理或处理中 |
| | | wrapper.eq("status", 1); |
| | | wrapper.orderBy("create_time", false); |
| | | |
| | | List<Order> orders = orderService.selectList(wrapper); |
| | | R r = R.ok(); |
| | | r.put("data", orders); |
| | | return r; |
| | | } |
| | | |
| | | @RequestMapping(value = "/order/inspection/matchingLocations/auth") |
| | | @ManagerAuth |
| | | public R queryMatchingLocations( |
| | | @RequestParam(required = false) String poNumber, |
| | | @RequestParam(required = false) String style, |
| | | @RequestParam(required = false) String color, |
| | | @RequestParam(required = false) Integer cartonNumberFrom, |
| | | @RequestParam(required = false) Integer cartonNumberTo) { |
| | | if(Cools.isEmpty(poNumber)){ |
| | | return R.error("response.poNumber_no_exists"); |
| | | } |
| | | |
| | | EntityWrapper<LocDetl> wrapper = new EntityWrapper<>(); |
| | | if (!Cools.isEmpty(poNumber)) { |
| | | wrapper.eq("sku", poNumber); |
| | | } |
| | | if (!Cools.isEmpty(style)) { |
| | | wrapper.eq("specs", style); |
| | | } |
| | | if (!Cools.isEmpty(color)) { |
| | | wrapper.eq("color", color); |
| | | } |
| | | wrapper.eq("item_num",null); |
| | | |
| | | List<LocDetl> all = locDetlService.selectList(wrapper); |
| | | List<LocDetl> list = new ArrayList<>(); |
| | | |
| | | if (cartonNumberFrom == null && cartonNumberTo == null) { |
| | | list = all; |
| | | } else { |
| | | for (LocDetl item : all) { |
| | | String batch = item.getBatch(); |
| | | if (Cools.isEmpty(batch)) { |
| | | continue; |
| | | } |
| | | String numStr = batch.replaceAll("[^0-9]", ""); |
| | | if (Cools.isEmpty(numStr)) { |
| | | continue; |
| | | } |
| | | Integer num; |
| | | try { |
| | | num = Integer.parseInt(numStr); |
| | | } catch (NumberFormatException e) { |
| | | continue; |
| | | } |
| | | if (cartonNumberFrom != null && num < cartonNumberFrom) { |
| | | continue; |
| | | } |
| | | if (cartonNumberTo != null && num > cartonNumberTo) { |
| | | continue; |
| | | } |
| | | list.add(item); |
| | | } |
| | | } |
| | | |
| | | Map<String, Object> data = new HashMap<>(); |
| | | data.put("records", list); |
| | | data.put("total", list.size()); |
| | | |
| | | return R.ok(data); |
| | | } |
| | | |
| | | @RequestMapping(value = "/order/inspection/create/auth") |
| | | @ManagerAuth(memo = "response.create_inspection_order") |
| | | @Transactional |
| | | public R createInspectionOrder(@RequestBody Map<String, Object> params) { |
| | | String orderNo = (String) params.get("orderNo"); |
| | | String buyerShortCode = (String) params.get("buyerShortCode"); |
| | | List<Map<String, Object>> records = (List<Map<String, Object>>) params.get("records"); |
| | | |
| | | if (Cools.isEmpty(orderNo) || Cools.isEmpty(records)) { |
| | | return R.error("response.invalid_param"); |
| | | } |
| | | |
| | | Order orderCheck = orderService.selectByNo(orderNo); |
| | | if (orderCheck != null) { |
| | | return R.error("response.order_no_exists"); |
| | | } |
| | | |
| | | Date now = new Date(); |
| | | Long userId = getUserId(); |
| | | |
| | | // 查找检验类型的单据 |
| | | DocType inspectionDocType = docTypeService.selectOne(new EntityWrapper<DocType>().like("doc_name", "检验").or().like("doc_name", "Inspection")); |
| | | Long docTypeId = (inspectionDocType != null) ? inspectionDocType.getDocId() : null; |
| | | |
| | | // 使用与 formAdd 相同的完整构造函数确保所有必要字段都被初始化 |
| | | Order order = new Order( |
| | | String.valueOf(snowflakeIdWorker.nextId()), // 编号[非空] |
| | | orderNo, // 订单编号 |
| | | DateUtils.convert(now), // 单据日期 |
| | | docTypeId, // 单据类型 |
| | | null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, |
| | | 1L, // 订单状态 (待处理) |
| | | 1, // 状态 (正常) |
| | | userId, now, userId, now, |
| | | "Inspection Order for Buyer: " + buyerShortCode // 备注 |
| | | ); |
| | | |
| | | if (!orderService.insert(order)) { |
| | | throw new CoolException("response.save_order_master_failed"); |
| | | } |
| | | |
| | | // 保存所有检索到的记录作为订单明细 |
| | | for (Map<String, Object> record : records) { |
| | | OrderDetl detl = new OrderDetl(); |
| | | detl.setOrderId(Long.valueOf(order.getId())); |
| | | detl.setOrderNo(order.getOrderNo()); |
| | | detl.setMatnr((String) record.get("matnr")); |
| | | detl.setMaktx((String) record.get("maktx")); |
| | | detl.setSpecs((String) record.get("specs")); |
| | | detl.setColor((String) record.get("color")); |
| | | detl.setBatch((String) record.get("batch")); |
| | | detl.setAnfme(Double.valueOf(String.valueOf(record.get("anfme")))); |
| | | detl.setSku((String) record.get("sku")); |
| | | detl.setOrigin((String) record.get("zpallet")); |
| | | detl.setBarcode((String) record.get("barcode")); |
| | | detl.setManu((String) record.get("manu")); |
| | | detl.setManuDate((String) record.get("manuDate")); |
| | | |
| | | detl.setWorkQty(0.0); |
| | | detl.setQty(0.0); |
| | | detl.setStatus(1); |
| | | detl.setCreateBy(userId); |
| | | detl.setCreateTime(now); |
| | | detl.setUpdateBy(userId); |
| | | detl.setUpdateTime(now); |
| | | |
| | | if (!orderDetlService.insert(detl)) { |
| | | throw new CoolException("response.save_order_detail_failed"); |
| | | } |
| | | LocDetl locDetl = locDetlService.selectOne(new EntityWrapper<LocDetl>().eq("zpallet", detl.getOrigin()).eq("batch",detl.getBatch())); |
| | | if (locDetl != null) { |
| | | if (!locDetlService.updateInspectNumber(detl.getOrigin(),detl.getBatch(),detl.getOrderNo())) { |
| | | throw new CoolException("response.save_order_detail_failed"); |
| | | } |
| | | } |
| | | } |
| | | |
| | | return R.ok("response.order_add_success"); |
| | | } |
| | | |
| | | @RequestMapping(value = "/order/form/add/auth") |
| | | @ManagerAuth(memo = "response.manual_add_order") |
| | | @Transactional |
| | |
| | | @ManagerAuth(memo = "response.manual_delete_order") |
| | | @Transactional |
| | | public R delete(@RequestParam Long orderId){ |
| | | Order order = orderService.selectById(orderId); |
| | | if (order != null) { |
| | | DocType docType = docTypeService.selectById(order.getDocType()); |
| | | String docName = docType != null ? String.valueOf(docType.getDocName()) : ""; |
| | | if (!Cools.isEmpty(docName)) { |
| | | String dn = docName.toLowerCase(); |
| | | if (dn.contains("inspection") || dn.contains("检验")) { |
| | | locDetlService.clearInspectNumberByOrderNo(order.getOrderNo()); |
| | | } |
| | | } |
| | | } |
| | | orderService.remove(orderId); |
| | | // Order order = orderService.selectById(orderId); |
| | | // if (order != null) { |
| | |
| | | return R.ok(); |
| | | } |
| | | |
| | | @RequestMapping(value = "/order/checkInspection/auth") |
| | | @ManagerAuth |
| | | @Transactional |
| | | public R checkInspection(@RequestParam String orderNo, Integer inspectNumber) { |
| | | if (orderNo == null || orderNo.isEmpty()) { |
| | | return R.error("response.order_no_is_empty"); |
| | | } |
| | | |
| | | // 1. 更新库存明细中的检验状态 |
| | | locDetlService.updateInspectionStatus(orderNo, inspectNumber); |
| | | |
| | | // 2. 更新单据主档状态为已完成 (settle = 4) |
| | | Order order = orderService.selectByNo(orderNo); |
| | | if (order != null) { |
| | | order.setSettle(4L); |
| | | orderService.updateById(order); |
| | | } |
| | | |
| | | return R.ok("response.operation_success"); |
| | | } |
| | | |
| | | } |
| | |
| | | return R.ok(orderDetlService.getPakoutPage(toPage(curr, limit, param, OrderDetl.class))); |
| | | } |
| | | |
| | | @RequestMapping(value = "/orderDetl/pakout/inspectionList/auth") |
| | | @ManagerAuth |
| | | public R getPakoutInspectionPage(@RequestParam(defaultValue = "1")Integer curr, |
| | | @RequestParam(defaultValue = "10")Integer limit, |
| | | @RequestParam Map<String, Object> param){ |
| | | return R.ok(orderDetlService.getPakoutInspectionPage(toPage(curr, limit, param, OrderDetl.class))); |
| | | } |
| | | |
| | | private <T> void convert(Map<String, Object> map, EntityWrapper<T> wrapper){ |
| | | for (Map.Entry<String, Object> entry : map.entrySet()){ |
| | | String val = String.valueOf(entry.getValue()); |
| | |
| | | List<Integer> staNos = staDescService.queryOutStaNosByLocNo(locDetl.getLocNo(), issued >= locDetl.getAnfme() ? 101 : 103); |
| | | locDto.setStaNos(staNos); |
| | | locDtos.add(locDto); |
| | | exist.add(locDetl.getLocNo()); |
| | | exist.add(locDetl.getLocNo() + "|" + Optional.ofNullable(locDetl.getBatch()).orElse("")); |
| | | // 剩余待出数量递减 |
| | | issued = issued - locDetl.getAnfme(); |
| | | } else { |
| | |
| | | |
| | | LocDetl selectItem(@Param("locNo")String locNo, @Param("matnr")String matnr, @Param("batch")String batch); |
| | | LocDetl selectItemCarton(@Param("locNo")String locNo, @Param("matnr")String matnr, @Param("batch")String batch,@Param("barcode")String barcode); |
| | | |
| | | boolean updateInspectNumber(@Param("barcode")String barcode,@Param("batch")String batch,@Param("orderNo")String orderNo); |
| | | @Update("update asr_loc_detl set item_num = NULL where item_num = #{orderNo}") |
| | | boolean clearInspectNumberByOrderNo(@Param("orderNo")String orderNo); |
| | | List<LocDetl> selectItemByLocNo(String locNo); |
| | | |
| | | boolean updateInspectionStatus(@Param("orderNo")String orderNo,@Param("inspectNumber")Integer inspectNumber); |
| | | int deleteItem(@Param("locNo")String locNo, @Param("matnr")String matnr, @Param("batch")String batch); |
| | | |
| | | int updateAnfme(@Param("anfme")Double anfme, @Param("locNo")String locNo, @Param("matnr")String matnr, @Param("batch")String batch); |
| | |
| | | List<OrderDetl> selectWorkingDetls(Long orderId); |
| | | |
| | | List<OrderDetl> getPakoutPage(Map<String, Object> map); |
| | | List<OrderDetl> getPakoutInspectionPage(Map<String, Object> map); |
| | | Integer getPakoutInspectionPageCount(Map<String, Object> map); |
| | | |
| | | Integer getPakoutPageCount(Map<String, Object> map); |
| | | |
| | |
| | | |
| | | List<StockVo> queryStockTotal(); |
| | | |
| | | boolean updateInspectionStatus(String orderNo, Integer inspectNumber); |
| | | |
| | | Integer sum(); |
| | | |
| | |
| | | |
| | | List<String> getSameDetlList2(String orderNo,Integer areaId); |
| | | |
| | | boolean updateInspectNumber(String barcode,String batch,String orderNo); |
| | | boolean clearInspectNumberByOrderNo(String orderNo); |
| | | } |
| | |
| | | List<OrderDetl> selectByOrderId(Long orderId); |
| | | |
| | | Page<OrderDetl> getPakoutPage(Page<OrderDetl> page); |
| | | Page<OrderDetl> getPakoutInspectionPage(Page<OrderDetl> page); |
| | | |
| | | OrderDetl selectItem(Long orderId, String matnr, String batch); |
| | | OrderDetl selectItem(Long orderId, String matnr, String batch,String cartonLabel); |
| | |
| | | } |
| | | |
| | | @Override |
| | | public boolean updateInspectionStatus(String orderNo,Integer inspectNumber) { |
| | | return this.baseMapper.updateInspectionStatus(orderNo,inspectNumber); |
| | | } |
| | | |
| | | @Override |
| | | public boolean updateInspectNumber(String barcode, String batch,String orderNo) { |
| | | return this.baseMapper.updateInspectNumber(barcode, batch,orderNo); |
| | | } |
| | | |
| | | @Override |
| | | public boolean clearInspectNumberByOrderNo(String orderNo) { |
| | | return this.baseMapper.clearInspectNumberByOrderNo(orderNo); |
| | | } |
| | | |
| | | @Override |
| | | public LocDetl selectItemCarton(String locNo, String matnr, String batch,String barcode) { |
| | | return this.baseMapper.selectItemCarton(locNo, matnr, batch,barcode); |
| | | } |
| | |
| | | } |
| | | |
| | | @Override |
| | | public Page<OrderDetl> getPakoutInspectionPage(Page<OrderDetl> page) { |
| | | page.setRecords(baseMapper.getPakoutInspectionPage(page.getCondition())); |
| | | page.setTotal(baseMapper.getPakoutInspectionPageCount(page.getCondition())); |
| | | return page; |
| | | } |
| | | |
| | | @Override |
| | | public OrderDetl selectItem(Long orderId, String matnr, String batch) { |
| | | return this.baseMapper.selectItem(orderId, matnr, batch); |
| | | } |
| | |
| | | WrkDetl wrkDetl = wrkDetlList.get(0); |
| | | findLocNoAttributeVo.setMatnr(wrkDetl.getMatnr()); |
| | | findLocNoAttributeVo.setBatch(wrkDetl.getBatch()); |
| | | // StartupDto dto = commonService.getLocNo(1, devpNo, matnrs.get(0), batchs.get(0), null, locTypeDto); |
| | | findLocNoAttributeVo.setAreaId(7); |
| | | // StartupDto dto = commonServic9e.getLocNo(1, devpNo, matnrs.get(0), batchs.get(0), null, locTypeDto); |
| | | StartupDto dto = commonService.getLocNoNew(1, devpNo, findLocNoAttributeVo, locTypeDto,barcode); |
| | | if (dto == null) { |
| | | throw new CoolException("response.no_empty_location_found"); |
| | |
| | | <foreach item="item" collection="locNos" index="index" separator="," open="(" close=")"> |
| | | #{item} |
| | | </foreach> |
| | | and a.loc_no + '|' + isnull(a.batch,'') not in |
| | | <foreach item="item" collection="locNos" index="index" separator="," open="(" close=")"> |
| | | #{item} |
| | | </foreach> |
| | | </if> |
| | | |
| | | order by |
| | |
| | | and lm.loc_sts = 'F' |
| | | order by ld.appe_time asc |
| | | </select> |
| | | |
| | | <update id="updateInspectNumber"> |
| | | UPDATE asr_loc_detl SET item_num = #{orderNo} |
| | | WHERE batch = #{batch} and zpallet = #{barcode} |
| | | </update> |
| | | <update id="updateInspectionStatus"> |
| | | UPDATE asr_loc_detl SET inspect = #{inspectNumber} |
| | | WHERE item_num = #{orderNo} |
| | | </update> |
| | | </mapper> |
| | |
| | | <include refid="pakOutPageCondition"></include> |
| | | </select> |
| | | |
| | | <select id="getPakoutInspectionPage" resultMap="BaseResultMap"> |
| | | select * from |
| | | ( |
| | | select |
| | | ROW_NUMBER() over (order by mo.create_time desc) as row, |
| | | mod.* |
| | | from man_order_detl mod |
| | | inner join man_order mo on mod.order_id = mo.id |
| | | inner join man_doc_type mdt on mo.doc_type = mdt.doc_id |
| | | where 1=1 |
| | | and mo.settle <= 2 |
| | | and mo.status = 1 |
| | | and mdt.doc_id = 9 |
| | | <include refid="pakOutPageCondition"></include> |
| | | ) t where t.row between ((#{pageNumber}-1)*#{pageSize}+1) and (#{pageNumber}*#{pageSize}) |
| | | </select> |
| | | |
| | | <select id="getPakoutInspectionPageCount" parameterType="java.util.Map" resultType="java.lang.Integer"> |
| | | select |
| | | count(1) |
| | | from man_order_detl mod |
| | | inner join man_order mo on mod.order_id = mo.id |
| | | inner join man_doc_type mdt on mo.doc_type = mdt.doc_id |
| | | where 1=1 |
| | | and mo.settle <= 2 |
| | | and mo.status = 1 |
| | | and mdt.doc_id = 9 |
| | | <include refid="pakOutPageCondition"></include> |
| | | </select> |
| | | |
| | | <update id="increase"> |
| | | update man_order_detl |
| | | set qty = qty + #{qty} |
| | |
| | | { |
| | | { |
| | | "_comment_common": "Common Table Columns", |
| | | "_comment_home": "Home Tab Bar", |
| | | "access_address": "Access Address", |
| | |
| | | "configuration": "Configuration", |
| | | "confirm": "OK", |
| | | "confirm_adjust_location_detail": "Are you sure to adjust details for location?", |
| | | "confirm_inspect_fail": "Confirm inspection fail?", |
| | | "confirm_inspect_pass": "Confirm inspection pass?", |
| | | "confirm_cancel_erp_order": "Current task linked to ERP sales order. Cancellation will regenerate outbound task. Continue?", |
| | | "confirm_cancel_work_order": "Confirm cancel this work order?", |
| | | "confirm_complete_work_order": "Confirm complete this work order?", |
| | |
| | | "crane_no": "Crane No", |
| | | "crane_start_time": "Crane Start Time", |
| | | "create_detail": "Creation Detail", |
| | | "create_inspection_order": "Create Inspection Order", |
| | | "buyer_short_code": "Buyer Short Code", |
| | | "buyer_short_code_placeholder": "Enter Buyer Short Code", |
| | | "po_number": "PO Number", |
| | | "po_number_placeholder": "Enter PO Number", |
| | | "style": "Style", |
| | | "style_placeholder": "Enter Style", |
| | | "color_placeholder": "Enter Color", |
| | | "carton_from": "Carton From", |
| | | "carton_from_placeholder": "From", |
| | | "to": "To", |
| | | "carton_to_placeholder": "To", |
| | | "po_summary": "PO Summary", |
| | | "buyer_po": "Buyer PO", |
| | | "total_styles": "Total Styles", |
| | | "total_colors": "Total Colors", |
| | | "total_cartons": "Total Cartons", |
| | | "total_quantity": "Total Quantity", |
| | | "matching_locations": "Matching Locations", |
| | | "qty": "Qty", |
| | | "create_time": "Create Time", |
| | | "creator": "Creator", |
| | | "creator_detail": "Creator Details", |
| | |
| | | "input_qty_cannot_less_than_working": "Input quantity cannot be less than working quantity", |
| | | "inspection_reqd": "Inspection Reqd", |
| | | "inventory_quantity": "Inventory Qty", |
| | | "inspection_status": "Inspection Status", |
| | | "inspect_status_0": "Pending", |
| | | "inspect_status_1": "Pass", |
| | | "inspect_status_2": "Fail", |
| | | "io_status": "Transaction Status", |
| | | "io_type_1": "1.Inbound", |
| | | "io_type_10": "10.Empty Pallet Inbound", |
| | | "inspection_orders": "Inspection Orders", |
| | | "io_type_101": "101.Outbound", |
| | | "io_type_103": "103.Picking Outbound", |
| | | "io_type_104": "104.Merge Outbound", |
| | |
| | | "manual_cancel": "Manual Cancel", |
| | | "manual_complete": "Manual Complete", |
| | | "manufacturer": "Manufacturer", |
| | | "mat_code": "Item Code", |
| | | "mat_code": "Item Material", |
| | | "mat_code_label": "Item No.:", |
| | | "mat_multi_select": "Material - Multi Select", |
| | | "mat_name": "Item Name", |
| | |
| | | "no_intersection_outbound_station": "No intersection of outbound stations, cannot batch modify", |
| | | "no_task": "No Task", |
| | | "normal": "Normal", |
| | | "locNo": "location", |
| | | "not_worked": "Not Worked", |
| | | "one_click_outbound": "One-click Outbound", |
| | | "operation": "Operation", |
| | |
| | | "requesting": "Requesting...", |
| | | "reset": "Reset", |
| | | "reset_pwd": "Reset Pwd", |
| | | "order_details": "Order Details", |
| | | "reset_pwd_success": "Reset password successful", |
| | | "response.account_disabled": "Account Disabled", |
| | | "response.account_not_exist": "Account Not Exist", |
| | |
| | | "response.fetch_outbound_station_failed": "Failed to fetch outbound station", |
| | | "response.fifo_handling": "FIFO Handling", |
| | | "response.friday": "Friday", |
| | | "response.order_no_is_empty": "order no is empty", |
| | | "response.front_loc_has_goods_forbid_out": "Front Loc Has Goods Forbid Out", |
| | | "response.front_loc_has_in_task_forbid_out": "Front Loc Has In Task Forbid Out", |
| | | "response.full_pallet_inbound": "Full Pallet Inbound", |
| | |
| | | "select_template": "Select Template", |
| | | "select_type": "Select Type", |
| | | "selection_mode_tip": "Selection mode enabled, please drag to select on the location map", |
| | | "serial_code": "Serial Code", |
| | | "serial_code": "CTN", |
| | | "serial_number": "No.", |
| | | "settle_1": "Pending", |
| | | "settle_2": "Processing", |
| | |
| | | "source_location": "Source Location", |
| | | "source_location_no": "source location", |
| | | "source_station": "Source Station", |
| | | "spec": "Spec", |
| | | "spec_label": "Spec:", |
| | | "spec": "Style", |
| | | "spec_label": "Style label:", |
| | | "standard_crane_whs": "Standard Crane Whs", |
| | | "start_crane": "Start Crane", |
| | | "start_end_bay": "Start/End Bay", |
| | |
| | | "导出": "Export", |
| | | "登录": "Login", |
| | | "订单出库": "Order Outbound", |
| | | "检验出库": "Inspection Outbound", |
| | | "订单系统": "Order System", |
| | | "订单状态": "Order Status", |
| | | "堆垛机导出": "Export Stacker", |
| | |
| | | { |
| | | { |
| | | "_comment_common": "Common Table Columns", |
| | | "_comment_home": "主页标签栏", |
| | | "_comment_loc_map": "=== 库位热点图 ===", |
| | |
| | | "complete": "完成", |
| | | "confirm": "确定", |
| | | "confirm_adjust_location_detail": "确定调整库位的明细吗?", |
| | | "confirm_inspect_fail": "确认检验不通过?", |
| | | "confirm_inspect_pass": "确认检验通过?", |
| | | "confirm_cancel_erp_order": "当前任务关联ERP销售单,取消将重新生成出库作业,是否继续?", |
| | | "confirm_cancel_work_order": "确认取消该笔工作档?", |
| | | "confirm_complete_work_order": "确认完成该笔工作档?", |
| | |
| | | "crane_no": "堆垛机号", |
| | | "crane_start_time": "堆垛机启动时间", |
| | | "create_detail": "创建详情", |
| | | "create_inspection_order": "创建检验单", |
| | | "buyer_short_code": "买家标签", |
| | | "buyer_short_code_placeholder": "输入买家标签", |
| | | "po_number": "PO号", |
| | | "po_number_placeholder": "输入PO号", |
| | | "style": "款式", |
| | | "style_placeholder": "输入款式", |
| | | "color_placeholder": "输入颜色", |
| | | "carton_from": "箱号从", |
| | | "carton_from_placeholder": "起始箱号", |
| | | "to": "至", |
| | | "carton_to_placeholder": "结束箱号", |
| | | "po_summary": "PO 汇总", |
| | | "buyer_po": "买方PO", |
| | | "total_styles": "总款式数", |
| | | "total_colors": "总颜色数", |
| | | "total_cartons": "总箱数", |
| | | "total_quantity": "总数量", |
| | | "matching_locations": "匹配库位", |
| | | "qty": "数量", |
| | | "create_time": "创建时间", |
| | | "creator": "创建者", |
| | | "creator_detail": "创建者详情", |
| | |
| | | "inventory_quantity": "库存数量", |
| | | "io_status": "入出状态", |
| | | "io_type": "任务类型", |
| | | "inspection_status": "检验状态", |
| | | "inspect_status_0": "待检验", |
| | | "inspect_status_1": "检验通过", |
| | | "inspect_status_2": "检验失败", |
| | | "io_type_1": "1.入库", |
| | | "io_type_10": "10.空板入库", |
| | | "io_type_101": "101.出库", |
| | |
| | | "leader_label": "上级", |
| | | "level": "层", |
| | | "license_validity_prefix": "临时许可证有效期:", |
| | | "inspection_orders": "检验单据", |
| | | "item": "品项", |
| | | "license_validity_suffix": "天", |
| | | "light_location": "轻库位", |
| | | "line_item": "行项目", |
| | |
| | | "order_intro": "入库通知单:由ERP提供单据编号、类型、单据时间及物料明细,生成入库作业单,为维护系统高可用,用户可自行添加入库通知单数据,完成独立的入库作业。", |
| | | "order_intro_warning": "手动添加时,请检查单据编号是否在ERP系统中已存在,避免发生数据错误问题。", |
| | | "order_no": "单据编号", |
| | | "order_details": "单据明细", |
| | | "order_status": "订单状态", |
| | | "origin": "产地", |
| | | "original_item_no": "原品号", |
| | |
| | | "response.manual_process_work": "手动处理工作档", |
| | | "response.manual_work_handling": "手动处理工作档", |
| | | "response.mat_add": "物料新增", |
| | | "response.order_no_is_empty": "单据编号为空", |
| | | "response.mat_code_print": "物料条码打印", |
| | | "response.mat_delete": "物料删除", |
| | | "response.mat_detail": "物料详情", |
| | |
| | | "select_template": "选择模板", |
| | | "select_type": "选择类型", |
| | | "selection_mode_tip": "已开启框选模式,请在库位图上拖拽选择", |
| | | "serial_code": "序列码", |
| | | "serial_code": "箱号", |
| | | "serial_number": "序号", |
| | | "settle_1": "待处理", |
| | | "settle_2": "作业中", |
| | |
| | | "导出": "导出", |
| | | "登录": "登录", |
| | | "订单出库": "订单出库", |
| | | "检验出库": "检验出库", |
| | | "订单系统": "订单系统", |
| | | "订单状态": "订单状态", |
| | | "堆垛机导出": "堆垛机导出", |
| | |
| | | ,{field: 'deadTime', align: 'center',title: typeof I18n !== 'undefined' ? I18n.t('shelf_life') : 'Shelf Life', hide: true} |
| | | ,{field: 'deadWarn', align: 'center',title: typeof I18n !== 'undefined' ? I18n.t('warning_days') : 'Warning Days', hide: true} |
| | | ,{field: 'source$', align: 'center',title: typeof I18n !== 'undefined' ? I18n.t('make_buy') : 'Make/Buy', hide: true} |
| | | ,{field: 'check$', align: 'center',title: typeof I18n !== 'undefined' ? I18n.t('inspection_reqd') : 'Inspection Reqd', hide: true} |
| | | ,{field: 'inspect', align: 'center', title: typeof I18n !== 'undefined' ? I18n.t('inspection_status') : '检验状态', templet: function(d) { |
| | | if (d.inspect === 1) { |
| | | return '<span class="layui-badge layui-bg-green">' + (typeof I18n !== 'undefined' ? I18n.t('inspect_status_1') : '检验通过') + '</span>'; |
| | | } else if (d.inspect === 2) { |
| | | return '<span class="layui-badge layui-bg-red">' + (typeof I18n !== 'undefined' ? I18n.t('inspect_status_2') : '检验失败') + '</span>'; |
| | | } else { |
| | | return '<span class="layui-badge layui-bg-gray">' + (typeof I18n !== 'undefined' ? I18n.t('inspect_status_0') : '待检验') + '</span>'; |
| | | } |
| | | }} |
| | | ,{field: 'danger$', align: 'center',title: typeof I18n !== 'undefined' ? I18n.t('hazardous') : 'Hazardous', hide: true} |
| | | |
| | | ]; |
| | |
| | | var form = layui.form; |
| | | |
| | | // 数据渲染 |
| | | tableIns = table.render({ |
| | | var tableIns = table.render({ |
| | | elem: '#locDetl', |
| | | headers: {token: localStorage.getItem('token')}, |
| | | url: baseUrl+'/locDetl/list/auth', |
| | |
| | | |
| | | // 监听排序事件 |
| | | table.on('sort(locDetl)', function (obj) { |
| | | var searchData = {}; |
| | | $.each($('#search-box [name]').serializeArray(), function() { |
| | | searchData[this.name] = this.value; |
| | | }); |
| | | searchData['orderByField'] = obj.field; |
| | | searchData['orderByType'] = obj.type; |
| | | tableIns.reload({ |
| | | where: searchData, |
| | | initSort: obj, |
| | | where: { |
| | | orderByField: obj.field, |
| | | orderByType: obj.type |
| | | }, |
| | | page: { |
| | | curr: 1 |
| | | }, |
| | | done: function (res, curr, count) { |
| | | if (res.code === 403) { |
| | | top.location.href = baseUrl+"/"; |
| | | } |
| | | if (typeof I18n !== 'undefined') { |
| | | I18n.updatePage($('.layui-table-tool')); |
| | | setTimeout(function() { |
| | | I18n.updateLayuiPagination(); |
| | | }, 50); |
| | | } |
| | | pageCurr=curr; |
| | | limit(); |
| | | } |
| | | }); |
| | | }); |
| New file |
| | |
| | | var insTb, insTb2; |
| | | layui.config({ |
| | | base: baseUrl + "/static/layui/lay/modules/" |
| | | }).extend({ |
| | | notice: 'notice/notice', |
| | | tableMerge: 'tableMerge' |
| | | }).use(['table', 'laydate', 'form', 'util', 'admin', 'notice', 'xmSelect', 'tableMerge', 'tableX'], function(){ |
| | | var table = layui.table; |
| | | var $ = layui.jquery; |
| | | var layer = layui.layer; |
| | | var form = layui.form; |
| | | var admin = layui.admin; |
| | | var notice = layui.notice; |
| | | var tableMerge = layui.tableMerge; |
| | | var tableX = layui.tableX; |
| | | |
| | | /****************************************** 左侧检验订单表 *************************************************/ |
| | | function getLeftCols() { |
| | | return [[ |
| | | {field: 'orderTime', title: typeof I18n !== 'undefined' ? I18n.t('date') : '日期', width: 100}, |
| | | {field: 'orderNo', title: typeof I18n !== 'undefined' ? I18n.t('order_no') : '单据编号', align: 'center'} |
| | | ]]; |
| | | } |
| | | |
| | | var initLeftTable = function() { |
| | | insTb = table.render({ |
| | | elem: '#originTable', |
| | | url: baseUrl + '/order/inspect/list/auth', |
| | | headers: {token: localStorage.getItem('token')}, |
| | | height: 'full-180', |
| | | page: false, |
| | | request: { pageName: 'curr', pageSize: 'limit' }, |
| | | parseData: function (res) { |
| | | return { 'code': res.code, 'msg': res.msg, 'data': res.data }; |
| | | }, |
| | | response: { statusCode: 200 }, |
| | | text: { none: typeof I18n !== 'undefined' ? I18n.t('no_data') : '暂无数据' }, |
| | | cols: getLeftCols(), |
| | | done: function (res, curr, count) { |
| | | if (typeof I18n !== 'undefined' && I18n.isReady()) { |
| | | I18n.updatePage(); |
| | | if (count === 0) { $('.layui-table-empty').text(I18n.t('no_data')); } |
| | | } |
| | | // 默认选中第一行 |
| | | $('#originTable+.layui-table-view .layui-table-body tbody>tr:first').trigger('click'); |
| | | |
| | | // 绑定右键一键出库 |
| | | tableX.bindCtxMenu('originTable', function (d) { |
| | | return [{ |
| | | icon: 'layui-icon layui-icon-ok', |
| | | name: typeof I18n !== 'undefined' ? I18n.t('one_click_outbound') : '一键出库', |
| | | click: function (d) { autoOut(d.id); } |
| | | }] |
| | | }); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | /****************************************** 右侧订单明细表 *************************************************/ |
| | | function getRightCols() { |
| | | return [[ |
| | | {type: 'checkbox', merge: 'origin'}, |
| | | {field: 'origin', align: 'center', title: typeof I18n !== 'undefined' ? I18n.t('pallet_code') : '托盘码', merge: true, width: 140}, |
| | | {field: 'matnr', align: 'center', title: typeof I18n !== 'undefined' ? I18n.t('mat_code') : '商品编码', width: 140}, |
| | | {field: 'maktx', align: 'center', title: typeof I18n !== 'undefined' ? I18n.t('mat_name') : '商品名称', width: 180}, |
| | | {field: 'batch', align: 'center', title: typeof I18n !== 'undefined' ? I18n.t('serial_code') : '批号'}, |
| | | {field: 'specs', align: 'center', title: typeof I18n !== 'undefined' ? I18n.t('spec') : '规格'}, |
| | | {field: 'color', align: 'center', title: typeof I18n !== 'undefined' ? I18n.t('color') : '颜色'}, |
| | | // {field: 'origin', align: 'center', title: typeof I18n !== 'undefined' ? I18n.t('locationNo') : '库位号'}, |
| | | {field: 'enableQty', align: 'center', title: typeof I18n !== 'undefined' ? I18n.t('outbound_pending_qty') : '待出库数量', style: 'font-weight: bold'}, |
| | | {fixed: 'right', title: typeof I18n !== 'undefined' ? I18n.t('operation') : '操作', align: 'center', toolbar: '#operate', width: 120, merge: 'origin'} |
| | | ]]; |
| | | } |
| | | |
| | | var initRightTable = function() { |
| | | insTb2 = table.render({ |
| | | elem: '#orderDetlTable', |
| | | headers: {token: localStorage.getItem('token')}, |
| | | url: baseUrl + '/orderDetl/pakout/inspectionList/auth', |
| | | page: true, |
| | | limit: 15, |
| | | height: 'full-180', |
| | | toolbar: '#orderDetToolbar', |
| | | text: { none: typeof I18n !== 'undefined' ? I18n.t('no_data') : '暂无数据' }, |
| | | where: { order_id: -1 }, |
| | | cols: getRightCols(), |
| | | parseData: function (res) { |
| | | return { 'code': res.code, 'msg': res.msg, 'count': res.data.total, 'data': res.data.records }; |
| | | }, |
| | | response: { statusCode: 200 }, |
| | | done: function(res, curr, count) { |
| | | if (typeof I18n !== 'undefined' && I18n.isReady()) { |
| | | I18n.updatePage(); |
| | | I18n.updateLayuiPagination(); |
| | | } |
| | | tableMerge.render(this); |
| | | } |
| | | }); |
| | | }; |
| | | |
| | | // 监听语言切换事件 |
| | | $(document).on('i18n:languageChanged', function() { |
| | | if (typeof I18n !== 'undefined') { |
| | | I18n.updatePage(); |
| | | } |
| | | if (insTb) { |
| | | insTb.reload({ |
| | | cols: getLeftCols(), |
| | | text: { none: typeof I18n !== 'undefined' ? I18n.t('no_data') : '暂无数据' } |
| | | }); |
| | | } |
| | | if (insTb2) { |
| | | insTb2.reload({ |
| | | cols: getRightCols(), |
| | | text: { none: typeof I18n !== 'undefined' ? I18n.t('no_data') : '暂无数据' } |
| | | }); |
| | | } |
| | | }); |
| | | |
| | | // 初始化加载 |
| | | if (typeof I18n !== 'undefined' && I18n.isReady()) { |
| | | initLeftTable(); |
| | | initRightTable(); |
| | | } else { |
| | | $(document).on('i18n:ready', function() { |
| | | initLeftTable(); |
| | | initRightTable(); |
| | | }); |
| | | } |
| | | |
| | | // 监听左侧行单击 |
| | | var currentOrderId = -1; |
| | | table.on('row(originTable)', function (obj) { |
| | | currentOrderId = obj.data.id; |
| | | obj.tr.addClass('layui-table-click').siblings().removeClass('layui-table-click'); |
| | | insTb2.reload({ where: { order_id: currentOrderId }, page: { curr: 1 } }); |
| | | }); |
| | | |
| | | // 搜索与重置 |
| | | form.on('submit(originTableSearch)', function (data) { |
| | | insTb.reload({ where: data.field }); |
| | | return false; |
| | | }); |
| | | |
| | | form.on('submit(sensorTbSearch)', function (data) { |
| | | insTb2.reload({ where: data.field, page: { curr: 1 } }); |
| | | return false; |
| | | }); |
| | | |
| | | // 表格操作 |
| | | table.on('toolbar(orderDetlTable)', function (obj) { |
| | | var checkStatus = table.checkStatus(obj.config.id).data; |
| | | if (obj.event === 'pakoutPreview') { |
| | | if (checkStatus.length === 0) { |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t('select_at_least_one_outbound_detail') : '请至少选择一条出库明细', {icon: 2}); |
| | | return; |
| | | } |
| | | pakoutPreview(checkStatus.map(d => d.id)); |
| | | } else if (obj.event === 'oneClickOut') { |
| | | if (currentOrderId === -1) { |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t('please_select_order') : '请先选择订单', {icon: 2}); |
| | | return; |
| | | } |
| | | autoOut(currentOrderId); |
| | | } else if (obj.event === 'inspectPass') { |
| | | if (currentOrderId === -1) { |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t('please_select_order') : '请先选择订单', {icon: 2}); |
| | | return; |
| | | } |
| | | inspectPass(currentOrderId); |
| | | } else if (obj.event === 'inspectFail') { |
| | | if (currentOrderId === -1) { |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t('please_select_order') : '请先选择订单', {icon: 2}); |
| | | return; |
| | | } |
| | | inspectFail(currentOrderId); |
| | | } |
| | | }); |
| | | |
| | | table.on('tool(orderDetlTable)', function (obj) { |
| | | if (obj.event === 'pakoutPreview') { |
| | | // 获取当前 origin 分组的所有明细 ID |
| | | var origin = obj.data.origin; |
| | | var tableData = table.cache['orderDetlTable']; |
| | | var groupIds = []; |
| | | if (origin) { |
| | | for (var i = 0; i < tableData.length; i++) { |
| | | if (tableData[i].origin === origin && tableData[i].enableQty > 0) { |
| | | groupIds.push(tableData[i].id); |
| | | } |
| | | } |
| | | } else { |
| | | groupIds = [obj.data.id]; |
| | | } |
| | | |
| | | if (groupIds.length === 0) { |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t('no_available_qty') : '没有可出库数量', {icon: 2}); |
| | | return; |
| | | } |
| | | pakoutPreview(groupIds); |
| | | } |
| | | }); |
| | | |
| | | // 出库预览与确认逻辑 |
| | | function pakoutPreview(ids) { |
| | | let loadIndex = layer.load(2); |
| | | $.ajax({ |
| | | url: baseUrl + "/out/pakout/preview/auth", |
| | | headers: {'token': localStorage.getItem('token')}, |
| | | contentType: 'application/json;charset=UTF-8', |
| | | data: JSON.stringify(ids), |
| | | method: 'POST', |
| | | success: function (res) { |
| | | layer.close(loadIndex); |
| | | if (res.code === 200) { |
| | | var tableCache; |
| | | layer.open({ |
| | | type: 1, title: false, closeBtn: false, offset: '50px', area: ['1000px', '600px'], shade: 0.5, |
| | | btn: [I18n.t('immediate_outbound'), I18n.t('process_later')], btnAlign: 'c', |
| | | content: $('#pakoutPreviewBox').html(), |
| | | success: function(layero, index) { |
| | | I18n.updatePage($(layero)); |
| | | var stoPreTabIdx = table.render({ |
| | | elem: '#stoPreTab', data: res.data, height: 420, page: false, limit: 1000, |
| | | cols: [[ |
| | | {field: 'orderNo', title: I18n.t('order_no'), align: 'center'}, |
| | | {field: 'batch', title: I18n.t('serial_code'), align: 'center'}, |
| | | {field: 'anfme', title: I18n.t('quantity'), align: 'center', width: 90}, |
| | | {field: 'locNo', title: I18n.t('location'), align: 'center', width: 120, templet: '#locNoTpl', merge: true}, |
| | | {field: 'staNos', align: 'center', title: I18n.t('station_outbound'), templet: '#tbBasicTbStaNos', merge: 'locNo'}, |
| | | {type: 'checkbox', merge: 'locNo'} |
| | | ]], |
| | | done: function() { |
| | | tableCache = table.cache.stoPreTab; |
| | | I18n.updatePage($('.layui-table-view[lay-id="stoPreTab"]')); |
| | | form.render('select'); |
| | | tableMerge.render(this); |
| | | } |
| | | }); |
| | | |
| | | form.on('select(tbBasicTbStaNos)', function (obj) { |
| | | let idx = obj.othis.parents('tr').attr("data-index"); |
| | | let currentLocNo = tableCache[idx]['locNo']; |
| | | let selectedStaNo = Number(obj.elem.value); |
| | | |
| | | // 同一库位的所有记录同步选择相同的站点 |
| | | for (let i = 0; i < tableCache.length; i++) { |
| | | if (tableCache[i]['locNo'] === currentLocNo) { |
| | | tableCache[i]['staNo'] = selectedStaNo; |
| | | // 同时更新界面上该库位对应的所有下拉框(如果有多个的话) |
| | | let $selects = $(layero).find('tr[data-index="' + i + '"] select.order-sta-select'); |
| | | if ($selects.length > 0) { |
| | | $selects.val(obj.elem.value); |
| | | } |
| | | } |
| | | } |
| | | form.render('select'); |
| | | }); |
| | | |
| | | form.on('submit(batchModifySta)', function (data) { |
| | | let checkStatus = table.checkStatus('stoPreTab').data; |
| | | if (checkStatus.length === 0) { |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t('select_at_least_one_outbound_detail') : '请至少选择一条记录', {icon: 2}); |
| | | return false; |
| | | } |
| | | |
| | | // 获取第一个选中的有效站点作为基准 |
| | | let baseStaNo = null; |
| | | for (let i = 0; i < checkStatus.length; i++) { |
| | | if (checkStatus[i].staNo) { |
| | | baseStaNo = checkStatus[i].staNo; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | if (!baseStaNo) { |
| | | layer.msg('请先为其中一个选中项选择站点', {icon: 2}); |
| | | return false; |
| | | } |
| | | |
| | | // 应用到所有选中的行,并同步同库位的行 |
| | | for (let i = 0; i < checkStatus.length; i++) { |
| | | let targetLocNo = checkStatus[i].locNo; |
| | | for (let j = 0; j < tableCache.length; j++) { |
| | | if (tableCache[j].locNo === targetLocNo) { |
| | | tableCache[j].staNo = baseStaNo; |
| | | $(layero).find('tr[data-index="' + j + '"] select.order-sta-select').val(baseStaNo); |
| | | } |
| | | } |
| | | } |
| | | form.render('select'); |
| | | return false; |
| | | }); |
| | | }, |
| | | yes: function(index) { pakout(tableCache, index); }, |
| | | btn2: function(index) { layer.close(index); } |
| | | }); |
| | | } else { |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t(res.msg) : res.msg, {icon: 2}); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | function pakout(tableCache, layerIndex) { |
| | | notice.msg(typeof I18n !== 'undefined' ? I18n.t('generating_outbound_task') : '正在生成出库任务...', {icon: 4}); |
| | | $.ajax({ |
| | | url: baseUrl + "/out/pakout/auth", |
| | | headers: {'token': localStorage.getItem('token')}, |
| | | contentType: 'application/json;charset=UTF-8', |
| | | data: JSON.stringify(tableCache), |
| | | method: 'POST', |
| | | success: function (res) { |
| | | notice.destroy(); |
| | | if (res.code === 200) { |
| | | layer.close(layerIndex); |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t(res.msg) : res.msg, {icon: 1}); |
| | | insTb.reload(); |
| | | insTb2.reload({ page: { curr: 1 } }); |
| | | } else { |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t(res.msg) : res.msg, {icon: 2}); |
| | | } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | function autoOut(orderId) { |
| | | let loadIndex = layer.msg(typeof I18n !== 'undefined' ? I18n.t('requesting') : '请求中...', {icon: 16, shade: 0.01, time: false}); |
| | | $.ajax({ |
| | | url: baseUrl + "/out/pakout/orderDetlIds/auth", |
| | | headers: {'token': localStorage.getItem('token')}, |
| | | data: { orderId : orderId }, |
| | | method: 'POST', |
| | | success: function (res) { |
| | | layer.close(loadIndex); |
| | | if (res.code === 200) { pakoutPreview(res.data); } |
| | | else { layer.msg(typeof I18n !== 'undefined' ? I18n.t(res.msg) : res.msg, {icon: 2}); } |
| | | } |
| | | }); |
| | | } |
| | | |
| | | function inspectPass(orderId) { |
| | | var data = table.cache['originTable']; |
| | | var orderNo = ""; |
| | | for (var i = 0; i < data.length; i++) { |
| | | if (data[i].id == orderId) { |
| | | orderNo = data[i].orderNo; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | layer.confirm(typeof I18n !== 'undefined' ? I18n.t('confirm_inspect_pass') : '确认检验通过?', {icon: 3}, function (index) { |
| | | layer.close(index); |
| | | let loadIndex = layer.msg(typeof I18n !== 'undefined' ? I18n.t('processing') : '处理中...', {icon: 16, shade: 0.01, time: false}); |
| | | $.ajax({ |
| | | url: baseUrl + "/order/checkInspection/auth", |
| | | headers: {'token': localStorage.getItem('token')}, |
| | | data: { orderNo: orderNo, inspectNumber: 1 }, |
| | | method: 'POST', |
| | | success: function (res) { |
| | | layer.close(loadIndex); |
| | | if (res.code === 200) { |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t(res.msg) : res.msg, {icon: 1}); |
| | | insTb.reload(); |
| | | insTb2.reload({ where: { order_id: -1 }, page: { curr: 1 } }); |
| | | currentOrderId = -1; |
| | | } else { |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t(res.msg) : res.msg, {icon: 2}); |
| | | } |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | function inspectFail(orderId) { |
| | | var data = table.cache['originTable']; |
| | | var orderNo = ""; |
| | | for (var i = 0; i < data.length; i++) { |
| | | if (data[i].id == orderId) { |
| | | orderNo = data[i].orderNo; |
| | | break; |
| | | } |
| | | } |
| | | |
| | | layer.confirm(typeof I18n !== 'undefined' ? I18n.t('confirm_inspect_fail') : '确认检验不通过?', {icon: 3}, function (index) { |
| | | layer.close(index); |
| | | let loadIndex = layer.msg(typeof I18n !== 'undefined' ? I18n.t('processing') : '处理中...', {icon: 16, shade: 0.01, time: false}); |
| | | $.ajax({ |
| | | url: baseUrl + "/order/checkInspection/auth", |
| | | headers: {'token': localStorage.getItem('token')}, |
| | | data: { orderNo: orderNo, inspectNumber: 2 }, |
| | | method: 'POST', |
| | | success: function (res) { |
| | | layer.close(loadIndex); |
| | | if (res.code === 200) { |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t(res.msg) : res.msg, {icon: 1}); |
| | | insTb.reload(); |
| | | insTb2.reload({ where: { order_id: -1 }, page: { curr: 1 } }); |
| | | currentOrderId = -1; |
| | | } else { |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t(res.msg) : res.msg, {icon: 2}); |
| | | } |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | |
| | | // 暴露函数 |
| | | window.autoOut = autoOut; |
| | | window.inspectPass = inspectPass; |
| | | window.inspectFail = inspectFail; |
| | | }); |
| | |
| | | var insTbCount = 0; |
| | | var insTb; |
| | | var insLookTb; |
| | | layui.config({ |
| | | var insLookTb; |
| | | |
| | | function generateInspectionOrderNo(buyerCode) { |
| | | var now = new Date(); |
| | | var year = String(now.getFullYear()).slice(-2); |
| | | var code = (buyerCode || '').toUpperCase(); |
| | | var seq = String(now.getTime() % 100000).padStart(5, '0'); |
| | | return 'INS' + year + code + '/' + seq; |
| | | } |
| | | |
| | | layui.config({ |
| | | base: baseUrl + "/static/layui/lay/modules/" |
| | | }).use(['layer', 'form', 'table', 'util', 'admin', 'xmSelect', 'laydate'], function () { |
| | | var $ = layui.jquery; |
| | |
| | | showEditModel(); |
| | | }); |
| | | |
| | | $("#createInspectionBtn").click(function () { |
| | | openInspectionDialog(''); |
| | | }); |
| | | |
| | | // 工具条点击事件 |
| | | table.on('tool(order)', function (obj) { |
| | | var data = obj.data; |
| | |
| | | } |
| | | }); |
| | | |
| | | function openInspectionDialog(buyerCode) { |
| | | admin.open({ |
| | | type: 1, |
| | | title: I18n.t('create_inspection_order'), |
| | | content: $('#inspectionDialog').html(), |
| | | area: '1200px', |
| | | end: function () { |
| | | $(document).off('i18n:languageChanged.inspection'); |
| | | }, |
| | | success: function (layero, dIndex) { |
| | | I18n.updatePage($(layero)); |
| | | $(layero).children('.layui-layer-content').css('overflow', 'visible'); |
| | | var $container = $(layero); |
| | | function getMatchingLocationCols() { |
| | | return [[ |
| | | {type: 'numbers'}, |
| | | {field: 'locNo', title: (typeof I18n !== 'undefined' ? I18n.t('location_no') : 'Location No')}, |
| | | {field: 'specs', title: (typeof I18n !== 'undefined' ? I18n.t('style') : 'Style')}, |
| | | {field: 'color', title: (typeof I18n !== 'undefined' ? I18n.t('color') : 'Color')}, |
| | | {field: 'anfme', title: (typeof I18n !== 'undefined' ? I18n.t('qty') : 'Qty')} |
| | | ]]; |
| | | } |
| | | var inspectionTable = table.render({ |
| | | elem: '#matchingLocationsTable', |
| | | data: [], |
| | | page: true, |
| | | cellMinWidth: 80, |
| | | cols: getMatchingLocationCols(), |
| | | text: {none: (typeof I18n !== 'undefined' ? I18n.t('no_data') : 'No Data')}, |
| | | done: function () { |
| | | I18n.updateLayuiPagination(); |
| | | $(layero).find('.layui-table-view').css('margin', '0'); |
| | | }, |
| | | size: '' |
| | | }); |
| | | |
| | | $(document).on('i18n:languageChanged.inspection', function () { |
| | | if (typeof I18n !== 'undefined') { |
| | | I18n.updatePage($container); |
| | | } |
| | | inspectionTable.reload({ |
| | | cols: getMatchingLocationCols(), |
| | | text: {none: (typeof I18n !== 'undefined' ? I18n.t('no_data') : 'No Data')} |
| | | }); |
| | | }); |
| | | |
| | | function updateSummary(records) { |
| | | if (!records || !records.length) { |
| | | $container.find('#poSummaryBuyerPo').text(''); |
| | | $container.find('#poSummaryTotalStyles').text(0); |
| | | $container.find('#poSummaryTotalColors').text(0); |
| | | $container.find('#poSummaryTotalCartons').text(0); |
| | | $container.find('#poSummaryTotalQty').text(0); |
| | | return; |
| | | } |
| | | var buyerPo = records[0].sku || ''; |
| | | var styleSet = {}; |
| | | var colorSet = {}; |
| | | var cartonSet = {}; |
| | | var totalQty = 0; |
| | | for (var i = 0; i < records.length; i++) { |
| | | var r = records[i]; |
| | | if (r.specs) styleSet[r.specs] = true; |
| | | if (r.color) colorSet[r.color] = true; |
| | | if (r.batch) cartonSet[r.batch] = true; |
| | | if (r.anfme) totalQty += Number(r.anfme) || 0; |
| | | } |
| | | $container.find('#poSummaryBuyerPo').text(buyerPo); |
| | | $container.find('#poSummaryTotalStyles').text(Object.keys(styleSet).length); |
| | | $container.find('#poSummaryTotalColors').text(Object.keys(colorSet).length); |
| | | $container.find('#poSummaryTotalCartons').text(Object.keys(cartonSet).length); |
| | | $container.find('#poSummaryTotalQty').text(totalQty); |
| | | } |
| | | |
| | | var lastSearchRecords = []; |
| | | form.on('submit(inspectionSearch)', function (data) { |
| | | var searchParam = data.field || {}; |
| | | $.ajax({ |
| | | url: baseUrl + "/order/inspection/matchingLocations/auth", |
| | | headers: {'token': localStorage.getItem('token')}, |
| | | data: searchParam, |
| | | method: 'GET', |
| | | success: function (res) { |
| | | if (res.code === 200) { |
| | | var records = res.data && res.data.records ? res.data.records : (res.data || []); |
| | | lastSearchRecords = records; |
| | | inspectionTable.reload({data: records, page: {curr: 1}}); |
| | | updateSummary(records); |
| | | } else if (res.code === 403) { |
| | | top.location.href = baseUrl+"/"; |
| | | } else { |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t(res.msg) : res.msg, {icon: 2}); |
| | | } |
| | | } |
| | | }); |
| | | return false; |
| | | }); |
| | | |
| | | $container.find('#inspectionCreateBtn').click(function () { |
| | | var buyerCodeInput = ($container.find('input[name="buyerShortCode"]').val() || buyerCode || '').trim(); |
| | | if (!buyerCodeInput) { |
| | | var msg = 'Buyer short code不能为空'; |
| | | if (typeof I18n !== 'undefined') { |
| | | msg = I18n.t('buyer_short_code') + I18n.t('form_required'); |
| | | } |
| | | layer.msg(msg, {icon: 2}); |
| | | return; |
| | | } |
| | | if (!lastSearchRecords || lastSearchRecords.length === 0) { |
| | | layer.msg('请先检索出匹配库位数据', {icon: 2}); |
| | | return; |
| | | } |
| | | var orderNo = generateInspectionOrderNo(buyerCodeInput); |
| | | |
| | | layer.load(2); |
| | | $.ajax({ |
| | | url: baseUrl + "/order/inspection/create/auth", |
| | | headers: {'token': localStorage.getItem('token')}, |
| | | contentType: 'application/json;charset=UTF-8', |
| | | data: JSON.stringify({ |
| | | orderNo: orderNo, |
| | | buyerShortCode: buyerCodeInput, |
| | | records: lastSearchRecords |
| | | }), |
| | | method: 'POST', |
| | | success: function (res) { |
| | | layer.closeAll('loading'); |
| | | if (res.code === 200) { |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t(res.msg) : res.msg, {icon: 1}); |
| | | layer.close(dIndex); |
| | | insTb.reload({page: {curr: 1}}); |
| | | } else { |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t(res.msg) : res.msg, {icon: 2}); |
| | | } |
| | | }, |
| | | error: function() { |
| | | layer.closeAll('loading'); |
| | | layer.msg(typeof I18n !== 'undefined' ? I18n.t('load_failed') : 'Load failed', {icon: 2}); |
| | | } |
| | | }); |
| | | }); |
| | | } |
| | | }); |
| | | } |
| | | |
| | | // 显示表单弹窗 |
| | | function showEditModel(expTpe) { |
| | | admin.open({ |
| New file |
| | |
| | | <!DOCTYPE html> |
| | | <html lang="en"> |
| | | <head> |
| | | <meta charset="utf-8"> |
| | | <title>检验出库</title> |
| | | <meta name="renderer" content="webkit"> |
| | | <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> |
| | | <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"> |
| | | <link rel="stylesheet" href="../../static/layui/css/layui.css" media="all"> |
| | | <link rel="stylesheet" href="../../static/css/admin.css?v=318" media="all"> |
| | | <link rel="stylesheet" href="../../static/css/cool.css" media="all"> |
| | | <link rel="stylesheet" href="../../static/css/originTable.css" media="all"> |
| | | <style> |
| | | body { color: #595959; background-color: #f5f7f9; } |
| | | .admin-form { padding: 25px 30px 0 0 !important; margin: 0 !important; } |
| | | /* 权限控制 */ |
| | | #btn-pakoutPreview { display: none; } |
| | | |
| | | /* 优化搜索栏对齐 */ |
| | | .toolbar .layui-form-item { |
| | | margin-bottom: 0; |
| | | display: flex; |
| | | flex-wrap: wrap; |
| | | align-items: center; |
| | | } |
| | | .toolbar .layui-inline { |
| | | margin-right: 15px; |
| | | margin-bottom: 10px; |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | .toolbar .layui-form-label { |
| | | width: auto !important; |
| | | padding: 0 10px 0 0 !important; |
| | | line-height: 38px; |
| | | height: 38px; |
| | | } |
| | | .toolbar .layui-input-inline { |
| | | width: 180px !important; |
| | | margin-right: 0 !important; |
| | | } |
| | | /* 左侧搜索栏特殊处理 */ |
| | | #left-table .toolbar .layui-input-inline { |
| | | width: 140px !important; |
| | | } |
| | | </style> |
| | | </head> |
| | | <body> |
| | | <!-- 正文开始 --> |
| | | <div class="layui-fluid" style="padding-bottom: 0;"> |
| | | </style> |
| | | </head> |
| | | <body> |
| | | <!-- 正文开始 --> |
| | | <div class="layui-fluid" style="padding-bottom: 0;"> |
| | | <div class="layui-row layui-col-space15"> |
| | | <!-- 左侧:检验单据 --> |
| | | <div class="layui-col-md3" id="left-table"> |
| | | <div class="layui-card"> |
| | | <div class="layui-card-header" data-i18n="inspection_orders">检验单据</div> |
| | | <div class="layui-card-body" style="padding: 10px;"> |
| | | <form class="layui-form toolbar"> |
| | | <div class="layui-form-item"> |
| | | <div class="layui-inline"> |
| | | <div class="layui-input-inline"> |
| | | <input name="orderNo" class="layui-input" placeholder="" data-i18n="order_no" autocomplete="off"/> |
| | | </div> |
| | | <button class="layui-btn icon-btn" lay-filter="originTableSearch" lay-submit> |
| | | <i class="layui-icon"></i> |
| | | </button> |
| | | </div> |
| | | </div> |
| | | </form> |
| | | <table id="originTable" lay-filter="originTable"></table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <!-- 右侧:订单明细 --> |
| | | <div class="layui-col-md9"> |
| | | <div class="layui-card"> |
| | | <div class="layui-card-header" data-i18n="order_details">订单明细</div> |
| | | <div class="layui-card-body" style="padding: 10px;"> |
| | | <form class="layui-form toolbar"> |
| | | <div class="layui-form-item"> |
| | | <div class="layui-inline"> |
| | | <label class="layui-form-label" data-i18n="mat_code">商品编码</label> |
| | | <div class="layui-input-inline"> |
| | | <input name="matnr" class="layui-input" placeholder="" data-i18n="mat_code"/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <label class="layui-form-label" data-i18n="serial_code">批号</label> |
| | | <div class="layui-input-inline"> |
| | | <input name="batch" class="layui-input" placeholder="" data-i18n="serial_code"/> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <button class="layui-btn icon-btn" lay-filter="sensorTbSearch" lay-submit> |
| | | <i class="layui-icon"></i><span data-i18n="search">搜索</span> |
| | | </button> |
| | | </div> |
| | | </div> |
| | | </form> |
| | | <table id="orderDetlTable" lay-filter="orderDetlTable"></table> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <!-- 头工具栏 --> |
| | | <script type="text/html" id="orderDetToolbar"> |
| | | <button class="layui-btn layui-btn-sm layui-btn-danger" id="btn-pakoutPreview" lay-event="pakoutPreview"> |
| | | <i class="layui-icon"></i> <span data-i18n="batch_outbound">批量出库</span> |
| | | </button> |
| | | <button class="layui-btn layui-btn-sm layui-btn-warm" id="btn-oneClickOut" lay-event="oneClickOut"> |
| | | <i class="layui-icon"></i> <span data-i18n="one_click_outbound">一键出库</span> |
| | | </button> |
| | | <button class="layui-btn layui-btn-sm layui-btn-normal" id="btn-inspectPass" lay-event="inspectPass"> |
| | | <i class="layui-icon"></i> <span data-i18n="inspect_pass">检验通过</span> |
| | | </button> |
| | | <button class="layui-btn layui-btn-sm layui-btn-primary layui-border-red" id="btn-inspectFail" lay-event="inspectFail"> |
| | | <i class="layui-icon">ဆ</i> <span data-i18n="inspect_fail">检验失败</span> |
| | | </button> |
| | | </script> |
| | | |
| | | <!-- 行工具栏 --> |
| | | <script type="text/html" id="operate"> |
| | | {{# if (d.enableQty > 0) { }} |
| | | <a class="layui-btn layui-btn-xs layui-btn-danger" lay-event="pakoutPreview"> |
| | | <i class="layui-icon"></i> <span data-i18n="outbound">出库</span> |
| | | </a> |
| | | {{# } }} |
| | | </script> |
| | | |
| | | <!-- 出库预览弹窗 --> |
| | | <script type="text/html" id="pakoutPreviewBox" style="display: none"> |
| | | <div style="padding: 20px; background-color: #393D49; color: #fff;"> |
| | | <span style="font-size: 18px; font-weight: bold" data-i18n="outbound_preview">出库预览</span> |
| | | </div> |
| | | <div class="layui-card"> |
| | | <div class="layui-card-body"> |
| | | <table id="stoPreTab" lay-filter="stoPreTab"></table> |
| | | </div> |
| | | <div style="text-align: right; padding: 10px;"> |
| | | <button class="layui-btn layui-btn-primary layui-border-black layui-btn-sm" lay-filter="batchModifySta" lay-submit data-i18n="batch_modify">批量修改站点</button> |
| | | </div> |
| | | </div> |
| | | </script> |
| | | |
| | | <!-- 库位显示模板 --> |
| | | <script type="text/html" id="locNoTpl"> |
| | | {{# if( d.lack === false){ }} |
| | | <span class="layui-badge layui-badge-green">{{d.locNo}}</span> |
| | | {{# } else { }} |
| | | <span class="layui-badge layui-badge-red" data-i18n="stock_shortage">缺货</span> |
| | | {{# } }} |
| | | </script> |
| | | |
| | | <!-- 站点选择模板 --> |
| | | <script type="text/html" id="tbBasicTbStaNos"> |
| | | <div class="ew-select-fixed"> |
| | | <select class="order-sta-select" lay-filter="tbBasicTbStaNos"> |
| | | <option value="" data-i18n="please_select">请选择</option> |
| | | {{# if(d.staNos != null) { }} |
| | | {{# for(let i=0; i<d.staNos.length; i++) { }} |
| | | <option value="{{d.staNos[i]}}">{{d.staNos[i]}}</option> |
| | | {{# } }} |
| | | {{# } }} |
| | | </select> |
| | | </div> |
| | | </script> |
| | | |
| | | <script type="text/javascript" src="../../static/js/jquery/jquery-3.3.1.min.js"></script> |
| | | <script type="text/javascript" src="../../static/js/handlebars/handlebars-v4.5.3.js"></script> |
| | | <script type="text/javascript" src="../../static/layui/layui.js" charset="utf-8"></script> |
| | | <script type="text/javascript" src="../../static/js/common.js" charset="utf-8"></script> |
| | | <script type="text/javascript" src="../../static/js/cool.js" charset="utf-8"></script> |
| | | <script src="../../static/js/i18n/i18n-helper.js"></script> |
| | | <script type="text/javascript" src="../../static/js/order/inspect.js" charset="utf-8"></script> |
| | | |
| | | </body> |
| | | </html> |
| | |
| | | <button class="layui-btn icon-btn" lay-filter="tbSearch" lay-submit> |
| | | <i class="layui-icon"></i><span data-i18n="search">搜索</span> |
| | | </button> |
| | | <button id="createInspectionBtn" class="layui-btn icon-btn btn-add" type="button"> |
| | | <i class="layui-icon"></i><span data-i18n="create_inspection_order">创建检验单</span> |
| | | </button> |
| | | <button id="orderAddBtn" class="layui-btn icon-btn btn-add"><i class="layui-icon"></i><span data-i18n="add">添加</span> |
| | | </button> |
| | | </div> |
| | |
| | | </div> |
| | | <!-- 表格操作列 --> |
| | | <script type="text/html" id="operate"> |
| | | {{# if (d.settle == 0 || d.settle == 1) { }} |
| | | {{# if ((d.settle == 0 || d.settle == 1) && d.docType !=9) { }} |
| | | <a class="layui-btn layui-btn-primary layui-btn-xs btn-edit" lay-event="edit">{{ I18n.t('modify') }}</a> |
| | | <a class="layui-btn layui-btn-danger layui-btn-xs btn-delete" lay-event="del">{{ I18n.t('delete') }}</a> |
| | | {{# } }} |
| | | {{# if (d.settle == 0 || d.settle == 1 ) { }} |
| | | <a class="layui-btn layui-btn-danger layui-btn-xs btn-delete" lay-event="del">{{ I18n.t('delete') }}</a> |
| | | {{# } }} |
| | | {{# if (d.settle == 2) { }} |
| | | <a class="layui-btn layui-btn-primary layui-border-blue layui-btn-xs btn-complete" lay-event="complete">{{ I18n.t('complete') }}</a> |
| | |
| | | </div> |
| | | </form> |
| | | </script> |
| | | <!-- 检验单创建弹窗 --> |
| | | <script type="text/html" id="inspectionDialog"> |
| | | <div class="layui-form model-form" style="padding: 15px;"> |
| | | <div class="layui-form-item"> |
| | | <div class="layui-inline"> |
| | | <label class="layui-form-label" style="width: 110px;" data-i18n="po_number">PO Number</label> |
| | | <div class="layui-input-inline" style="width: 200px;"> |
| | | <input name="poNumber" class="layui-input" type="text" placeholder="PO Number" data-i18n-placeholder="po_number_placeholder"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <label class="layui-form-label" style="width: 80px;" data-i18n="style">Style</label> |
| | | <div class="layui-input-inline" style="width: 160px;"> |
| | | <input name="style" class="layui-input" type="text" placeholder="Style" data-i18n-placeholder="style_placeholder"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <label class="layui-form-label" style="width: 80px;" data-i18n="color">Color</label> |
| | | <div class="layui-input-inline" style="width: 160px;"> |
| | | <input name="color" class="layui-input" type="text" placeholder="Color" data-i18n-placeholder="color_placeholder"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <label class="layui-form-label" style="width: 120px;" data-i18n="carton_from">Carton From</label> |
| | | <div class="layui-input-inline" style="width: 120px;"> |
| | | <input name="cartonNumberFrom" class="layui-input" type="number" placeholder="From" data-i18n-placeholder="carton_from_placeholder"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <label class="layui-form-label" style="width: 1px;" data-i18n="to">To</label> |
| | | <div class="layui-input-inline" style="width: 120px;"> |
| | | <input name="cartonNumberTo" class="layui-input" type="number" placeholder="To" data-i18n-placeholder="carton_to_placeholder"> |
| | | </div> |
| | | </div> |
| | | <div class="layui-inline"> |
| | | <button class="layui-btn" lay-filter="inspectionSearch" lay-submit><span data-i18n="search">搜索</span></button> |
| | | </div> |
| | | </div> |
| | | <div class="layui-form-item"> |
| | | <fieldset class="layui-elem-field"> |
| | | <legend data-i18n="po_summary" style="font-size: 18px; font-weight: inherit;">Po Summary</legend> |
| | | <div class="layui-field-box"> |
| | | <div class="layui-row layui-col-space10"> |
| | | <div class="layui-col-md2"> |
| | | <span data-i18n="buyer_po">Buyer PO</span>: |
| | | <span id="poSummaryBuyerPo"></span> |
| | | </div> |
| | | <div class="layui-col-md2"> |
| | | <span data-i18n="total_styles">Total Styles</span>: |
| | | <span id="poSummaryTotalStyles"></span> |
| | | </div> |
| | | <div class="layui-col-md2"> |
| | | <span data-i18n="total_colors">Total Colors</span>: |
| | | <span id="poSummaryTotalColors"></span> |
| | | </div> |
| | | <div class="layui-col-md2"> |
| | | <span data-i18n="total_cartons">Total Cartons</span>: |
| | | <span id="poSummaryTotalCartons"></span> |
| | | </div> |
| | | <div class="layui-col-md2"> |
| | | <span data-i18n="total_quantity">Total Quantity</span>: |
| | | <span id="poSummaryTotalQty"></span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | </fieldset> |
| | | </div> |
| | | <div class="layui-form-item"> |
| | | <fieldset class="layui-elem-field"> |
| | | <legend data-i18n="matching_locations" style="font-size: 18px; font-weight: inherit;">Matching Locations</legend> |
| | | <div class="layui-field-box"> |
| | | <table id="matchingLocationsTable" lay-filter="matchingLocationsTable"></table> |
| | | </div> |
| | | </fieldset> |
| | | </div> |
| | | <div class="layui-form-item"> |
| | | <div class="layui-inline"> |
| | | <label class="layui-form-label" style="width: 140px;" data-i18n="buyer_short_code">Buyer short code</label> |
| | | <div class="layui-input-inline" style="width: 180px;"> |
| | | <input name="buyerShortCode" class="layui-input" type="text" placeholder="Buyer short code" data-i18n-placeholder="buyer_short_code_placeholder"> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="layui-form-item text-right"> |
| | | <button class="layui-btn layui-btn-primary" type="button" ew-event="closeDialog" data-i18n="cancel">取消</button> |
| | | <button class="layui-btn" type="button" id="inspectionCreateBtn"><span data-i18n="create_inspection_order">创建检验单</span></button> |
| | | </div> |
| | | </div> |
| | | </script> |
| | | <!-- 订单任务追溯 --> |
| | | <script id="wrkTraceDialog" type="text/html" style="position: relative"> |
| | | <div style="position: absolute; top: 0; left: 0;"> |