OpenHarmony实现一次开发多端部署分布式新闻客户端页面

分布式新闻客户端(ArkTS)

介绍

本篇Codelab基于栅格布局、设备管理和多端协同,实现一次开发,多端部署的分布式新闻客户端页面。主要包含以下功能:

  1. 展示新闻列表以及左右滑动切换新闻Tab。
  2. 点击新闻展示新闻详情页。
  3. 点击新闻详情页底部的分享按钮,发现周边处在同一无线网络下的设备并进行可信认证连接。
  4. 可信认证后,再次点击分享按钮,选择已连接的设备进行跨设备启动UIAbility。

最终效果图如下:

相关概念

  • 栅格布局:一种通用的辅助定位工具,解决多尺寸多设备的动态布局问题。
  • 设备管理:模块提供分布式设备管理能力。
  • 跨设备启动UIAbility:多端上的不同UIAbility/ServiceExtensionAbility同时运行、或者交替运行实现完整的业务。
  • Tabs组件:通过页签进行内容视图切换的容器组件,每个页签对应一个内容视图。

相关权限

本篇Codelab使用了设备管理及跨设备实现多端协同能力,需要手动替换full-SDK,并在配置文件module.json5文件requestPermissions属性中添加如下权限:

  • 分布式设备认证组网权限:ohos.permission.ACCESS_SERVICE_DM。
  • 设备间的数据交换权限:ohos.permission.DISTRIBUTED_DATASYNC。

约束与限制

  1. 本篇Codelab部分能力依赖于系统API,需下载full-SDK并替换DevEco Studio自动下载的public-SDK。具体操作可参考指南《如何替换full-SDK》。
  2. 本篇Codelab使用的部分API仅系统应用可用,需要提升应用等级。具体可参考指南《访问控制授权申请指导》。

环境搭建

软件要求

  • DevEco Studio版本:DevEco Studio 4.0 Beta2。
  • OpenHarmony SDK版本:API version 10。

硬件要求

  • 开发板类型:润和RK3568开发板。
  • OpenHarmony系统:4.0 Beta1。

环境搭建

完成本篇Codelab我们首先要完成开发环境的搭建,本示例以RK3568开发板为例,参照以下步骤进行:

  1. 获取OpenHarmony系统版本:标准系统解决方案(二进制)。以4.0 Beta1版本为例:

  2. 搭建烧录环境。
    1. 完成DevEco Device Tool的安装
    2. 完成RK3568开发板的烧录
  3. 搭建开发环境。
    1. 开始前请参考工具准备,完成DevEco Studio的安装和开发环境配置。
    2. 开发环境配置完成后,请参考使用工程向导创建工程(模板选择“Empty Ability”)。
    3. 工程创建完成后,选择使用真机进行调测。

代码结构解读

本篇Codelab只对核心代码进行讲解。

├──entry/src/main/ets                   // 代码区
│  ├──common
│  │  ├──constants
│  │  │  └──CommonConstants.ets         // 常量类
│  │  └──utils
│  │     └──Logger.ets                  // 日志工具类
│  ├──entryability
│  │  └──EntryAbility.ets               // 程序入口类
│  ├──model
│  │  └──RemoteDeviceModel.ets          // 设备管理类
│  ├──pages
│  │  ├──Index.ets                      // 新闻列表页
│  │  └──NewsDetail.ets                 // 新闻详情页
│  ├──view
│  │  ├──DetailFooter.ets               // 详情页页脚
│  │  ├──DetailHeadContent.ets          // 新闻详情
│  │  ├──DeviceListDialog.ets           // 设备列表弹窗
│  │  ├──NewsList.ets                   // 新闻列表
│  │  └──NewsTab.ets                    // 新闻页签
│  └──viewmodel
│     └──NewsDataModel.ets              // 新闻数据处理
└──entry/src/main/resources             // 资源文件目录

构建新闻列表页

新闻列表页由页签区域和新闻列表区域组成,页签区域为自定义布局TabBuilder,新闻列表区域为Tabs组件嵌套List组件,并适配不同尺寸设备对应的栅格。新闻列表页能够左右滑动或点击页签切换新闻Tab,并设置点击新闻跳转至新闻详情页。

// NewsTab.ets
@Component
export default struct NewsTab {@State currentIndex: number = 0;@State currentBreakpoint: string = CommonConstants.BREAKPOINT_SM;private newsItems: NewsData[] = [];// 自定义页签栏@Builder TabBuilder(title: Resource, index: number) {Row() {Text(title).fontSize(this.currentIndex === index ? $r('app.float.lager_font_size') : $r('app.float.middle_font_size')).fontWeight(this.currentIndex === index ? CommonConstants.FONT_WEIGHT_500 : FontWeight.Normal).fontColor(this.currentIndex === index ? $r('app.color.tab_font_select') : $r('app.color.font_color_gray'))}.layoutWeight(1).margin({right: $r('app.float.news_tab_margin_right'),left: (this.currentBreakpoint === CommonConstants.BREAKPOINT_SM && index === 0) ?$r('app.float.news_tab_margin_left') : 0}).height(this.currentIndex === index ? $r('app.float.news_tab_current_height') : $r('app.float.news_tab_height'))}build() {...Tabs() {ForEach(CommonConstants.ALL_TITLE, (title: string, index: number) => {TabContent() {// 新闻内容列表NewsList({ newsItems: NewsDataModel.getNewsByType(this.newsItems, title) })}.tabBar(this.TabBuilder(NewsDataModel.getTypeByStr(title), index))}, (title: string, index: number) => index + JSON.stringify(title))}.barHeight($r('app.float.news_tab_bar_height')).barWidth(CommonConstants.FULL_COMPONENT).barMode(this.currentBreakpoint === CommonConstants.BREAKPOINT_SM ? BarMode.Scrollable : BarMode.Fixed).onChange((index: number) => {this.currentIndex = index;})...}
}// NewsList.ets
@Component
export default struct NewsList {private newsItems: NewsData[] = [];build() {List() {ForEach(this.newsItems, (item: NewsData, index: number) => {ListItem() {// 栅格布局GridRow({columns: {sm: CommonConstants.FOUR_COLUMN,md: CommonConstants.EIGHT_COLUMN,lg: CommonConstants.TWELVE_COLUMN},breakpoints: {value: [CommonConstants.SMALL_DEVICE_TYPE,CommonConstants.MIDDLE_DEVICE_TYPE,CommonConstants.LARGE_DEVICE_TYPE]},gutter: { x: $r('app.float.grid_row_gutter') }}) {GridCol({span: {sm: CommonConstants.FOUR_COLUMN,md: CommonConstants.EIGHT_COLUMN,lg: CommonConstants.EIGHT_COLUMN},offset: {sm: CommonConstants.ZERO_COLUMN,md: CommonConstants.ZERO_COLUMN,lg: CommonConstants.TWO_COLUMN}}) {NewsItem({ newsItem: item, isLast: index === this.newsItems.length - 1 })}}}}, (item: NewsData, index: number) => index + JSON.stringify(item))}.height(CommonConstants.FULL_COMPONENT)}
}

构建新闻详情页

新闻详情页

新闻详情页由新闻内容区域和页脚区域组成,其中新闻内容区域为Scroll组件嵌套栅格组件展示新闻详情,页脚区域为栅格布局,包含TextInput组件和三个按钮图标。

// DetailHeadContent.ets
build() {Column() {...// 可滚动的容器组件Scroll() {// 栅格布局GridRow({columns: {sm: CommonConstants.FOUR_COLUMN,md: CommonConstants.EIGHT_COLUMN,lg: CommonConstants.TWELVE_COLUMN},breakpoints: {value: [CommonConstants.SMALL_DEVICE_TYPE,CommonConstants.MIDDLE_DEVICE_TYPE,CommonConstants.LARGE_DEVICE_TYPE]},gutter: { x: $r('app.float.grid_row_gutter') }}) {GridCol({span: {sm: CommonConstants.FOUR_COLUMN,md: CommonConstants.EIGHT_COLUMN,lg: CommonConstants.EIGHT_COLUMN},offset: {sm: CommonConstants.ZERO_COLUMN,md: CommonConstants.ZERO_COLUMN,lg: CommonConstants.TWO_COLUMN}}) {...}...}}.padding({bottom: $r('app.float.news_detail_padding_bottom')}).scrollBar(BarState.Off)}.margin({left: $r('app.float.news_detail_margin'),right: $r('app.float.news_detail_margin')}).height(CommonConstants.FULL_COMPONENT).alignItems(HorizontalAlign.Start)
}// DetailFooter.ets
build() {Column() {// 分割线Divider().color($r('app.color.detail_divider_color')).width(CommonConstants.FULL_COMPONENT)// 栅格布局GridRow({columns: {sm: CommonConstants.FOUR_COLUMN,md: CommonConstants.EIGHT_COLUMN,lg: CommonConstants.TWELVE_COLUMN},breakpoints: {value: [CommonConstants.SMALL_DEVICE_TYPE,CommonConstants.MIDDLE_DEVICE_TYPE,CommonConstants.LARGE_DEVICE_TYPE]},gutter: { x: $r('app.float.grid_row_gutter') }}) {GridCol({span: {sm: CommonConstants.FOUR_COLUMN,md: CommonConstants.EIGHT_COLUMN,lg: CommonConstants.EIGHT_COLUMN},offset: {sm: CommonConstants.ZERO_COLUMN,md: CommonConstants.ZERO_COLUMN,lg: CommonConstants.TWO_COLUMN}}) {...}.margin({left: this.currentBreakpoint === CommonConstants.BREAKPOINT_SM ? $r('app.float.footer_margin_sm') :$r('app.float.footer_margin_other'),right: this.currentBreakpoint === CommonConstants.BREAKPOINT_SM ? $r('app.float.footer_margin_sm') :$r('app.float.footer_margin_other')})}.backgroundColor($r('app.color.bg_color_gray')).height($r('app.float.footer_height')).width(CommonConstants.FULL_COMPONENT).onBreakpointChange((breakpoints) => {...})}
}

分享按钮弹窗

页脚点击分享按钮,弹出自定义弹窗DeviceListDialog,用于多端协同拉起应用。DeviceListDialog由两个标题栏和两个List组件构成,其中List组件使用ForEach循环渲染设备数据。

// DeviceListDialog.ets
build() {Column() {Row() {...}.height($r('app.float.choose_device_row_height')).width(CommonConstants.FULL_COMPONENT).padding({left: $r('app.float.dialog_padding'),right: $r('app.float.dialog_padding')})// 信任设备列表List() {ForEach(this.trustedDeviceList, (item: deviceManager.DeviceInfo, index: number) => {ListItem() {...}}, (item: deviceManager.DeviceInfo) => JSON.stringify(item.deviceId))}Row() {...}.height($r('app.float.choose_device_row_height')).width(CommonConstants.FULL_COMPONENT).padding({left: $r('app.float.dialog_padding'),right: $r('app.float.dialog_padding')})// 发现设备列表List() {ForEach(this.discoverDeviceList, (item: deviceManager.DeviceInfo, index: number) => {ListItem() {...}}, (item: deviceManager.DeviceInfo) => JSON.stringify(item.deviceId))}Row() {...}.height($r('app.float.dialog_button_row_height')).padding({top: $r('app.float.dialog_button_padding_top'),bottom: $r('app.float.dialog_button_padding_bottom'),left: $r('app.float.dialog_padding'),right: $r('app.float.dialog_padding')}).width(CommonConstants.FULL_COMPONENT)}.borderRadius($r('app.float.dialog_border_radius')).backgroundColor($r('app.color.device_dialog_background')).width(CommonConstants.FULL_COMPONENT)
}

多端协同拉起应用

创建设备管理器

应用创建时创建一个设备管理器实例,注册设备状态监听和获取信任的设备列表。其中deviceManager类需使用full-SDK。

// EntryAbility.ets
onCreate(want: Want) {...// 创建设备管理器RemoteDeviceModel.createDeviceManager(this.context);
}// RemoteDeviceModel.ets
async createDeviceManager(context: common.UIAbilityContext): Promise<void> {if (this.deviceManager !== undefined) {return;}await new Promise((resolve: (value: Object | PromiseLike<Object>) => void, reject:((reason?: RejectError) => void)) => {deviceManager.createDeviceManager(context.abilityInfo.bundleName, (err, value) => {if (err) {reject(err);logger.error('createDeviceManager failed.');return;}this.deviceManager = value;// 注册设备状态监听this.registerDeviceStateListener();// 获取信任设备列表this.getTrustedDeviceList();resolve(value);})})
}

发现设备

用户点击新闻详情页底部的分享按钮,调用startDeviceDiscovery()方法,发现周边处在同一无线网络下的设备并添加设备至已发现的设备列表。

// RemoteDeviceModel.ets
startDeviceDiscovery(): void {if (this.deviceManager === undefined) {logger.error('deviceManager has not initialized');this.showToast($r('app.string.no_device_manager'));return;}this.deviceManager.on('deviceFound', (data) => {if (data === null) {return;}// 监听设备发现this.deviceFound(data);})this.deviceManager.on('discoverFail', (data) => {logger.error(`discoverFail data = ${JSON.stringify(data)}`);})this.deviceManager.on('serviceDie', () => {logger.error('serviceDie');})let info: deviceManager.SubscribeInfo = {subscribeId: SUBSCRIBE_ID,mode: CommonConstants.INFO_MODE,medium: 0,freq: CommonConstants.INFO_FREQ,isSameAccount: false,isWakeRemote: true,capability: 0};// 添加设备至发现列表this.discoverList = [];AppStorage.setOrCreate(CommonConstants.DISCOVER_DEVICE_LIST, this.discoverList);try {this.deviceManager.startDeviceDiscovery(info);} catch (err) {logger.error(`startDeviceDiscovery failed error = ${JSON.stringify(err)}`);}
}

进行可信认证连接

在已发现的设备列表中选择设备,调用authenticateDevice()方法进行可信认证,输入PIN码,连接设备,将设备改为信任状态,添加至已信任设备列表。

// RemoteDeviceModel.ets
authenticateDevice(device: deviceManager.DeviceInfo, context: common.UIAbilityContext): void {if (this.deviceManager === undefined) {logger.error('deviceManager has not initialized');this.showToast($r('app.string.no_device_manager'));return;}for (let i: number = 0; i < this.discoverList.length; i++) {if (this.discoverList[i].deviceId !== device.deviceId) {continue;}let extraInfo: AuthExtraInfoInterface = {targetPkgName: context.abilityInfo.bundleName,appName: context.applicationInfo.name,appDescription: context.applicationInfo.description,business: CommonConstants.ZERO};let authParam: deviceManager.AuthParam = {'authType': CommonConstants.ONE,'extraInfo': extraInfo};try {// 可信认证this.deviceManager.authenticateDevice(device, authParam, (err) => {if (err) {logger.error(`authenticateDevice error. Code is ${err.code}, message is ${err.message}`);return;}})} catch (err) {logger.error(`authenticateDevice failed error = ${JSON.stringify(err)}`);}}
}

跨设备启动UIAbility

可信认证后,用户再次点击分享按钮,选择已信任设备列表中的设备,调用startAbilityContinuation()方法进行拉起应用,在另一设备中触发aboutToAppear()方法渲染当前的新闻详情页,实现跨设备启动UIAbility。

// DeviceListDialog.ets
function startAbilityContinuation(deviceId: string, newsId: string, context: common.UIAbilityContext): void {let want: Want = {deviceId: deviceId,bundleName: context.abilityInfo.bundleName,abilityName: CommonConstants.ABILITY_NAME,parameters: {newsId: newsId}};// 拉起应用context.startAbility(want).catch((err: Error) => {Logger.error(`startAbilityContinuation failed error = ${JSON.stringify(err)}`);prompt.showToast({message: $r('app.string.start_ability_continuation_error')});})
}// NewsDetail.ets
aboutToAppear() {let newsId: string | undefined = AppStorage.get<string>('wantNewsId');if (newsId === undefined) {this.newsData = (router.getParams() as Record<string, NewsData>)['newsItem'];return;}// 读取跨设备传递的参数信息this.newsData = this.newsItems.filter((item: NewsData) => (item.newsId === newsId))[0];
}

总结

您已经完成了本次Codelab的学习,并了解到以下知识点:

  1. 构建分布式新闻客户端页面。
  2. 实现应用的一次开发,多端部署。
  3. 使用跨设备启动UIAbility拉起应用。

为了帮助大家更深入有效的学习到鸿蒙开发知识点,小编特意给大家准备了一份全套最新版的HarmonyOS NEXT学习资源,获取完整版方式请点击→HarmonyOS教学视频

HarmonyOS教学视频

鸿蒙语法ArkTS、TypeScript、ArkUI等…视频教程

鸿蒙生态应用开发白皮书V2.0PDF:

获取完整版白皮书方式请点击→《鸿蒙生态应用开发白皮书V2.0PDF

在这里插入图片描述

鸿蒙 (Harmony OS)开发学习手册

一、入门必看

  1. 应用开发导读(ArkTS)
  2. .……

在这里插入图片描述


二、HarmonyOS 概念

  1. 系统定义
  2. 技术架构
  3. 技术特性
  4. 系统安全

在这里插入图片描述

三、如何快速入门?《鸿蒙基础入门学习指南》

  1. 基本概念
  2. 构建第一个ArkTS应用
  3. .……

在这里插入图片描述


四、开发基础知识

  1. 应用基础知识
  2. 配置文件
  3. 应用数据管理
  4. 应用安全管理
  5. 应用隐私保护
  6. 三方应用调用管控机制
  7. 资源分类与访问
  8. 学习ArkTS语言
  9. .……

在这里插入图片描述


五、基于ArkTS 开发

  1. Ability开发
  2. UI开发
  3. 公共事件与通知
  4. 窗口管理
  5. 媒体
  6. 安全
  7. 7.网络与链接
  8. 电话服务
  9. 数据管理
  10. 后台任务(Background Task)管理
  11. 设备管理
  12. 设备使用信息统计
  13. DFX
  14. 国际化开发
  15. 折叠屏系列
  16. .……

在这里插入图片描述


更多了解更多鸿蒙开发的相关知识可以参考:《鸿蒙 (Harmony OS)开发学习手册

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/764235.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

opencv自定义间隔帧获取视频转存为图片的GUI界面实现

该程序功能只将mp4转为jpg 希望得到您的指导 非常感谢您观看我的博客&#xff0c;我的博客是为了记录我的学习过程同时保留我的某些可重复利用代码以方便下次使用。如果您对我的博客有任何建议还请您不吝指出&#xff0c;非常感谢您对我的指导。 背景 在实现opencv逐帧获取…

深度学习中的随机种子random_seed

解释 由于模型中的参数初始化例如权重参数如下图&#xff0c;就是随机初始化的&#xff0c;为了能够更好的得到论文中提到效果&#xff0c;可以设置随机种子&#xff0c;从而减少算法结果的随机性&#xff0c;使其接近于原始结果。 设置了随机种子&#xff0c;产生的随机数都…

基于Java中的SSM框架实现考研指导平台系统项目【项目源码+论文说明】计算机毕业设计

基于Java中的SSM框架实现考研指导平台系统演示 摘要 应对考研的学生&#xff0c;为了更好的使校园考研有一个更好的环境好好的学习&#xff0c;建议一个好的校园网站&#xff0c;是非常有必要的。提供学生的学习提供一个交流的空间。帮助同学们在学习高数、学习设计、学习统计…

基于python+vue的ITS 信息平台的设计与实现flask-django-nodejs-php

伴随着我国社会的发展&#xff0c;人民生活质量日益提高。于是对系统进行规范而严格是十分有必要的&#xff0c;所以许许多多的信息管理系统应运而生。此时单靠人力应对这些事务就显得有些力不从心了。所以本论文将设计一套信息平台&#xff0c;帮助交通局进行信息共享、交通信…

【Spring框架】单元测试:JUnit

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

使用 Pytorch 和 Rasterio 的自定义地理空间数据加载器

地理空间数据在从遥感和城市规划到环境监测和灾害管理的各个领域发挥着至关重要的作用。在处理机器学习任务的地理空间数据时,准备自定义数据加载器对于有效加载、预处理和增强数据而不丢失其属性至关重要,特别是当输入图像具有超过 3 个波段时。 Rasterio确实是一个专门为有…

2核2G服务器阿里云多少钱一年?

阿里云2核2G服务器配置优惠价格61元一年和99元一年&#xff0c;61元是轻量应用服务器2核2G3M带宽、50G高效云盘&#xff1b;99元服务器是ECS云服务器经济型e实例ecs.e-c1m1.large&#xff0c;2核2G、3M固定带宽、40G ESSD entry系统盘&#xff0c;阿里云活动链接 aliyunfuwuqi.…

Gavin Wood 精彩演讲|安全灵活 JAM 链,打造去中心化多核计算机

Polkadot 年度开发者大会 sub0 Asia 近期在泰国曼谷正式落幕。面对区块链行业的激烈竞争&#xff0c;Polkadot 创始人 Gavin Wood 在演讲中说明将如何利用 Polkadot 2.0 与 JAM 链带来新的技术创新&#xff0c;推动生态持续发展。 Polkadot 将推一个名为 JAM 链的新网络。JAM …

单机模拟分布式MINIO(阿里云)

拉取的最新MINIO&#xff1a; minio version RELEASE.2024-03-15T01-07-19Z Runtime: go1.21.8 linux/amd64 分布式 MinIO 至少需要4个节点&#xff0c;也就意味着至少4个硬盘&#xff0c;对于囊中羞涩仅用来开发测试的人来说&#xff0c;这笔花销还是比较高昂。有没有更好的…

Day61:WEB攻防-PHP反序列化原生类TIPSCVE绕过漏洞属性类型特征

知识点&#xff1a; 1、PHP-反序列化-属性类型&显示特征 2、PHP-反序列化-CVE绕过&字符串逃逸 3、PHP-反序列化-原生类生成&利用&配合 补充&#xff1a;如果在 PHP 类中没有实现某个魔术方法&#xff0c;那么该魔术方法在相应的情况下不会被自动触发。PHP 的魔…

Oracle 11G备份集中控制文件和spfile被异常删除

坐标大理&#xff0c;苍山下&#xff0c;洱海旁&#xff0c;风花雪月&#xff01;&#xff01; 今日一大早就接到一个case&#xff0c;根据客户描述&#xff0c;大概意思是昨天晚上发现18号的ctl和spfile无故消失&#xff0c;备份策略是一周一个0级增量备份&#xff0c;每日进…

机器学习——线性回归(头歌实训)

头歌机器学习实训代码、答案&#xff0c;如果能够帮到您&#xff0c;希望可以点个赞&#xff01;&#xff01;&#xff01; 如果有问题可以csdn私聊或评论&#xff01;&#xff01;&#xff01;感谢您的支持 目录 第1关&#xff1a;简单线性回归与多元线性回归 第2关&#…

Vue3:网页项目中路由的设计和配置

为了避免我每次建项目配路由的时候都回去翻网课&#xff0c;打算整一博客 路由设计 不同网页的路由设计思路基本相同&#xff0c;分为一级路由和二级路由&#xff0c;基本设计思路如下图 以我之前做过的招新系统管理端为例&#xff0c;可设计出如下路由 路由配置 还是以招新系…

递归的个人总结

递归函数&#xff08;递去、回归&#xff09;是函数不断的调用自己&#xff1b; 可以按照如下来理解&#xff1a;func1中调用func2&#xff0c;func2中调用func3; func3函数返回了&#xff0c;继续执行func2中的语句&#xff1b;func2执行完了&#xff0c;继续执行func1之后的…

ky10.aarch64安装Jenkins

参考地址&#xff1a;《安装部署 Jenkins》 前言 有war包和rpm两种安装方式&#xff0c;如果是长期使用更加推荐rpm的安装方式&#xff0c;可以更好的管理Jenkins&#xff1b; 我此次安装jenkins主要用于测试和简单的个人使用&#xff0c;所以选择更轻便的war安装。 1 下载J…

每日一题 --- 209. 长度最小的子数组[力扣][Go]

长度最小子数组 题目&#xff1a; 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 连续 子数组 [numsl, numsl1, ..., numsr-1, numsr] &#xff0c;并返回其长度**。**如果不存在符合条件的子数组&#xff0c…

【docker】查看并拷贝容器内文件

一、查询容器 查询所有容器 docker ps查询名为os11的容器 docker ps | grep os11查询名为os11的容器&#xff08;包含不运行的&#xff09; docker ps -a| grep os11 docker ps [option] 显示结果介绍如下&#xff1a; 参考&#xff1a;[https://blog.51cto.com/u_15009374/31…

Linux离线部署gitLab及使用教程

一、下载gitLab的linux系统rpm包 地址&#xff1a;Index of /gitlab-ce/yum/el7/ | 清华大学开源软件镜像站 | Tsinghua Open Source Mirror 找到这个最新版 点击下载 二、上传到linux系统 笔者是在windows系统下的vmware虚拟机中部署安装的&#xff0c;虚拟机中安装了cent…

腾讯在GDC 2024展示GiiNEX AI游戏引擎现已投入《元梦之星》中开发使用,展示强大AIGC能力

在近日举行的GDC 2024游戏开发者大会上&#xff0c;腾讯揭开了其AI Lab团队精心打造的GiiNEX AI游戏引擎的神秘面纱。这款引擎依托先进的生成式AI和决策AI技术&#xff0c;为游戏行业带来了革命性的变革。 相关阅读&#xff1a;腾讯游戏出品&#xff01;腾讯研效AIGC&#xff…

【DataWhale学习】用免费GPU线上跑chatGLM、SD项目实践

用免费GPU线上跑chatGLM、SD项目实践 ​ DataWhale组织了一个线上白嫖GPU跑chatGLM与SD的项目活动&#xff0c;我很感兴趣就参加啦。之前就对chatGLM有所耳闻&#xff0c;是去年清华联合发布的开源大语言模型&#xff0c;可以用来打造个人知识库什么的&#xff0c;一直没有尝试…