发布作者: 小常
百度收录: 正在检测是否收录...
作品采用: 《 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 》许可协议授权
AI摘要:文章介绍了对留言板搜索功能的优化,包括后端和前端的改进。后端优化包括添加搜索参数处理、防止SQL注入、实现同时匹配用户名和留言内容的搜索逻辑,并在无结果时返回提示。前端优化包括支持模糊搜索、不区分大小写、同时匹配用户名和留言内容,并支持回车键快捷搜索。优化后的代码提高了搜索功能的实用性和用户体验。
Powered by Moonshot AI
1.后端优化:
保留了你原有的数据库连接方式和返回格式
添加了搜索参数处理,通过 GET 方法接收搜索关键词
使用 mysqli_real_escape_string 防止 SQL 注入攻击
实现了同时匹配用户名和留言内容的搜索逻辑
当搜索无结果时,返回相应的提示信息
2.搜索功能提升:
支持模糊搜索,只要包含关键词即可匹配
不区分大小写,提高搜索成功率
同时匹配用户名和留言内容,扩大搜索范围
支持回车键快捷搜索,操作更便捷
此优化保持了与你原有代码的兼容性,同时显著提升了搜索功能的实用性和用户体验。
getMessage.php
<?php
$conn = mysqli_connect('localhost', 'root', '1c133624154d8dbc', 'message');
if (!$conn) {
die(json_encode([
'code' => 500,
'msg' => mysqli_connect_error()
]));
}
// 获取搜索关键词并处理
$search = isset($_GET['search']) ? trim($_GET['search']) : '';
// 基础SQL语句
$sql = "select * from message";
// 如果有搜索关键词,添加搜索条件
if (!empty($search)) {
// 对搜索词进行安全处理,防止SQL注入
$searchTerm = mysqli_real_escape_string($conn, $search);
// 匹配用户名或留言内容,不区分大小写
$sql .= " where username like '%{$searchTerm}%' or content like '%{$searchTerm}%'";
}
// 保持按时间倒序排列
$sql .= " order by create_time desc";
$res = mysqli_query($conn, $sql);
$row = mysqli_fetch_all($res, MYSQLI_ASSOC);
mysqli_close($conn);
echo(json_encode([
'code' => 200,
'data' => $row,
'msg' => empty($row) && !empty($search) ? '未找到匹配的留言' : '数据获取成功'
]));
?>
以下为mail.html代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>小常的留言板</title>
<style>
* {
padding: 0;
margin: 0;
color: #fff;
box-sizing: border-box;
}
body {
background-image: linear-gradient(90deg, #e0c3fc 0%, #8ec5fc 100%);
padding: 50px 20px;
}
@media (min-width: 1200px) {
.messages {
width: 1200px;
}
}
.messages {
margin: auto;
padding: 50px;
background: linear-gradient(
to right bottom,
rgba(255, 255, 255, .6),
rgba(255, 255, 255, .3),
rgba(255, 255, 255, .2)
);
border-radius: 40px;
box-shadow: 0 10px 50px #00000019;
}
.search-container {
margin-bottom: 40px;
display: flex;
gap: 10px;
}
#searchInput {
flex: 1;
color: #000;
padding: 20px 30px;
border-radius: 10px;
border: none;
font-size: 24px;
}
#searchBtn {
background-image: linear-gradient(90deg, #e0c3fc 0%, #8ec5fc 100%);
border: none;
font-size: 24px;
padding: 0 30px;
border-radius: 10px;
cursor: pointer;
}
.form {
display: flex;
justify-content: center;
position: relative;
flex-direction: column;
width: 100%;
padding-bottom: 90px;
margin-bottom: 50px;
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
}
input:focus,
textarea:focus {
outline: none;
}
input,
textarea {
border: none;
color: #000;
margin-bottom: 40px;
border-radius: 10px;
padding: 30px;
width: 100%;
}
#username {
height: 90px;
font-size: 30px;
}
#message {
height: 200px;
font-size: 24px;
resize: none;
}
.messages h1 {
width: 100%;
text-align: left;
margin-bottom: 70px;
font-size: 80px;
background-image: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
letter-spacing: 10px;
}
#submitBtn {
position: absolute;
right: 0;
bottom: 0;
background-image: linear-gradient(90deg, #e0c3fc 0%, #8ec5fc 100%);
border: none;
font-size: 30px;
letter-spacing: 5px;
width: 180px;
height: 70px;
border-radius: 50PX;
cursor: pointer;
}
#messageBoard {
width: 100%;
text-align: left;
}
.no-results {
text-align: center;
font-size: 30px;
color: #667eea;
padding: 50px;
}
@keyframes messageFadeIn {
to {
opacity: 1;
}
}
.message {
width: 100%;
margin: 10px;
padding: 30px;
opacity: 0;
animation: messageFadeIn 0.5s ease forwards;
background-image: linear-gradient(90deg, #8ec5fc 0%, #e0c3fc 100%);
margin: 30px 0;
border-radius: 10px;
box-shadow: 0 10px 20px #00000026;
text-shadow: 0px 0px 20px #ffffff;
}
.message-info {
display: flex;
justify-content: space-between;
align-items: center;
font-size: 24px;
position: relative;
margin-bottom: 20px;
}
.info {
display: flex;
align-items: center;
gap: 20px;
}
.info img {
width: 80px;
height: 80px;
border-radius: 50%;
border: 5px #fff solid;
}
strong {
font-size: 28px;
letter-spacing: 2px;
}
.message-info span {
color: rgba(255, 255, 255, 0.8);
font-size: 18px;
}
.content {
font-size: 24px;
padding: 20px;
background-color: rgba(255, 255, 255, 0.2);
border-radius: 5px;
}
</style>
<link rel="icon" type="image/png" href="https://www.changhongbin.com/photo/lyb.png">
</head>
<body>
<div class="messages">
<h1>留言板</h1>
<!-- 搜索区域 -->
<div class="search-container">
<input type="text" id="searchInput" placeholder="搜索留言内容...">
<button id="searchBtn">搜索</button>
</div>
<div class="form">
<input type="text" id="username" placeholder="用户名" maxlength="20">
<textarea placeholder="留言内容" id="message" maxlength="500"></textarea>
<button id="submitBtn">留言</button>
</div>
<div id="messageBoard">
<!-- 留言会动态加载到这里 -->
</div>
</div>
<script>
let avatarUrls = [];
// 页面加载时初始化
window.onload = async () => {
try {
avatarUrls = await fetchAvatarUrls();
// 初始加载所有留言
loadMessages();
// 绑定搜索事件
document.getElementById('searchBtn').addEventListener('click', performSearch);
// 支持回车键搜索
document.getElementById('searchInput').addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
performSearch();
}
});
// 绑定提交事件
document.getElementById('submitBtn').addEventListener('click', submitMessage);
} catch (error) {
console.error('初始化失败:', error);
alert('加载失败,请刷新页面重试');
}
}
// 获取头像URL列表
async function fetchAvatarUrls() {
try {
const response = await fetch('/getAvatarUrls.php');
const { data } = await response.json();
return data || [];
} catch (error) {
console.error('获取头像失败:', error);
// 提供默认头像作为备选
return ['https://picsum.photos/seed/avatar1/200', 'https://picsum.photos/seed/avatar2/200'];
}
}
// 加载留言(支持搜索关键词)
async function loadMessages(searchKeyword = '') {
try {
const messageBoard = document.getElementById('messageBoard');
messageBoard.innerHTML = '<div class="loading">加载中...</div>';
// 构建请求URL,包含搜索关键词
let url = '/getMessage.php';
if (searchKeyword) {
url += `?search=${encodeURIComponent(searchKeyword)}`;
}
const response = await fetch(url);
const { data: messageList } = await response.json();
if (messageList && messageList.length > 0) {
messageBoard.innerHTML = messageList.map((item, index) => {
const avatarUrl = avatarUrls[index % avatarUrls.length] || 'https://picsum.photos/seed/default/200';
return `
<div class="message">
<div class="message-info">
<div class="info">
<img src="${avatarUrl}" alt="${item.username}的头像">
<strong>${item.username}</strong>
</div>
<span>发布于: ${item.create_time}</span>
</div>
<div class="content">
${item.content}
</div>
</div>
`;
}).join('');
} else {
messageBoard.innerHTML = '<div class="no-results">没有找到匹配的留言</div>';
}
} catch (error) {
console.error('加载留言失败:', error);
document.getElementById('messageBoard').innerHTML = '<div class="no-results">加载失败,请重试</div>';
}
}
// 执行搜索
function performSearch() {
const searchKeyword = document.getElementById('searchInput').value.trim();
loadMessages(searchKeyword);
}
// 提交留言
async function submitMessage() {
const submitBtn = document.getElementById('submitBtn');
const usernameInput = document.getElementById('username');
const messageInput = document.getElementById('message');
// 获取输入值
let username = usernameInput.value.trim();
const message = messageInput.value.trim();
// 验证输入
if (!message) {
alert('请输入留言内容');
return;
}
// 处理匿名用户
if (!username) {
username = '匿名';
}
// 防止重复提交
submitBtn.disabled = true;
submitBtn.innerText = '提交中...';
try {
const formData = new FormData();
formData.append('username', username);
formData.append('content', message);
const response = await fetch('/addMessage.php', {
method: 'post',
body: formData
});
const result = await response.json();
if (result.code === 200) {
// 提交成功,清空输入框并重新加载留言
usernameInput.value = '';
messageInput.value = '';
// 如果有搜索关键词,保持搜索状态,否则加载全部
const searchKeyword = document.getElementById('searchInput').value.trim();
loadMessages(searchKeyword);
alert('留言成功');
} else {
alert(result.msg || '留言失败,请重试');
}
} catch (error) {
console.error('提交留言失败:', error);
alert('网络错误,请重试');
} finally {
// 恢复按钮状态
submitBtn.disabled = false;
submitBtn.innerText = '留言';
}
}
// 获取当前时间
function getCurrentTime() {
const now = new Date();
const year = now.getFullYear();
const month = ('0' + (now.getMonth() + 1)).slice(-2);
const day = ('0' + now.getDate()).slice(-2);
const hours = ('0' + now.getHours()).slice(-2);
const minutes = ('0' + now.getMinutes()).slice(-2);
const seconds = ('0' + now.getSeconds()).slice(-2);
return `${year}/${month}/${day} ${hours}:${minutes}:${seconds}`;
}
</script>
</body>
</html>
—— 评论区 ——