同上改我原文里 不然看不懂 // === 历史记录弹窗开始(最终安全版)===
console.log("拿到历史数据:", this.recordList);
this.historyListContainer = new Container();
this.historyListContainer.visible = false; // 默认隐藏
this.historyListContainer.zIndex = 100;
this.historyListContainer.position.set(-270, -110);
const recordBg = new Sprite(Texture.from("assets/UIShop/商店底5.png"));
recordBg.width *= this.app.rat;
recordBg.height *= this.app.rat;
recordBg.anchor.set(0.5, 0.5);
recordBg.position.set(260, 110);
this.historyListContainer.addChild(recordBg);
const listWidth = 500; // 列表总宽度
const listHeight = 250; // 显示区域高度 一开始能看到几条
const itemHeight = 95; // 每条记录的高度
const contentStartX = 0; // 左边距
const contentStartY = 0; // 上边距(离顶)
// 滚动内容容器
const scrollContent = new Container();
scrollContent.position.set(contentStartX, contentStartY);
this.historyListContainer.addChild(scrollContent);
// 文本样式
const baseStyle = {
fontFamily: "Arial",
fontSize: 14,
fill: 0xffffff,
stroke: "#000000",
strokeThickness: 2,
align: "left"
};
// 如果没有数据,显示提示文字
if (!this.recordList || this.recordList.length === 0) {
const noDataText = new Text("暂无充值记录", {
...baseStyle,
fontSize: 18,
fill: 0x999999
});
noDataText.anchor.set(0.5);
noDataText.position.set(listWidth / 2, 100); // 居中显示
scrollContent.addChild(noDataText);
} else {
// 有数据时:遍历生成每一条记录
this.recordList.forEach((record, index) => {
const y = index * itemHeight;
// 圆角背景框
const bg = new Graphics();
bg.lineStyle(2, 0xd18b5c, 0.6); // 边框:颜色+透明度
bg.beginFill(0x7d503a, 0.3); // 填充色 + 透明度
bg.drawRoundedRect(
10, // x: 距离左边10像素
y + 5, // y: 微微下移避免贴边
listWidth - 20, // 宽度:左右各留10px边距
itemHeight - 10, // 高度:上下留空
18 // ✅ 四个角的圆角半径(越大越圆!推荐12~20)
);
bg.endFill();
scrollContent.addChild(bg);
// 时间格式化
const date = new Date(record.createDate);
const formattedTime = date.toLocaleString('en-US', {
month: 'numeric',
day: 'numeric',
year: 'numeric',
hour: 'numeric',
minute: '2-digit',
second: '2-digit',
hour12: true
});
// 第一行:Top up amount
const amountLabel = new Text("Top up amount", {
...baseStyle,
fontSize: 13,
fill: 0xb88e7e
});
amountLabel.position.set(20, y + 12);
const amountValue = new Text(`$${record.amount.toLocaleString()}`, {
...baseStyle,
fontSize: 16,
fill: 0xffff00
});
amountValue.position.set(180, y + 12);
// 第二行:Recharge Order
const orderLabel = new Text("Recharge Order", {
...baseStyle,
fontSize: 13,
fill: 0xb88e7e
});
orderLabel.position.set(20, y + 32);
const orderId = new Text(record.id, {
...baseStyle,
fontSize: 13,
fill: 0xaaffaa
});
orderId.position.set(180, y + 32);
// 第三行:Top up time
const timeLabel = new Text("Top up time", {
...baseStyle,
fontSize: 13,
fill: 0xb88e7e
});
timeLabel.position.set(20, y + 52);
const timeValue = new Text(formattedTime, {
...baseStyle,
fontSize: 13,
fill: 0xcccccc
});
timeValue.position.set(180, y + 52);
// 第四行:Order status
const statusLabel = new Text("Order status", {
...baseStyle,
fontSize: 13,
fill: 0xb88e7e
});
statusLabel.position.set(20, y + 72);
const statusStr = record.status === "1" ? "Finished" : "Waiting processing";
const statusValue = new Text(statusStr, {
...baseStyle,
fontSize: 14,
fill: record.status === "1" ? 0x00ff00 : 0xff0000
});
statusValue.position.set(180, y + 72);
// 将文本添加进滚动容器
scrollContent.addChild(
amountLabel, amountValue,
orderLabel, orderId,
timeLabel, timeValue,
statusLabel, statusValue
);
// 复制图标(点击复制订单号)
const copyIcon = new Sprite(Texture.from("assets/UIShop/复制.png"));
copyIcon.width = 55 * this.app.rat;
copyIcon.height = 55 * this.app.rat;
copyIcon.anchor.set(0.5);
copyIcon.position.set(listWidth - 40, y + itemHeight / 2); // 靠右居中
copyIcon.eventMode = "static";
copyIcon.cursor = "pointer";
copyIcon.on("pointerdown", (e) => {
e.stopPropagation();
navigator.clipboard.writeText(record.id).then(() => {
console.log(`已复制订单号: ${record.id}`);
copyIcon.tint = 0x00ff00;
setTimeout(() => { copyIcon.tint = 0xffffff; }, 300);
}).catch(err => {
alert("复制失败,请手动选择文本复制");
console.warn("Clipboard error:", err);
});
});
scrollContent.addChild(copyIcon);
});
// 裁剪区域 mask只显示 listHeight 范围内的内容
const clipMask = new Graphics();
clipMask.beginFill(0x000000, 0.01); // 不可见填充
clipMask.drawRect(0, 0, listWidth, listHeight); // 裁剪范围
clipMask.endFill();
clipMask.position.set(0, 0);
this.historyListContainer.addChild(clipMask);
scrollContent.mask = clipMask;
// 拖拽滚动逻辑
let isDragging = false;
let dragStartY = 0;
let scrollStartY = 0;
scrollContent.eventMode = "static"; // 启用交互
scrollContent.cursor = "grab";
scrollContent.on("pointerdown", (event) => {
isDragging = true;
dragStartY = event.global.y;
scrollStartY = scrollContent.y;
scrollContent.cursor = "grabbing";
event.stopPropagation(); // 防止触发底层按钮
});
const handlePointerMove = (e) => {
if (!isDragging) return;
const dy = e.clientY - dragStartY;
let newY = scrollStartY + dy;
// 计算最大滚动范围
const maxScrollUp = 0;
const totalItemsHeight = this.recordList.length * itemHeight;
const maxScrollDown = listHeight - totalItemsHeight; // 向上拉最多到这个位置
if (newY > maxScrollUp) newY = maxScrollUp;
else if (newY < maxScrollDown) newY = maxScrollDown;
scrollContent.y = newY;
};
const handlePointerUp = () => {
isDragging = false;
scrollContent.cursor = "grab";
};
// 绑定到画布元素(不会因层级丢失)
this.app.view.addEventListener("pointermove", handlePointerMove);
this.app.view.addEventListener("pointerup", handlePointerUp);
this.app.view.addEventListener("pointerupoutside", handlePointerUp);
}
// 关闭按钮
const closeHistory = new Sprite(Texture.from("assets/UIShop/UI1_03.png"));
closeHistory.width *= this.app.rat;
closeHistory.height *= this.app.rat;
closeHistory.position.set(500, -30);
closeHistory.eventMode = "static";
closeHistory.cursor = "pointer";
closeHistory.on("pointerdown", () => {
this.historyListContainer.visible = false;
if (this.overlay) this.overlay.visible = false;
this.enableMainContainerInteractivity(true); // 恢复主界面操作
});
this.historyListContainer.addChild(closeHistory);
// 添加到主容器显示
this.container.addChild(this.historyListContainer);
// === 历史记录弹窗结束 ===