当前位置: 首页 > 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}`}

相关文章:

  • Kafka 面试,java实战贴
  • ARM Cortex-M (STM32)如何调试HardFault
  • 【美化vim】
  • kafka auto.offset.reset详解
  • QML ColorDialog:组件应用详解
  • 3.1 WPF使用MaterialDesign的介绍1
  • YOLO算法的革命性升级:深度解析Repulsion损失函数在目标检测中的创新应用
  • 三餐四季、灯火阑珊
  • Sentinel源码—8.限流算法和设计模式总结二
  • nodejs模块暴露数据的方式,和引入(导入方式)方式
  • 使用Python+OpenCV将多级嵌套文件夹下的视频文件抽帧
  • mybatis-plus开发orm
  • [Git] Git Stash 命令详解
  • Linux-skywalking部署步骤并且添加探针
  • 【设计模式】深入解析代理模式(委托模式):代理模式思想、静态模式和动态模式定义与区别、静态代理模式代码实现
  • 云原生 - Service Mesh
  • 基于SpringBoot的高校学习讲座预约系统-项目分享
  • 滑动窗口学习
  • 【Linux网络】各版本TCP服务器构建 - 从理解到实现
  • 基于Python+Pytest实现自动化测试(全栈实战指南)
  • 几百元的工资优势已不能吸引人才流动,江苏多地探讨“抢人”高招
  • 罗马教皇方济各去世,享年88岁
  • 发布近百条《原神》涉密游戏内容,游戏资讯网站被判赔33万元
  • AI时代教育如何变革?上海首批 “标准化家长学校”出炉
  • 对话地铁读书人|来自法学副教授的科普:读书日也是版权日
  • 老年人越“懒”越健康,特别是这5种“懒”