Files
chatroom/resources/views/chat/partials/guestbook-modal.blade.php
T
pllx 540d8bf6ff 新增:聊天室留言板模态弹窗(仿商店样式)
点击工具栏「留言」按钮弹出留言板弹窗,不再跳转新页面。

新建文件:
- guestbook-modal.blade.php — 蓝白渐变标题栏、三Tab切换、留言卡片列表、内嵌写留言表单
- guestbook.js — 完整的AJAX加载/提交/删除逻辑,绑定所有事件

修改文件:
- toolbar.blade.php — 留言按钮 data-toolbar-url → data-toolbar-action
- toolbar.js — 添加 guestbook 动作
- chat-room.js — 静态导入 guestbook 模块
- frame.blade.php — 引入留言弹窗
- routes/web.php — 新增 guestbook.data JSON 路由
- GuestbookController.php — 新增 data() 方法
2026-04-28 10:20:32 +08:00

439 lines
11 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
{{--
文件功能:星光留言板模态弹窗(仿商店弹窗样式)
供聊天室工具栏"留言"按钮使用,替代跳转留言板页面。
依赖 CSS:与商店弹窗一致的蓝白风格
依赖 JSresources/js/chat-room/guestbook.js
--}}
<style>
/* 留言板弹窗遮罩 */
#guestbook-modal {
display: none;
position: fixed;
inset: 0;
background: rgba(0, 0, 0, .5);
z-index: 9999;
justify-content: center;
align-items: center;
}
/* 弹窗主体 */
#guestbook-modal-inner {
background: #fff;
border-radius: 8px;
width: 720px;
max-width: 95vw;
max-height: 84vh;
display: flex;
flex-direction: column;
box-shadow: 0 8px 32px rgba(0, 0, 0, .3);
overflow: hidden;
position: relative;
}
/* 标题栏 */
#guestbook-modal-header {
background: linear-gradient(135deg, #336699, #5a8fc0);
color: #fff;
padding: 10px 16px;
display: flex;
align-items: center;
gap: 10px;
flex-shrink: 0;
}
#guestbook-modal-title {
font-size: 14px;
font-weight: bold;
flex: 1;
}
#guestbook-modal-close {
cursor: pointer;
font-size: 18px;
opacity: .8;
transition: opacity .15s;
line-height: 1;
}
#guestbook-modal-close:hover {
opacity: 1;
}
/* Toast */
#guestbook-toast {
display: none;
margin: 6px 12px 0;
padding: 5px 10px;
border-radius: 4px;
font-size: 12px;
font-weight: bold;
flex-shrink: 0;
}
/* Tab 导航 */
#guestbook-tabs {
display: flex;
border-bottom: 1px solid #cde;
flex-shrink: 0;
background: #eef4fb;
}
.guestbook-tab {
flex: 1;
padding: 8px 6px;
background: transparent;
border: none;
color: #6b7280;
font-size: 12px;
cursor: pointer;
border-bottom: 2px solid transparent;
font-weight: bold;
transition: all .2s;
}
.guestbook-tab.active { color: #336699 !important; border-bottom-color: #336699 !important; }
.guestbook-tab:hover { color: #5a8fc0; }
/* 留言列表容器 */
#guestbook-list {
flex: 1;
overflow-y: auto;
padding: 10px 12px;
background: #f6faff;
}
/* 留言卡片 */
.gb-card {
background: #fff;
border: 1px solid #d0e4f5;
border-radius: 6px;
padding: 10px 12px;
margin-bottom: 8px;
transition: border-color .2s, box-shadow .2s;
}
.gb-card:hover {
border-color: #5a8fc0;
box-shadow: 0 2px 8px rgba(51, 102, 153, .18);
}
.gb-card.gb-secret {
border-color: #f9c7d3;
background: #fff5f7;
}
.gb-card.gb-secret:hover {
border-color: #e91e63;
box-shadow: 0 2px 8px rgba(233, 30, 99, .12);
}
.gb-card-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 6px;
font-size: 12px;
}
.gb-card-author {
display: flex;
align-items: center;
gap: 6px;
}
.gb-avatar {
width: 24px;
height: 24px;
border-radius: 50%;
background: #dbeafe;
color: #336699;
display: flex;
align-items: center;
justify-content: center;
font-size: 11px;
font-weight: bold;
flex-shrink: 0;
}
.gb-avatar.secret {
background: #fce4ec;
color: #c62828;
}
.gb-who {
font-weight: bold;
color: #225588;
}
.gb-arrow {
color: #9ca3af;
font-size: 11px;
}
.gb-towho {
font-weight: 600;
color: #336699;
}
.gb-towho.public {
color: #9ca3af;
font-style: italic;
}
.gb-secret-badge {
background: #fce4ec;
color: #c62828;
font-size: 10px;
font-weight: bold;
padding: 1px 6px;
border-radius: 8px;
margin-left: 4px;
}
.gb-time {
color: #9ca3af;
font-size: 11px;
}
.gb-body {
font-size: 13px;
color: #374151;
line-height: 1.6;
word-break: break-word;
padding: 2px 0 4px;
}
.gb-card-footer {
display: flex;
justify-content: flex-end;
gap: 8px;
margin-top: 4px;
}
.gb-btn {
font-size: 11px;
padding: 3px 10px;
border-radius: 4px;
border: none;
cursor: pointer;
font-weight: bold;
transition: opacity .15s;
}
.gb-btn:hover { opacity: .8; }
.gb-btn-reply {
background: #eef4fb;
color: #336699;
border: 1px solid #cde;
}
.gb-btn-reply:hover { background: #dbeafe; }
.gb-btn-delete {
background: #fee2e2;
color: #dc2626;
border: 1px solid #fecaca;
}
.gb-btn-delete:hover { background: #fecaca; }
/* 写留言按钮 */
#guestbook-write-btn-wrap {
flex-shrink: 0;
padding: 8px 12px;
background: #eef4fb;
border-top: 1px solid #cde;
text-align: center;
}
#guestbook-write-btn {
background: linear-gradient(135deg, #336699, #5a8fc0);
color: #fff;
border: none;
border-radius: 4px;
padding: 7px 20px;
font-size: 13px;
font-weight: bold;
cursor: pointer;
transition: opacity .15s;
width: 100%;
}
#guestbook-write-btn:hover { opacity: .85; }
/* 写留言表单(内嵌) */
#guestbook-write-form {
display: none;
flex-shrink: 0;
padding: 10px 12px;
background: #fff;
border-top: 1px solid #cde;
}
#guestbook-write-form.active { display: block; }
.gb-form-row {
margin-bottom: 8px;
}
.gb-form-row label {
display: block;
font-size: 12px;
font-weight: bold;
color: #336699;
margin-bottom: 4px;
}
.gb-form-row select,
.gb-form-row textarea {
width: 100%;
padding: 6px 8px;
border: 1px solid #cde;
border-radius: 4px;
font-size: 12px;
outline: none;
transition: border-color .2s;
box-sizing: border-box;
}
.gb-form-row select:focus,
.gb-form-row textarea:focus {
border-color: #336699;
}
.gb-form-row textarea {
resize: vertical;
min-height: 60px;
}
.gb-form-checkbox {
display: flex;
align-items: center;
gap: 6px;
font-size: 12px;
color: #555;
}
.gb-form-checkbox input[type="checkbox"] {
accent-color: #336699;
}
.gb-form-actions {
display: flex;
gap: 8px;
justify-content: flex-end;
}
.gb-form-actions button {
padding: 5px 14px;
border-radius: 4px;
font-size: 12px;
font-weight: bold;
cursor: pointer;
border: none;
transition: opacity .15s;
}
.gb-form-actions button:hover { opacity: .85; }
.gb-form-submit {
background: linear-gradient(135deg, #336699, #5a8fc0);
color: #fff;
}
.gb-form-cancel {
background: #e5e7eb;
color: #555;
}
/* 空状态 */
.gb-empty {
text-align: center;
color: #9ca3af;
padding: 40px 0;
font-size: 13px;
}
.gb-empty-icon {
font-size: 36px;
display: block;
margin-bottom: 10px;
}
/* 加载中 */
.gb-loading {
text-align: center;
color: #6366f1;
padding: 30px 0;
font-size: 13px;
}
/* 分页 */
#guestbook-pager {
flex-shrink: 0;
padding: 8px 12px;
background: #eef4fb;
border-top: 1px solid #cde;
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
font-size: 12px;
}
#guestbook-pager button {
padding: 3px 10px;
border: 1px solid #cde;
border-radius: 4px;
background: #fff;
color: #336699;
cursor: pointer;
font-size: 11px;
font-weight: bold;
transition: all .15s;
}
#guestbook-pager button:hover {
background: #dbeafe;
}
#guestbook-pager button:disabled {
opacity: .4;
cursor: default;
}
#guestbook-pager span {
color: #6b7280;
}
</style>
<div id="guestbook-modal"
data-guestbook-data-url="{{ route('guestbook.data') }}"
data-guestbook-store-url="{{ route('guestbook.store') }}"
data-guestbook-destroy-url-template="{{ route('guestbook.destroy', '__ID__') }}">
<div id="guestbook-modal-inner">
{{-- 标题栏 --}}
<div id="guestbook-modal-header">
<div id="guestbook-modal-title">✉️ 星光留言板</div>
<span id="guestbook-modal-close" data-guestbook-modal-close></span>
</div>
{{-- Toast --}}
<div id="guestbook-toast"></div>
{{-- Tab 导航 --}}
<div id="guestbook-tabs">
<button class="guestbook-tab active" data-guestbook-tab="public">🌍 公共留言墙</button>
<button class="guestbook-tab" data-guestbook-tab="inbox">📥 我收件的</button>
<button class="guestbook-tab" data-guestbook-tab="outbox">📤 我发出的</button>
</div>
{{-- 留言列表 --}}
<div id="guestbook-list">
<div class="gb-loading">加载中…</div>
</div>
{{-- 写留言表单(内嵌) --}}
<div id="guestbook-write-form">
<form id="guestbook-form" method="POST">
@csrf
<div class="gb-form-row">
<label>📬 收件人 <span style="font-weight:normal;color:#9ca3af;">(留空则为公共留言)</span></label>
<select name="towho" id="gb-towho">
<option value="">🌍 公共留言(所有人可见)</option>
</select>
</div>
<div class="gb-form-row">
<label class="gb-form-checkbox">
<input type="checkbox" name="secret" value="1"> 🔒 悄悄话(仅双方可见)
</label>
</div>
<div class="gb-form-row">
<label>📝 留言内容 <span style="color:#dc2626;">*</span></label>
<textarea name="text_body" id="gb-text-body" rows="3" required placeholder="相逢何必曾相识,留下您的足迹吧..."></textarea>
</div>
<div class="gb-form-actions">
<button type="button" class="gb-form-cancel" data-gb-form-cancel>取消</button>
<button type="submit" class="gb-form-submit">✈️ 发送飞鸽</button>
</div>
</form>
</div>
{{-- 写留言按钮 --}}
<div id="guestbook-write-btn-wrap">
<button id="guestbook-write-btn" data-guestbook-write-btn>✏️ 写新留言</button>
</div>
{{-- 分页 --}}
<div id="guestbook-pager" style="display:none;">
<button id="gb-page-prev" data-gb-page="prev"> 上一页</button>
<span id="gb-page-info"></span>
<button id="gb-page-next" data-gb-page="next">下一页 </button>
</div>
</div>
</div>