<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chat Interface</title>
<script src="https://cdn.jsdelivr.net/npm/emoji-picker-element@^1/index.js" type="module"></script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
display: flex;
justify-content: center;
align-items: center;
}
.phone-container {
width: min(100%, 360px);
border: 12px solid #d9c4f5;
border-radius: 36px;
background-image: url('https://files.catbox.moe/n72l2h.jpg');
background-size: cover;
background-position: center;
position: relative;
margin: 15px;
box-shadow:
0 0 0 6px #f8f5ff,
0 0 20px rgba(0,0,0,0.1);
overflow: hidden;
}
/* 手机挂饰 */
.phone-charm {
position: absolute;
top: -5px;
right: -71px;
width: 190px;
height: 190px;
background-image: url('https://files.catbox.moe/bwll9i.GIF');
background-size: contain;
background-repeat: no-repeat;
z-index: 1;
pointer-events: none;
}
/* 顶部图标容器 */
.header-icons {
display: flex;
gap: 10px; /* 调整图标间距 */
}
/* 图标样式 */
.header-icon {
width: 24px;
height: 24px;
color: #ae94d1;
}
.header-icon:hover {
color: #ceb7ed; /* 悬停时变亮 */
transform: scale(1.1); /* 放大效果 */
}
/* 手机刘海 */
.phone-notch {
position: absolute;
top: 0;
left: 50%;
transform: translateX(-50%);
width: 160px;
height: 13px;
background: #d9c4f5;
border-bottom-left-radius: 12px;
border-bottom-right-radius: 12px;
z-index: 999;
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
}
.notch-camera {
width: 8px;
height: 8px;
background: #c8b3e3;
border-radius: 50%;
border: 2px solid #b9a3d6;
}
.notch-speaker {
width: 40px;
height: 4px;
background: #c8b3e3;
border-radius: 2px;
}
.notch-sensor {
width: 6px;
height: 6px;
background: #c8b3e3;
border-radius: 50%;
border: 1px solid #b9a3d6;
}
/* 聊天容器 */
.chat-container {
width: 100%;
height: 600px;
background-size: cover;
background-position: center;
border-radius: 24px;
overflow: hidden;
font-family: -apple-system, "Segoe UI", "Hiragino Kaku Gothic ProN", sans-serif;
margin: 0 auto;
}
/* 聊天头部 */
.chat-header {
height: 56px;
background: rgba(255,255,255,0.95);
padding: 0 16px;
display: flex;
align-items: center;
justify-content: space-between;
border-bottom: 1px solid rgba(0,0,0,0.05);
backdrop-filter: blur(10px);
}
/* 头部信息 */
.header-info {
display: flex;
align-items: center;
gap: 12px;
}
/* 头像 */
.header-avatar {
width: 36px;
height: 36px;
border-radius: 50%;
object-fit: cover;
border: 2px solid #fff;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
/* 文本容器 */
.header-text {
display: flex;
flex-direction: column;
}
/* 聊天对象名称 */
.chat-header h2 {
font-size: 16px;
color: #333;
font-weight: 600;
margin-bottom: 2px;
}
/* 状态 */
.header-status {
font-size: 12px;
color: #4CAF50;
display: flex;
align-items: center;
gap: 4px;
}
/* 状态点 */
.status-dot {
width: 6px;
height: 6px;
background: #4CAF50;
border-radius: 50%;
}
.chat-messages {
height: 492px;
padding: 16px;
overflow-y: auto;
}
.chat-messages::-webkit-scrollbar {
width: 6px;
}
.chat-messages::-webkit-scrollbar-track {
background: transparent;
}
.chat-messages::-webkit-scrollbar-thumb {
background: rgba(0,0,0,0.1);
border-radius: 3px;
}
/* 消息 */
.message {
display: flex;
margin-bottom: 8px;
align-items: flex-start;
position: relative;
animation: message-pop 0.3s ease-out;
}
@keyframes message-pop {
0% {
transform: translateY(10px);
opacity: 0;
}
100% {
transform: translateY(0);
opacity: 1;
}
}
.message.sent {
flex-direction: row-reverse;
}
/* 头像 */
.avatar {
width: 36px;
height: 36px;
border-radius: 50%;
margin-top: 4px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
border: 2px solid #fff;
transition: transform 0.2s;
}
.avatar:hover {
transform: scale(1.1);
}
.message-wrapper {
max-width: 70%;
display: flex;
flex-direction: column;
margin: 0 10px;
}
/* 消息内容 */
.message-content {
padding: 10px 14px;
border-radius: 18px;
font-size: 14px;
line-height: 1.4;
word-wrap: break-word;
position: relative;
transition: transform 0.2s;
}
.message-content:hover {
transform: translateY(-2px);
}
/* 接收消息 */
.received .message-content {
background: #fff;
color: #333;
box-shadow: 0 2px 4px rgba(0,0,0,0.05);
border-bottom-left-radius: 4px;
}
/* 发送消息 */
.sent .message-content {
background: #be99e0;
color: #fff;
border-bottom-right-radius: 4px;
}
/* 消息时间 */
.message-time {
font-size: 11px;
color: #888;
margin-top: 4px;
margin-left: 4px;
margin-right: 4px;
}
.sent .message-time {
text-align: right;
}
.typing-indicator {
display: inline-flex;
gap: 2px; /* 减小点之间的间距 */
padding: 2px 4px; /* 减小内边距 */
margin-top: 2px;
animation: none; /* 移除整体动画 */
}
.typing-dot {
width: 3px; /* 减小点的大小 */
height: 3px;
background: #999; /* 使用更柔和的颜色 */
border-radius: 50%;
animation: subtle-typing 1.5s infinite; /* 减慢动画速度,使用更柔和的动画 */
}
@keyframes subtle-typing {
0%, 100% {
transform: translateY(0);
opacity: 0.5;
}
50% {
transform: translateY(-1px); /* 减小上下移动的幅度 */
opacity: 0.8;
}
}
.chat-input {
height: 52px;
background: rgba(255,255,255,0.95);
padding: 8px 16px;
display: flex;
align-items: center;
gap: 8px;
border-top: 1px solid rgba(0,0,0,0.05);
backdrop-filter: blur(10px);
position: relative;
}
/* 转账按钮样式 */
.transfer-btn {
width: 24px;
height: 24px;
color: #ae94d1;
cursor: pointer;
transition: transform 0.2s;
}
.transfer-btn:hover {
color: #ceb7ed;
transform: scale(1.1);
}
/* 转账弹窗样式 */
.transfer-modal {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 90%;
max-width: 320px;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(12px);
border-radius: 24px;
padding: 28px 24px;
text-align: center;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
z-index: 1000;
animation: modalSlideIn 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
/* 转账弹窗内容 */
.transfer-content {
display: flex;
flex-direction: column;
align-items: center;
gap: 16px;
}
/* 转账头像 */
.transfer-avatar {
width: 96px;
height: 96px;
border-radius: 50%;
border: 3px solid #c4a6ed;
padding: 3px;
box-shadow: 0 0 0 rgba(108, 140, 213, 0.4);
margin-bottom: 4px;
object-fit: cover;
}
/* 转账标题 */
.transfer-title {
font-size: 20px;
font-weight: 600;
color: #fff;
margin-bottom: 8px;
}
/* 转账表单 */
.transfer-form {
width: 100%;
display: flex;
flex-direction: column;
gap: 12px;
}
/* 金额输入框组 */
.amount-input-group {
position: relative;
margin-bottom: 4px;
}
/* 金额输入框 */
.amount-input {
width: 100%;
padding: 10px 36px 10px 10px;
border: 1px solid #616161;
border-radius: 25px;
background: rgba(255, 255, 255, 0.9);
font-size: 18px;
color: #333;
text-align: center;
}
/* 金额符号 */
.amount-symbol {
position: absolute;
right: 10px;
top: 50%;
transform: translateY(-50%);
color: #666;
font-weight: bold;
}
/* 备注输入框 */
.note-input {
width: 85%;
margin: 0 auto;
padding: 8px;
border: 1px solid #616161;
border-radius: 25px;
background: rgba(255, 255, 255, 0.8);
font-size: 14px;
color: #333;
}
/* 按钮容器 */
.transfer-buttons {
display: flex;
gap: 16px;
margin-top: 16px;
justify-content: center;
}
/* 按钮基础样式 */
.transfer-button {
padding: 10px 24px;
border-radius: 8px;
border: none;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
}
/* 确认按钮 */
.confirm-transfer {
background: #e2c2ff;
color: white;
}
.confirm-transfer:hover {
background: #d4aeeb;
transform: translateY(-2px);
}
/* 取消按钮 */
.cancel-transfer {
background: #98d6d0;
color: white;
}
.cancel-transfer:hover {
background: #99c8c9;
transform: translateY(-2px);
}
/* 输入框聚焦样式 */
.amount-input:focus, .note-input:focus {
outline: none;
border-color: #e2c2ff;
box-shadow: 0 0 0 2px rgba(102, 102, 102, 0.2);
}
.transfer-card-wrapper {
display: flex;
justify-content: flex-end;
align-items: flex-start;
width: 100%;
margin: 3px 0;
gap: 8px;
}
.transfer-card {
background:#f8f5ff;
background-size: cover;
background-position: center;
border-radius: 12px;
width: fit-content;
max-width: 160px;
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
padding: 3px;
position: relative;
overflow: hidden;
}
.transfer-inner {
background: rgba(255, 255, 255, 0.8);
border-radius: 10px;
padding: 12px;
display: flex;
flex-direction: column;
align-items: center;
position: relative;
margin: 0;
box-shadow: inset 0 1px 3px rgba(255, 255, 255, 0.8),
inset 0 -1px 3px rgba(0, 0, 0, 0.1),
0 1px 4px rgba(0, 0, 0, 0.15);
}
.transfer-header {
display: flex;
align-items: center;
margin-bottom: 0;
gap: 7px;
}
.transfer-icon {
width: 14px;
height: 14px;
color: #444;
}
.transfer-title {
font-size: 12px;
font-weight: 600;
color: #444;
}
.transfer-amount {
font-size: 16px;
font-weight: bold;
color: #333;
margin: 2px;
line-height: 1;
}
.transfer-to {
font-size: 10px;
color: #2E8B57;
margin: 1px 0;
line-height: 1.2;
}
.transfer-note {
font-size: 12px;
color: #333;
margin: 1px 0;
max-width: 100%;
overflow: hidden;
text-overflow: ellipsis;
text-align: center;
line-height: 1.2;
}
/* 表情按钮 */
.emoji-btn {
width: 32px;
height: 32px;
border: none;
border-radius: 50%;
background: #f5f5f5;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
color: #ae94d1;
flex-shrink: 0;
}
.emoji-btn:hover {
background: #f5f5f5;
transform: scale(1.1);
}
/* 表情选择器容器 */
.emoji-picker-container {
position: absolute;
bottom: 60px;
left: 16px;
display: none;
z-index: 1000;
}
/* 输入框 */
.input-field {
flex: 1;
height: 36px;
border: 1px solid rgba(0,0,0,0.1);
border-radius: 18px;
background: #fff;
padding: 0 16px;
outline: none;
font-size: 14px;
color: #333;
transition: all 0.2s;
margin-right: 8px;
max-width: calc(100% - 96px);
}
.input-field:focus {
border-color: #6C8CD5;
box-shadow: 0 0 0 2px rgba(108,140,213,0.2);
}
.input-field::placeholder {
color: #999;
}
/* 发送按钮 */
.send-btn {
width: 36px;
height: 36px;
border: none;
border-radius: 50%;
background: linear-gradient(135deg, #e2c2ff 0%, #a5ffd6 120%);
color: white;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
flex-shrink: 0;
}
.send-btn:hover {
background: linear-gradient(135deg, #f0d5ff 0%, #b5ffdf 120%);
transform: scale(1.1);
}
/* 响应式调整 */
@media screen and (max-width: 400px) {
.phone-container {
margin: 10px;
border-width: 8px;
}
.chat-container {
height: 580px;
}
.chat-messages {
height: 472px;
}
.message-content {
font-size: 13px;
}
.input-field {
max-width: calc(100% - 88px);
}
}
.voice-call-modal {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 90%;
max-width: 320px;
background: rgba(255, 255, 255, 0.95);
backdrop-filter: blur(12px);
border-radius: 24px;
padding: 28px 24px;
text-align: center;
box-shadow: 0 8px 32px rgba(31, 38, 135, 0.15);
z-index: 1000;
animation: modalSlideIn 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
/* 模态框内容 */
.modal-content {
display: flex;
flex-direction: column;
align-items: center;
gap: 20px;
}
/* 头像 */
.caller-avatar {
width: 96px;
height: 96px;
border-radius: 50%;
border: 3px solid #c4a6ed;
padding: 3px;
box-shadow: 0 0 0 rgba(108, 140, 213, 0.4);
animation: avatar-pulse 1.5s infinite;
margin-bottom: 4px;
object-fit: cover;
}
/* 来电者名称 */
.caller-name
font-size: 24px;
font-weight: 600;
color: #333;
margin: 4px 0;
font-family: -apple-system, system-ui, sans-serif;
}
/* 通话状态 */
.call-status {
color: #666;
font-size: 15px;
margin-bottom: 24px;
display: flex;
align-items: center;
gap: 6px;
justify-content: center;
}
/* 状态点 */
.call-status::before {
content: "";
display: inline-block;
width: 8px;
height: 8px;
background: #6C8CD5;
border-radius: 50%;
animation: status-blink 1s infinite;
}
/* 按钮容器 */
.call-buttons {
display: flex;
gap: 32px;
margin-top: 8px;
}
/* 通话按钮基础样式 */
.call-button {
width: 64px;
height: 64px;
border-radius: 50%;
border: none;
display: flex;
align-items: center;
justify-content: center;
cursor: pointer;
transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
}
/* 接听按钮 */
.accept-call {
background: #e2c2ff;
color: white;
}
.accept-call:hover {
background: #d4aeeb;
transform: scale(1.1) rotate(15deg);
box-shadow: 0 6px 20px rgba(194, 158, 255, 0.4);
}
/* 拒绝按钮 */
.reject-call {
background: #98d6d0;
color: white;
}
.reject-call:hover {
background: #99c8c9;
transform: scale(1.1) rotate(-15deg);
box-shadow: 0 6px 20px rgba(120, 214, 196, 0.4);
}
/* 按钮图标 */
.call-button svg {
width: 28px;
height: 28px;
transition: transform 0.3s ease;
}
.call-button:hover svg {
transform: scale(1.1);
}
/* 动画定义 */
@keyframes modalSlideIn {
from {
opacity: 0;
transform: translate(-50%, -45%);
}
to {
opacity: 1;
transform: translate(-50%, -50%);
}
}
@keyframes avatar-pulse {
0% {
box-shadow: 0 0 0 0 rgba(108, 140, 213, 0.4);
}
70% {
box-shadow: 0 0 0 20px rgba(108, 140, 213, 0);
}
100% {
box-shadow: 0 0 0 0 rgba(108, 140, 213, 0);
}
}
@keyframes status-blink {
0%, 100% {
opacity: 1;
}
50% {
opacity: 0.4;
}
/* 响应式调整 */
@media screen and (max-width: 480px) {
.voice-call-modal {
width: 85%;
padding: 24px 20px;
}
.caller-avatar {
width: 80px;
height: 80px;
}
.caller-name {
font-size: 20px;
}
.call-buttons {
gap: 24px;
}
.call-button {
width: 56px;
height: 56px;
}
}
/* 浏览器分享样式 */
.browser-share {
background: #333; /* 深色背景 */
border-radius: 12px;
overflow: hidden;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2); /* 阴影 */
width: 100%;
max-width: 380px;
font-family: 'Cormorant Garamond', serif; /* 哥特字体 */
}
/* 头部 */
.browser-share-header {
display: flex;
align-items: center;
padding: 8px 12px;
border-bottom: 1px solid #444; /* 深色边框 */
background: #2a2a2a; /* 深色背景 */
}
/* 图标 */
.browser-share-icon {
width: 16px;
height: 16px;
margin-right: 6px;
color: #999;
}
/* 标题 */
.browser-share-title {
font-size: 13px; /* 增大字号 */
color: #999; /* 深灰色 */
}
/* 预览 */
.browser-share-preview {
cursor: pointer;
transition: all 0.2s ease;
padding: 15px; /* 增加内边距 */
}
.browser-share-preview:hover {
background: rgba(255, 255, 255, 0.05); /* 浅色悬停 */
}
/* 预览标题 */
.preview-title {
font-size: 16px; /* 增大字号 */
font-weight: 500;
color: #ddd; /* 浅色文本 */
margin-bottom: 8px; /* 增加间距 */
line-height: 1.4;
}
/* 元信息 */
.preview-meta {
display: flex;
align-items: center;
gap: 10px; /* 增加间距 */
margin-bottom: 8px;
font-size: 12px; /* 增大字号 */
color: #999;
}
/* 来源 */
.preview-source {
color: #ddd; /* 浅色文本 */
font-weight: 500;
}
/* 描述 */
.preview-description {
font-size: 13px; /* 增大字号 */
color: #bbb; /* 浅灰色 */
line-height: 1.5;
margin-bottom: 8px;
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
}
/* URL */
.preview-url {
font-size: 12px;
color: #999;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/* 动画 */
@keyframes share-appear {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
.browser-share {
animation: share-appear 0.3s ease-out;
}
/* 响应式调整 */
@media screen and (max-width: 480px) {
.browser-share {
max-width: 100%;
}
.preview-title {
font-size: 15px;
}
.preview-description {
font-size: 12px;
}
}
</style>
</head>
<body>
<div class="phone-container">
<div class="phone-charm"></div>
<div class="phone-notch">
<div class="notch-sensor"></div>
<div class="notch-camera"></div>
<div class="notch-speaker"></div>
<div class="notch-sensor"></div>
</div>
<div class="chat-container">
<audio class="voice-call-audio" loop>
<source src="https://files.catbox.moe/23kcq4.mp3" type="audio/mpeg">
</audio>
<div class="voice-call-modal" style="display: none;">
<div class="modal-content">
<img src="https://files.catbox.moe/t511iu.png" class="caller-avatar" alt="Caller Avatar">
<div class="caller-name">$1</div>
<div class="call-status">语音通话邀请...</div>
<div class="call-buttons">
<button class="call-button accept-call">
<svg viewBox="0 0 24 24" width="24" height="24">
<path fill="currentColor" d="M20.01 15.38c-1.23 0-2.42-.2-3.53-.56a.977.977 0 0 0-1.01.24l-1.57 1.97c-2.83-1.35-5.48-3.9-6.89-6.83l1.95-1.66c.27-.28.35-.67.24-1.02c-.37-1.11-.56-2.3-.56-3.53c0-.54-.45-.99-.99-.99H4.19C3.65 3 3 3.24 3 3.99C3 13.28 10.73 21 20.01 21c.71 0 .99-.63.99-1.18v-3.45c0-.54-.45-.99-.99-.99z"/>
</svg>
</button>
<button class="call-button reject-call">
<svg viewBox="0 0 24 24" width="24" height="24">
<path fill="currentColor" d="M12 9c-1.6 0-3.15.25-4.6.72v3.1c0 .39-.23.74-.56.9c-.98.49-1.87 1.12-2.66 1.85c-.18.18-.43.28-.7.28c-.28 0-.53-.11-.71-.29L.29 13.08a.996.996 0 0 1 0-1.41c1.34-1.34 2.87-2.42 4.55-3.2C6.87 7.81 9.04 7 12 7s5.13.81 7.16 2.47c1.68.78 3.21 1.86 4.55 3.2c.39.39.39 1.02 0 1.41l-2.49 2.49c-.18.18-.43.29-.71.29c-.27 0-.52-.11-.7-.28c-.79-.74-1.69-1.36-2.67-1.85c-.33-.16-.56-.51-.56-.9v-3.1C15.15 9.25 13.6 9 12 9z"/>
</svg>
</button>
</div>
</div>
</div>
<div class="transfer-modal" style="display: none;">
<div class="transfer-content">
<img src="https://files.catbox.moe/t511iu.png" class="transfer-avatar" alt="Transfer Avatar">
<div class="transfer-title">转账给 $1</div>
<div class="transfer-form">
<div class="amount-input-group">
<span class="amount-symbol">¥</span>
<input type="number" class="amount-input" placeholder="输入金额…" min="0">
</div>
<input type="text" class="note-input" placeholder="输入备注…">
<div class="transfer-buttons">
<button class="transfer-button confirm-transfer">确认</button>
<button class="transfer-button cancel-transfer">取消</button>
</div>
</div>
</div>
</div>
<div class="chat-header">
<div class="header-info">
<img src="https://files.catbox.moe/t511iu.png" class="header-avatar">
<div class="header-text">
<h2>$1</h2>
<div class="header-status">
<div class="status-dot"></div>
在线中
</div>
</div>
</div>
<div class="header-icons">
<svg class="header-icon diary-btn" viewBox="0 0 24 24">
<path fill="currentColor" d="M19,3H14.82C14.4,1.84 13.3,1 12,1C10.7,1 9.6,1.84 9.18,3H5C3.9,3 3,3.9 3,5V19C3,20.1 3.9,21 5,21H19C20.1,21 21,20.1 21,19V5C21,3.9 20.1,3 19,3M12,3C12.55,3 13,3.45 13,4C13,4.55 12.55,5 12,5C11.45,5 11,4.55 11,4C11,3.45 11.45,3 12,3M7,7H17V5H19V19H5V5H7V7Z"/>
</svg>
<svg class="header-icon call-btn" viewBox="0 0 24 24">
<path fill="currentColor" d="M12,2A3,3 0 0,1 15,5V11A3,3 0 0,1 12,14A3,3 0 0,1 9,11V5A3,3 0 0,1 12,2M19,11C19,14.53 16.39,17.44 13,17.93V21H11V17.93C7.61,17.44 5,14.53 5,11H7A5,5 0 0,0 12,16A5,5 0 0,0 17,11H19Z"/>
</svg>
<svg class="header-icon transfer-btn" viewBox="0 0 24 24">
<path fill="currentColor" d="M20,8H4V6H20M20,18H4V12H20M20,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V6C22,4.89 21.1,4 20,4Z"/>
</svg>
</div>
</div>
<div class="chat-messages">
$2
</div>
<div class="chat-input">
<button class="emoji-btn">
<svg viewBox="0 0 24 24" width="20" height="20">
<path fill="currentColor" d="M12,2C6.477,2,2,6.477,2,12c0,5.523,4.477,10,10,10s10-4.477,10-10C22,6.477,17.523,2,12,2z M12,20c-4.418,0-8-3.582-8-8 s3.582-8,8-8s8,3.582,8,8S16.418,20,12,20z M15.5,11c0.828,0,1.5-0.672,1.5-1.5S16.328,8,15.5,8S14,8.672,14,9.5S14.672,11,15.5,11z M8.5,11c0.828,0,1.5-0.672,1.5-1.5S9.328,8,8.5,8S7,8.672,7,9.5S7.672,11,8.5,11z M12,17.5c2.33,0,4.31-1.46,5.11-3.5H6.89 C7.69,16.04,9.67,17.5,12,17.5z"/>
</svg>
</button>
<div class="emoji-picker-container">
<emoji-picker></emoji-picker>
</div>
<input type="text" class="input-field" placeholder="输入聊天内容...">
<button class="send-btn">
<svg viewBox="0 0 24 24" width="20" height="20">
<path fill="currentColor" d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/>
</svg>
</button>
</div>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const emojiBtn = document.querySelector('.emoji-btn');
const emojiPickerContainer = document.querySelector('.emoji-picker-container');
const emojiPicker = document.querySelector('emoji-picker');
const textInput = document.querySelector('.input-field');
const sendBtn = document.querySelector('.send-btn');
const chatMessages = document.querySelector('.chat-messages');
const callBtn = document.querySelector('.call-btn');
const avatars = document.querySelectorAll('.avatar');
const messageContents = document.querySelectorAll('.message-content');
// 获取转账按钮和弹窗元素
const transferBtn = document.querySelector('.transfer-btn');
const transferModal = document.querySelector('.transfer-modal');
const cancelTransferBtn = document.querySelector('.cancel-transfer');
const confirmTransferBtn = document.querySelector('.confirm-transfer');
const amountInput = document.querySelector('.amount-input');
const noteInput = document.querySelector('.note-input');
// 为转账按钮添加点击事件
transferBtn.addEventListener('click', () => {
playSound('click');
// 显示转账弹窗
transferModal.style.display = 'block';
// 重置输入
amountInput.value = '';
noteInput.value = '';
// 设置焦点到金额输入框
setTimeout(() => amountInput.focus(), 300);
});
// 取消转账
cancelTransferBtn.addEventListener('click', () => {
playSound('click');
transferModal.style.display = 'none';
});
// 修改确认转账按钮的事件处理函数中的这部分代码
confirmTransferBtn.addEventListener('click', () => {
const amount = amountInput.value.trim();
const note = noteInput.value.trim();
if (!amount || isNaN(amount) || Number(amount) <= 0) {
// 添加输入框震动效果
amountInput.classList.add('shake');
setTimeout(() => amountInput.classList.remove('shake'), 500);
return;
}
playSound('send');
transferModal.style.display = 'none';
// 获取聊天对象名称
const chatName = document.querySelector('.header-text h2').textContent;
// 构建转账消息
let transferMessage;
if (note) {
// 如果有备注,使用新格式
transferMessage = `转账给$1:¥${amount}[备注:${note}`;
} else {
// 如果没有备注,只显示金额
transferMessage = `转账给$1:¥${amount}`;
}
// 发送转账消息到聊天系统
if (typeof triggerSlash === 'function') {
triggerSlash(`/send ${transferMessage}|/trigger`);
}
// 在本地聊天界面中添加转账消息
// 获取最后一条消息的时间
const lastMessage = chatMessages.querySelector('.message:last-child');
let lastTimeStr = '11:47'; // 默认时间
if (lastMessage) {
lastTimeStr = lastMessage.querySelector('.message-time').textContent;
}
// 解析最后一条消息的时间
const [hours, minutes] = lastTimeStr.split(':').map(Number);
// 计算新消息的时间(最后一条消息时间+1分钟)
let newMinutes = minutes + 1;
let newHours = hours;
if (newMinutes >= 60) {
newMinutes = 0;
newHours = (newHours + 1) % 24;
}
// 格式化新时间
const timeString = `${newHours.toString().padStart(2, '0')}:${newMinutes.toString().padStart(2, '0')}`;
// 创建新的转账卡片HTML
const messageHtml = `
<div class="message sent">
<div class="user_avatar avatar" style="background-size: cover; background-position: center;"></div>
<div class="message-wrapper">
<div class="transfer-card-wrapper">
<div class="transfer-card">
<div class="transfer-inner">
<div class="transfer-header">
<svg class="transfer-icon" viewBox="0 0 24 24">
<path fill="currentColor" d="M15,14V11H18V9L22,12.5L18,16V14H15M14,7.7V9H2V7.7L8,4L14,7.7M7,10H9V15H7V10M3,10H5V15H3V10M13,10V12.5L11,14.3V10H13M9.1,16L8.5,16.5L10.2,18H2V16H9.1M17,15V18H14V20L10,16.5L14,13V15H17Z"/>
</svg>
<div class="transfer-title">转账给${chatName}*゚</div>
</div>
<div class="transfer-amount">¥${amount}</div>
<div class="transfer-to">转账成功</div>
${note ? `<div class="transfer-note">备注: ${note}</div>` : ''}
</div>
</div>
</div>
<div class="message-time">${timeString}</div>
</div>
</div>
`;
// 添加新消息到聊天界面
chatMessages.insertAdjacentHTML('beforeend', messageHtml);
// 滚动到底部
chatMessages.scrollTop = chatMessages.scrollHeight;
});
// 为输入框添加键盘事件
amountInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
noteInput.focus();
}
});
noteInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
confirmTransferBtn.click();
}
});
// 添加输入框震动效果的CSS
const shakeStyle = document.createElement('style');
shakeStyle.textContent = `
@keyframes shake {
0%, 100% { transform: translateX(0); }
20%, 60% { transform: translateX(-5px); }
40%, 80% { transform: translateX(5px); }
}
.shake {
animation: shake 0.5s ease-in-out;
border-color: #ff4d4f !important;
}
`;
document.head.appendChild(shakeStyle);
// 音效对象
const sounds = {
click: new Audio('https://assets.mixkit.co/active_storage/sfx/2568/2568-preview.mp3'),
send: new Audio('https://assets.mixkit.co/active_storage/sfx/2570/2570-preview.mp3'),
emoji: new Audio('https://files.catbox.moe/gb0so5.mp3'),
bubble: new Audio('https://assets.mixkit.co/active_storage/sfx/2568/2568-preview.mp3'),
avatar: new Audio('https://assets.mixkit.co/active_storage/sfx/2575/2575-preview.mp3')
};
// 播放音效的函数
function playSound(soundType) {
const sound = sounds[soundType];
if(sound) {
sound.currentTime = 0;
sound.play().catch(err => console.log('音频播放失败:', err));
}
}
// 修改表情选择器样式
const style = document.createElement('style');
style.textContent = `
.emoji-picker-container {
position: absolute;
bottom: 60px;
left: 16px;
display: none;
z-index: 1000;
max-height: 300px;
overflow-y: auto;
background: #f8f5ff; /* 改为浅紫色背景 */
border-radius: 8px;
box-shadow: 0 3px 12px rgba(0, 0, 0, 0.1);
}
/* 表情选择器内部样式 */
emoji-picker {
--num-columns: 8;
width: 305px;
height: 300px;
--emoji-size: 1.25rem;
--background: #f8f5ff; /* 浅紫色背景 */
--border-color: #d9c4f5; /* 浅紫色边框 */
--border-radius: 10px;
--input-background: #e9e0f7; /* 浅紫色输入框 */
--input-text-color: #333; /* 深色文本 */
--category-icon-color: #ae94d1; /* 紫色图标 */
--category-icon-hover-color: #8e74b1; /* 悬停时变深 */
--search-input-focus-background: #e2d2fa; /* 聚焦时变亮 */
}
`;
document.head.appendChild(style);
// 为头像添加点击事件
avatars.forEach(avatar => {
avatar.addEventListener('click', () => {
playSound('avatar');
});
});
// 添加头像点击事件
const headerAvatar = document.querySelector('.header-avatar');
headerAvatar.addEventListener('click', () => {
playSound('avatar');
// 获取聊天对象名称
const chatName = document.querySelector('.header-text h2').textContent;
// 发送消息到聊天系统
if (typeof triggerSlash === 'function') {
}
});
// 为消息气泡添加点击事件
messageContents.forEach(content => {
content.addEventListener('click', () => {
playSound('bubble');
});
});
// 为输入框添加点击事件
textInput.addEventListener('click', () => {
playSound('bubble');
});
// 表情按钮点击事件
emojiBtn.addEventListener('click', () => {
playSound('emoji');
emojiPickerContainer.style.display = emojiPickerContainer.style.display === 'none' ? 'block' : 'none';
});
// 选择表情事件
emojiPicker.addEventListener('emoji-click', (event) => {
playSound('click');
const emoji = event.detail.unicode;
const start = textInput.selectionStart;
const end = textInput.selectionEnd;
const text = textInput.value;
textInput.value = text.slice(0, start) + emoji + text.slice(end);
const newCursorPosition = start + emoji.length;
textInput.setSelectionRange(newCursorPosition, newCursorPosition);
emojiPickerContainer.style.display = 'none';
textInput.focus();
});
// 发送按钮点击事件
sendBtn.addEventListener('click', () => {
const messageText = textInput.value.trim();
if (messageText) {
playSound('send');
// 向聊天系统发送消息
if (typeof triggerSlash === 'function') {
triggerSlash(`/send 回复和$1的聊天:${messageText}|/trigger`);
}
// 获取最后一条消息的时间
const lastMessage = chatMessages.querySelector('.message:last-child');
let lastTimeStr = '11:47'; // 默认时间,以防没有之前的消息
if (lastMessage) {
lastTimeStr = lastMessage.querySelector('.message-time').textContent;
}
// 解析最后一条消息的时间
const [hours, minutes] = lastTimeStr.split(':').map(Number);
// 计算新消息的时间(最后一条消息时间+1分钟)
let newMinutes = minutes + 1;
let newHours = hours;
if (newMinutes >= 60) {
newMinutes = 0;
newHours = (newHours + 1) % 24;
}
// 格式化新时间
const timeString = `${newHours.toString().padStart(2, '0')}:${newMinutes.toString().padStart(2, '0')}`;
// 创建新消息HTML
const messageHtml = `
<div class="message sent">
<div class="user_avatar avatar" style="background-size: cover; background-position: center;"></div>
<div class="message-wrapper">
<div class="message-content">${messageText}</div>
<div class="message-time">${timeString}</div>
</div>
</div>
`;
// 添加新消息到聊天界面
chatMessages.insertAdjacentHTML('beforeend', messageHtml);
// 为新添加的消息元素添加音效事件
const newAvatar = chatMessages.lastElementChild.querySelector('.avatar');
const newContent = chatMessages.lastElementChild.querySelector('.message-content');
newAvatar.addEventListener('click', () => {
playSound('avatar');
});
newContent.addEventListener('click', () => {
playSound('bubble');
});
// 滚动到底部并清空输入框
chatMessages.scrollTop = chatMessages.scrollHeight;
textInput.value = '';
}
});
// 按Enter键发送消息
textInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
sendBtn.click();
}
});
// 将日记按钮事件监听器移到这里
const diaryBtn = document.querySelector('.diary-btn');
diaryBtn.addEventListener('click', () => {
playSound('click');
if (typeof triggerSlash === 'function') {
}
});
callBtn.addEventListener('click', () => {
playSound('click');
// 获取聊天对象名称
const chatName = document.querySelector('.header-text h2').textContent;
// 显示通话弹窗
const modal = document.querySelector('.voice-call-modal');
modal.style.display = 'block';
// 播放通话音效
const callAudio = document.querySelector('.voice-call-audio');
callAudio.currentTime = 0;
callAudio.play();
// 获取挂断按钮
const rejectBtn = modal.querySelector('.reject-call');
let callTimeout;
// 添加挂断按钮点击事件
rejectBtn.addEventListener('click', () => {
modal.style.display = 'none';
callAudio.pause();
if (callTimeout) {
clearTimeout(callTimeout);
}
});
// 生成3-10秒的随机等待时间
const randomWaitTime = Math.floor(Math.random() * (10000 - 3000 + 1) + 3000);
// 随机时间后决定接听或拒绝
callTimeout = setTimeout(() => {
const randomNum = Math.random();
modal.style.display = 'none';
callAudio.pause();
if (randomNum <= 0.8) { // 80%概率接听
if (typeof triggerSlash === 'function') {
triggerSlash(`/send ${chatName}接听了语音通话|/trigger`);
}
} else { // 40%概率拒绝
if (typeof triggerSlash === 'function') {
triggerSlash(`/send ${chatName}拒绝了语音通话|/trigger`);
}
}
}, randomWaitTime);
});
// ... existing code ...
// 点击其他地方关闭表情选择器
document.addEventListener('click', (e) => {
if (!emojiBtn.contains(e.target) && !emojiPickerContainer.contains(e.target)) {
emojiPickerContainer.style.display = 'none';
}
});
// 预加载音频
Object.values(sounds).forEach(sound => {
sound.load();
});
// 动态监听新添加的消息
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.addedNodes.length) {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1) { // 元素节点
const newAvatars = node.querySelectorAll('.avatar');
const newContents = node.querySelectorAll('.message-content');
newAvatars.forEach(avatar => {
avatar.addEventListener('click', () => {
playSound('avatar');
});
});
newContents.forEach(content => {
content.addEventListener('click', () => {
playSound('bubble');
});
});
}
});
}
});
});
observer.observe(chatMessages, {
childList: true,
subtree: true
});
});
// 存储对方的所有消息
const receivedMessages = Array.from(document.querySelectorAll('.message.received'));
// 创建音效对象
const messageSound = new Audio('https://files.catbox.moe/b4amzm.mp3');
// 检查是否是最新的界面
function isLatestInterface() {
const currentTimestamp = Date.now();
const lastTimestamp = parseInt(localStorage.getItem('lastInterfaceTimestamp') || '0');
// 更新时间戳
localStorage.setItem('lastInterfaceTimestamp', currentTimestamp.toString());
// 如果当前时间戳与上一个时间戳相差不到100ms,说明是同一个界面的复制
return (currentTimestamp - lastTimestamp) > 100;
}
function showMessages() {
// 检查是否有我方消息
const hasSentMessages = document.querySelectorAll('.message.sent').length > 0;
// 检查是否是最新界面
const isLatest = isLatestInterface();
if (!isLatest || !hasSentMessages) {
// 不是最新界面或没有我方消息时,直接显示所有消息
receivedMessages.forEach(msg => {
msg.style.display = 'flex';
// 播放消息音效
messageSound.currentTime = 0;
messageSound.play();
});
return;
}
// 最新界面且有我方消息时,使用渐进显示效果
receivedMessages.forEach(msg => {
msg.style.display = 'none';
});
// 随机打字时间(1-3秒)
function getRandomTypingTime() {
return Math.floor(Math.random() * (3000 - 1000 + 1) + 1000);
}
// 随机消息间隔时间(0.5-1.5秒)
function getRandomDelay() {
return Math.floor(Math.random() * (1500 - 500 + 1) + 500);
}
// 打字动画效果
function typeMessage(messageContent, originalContent, onComplete) {
// 检查是否包含特殊内容
if (originalContent.includes('random-image-container') ||
originalContent.includes('typing-indicator') ||
originalContent.includes('<div') ||
originalContent.includes('<img')) {
// 如果包含特殊内容,直接显示原始HTML
messageContent.innerHTML = originalContent;
messageSound.currentTime = 0;
messageSound.play();
onComplete();
return;
}
const typingIndicator = document.createElement('div');
typingIndicator.className = 'typing-indicator';
typingIndicator.innerHTML = '<span class="typing-dot"></span><span class="typing-dot"></span><span class="typing-dot"></span>';
messageContent.textContent = '';
messageContent.appendChild(typingIndicator);
// 随机打字时间
const typingTime = getRandomTypingTime();
setTimeout(() => {
// 渐变过渡效果
typingIndicator.style.transition = 'opacity 0.5s';
typingIndicator.style.opacity = '0';
setTimeout(() => {
typingIndicator.remove();
messageContent.textContent = '';
let charIndex = 0;
const typeChar = () => {
if (charIndex === 0) {
// 在开始显示文字时就播放音效
messageSound.currentTime = 0;
messageSound.play();
}
if (charIndex < originalContent.length) {
messageContent.textContent += originalContent.charAt(charIndex);
charIndex++;
setTimeout(typeChar, 50);
} else {
onComplete();
}
};
typeChar();
}, 500);
}, typingTime);
}
// 逐条显示消息
function showMessagesSequentially(messages, currentIndex = 0) {
if (currentIndex >= messages.length) return;
const message = messages[currentIndex];
const messageContent = message.querySelector('.message-content');
const originalContent = messageContent.innerHTML;
// 显示消息容器
message.style.display = 'flex';
// 开始打字动画
typeMessage(messageContent, originalContent, () => {
// 当前消息显示完成后,延迟显示下一条
setTimeout(() => {
showMessagesSequentially(messages, currentIndex + 1);
}, getRandomDelay());
});
}
// 添加CSS样式
const style = document.createElement('style');
style.textContent = `
.typing-indicator {
display: inline-flex;
gap: 2px; /* 减小点之间的间距 */
padding: 2px 4px; /* 减小内边距 */
margin-top: 2px;
animation: none; /* 移除整体动画 */
}
.typing-dot {
width: 3px; /* 减小点的大小 */
height: 3px;
background: #999; /* 使用更柔和的颜色 */
border-radius: 50%;
animation: subtle-typing 1.5s infinite; /* 减慢动画速度,使用更柔和的动画 */
}
@keyframes subtle-typing {
0%, 100% {
transform: translateY(0);
opacity: 0.5;
}
50% {
transform: translateY(-1px); /* 减小上下移动的幅度 */
opacity: 0.8;
}
}
`;
document.head.appendChild(style);
// 延迟一段时间后开始显示消息
setTimeout(() => {
showMessagesSequentially(receivedMessages);
}, 1000);
}
// 启动消息显示
showMessages();
function handleBrowserHistoryClick(content) {
// 播放精致的点击音效
const clickSound = new Audio('https://files.catbox.moe/gb0so5.mp3');
clickSound.volume = 0.6; // 调整音量
clickSound.play().catch(err => console.log('音频播放失败:', err));
// 添加点击视觉反馈
const preview = document.querySelector('.browser-share-preview');
preview.style.transform = 'scale(0.98)';
setTimeout(() => {
preview.style.transform = 'scale(1)';
}, 100);
// 从预览内容中获取URL
const urlElement = document.querySelector('.preview-url');
const url = urlElement ? urlElement.textContent : '';
// 发送消息到聊天系统,包含URL信息
if (typeof triggerSlash === 'function') {
triggerSlash(`/send 查看${content}浏览器内容
${url}|/trigger`);
}
}
</script>
</body>
</html>
index.html
style.css
index.js
index.html