当前位置: 首页 > news >正文

【鸿蒙HarmonyOS】一文详解华为的服务卡片

7.服务卡片

1.什么是卡片

Form Kit(卡片开发服务)提供一种界面展示形式,可以将应用的重要信息或操作前置到服务卡片(以下简称“卡片”),以达到服务直达、减少跳转层级的体验效果。卡片常用于嵌入到其他应用(当前被嵌入方即卡片使用方只支持系统应用,例如桌面)中作为其界面显示的一部分,并支持拉起页面、发送消息等基础的交互能力。

2.卡片的一些配置参数

entry/src/main/resources/base/profile/form_config.json

3. 卡片的生命周期

//卡片生命周期
import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit';
import { Want } from '@kit.AbilityKit';export default class EntryFormAbility extends FormExtensionAbility {// 	卡片被创建时触发onAddForm(want: Want) {// formBindingData:提供卡片数据绑定的能力,包括FormBindingData对象的创建、相关信息的描述// 获取卡片 IDconst formId = want.parameters && want.parameters['ohos.extra.param.key.form_identity'].toString()return formBindingData.createFormBindingData({title: '获取数据中~'});// Called to return a FormBindingData object.const formData = '';return formBindingData.createFormBindingData(formData);}// 卡片转换成常态卡片时触发onCastToNormalForm(formId: string) {// Called when the form provider is notified that a temporary form is successfully// converted to a normal form.}// 卡片被更新时触发(调用 updateForm 时)onUpdateForm(formId: string) {// Called to notify the form provider to update a specified form.}// 卡片发起特定事件时触发(message)onFormEvent(formId: string, message: string) {// Called when a specified message event defined by the form provider is triggered.}//卡片被卸载时触发onRemoveForm(formId: string) {// Called to notify the form provider that a specified form has been destroyed.}// 卡片状态发生改变时触发onAcquireFormState(want: Want) {// Called to return a {@link FormState} object.return formInfo.FormState.READY;}
}

4.卡片的通信

1.卡片之间通信

卡片在创建时,会触发onAddForm生命周期,此时返回数据可以直接传递给卡片

另外卡片在被卸载时,会触发onRemoveForm生命周期

1.卡片创建时传递数据

2.卡片向卡片的生命周期通信

卡片页面中可以通过postCardAction接口触发message事件拉起FormExtensionAbility中的onUpdateForm

onUpdateForm中通过updateForm来返回数据

const localStorage = new LocalStorage()
// 卡片组件通过LocalStorage来接收onAddForm中返回的数据
@Entry(localStorage)
@Component
struct WidgetCard {// 接收onAddForm中返回的卡片Id@LocalStorageProp("formId")formId: string = "xxx"
@LocalStorageProp('num')
num:number=0build() {Column() {Button(this.formId)Text(`${this.num}`).fontSize(15)Button('点击数字+100').onClick(() => {postCardAction(this, {action: 'message',// 提交过去的参数params: { num: this.num, aa: 200, formId: this.formId }})})}.width("100%").height("100%").justifyContent(FlexAlign.Center)}
}

记得要携带formId过去,因为返回数据时需要根据formId找到对应的卡片

//卡片生命周期
import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit';
import { Want } from '@kit.AbilityKit';
import { JSON } from '@kit.ArkTS';export default class EntryFormAbility extends FormExtensionAbility {// 	卡片被创建时触发onAddForm(want: Want) {// formBindingData:提供卡片数据绑定的能力,包括FormBindingData对象的创建、相关信息的描述class FormData {// 每一张卡片创建时都会被分配一个唯一的idformId: string = want.parameters!['ohos.extra.param.key.form_identity'].toString();}let formData = new FormData()// console.log('测试',JSON.stringify(formData))// 返回数据给卡片return formBindingData.createFormBindingData(formData);}// 卡片转换成常态卡片时触发onCastToNormalForm(formId: string) {// Called when the form provider is notified that a temporary form is successfully// converted to a normal form.}// 卡片被更新时触发(调用 updateForm 时)onUpdateForm(formId: string) {// Called to notify the form provider to update a specified form.console.log('测试','卡片更新了')}// 卡片发起特定事件时触发(message)onFormEvent(formId: string, message: string) {//   接收到卡片通过message事件传递的数据// message {"num":0,"aa":200,"params":{"num":100,"aa":200},"action":"message"}interface IData {num: numberaa: number}interface IRes extends IData {params: IData,action: "message"formId: string}const params = JSON.parse(message) as IResconsole.log('测试',JSON.stringify(params))interface IRet {num: number}const data: IRet = {num: params.num + 100}const formInfo = formBindingData.createFormBindingData(data)console.log('测试',JSON.stringify(formInfo))// 返回数据给对应的卡片formProvider.updateForm(params.formId, formInfo)}//卡片被卸载时触发onRemoveForm(formId: string) {// Called to notify the form provider that a specified form has been destroyed.}// 卡片状态发生改变时触发onAcquireFormState(want: Want) {// Called to return a {@link FormState} object.return formInfo.FormState.READY;}
}

当卡片组件发起message事件时,我们可以通过onFormEvent监听到

数据接收要声明对应的接口

formProvider.updateForm(params.formId, formInfo)更新卡片

2.卡片与应用之间的通信

1.router 通信

router事件的特定是会拉起应用,前台会展示页面,会触发应用的onCreateonNewWant生命周期

我们可以利用这个特性做唤起特定页面并且传递数据。

当触发router事件时,

  1. 如果应用没有在运行,便触发 onCreate事件
  2. 如果应用正在运行,便触发onNewWant事件
const localStorage = new LocalStorage()
// 卡片组件通过LocalStorage来接收onAddForm中返回的数据
@Entry(localStorage)
@Component
struct WidgetCard {// 接收onAddForm中返回的卡片Id@LocalStorageProp("formId")formId: string = "xxx"
@LocalStorageProp('num')
num:number=0build() {Column() {//卡片与卡片的声明周期Button(this.formId)Text(`${this.num}`).fontSize(15)Button('点击数字+100').onClick(() => {postCardAction(this, {action: 'message',// 提交过去的参数params: { num: this.num, aa: 200, formId: this.formId }})})//router通信Button("跳转到主页").margin({top:10}).onClick(() => {postCardAction(this, {action: 'router',abilityName: 'EntryAbility', // 只能跳转到当前应用下的UIAbilityparams: {targetPage: 'pages-3路由与axios/Index',}});})}.width("100%").height("100%").justifyContent(FlexAlign.Center)}
}

解析传递过来的卡片 id 与卡片的参数

分别在应用的onCreate和onNewWant编写逻辑实现跳转页面

import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { display, router, window } from '@kit.ArkUI';
import { formInfo } from '@kit.FormKit';export default class EntryAbility extends UIAbility {// 要跳转的页面 默认是首页targetPage: string = "pages/Demo"onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {// 判断是否带有formId 因为我们直接点击图标,也会拉起应用,此时不会有formIdif (want.parameters && want.parameters[formInfo.FormParam.IDENTITY_KEY] !== undefined) {// 获取卡片的formIdconst formId = want.parameters![formInfo.FormParam.IDENTITY_KEY].toString();// 获取卡片传递过来的参数interface IData {targetPage: string}const params: IData = (JSON.parse(want.parameters?.params as string))console.log('测试','应用没有运行')this.targetPage = params.targetPage//   我们也可以在这里通过 updateForm(卡片id,数据) 来返回内容给卡片}}// 如果应用已经在运行,卡片的router事件不会再触发onCreate,会触发onNewWantonNewWant(want: Want, launchParam: AbilityConstant.LaunchParam): void {const formId = want.parameters![formInfo.FormParam.IDENTITY_KEY].toString();// 获取卡片传递过来的参数interface IData {targetPage: string}const params: IData = (JSON.parse(want.parameters?.params as string))this.targetPage = params.targetPageconsole.log('测试','应用已经在运行')// 跳转页面router.pushUrl({url: this.targetPage})//   我们也可以在这里通过 updateForm(卡片id,数据) 来返回内容给卡片}onDestroy(): void {hilog.info(0x0000, 'testTag', '%{public}s', 'Ability onDestroy');}onWindowStageCreate(windowStage: window.WindowStage): void {//模拟器启动windowStage.loadContent(this.targetPage, (err) => {console.log('测试',this.targetPage)});}onWindowStageDestroy(): void {// Main window is destroyed, release UI related resourceshilog.info(0x0000, 'testTag', '%{public}s', 'Ability onWindowStageDestroy');}onForeground(): void {// Ability has brought to foregroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');}onBackground(): void {// Ability has back to backgroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');}
}

2.call 通信

call会拉起应用,但是会在后台的形式运行。需要申请后台运行权限,可以进行比较耗时的任务

需要申请后台运行应用权限

{"module": {// ..."requestPermissions": [{"name": "ohos.permission.KEEP_BACKGROUND_RUNNING"}],
  1. 卡片组件触发call事件,参数中必须携带method属性,用来区分不同的方法
export const localStorage = new LocalStorage()@Entry(localStorage)
@Component
struct WidgetCard {// 接收onAddForm中返回的卡片Id@LocalStorageProp("formId")formId: string = "xxx"@LocalStorageProp("num")num: number = 100build() {Column() {Button("call事件" + this.num).onClick(() => {postCardAction(this, {action: 'call',abilityName: 'EntryAbility', // 只能跳转到当前应用下的UIAbilityparams: {// 如果事件类型是call,必须传递method属性,用来区分不同的事件method: "inc",formId: this.formId,num: this.num,}});})}.width("100%").height("100%").justifyContent(FlexAlign.Center)}
}
  1. 应用EntryAbility在onCreate中,通过 callee来监听不同的method事件
import { AbilityConstant, UIAbility, Want } from '@kit.AbilityKit';
import { hilog } from '@kit.PerformanceAnalysisKit';
import { router, window } from '@kit.ArkUI';
import { formBindingData, formInfo, formProvider } from '@kit.FormKit';
import { rpc } from '@kit.IPCKit';// 占位 防止语法出错,暂无实际作用
class MyParcelable implements rpc.Parcelable {marshalling(dataOut: rpc.MessageSequence): boolean {return true}unmarshalling(dataIn: rpc.MessageSequence): boolean {return true}
}export default class EntryAbility extends UIAbility {// 要跳转的页面 默认是首页targetPage: string = "pages/Index"onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {//   监听call事件中的特定方法this.callee.on("inc", (data: rpc.MessageSequence) => {// data中存放的是我们的参数params: {// 如果事件类型是call,必须传递method属性,用来区分不同的事件// method: "inc",// formId: this.formId,// num: this.num,interface IRes {formId: stringnum: number}// 读取参数const params = JSON.parse(data.readString() as string) as IResinterface IData {num: number}// 修改数据const info: IData = {num: params.num + 100}// 响应数据const dataInfo = formBindingData.createFormBindingData(info)formProvider.updateForm(params.formId, dataInfo)}// 防止语法报错,暂无实际应用return new MyParcelable()})}onWindowStageCreate(windowStage: window.WindowStage): void {// 跳转到对应的页面windowStage.loadContent(this.targetPage, (err) => {if (err.code) {return;}});}onForeground(): void {// Ability has brought to foregroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onForeground');}onBackground(): void {// Ability has back to backgroundhilog.info(0x0000, 'testTag', '%{public}s', 'Ability onBackground');}
}

5.卡片与图片的通信

1.传递本地图片

import { photoAccessHelper } from '@kit.MediaLibraryKit';
import { fileIo } from '@kit.CoreFileKit';
import { promptAction } from '@kit.ArkUI';@Entry
@Component
struct Index {async aboutToAppear() {//-------------------------------------------------------------- 1.初始化图片配置项// 创建一个新的 PhotoSelectOptions 实例来配置图片选择器的行为let PhotoSelectOptions = new photoAccessHelper.PhotoSelectOptions();// 设置 MIME 类型为图像类型,这样用户只能选择图像文件PhotoSelectOptions.MIMEType = photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE;// 设置用户可以选择的最大图片数量为 1 张PhotoSelectOptions.maxSelectNumber = 1;//----------------------------------------------------------- 2.打开图片选择器,拿到图片// 创建一个新的 PhotoViewPicker 实例,用于打开图片选择器let photoPicker = new photoAccessHelper.PhotoViewPicker();// 使用前面配置好的选项打开图片选择器,并等待用户完成选择// 注意这里的 select 方法是一个异步方法,所以需要使用 await 关键字等待其结果const PhotoSelectResult = await photoPicker.select(PhotoSelectOptions);// 获取用户选择的第一张图片的 URI(统一资源标识符)// 假设这里只关心用户选择的第一张图片// uri file://media/Photo/3/IMG_1729864738_002/screenshot_20241025_215718.jpgconst uri = PhotoSelectResult.photoUris[0];promptAction.showToast({ message: `${uri}` })//------------------------------------------------------------- 3.拷贝图片到临时目录// 获取应用的临时目录let tempDir = getContext(this).getApplicationContext().tempDir;// 生成一个新的文件名const fileName = 123 + '.png'// 通过缓存路径+文件名 拼接出完整的路径const copyFilePath = tempDir + '/' + fileName// 将文件 拷贝到 临时目录const file = fileIo.openSync(uri, fileIo.OpenMode.READ_ONLY)fileIo.copyFileSync(file.fd, copyFilePath)}build() {RelativeContainer() {}.height('100%').width('100%')}
}

一旦保存到本地缓存除非卸载应用不然就一直有的

import { Want } from '@kit.AbilityKit';
import { fileIo } from '@kit.CoreFileKit';
import { formBindingData, FormExtensionAbility } from '@kit.FormKit';export default class EntryFormAbility extends FormExtensionAbility {// 在添加卡片时,打开一个本地图片并将图片内容传递给卡片页面显示onAddForm(want: Want): formBindingData.FormBindingData {// 假设在当前卡片应用的tmp目录下有一个本地图片 123.pnglet tempDir = this.context.getApplicationContext().tempDir;let imgMap: Record<string, number> = {};// 打开本地图片并获取其打开后的fdlet file = fileIo.openSync(tempDir + '/' + '123.png');//file.fd 打开的文件描述符。imgMap['imgBear'] = file.fd;class FormDataClass {// 卡片需要显示图片场景, 必须和下列字段formImages 中的key 'imgBear' 相同。imgName: string = 'imgBear';// 卡片需要显示图片场景, 必填字段(formImages 不可缺省或改名), 'imgBear' 对应 fdformImages: Record<string, number> = imgMap;}let formData = new FormDataClass();console.log("formDataformData", JSON.stringify(formData))// 将fd封装在formData中并返回至卡片页面return formBindingData.createFormBindingData(formData);}
}
let storageWidgetImageUpdate = new LocalStorage();@Entry(storageWidgetImageUpdate)
@Component
struct WidgetCard {@LocalStorageProp('imgName') imgName: ResourceStr = "";build() {Column() {Text(this.imgName)}.width('100%').height('100%').backgroundImage('memory://' + this.imgName).backgroundImageSize(ImageSize.Cover)}
}

Image组件通过入参(memory://fileName)中的(memory://)标识来进行远端内存图片显示,其中fileName需要和EntryFormAbility传递对象('formImages': {key: fd})中的key相对应。

2.传递网络图片

import { Want } from '@kit.AbilityKit';
import { fileIo } from '@kit.CoreFileKit';
import { formBindingData, FormExtensionAbility, formInfo, formProvider } from '@kit.FormKit';
import { http } from '@kit.NetworkKit';
import { BusinessError } from '@kit.BasicServicesKit';export default class EntryFormAbility extends FormExtensionAbility {// 将网络图片传递给onAddForm(want: Want) {// 注意:FormExtensionAbility在触发生命周期回调时被拉起,仅能在后台存在5秒// 建议下载能快速下载完成的小文件,如在5秒内未下载完成,则此次网络图片无法刷新至卡片页面上const formId = want.parameters![formInfo.FormParam.IDENTITY_KEY] as string// 需要在此处使用真实的网络图片下载链接let netFile ='https://env-00jxhf99mujs.normal.cloudstatic.cn/card/3.webp?expire_at=1729871552&er_sign=0eb3f6ac3730703039b1565b6d3e59ad'; let httpRequest = http.createHttp()// 下载图片httpRequest.request(netFile).then(async (data) => {if (data?.responseCode == http.ResponseCode.OK) {// 拼接图片地址let tempDir = this.context.getApplicationContext().tempDir;let fileName = 'file' + Date.now();let tmpFile = tempDir + '/' + fileName;let imgMap: Record<string, number> = {};class FormDataClass {// 卡片需要显示图片场景, 必须和下列字段formImages 中的key fileName 相同。imgName: string = fileName;// 卡片需要显示图片场景, 必填字段(formImages 不可缺省或改名), fileName 对应 fdformImages: Record<string, number> = imgMap;}// 打开文件let imgFile = fileIo.openSync(tmpFile, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE);imgMap[fileName] = imgFile.fd;// 写入文件await fileIo.write(imgFile.fd, data.result as ArrayBuffer);let formData = new FormDataClass();let formInfo = formBindingData.createFormBindingData(formData);// 下载完网络图片后,再传递给卡片formProvider.updateForm(formId, formInfo)fileIo.closeSync(imgFile);httpRequest.destroy();console.log("============")}}).catch((e: BusinessError) => {console.log("eeee", e.message)})class FormData {formId: string = ""}// 先返回基本数据return formBindingData.createFormBindingData(new FormData);}onFormEvent(formId: string, message: string): void {}
}

相关文章:

【鸿蒙HarmonyOS】一文详解华为的服务卡片

7.服务卡片 1.什么是卡片 Form Kit&#xff08;卡片开发服务&#xff09;提供一种界面展示形式&#xff0c;可以将应用的重要信息或操作前置到服务卡片&#xff08;以下简称“卡片”&#xff09;&#xff0c;以达到服务直达、减少跳转层级的体验效果。卡片常用于嵌入到其他应…...

深度卷积模型:案例研究

1 为什么要进行案例研究&#xff1f; 过去&#xff0c;计算机视觉中的大量研究都集中在如何将卷积层、池化层以及全连接层这些基本组件组合起来&#xff0c;形成有效的卷积神经网络。 找感觉的最好方法之一就是去看一些示例&#xff0c;就像很多人通过看别人的代码来学习编程一…...

BBR 的 RTT 公平性问题求解

如果 BBR 要跟 reno/cubic 公平&#xff0c;只能顾此失彼&#xff0c;没有任何变通方法&#xff0c;唯一的方法就是在放弃 reno/cubic&#xff0c;但前提你得保证 BBR 流之间是公平的。如果非要照顾 reno/cubic&#xff0c;那就必须要变成 reno/cubic&#xff0c;这就是 BBRv2/…...

SQL命令二:SQL 高级查询与特殊算法

引言 在掌握了 SQL 的基础操作和建表约束后&#xff0c;我们可以进一步探索 SQL 的高级查询功能和一些特殊算法。这些高级技巧能够帮助我们更高效地处理和分析数据&#xff0c;满足复杂的业务需求。 一、查询进阶 &#xff08;一&#xff09;简单查询 简单查询通过 select 语…...

Databend 产品月报(2025年4月)

很高兴为您带来 Databend 2025 年 4 月的最新更新、新功能和改进&#xff01;我们希望这些增强功能对您有所帮助&#xff0c;并期待您的反馈。 BendDeploy&#xff1a;安装 Databend 的新方式 BendDeploy 是由 Databend 开发的一款基于 Kubernetes 的平台&#xff0c;旨在简化…...

Best Video下载器——全能高清无水印视频下载工具

在当今短视频和流媒体盛行的时代&#xff0c;用户经常遇到想要下载视频却受限于平台限制的情况。无论是收藏喜欢的影视片段、保存有价值的教程&#xff0c;还是进行二次创作&#xff0c;一款高效、免费且支持多平台的视频下载工具显得尤为重要。Best Video下载器正是为此而生&a…...

2025东三省D题深圳杯D题数学建模挑战赛数模思路代码文章教学

完整内容请看文章最下面的推广群 一、问题一&#xff1a;混合STR图谱中贡献者人数判定 问题解析 给定混合STR图谱&#xff0c;识别其中的真实贡献者人数是后续基因型分离与个体识别的前提。图谱中每个位点最多应出现2n个峰&#xff08;n为人数&#xff09;&#xff0c;但由…...

这些是什么充电模块调试手段,对USB、Thermal、DP

在电子产品开发中&#xff0c;充电模块调试及对相关模块的了解是保障产品性能与稳定性的关键环节。下面为你详细介绍&#xff1a; 充电模块调试手段&#xff1a;充电模块负责将外部电源的电能转化为适用于设备的电能&#xff0c;并对电池进行充电管理。调试手段包括使用专业的…...

Gradio全解20——Streaming:流式传输的多媒体应用(2)——构建对话式聊天机器人

Gradio全解20——Streaming&#xff1a;流式传输的多媒体应用&#xff08;2&#xff09;——构建对话式聊天机器人 本篇摘要20. Streaming&#xff1a;流式传输的多媒体应用20.2 构建对话式聊天机器人20.2.1 应用概述20.2.2 记录用户音频20.2.3 存储音频并生成响应20.2.4 构建G…...

字节暑期实习-网络运维工程师面经

岗位描述 这个是ByteIntern实习&#xff0c;是暑期实习岗位 岗位 一面 先自我介绍 抓项目技术&#xff08;会进行确认是什么技术&#xff09; TCP的三次握手和四次挥手 序列号和确认应答号的位置和大小 序列号是随机的吗&#xff1f; 序列号为什么是随机的&#xff1f; …...

多用户远程 Debugger 服务隔离方案技术实践

多用户远程 Debugger 服务隔离方案技术实践 摘要&#xff1a; 针对多用户同时连接远程 Debugger 服务可能导致的断点冲突、调试流程干扰等问题&#xff0c;本文基于主流调试工具&#xff08;如 Python debugpy、Java JDWP、Node.js Inspector 等&#xff09;&#xff0c;梳理和…...

华为发布全球首个L3商用智驾ADS4.0

2024年10月2024世界智能网联汽车大会上&#xff0c;余承东讲到&#xff1a;“华为ADS 4.0将于2025年推出高速L3级自动驾驶商用及城区L3级自动驾驶试点&#xff0c;希望加快L3级自动驾驶标准的进程&#xff0c;推动L3级自动驾驶技术的普及。” 世界智能网联汽车大会演讲PPT 所以…...

Silo 科学数据工具库安装与使用指南

Silo 科学数据工具库安装与使用指南 Silo 是一个用于科学数据可视化和分析的工具库&#xff0c;由 Lawrence Livermore National Laboratory (LLNL) 开发。以下是 Silo 的安装和使用方法&#xff1a; 安装 Silo Linux 系统安装 从源码安装&#xff1a; wget https://wci.lln…...

vs2019编译occ7.9.0时,出现fatal error C1060: compiler is out of heap space

问题描述 visual studio 2019编译opencascade 7.9.0时&#xff0c;出现编译错误 fatal error C1060: compiler is out of heap space 解决方案 修改vs2019并行编译的线程个数&#xff0c;默认是12个&#xff0c;我改成了4个&#xff0c;问题解决 Tools > Project and Sol…...

Poco C++全面开发指南:网络应用开发

UDP接收器 项目结构 poco_demo/ ├── CMakeLists.txt ├── src/ │ ├── main.cpp │ └── Receiver.cpp └── include/└── Receiver.h创建 Receiver.h #pragma once#include <Poco/Net/DatagramSocket.h> #include <Poco/Net/SocketAddress.h>…...

Spring AOP概念及其实现

一、什么是AOP 全称Aspect Oriented Programming&#xff0c;即面向切面编程&#xff0c;AOP是Spring框架的第二大核心&#xff0c;第一大为IOC。什么是面向切面编程&#xff1f;切面就是指某一类特定的问题&#xff0c;所以AOP也可以称为面向特定方法编程。例如对异常的统一处…...

业务部绩效考核关键指标与数据分析

在业务部的绩效考核中&#xff0c;重点通过销售额、客户关系、财务管理等多个维度来评估团队的工作成果。绩效考核指标&#xff08;KPI&#xff09;不仅帮助公司衡量销售团队的业绩&#xff0c;还能反映出团队在客户管理、财务控制以及市场拓展方面的综合表现。每一个考核指标都…...

线上婚恋相亲小程序源码介绍

​基于ThinkPHP、FastAdmin和UniApp开发的线上婚恋相亲小程序源码&#xff0c;这款小程序源码采用了ThinkPHP作为后端框架&#xff0c;其强大的功能与良好的扩展性为程序的稳定运行提供了保障。 ​FastAdmin作为后台管理框架&#xff0c;使得管理员能够便捷地对用户信息、相亲…...

【SystemC初认识】SystemC是什么?有哪些主要组件?如何简单使用?

【SystemC初认识】SystemC是什么&#xff1f;有哪些主要组件&#xff1f;如何简单使用&#xff1f; 1 SystemC简介2 主要组件3 关于时序与调度4 如何安装4.1 安装C编译器4.2 安装SystemC 库 5 SystemC代码示例6 关于SystemC 仿真与调度7 SystemC 中的常用类和函数8 常见的设计模…...

软考:硬件中的CPU架构、存储系统(Cache、虚拟内存)、I/O设备与接口

文章目录 1. 引言1.1 硬件知识的重要性1.2 软件设计师考试中硬件的考察目标 2. CPU架构2.1 CPU的基本概念2.2 CPU的内部结构2.3 CPU的工作原理2.4 指令集架构&#xff08;ISA&#xff09;2.5 多核处理器 3. 存储系统3.1 存储器的基本概念3.2 主存储器&#xff08;RAM&#xff0…...

力扣hot100——98.验证二叉搜索树

题目链接&#xff1a;98. 验证二叉搜索树 - 力扣&#xff08;LeetCode&#xff09; 首先列举一个错误代码 class Solution { public:bool isValidBST(TreeNode* root) {if(rootnullptr) return true;if(root->right){if(root->right->val<root->val) return f…...

UE 像素和线框盒子 材质

像素材质&#xff1a; 线框盒子材质&#xff1a;...

工业质检领域相关近期顶会论文汇总CVPR2025

目录 异常检测Anomaly Detection多类别数据集开集有监督异常检测Open-set Supervised Anomaly Detection&#xff08;OSAD&#xff09;基于多模态大模型能力 骨干网络Mamba系列&#xff08;mamba为transformer后的新骨干网络形式&#xff09;其他 目标检测开集识别DETR实例检测…...

leetcode76

目录 803ms超时。。。。越改越超时。。。 一些纠缠 代码分析&#xff1a; 代码问题&#xff1a; 改进建议&#xff1a; 示例代码&#xff1a; The error message you’re seeing indicates that there is a reference binding to a null pointer in your code. This typ…...

Android Studio下载安装教程

## 什么是Android Studio Android Studio是Google官方推出的Android应用开发集成环境(IDE)&#xff0c;基于IntelliJ IDEA开发&#xff0c;专门用于Android应用开发。它包含了代码编辑器、可视化布局编辑器、应用性能分析工具、模拟器等功能&#xff0c;为开发者提供了一站式的…...

shell---expect

1.expect的安装 [rootqfedu ~] yum -y install expect 2.expect的语法: 用法: 1)定义expect脚本执行的shell #!/usr/bin/expect -----类似于#!/bin/bash 2)spawn spawn是执行expect之后后执行的内部命令开启一个会话 #功能:用来执行shell的交互命令 3)…...

基于PHP的在线编程课程学习系统

有需要请加文章底部Q哦 可远程调试 基于PHP在线编程课程学习系统 一 介绍 在线编程课程学习系统基于原生PHP开发&#xff0c;数据库mysql&#xff0c;前端jquery.js。系统角色分为学生&#xff0c;教师和管理员。(附带参考设计文档) 技术栈&#xff1a;phpmysqljquery.jsphps…...

深度学习概述

近年来&#xff0c;我们在媒体上到处可见人工智能&#xff08;AI&#xff09;这个词&#xff0c;而深度学 习是人工智能的一种实现方法。下面我们就来简单地看一下深度学习具 有怎样划时代的意义。 下面是三张花的图片&#xff0c;它们都具有同一个名字&#xff0c;那究竟是什…...

[原创](现代Delphi 12指南):[macOS 64bit App开发]: [1]如何使用原生NSAlert消息框 (runModal模式)

[作者] 常用网名: 猪头三 出生日期: 1981.XX.XX 企鹅交流: 643439947 个人网站: 80x86汇编小站 编程生涯: 2001年~至今[共24年] 职业生涯: 22年 开发语言: C/C++、80x86ASM、Object Pascal、Objective-C、C#、R、Python、PHP、Perl、 开发工具: Visual Studio、Delphi、XCode、…...

【NumPy完全指南】从基础操作到高性能计算实战

&#x1f4d1; 目录 一、NumPy核心价值1.1 科学计算现状分析1.2 ndarray设计哲学 二、核心数据结构解析2.1 ndarray内存布局2.2 数据类型体系 三、矢量化编程实践3.1 通用函数(ufunc)示例3.2 广播机制图解 四、高性能计算进阶4.1 内存预分配策略4.2 Cython混合编程 五、典型应用…...

深入解析词嵌入(Word2Vec、GloVe)技术原理:从词语到向量的转变

&#x1f4cc; 友情提示&#xff1a; 本文内容由银河易创AI&#xff08;https://ai.eaigx.com&#xff09;创作平台的gpt-4o-mini模型生成&#xff0c;旨在提供技术参考与灵感启发。文中观点或代码示例需结合实际情况验证&#xff0c;建议读者通过官方文档或实践进一步确认其准…...

Android学习总结之点击登录按钮流程

1. 事件分发阶段 1.1 触摸事件产生 当用户点击屏幕上的登录按钮时&#xff0c;触摸屏硬件会检测到触摸操作&#xff0c;并将触摸事件的相关信息&#xff08;如触摸的坐标、触摸的时间等&#xff09;传递给 Android 系统的 InputManagerService。 1.2 Activity 接收事件 Inp…...

多数元素题解(LC:169)

169. 多数元素 核心思想&#xff08;Boyer-Moore 投票算法&#xff09;&#xff1a; 解题思路&#xff1a;可以使用 Boyer-Moore 投票算法、该算法的核心思想是&#xff1a; 维护一个候选元素和计数器、初始时计数器为 0。 遍历数组&#xff1a; 当计数器为 0 时、设置当前元…...

C# 在VS2022中开发常用设置

一、基础环境配置 1. 安装必要组件 在 VS2022 安装时确保勾选以下工作负载&#xff1a; ​​使用 .NET 的桌面开发​​&#xff08;包含 WPF/WinForms&#xff09;​​ASP.NET 和 Web 开发​​​​.NET 跨平台开发​​​​Azure 开发​​​​数据存储和处理​​ 2. 主题与外…...

三个概念:DataBinding,Dependency Property 与DataTemplate

WPF 核心概念详解&#xff1a;DataBinding、Dependency Property 和 DataTemplate 1. DataBinding (数据绑定) 基本概念 DataBinding 是 WPF 的核心机制&#xff0c;用于在 UI 元素和数据源之间建立自动同步关系。 关键特性 双向绑定&#xff1a;数据变化自动反映到 UI&…...

基于C#开发的适合Windows开源文件管理器

使用DDD从零构建一个完整的系统 推荐一个功能强大且直观的开源文件管理器&#xff0c;适用于Windows平台。 01 项目简介 该项目是一个基于C#开发、开源的文件管理器&#xff0c;适用于Windows&#xff0c;界面UI美观、方便轻松浏览文件。此外&#xff0c;支持创建和提取压缩…...

nacos和redis本地启动

1. 下载Nacos 首先&#xff0c;你需要从Nacos的官方GitHub仓库下载最新版本的Nacos服务器。你可以访问Nacos GitHub页面来下载。 2. 解压下载的文件 下载完成后&#xff0c;解压你下载的Nacos包到一个目录中。例如&#xff0c;你可以将其解压到~/nacos/。 3. 启动Nacos服务…...

时态--00--总述

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 时态句子结构时态标志词 时态 句子结构 时态标志词...

PH热榜 | 2025-04-30

1. Daytona 标语&#xff1a;安全且灵活的基础设施&#xff0c;用于运行你的人工智能生成的代码。 介绍&#xff1a;Daytona Cloud 为 AI 智能体重塑了基础设施&#xff0c;具备不到 90 毫秒的启动时间、原生性能以及有状态执行的能力&#xff0c;这些是传统云计算所无法实现…...

.NET Core 数据库ORM框架用法简述

.NET Core ORM框架用法简述 一、主流.NET Core ORM框架概述 在.NET Core生态系统中&#xff0c;主流的ORM(Object-Relational Mapping)框架包括&#xff1a; ​​Entity Framework Core (EF Core)​​ - 微软官方推出的ORM框架​​Dapper​​ - 轻量级微ORM​​Npgsql.Entit…...

在Windows系统上如何用Manifest管理嵌入式项目

相信很多Android开发出身的工程师对于manifest、repo和gerrit会有一定的好感&#xff0c;即使转行做了其他的行业&#xff0c;也希望可以延续Android的代码管理风格。这里记录了一个在汽车电子行业使用GerritrepoManifest来管理嵌入式项目的方法&#xff0c;希望对读者有帮助。…...

Qt -DFS可视化

博客主页&#xff1a;【夜泉_ly】 本文专栏&#xff1a;【暂无】 欢迎点赞&#x1f44d;收藏⭐关注❤️ 目录 前言关于如何sleep实现思路Pixmapspixmaps.hpixmaps.cpp MapSquaremapsquare.hmapsquare.cpp dfsthreaddfsthread.hdfsthread.cpprun dfs其他 WidgetUnit其他 Qt -DFS…...

H.264添加 SEI 信息技术文档

概述 本文档描述如何在 H.264 视频流中动态插入自定义 SEI信息。SEI 是 H.264/AVC 标准中定义的一种元数据格式&#xff0c;可用于携带时间戳、版权信息、场景标记等附加数据。本方案基于 FFmpeg 的 AVPacket 结构和标准 H.264 NAL 单元格式实现&#xff0c;支持与视频帧的精确…...

ICMP协议

ICMP协议 一、ICMP基本概念 1、ICMP协议 Internet控制报文协议&#xff0c;用于在IP主机、路由器之间传递控制消息&#xff0c;控制消息指网络通不通、主机是否可达、路由是否可用等等ICMP是属于网络层的协议&#xff0c;封装在传输层与网络层之间 2、ICMP报文格式 类型 (t…...

react中封装一个预览.doc和.docx文件的组件

主要用到了mammoth这个插件,mammoth.js‌是一个JavaScript库&#xff0c;主要用于将Microsoft Word文档&#xff08;.docx格式&#xff09;转换为HTML。它可以通过Node.js环境使用&#xff0c;也可以直接在浏览器中使用。 关键代码: import mammoth from mammoth; import { u…...

驾驭音质,尽享四通道力量——AXPA17851

AXPA17851: 4x48W 车用AB类四通道桥式输出音频功率放大器 AXPA17851是采用BCD(双极型&#xff0c;CMOS&#xff0c;DMOS)工艺技术设计的四通道桥式输出AB类车用音频功率放大器&#xff0c;采用完全互补的P型/ N型输出结构&#xff0c; 具有轨到轨的输出电压摆幅&#xff0c;高输…...

人格伤疤测试:发现内心深处的情感创伤

人格伤疤测试&#xff1a;发现内心深处的情感创伤 工具介绍 我们开发了一个专业的人格伤疤测试工具&#xff0c;帮助您发现和了解内心深处的情感创伤。这个在线测评从十个关键维度全面评估您的心理状态&#xff1a; 核心维度 情感创伤: 评估童年经历对当前情绪的影响自我认…...

CANopen协议简单介绍和使用

文章目录 一、CAN总线介绍二、CAN总线的帧类型三、CAN总线的特性四、Linux中的CAN帧驱动结构体五、CAN总线升级版本-CANFD六、更高层封装的协议-应用层封装的CANopen协议总结 一、CAN总线介绍 CAN总线&#xff08;Controller Area Network&#xff09; 是一种串行通信协议&…...

数据隐私在Web3环境下的重要性及实现方法

在这个信息爆炸的时代&#xff0c;我们正站在 Web3 的门槛上&#xff0c;迎接着一个全新的网络架构和用户交互方式。Web3 不仅仅是技术的迭代&#xff0c;它还代表了一种全新的网络架构和用户交互方式。在 Web3 环境下&#xff0c;数据隐私成为了一个至关重要的话题。本文将探讨…...

【每日八股】复习 Redis Day4:线程模型

文章目录 复习 Redis Day4&#xff1a;线程模型介绍一下 Redis 的线程模型核心线程模型&#xff08;Redis 6.0 之前&#xff09;Redis 6.0 的多线程改进Redis 真的是单线程吗&#xff1f;Redis 的线程模型剖析 上一篇 Redis 的应用我今天才完成&#xff0c;因此明天一并复习 Re…...