xiuno 的内置聊天室(粗暴版本/非插件版本)

胥月 08月04日 302

<p>前两天用 AI 搞得聊天室,陆陆续续优化了两天,懒得后续优化了,打包发上来。</p>
<p><strong>注:非插件应用,直接把代码放到网站即可使用。</strong></p>
<p>懒得弄成插件,起初是用 json 存储数据的,但会遇到读取和写入同时进行时,偶发性让记录清空,尝试加上文件锁,但还是有清空情况。</p>
<p>于是现在的版本是改成了数据库存储的,但独立于论坛的数据库。</p>
<p>实现的原理很简单,获取本人已登录的个人信息,发消息时存入数据库即可(所以说其它程序也能使用,只要改一下获取用户信息的部分即可。甚至可以完全去掉改成博客那种留邮箱发消息的效果)。</p>
<p><span>表情功能是调用/plugin/Ty_face/face/arclist/目录下的表情,与表情插件无关,只是单纯的调用图片而已。你可以修改为你的目录。</span></p>
<p>预览:</p>
<p><img src="upload/attach/202508/88_DSQJYDJZUNGFJAZ.jpg" width="2048" height="1086" /></p>
<p><img src="upload/attach/202508/88_PDXSX57289X9887.jpg" width="690" height="1086" /></p>
<p><img src="upload/attach/202508/88_8ZQT8ZX57NNJBKP.jpg" width="692" height="1090" /></p>
<p>PS:如有需要,请自行修改文件目录,代码很垃,请勿点评。</p>
<p>html 部分</p>
<pre class="language-markup"><code>&lt;?php if (!empty($uid)): ?&gt;
&lt;style&gt;
.chat-container {
position: fixed;
bottom: 30px;
right: 30px;
z-index: 999;
transition: all 0.3s ease;
}

.chat-box {
width: 340px;
background-color: white;
border-radius: 8px;
box-shadow: 0 0 10px rgb(0 0 0 / 73%);
overflow: hidden;
display: none;
position: relative;
animation: fadeIn 0.3s ease;
}

@keyframes fadeIn {
from {
opacity: 0;
transform: scale(0.9);
}

to {
opacity: 1;
transform: scale(1);
}
}

@keyframes fadeOut {
from {
opacity: 1;
transform: scale(1);
}

to {
opacity: 0;
transform: scale(0.9);
}
}

.chat-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 15px;
background-color: #f7f6f1;
border-bottom: 1px solid #e2e8f0;
}

.chat-header h3 {
margin: 0;
font-size: 16px;
color: #333;
}

.chat-header button {
background: none;
border: none;
cursor: pointer;
font-size: 18px;
color: #333;
outline: none;
/ 取消按钮点击时的边框 /
}

div#chat-box {
position: relative;
overflow: hidden;
background-color: #f7f6f1;
padding: 2px 15px;
overflow-y: scroll;
height: 30rem;
}

.flex.items-start {
align-items: flex-start;
display: flex;
}

.max-w-\[75\%\].flex.flex-col.items-start {
--tw-space-x-reverse: 0;
margin-right: calc(.5rem var(--tw-space-x-reverse));
margin-left: calc(.5rem
(1 - var(--tw-space-x-reverse)));
align-items: flex-start;
flex-direction: column;
margin-left:.2rem;
}

.text-xs.text-blue-600.font-semibold.mb-1.no-underline {
text-decoration-line: none;
font-size: 0.75rem;
line-height: 1rem;
--tw-text-opacity: 1;
}

.bg-gray-200.mees {
font-size:.875rem;
line-height: 1.25rem;
padding:.5rem;
--tw-bg-opacity: 1;
background-color: #dfdfdf;
border-top-left-radius: 0;
border-radius:.75rem;
word-break: break-all;
border-radius:.75rem;
border-top-left-radius: 0;
color: #6A4A3C;
width: auto;
}

.flex {
display: flex;
}

.input#message-input {
flex: 1;
min-width: 0;
padding: 0.75rem 1rem;
font-size: 0.875rem;
border: none;
/ 取消输入框边框 /
border-right: none;
border-top-left-radius: 0.5rem;
border-bottom-left-radius: 2px;
outline: none;
/ 取消输入框聚焦时的边框 /
padding-left: 10px;
}

.text-white {
padding: 0.75rem 1rem;
color: white;
border: none;
border-top-right-radius: 0.5rem;
border-bottom-right-radius: 2px;
transition: all 0.3s ease;
flex-shrink: 0;
width: 48px;
display: flex;
align-items: center;
justify-content: center;
}

.chat-message-left {
margin-right: auto;
}

.chat-message-right {
margin-left: auto;
flex-direction: row-reverse;
}

.chat-message-right.max-w-\[75\%\].flex.flex-col.items-start {
align-items: flex-end;
}

.chat-message-right.bg-gray-200.mees {
border-top-left-radius:.75rem;
border-top-right-radius: 0;
}

.text-xs.text-gray-500 {
font-size: 8px;
color: #9ea4a9;
}

.beta-icon {
color: #2e8786;
font-size: 9px;
font-weight: 400;
position: relative;
top: -11px;
margin-left:.3rem;
}

.unread-indicator {
position: absolute;
top: 20%;
left: 50%;
transform: translate(-50%, -50%);
background-color: #f00;
color: white;
border-radius: 2%;
padding: 2px 10px;
font-size: 10px;
display: none;
}

.last-seen {
text-align: center;
color: #9ea4a9;
font-size: 10px;
margin-top: 5px;
z-index: 30;
}

button#refresh-button {
position: relative;
background: none;
border: none;
cursor: pointer;
font-size: 18px;
color: #333;
outline: none;
/ 取消刷新按钮点击时的边框 /
transition: transform 0.3s ease;
/ 添加过渡效果 /
}

button#refresh-button:disabled {
opacity: 0.6;
cursor: not-allowed;
}

input#message-input {
width: 100%;
height: 40px;
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
box-shadow: none;
padding-left: 10px;
}

.time&gt;span {
display: inline-block;
padding: 0 15px;
font-size: 9pt;
color: #fff;
border-radius: 2px;
background-color: #dcdcdc;
}

p.time {
margin: 9px 0;
text-align: center;
}

/ 缩小图标样式 /

.chat-icon {
position: fixed;
bottom: 40px;
right: 28px;
background-color: #38b2ac;
color: white;
width: 50px;
height: 50px;
border-radius: 50%;
display: flex
;
justify-content: center;
align-items: center;
cursor: pointer;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.2);
transition: all 0.3s ease;
}

input {
border: none;
outline: none;
}
.input#message-input {
/ 新增移动端适配 /
height: 44px; / 适配移动端输入框高度 /
padding: 0.75rem 1rem;
}

button#send-button {
/ 优化移动端点击区域 /
width: 60px;
}
.border-red-500 {
border: 2px solid #dc2626 !important; / 红色边框 /
color: #dc2626;
}

img.avatar-chat.w-8.h-8.rounded-full.mr-2 {
border-radius: 1.3rem;
}
.fa-paper-plane:before {
content: "\f1d8";
font-size: 22px;
}
/ 新增声音按钮样式 /
.sound-button {
background: none;
border: none;
cursor: pointer;
font-size: 18px;
color: #333;
outline: none;
transition: color 0.3s ease;
}

.sound-button.muted {
color: #9ea4a9;
}
/ 灯箱样式 /
.lightbox {
display: none; / 默认隐藏 /
position: absolute;
top: 47px;
left: 0;
width: 100%;
height: 83%;
background: rgba(0, 0, 0, 0.8);
z-index: 1000;
justify-content: center;
align-items: center;
overflow: auto;
}

.lightbox-content {
position: relative;
max-width: 100%;
text-align: center;
height: auto;
}

lightbox-image {

max-width: 100%;
max-height: 100vh;
display: block;
margin: 0 auto;
}

.close-lightbox {
position: absolute;
top: 10px;
right: 10px;
color: white;
font-size: 24px;
font-weight: bold;
cursor: pointer;
}
.video-container {
position: relative;
display: inline-block;
}

.play-button {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
cursor: pointer;
z-index: 1;
border-radius: .75rem;
border-top-left-radius: 0;
}

.play-icon {
font-size: 2.5rem;
font-weight: bold;
}
.video-container video {
border-radius: .75rem;
border-top-left-radius: 0;
}
img.chat-image {
border-radius: .75rem;
border-top-left-radius: 0;
display: block;
}
button#send-button {
background-image: linear-gradient(135deg, #38b2ac 0%, #2c7a7b 100%);
color: white;
border: none;
border-top-right-radius: 0.5rem;
border-bottom-right-radius: 0.5rem;
transition: all 0.3s ease;
flex-shrink: 0;
width: 48px;
display: flex
;
align-items: center;
justify-content: center;
outline: none;
}

.video-container {
display: block;
}

.video-container video {
vertical-align: top;
display: block;
margin: 0 auto;
}

.flex.items-start.chat-self {
justify-content: flex-end;
}

.chat-self .max-w-\[75\%\].flex.flex-col.items-start {
align-items: flex-end;
}

.chat-self img.avatar-chat.w-8.h-8.rounded-full.mr-2 {
order: 1;
margin-right: 0 !important;
margin-left: 0.5rem;
}

.chat-self .bg-gray-200.mees {
border-top-left-radius: .75rem;
border-top-right-radius: 0;
background-color: #b2e281!important;
}
/ 自身消息(靠右)的图片样式 /
.chat-self .chat-image {
border-top-right-radius: 0;
border-top-left-radius: 0.75rem; / 保持和消息气泡一致的左上圆角 /
border-bottom-left-radius: 0.75rem;
border-bottom-right-radius: 0.75rem;
}

/ 自身消息的视频容器及视频元素样式 /
.chat-self .video-container video,
.chat-self .video-container .play-button {
border-top-right-radius: 0; / 右上直角 /
border-top-left-radius: 0.75rem; / 左上圆角 /
border-bottom-left-radius: 0.75rem;
border-bottom-right-radius: 0.75rem;
}

/ 修正自身消息气泡与媒体元素的圆角一致性 /
.chat-self .bg-gray-200.mees, / 自身消息气泡 /
.chat-self .video-container, / 视频容器外层 /
.chat-self .chat-image {
border-top-right-radius: 0 !important; / 强制右上直角 /
border-top-left-radius: 0.75rem !important; / 统一左上圆角 /
}
/ 自身消息(靠右)的视频封面样式 /
.chat-self .video-container .video-cover {
border-top-right-radius: 0 !important; / 右上直角 /
border-top-left-radius: 0.75rem !important; / 左上圆角 /
border-bottom-left-radius: 0.75rem !important; / 保持底部圆角 /
border-bottom-right-radius: 0.75rem !important;
}
/ 左侧消息(他人消息)整体容器 /
.flex.items-start:not(.chat-self) {
/ 关键:让左侧消息占据左侧空间,右侧自动留白 /
margin-right: auto; / 右侧自动填充,消息气泡靠左 /
max-width: 90%; / 左侧消息最大宽度 70%(小于 80% 留出右侧空间) /
}

/ 右侧消息(自身消息)整体容器 /
.chat-self {
/ 关键:让右侧消息占据右侧空间,左侧自动留白 /
margin-left: auto; / 左侧自动填充,消息气泡靠右 /
max-width: 90%; / 右侧消息最大宽度 70%(对称设置) /
}

/ 消息气泡核心样式(统一调整) /
.bg-gray-200.mees {
max-width: 100% !important; / 气泡宽度基于外层容器的 70% /
width: auto;
word-wrap: break-word;
/ 移除之前冲突的全局 max-width,改为由外层容器控制 /
}
/ 原限制宽度的容器改为自动适应 /
.max-w-[75%].flex.flex-col.items-start {
max-width: 100% !important; / 取消 75% 固定限制,让外层消息容器(70%)生效 /
width: fit-content; / 容器宽度随内容自适应 /
}
/ 极长文本时进一步缩小气泡宽度 /
@media (min-width: 769px) {
.flex.items-start:not(.chat-self),
.chat-self {
max-width: 90%; / 大屏下可稍宽 /
}
}

/ 超小屏幕(如手机竖屏)极致适配 /
@media (max-width: 480px) {
.flex.items-start:not(.chat-self),
.chat-self {
max-width: 90%; / 小屏幕放宽到 90% /
}
}

/ 确保头像与消息气泡间距合理 /
.avatar-chat {
width: 25px !important; / 固定头像宽度,避免影响布局计算 /
height: 25px !important;
}
/ 聊天框样式(新增/修改部分) /
div#chat-box {
touch-action: auto; / 关键修复:允许内部滚动 /
overscroll-behavior-y: contain; / 阻止滚动影响页面主体 /
-webkit-overflow-scrolling: touch; / 移动端优化 /
user-select: text; / 允许内容选择 /
}

message-list {

user-select: text; / 明确消息列表可选择 /
}

/ 禁止非文本区域选择(如头像、时间戳) /
.avatar-chat, .text-xs.text-gray-500, .items-center, .chat-header {
user-select: none;
}

/ 输入框和发送按钮可交互 /

message-input {

user-select: auto; / 输入框允许文本选择 /
}

/ 防止聊天框外的区域响应滑动事件(可选,根据布局调整) /
.chat-container {
pointer-events: auto;
}
.meida1 {
display: flex
;
align-items: center;
padding-left: 6px;
position: relative;
background-color: #f7f6f1;
}
.mediaItem {
display: flex
;
justify-content: center;
align-items: center;
box-sizing: border-box;
margin: 0 5px;
cursor: pointer;
pointer-events: auto;
}
i.far.fa-smile {
font-size: 18px;
}

/ 表情面板样式 /
#faceBox {
position: absolute;
background: white;
border: 1px solid rgb(224, 224, 224);
padding: 5px;
margin-top: 4px;
background: #fff;
padding: 2px;
border: 1px #dfe6f6 solid;
border-radius: 10px;
height: 126px;
overflow: auto;
padding: 5px;
width: 232px;
top: 341px;
display: none;
pointer-events: auto;
}

#faceBox img {
width: 25px;
height: 25px;
margin: 2px;
cursor: pointer;
border: 0;
vertical-align: middle;
}
/ 消息状态提示 /
.status-text {
font-size: 0.7rem;
color: #666;
margin-top: 4px;
display: block;
text-align: left;
}

.status-sending {
color: #888;
}

.status-success {
color: green;
}

.status-error {
color: red;
}
.load-more-indicator {
text-align: center;
font-size: 0.75rem;
color: #666;
padding: 8px;
cursor: pointer;
}

.unread-indicator {
position: absolute;
top: 8%;
left: 80%;
transform: translate(-50%, -50%);
background-color: #878787;
color: white;
border-radius: 10px;
padding: 2px 5px;
font-size: 10px;
z-index: 10;
cursor: pointer;
}
&lt;/style&gt;
&lt;div class="chat-container"&gt;
&lt;div class="chat-box"&gt;
&lt;div class="chat-header"&gt;
&lt;div&gt;聊天室&lt;span class="beta-icon"&gt;beta V3.0&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
&lt;button id="refresh-button"&gt;</code></pre>

看过的人 (5)
  • 修罗之家
  • JimmyHung
  • 2222
  • 23948098
  • 六万
最新回复 (13)
返回