鸿蒙NEXT项目实战-百得知识库05
代码仓地址,大家记得点个star
IbestKnowTeach: 百得知识库基于鸿蒙NEXT稳定版实现的一款企业级开发项目案例。 本案例涉及到多个鸿蒙相关技术知识点: 1、布局 2、配置文件 3、组件的封装和使用 4、路由的使用 5、请求响应拦截器的封装 6、位置服务 7、三方库的使用和封装 8、头像上传 9、应用软件更新等
https://gitee.com/xt1314520/IbestKnowTeach
消息页面开发
设计图


需求分析

消息组件的封装
import { CommonConstant } from '../contants/CommonConstant'@Componentexport struct MessageComponent {@State icon: ResourceStr = ''@State title: string = ''@Prop content: string@Prop unReadCount: numberbuild() {Row({ space: 15 }) {Badge({count: this.unReadCount,position: BadgePosition.RightTop,style: { badgeSize: 15, badgeColor: '#FA2A2D' }}) {Image(this.icon).width($r('app.float.common_width_small')).aspectRatio(1)}Column({ space: 10 }) {Text(this.title).fontWeight(FontWeight.Medium).fontSize($r('app.float.common_font_size_medium'))Text(this.content).maxLines(1).textOverflow({ overflow: TextOverflow.Ellipsis }).fontColor($r('app.color.common_gray')).fontSize($r('app.float.common_font_size_small'))}.height(80).justifyContent(FlexAlign.Center).alignItems(HorizontalAlign.Start).width('80%')}.width(CommonConstant.WIDTH_FULL).height(80).backgroundColor($r('app.color.common_white')).borderRadius(15).padding(10)}}
编写消息页面的接口方法
import http from '../request/Request'
import { MessageInfoNew, PageVo, UserMessageCount, UserMessageInfo, UserMessagePageParam } from './MessageApi.type'/*** 消息接口*/
class MessageApi {/*** 获取最新消息*/getMessageNew = (): Promise<Array<MessageInfoNew>> => {return http.get('/v1/message/new')}/*** 查询用户获得的消息总数量和未读*/getUserMessageCount = (): Promise<UserMessageCount> => {return http.get('/v1/message/count')}/*** 用户根据消息分类查询分页的消息*/getMessageList = (data: UserMessagePageParam): Promise<PageVo<UserMessageInfo>> => {return http.get('/v1/message/list?type=' + data.type + '&&page=' + data.page + '&&pageSize=' + data.pageSize)}/*** 查看消息详情*/getMessageInfo = (data: number): Promise<UserMessageInfo> => {return http.get('/v1/message/info?id=' + data)}
}const messageApi = new MessageApi();export default messageApi as MessageApi;
/*** 最新消息*/
export interface MessageInfoNew extends BaseTime {/*** 消息id*/id: number/*** 消息标题*/title: string/*** 消息内容*/content: string/*** 消息类型'1' 系统消息 '2' 通知公告*/type: string}/*** 时间*/
export interface BaseTime {/*** 创建时间*/createTime?: Date/*** 更新时间*/updateTime?: Date
}/*** 分页参数*/
export interface PageParam {/*** 当前页*/page?: number/*** 每一页展示的数据条数*/pageSize?: number
}/*** 消息总数量和未读*/
export interface UserMessageCount {/*** 总消息数量*/totalQuantity: number/*** 总未读数量*/totalUnReadQuantity: number/*** 系统消息未读数量*/systemUnReadQuantity: number/*** 通知公告消息未读数量*/noticeUnReadQuantity: number
}/*** 用户消息详情*/
export interface UserMessageInfo extends BaseTime {/*** 用户消息id*/id: number/*** 是否查看 '0'未查看 '1'查看*/isLook: string/*** 消息id*/messageId?: number/*** 消息标题*/title: string/*** 消息内容*/content: string/*** 消息类型'1' 系统消息 '2' 通知公告*/type?: string/*** 创建时间*/time: string}/*** 分页响应参数*/
export interface PageVo<T> {current: number,size: number,total: number,records: Array<T>
}/*** 用户根据消息分类查询所有的消息*/
export interface UserMessagePageParam extends PageParam {/*** 消息类型*/type: string
}
学习页面开发
设计图

需求分析

学习打卡
1、手机定位
在module.json5文件里面配置位置权限

代码向用户申请权限(弹窗)
/*** 动态授权*/
async aboutToAppear() {// 使用UIExtensionAbility:将common.UIAbilityContext 替换为common.UIExtensionContextconst context: common.UIAbilityContext = getContext(this) as common.UIAbilityContext;// 定义要申请的权限const permissions: Array<Permissions> = ['ohos.permission.APPROXIMATELY_LOCATION'];let atManager: abilityAccessCtrl.AtManager = abilityAccessCtrl.createAtManager();// requestPermissionsFromUser会判断权限的授权状态来决定是否唤起弹窗try {const data = await atManager.requestPermissionsFromUser(context, permissions);let grantStatus: Array<number> = data.authResults;let length: number = grantStatus.length;for (let i = 0; i < length; i++) {if (grantStatus[i] === 0) {// 获取位置信息this.getLocation()} else {// 用户拒绝授权,提示用户必须授权才能访问当前页面的功能,并引导用户到系统设置中打开相应的权限showToast('用户必须授权才能访问当前定位功能')return;}}} catch (error) {showToast('用户必须授权才能访问当前定位功能')}
}
获取用户位置信息,获取经度纬度然后进行地理编码
/*** 获取位置*/
async getLocation() {let request: geoLocationManager.SingleLocationRequest = {'locatingPriority': geoLocationManager.LocatingPriority.PRIORITY_LOCATING_SPEED,'locatingTimeoutMs': 10000}try {// 调用getCurrentLocation获取当前设备位置,通过promise接收上报的位置const result = await geoLocationManager.getCurrentLocation(request)Logger.info('current location: ' + JSON.stringify(result));// 判断地理编码服务是否可用let isAvailable = geoLocationManager.isGeocoderAvailable();if (isAvailable) {// 地理编码服务可用let reverseGeocodeRequest: geoLocationManager.ReverseGeoCodeRequest ={ "latitude": result.latitude, "longitude": result.longitude, "maxItems": 1 };geoLocationManager.getAddressesFromLocation(reverseGeocodeRequest, (err, data) => {if (err) {Logger.error('getAddressesFromLocation err: ' + JSON.stringify(err));} else {Logger.info('getAddressesFromLocation data: ' + JSON.stringify(data));// 成功获取到位置信息this.location = data[0].administrativeArea + '' + data[0].subAdministrativeAreareturn}});} else {showToast('地理编码服务不可用')}} catch (err) {Logger.error("errCode:" + JSON.stringify(err));showToast("获取位置失败")}
}
2、日历组件
使用我们一开始项目准备阶段引入的鸿蒙三方库ibest-ui
import { IBestCalendar } from "@ibestservices/ibest-ui";
// 日历
IBestCalendar({clock: true, // 设置 clock 为 true, 可开启打卡模式, 打卡模式下只能切换年月, 不能选择日期defaultSelectedDate: this.clockDate, // 打卡的日期是一个字符串数组clockSuccessText: '✔', // 已打卡展示的unClockText: '✖', // 未打卡展示的
})
3、打卡记录

4、编写学习打卡接口方法
import http from '../request/Request'
import { LearnClockParam, PageParam, UserLearnClockData } from './LearnClockApi.type'
import { PageVo } from './MessageApi.type'/*** 消息接口*/
class LearnClockApi {/*** 学习打卡*/learnClock = (data: LearnClockParam) => {return http.post('/v1/learn/clock', data)}/*** 查询用户已打卡的日期*/listClockTime = (): Promise<Array<string>> => {return http.get('/v1/learn/listClockTime')}/*** 查询用户今日是否打卡*/isClock = (): Promise<boolean> => {return http.get('/v1/learn/isClock')}/*** 分页查询用户打卡记录*/pageListUserClock = (data: PageParam): Promise<PageVo<UserLearnClockData>> => {return http.get('/v1/learn/page?page=' + data.page + '&&pageSize=' + data.pageSize)}
}const learnClockApi = new LearnClockApi();export default learnClockApi as LearnClockApi;
/*** 学习打卡入参*/
export interface LearnClockParam {/*** 打卡地点*/location: string/*** 打卡内容*/content: string
}/*** 时间*/
export interface BaseTime {/*** 创建时间*/createTime?: Date/*** 更新时间*/updateTime?: Date
}/*** 分页参数*/
export interface PageParam {/*** 当前页*/page?: number/*** 每一页展示的数据条数*/pageSize?: number
}/*** 分页响应参数*/
export interface PageVo<T> {current: number,size: number,total: number,records: Array<T>
}/*** 用户打卡记录数据*/
export interface UserLearnClockData extends BaseTime {/*** 学习打卡id*/id: number/*** 打卡地点*/location: string/*** 打卡内容*/content: string/*** 用户昵称*/nickname: string/*** 创建时间字符串格式*/time: string}
学习目标

1、目标整体进度
使用的是鸿蒙进度条组件
// 环形进度条
Stack() {Progress({value: this.countData.completeQuantity,total: this.countData.totalQuantity,type: ProgressType.Ring}).width($r('app.float.common_width_medium')).height($r('app.float.common_height_medium')).color('#1698CE').style({ strokeWidth: 8 })Text(this.countData.completeQuantity + '/' + this.countData.totalQuantity).fontSize($r('app.float.common_font_size_tiny'))
}
2、添加目标
使用的是ibest-ui里面的IBestDialog组件
IBestDialog({visible: $dialogVisible,title: "添加目标",showCancelButton: true,defaultBuilder: (): void => this.formInputContain(),beforeClose: async (action) => {if (action === 'cancel') {return true}const valueLength = this.inputTargetValue.trim().length;this.formInputError = !valueLength;if (!this.formInputError) {// 添加新目标await targetInfoApi.addTargetInfo({ content: this.inputTargetValue })showToast('添加目标成功')// 查询数据this.page = 1this.aboutToAppear()return true}return !this.formInputError}
})
@BuilderformInputContain() {Column() {TextInput({ 'placeholder': '请输入目标内容,长度不能超过255字符' }).fontSize(14).placeholderFont({ size: 14 }).onChange((value) => {this.inputTargetValue = value;this.formInputError = false})if (this.formInputError) {Text('目标内容不能为空').width(CommonConstant.WIDTH_FULL).textAlign(TextAlign.Start).margin({top: 5,left: 5}).fontColor(Color.Red).fontSize($r('app.float.common_font_size_small')).transition({ type: TransitionType.Insert, opacity: 1 }).transition({ type: TransitionType.Delete, opacity: 0 })}}.width('90%').margin({ top: 15, bottom: 15 })}
3、完成、删除目标
左滑目标即可看到完成和删除按钮
使用的是ListItem.swipeAction方法
核心代码如下
@BuilderitemEnd(item: TargetInfoVo) {Row() {// 构建尾端滑出组件Button({ type: ButtonType.Circle }) {Image($r('app.media.icon_finish')).width(40).aspectRatio(1)}.onClick(async () => {// 完成未完成的目标if (item.status === '1') {showToast('当前目标已完成,无需重复点击')return}// 完成目标await targetInfoApi.completeTargetInfo({ id: item.id })showToast('目标已完成')router.replaceUrl({ url: RouterConstant.VIEWS_LEARN_TARGET })}).margin({ right: 10 })// 构建尾端滑出组件Button({ type: ButtonType.Circle }) {Image($r('app.media.icon_delete')).width(40).aspectRatio(1)}.margin({ right: 10 }).onClick(async () => {IBestDialogUtil.open({title: "提示",message: "是否确认删除当前目标?",showCancelButton: true,onConfirm: async () => {// 删除目标await targetInfoApi.deleteTargetInfo({ id: item.id })showToast('删除目标成功')router.replaceUrl({ url: RouterConstant.VIEWS_LEARN_TARGET })}})})}.justifyContent(FlexAlign.SpaceBetween)}
4、编写学习目标接口方法
import http from '../request/Request'
import { PageParam, PageVo, TargetInfoAddParam,TargetInfoCompleteParam,TargetInfoCountVo,TargetInfoDeleteParam,TargetInfoEditParam,TargetInfoVo } from './TargetInfoApi.type'/*** 目标内容接口*/
class TargetInfoApi {/*** 获取用户整体目标完成进度统计*/getTargetInfoCount = (): Promise<TargetInfoCountVo> => {return http.get('/v1/target/count')}/*** 分页查询用户整体目标*/pageListTargetInfo = (data: PageParam): Promise<PageVo<TargetInfoVo>> => {return http.get('/v1/target/page?page=' + data.page + '&&pageSize=' + data.pageSize)}/*** 新增目标*/addTargetInfo = (data: TargetInfoAddParam) => {return http.post('/v1/target/add', data)}/*** 修改目标*/editTargetInfo = (data: TargetInfoEditParam) => {return http.post('/v1/target/edit', data)}/*** 完成目标*/completeTargetInfo = (data: TargetInfoCompleteParam) => {return http.post('/v1/target/complete', data)}/*** 删除目标*/deleteTargetInfo = (data: TargetInfoDeleteParam) => {return http.post('/v1/target/delete', data)}}const targetInfoApi = new TargetInfoApi();export default targetInfoApi as TargetInfoApi;
/*** 用户整体目标完成进度统计*/
export interface TargetInfoCountVo {/*** 总目标数量*/totalQuantity: number/*** 完成目标的数量*/completeQuantity: number/*** 更新时间*/updateTime: string
}/*** 新增目标*/
export interface TargetInfoAddParam {/*** 目标内容*/content: string}/*** 修改目标*/
export interface TargetInfoEditParam {/*** 目标内容*/content: string/*** 目标内容id*/id: number}/*** 完成目标*/
export interface TargetInfoCompleteParam {/*** 目标内容id*/id: number}/*** 删除目标*/
export interface TargetInfoDeleteParam {/*** 目标内容id*/id: number}/*** 用户目标内容详情*/
export interface TargetInfoVo extends BaseTime {/*** 目标内容id*/id: number/*** 目标内容*/content: string/*** 目标状态:0未完成 1完成*/status: string/*** 创建时间字符串格式*/time: string
}/*** 时间*/
export interface BaseTime {/*** 创建时间*/createTime?: Date/*** 更新时间*/updateTime?: Date
}/*** 分页参数*/
export interface PageParam {/*** 当前页*/page?: number/*** 每一页展示的数据条数*/pageSize?: number
}/*** 分页响应参数*/
export interface PageVo<T> {current: number,size: number,total: number,records: Array<T>
}
学习平台和面试平台
学习平台和面试平台跟首页差不多雷同,所以在这里就不说了
相关文章:
鸿蒙NEXT项目实战-百得知识库05
代码仓地址,大家记得点个star IbestKnowTeach: 百得知识库基于鸿蒙NEXT稳定版实现的一款企业级开发项目案例。 本案例涉及到多个鸿蒙相关技术知识点: 1、布局 2、配置文件 3、组件的封装和使用 4、路由的使用 5、请求响应拦截器的封装 6、位置服务 7、三…...
记录一次,rabbitmq开启stomp插件之后,还是连不上15674端口的问题
原因是装在docker 里面的rabbitmq 没有映射15674端口,需重新删除容器之后重新运行 docker run -d --name rabbitmq -p 5672:5672 -p 15672:15672 -p 15674:15674 -p 1883:1883 -p 15675:15675 rabbitmq:版本号 进入docker容器开启插件 docker exec -it rabbitm…...
黑马node.js教程(nodejs教程)——AJAX-Day01-04.案例_地区查询——查询某个省某个城市所有地区(代码示例)
文章目录 代码示例效果 代码示例 axiosTest.html <!DOCTYPE html> <!-- 文档类型声明,告诉浏览器这是一个HTML5文档 --> <html lang"en"> <!-- HTML根元素,设置文档语言为英语 --><head> <!-- 头部区域&am…...
vue 自制列表,循环滚动
需求人员表示,超过高度的表格内容需要滚动展示,所以效果图如下: 自定义列表样式,主要是通过flex布局,控制 类th 与 类td 的宽度保持一致,标签结构还是参考了table的结构,由thead与tbody包裹tr再…...
【QA】模板方法模式在Qt中有哪些应用?
在 Qt 框架中,模板方法模式(Template Method Pattern)被广泛应用于框架的设计中,通过定义算法骨架并允许子类在不改变结构的情况下重写部分步骤。以下是 Qt 中典型的应用场景及示例: 1. 事件处理(Event Ha…...
图论——kruskal算法
53. 寻宝(第七期模拟笔试) 题目描述 在世界的某个区域,有一些分散的神秘岛屿,每个岛屿上都有一种珍稀的资源或者宝藏。国王打算在这些岛屿上建公路,方便运输。 不同岛屿之间,路途距离不同,国王希望你可以规划建公路的方案,如何可以以最短的总公路距离将 所有岛屿联通…...
Windows主机、虚拟机Ubuntu、开发板,三者之间文件互传
以下内容源于日常学习的整理,欢迎交流。 下图是Windows主机、虚拟机Ubuntu、开发者三者之间文件互传的方式示意图: 注意,下面谈及的所有方式,都要求两者的IP地址处于同一网段,涉及到的软件资源见felm。 一、Windows主…...
Flutter Dart 泛型详解
引言 在 Flutter 开发中,Dart 语言的泛型是一项强大且实用的特性。泛型允许我们在定义类、方法或接口时使用类型参数,这样可以编写更加灵活、可复用且类型安全的代码。下面将详细介绍 Dart 泛型的各个方面,并结合代码示例进行说明。 1. 泛型…...
Windows Docker 报错: has no HTTPS proxy,换源
pull python 3.7报错: 尝试拉取Docker 测试库hello world也失败 尝试使用临时镜像源,可以成功拉取: sudo docker pull docker.m.daocloud.io/hello-world说明确实是网络问题,需要配置镜像源,为了方便,在d…...
Java:Arrays类:操作数组的工具类
文章目录 Arrays类常见方法SetAll(); 代码排序如果数组中存储的是自定义对象 Arrays类 常见方法 SetAll(); 注意: 不能用新的数组接是因为修改的是原数组,所以完了要输出原数组发现会产生变化参数是数组下标变成灰色是因为还能简化(Lambda…...
【面试场景题-Redis中String类型和map类型的区别】
今天在面试中碰到一个场景题:在 Redis 中存储 100 万用户数据时,使用 String 类型和 Hash(Map)类型的主要区别是什么?体现在以下几个方面: 1. 存储结构与内存占用 String 类型 存储方式:每个用…...
List附加对象
List里面的某个对象需要修改,赋值 可以使用ALL或者ForEach,All的话,不能直接使用赋值对象只能赋值对象的某个字段 static void Main(string[] args){List<UserData> UserDatas new List<UserData>{new UserData { Id 1, Name …...
VLLM专题(三十六)—自动前缀缓存
PagedAttention 的核心思想是将每个请求的 KV 缓存划分为 KV 块。每个块包含固定数量的标记(tokens)对应的注意力键(keys)和值(values)。PagedAttention 算法允许将这些块存储在非连续的物理内存中,从而通过按需分配内存来消除内存碎片。 为了自动缓存 KV 缓存,我们利…...
相机光学(四十七)——相纸材质
1. 光面相纸 光面相纸表面光滑,亮度高,反光性好,能够呈现出清晰、鲜艳的图像效果,适合用于表现色彩艳丽、反差要求较高的题材,如产品照、艺术照和风景照。然而,这种相纸容易沾上指纹和灰尘。 2. 绒面相纸…...
数据表100多字段如何写mapper文件的xml
编写一个包含100多个字段的插入语句通常涉及到使用<mapper>标签来定义映射规则,特别是在使用MyBatis这样的持久层框架时。 1. 定义<mapper>命名空间 order表 <mapper namespace"com.example.mapper.orderMapper"><!-- 插入语句 --…...
只是“更轻更薄”?不!遨游三防平板还选择“更强更韧”
当消费电子领域普遍追求“更轻更薄”的设计美学时,遨游三防平板不止于此,还选择了另一条道路——“更强更韧”。在智能制造的复杂场景中,三防平板需直面高温、油污、撞击与极端气候的考验。普通消费级平板因防护性能不足,常因环境…...
拉取镜像太慢?一文解决!
# 拉取 Docker 镜像太慢?一文解决!🚀在国内使用 Docker 拉取镜像时,可能会遇到速度慢甚至失败的情况。别担心!本文带你快速优化 Docker 拉取方法!🔥01 | 确保 Docker Hub 登录认证 🔐…...
基于RAGFlow本地部署DeepSeek-R1大模型与知识库:从配置到应用的全流程解析
作者:后端小肥肠 🍊 有疑问可私信或评论区联系我。 🥑 创作不易未经允许严禁转载。 姊妹篇: DeepSpeek服务器繁忙?这几种替代方案帮你流畅使用!(附本地部署教程)-CSDN博客 10分钟上手…...
(分块)洛谷 P2801 教主的魔法 题解
之前学过 莫队 算法,其运用了分块思想;但是我居然是第一次写纯种的分块题目。 题意 给你一个长度为 n n n 的序列 a a a(一开始 ∀ a i ∈ [ 1 , 1000 ] \forall a_i\in[1,1000] ∀ai∈[1,1000])。要求执行 q q q 次操作&…...
[蓝桥杯 2023 省 B] 飞机降落(不会dfs的看过来)
[蓝桥杯 2023 省 B] 飞机降落 题目描述 N N N 架飞机准备降落到某个只有一条跑道的机场。其中第 i i i 架飞机在 T i T_{i} Ti 时刻到达机场上空,到达时它的剩余油料还可以继续盘旋 D i D_{i} Di 个单位时间,即它最早可以于 T i T_{i} Ti 时刻…...
信创系统极速文件查找:locate 命令详解
原文链接:信创系统极速文件查找:locate 命令详解 Hello,大家好啊!今天给大家带来一篇信创终端操作系统上 locate 命令详解的文章。在 Linux 及信创终端操作系统(如 统信 UOS、麒麟 KOS)中,查找…...
C# | 超简单CSV表格读写操作(轻松将数据保存到CSV,并支持读取还原)
C# | 超简单CSV表格读写操作(轻松将数据保存到CSV,并支持读取还原) 文章目录 C# | 超简单CSV表格读写操作(轻松将数据保存到CSV,并支持读取还原)一、上位机开发中的CSV应用背景二、CSV读写实战教学1. 基本对…...
PostgreSQL:语言基础与数据库操作
🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,精通Java编…...
RK3568 Android11 sh366006驱动
sh366006.c /* 谁愿压抑心中怒愤冲动咒骂这虚与伪与假从没信要屈膝面对生命纵没有别人帮一生只靠我双手让我放声疯狂叫囔今天的他 呼风可改雨不可一世太嚣张 --《不可一世》Beyond */ #include <linux/module.h> #include <linux/init.h> #include <linux/fs.h…...
蓝桥杯学习——二叉树+奇点杯题目解析
基础认知 一、二叉树种类: 1.满二叉树。记深度k,节点数量2^k-1。 2.完全二叉树:除了底层,其余全满,底部从左到右连续。 3,平衡二叉搜索树:左子树和右子树高度差不大于1。 二、存储方式&…...
基于django+vue的购物商城系统
开发语言:Python框架:djangoPython版本:python3.8数据库:mysql 5.7数据库工具:Navicat11开发软件:PyCharm 系统展示 系统首页 热卖商品 优惠资讯 个人中心 后台登录 管理员功能界面 用户管理 商品分类管理…...
AI安全、大模型安全研究(DeepSeek)
DeepSeek 点燃AI应用革命之火,但安全 “灰犀牛” 正在逼近 DeepSeek-R1国产大模型的发布,以技术创新惊艳了全球,更是极致的性价比推动国内千行百业接入 AI,政府、企业竞速开发智能业务处理、智能客服、代码生成、营销文案等应用,“落地效率” 成为第一关键词。然而与此相…...
卷积神经网络 - 汇聚层
卷积神经网络一般由卷积层、汇聚层和全连接层构成,本文我们来学习汇聚层。 汇聚层(Pooling Layer)也叫子采样层(Subsampling Layer),其作用是进 行特征选择,降低特征数量,从而减少参数数量。 卷积层虽然可以显著减少网络中连接的…...
蓝桥杯备赛-贪心-管道
问题描述 有一根长度为 lenlen 的横向的管道,该管道按照单位长度分为 lenlen 段,每一段的中央有一个可开关的阀门和一个检测水流的传感器。 一开始管道是空的,位于 LiLi 的阀门会在 SiSi 时刻打开,并不断让水流入管道。 对…...
论文分享:PL-ALF框架实现无人机低纹理环境自主飞行
在室内仓库、地下隧道等低纹理复杂场景中,无人机依赖视觉传感器进行自主飞行时,往往会遇到定位精度低、路径规划不稳定等难题。针对这一问题,重庆邮电大学计算机学院雷大江教授团队在IEEE Trans期刊上提出了一种新型自主飞行框架:…...
