物流项目第十期(轨迹微服务)

article/2025/7/24 7:15:22

本项目专栏:

物流项目_Auc23的博客-CSDN博客

建议先看这期:

MongoDB入门之Java的使用-CSDN博客

物流项目第九期(MongoDB的应用之作业范围)-CSDN博客

业务需求

快递员取件成功后,需要将订单转成运单,用户会比较关注目前包裹走到哪里,类似这样:

需求描述

轨迹微服务是一个独立的微服务,主要提供创建运单轨迹点、记录最新位置、查询轨迹这些服务,具体要求如下:

  • 运单创建成功后,为运单创建轨迹点数据,并且将此数据持久化,以供后续的查询
  • 司机端在运输途中,需要上报最新的位置,更新相应的运单的最新位置数据
  • 快递员端在运输途中,需要上报最新的位置,更新相应的运单的最新位置数据
  • 提供查询轨迹的接口服务
  • 为查询轨迹接口服务设置缓存
  • 用户签收后,需要关闭轨迹的更新,不再更新最新位置数据

业务流程

MQListener

@Slf4j
@Component
public class MQListener {@Resourceprivate TrackService trackService;/*** 创建运单后创建轨迹** @param msg 消息*/@RabbitListener(bindings = @QueueBinding(value = @Queue(name = Constants.MQ.Queues.TRACK_TRANSPORT_ORDER_CREATED),exchange = @Exchange(name = Constants.MQ.Exchanges.TRANSPORT_ORDER_DELAYED, type = ExchangeTypes.TOPIC, delayed = Constants.MQ.DELAYED),key = Constants.MQ.RoutingKeys.TRANSPORT_ORDER_CREATE))public void listenTransportOrderCreatedMsg(String msg) {log.info("接收到新增运单的消息 ({})-> {}", Constants.MQ.Queues.TRACK_TRANSPORT_ORDER_CREATED, msg);TransportOrderMsg transportOrderMsg = JSONUtil.toBean(msg, TransportOrderMsg.class);this.trackService.create(transportOrderMsg.getId());}/*** 运单签收后完成轨迹** @param msg 消息*/@RabbitListener(bindings = @QueueBinding(value = @Queue(name = Constants.MQ.Queues.TRACK_TRANSPORT_ORDER_UPDATE_STATUS),exchange = @Exchange(name = Constants.MQ.Exchanges.TRANSPORT_ORDER_DELAYED, type = ExchangeTypes.TOPIC, delayed = Constants.MQ.DELAYED),key = Constants.MQ.RoutingKeys.TRANSPORT_ORDER_UPDATE_STATUS_PREFIX + "RECEIVED"))public void listenTransportOrderUpdateStatusMsg(String msg) {log.info("接收到更新运单状态的消息 ({})-> {}", Constants.MQ.Queues.TRACK_TRANSPORT_ORDER_UPDATE_STATUS, msg);TransportOrderStatusMsg transportOrderStatusMsg = JSONUtil.toBean(msg, TransportOrderStatusMsg.class);this.trackService.complete(transportOrderStatusMsg.getIdList());}
}

util

public class TrackEntityUtil {/*** 将 TrackEntity 转换为 TrackDTO* 主要用于接口返回或业务层使用,脱敏敏感字段并格式化数据结构** @param trackEntity 原始实体对象(来自数据库)* @return 转换后的 DTO 对象(用于返回给前端或其他服务)*/public static TrackDTO toDTO(TrackEntity trackEntity) {// 创建 CopyOptions 配置项,指定忽略某些字段的复制// 这里忽略了 planGeoJsonLine 和 lastPoint 字段,因为这两个字段是 GeoJSON 类型,不适合直接暴露给外部// ignoreNullValue 表示不复制 null 值属性,避免空值污染 DTOCopyOptions copyOptions = CopyOptions.create().setIgnoreProperties("planGeoJsonLine", "lastPoint").ignoreNullValue();// 使用 Hutool 的 BeanUtil.toBean 方法进行基础字段拷贝// 会自动将 trackEntity 中非忽略字段复制到 TrackDTO 中TrackDTO trackDTO = BeanUtil.toBean(trackEntity, TrackDTO.class, copyOptions);// 处理计划轨迹点(planGeoJsonLine):这是一个 GeoJsonLineString 类型的地理轨迹线GeoJsonLineString planGeoJsonLine = trackEntity.getPlanGeoJsonLine();if (ObjectUtil.isAllNotEmpty(planGeoJsonLine, planGeoJsonLine.getCoordinates())) {// 如果轨迹线及其坐标列表存在且非空,则进行转换// 将 GeoJsonLineString 中的坐标点列表转换为 MarkerPointDTO 列表List<MarkerPointDTO> coordinateList = planGeoJsonLine.getCoordinates().stream()// 每个 Coordinate 点转成 MarkerPointDTO(只包含 x 和 y 坐标).map(point -> new MarkerPointDTO(point.getX(), point.getY()))// 收集为 List<MarkerPointDTO>.collect(Collectors.toList());// 设置到 DTO 的 pointList 字段中,供前端展示使用trackDTO.setPointList(coordinateList);}// 处理最新位置坐标(lastPoint):是一个 GeoJsonPoint 类型的点if (ObjectUtil.isNotEmpty(trackEntity.getLastPoint())) {// 如果 lastPoint 存在// 获取该点的经纬度信息GeoJsonPoint point = trackEntity.getLastPoint();// 转换成 MarkerPointDTO 并设置到 DTO 中trackDTO.setLastPoint(new MarkerPointDTO(point.getX(), point.getY()));}// 返回最终处理好的 DTO 对象return trackDTO;}}

entity

/*** 轨迹数据** @author zzj* @version 1.0*/
@Data
@Document("sl_track")
public class TrackEntity {@Id@JsonIgnoreprivate ObjectId id;/*** 运单id*/@Indexedprivate String transportOrderId;/*** 规划的轨迹坐标点线(通过地图服务商规划出来的轨迹点)*/private GeoJsonLineString planGeoJsonLine;/*** 距离,单位:米*/private Double distance;/*** 最新的位置坐标,x:经度,y:纬度*/private GeoJsonPoint lastPoint;/*** 状态*/private TrackStatusEnum status;/*** 类型*/private TrackTypeEnum type;/*** 创建时间*/private Long created;/*** 更新时间*/private Long updated;}

enums

/*** 异常枚举** @author zzj* @version 1.0*/
public enum TrackExceptionEnum implements BaseExceptionEnum {TRACK_ALREADY_EXISTS(1001, "轨迹已经存在");private Integer code;private Integer status;private String value;TrackExceptionEnum(Integer code, String value) {this.code = code;this.value = value;this.status = 500;}TrackExceptionEnum(Integer code, Integer status, String value) {this.code = code;this.value = value;this.status = status;}@Overridepublic Integer getCode() {return this.code;}@Overridepublic String getValue() {return this.value;}@Overridepublic Integer getStatus() {return this.status;}public static TrackExceptionEnum codeOf(Integer code) {return EnumUtil.getBy(TrackExceptionEnum::getCode, code);}
}

controller

@RestController
@Api(tags = "轨迹管理")
@RequestMapping("track")
public class TrackController {@Resourceprivate TrackService trackService;@PostMapping@ApiOperation(value = "创建轨迹", notes = "创建轨迹,会完成路线规划")@ApiImplicitParams({@ApiImplicitParam(name = "transportOrderId", value = "运单号", required = true)})public boolean create(@RequestParam("transportOrderId") String transportOrderId) {return this.trackService.create(transportOrderId);}@PutMapping("complete")@ApiOperation(value = "完成轨迹", notes = " 完成轨迹,修改为完成状态")@ApiImplicitParams({@ApiImplicitParam(name = "transportOrderIds", value = "运单号列表", required = true)})public boolean complete(@RequestParam("transportOrderIds") List<String> transportOrderIds) {return this.trackService.complete(transportOrderIds);}/*** 通过运单号查询轨迹** @param transportOrderId 运单号* @return 轨迹数据*/@GetMapping("{transportOrderId}")@ApiOperation(value = "查询轨迹", notes = "通过运单号查询轨迹")@ApiImplicitParams({@ApiImplicitParam(name = "transportOrderId", value = "运单号", required = true)})public TrackDTO queryByTransportOrderId(@PathVariable("transportOrderId") String transportOrderId) {TrackEntity trackEntity = this.trackService.queryByTransportOrderId(transportOrderId);return TrackEntityUtil.toDTO(trackEntity);}@PutMapping("upload/truck")@ApiOperation(value = "车辆上报位置", notes = "车辆上报位置")@ApiImplicitParams({@ApiImplicitParam(name = "transportTaskId", value = "运输任务id", required = true),@ApiImplicitParam(name = "lng", value = "经度", required = true),@ApiImplicitParam(name = "lat", value = "纬度", required = true),})public boolean uploadFromTruck(@RequestParam("transportTaskId") Long transportTaskId,@RequestParam("lng") double lng,@RequestParam("lat") double lat) {return this.trackService.uploadFromTruck(transportTaskId, lng, lat);}@PutMapping("upload/courier")@ApiOperation(value = "快递员上报位置", notes = "快递员上报位置")@ApiImplicitParams({@ApiImplicitParam(name = "transportOrderIds", value = "运单号列表", required = true),@ApiImplicitParam(name = "lng", value = "经度", required = true),@ApiImplicitParam(name = "lat", value = "纬度", required = true),})public boolean uploadFromCourier(@RequestParam("transportOrderIds") List<String> transportOrderIds,@RequestParam("lng") double lng,@RequestParam("lat") double lat) {return this.trackService.uploadFromCourier(transportOrderIds, lng, lat);}}

service

/*** 轨迹服务** @author zzj* @version 1.0*/
public interface TrackService {/*** 创建轨迹,会完成路线规划** @param transportOrderId 运单号* @return 是否成功*/boolean create(String transportOrderId);/*** 完成轨迹,修改为完成状态** @param transportOrderIds 运单号列表* @return 是否成功*/boolean complete(List<String> transportOrderIds);/*** 通过运单号查询轨迹** @param transportOrderId 运单号* @return 轨迹数据*/TrackEntity queryByTransportOrderId(String transportOrderId);/*** 车辆上报位置** @param transportTaskId 运输任务id* @param lng             经度* @param lat             纬度* @return 是否成功*/boolean uploadFromTruck(Long transportTaskId, double lng, double lat);/*** 快递员上报位置** @param transportOrderIds 运单号列表* @param lng               经度* @param lat               纬度* @return 是否成功*/boolean uploadFromCourier(List<String> transportOrderIds, double lng, double lat);}

实现接口

/*** TrackServiceImpl 是一个服务实现类,用于处理物流轨迹相关的业务逻辑。* 包括创建轨迹、更新状态、路径规划、位置上报等功能。*/
@Service // Spring 注解,表示这是一个服务层 Bean,可被自动注入使用
public class TrackServiceImpl implements TrackService {/*** MongoDB 操作模板,用于持久化 TrackEntity 数据*/@Resourceprivate MongoTemplate mongoTemplate;/*** 自定义的地图服务模板(如封装了高德地图 API),用于路径规划等地理操作*/@Resourceprivate EagleMapTemplate eagleMapTemplate;/*** Feign 客户端,用于调用运输订单微服务接口*/@Resourceprivate TransportOrderFeign transportOrderFeign;/*** Feign 客户端,用于调用运输任务微服务接口*/@Resourceprivate TransportTaskFeign transportTaskFeign;/*** Feign 客户端,用于调用订单微服务接口*/@Resourceprivate OrderFeign orderFeign;/*** Feign 客户端,用于调用组织机构微服务接口*/@Resourceprivate OrganFeign organFeign;/*** 创建一个新的物流轨迹记录** @param transportOrderId 运单 ID* @return 是否创建成功*/@Overridepublic boolean create(String transportOrderId) {// 构造查询条件:根据 transportOrderId 查询是否已有对应轨迹记录Query query = Query.query(Criteria.where("transportOrderId").is(transportOrderId));// 从 MongoDB 中查找是否存在该运单的轨迹信息TrackEntity trackEntity = mongoTemplate.findOne(query, TrackEntity.class);// 如果已经存在轨迹数据,则抛出自定义异常 TRACK_ALREADY_EXISTSif (ObjectUtil.isNotEmpty(trackEntity)) {throw new SLException(TrackExceptionEnum.TRACK_ALREADY_EXISTS);}// 创建新的轨迹实体对象TrackEntity track = new TrackEntity();track.setTransportOrderId(transportOrderId); // 设置运单 IDtrack.setStatus(TrackStatusEnum.NEW); // 设置初始状态为“新建”track.setCreated(System.currentTimeMillis()); // 设置创建时间戳track.setUpdated(track.getCreated()); // 初始更新时间等于创建时间// 调用方法获取计划路线 GeoJSON 线段,并设置到轨迹实体中track.setPlanGeoJsonLine(this.queryPlanGeoJsonLineString(transportOrderId, track));// 将新创建的轨迹实体保存到 MongoDBthis.mongoTemplate.save(track);// 返回 true 表示创建成功return true;}/*** 获取计划路线的 GeoJsonLineString(即路径线)** @param transportOrderId 运单 ID* @param track            当前轨迹实体(用于设置距离等属性)* @return GeoJsonLineString 表示路径线*/private GeoJsonLineString queryPlanGeoJsonLineString(String transportOrderId, TrackEntity track) {// 通过 Feign 接口获取运输订单详情TransportOrderDTO transportOrderDTO = transportOrderFeign.findById(transportOrderId);// 获取运输线路字符串(通常是 JSON 格式的运输节点列表)String transportLine = transportOrderDTO.getTransportLine();String wayPoints = null;// 如果运输线路不为空if (StrUtil.isNotEmpty(transportLine)) {// 解析成 JSON 对象JSONObject transportLineJson = JSONUtil.parseObj(transportLine);// 获取节点列表 JSONArrayJSONArray nodeList = transportLineJson.getJSONArray("nodeList");// 遍历每个节点,提取经纬度并格式化为 "lng,lat" 字符串List<String> pointList = nodeList.stream().map(obj -> {JSONObject json = (JSONObject) obj;double longitude = json.getDouble("longitude", 0d);double latitude = json.getDouble("latitude", 0d);// 如果经纬度为 0,标记为错误点if (ObjectUtil.equalsAny(0d, longitude, latitude)) {return "err";}// 正常点则格式化为字符串return StrUtil.format("{},{}", longitude, latitude);})// 过滤掉错误点.filter(o -> ObjectUtil.notEqual(o, "err")).collect(Collectors.toList());// 多个坐标点之间用分号拼接,作为途经点参数wayPoints = StrUtil.join(";", pointList);} else {// 如果没有运输线路信息,则尝试获取当前网点的经纬度作为起点OrganDTO organDTO = this.organFeign.queryById(transportOrderDTO.getCurrentAgencyId());if (ObjectUtil.isNotEmpty(organDTO)) {// 使用网点坐标作为途经点wayPoints = StrUtil.format("{},{}", organDTO.getLongitude(), organDTO.getLatitude());} else {// 理论上不会出现这种情况,如果没有就不设置途经点}}// 获取订单的位置信息(发货地和收货地)OrderLocationDTO orderLocationDTO = this.orderFeign.findOrderLocationByOrderId(transportOrderDTO.getOrderId());// 格式化发货地和收货地坐标CoordinateUtil.Coordinate origin = CoordinateUtil.format(orderLocationDTO.getSendLocation());CoordinateUtil.Coordinate destination = CoordinateUtil.format(orderLocationDTO.getReceiveLocation());// 构建请求参数 MapMap<String, Object> param = MapUtil.<String, Object>builder().put(ObjectUtil.isNotEmpty(wayPoints), "waypoints", wayPoints) // 添加途经点(如果有的话).put("show_fields", "polyline") // 请求返回 polyline 字段.build();// 调用地图服务,获取驾车路线规划结果String driving = this.eagleMapTemplate.opsForDirection().driving(ProviderEnum.AMAP, new Coordinate(origin), new Coordinate(destination), param);// 如果返回为空,说明调用失败或无结果if (StrUtil.isEmpty(driving)) {return null;}// 解析返回的 JSON 数据JSONObject jsonObject = JSONUtil.parseObj(driving);// 提取总距离Double distance = Convert.toDouble(jsonObject.getByPath("route.paths[0].distance"), -1d);track.setDistance(distance); // 设置到轨迹实体中// 提取步骤列表JSONArray steps = jsonObject.getByPath("route.paths[0].steps", JSONArray.class);// 收集所有坐标点List<Point> points = new ArrayList<>();// 获取所有 polyline 字段值(每一步的坐标点集合)List<Object> polyLines = CollUtil.getFieldValues(steps, "polyline");for (Object polyLine : polyLines) {// 将 polyline 字符串拆分成多个坐标点List<GeoJsonPoint> list = StrUtil.split(Convert.toStr(polyLine), ';').stream().map(coordinateStr -> {// 拆分为 lng 和 latdouble[] ds = Convert.convert(double[].class, StrUtil.splitTrim(coordinateStr, ','));return new GeoJsonPoint(ds[0], ds[1]);}).collect(Collectors.toList());// 添加到总坐标点列表中points.addAll(list);}// 返回构造好的 GeoJsonLineString(代表整条路径线)return new GeoJsonLineString(points);}/*** 批量完成轨迹记录(更新状态为 COMPLETE)** @param transportOrderIds 运单 ID 列表* @return 是否有记录被修改*/@Overridepublic boolean complete(List<String> transportOrderIds) {// 构造查询条件:匹配 transportOrderId 在传入列表中的记录,且状态为 NEWQuery query = Query.query(Criteria.where("transportOrderId").in(transportOrderIds));// 构造更新语句:将 status 更新为 COMPLETEUpdate update = Update.update("status", TrackStatusEnum.COMPLETE);// 执行批量更新UpdateResult updateResult = this.mongoTemplate.updateMulti(query, update, TrackEntity.class);// 如果修改了至少一条记录,返回 truereturn updateResult.getModifiedCount() > 0;}/*** 根据运单 ID 查询轨迹实体** @param transportOrderId 运单 ID* @return 查询到的 TrackEntity 实体对象 或 null*/@Overridepublic TrackEntity queryByTransportOrderId(String transportOrderId) {// 构造查询条件:按 transportOrderId 查询Query query = Query.query(Criteria.where("transportOrderId").is(transportOrderId));// 查询唯一匹配的记录return this.mongoTemplate.findOne(query, TrackEntity.class);}/*** 司机端上报当前位置** @param transportTaskId 运输任务 ID* @param lng             经度* @param lat             纬度* @return 是否上报成功*/@Overridepublic boolean uploadFromTruck(Long transportTaskId, double lng, double lat) {// 根据运输任务 ID 查询对应的运单 ID 列表List<String> list = this.transportTaskFeign.queryTransportOrderIdListById(transportTaskId);// 调用通用上传方法,类型为 DRIVERreturn upload(list, lng, lat, TrackTypeEnum.DRIVER);}/*** 快递员端上报当前位置** @param transportOrderIds 运单 ID 列表* @param lng               经度* @param lat               纬度* @return 是否上报成功*/@Overridepublic boolean uploadFromCourier(List<String> transportOrderIds, double lng, double lat) {// 直接调用通用上传方法,类型为 COURIERreturn upload(transportOrderIds, lng, lat, TrackTypeEnum.COURIER);}/*** 通用位置上报逻辑** @param transportOrderIds 运单 ID 列表* @param lng               经度* @param lat               纬度* @param trackTypeEnum     上报类型(DRIVER/COURIER)* @return 是否更新成功*/private boolean upload(List<String> transportOrderIds, double lng, double lat, TrackTypeEnum trackTypeEnum) {// 如果运单列表为空,直接返回 falseif (CollUtil.isEmpty(transportOrderIds)) {return false;}// 构造查询条件:transportOrderId 在列表中,且状态为 NEWQuery query = Query.query(Criteria.where("transportOrderId").in(transportOrderIds).and("status").is(TrackStatusEnum.NEW));// 构造更新内容:更新 lastPoint(最新位置)、type(轨迹类型)、updated(更新时间)Update update = Update.update("lastPoint", new GeoJsonPoint(lng, lat)).set("type", trackTypeEnum).set("updated", System.currentTimeMillis());// 执行批量更新UpdateResult updateResult = this.mongoTemplate.updateMulti(query, update, TrackEntity.class);// 返回是否成功更新(是否有记录被修改)return updateResult.getModifiedCount() > 0;}
}


http://www.hkcw.cn/article/buieSenZbc.shtml

相关文章

【C++高级主题】命令空间(四):命名空间成员的使用

目录 一、扼要重述&#xff1a;命名空间的本质 二、using声明&#xff1a;精准引入单个成员 2.1 定义与语法 2.2 using声明的作用域 2.3 using声明的关键特性 三、命名空间别名&#xff1a;简化长命名空间 3.1 定义与语法 3.2 使用场景 3.3 注意事项 四、using指示&a…

Java基础知识总结继承与多态详解

1. 引言 面向对象编程的核心概念 面向对象编程是模拟人的思维方式来组织代码&#xff0c;便于处理复杂的业务。 面向对象四大核心特征&#xff1a; 封装&#xff1a;将数据和操作数据的方法组合在一起&#xff0c;隐藏内部实现的具体细节&#xff0c;只需要暴露必要的接口。 …

Lyra学习笔记2 GFA_AddComponents与ULyraPlayerSpawningManagerComponent

目录 前言GameFeatureAction_AddComponentsULyraPlayerSpawningManagerComponent缓存所有PlayerStart位置选择位置 前言 1.以control模式为例 2.比较散&#xff0c;想单独拿出一篇梳理下Experience的流程 GameFeatureAction_AddComponents 这部分建议看 《InsideUE5》GameFeatu…

EDW2025|数据治理的神话破除——从误区到现实

在当今数据驱动的世界中&#xff0c;数据治理已成为企业成功的关键因素。然而&#xff0c;许多组织在实施数据治理时&#xff0c;常常被一些常见的误区所困扰。本文将逐一破除这些误区&#xff0c;揭示数据治理的真实面貌。 误区一&#xff1a;你需要一个大的预算&#xff01;…

(24)多租户 SaaS 平台设计

文章目录 2️⃣4️⃣ 多租户 SaaS 平台设计 &#x1f3e2;&#x1f510;&#x1f680; 多租户SaaS平台&#xff1a;打造云端共享公寓的隔离术&#xff01;&#x1f3d7;️ 多租户架构模型&#xff1a;三种共存方式1️⃣ 独立数据库模式2️⃣ 共享数据库&#xff0c;独立Schema模…

理想树图书:以科技赋能教育,开启AI时代自主学习新范式

深耕教育沃土 构建全场景教辅产品矩阵 自2013年创立以来&#xff0c;理想树始终以教育匠心回应时代命题。在教辅行业这片竞争激烈的领域&#xff0c;由专业教育工作者组成的理想树图书始终秉持“知识互映”理念&#xff0c;经过十余年的精耕细作&#xff0c;精心打造了小学同步…

26 C 语言函数深度解析:定义与调用、返回值要点、参数机制(值传递)、原型声明、文档注释

1 函数基础概念 1.1 引入函数的必要性 在《街霸》这类游戏中&#xff0c;实现出拳、出脚、跳跃等动作&#xff0c;每项通常需编写 50 - 80 行代码。若每次调用都重复编写这些代码&#xff0c;程序会变得臃肿不堪&#xff0c;代码可读性与维护性也会大打折扣。 为解决这一问题&…

网易 - 灵犀办公文档

一. 企业介绍 网易是中国领先的互联网技术公司&#xff0c;为用户提供免费邮箱、游戏、搜索引擎服务&#xff0c;通过开设新闻、娱乐、体育等30多个内容频道&#xff0c;以及博客、视频、论坛等互动交流&#xff0c;网聚人的力量。 为了给中小企业和个人打造一款综合性办公产…

2025年素养大赛编程赛项练习题

我用K克网盘分享了「最新素养大赛.zip」&#xff0c;点击链接即可保存。打开「K克App」&#xff0c;无需下载在线播放视频&#xff0c;畅享原画5倍速&#xff0c;支持电视投屏。 链接&#xff1a;https://pan.quark.cn/s/c2f85a297992 提取码&#xff1a;d4Uq

CSS3前端入门(第三天)2D转换 transform

转换&#xff08;transform&#xff09;是CSS3中具有颠覆性的特征之一&#xff0c;可以根据实现元素的位移、旋转、缩放等效果 移动&#xff1a;translate旋转&#xff1a;rorate缩放&#xff1a;scale 2D转换之移动translate 2D移动是2D转换里面的一种功能&#xff0c;可以…

深兰科技董事长陈海波受邀出席2025苏商高质量发展(常州)峰会,共话AI驱动产业升级

5月29日&#xff0c;2025苏商高质量发展峰会在常州隆重开幕。本次峰会聚焦新质生产力培育与产业创新转型&#xff0c;汇聚了众多江苏省内知名企业家、专家学者及政府代表。深兰科技创始人、董事长陈海波作为人工智能领域的领军企业代表&#xff0c;受邀出席盛会并参与重要活动环…

【软件】navicat 官方免费版

Navicat Premium Lite https://www.navicat.com.cn/download/navicat-premium-lite

AIGC与影视制作:技术革命、产业重构与未来图景

文章目录 一、AIGC技术全景&#xff1a;从算法突破到产业赋能1. **技术底座&#xff1a;多模态大模型的进化路径**2. **核心算法&#xff1a;从生成对抗网络到扩散模型的迭代** 二、AIGC在影视制作全流程中的深度应用1. **剧本创作&#xff1a;从“灵感枯竭”到“创意井喷”**2…

消防体能考核器材的智能化发展

消防员体能考核器材的智能化发展&#xff0c;在实际应用中带来了诸多益处。 一、精准计时与动作评判 高精度计时 &#xff1a;如400米障碍智能考官&#xff0c;依托高精度传感器和先进算法&#xff0c;能够精确到毫秒记录跑步用时&#xff0c;改变了传统人工计时易出现误差的…

大厂前端研发岗位设计的30道Webpack面试题及解析

文章目录 一、基础核心二、配置进阶三、性能优化四、Loader原理五、Plugin机制六、高级应用七、工程化实战八、原理深挖九、异常处理十、综合场景一、基础核心 Webpack的核心概念是什么? 解析:入口(entry)、输出(output)、加载器(loader)、插件(plugins)、模式(mode)。Loader…

展会聚焦丨漫途科技亮相2025西北水务博览会!

2025第三届西北水务数字化发展论坛暨供排水节水灌溉新技术设备博览会在兰州甘肃国际会展中心圆满落幕。本届展会以“科技赋能水资源&#xff0c;数智引领新动能”为主题&#xff0c;活动汇集水务集团、科研院所、技术供应商等全产业链参与者&#xff0c;旨在通过前沿技术展示与…

二、OpenCV图像处理-图像处理

目录 1、连通性 2、形态学操作 2.1腐蚀和膨胀 2.2开闭运算 2.3礼帽和黑帽 2.4总结 3、图像平滑 3.1图像噪声 3.2均值滤波 3.3高斯滤波 3.4中值滤波 3.5总结 4、直方图 4.1直方图的原理与显示 4.2掩膜的应用 4.3直方图均衡化 4.4自适应均衡化 4.5总结 5、边缘…

代码随想录算法训练营 Day60 图论Ⅹ Bellmen_ford 系列算法

图论 题目 94. 城市间货物运输 I Bellmen_ford 队列优化算法 SPFA 大家可以发现 Bellman_ford 算法每次松弛 都是对所有边进行松弛。 但真正有效的松弛&#xff0c;是基于已经计算过的节点在做的松弛。 本图中&#xff0c;对所有边进行松弛&#xff0c;真正有效的松弛&#…

CppCon 2014 学习:Making C++ Code Beautiful

你说的完全正确&#xff0c;也很好地总结了 C 这门语言在社区中的两种典型看法&#xff1a; C 的优点&#xff08;Praise&#xff09; 优点含义Powerful允许底层控制、系统编程、高性能计算、模板元编程、并发等多种用途Fast无运行时开销&#xff0c;接近汇编级别性能&#x…

手机照片太多了存哪里?

手机相册里塞满了旅行照片、生活碎片&#xff0c;每次清理都舍不得删&#xff1f;NAS——一款超实用的存储方案&#xff0c;让你的回忆安全又有序&#xff5e; 1️⃣自动备份解放双手 手机 / 电脑 / 相机照片全自动同步到 NAS&#xff0c;再也不用手动传文件 2️⃣远程访问像…