HarmonyOS应用六之应用程序进阶二

server/2024/12/22 14:43:21/

目录:

    • 一、进度条通知
    • 二、闹钟提醒
      • 2.1、在module.json5配置文件中开启权限
      • 2.2、导入后台代理提醒reminderAgentManager模块,将此模块命名为reminderAgentManager
      • 2.3、如果是新增提醒,实现步骤如下:
    • 3、Native C++交互
    • 4、第三方库的基本使用

一、进度条通知

/** Copyright (c) 2023 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at**     http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import { common } from '@kit.AbilityKit';
import { promptAction } from '@kit.ArkUI';
import { notificationManager } from '@kit.NotificationKit';
import { createWantAgent, publishNotification, openNotificationPermission } from '../common/utils/NotificationUtil';
import { getStringByRes } from '../common/utils/ResourseUtil';
import Logger from '../common/utils/Logger';
import CommonConstants, { DOWNLOAD_STATUS } from '../common/constants/CommonConstants';@Entry
@Component
struct MainPage {@State downloadStatus: number = DOWNLOAD_STATUS.INITIAL;@State downloadProgress: number = 0;private context = getContext(this) as common.UIAbilityContext;private isSupport: boolean = true;private notificationTitle: string = '';private wantAgentObj: object = new Object();private interval: number = -1;aboutToAppear() {//打开通知权限openNotificationPermission();let bundleName = this.context.abilityInfo.bundleName;let abilityName = this.context.abilityInfo.name;//创建want行为意图createWantAgent(bundleName, abilityName).then(want => {this.wantAgentObj = want;}).catch((err: Error) => {Logger.error(`getWantAgent fail, err: ${JSON.stringify(err)}`);});//判断当前系统知否支持下载通知模版notificationManager.isSupportTemplate('downloadTemplate').then(isSupport => {if (!isSupport) {promptAction.showToast({message: $r('app.string.invalid_button_toast')})}this.isSupport = isSupport;});}
//此方法监听页面返回,此处是页面返回后调用取消下载的方法onBackPress() {this.cancel();}build() {Column() {Text($r('app.string.title')).fontSize($r('app.float.title_font_size')).fontWeight(CommonConstants.FONT_WEIGHT_LAGER).width(CommonConstants.TITLE_WIDTH).textAlign(TextAlign.Start).margin({top: $r('app.float.title_margin_top'),bottom: $r('app.float.title_margin_top')})Row() {Column() {Image($r('app.media.ic_image')).objectFit(ImageFit.Fill).width($r('app.float.card_image_length')).height($r('app.float.card_image_length'))}.layoutWeight(CommonConstants.IMAGE_WEIGHT).height(CommonConstants.FULL_LENGTH).alignItems(HorizontalAlign.Start)Column() {Row() {Text(CommonConstants.DOWNLOAD_FILE).fontSize($r('app.float.name_font_size')).textAlign(TextAlign.Center).fontWeight(CommonConstants.FONT_WEIGHT_LAGER).lineHeight($r('app.float.name_font_height'))Text(`${this.downloadProgress}%`).fontSize($r('app.float.normal_font_size')).lineHeight($r('app.float.name_font_height')).opacity(CommonConstants.FONT_OPACITY)}.justifyContent(FlexAlign.SpaceBetween).width(CommonConstants.FULL_LENGTH)Progress({value: this.downloadProgress,total: CommonConstants.PROGRESS_TOTAL}).width(CommonConstants.FULL_LENGTH)Row() {Text(CommonConstants.FILE_SIZE).fontSize($r('app.float.normal_font_size')).lineHeight($r('app.float.name_font_height')).opacity(CommonConstants.FONT_OPACITY)if (this.downloadStatus === DOWNLOAD_STATUS.INITIAL) {this.customButton($r('app.string.button_download'), (): Promise<void> => this.start())} else if (this.downloadStatus === DOWNLOAD_STATUS.DOWNLOADING) {Row() {this.cancelButton()this.customButton($r('app.string.button_pause'), (): Promise<void> => this.pause())}} else if (this.downloadStatus === DOWNLOAD_STATUS.PAUSE) {Row() {this.cancelButton()this.customButton($r('app.string.button_resume'), (): Promise<void> => this.resume())}} else {this.customButton($r('app.string.button_finish'), (): void => this.open())}}.width(CommonConstants.FULL_LENGTH).justifyContent(FlexAlign.SpaceBetween)}.layoutWeight(CommonConstants.CARD_CONTENT_WEIGHT).height(CommonConstants.FULL_LENGTH).justifyContent(FlexAlign.SpaceBetween)}.width(CommonConstants.CARD_WIDTH).height($r('app.float.card_height')).backgroundColor(Color.White).borderRadius($r('app.float.card_border_radius')).justifyContent(FlexAlign.SpaceBetween).padding($r('app.float.card_padding'))}.width(CommonConstants.FULL_LENGTH).height(CommonConstants.FULL_LENGTH).backgroundColor($r('app.color.index_background_color'))}/*** Start the timer and send notification.(下载逻辑)*/download() {this.interval = setInterval(async () => {if (this.downloadProgress === CommonConstants.PROGRESS_TOTAL) {this.notificationTitle = await getStringByRes($r('app.string.notification_title_finish'), this);this.downloadStatus = DOWNLOAD_STATUS.FINISHED;clearInterval(this.interval);} else {this.downloadProgress += CommonConstants.PROGRESS_SPEED;}if (this.isSupport) {publishNotification(this.downloadProgress, this.notificationTitle, this.wantAgentObj);}}, CommonConstants.UPDATE_FREQUENCY);}/*** Click to download.(开始下载)*/async start() {this.notificationTitle = await getStringByRes($r('app.string.notification_title_download'), this);this.downloadStatus = DOWNLOAD_STATUS.DOWNLOADING;this.downloadProgress = 0;this.download();}/*** Click pause.(暂停逻辑)*/async pause() {this.notificationTitle = await getStringByRes($r('app.string.notification_title_pause'), this);clearInterval(this.interval);this.downloadStatus = DOWNLOAD_STATUS.PAUSE;if (this.isSupport) {publishNotification(this.downloadProgress, this.notificationTitle, this.wantAgentObj);}}/*** Click resume.(继续下载逻辑)*/async resume() {this.notificationTitle = await getStringByRes($r('app.string.notification_title_download'), this);this.download();this.downloadStatus = DOWNLOAD_STATUS.DOWNLOADING;}/*** Click cancel.(取消逻辑)*/async cancel() {this.downloadProgress = 0;clearInterval(this.interval);this.downloadStatus = DOWNLOAD_STATUS.INITIAL;notificationManager.cancel(CommonConstants.NOTIFICATION_ID);}/*** Open file*/open() {promptAction.showToast({message: $r('app.string.invalid_button_toast')})}@BuildercustomButton(textResource: Resource, click: Function = () => {}) {Button(textResource).backgroundColor($r('app.color.button_color')).buttonsStyle().onClick(() => {click();})}@BuildercancelButton() {Button($r('app.string.button_cancel')).buttonsStyle().backgroundColor($r('app.color.cancel_button_color')).fontColor($r('app.color.button_color')).margin({ right: $r('app.float.button_margin') }).onClick(() => {this.cancel();})}
}@Extend(Button)
function buttonsStyle() {.constraintSize({ minWidth: $r('app.float.button_width') }).height($r('app.float.button_height')).borderRadius($r('app.float.button_border_radius')).fontSize($r('app.float.button_font_size'))
}

NotificationUtil.ets:

/** Copyright (c) 2023 Huawei Device Co., Ltd.* Licensed under the Apache License, Version 2.0 (the "License");* you may not use this file except in compliance with the License.* You may obtain a copy of the License at** http://www.apache.org/licenses/LICENSE-2.0** Unless required by applicable law or agreed to in writing, software* distributed under the License is distributed on an "AS IS" BASIS,* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.* See the License for the specific language governing permissions and* limitations under the License.*/import { wantAgent } from '@kit.AbilityKit';
import { notificationManager } from '@kit.NotificationKit';
import CommonConstants from '../constants/CommonConstants';
import Logger from '../utils/Logger';/*** Obtains the WantAgent of an application.** @returns WantAgent of an application.*///创建行为意图并拉起拉起UIAbility
export function createWantAgent(bundleName: string, abilityName: string): Promise<object> {let wantAgentInfo = {wants: [{bundleName: bundleName,abilityName: abilityName}],operationType: wantAgent.OperationType.START_ABILITY,requestCode: 0,wantAgentFlags: [wantAgent.WantAgentFlags.CONSTANT_FLAG]} as wantAgent.WantAgentInfo;return wantAgent.getWantAgent(wantAgentInfo);
}/*** Publish notification.** @param progress Download progress* @param title Notification title.* @param wantAgentObj The want of application.*///发布下载通知模版
export function publishNotification(progress: number, title: string, wantAgentObj: object) {let template:notificationManager.NotificationTemplate = {name: 'downloadTemplate',data: {title:  `${title}`,fileName:  `${title}${CommonConstants.DOWNLOAD_FILE}`,progressValue: progress,progressMaxValue: CommonConstants.PROGRESS_TOTAL,isProgressIndeterminate: false}};let notificationRequest: notificationManager.NotificationRequest = {id: CommonConstants.NOTIFICATION_ID,notificationSlotType: notificationManager.SlotType.CONTENT_INFORMATION,// Construct a progress bar template. The name field must be set to downloadTemplate.template: template,content: {notificationContentType: notificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,normal: {title: `${title}${CommonConstants.DOWNLOAD_FILE}`,text: ' ',additionalText: `${progress}%`}},wantAgent: wantAgentObj};notificationManager.publish(notificationRequest).catch((err: Error) => {Logger.error(`[ANS] publish failed,message is ${err}`);});
}/*** open notification permission*///请求通知权限
export function openNotificationPermission() {notificationManager.requestEnableNotification().then(() => {Logger.info('Enable notification success');}).catch((err:Error) => {Logger.error('Enable notification failed because ' + JSON.stringify(err));});
}

二、闹钟提醒

2.1、在module.json5配置文件中开启权限

"module": {// ..."requestPermissions": [{"name": "ohos.permission.PUBLISH_AGENT_REMINDER"}]
}

2.2、导入后台代理提醒reminderAgentManager模块,将此模块命名为reminderAgentManager

import { reminderAgentManager } from '@kit.BackgroundTasksKit';

2.3、如果是新增提醒,实现步骤如下:

  • 用reminderAgent.ReminderRequest类定义提醒实例。
import { reminderAgentManager } from '@kit.BackgroundTasksKit';
// ...export class ReminderService {public addReminder(alarmItem: ReminderItem, callback?: (reminderId: number) => void) {let reminder = this.initReminder(alarmItem);reminderAgentManager.publishReminder(reminder, (err, reminderId) => {if (callback != null) {callback(reminderId);}});}private initReminder(item: ReminderItem): reminderAgentManager.ReminderRequestAlarm {return {reminderType: item.remindType,hour: item.hour,minute: item.minute,daysOfWeek: item.repeatDays,title: item.name,ringDuration: item.duration * CommonConstants.DEFAULT_TOTAL_MINUTE,snoozeTimes: item.intervalTimes,timeInterval: item.intervalMinute * CommonConstants.DEFAULT_TOTAL_MINUTE,actionButton: [{title: '关闭',type: reminderAgentManager.ActionButtonType.ACTION_BUTTON_TYPE_CLOSE},// ...],wantAgent: {pkgName: CommonConstants.BUNDLE_NAME,abilityName: CommonConstants.ABILITY_NAME},notificationId: item.notificationId,// ...}}// ...
}
  • 发布提醒。

import { reminderAgentManager } from '@kit.BackgroundTasksKit';
// ...export class ReminderService {public addReminder(alarmItem: ReminderItem, callback?: (reminderId: number) => void) {let reminder = this.initReminder(alarmItem);reminderAgentManager.publishReminder(reminder, (err, reminderId) => {if (callback != null) {callback(reminderId);}});}private initReminder(item: ReminderItem): reminderAgentManager.ReminderRequestAlarm {// ...}// ...
}

3、Native C++交互

  • 设置模块注册信息

ArkTS侧import native模块时,会加载其对应的so。加载so时,首先会调用napi_module_register方法,将模块注册到系统中,并调用模块初始化函数。

napi_module有两个关键属性:一个是.nm_register_func,定义模块初始化函数;另一个是.nm_modname,定义模块的名称,也就是ArkTS侧引入的so库的名称,模块系统会根据此名称来区分不同的so。

// entry/src/main/cpp/hello.cpp// 准备模块加载相关信息,将上述Init函数与本模块名等信息记录下来。
static napi_module demoModule = {.nm_version = 1,.nm_flags = 0,.nm_filename = nullptr,.nm_register_func = Init,.nm_modname = "entry",.nm_priv = nullptr,.reserved = {0},
};// 加载so时,该函数会自动被调用,将上述demoModule模块注册到系统中。
extern "C" __attribute__((constructor)) void RegisterDemoModule() { napi_module_register(&demoModule);}
  • 模块初始化

实现ArkTS接口与C++接口的绑定和映射。

// entry/src/main/cpp/hello.cpp
EXTERN_C_START
// 模块初始化
static napi_value Init(napi_env env, napi_value exports) {// ArkTS接口与C++接口的绑定和映射napi_property_descriptor desc[] = {{"callNative", nullptr, CallNative, nullptr, nullptr, nullptr, napi_default, nullptr},{"nativeCallArkTS", nullptr, NativeCallArkTS, nullptr, nullptr, nullptr, napi_default, nullptr},};// 在exports对象上挂载CallNative/NativeCallArkTS两个Native方法napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);return exports;
}
EXTERN_C_END// 模块基本信息
static napi_module demoModule = {.nm_version = 1,.nm_flags = 0,.nm_filename = nullptr,.nm_register_func = Init,.nm_modname = "entry",.nm_priv = nullptr,.reserved = {0},
};
  • 在index.d.ts文件中,提供JS侧的接口方法。
// entry/src/main/cpp/types/libentry/index.d.ts
export const callNative: (a: number, b: number) => number;
export const nativeCallArkTS: (cb: (a: number) => number) => number;
在oh-package.json5文件中将index.d.ts与cpp文件关联起来。{"name": "libentry.so","types": "./index.d.ts","version": "","description": "Please describe the basic information."
}
  • 在CMakeLists.txt文件中配置CMake打包参数。
# entry/src/main/cpp/CMakeLists.txt
cmake_minimum_required(VERSION 3.4.1)
project(MyApplication2)set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})include_directories(${NATIVERENDER_ROOT_PATH}${NATIVERENDER_ROOT_PATH}/include)# 添加名为entry的库
add_library(entry SHARED hello.cpp)
# 构建此可执行文件需要链接的库
target_link_libraries(entry PUBLIC libace_napi.z.so)
  • 实现Native侧的CallNative以及NativeCallArkTS接口。具体代码如下:
// entry/src/main/cpp/hello.cpp
static napi_value CallNative(napi_env env, napi_callback_info info)
{size_t argc = 2;// 声明参数数组napi_value args[2] = {nullptr};// 获取传入的参数并依次放入参数数组中napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);// 依次获取参数double value0;napi_get_value_double(env, args[0], &value0);double value1;napi_get_value_double(env, args[1], &value1);// 返回两数相加的结果napi_value sum;napi_create_double(env, value0 + value1, &sum);return sum;
}static napi_value NativeCallArkTS(napi_env env, napi_callback_info info)
{    size_t argc = 1;// 声明参数数组napi_value args[1] = {nullptr};// 获取传入的参数并依次放入参数数组中napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);// 创建一个int,作为ArkTS的入参napi_value argv = nullptr;    napi_create_int32(env, 2, &argv );// 调用传入的callback,并将其结果返回napi_value result = nullptr;napi_call_function(env, nullptr, args[0], 1, &argv, &result);return result;
}
  • ArkTS侧调用C/C++方法实现

ArkTS侧通过import引入Native侧包含处理逻辑的so来使用C/C++的方法。

// entry/src/main/ets/pages/Index.ets
// 通过import的方式,引入Native能力。
import nativeModule from 'libentry.so'@Entry
@Component
struct Index {@State message: string = 'Test Node-API callNative result: ';@State message2: string = 'Test Node-API nativeCallArkTS result: ';build() {Row() {Column() {// 第一个按钮,调用add方法,对应到Native侧的CallNative方法,进行两数相加。Text(this.message).fontSize(50).fontWeight(FontWeight.Bold).onClick(() => {this.message += nativeModule.callNative(2, 3);})// 第二个按钮,调用nativeCallArkTS方法,对应到Native的NativeCallArkTS,在Native调用ArkTS function。Text(this.message2).fontSize(50).fontWeight(FontWeight.Bold).onClick(() => {this.message2 += nativeModule.nativeCallArkTS((a: number)=> {return a * 2;});})}.width('100%')}.height('100%')}
}

具体的和c++交互的流程如上,具体的c++代码可以自行参考去实现。

4、第三方库的基本使用

  • 安装@ohos/lottie

通过ohpm执行对应的指令,将lottie安装到项目中。

ohpm install @ohos/lottie
  • 卸载@ohos/lottie

通过ohpm执行卸载指令,将lottie从项目中删除,其程序包和配置信息将会从项目中移除。

ohpm uninstall @ohos/lottie
  • 构建Canvas画布

@ohos/lottie解析JSON动画文件的数据需要基于Canvas 画布进行2D渲染,所以在加载JSON动画之前,要先初始化渲染上下文,并在画面中创建Canvas画布区域,将对应的渲染上下文renderingContext传递给Canvas。

// 初始化渲染上下文  
private renderingSettings: RenderingContextSettings = new RenderingContextSettings(true) // 设置开启抗锯齿
private renderingContext: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.renderingSettings)  // 创建2D渲染上下文// 加载Canvas画布   
Canvas(this.renderingContext)...
  • 使用@ohos/lottie加载JSON动画
    加载JSON动画需要用到loadAnimation方法,在方法中需配置相应的初始设置,包括渲染上下文、渲染方式以及JSON动画资源的路径等。可以直接使用lottie.loadAnimation方法,也可以用一个animationItem实例来接收返回的animationItem对象。
// 用animationItem实例接收
let animationItem = lottie.loadAnimation({container: this.renderingContext,            // 渲染上下文renderer: 'canvas',                          // 渲染方式loop: true,                                  // 是否循环播放,默认trueautoplay: true,                              // 是否自动播放,默认truepath: 'common/lottie/data.json',             // json路径})      lottie.loadAnimation({                               // 或者直接使用container: this.renderingContext,            // 渲染上下文renderer: 'canvas',                          // 渲染方式loop: true,                                  // 是否循环播放,默认trueautoplay: true,                              // 是否自动播放,默认truepath: 'common/lottie/data.json',             // json路径})
  • @ohos/lottie控制动画

@ohos/lottie内封装了包括状态控制,进度控制,播放设置控制和属性控制等多个API,用户可以利用这些API完成对动画的控制,实现更加灵活的交互效果。

// 播放、暂停、停止、销毁  可以使用lottie,也可以使用animationItem实例进行控制
lottie.play();        // 从目前停止的帧开始播放
lottie.stop();        // 停止播放,回到第0帧
lottie.pause();       // 暂停该动画,在当前帧停止并保持
lottie.togglePause(); // 切换暂停/播放状态
lottie.destroy();     // 删除该动画,移除相应的元素标签等。在unmount的时候,需要调用该方法// 播放进度控制
animationItem.goToAndStop(value, isFrame); // 跳到某个时刻/帧并停止。isFrame(默认false)指示value表示帧还是时间(毫秒)
animationItem.goToAndPlay(value, isFrame); // 跳到某个时刻/帧并进行播放
animationItem.goToAndStop(30, true);       // 例:跳转到第30帧并停止
animationItem.goToAndPlay(300);            // 例:跳转到第300毫秒并播放// 控制帧播放
animationItem.setSegment(5,15);             // 限定动画资源播放时的整体帧范围,即设置动画片段
animationItem.resetSegments(5,15);          // 重置播放的动画片段
animationItem.playSegments(arr, forceFlag); // arr可以包含两个数字或者两个数字组成的数组,forceFlag表示是否立即强制播放该片段
animationItem.playSegments([10,20], false); // 例:播放完之前的片段,播放10-20帧
animationItem.playSegments([[5,15],[20,30]], true); //例: 直接播放5-15帧和20-30帧// 动画基本属性控制
lottie.setSpeed(speed);         // 设置播放速度,speed为1表示正常速度
lottie.setDirection(direction); // 设置播放方向,1表示正向播放,-1表示反向播放// 获取动画帧数属性
animationItem.getDuration();    //获取动画时长

通过上述的引用第三方库后就可以使用第三方库里面的一些函数方法了,引用第三方库都可以使用这个方法去调用第三方库的函数。


http://www.ppmy.cn/server/129208.html

相关文章

低代码平台的缩写和使用方法是什么?蓝燕云低代码平台开发经验!

随着企业数字化转型的加速&#xff0c;低代码平台越来越受到欢迎。低代码平台可以极大地简化开发过程&#xff0c;使得非专业开发者也能够快速创建应用程序。然而&#xff0c;对于低代码平台&#xff0c;很多人还存在一些疑惑&#xff0c;尤其是在其缩写和具体使用方法方面。本…

单片机(学习)2024.10.8

ok家人们&#xff0c;国庆回来继续开始新的单片机的学习&#xff0c;这次学习的单片机芯片为STM32U575RIT6 计算机基础 IO逻辑 计算机系统中的高低电平逻辑1和0&#xff0c;数据在计算机中的存储、传输、运算都是以二进制形式进行的。数据的传输通过总线真正传递的是电信号&a…

力扣10.8

174. 地下城游戏 恶魔们抓住了公主并将她关在了地下城 dungeon 的 右下角 。地下城是由 m x n 个房间组成的二维网格。我们英勇的骑士最初被安置在 左上角 的房间里&#xff0c;他必须穿过地下城并通过对抗恶魔来拯救公主。 骑士的初始健康点数为一个正整数。如果他的健康点数…

在ES6中,数组新增扩展及其用法汇总

在ES6中&#xff0c;数组新增了多项扩展&#xff0c;极大提高了操作数组的便捷性。以下是一些常用的扩展及其用法&#xff1a; 1. Array.from() 用于从类数组对象或迭代器创建一个新的数组实例。这个方法可以接受两个参数&#xff1a; source (来源)&#xff1a;这是必须的参…

第五章:软件工程(5.5部署交付--5.7软件过程能力成熟度)

5.5 部署交付 5.5.1 软件部署 软件部署过程的主要特征有:过程覆盖度、过程可变更性、过程间协调和模型抽象。 已经提出一些抽象的软件部署模型&#xff0c;用于有效地指导部署过程&#xff0c;包括应用模型、组织模型、站点模型、产品模型、策略模型和部署模型。 软件部署模…

【JavaScript】JS核心语法及函数

文章目录 一、初识 JS二、JS 核心语法2-1 变量2-2 数据类型typeofString 对象 2-3 数组创建数组常用属性方法 2-4 运算符号加号运算符 减号运算符 -比较运算符逻辑运算符 2-5 控制语句for-inbreakcontinue 三、函数3-1 常用系统函数3-2 自定义函数函数声明函数调用 3-3 创建对象…

在线问诊APP开发,开启智慧医疗新模式

随着互联网医疗的不断发展&#xff0c;患者对线上问诊的需求逐渐增加。为了满足市场需求&#xff0c;提供便捷、高效的在线问诊服务。现在很多医院和诊所都着手互联网医院智慧医疗系统&#xff0c;利用在线问诊APP解决了医院每天要面对大量患者&#xff0c;医疗资源紧张&#x…

论文浅尝 | GenTKG:结合大语言模型的时间知识图谱生成式预测(NAACL2024)

笔记整理&#xff1a;喻靖&#xff0c;浙江大学硕士&#xff0c;研究方向为大语言模型 论文链接&#xff1a;https://arxiv.org/pdf/2310.07793 发表会议&#xff1a;NAACL2024 摘要 随着大语言模型&#xff08;LLMs&#xff09;的迅速发展&#xff0c;人们对时间知识图谱&…