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

【Harmony】常用工具类封装

文章目录

  • 一,简介
  • 二,网络请求工具类
    • 2.1、鸿蒙原生http封装
    • 2.2、第三方axios封装(需提前下载依赖)
  • 三、录音笔相关工具类
    • 3.1、录音封装(录入)
    • 3.2、录音封装(放音/渲染)
    • 3.3、文件写入封装(针对录音/放音功能)
  • 四、RDB关系型数据库
    • 4.1、relationalStore简答的CRUD封装
    • 4.2、relationalStore单例模式封装(待更新)
  • 五、首选项
    • 5.1、preferences简单封装
    • 5.2、preferences单例模式封装
  • 六、权限管理
    • 6.1、权限管理封装
  • 七、其他工具类
    • 7.1、生成一个指定连续数值的数组
    • 7.2、生成随机颜色(RGB)
    • 7.3、生成随机颜色(16进制)
    • 7.4、格式化日期

一,简介

本文工具类更新至2025年4月22日,后续有新内容也会持续更新。并且本文工具类为本人在学习过程中自己总结和封装,可能有不足的地方,欢迎大佬指正。

二,网络请求工具类

2.1、鸿蒙原生http封装

//【鸿蒙http】
// -http只提供底层核心代码功能,没有任何功能的封装,需要自己开发。
// -适配应用,采用泛型进行封装
import { http } from "@kit.NetworkKit";
import { BASE_URL, TOKEN_KEY } from "../constants";
import { promptAction, router } from "@kit.ArkUI";
import { UserSettingClass } from ".";
import { ResponseData } from "../models";//【网络请求过程】
// 当前模块私有方法,不导出,提供正式对外开放的功能使用
// 其中包括:请求拦截处理,头部处理,过程处理,响应结果处理
//  -url:请求的路径:必填项
//  -data:请求的参数对象:什么都可以,用object,可选的
//  -method:请求方式,可选,默认是GET请求
async function requestHttp<T> (url: string,data?: object,method:http.RequestMethod = http.RequestMethod.GET
): Promise<T> {//创建请求对象const httpRequest = http.createHttp()//设置请求参数对象const options: http.HttpRequestOptions = {method,readTimeout: 10000,header: {//与后台匹配,提交的是json对象'Content-Type': 'application/json',//用户登录后,应用级数据对象获取用户令牌,拿不到就是空的'Authorization': AppStorage.get<string>(TOKEN_KEY) || ''},//设置除get请求之外的请求参数(因为get请求提交的数据是组合在地址中的)extraData: method === http.RequestMethod.GET ? '' : data}//组合正式请求的完整网址let urlStr = BASE_URL + url//处理get请求情况if(method === http.RequestMethod.GET){//需要将请求对象中的属性提取出来,组合到请求地址中//判断:是否提交了请求数据对象if(data){//调用Object的方法,自动获取对象中所有的属性名,返回字符串数组const allKeys:string[] = Object.keys(data)//是否有请求的参数属性if(allKeys){//创建一个数组,字符串的,里面是请求内容[key=value]const arr:string[] = []//循环key的数组for(let key of allKeys){//在数据中,按照key获取值,然后组合成要的格式,加入数组arr.push(`${key}=${data[key]}`)}//组合到请求地址中:按照指定字符将数组所有元素组合成一个字符串urlStr += '?' + arr.join('&')}}}//正式发送请求//  -异常需要处理:这个数据代码错误了//  -http请求操作是一次性的(鸿蒙固定的),用完了要销毁的//  -需要对应好resolve和reject//   错误情况有多种,err是错误,服务器正常返回也有错误的//  -采用Promise特性,async自动封装了Promise,内部可以直接对应resolve和rejecttry{//发起请求,获取响应结果const res = await httpRequest.request(urlStr, options)//解析响应结果:if(res.responseCode === 401){//服务器验证用户身份Authorization失败promptAction.showToast({message: '未授权或令牌失效!'})//清空本地令牌AppStorage.setOrCreate(TOKEN_KEY, '')new UserSettingClass(getContext()).setUserToken('')//跳转登录router.replaceUrl({ url: 'pages/Login/Login' })//返回错误return Promise.reject(new Error('未授权或令牌失效!'))}else if(res.responseCode === 404){//访问的地址已失效promptAction.showToast({message: '请求的地址无效!'})return Promise.reject(new Error('请求的地址无效!'))}else if(res.responseCode === 200){//正确响应,提取响应结果// -先将响应结果统一类型string// -然后转成json对象,它是object// -然后对应好类型约束:ResponseData:参考所有接口返回的统一格式const result = JSON.parse(res.result as string) as ResponseData<T>//校验结果:回发的数据中的编码if(result.code === 200){//返回结果:适配泛型,默认返回自动对应resolve,不用写了return result.data as T}else{//请求对的,也响应了,但是代码中说失败//请找后端开发人员了解具体情况:需要告知:请求方式、头部、参数promptAction.showToast({message: '请求失败!'})return Promise.reject(new Error('请求失败!'))}}else{return Promise.reject(new Error('服务器接口调用失败!'))}}catch(err){//错误return Promise.reject(new Error(JSON.stringify(err)))}finally {//对和错都执行:销毁请求对象httpRequest.destroy()}
}//【http接口请求工具类】
// -对外提供RestFul请求风格的四类请求:GET/POST/PUT/DELETE
// -采用静态方法,提供应用直接使用
export class Request {//方法格式统一,用方法名描述请求方式//参数只要路径和请求数据对象//响应结果是Promise<泛型>,你要什么返回什么static get<T>(url:string, data?:object):Promise<T> {return requestHttp<T>(url, data, http.RequestMethod.GET)}static post<T>(url:string, data?:object):Promise<T> {return requestHttp<T>(url, data, http.RequestMethod.POST)}static put<T>(url:string, data?:object):Promise<T> {return requestHttp<T>(url, data, http.RequestMethod.PUT)}static delete<T>(url:string, data?:object):Promise<T> {return requestHttp<T>(url, data, http.RequestMethod.DELETE)}
}

2.2、第三方axios封装(需提前下载依赖)

如果没有axios依赖,须在项目目录下,命令行执行如下命令

ohpm install @ohos/axios

出现绿色completed证明安装成功

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

//【第三方axios】
import axios,{InternalAxiosRequestConfig,AxiosError,AxiosResponse,AxiosRequestConfig,AxiosInstance} from "@ohos/axios"
import { UserSettingClass } from "."
import { BASE_URL, TOKEN_KEY } from "../constants"
import { router } from "@kit.ArkUI"const instance = axios.create({baseURL:BASE_URL,//自动组合到请求路径readTimeout:10000
})//请求拦截配置,发起请求时,先执行这里追加令牌
instance.interceptors.request.use((config:InternalAxiosRequestConfig)=>{//config就是配置,我们在头部追加用户令牌config.headers.Authorization = AppStorage.get(TOKEN_KEY) || ""return config},(err:AxiosError)=>{return Promise.reject(err)
})//响应拦截,接收到响应结果后,执行这里的操作
instance.interceptors.response.use((response:AxiosResponse)=>{//data:{code,meg,data}//判断结果:if(response.data && response.data.code ===200){return response.data.data}//TODO:如果response.data.code ===401等自行处理//默认返回响应,调用者处理return response
},(err:AxiosError)=>{//是否是401,身份验证不通过if(err.response?.status===401){//说明令牌无效AppStorage.setOrCreate(TOKEN_KEY,"")//删除应用中的token记录new UserSettingClass(getContext()).setUserToken("")//删除首选项中的token//跳转登录router.replaceUrl({ url: 'pages/Login/Login' })}return Promise.reject(err)
})//提供执行操作对象,适配泛型
//R是返回类型,D是请求类型
//支持调用时,自定义配置
function request<R=null,D=null>(config:AxiosRequestConfig){//返回操作实例return instance<null,R,D>(config)
}export class RequestAxios{static get<T>(url:string, data?:object):Promise<T> {return request<T,null>({url,params:data,method:"GET"})}static post<T>(url:string, data?:object):Promise<T> {return request<T,object>({url,data,method:"POST"})}static put<T>(url:string, data?:object):Promise<T> {return request<T,object>({url,data,method:"PUT"})}static delete<T>(url:string, data?:object):Promise<T> {return request<T,object>({url,data,method:"DELETE"})}
}

三、录音笔相关工具类

3.1、录音封装(录入)

//音频工具
//官方称之为录音笔
//需要集成audio和fileIo
import { audio } from "@kit.AudioKit";
import { fileIo } from "@kit.CoreFileKit";
import { emitter } from "@kit.BasicServicesKit";export class AudioCapturer{//录音笔对象static audioCapture:audio.AudioCapturer//音频流配置static audioStreamInfo:audio.AudioStreamInfo = {samplingRate:audio.AudioSamplingRate.SAMPLE_RATE_16000,//音频的采样率:帧数sampleFormat:audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,//音频文件的转码格式--音频播放解析encodingType:audio.AudioEncodingType.ENCODING_TYPE_RAW,//文件编码格式--读写文件channels:audio.AudioChannel.CHANNEL_1 //等级} as audio.AudioStreamInfo//录音笔配置static  audioCapturerInfo:audio.AudioCapturerInfo = {source:audio.SourceType.SOURCE_TYPE_MIC,//资源的来源:麦克风capturerFlags:0//功能启动标识}//控制变量:是否进行录制static recordIng:boolean =false//初始化static async  init(){//创建录音笔实例AudioCapturer.audioCapture = await audio.createAudioCapturer({streamInfo:AudioCapturer.audioStreamInfo,capturerInfo:AudioCapturer.audioCapturerInfo})}//开始录制static async start(filePath:string){try {//打开目标文件,得到文件对象,只写,读不在这块const file=fileIo.openSync(filePath,fileIo.OpenMode.READ_WRITE|fileIo.OpenMode.CREATE)//文件大小:字节const fd = file.fdlet bufferSize = fileIo.statSync(fd).size//开始采集,状态转换AudioCapturer.recordIng = true//开启录音笔能力await AudioCapturer.audioCapture.start()//采集音频:循环执行,由状态变量AudioCapturer.recordIng决定是否录制while (AudioCapturer.recordIng){//获取采集音频已经录下的在缓冲区内容的大小,他是一段一段读的const size = AudioCapturer.audioCapture.getBufferSizeSync()//从缓冲区中读取一段const  buffer = await AudioCapturer.audioCapture.read(size,true)//如果可以读到if(buffer){//追加写入fileIo.writeSync(fd,buffer,{offset:bufferSize,length:buffer.byteLength})//通知页面emitter.emit("caleVoice",{data:{buffer}})//下一段bufferSize+=buffer.byteLength}}}catch (err) {console.log(JSON.stringify(err));AlertDialog.show({message:"当前设备不支持录音"})}}//结束录制static async stop(){//只有在录制才可以结束根据状态变量判断if(AudioCapturer.recordIng && AudioCapturer.audioCapture){//结束音频录制AudioCapturer.recordIng = false//关闭录音功能await AudioCapturer.audioCapture.stop()}}//释放资源static async close(){//只要对象存在都可以执行if(AudioCapturer.audioCapture){//释放缓冲区await AudioCapturer.audioCapture.release()}}}

3.2、录音封装(放音/渲染)

//音频渲染/播放工具
//主要集中于本地文件,先下载
import { audio } from "@kit.AudioKit";
import { fileIo } from "@kit.CoreFileKit";export  class AudioRender {//播放器对象static audioRenderer:audio.AudioRenderer//音频流的配置static audioStreamInfo:audio.AudioStreamInfo = {samplingRate:audio.AudioSamplingRate.SAMPLE_RATE_16000,sampleFormat:audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,channels:audio.AudioChannel.CHANNEL_1,encodingType:audio.AudioEncodingType.ENCODING_TYPE_RAW} as audio.AudioStreamInfo//渲染器的配置static audioRenderInfo:audio.AudioRendererInfo = {rendererFlags:0,//标记usage:audio.StreamUsage.STREAM_USAGE_VOICE_ASSISTANT //语音助手的} as audio.AudioRendererInfo//渲染器的配置对象,将上面两个配置合在一起static  audioRenderOptions:audio.AudioRendererOptions = {streamInfo:AudioRender.audioStreamInfo,rendererInfo:AudioRender.audioRenderInfo}//文件static renderFile:fileIo.File//文件大小static maxSize:number = 0//已经播放的字节数static renderSize:number = 0//播放完的回调static callBack=()=>{}//初始化static async init(){//创建渲染器实例AudioRender.audioRenderer = await audio.createAudioRenderer(AudioRender.audioRenderOptions)//注册(监听)数据写入事件操作AudioRender.audioRenderer.on("writeData",//当有数据写入时(buffer:ArrayBuffer)=>{//是否有文件if(AudioRender.renderFile){//有,从文件中读取,文件大小必须保持一致fileIo.readSync(AudioRender.renderFile.fd,buffer,{offset:AudioRender.renderSize,length:buffer.byteLength})//更新字节数AudioRender.renderSize += buffer.byteLength}//前面的内容是否播放完毕if(AudioRender.renderSize>=AudioRender.maxSize){//关闭文件fileIo.closeSync(AudioRender.renderFile.fd)//停止播放//TODO:AudioRender.stop()}})}//播放static async start(filePath:string,callBack1?:()=>void,callBack2?:()=>void){//播放之前,停止之前播放,确保同时只播放一个await AudioRender.stop()//打开需要播放的文件AudioRender.renderFile= fileIo.openSync(filePath,fileIo.OpenMode.READ_WRITE)//获取文件大小AudioRender.maxSize= fileIo.statSync(AudioRender.renderFile.fd).size//文件有内容时if(AudioRender.maxSize>0){//如果有回调1:作为当前播放之前的方法调用callBack1 && callBack1()//如果有回调2:作为当前停止之后的方法调用,通过引用传递if(callBack2){AudioRender.callBack = callBack2}//正式播放AudioRender.audioRenderer.start()}else {AlertDialog.show({message:`文件为空`})}}//停止static async stop(){//必须播放状态下才可以停止if(AudioRender.audioRenderer && AudioRender.audioRenderer.state=== audio.AudioState.STATE_RUNNING){//停止await AudioRender.audioRenderer.stop()//重置信息AudioRender.maxSize = 0AudioRender.renderSize = 0//调用回调,告知外部AudioRender.callBack && AudioRender.callBack()}}}

3.3、文件写入封装(针对录音/放音功能)

//文件处理工具
//用于处理物理文件,针对files/目录
//针对录音功能,音频文件后缀.wav
import {fileIo} from  "@kit.CoreFileKit"export  class  FileOperate{//创建空文件,返回路径static  createAudioFile(userId:string){//判断有没有路径,没有就创建const dirPath = getContext().filesDir+"/"+userIdif(!fileIo.accessSync(dirPath)){fileIo.mkdirSync(dirPath)}//文件不能重名,利用时间戳作为文件名const  filePath = dirPath+"/"+Date.now()+".wav"//打开并创建文件const file = fileIo.openSync(filePath,fileIo.OpenMode.CREATE)//关闭文件,防止挂起fileIo.closeSync(file)return filePath}//删除指定文件static deleteFile(path:string){fileIo.unlinkSync(path)}//删除整个个人目录static deleteUser(userId:string){const dirPath = getContext().filesDir+"/"+userIdif(fileIo.accessSync(dirPath)){fileIo.rmdirSync(dirPath)}}}

四、RDB关系型数据库

4.1、relationalStore简答的CRUD封装

补充:

​ 1.这个工具类关闭数据库那里有点问题,我加了延时器关闭。因为store.close()是异步操作,如果不加,查询操作可能会出现数据库连接关闭了,返回的结果为空这种情况。所以手动延迟2秒关闭,造成这种情况原因还没完全搞明白,后续搞懂了再更新。

​ 2.resultSet结果集需要在调用处自行关闭释放。

import { relationalStore } from "@kit.ArkData"export  class  DBHelper{//TODO:这里数据库名需要替换为自己的,注意不要忘了.db后缀private DB_NAME:string = "Test.db"//TODO:这里数据库安全等级需要替换为自己的private DB_SECURITY_LEVEL = relationalStore.SecurityLevel.S1private store:relationalStore.RdbStore = {} as relationalStore.RdbStoreprivate config:relationalStore.StoreConfig = {name:this.DB_NAME,securityLevel:this.DB_SECURITY_LEVEL}//创建链接,需要传入上下文对象private async createDB(context:Context){try {this.store = await relationalStore.getRdbStore(context,this.config)}catch (e){console.log("createDB执行异常",e);}}//增删改操作,由调用处决定上下文对象async  execDML(context:Context,sql:string,params?:Array<relationalStore.ValueType>){try {await this.createDB(context)await this.store.executeSql(sql,params)} catch (e) {console.log("execDML执行异常",e)} finally {if(this.store){setTimeout(async ()=>{await this.store.close()},2000)}}}//查询操作,由调用处决定上下文对象async  execDQL(context:Context,sql:string,params?:Array<relationalStore.ValueType>){try {await this.createDB(context)let res =  await this.store.querySql(sql,params)return res}catch (e){console.log("execDQL执行异常",e);return {} as relationalStore.ResultSet} finally {if(this.store){setTimeout(async ()=>{await this.store.close()},2000)}}}
}

4.2、relationalStore单例模式封装(待更新)

五、首选项

5.1、preferences简单封装

import { preferences } from "@kit.ArkData"export class UserSettingClass{private  context:Contextconstructor(context:Context) {this.context=context}//获取首选项仓库private getStore():Promise<preferences.Preferences>{//TODO:这里USER_SETTING需要替换为你的首选项文件存储时的名字return preferences.getPreferences(this.context,USER_SETTING)}//TODO:通过getStore()获取首选项仓库,然后定义对应方法//TODO:以下是两个案例:1.广告数据的存取,用户令牌的存取// //广告的数据存取// async setUserAd(ad:AdvertClass):Promise<void>{//   const store = await this.getStore()//   await store.put(USER_SETTING_AD,JSON.stringify(ad))//   await store.flush()// }//// async getUserAd():Promise<AdvertClass>{//   const store = await this.getStore()//   const result =  await store.get(USER_SETTING_AD,JSON.stringify(defaultAd))//   return JSON.parse(result as string) as AdvertClass// }//// //用户的令牌存取// async setUserToken(token:string):Promise<void>{//   const store = await this.getStore()//   await store.put(TOKEN_KEY,token)//   await store.flush()// }//// async getUserToken():Promise<string>{//   const store = await this.getStore()//   const result =  await store.get(TOKEN_KEY,"")//   return result as string// }}

5.2、preferences单例模式封装

//首选项功能类
import { preferences } from "@kit.ArkData"
import { MessageInfoModel } from "../models/message"
import { emitter } from "@kit.BasicServicesKit"
import { DefaultUserList } from "../models/users"export class StoreClass{static context:Context //上下文static KEY:string = "Ding" //标识//初始化方法,固定好上下文对象,全局都用这一个//TODO:这里推荐在entryAbility中进行初始化,固定上下文static init(context:Context){StoreClass.context = context}//每一个聊天用户一个文件,而不是所有人都存在一个地方//通过用户id获取指定用户的首选项仓库//TODO:核心就是这个方法,如果不想所有东西保存在一个位置,那么就用参数+key(随便什么字符串)拼接private  static  getUserStoreById(userId:string):preferences.Preferences{return preferences.getPreferencesSync(StoreClass.context,{name:`${StoreClass.KEY}_${userId}`})}//TODO:下面的方法是一些案例,可以参考。不需要就删掉自行定义相关方法// //给指定用户添加一条消息// static async addChatMessage(userId:string,message:MessageInfoModel){//   //获取用户仓库//   const store =  StoreClass.getUserStoreById(userId)//   //添加(按照消息id,转字符串)//   store.putSync(message.id,JSON.stringify(message))//   //更新//   store.flushSync()//   //【发布通知,告知消息放好了】给对方说有新内容,你可以读了,不然对方不知道有新的消息需要更新//   //利用线程通讯,告知应用,消息发送好了//   emitter.emit(StoreClass.KEY)//// }//// //删除指定用户的消息// static async removeChatMessage(userId:string,messageId:string){//   //获取用户仓库//   const store =  StoreClass.getUserStoreById(userId)//   //删除//   store.deleteSync(messageId)//   //更新//   store.flushSync()//   //【发布通知】//   emitter.emit(StoreClass.KEY)// }//// //删除指定用户的所有信息// static async removeChatAllMessage(userId:string){//   //删除用户仓库//   preferences.deletePreferences(StoreClass.context,{name:`${StoreClass.KEY}_${userId}`})//   //【发布通知】//   emitter.emit(StoreClass.KEY)// }//// //获取指定用户的所有信息// static getChatAllMessage(userId:string):MessageInfoModel[]{//   //获取用户仓库//   const store =  StoreClass.getUserStoreById(userId)//   //获取所有//   const  all = store.getAllSync() as object//   //有吗?//   if(all){//     //系统方法,通过字符串内容实现数据集合//     const list: MessageInfoModel[] = Object.values(all).map((item:string)=>{//       return JSON.parse(item) as MessageInfoModel//     })//     //按照时间进行数据排序//     list.sort((a,b)=>{return a.sendTime-b.sendTime})//     return list//   }else {//     return []//   }//// }//// //获取所有用户最后一条消息【不需要参数】// //针对接收到新消息,只要有发布,我就获取所有// static async getAllChatLastMessage(){//   const  lastList:MessageInfoModel[] = []//   //从默认用户列表,提取所有用户信息//   DefaultUserList.forEach((user)=>{//     //按照用户id提取他所有的消息//     const  chatList = StoreClass.getChatAllMessage(user.user_id)//     //是否存在//     if(chatList.length>0){//       //最后一个消息,放入数组//       lastList.push(chatList[chatList.length-1])//     }//     //按照时间进行数据排序//     lastList.sort((a,b)=>{return a.sendTime-b.sendTime})//   })//   return lastList// }}

六、权限管理

6.1、权限管理封装

此工具类包含:检查权限\拉起权限弹窗\跳转系统权限设置

//之前需要授权管理,每次都要重新写代码
//所以我们先封装一个工具,后续可以一直使用
import { abilityAccessCtrl, bundleManager, common, Permissions } from '@kit.AbilityKit';class PermissionManager{/*** 检查有没有指定的权限* @param permissions 指定的权限的列表*/checkPermissions(permissions:Permissions[]){//权限管理器let manager = abilityAccessCtrl.createAtManager();//获取应用信息(通过系统方法获取)let appInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION)//获取应用唯一标识let tokenId = appInfo.appInfo.accessTokenId//校验这个token是否拥有权限let authResults = permissions.map((permission:Permissions)=>{return manager.checkAccessTokenSync(tokenId,permission)})//返回是否拥有权限return authResults.every((authResult:abilityAccessCtrl.GrantStatus)=>{return authResult === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED})}/*** 动态弹窗申请权限* @param permissions* @returns*/async requestPermissions(permissions:Permissions[]):Promise<boolean>{let mangager =  abilityAccessCtrl.createAtManager();let res = await mangager.requestPermissionsFromUser(getContext(),permissions)//选择结果let isAuth = res.authResults.every((authResult:abilityAccessCtrl.GrantStatus)=>{return authResult === abilityAccessCtrl.GrantStatus.PERMISSION_GRANTED})return isAuth}//如果出问题需要打开系统设置手动给权限//打开系统设置:权限管理页面openPermissionSettingPage() {//获取UIAbility上下文对象const context = getContext() as common.UIAbilityContext//应用信息(通过系统方法设置为当前本地应用对象)const appInfo = bundleManager.getBundleInfoForSelfSync(bundleManager.BundleFlag.GET_BUNDLE_INFO_WITH_APPLICATION)//打开系统设置窗口,进行配置context.startAbility({bundleName: 'com.huawei.hmos.settings',abilityName: 'com.huawei.hmos.settings.MainAbility',uri: 'application_info_entry',parameters: {pushParams: appInfo.name}})}
}export let permissionManager = new PermissionManager()

七、其他工具类

7.1、生成一个指定连续数值的数组

/*生成一个指定连续数值的数组* startNum:number 开始参数* endNum:number 结束参数* step:number=1 步长参数(默认为1)* */
export  function range(startNum:number,endNum:number,step:number=1){let arr:number[]=[];for(let i=startNum;i<=endNum;i+=step){arr.push(i)}return arr;
}

7.2、生成随机颜色(RGB)

export function getRandColorRGB(){const  red = Math.floor(Math.random()*256) //0~255的随机数const  green = Math.floor(Math.random()*256) //0~255的随机数const  blue = Math.floor(Math.random()*256) //0~255的随机数return `rgb(${red},${green},${blue})`
}

7.3、生成随机颜色(16进制)

export function getRandColorHEX(){const  result = Math.floor(Math.random()*16777216).toString(16) //16777216=256*256*256return "#"+result
}

7.4、格式化日期

export function formatDate(date:Date):string{let year= date.getFullYear()let month= date.getMonth()+1let day= date.getDate()let hour= date.getHours()let minter= date.getMinutes()let seconds= date.getSeconds()let monthStr = month<10?"0"+month:month.toString()let dayStr = day<10?"0"+day:day.toString()let hourStr = hour<10?"0"+hour:hour.toString()let minterStr = minter<10?"0"+minter:minter.toString()let secondsStr = seconds<10?"0"+seconds:seconds.toString()return `${year}-${monthStr}-${dayStr} ${hourStr}:${minterStr}:${secondsStr}`}

相关文章:

【Harmony】常用工具类封装

文章目录 一&#xff0c;简介二&#xff0c;网络请求工具类2.1、鸿蒙原生http封装2.2、第三方axios封装(需提前下载依赖) 三、录音笔相关工具类3.1、录音封装(录入)3.2、录音封装(放音/渲染)3.3、文件写入封装(针对录音/放音功能) 四、RDB关系型数据库4.1、relationalStore简答…...

大模型部署到本地就是私有化部署吗?

大模型私有化的定义需要从部署方式和数据/模型控制权两个维度来理解&#xff0c;不能简单地仅以“部署位置”或“数据训练”单一条件判断。以下是具体分析&#xff1a; 1. 大模型私有化的核心定义 根据知识库中的描述&#xff08;[1][2][3][8]&#xff09;&#xff1a; 私有化…...

C语言高频面试题——嵌入式系统中中断服务程序

在嵌入式系统中&#xff0c;中断服务程序&#xff08;ISR&#xff09;的设计需遵循严格的规则以确保系统稳定性和实时性。以下是对这段代码的分析及改进建议&#xff1a; 代码分析 __interrupt double compute_area (double radius) { double area PI * radius * radius; pri…...

JavaFX 实战:从零打造一个功能丰富的英文“刽子手”(Hangman)游戏

大家好&#xff01;今天我们要挑战一个经典的单词猜谜游戏——“刽子手”&#xff08;Hangman&#xff09;&#xff0c;并使用 JavaFX 这个强大的 GUI 工具包来赋予它现代化的交互体验。这个项目不仅有趣&#xff0c;而且是学习和实践 JavaFX 核心概念的绝佳途径&#xff0c;涵…...

第 2.1 节: 机器人仿真环境选择与配置 (Gazebo, MuJoCo, PyBullet)

在真实机器人硬件上进行开发和测试既耗时又存在风险&#xff08;硬件损坏、安全问题&#xff09;。机器人仿真环境提供了一个虚拟的沙盒&#xff0c;让开发者能够在计算机中模拟机器人的物理行为、传感器读数和环境互动&#xff0c;极大地加速了开发、测试和调试过程。特别是对…...

网络开发基础(游戏)之 粘包分包

粘&#xff08;nin&#xff09;包、分包 在网络通信中&#xff0c;TCP协议是面向流的协议&#xff0c;没有消息边界概念&#xff0c;粘包和分包是常见的问题。在某种情况下&#xff08;例如网络环境不稳定&#xff09;就会导致"粘包"和"分包"问题&#xf…...

联邦元学习实现个性化物联网的框架

随着数据安全和隐私保护相关法律法规的出台&#xff0c;需要直接在中央服务器上收集和处理数据的集中式解决方案&#xff0c;对于个性化物联网而言&#xff0c;训练各种特定领域场景的人工智能模型已变得不切实际。基于此&#xff0c;中山大学&#xff0c;南洋理工大学&#xf…...

使用 Nacos 的注意事项与最佳实践

&#x1f4f9; 背景 Nacos 凭借其强大&#x1f4aa;的服务发现、配置管理和服务管理能力&#xff0c;成为构建分布式系统的得力助手。然而&#xff0c;要充分发挥 Nacos 的优势&#xff0c;实现系统的高性能、高可用&#xff0c;掌握其使用过程中的注意事项和最佳实践至关…...

在Pytorch中使用Tensorboard可视化训练过程

【在Pytorch中使用Tensorboard可视化训练过程】 https://www.bilibili.com/video/BV1Qf4y1C7kz/?share_sourcecopy_web&vd_sourcef00bfb41b3b450c3767070ed82f30ac8 主要功能&#xff1a; 1.保存网络结构图 2.保存训练集的损失Loss&#xff0c;验证集的正确性Accuracy以…...

15.电感特性在EMC设计中的运用

电感特性在EMC设计中的运用 1. 共模电感与差模电感的差异2. 电感的高频等效特性![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/b4dc000672af4dd69a528450eb42cf10.png)3. 电感在EMC设计中的使用注意事项3.1 LC滤波计算3.2 并联型多级浪涌防护的电感退耦 1. 共模电感…...

代理设计模式:从底层原理到源代码 详解

代理设计模式&#xff08;Proxy Pattern&#xff09;是一种结构型设计模式&#xff0c;它通过创建一个代理对象来控制对目标对象的访问。代理对象充当客户端和目标对象之间的中介&#xff0c;允许在不修改目标对象的情况下添加额外的功能&#xff08;如权限控制、日志记录、延迟…...

25、简述.NET程序集(Assembly)

.NET 程序集&#xff08;Assembly&#xff09; .NET 程序集&#xff08;Assembly&#xff09; 是 .NET 应用程序的基本部署单元&#xff0c;包含以下核心内容&#xff1a; 类型与代码&#xff1a; 存储类、接口等类型的定义及实现&#xff08;以中间语言 IL 形式&#xff09;。…...

JavaScript 笔记 --- part 5 --- Web API (part 3)

(webAPI part3) BOM 操作 JS 执行机制 javascript 是单线程的, 也就是说, 只能同时执行一个任务。 为了解决这个问题, 利用多核 CPU 的计算能力, HTML5 提出 Web Worker API, 允许 JavaScript 脚本创建多个线程, 并将任务分配给这些线程。 于是, JS 出现了同步和异步的概念。…...

HCIP(OSPF)(3)

OSPF 报文结构 公共头部&#xff1a;包含版本&#xff08;8bit&#xff09;、类型&#xff08;8bit&#xff09;、报文长度&#xff08;16bit&#xff09;、路由器 ID&#xff08;32bit&#xff09;、区域 ID&#xff08;32bit&#xff09;、校验和&#xff08;16bit&#xff0…...

Docker:重塑应用开发与部署的未来[特殊字符]

Docker&#xff1a;重塑应用开发与部署的未来&#x1f680; 在数字化转型的浪潮中&#x1f30a;&#xff0c;应用开发与部署面临着诸多挑战&#xff0c;如环境一致性差、资源利用率低、运维复杂等。而Docker&#xff0c;作为容器技术领域的明星产品&#x1f31f;&#xff0c;凭…...

逻辑回归:损失和正则化技术的深入研究

逻辑回归&#xff1a;损失和正则化技术的深入研究 引言 逻辑回归是一种广泛应用于分类问题的统计模型&#xff0c;尤其在机器学习领域中占据着重要的地位。尽管其名称中包含"回归"&#xff0c;但逻辑回归本质上是一种分类算法。它的核心思想是在线性回归的基础上添…...

如何改电脑网络ip地址完整教程

更改电脑的网络IP地址以满足特定的网络需求&#xff0c;本文将为您提供一份详细的步骤指南。其实&#xff0c;改变IP地址并不是一件复杂的事&#xff0c;能解决因为IP限制带来的麻烦。以下是操作指南&#xff1a; 方法一&#xff1a;Windows 系统&#xff0c;通过图形界面修改 …...

Scenario Dreamer:用于生成驾驶模拟环境的矢量化潜扩散模型

25年3月来自加拿大 Mila AI研究院、蒙特利尔大学、蒙特利尔理工、普林斯顿、加拿大 CIFAR AI Chair 计划和 Torc 机器人公司的论文“Scenario Dreamer: Vectorized Latent Diffusion for Generating Driving Simulation Environments”。 Scenario Dreamer&#xff0c;是一个完…...

# 基于PyTorch的食品图像分类系统:从训练到部署全流程指南

基于PyTorch的食品图像分类系统&#xff1a;从训练到部署全流程指南 本文将详细介绍如何使用PyTorch框架构建一个完整的食品图像分类系统&#xff0c;涵盖数据预处理、模型构建、训练优化以及模型保存与加载的全过程。 1. 系统概述 本系统实现了一个基于卷积神经网络(CNN)的…...

【MCP Node.js SDK 全栈进阶指南】初级篇(1):MCP开发环境搭建详解

引言 Model Context Protocol (MCP) 是一种开放标准,旨在规范模型与应用程序之间的交互方式。本文作为MCP TypeScript-SDK系列的第一篇,将详细介绍如何搭建MCP开发环境,包括Node.js与TypeScript环境配置、SDK安装、开发工具推荐以及项目结构设计,帮助你快速入门MCP应用开发…...

unity脚本-FBX自动化模型面数校验

根据目前模型资源平均面数预算进行脚本制作&#xff0c;自动化校验模型面数是否符合规范。 *注&#xff1a;文件格式为.cs。需要放置在unity资源文件夹Assets>Editor下。 测试效果&#xff08;拖一个fbx文件进unity时自动检测&#xff09;&#xff1a; 以下为完整代码 us…...

压力容器的优化设计

1 优化设计概述 优化设计是一种寻找确定最优设计方案的技术。所谓“最优设计”&#xff0c;指的是一种方案可以满足所有的设计要求&#xff0c;而且所需的支出&#xff08;如重量&#xff0c;面积&#xff0c;体积&#xff0c;应力&#xff0c;费用等&#xff09;最小。也就是…...

在Windows上安装Git

一、安装 Git 下载 Git地址&#xff1a;Git - Downloads (git-scm.com) 1、在页面中找到适用于 Windows 系统的最新版本安装包&#xff08;通常为.exe 格式文件&#xff09;&#xff0c;点击下载链接。 出于访问Git官网需要科学上网&#xff0c;不会的可以私信我要软件包&…...

python包管理器,conda和uv 的区别

python包管理器&#xff0c;conda和uv 的区别 以下是 conda 和 uv 在 Python 包管理中的深度对比&#xff0c;结合知识库内容进行分析&#xff1a; 1. 核心设计理念 conda 以“环境为中心”&#xff0c;强调跨语言支持&#xff08;如 Python、R、Julia&#xff09;和严格的依赖…...

Oracle在ERP市场击败SAP

2024年&#xff0c;甲骨文&#xff08;Oracle&#xff09;以87亿美元的ERP收入和6.63%的市场份额&#xff0c;首次超越SAP&#xff0c;成为全球最大的ERP应用软件供应商&#xff0c;结束了SAP自上世纪80年代以来在该领域的长期霸主地位。据APPS RUN THE WORLD的市场调研&#x…...

Kafka 消息积压监控和报警配置的详细步骤

Kafka 消息积压监控和报警配置的详细步骤示例&#xff0c;涵盖常用工具&#xff08;如 Prometheus Grafana、云服务监控&#xff09;和自定义脚本方法&#xff1a; 一、监控配置 方法1&#xff1a;使用 Prometheus Grafana kafka-exporter 步骤1&#xff1a;部署 kafka-ex…...

记录一次使用面向对象的C语言封装步进电机驱动

简介 (2025/4/21) 本库对目前仅针对TB6600驱动下的42步进电机的基础功能进行了一定的封装, 也是我初次尝试以面向对象的思想去编写嵌入式代码, 和直流电机的驱动步骤相似在调用stepmotor_attach()函数和stepmotor_init()函数之后仅通过结构体数组stepm然后指定枚举变量中的id即…...

QTextDocument 入门

一、QTextDocument QTextDocument 是 Qt 中用于处理富文本文档的核心类,支持文本格式、图片、表格等复杂内容。 1. QTextDocument 入门 1.1 基本概念 QTextDocument 是 Qt 中用于处理富文本内容的核心类,它提供了: 结构化文本存储(段落、列表、表格等) 文本格式支持(…...

Arthas进阶用法

目录 查看已加载的类反编译代码动态执行代码排查 HTTP 请求问题热更新代码获取 Spring Context 并操作查看 JVM 信息自定义命令Web Console重置与退出 查看已加载的类 sc 命令 &#xff1a;可以查找所有 JVM 已经加载到的类。如果搜索的是接口&#xff0c;还会搜索所有的实现类…...

三生原理与现有密码学的核心区别?

AI辅助创作&#xff1a; 三生原理与现有密码学的核心区别 一、‌哲学基础与设计逻辑‌ ‌动态生成 vs 静态分析‌ 三生原理以“阴阳动态平衡”为核心&#xff0c;通过参数化生成&#xff08;如素数构造中的阴阳元联动公式&#xff09;模拟系统演化过程&#xff0c;而现有密码…...

定义python中的函数和类

1.函数 在Python中&#xff0c;定义一个函数要使用def语句&#xff0c;依次写出函数名、括号、括号中的参数和冒号:&#xff0c;然后&#xff0c;在缩进块中编写函数体&#xff0c;函数的返回值用return语句返回 1.1 定义函数 def showshow(sex):if sex1:return manelse:retu…...

明远智睿2351开发板四核1.4G Linux处理器:驱动创新的引擎

在科技日新月异的今天&#xff0c;创新成为了推动社会进步的核心动力。而在这场创新的浪潮中&#xff0c;一款性能卓越、功能全面的处理器无疑是不可或缺的引擎。今天&#xff0c;我们介绍的这款四核1.4G处理器搭配Linux系统的组合&#xff0c;正是这样一款能够驱动未来创新的强…...

【前端】【业务逻辑】【面试】JSONP处理跨域原理与封装

&#x1f9e0; 一、JSONP 是什么&#xff1f; 项目内容&#x1f4cc; 全称JSON with Padding&#x1f4cd; 用途跨域请求数据的一种方式&#xff0c;绕过同源策略&#x1f4e6; 本质通过 <script> 标签加载远程 JS 文件&#xff0c;这个文件执行一个回调函数并传入数据 …...

深入探索RAG:用LlamaIndex为大语言模型扩展知识,实现智能检索增强生成

大型语言模型&#xff08;LLM&#xff09;&#xff0c;如ChatGPT和Llama&#xff0c;在回答问题方面表现出色&#xff0c;但它们的知识仅限于训练时所获取的信息。它们无法访问私有数据&#xff0c;也无法在训练截止日期之后学习新知识。那么&#xff0c;核心问题就是……我们如…...

移远通信智能模组助力东成“无边界智能割草机器人“闪耀欧美市场

2025年4月21日&#xff0c;移远通信宣布&#xff0c;旗下SC206E-EM智能模组已成功应用于江苏东成电动工具有限公司旗下的DCK TERRAINA无边界智能割草机器人。 这款智能模组高度集成计算、通信、定位等多元能力&#xff0c;以小型化、低功耗、实时性强和低成本等综合优势&#…...

测试-时间规模化定律可以改进世界基础模型吗?

25年3月来自 UT Austin、UW Madison 和 Nvidia 的论文“Can Test-Time Scaling Improve World Foundation Model?”。 世界基础模型&#xff08;WFM&#xff09;通过根据当前的观察和输入预测未来状态来模拟物理世界&#xff0c;已成为许多物理智能&#xff08;PI&#xff09…...

VMwaer虚拟机复制粘贴、ROS系统安装

一、VMwaer虚拟机复制粘贴设置&#xff1a;设置完记得重启VMwaer 1.首先确定 虚拟机设置-->选项-->客户机隔离-->勾选 启用拖放 启用复制粘贴 2.如果还是不能粘贴 可能是 没有 VMware Tools 可参考 怎么在linux安装vmware tools-CSDN博客 设置完记得重启VMwaer。…...

安装 vmtools

第2章 安装 vmtools 1.安装 vmtools 的准备工作 1&#xff09;现在查看是否安装了 gcc ​ 查看是否安装gcc 打开终端 输入 gcc - v 安装 gcc 链接&#xff1a;https://blog.csdn.net/qq_45316173/article/details/122018354?ops_request_misc&request_id&biz_id10…...

HCIP(综合实验2)

1.实验拓补图 2.实验要求 1.根据提供材料划分VLAN以及IP地址&#xff0c;PC1/PC2属于生产一部员工划分VLAN10,PC3属于生产二部划分VLAN20 2.HJ-1HJ-2交换机需要配置链路聚合以保证业务数据访问的高带宽需求 3.VLAN的放通遵循最小VLAN透传原则 4.配置MSTP生成树解决二层环路问题…...

机器学习第一篇 线性回归

数据集&#xff1a;公开的World Happiness Report | Kaggle中的happiness dataset2017. 目标&#xff1a;基于GDP值预测幸福指数。&#xff08;单特征预测&#xff09; 代码&#xff1a; 文件一&#xff1a;prepare_for_traning.py """用于科学计算的一个库…...

Spark-Streaming简介及核心编程

一、核心概念&#xff1a; 1.Spark-Streaming 是流式数据处理框架&#xff0c;基于 **DStream&#xff08;离散化流&#xff09;** 抽象&#xff0c;将实时数据划分为多个时间区间的 RDD 序列。 DStream 本质是RDD 序列&#xff0c;每个时间区间数据对应一个 RDD。 2.特点&a…...

优化提示词方面可以使用的数学方法理论:信息熵,概率论 ,最优化理论

优化提示词方面可以使用的数学方法理论:信息熵,概率论 ,最优化理论 目录 优化提示词方面可以使用的数学方法理论:信息熵,概率论 ,最优化理论信息论信息熵明确问题主题提供具体细节限定回答方向规范语言表达概率论最优化理论信息论 原理:信息论中的熵可以衡量信息的不确定性。…...

Sqlserver安全篇之_Sqlcmd命令使用windows域账号认证sqlserver遇到问题如何处理的案例

sqlcmd https://learn.microsoft.com/zh-cn/sql/tools/sqlcmd/sqlcmd-connect-database-engine?viewsql-server-ver16 sqlcmd -S指定的数据库连接字符串必须有对应的有效的SPN信息&#xff0c;否则会报错SSPI Provider: Server not found in Kerberos database. 正常连接 1、…...

基于华为云 ModelArts 的在线服务应用开发(Requests 模块)

基于华为云 ModelArts 的在线服务应用开发&#xff08;Requests 模块&#xff09; 一、本节目标 了解并掌握 Requests 模块的特点与用法学会通过 PythonRequests 访问华为云 ModelArts 在线推理服务熟悉 JSON 模块在 Python 中的数据序列化与反序列化掌握 Python 文件 I/O 的基…...

Graph Database Self-Managed Neo4j 知识图谱存储实践1:安装和基础知识学习

Neo4j 是一个原生图数据库&#xff0c;这意味着它在存储层实现了真正的图模型。它不是在其他技术之上使用“图抽象”&#xff0c;而是以您在白板上绘制想法的相同方式在Neo4j中存储数据。 自2007年以来&#xff0c;Neo4j已经发展成为一个丰富的工具、应用程序和库的生态系统。…...

【Python进阶】VSCode Python开发完全指南:从环境配置到高效调试

目录 前言技术背景与价值当前技术痛点解决方案概述目标读者说明 一、技术原理剖析核心概念图解核心作用讲解关键技术模块说明技术选型对比 二、实战演示环境配置要求核心代码实现案例1&#xff1a;配置虚拟环境案例2&#xff1a;智能代码补全案例3&#xff1a;调试配置 运行结果…...

vscode:Live Server Preview插件

这个插件不用另外打开浏览器&#xff1b;它是直接在Vscode里面预览html的&#xff0c;并且是自动实时更新的&#xff0c;不用不停地CtrlS保存查看 使用方法&#xff1a;F1 -> 弹出一个窗口输入live&#xff0c;选择即可。 运行结果如下&#xff1a;...

关于在Springboot中设置时间格式问题

目录 1-设置全局时间格式1.Date类型的时间2.JDK8时间3.使Date类和JDK8时间类统统格式化时间 2-关于DateTimeFormat注解 1-设置全局时间格式 1.Date类型的时间 对于老项目来说&#xff0c;springboot中许多类使用的是Date类型的时间&#xff0c;没有用到LocalDateTime等JDK8时…...

双周报Vol.70: 运算符重载语义变化、String API 改动、IDE Markdown 格式支持优化...多项更新升级!

2025-04-21 语言更新 async 函数的调用处语法改为和 error 相同的 f!(..)&#xff0c;原语法 f!!(..) 将触发警告 运算符重载的语义从基于方法迁移到了基于 trait&#xff0c;以后重载运算符需要通过给 moonbitlang/core/builtin 中对应的 trait 添加 impl 的形式。各个运算符…...

AI 技术发展:从起源到未来的深度剖析

一、AI 的起源与早期发展​ 人工智能&#xff08;AI&#xff09;作为计算机科学的重要分支&#xff0c;其诞生可以追溯到 20 世纪中叶。1943 年&#xff0c;艾伦・图灵提出图灵机的概念&#xff0c;为计算机科学和 AI 理论奠定了基础。1950 年&#xff0c;图灵又提出著名的图灵…...