深度解析:TextRenderManager——Cocos Creator艺术字体渲染核心类
一、类概述
TextRenderManager
是 Cocos Creator 中实现动态艺术字体渲染的核心单例类。它通过整合资源加载、缓存管理、异步队列和自动布局等功能,支持普通字符模式和图集模式两种渲染方案,适用于游戏中的动态文本(如聊天内容、排行榜)和静态艺术字(如UI标题)的高效渲染。
二、核心功能与设计理念
1. 核心功能
-
资源预加载:分批次异步加载字符纹理或图集,避免主线程阻塞。
-
动态缓存管理:通过
LRUCache
实现字符纹理的智能缓存与淘汰。 -
自动布局排版:支持水平对齐(左/中/右)、垂直对齐(上/中/下)及字符间距调整。
-
多模式渲染:
-
普通模式:从独立文件加载每个字符的纹理。
-
图集模式:从预生成的图集(如BMFont输出)中提取字符。
-
2. 设计目标
-
高性能:通过异步加载、LRU缓存减少资源重复请求。
-
易扩展:模块化设计,支持自定义布局策略与渲染模式。
-
内存安全:动态释放无用资源,防止内存泄漏。
三、代码结构与核心方法详解
1. 私有属性与缓存机制
// 字符纹理缓存(LRU策略)
private _spriteCache = new LRUCache<string, SpriteFrame>(100);
// 加载队列(防止重复请求)
private _loadingQueue = new Map<string, Promise<void>>();
// 渲染请求队列(异步任务调度)
private _requestQueue: Array<{ text: string, config: TextRenderConfig, resolve: Function }> = [];
// 占位符纹理(加载失败时使用)
private _placeholderCache: SpriteFrame | null = null;
2. 核心方法解析
(1) 文本渲染入口:renderText()
/*** 渲染文本* @param text 文本内容* @param config 渲染配置* @returns 包含所有字符节点的容器*/
public async renderText(text: string, config: TextRenderConfig = {}): Promise<Node> {return new Promise((resolve) => {// 将请求加入队列,触发异步处理this._requestQueue.push({ text, config, resolve });this._processQueue();});
}
-
流程:
-
将渲染请求推入队列,确保异步任务按顺序执行。
-
调用
_processQueue()
处理队列中的任务。
-
(2) 队列处理器:_processQueue()
/** 处理渲染队列(单线程异步执行) */
private async _processQueue() {if (this._isProcessing || this._requestQueue.length === 0) return;this._isProcessing = true;const { text, config, resolve } = this._requestQueue.shift()!;try {const container = await this._doRender(text, config);resolve(container);} finally {this._isProcessing = false;this._processQueue(); // 递归处理下一个任务}
}
-
关键点:
-
使用
_isProcessing
状态锁防止并发处理。 -
通过递归调用实现队列的持续消费。
-
(3) 实际渲染逻辑:_doRender()
/** 执行实际渲染逻辑 */
private async _doRender(text: string, config: TextRenderConfig): Promise<Node> {const container = new Node('TextContainer');this._applyConfig(config, container); // 应用配置(位置、父节点等)// 预加载资源(字符或图集)try {if (config.useAtlas) {await this._loadAtlas(config);} else {await this._preloadCharacters(text, config);}} finally {if (config.preRender) {container.destroy(); // 预渲染模式直接销毁容器return;}}// 创建字符节点并布局const nodes = await this._createCharacterNodes(text, config);this._layoutNodes(nodes, config);// 设置字符缩放并添加到容器nodes.forEach(node => {container.addChild(node);if (config.fontSize) {node.setScale(new Vec3(config.fontSize / 100, config.fontSize / 100, 1));}});return container;
}
-
流程:
-
配置初始化:设置容器位置、父节点等基础属性。
-
资源预加载:根据配置选择加载图集或独立字符。
-
字符节点创建:生成所有字符的Sprite节点。
-
布局计算:根据对齐方式排列字符位置。
-
(4) 字符预加载:_preloadCharacters()
/** 预加载字符资源(分批次加载) */
private async _preloadCharacters(text: string, config: TextRenderConfig) {const uniqueChars = [...new Set(text.split(''))];// 分批次加载(每批5个字符)for (let i = 0; i < uniqueChars.length; i += 5) {const batch = uniqueChars.slice(i, i + 5);await Promise.all(batch.map(char => this._loadWithCacheControl(char, config)));}
}
-
优化策略:
-
分批加载减少瞬时资源请求压力。
-
使用
_loadWithCacheControl
结合LRU缓存管理。
-
(5) 布局计算:_layoutNodes()
/** 自动布局字符节点 */
private _layoutNodes(nodes: Node[], config: TextRenderConfig) {const firstNode = nodes[0]?.getComponent(Sprite);if (!firstNode?.spriteFrame) return;// 计算总宽度和基础高度const baseHeight = firstNode.spriteFrame.rect.height;const totalWidth = nodes.reduce((sum, node) => sum + node.getComponent(Sprite)!.spriteFrame.rect.width, 0) + (nodes.length - 1) * (config.spacing || 0);// 计算起始位置let xPos = this._calculateXPosition(totalWidth, config.alignment);const yPos = this._calculateYPosition(baseHeight, config.verticalAlign);// 排列节点nodes.forEach(node => {const width = node.getComponent(Sprite)!.spriteFrame.rect.width;node.setPosition(xPos, yPos, 0);xPos += width + (config.spacing || 0);});
}
-
布局逻辑:
-
水平对齐:根据
alignment
计算起始X坐标。 -
垂直对齐:根据
verticalAlign
计算起始Y坐标。 -
动态间距:累加每个字符的宽度与间距,实现自动换行(如需)。
-
(6) 占位符生成:_getPlaceholder()
/** 生成透明占位符纹理 */
private _getPlaceholder(): SpriteFrame {if (!this._placeholderCache) {const frame = new SpriteFrame();const charWidth = 30, charHeight = 30; // 与实际字符尺寸一致const texture = new Texture2D();texture.create(charWidth, charHeight, Texture2D.PixelFormat.RGBA8888);const data = new Uint8Array(charWidth * charHeight * 4).fill(150); // 半透明灰色texture.uploadData(data);frame.rect = new Rect(0, 0, charWidth, charHeight);frame.texture = texture;this._placeholderCache = frame;}return this._placeholderCache;
}
-
作用:
-
在字符加载失败时提供占位显示,避免UI错乱。
-
使用透明纹理减少视觉干扰。
-
3. 关键配置参数:TextRenderConfig
/** 生成透明占位符纹理 */
private _getPlaceholder(): SpriteFrame {if (!this._placeholderCache) {const frame = new SpriteFrame();const charWidth = 30, charHeight = 30; // 与实际字符尺寸一致const texture = new Texture2D();texture.create(charWidth, charHeight, Texture2D.PixelFormat.RGBA8888);const data = new Uint8Array(charWidth * charHeight * 4).fill(150); // 半透明灰色texture.uploadData(data);frame.rect = new Rect(0, 0, charWidth, charHeight);frame.texture = texture;this._placeholderCache = frame;}return this._placeholderCache;
}
相关文章:
深度解析:TextRenderManager——Cocos Creator艺术字体渲染核心类
一、类概述 TextRenderManager 是 Cocos Creator 中实现动态艺术字体渲染的核心单例类。它通过整合资源加载、缓存管理、异步队列和自动布局等功能,支持普通字符模式和图集模式两种渲染方案,适用于游戏中的动态文本(如聊天内容、排行榜&…...
同样开源的自动化工作流工具n8n和Dify对比
n8n和Dify作为两大主流工具,分别专注于通用自动化和AI应用开发领域,选择哪个更“好用”需结合具体需求、团队能力及业务场景综合判断。以下是核心维度的对比分析: 一、核心定位与适用场景 维度n8nDify核心定位开源全场景自动化工具ÿ…...
设计模式每日硬核训练 Day 16:责任链模式(Chain of Responsibility Pattern)完整讲解与实战应用
🔄 回顾 Day 15:享元模式小结 在 Day 15 中,我们学习了享元模式(Flyweight Pattern): 通过共享对象,分离内部状态与外部状态,大量减少内存开销。适用于字符渲染、游戏场景、图标缓…...
基于边缘人工智能的AI无人机-更高效更安全的飞行任务执行
基于边缘人工智能的AI无人机-更高效更安全的飞行任务执行 人工智能有可能改变人们的生活和工作方式。人工智能和无人机是近年来发展迅速的两项技术。当这两种技术结合在一起时,它们会创造出许多以前不可能的应用。基于人工智能的无人机旨在独立执行任务,…...
30、不是说字符串是不可变的吗,string s=“abc“;s=“123“不就是变了吗?
一、核心概念澄清:不可变性的真实含义 1、不可变性的定义 字符串不可变性指对象内容不可修改,而非变量不可修改。 类比: 不可变字符串 装在密封信封里的信纸(内容不可更改)变量赋值 更换信封的指向(从…...
线上查询车辆出险记录:快速掌握事故情况!
在如今汽车成为人们日常不可或缺的交通工具之际,车辆出险记录成为了许多车主关注的焦点之一。为了帮助车主们快速了解车辆出险、理赔、事故记录,现在有了一种便捷的方式,那就是通过API接口在线查询。本文将介绍如何利用API接口,通…...
Python爬虫课程实验指导书
1.1Requests类库的认知 1.1.1 认识请求类库 Requests是用Python语言编写,基于,采用Apache2 Licensed开源协议的。它比urllib更加方便,可以节约我们大量的工作,完全满足HTTP测试需求。urllibHTTP库 Requests官网地址:ht…...
streamlit实现非原生的按钮触发效果 + flask实现带信息的按钮触发
目录 简介不携带信息的触发隐藏指定st.button(label, key)触发button的html代码汇总 携带信息的触发为什么需要携带信息前端JavaScript修改flask处理总代码 简介 由于streamlit可以同时在实现前后端结合,非常方便,但是这也造成了user难以方便的对页面的…...
机器学习基础——Seaborn使用
1.使用tips数据集,创建一个展示不同时间段(午餐/晚餐)账单总额分布的箱线图 import matplotlib.pyplot as plt import numpy as np import pandas as pd import seaborn as snstips pd.read_csv(./tips.csv)sns.boxplot(data tips,x time,y total_bill, )plt.show() 2.使用…...
Godot开发2D冒险游戏——第三节:游戏地图绘制
一、初步构建游戏地图 在游戏场景当中添加一个新的子节点:TileMapLayer 这一层称为瓦片地图层 根据提示,下一步显然是添加资源 为TileMapLayer节点添加一个TileSet 将地板添加进来,然后选择自动分割图集 自定义时要确保大小合适 让Godot自…...
Spark Mllib 机器学习
概述 机器学习是什么 根据百度百科的定义: 机器学习是一种通过算法和模型使计算机从数据中自动学习并进行预测或决策的技术。 定义比较抽象,根据常见的机器学习可以总结出三个关键字: 算法、经验、性能。 机器学习的过程可以抽象成一个pipel…...
在windows使用docker打包springboot项目镜像并上传到阿里云
1、前提:已有spring项目 2、在项目根目录下创建Dockerfile文件 FROM openjdk:11 WORKDIR /ruoyi-admin COPY ruoyi-admin/build/libs/lifecolor-web.jar lifecolor-web.jar CMD ["java", "-jar", "lifecolor-web.jar"] 3、选…...
前端高频面试题day3
JavaScript作用域理解 核心概念 作用域:定义变量/函数的可见范围及生命周期,分为 全局作用域、函数作用域、块级作用域。作用域链:变量查找从当前作用域逐级向上直至全局,遵循词法作用域(静态作用域)。闭…...
时空特征如何融合?LSTM+Resnet有奇效,SOTA方案预测准确率超91%
LSTM有着不错的时序信息提取能力,ResNet有着不错的空间特征信息提取能力。如果现在有时空特征融合的创新需求,我们是否能将LSTM和ResNet两者的优点融合起来呢? 随着这个思路下去,LSTM ResNet混合模型横空出世,在各个…...
蓝桥杯Java全攻略:从零到一掌握竞赛与企业开发实战
蓝桥杯Java软件开发竞赛已成为全国高校学生展示编程能力的重要舞台,本指南将带您从零开始构建完整的Java知识体系,不仅覆盖蓝桥杯高频考点,还延伸至企业级开发实战,助您在竞赛中脱颖而出并为未来职业发展奠定坚实基础。 一、Java基础语法与数据结构 竞赛解题流程图设计 蓝…...
【Nginx】负载均衡配置详解
Nginx作为高性能的HTTP服务器和反向代理服务器,提供了强大的负载均衡功能。本文将详细介绍Nginx负载均衡的配置方法和相关策略。 一、基础负载均衡配置 1.单服务示例配置 配置nginx.conf模块 在Nginx配置文件中定义upstream模块: worker_processes a…...
打造企业级AI文案助手:GPT-J+Flask全栈开发实战
一、智能文案革命的序幕:为什么需要AI文案助手? 在数字化营销时代,内容生产效率成为企业核心竞争力。据统计,营销人员平均每天需要撰写3.2篇文案,而传统人工创作存在三大痛点: 效率瓶颈:创意构…...
【文献速递】snoRNA-SNORD113-3/ADAR2通过对PHKA2的A-to-I编辑影响胶质母细胞瘤糖脂代谢
Cui等人于2025年在Cellular & Molecular Biology Letters上的发表一篇研究论文,题目为“Effect of SNORD113-3/ADAR2 on glycolipid metabolism in glioblastoma via A-to-I editing of PHKA2”。这篇文章的核心内容是研究胶质母细胞瘤(GBMÿ…...
视频HLS分片与关键帧优化深度解析
视频HLS分片与关键帧优化深度解析 🌐 HLS基础架构 #mermaid-svg-OQmrXfradiCv3EGC {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-OQmrXfradiCv3EGC .error-icon{fill:#552222;}#mermaid-svg-OQmrXfrad…...
再谈从视频中学习:从给视频打字幕的Humanoid-X、UH-1到首个人形VLA Humanoid-VLA:迈向整合第一人称视角的通用人形控制
前言 本博客内,之前写了比较多的大脑相关的,或者上肢操作,而解读运动控制、规划的虽也有,但相对少 故近期 准备多写写双足人形的运动控制相关 一方面,我们有些客户订单涉及这块二方面,想让双足人形干好活…...
Ubuntu下MySQL的安装
Ubuntu下MySQL的安装 1. 查看当前操作系统版本2. 添加MySQL APT源2.1 访问下载页面,并下载发布包2.2 执行安装指令2.3 安装MySQL 3. 查看MySQL状态4. 设置开机自启动 1. 查看当前操作系统版本 通过命令lsb_release -a查看: 2. 添加MySQL APT源 2.1 访问下…...
DataStreamAPI实践原理——快速上手
引入 通过编程模型,我们知道Flink的编程模型提供了多层级的抽象,越上层的API,其描述性和可阅读性越强,越下层API,其灵活度高、表达力越强,多数时候上层API能做到的事情,下层API也能做到&#x…...
《数据结构初阶》【顺序表 + 单链表 + 双向链表】
《数据结构初阶》【顺序表 单链表 顺序表】 前言:先聊些其他的东西!!!什么是线性表?什么是顺序表?顺序表的种类有哪些? 什么是链表?链表的种类有哪些? ---------------…...
【JS-Leetcode】2621睡眠函数|2629复合函数|2665计数器||
文章目录 2621睡眠函数2629复合函数2665计数器|| 这三个题目涉及setTimeout、promise、数组reduce方法,闭包。 2621睡眠函数 请你编写一个异步函数,它接收一个正整数参数 millis ,并休眠 millis 毫秒。要求此函数可以解析任何值。 原理&am…...
全国各地级城市月度平均房价统计数据2009-2021年
全国各地级城市月度平均房价统计数据2009-2021年.ziphttps://download.csdn.net/download/2401_84585615/90259770 https://download.csdn.net/download/2401_84585615/90259770 来源:安居客,本数据以excel格式展示,列举2.5万多条样本数据。总…...
ElasticSearch从入门到精通-覆盖DSL操作和Java实战
一、ElasticSearch基础概念 1.1 认识elasticSearch ElasticSearch(简称ES)是一款开源的、分布式的搜索引擎,它建立在Apache Lucene之上。简单来说,ElasticSearch就是一个能让你以极快速度进行数据搜索、存储和分析的系统。它不仅…...
SHCTF-REVERSE
前言 之前写的,一直没发,留个记录吧,万一哪天记录掉了起码在csdn有个念想 1.ezapk 反编译 快速定位关键函数 package com.mycheck.ezjv;import adrt.ADRTLogCatReader; import android.app.Activity; import android.content.Context; impo…...
C++学习:六个月从基础到就业——模板编程:模板特化
C学习:六个月从基础到就业——模板编程:模板特化 本文是我C学习之旅系列的第三十四篇技术文章,也是第二阶段"C进阶特性"的第十二篇,主要介绍C中的模板特化技术。查看完整系列目录了解更多内容。 目录 引言模板特化基础…...
【中级软件设计师】编译和解释程序的翻译阶段、符号表 (附软考真题)
【中级软件设计师】编译和解释程序的翻译阶段、符号表 (附软考真题) 目录 【中级软件设计师】编译和解释程序的翻译阶段、符号表 (附软考真题)一、历年真题二、考点:编译和解释程序的翻译阶段1、解释2、编译3、解释和编译的异同之处4、符号表 三、真题的答案与解析答…...
G1(Garbage-First)垃圾回收器与JVM内存
G1垃圾回收器简介 G1(Garbage-First)是Java虚拟机(JVM)中的一种垃圾回收器,它是针对服务器端应用设计的,旨在提供高吞吐量和低延迟的垃圾回收性能。G1垃圾回收器的主要目标是高效地管理JVM的堆内存,同时尽量减少垃圾回收(GC)过程对应用程序性能的影响。 特点 分区回收…...
STM32 驱动 INA226 测量电流电压功率
文章目录 一、INA226简介二、引脚功能三、寄存器介绍1.配置寄存器 0x002.分流电压寄存器 0x013.总线电压寄存器 0x024.功率寄存器 0x035.电流寄存器 0x046.基准寄存器 0x05 四、IIC 时序说明1.写时序2.读时序 五、程序六、实验现象1.线路图2.输出数据 一、INA226简介 INA226 是…...
解决新搭建的centos虚拟器,yum下载不了的问题
1. 检查网络连接 确保虚拟机可以访问互联网: ping 8.8.8.8 # 测试基础网络连通性若不通: 检查网卡 IP 配置(参考之前的 IP 恢复步骤)。 确认虚拟机网络模式(如 NAT 或桥接模式)是否允许访问外网。 检查网…...
python连接Elasticsearch并完成增删改查
python库提供了elasticsearch模块,可以通过以下命令进行快速安装,但是有个细节需要注意一下,安装的模块版本要跟es软件版本一致,此处举例:7.8.1 pip install elasticsearch==7.8.1 首先连接elasticsearch,以下是免密示例 from elasticsearch import Elasticsearch# El…...
Python爬虫(7)Python数据存储实战:CSV文件读写与复杂数据处理指南
目录 一、背景与核心价值二、CSV基础与核心应用场景2.1 CSV文件结构解析2.2 适用场景 三、Python csv模块核心操作3.1 安装与基础读写3.2 高级功能:字典读写与自定义格式 四、处理复杂数据场景4.1 含特殊字符的字段4.2 嵌套数据(如JSO…...
Spring Boot 中的条件注解
Spring Boot条件注解的汇总: 注解作用判断依据使用场景ConditionalOnBean容器中存在指定Bean时,被注解的配置或Bean定义生效指定Bean在容器中存在依赖其他已存在Bean时配置相关功能ConditionalOnCheckpointRestore在特定检查点恢复相关条件满足时生效满…...
Java 字符串分解技术:substring、tokenizing 和 trimming 方法详解
关键点 Java 字符串处理是开发中不可或缺的一部分,广泛用于数据解析和格式化。substring() 方法能够精确提取字符串的子串,需注意索引范围以避免异常。String.split() 是分词的首选方法,支持正则表达式,灵活性高。trim() 和 stri…...
OpenCV进阶操作:图像金字塔
文章目录 前言一、图像金字塔1、什么是图像金字塔2、金字塔类型1) 高斯金字塔 (Gaussian Pyramid)2)拉普拉斯金字塔 (Laplacian Pyramid) 3、图像金字塔的作用 二、图像金字塔中的操作1、向下采样步骤 2、向上采样步骤 3、拉普拉斯金字塔4、结论 三、代码…...
Rust游戏开发全栈指南:从理论到实践的革新之路
一、Rust游戏开发生态全景 1.1 核心引擎框架 Rust游戏生态已形成多层级工具链,覆盖从轻量级2D到3A级项目的开发需求: Bevy:采用ECS架构的模块化引擎,提供优雅的API设计和活跃社区支持,支持实时热重载和跨平台部署Fy…...
[GXYCTF2019]Ping Ping Ping
解题步骤 1、先使用 内敛执行 查看当前的php文件 执行 命令执行 发现空格被过滤 ?ip127.0.0.1$IFS|$IFSwhomi 还有一个点就是这个 执行的命令是不能进行拼接的 可能就是被过滤了 | 所以我们使用 ; 进行绕过一下 空格过滤代替 $IFS ${IFS} ${IFS}$9 //这里$1到$9都可以 $IFS$1…...
马哥教育Linux云计算运维课程
课程大小:19.1G 课程下载:https://download.csdn.net/download/m0_66047725/90640128 更多资源下载:关注我 你是否找了很多资料看了很多视频聊了很多群友,却发现自己技术仍然原地踏步?本教程联合BAT一线导师倾囊相授…...
科技打头阵,创新赢未来——中科视界携千眼狼超高速摄像机亮相第三届科交会
2025年4月26日,合肥,第三届中国(安徽)科技创新成果转化交易会国际合作板块展区,中科视界及其旗下品牌“千眼狼”高速摄像机成为展会焦点。作为国内科学仪器的领军企业,中科视界以“科技打头阵,创…...
【Flutter】Unity 三端封装方案:Android / iOS / Web
关联文档:【方案分享】Flutter Unity 跨平台三维渲染架构设计全解:插件封装、通信机制与热更新机制—— 支持 Android/iOS/Web 的 3D 内容嵌入与远程资源管理,助力 XR 项目落地 —— 支持 Android/iOS/Web 的 3D 内容嵌入与远程资源管理&…...
高能效计算:破解算力增长与能源约束的科技密码
引言 在人工智能和大模型技术迅猛发展的今天,全球算力需求正以每年50%的速度激增[3]。然而,传统计算范式已逼近物理极限——国际能源署预测,到2030年数据中心的全球电力消耗占比可能突破3%[3]。面对这场"算力革命"与"能源危机…...
【质量管理】TRIZ(萃智)的工程系统进化法则
在文章【质量管理】现代TRIZ(萃智)理论概述-CSDN博客 我们谈到到现代TRIZ的理论、TRIZ与传统创新的差异等。在文章中我们有说到TRIZ的创始人阿奇舒勒发现其实技术的进化是有规律可循的。 那到底技术进步有什么规律呢? 技术进化发展趋势和路径…...
FastAPI系列07:“请求-响应”过程高阶技巧
“请求-响应”过程高阶技巧 1、自定义 Request自定义 Request的用途如何自定义 Request 2、自定义APIRouteAPIRoute的用途自定义 APIRoute的用途如何自定义 APIRoute 3、使用BackgroundTasks(后台任务)BackgroundTasks的用途如何使用BackgroundTasksBack…...
游戏服务器不加防护能活多久?
游戏服务器若不加防护,其存活时间受多种因素影响,但通常面临极高的安全风险,可能在数小时至数天内因攻击或漏洞利用而崩溃。以下是具体分析: 1. DDoS攻击与勒索风险 未加防护的服务器极易成为黑客攻击目标,尤其是DDoS…...
Embedding入门概述
概述 Embedding,嵌入,一种将离散的符号数据(如单词、句子、图像等)映射到连续的向量空间中的技术,这些向量能够捕捉数据之间的语义、结构等关系。就是把原本难以直接处理的符号数据,转换成计算机更容易理解…...
革新桌面自动化:微软UFO²操作系统深度解析与未来展望
一、系统架构:多智能体协同的OS级创新 微软UFO(Unified Framework for Operations)是首个深度集成于Windows底层的多智能体操作系统,其核心架构由HostAgent控制中枢与模块化AppAgent执行单元构成。 HostAgent作为系统级调度器…...
【Java】分布式事务解决方案
分布式事务是指在分布式系统中,为了保证多个节点上的操作要么全部成功提交,要么全部失败回滚,所采取的一系列技术手段和协议。 CAP理论 在一个分布式系统中以下三个基本属性无法被同时满足: C(一致性):一致性是指写…...
es数据导出
有大数据量导出的需求 整体思路:分页查询es,一页查询2000条,下一页查询的截止时间取上一页最后一条记录的创建时间(因为分页是按照创建时间逆序排列的),组装最后导出的list,利用EasyExcel导出到…...