在?《Tailwind CSS 實戰:基于 Kooboo 構建 AI 對話框頁面(五)》?中,完成了語音交互功能的優化。本文作為該系列教程的第六篇,將聚焦于圖片上傳功能的開發。通過集成圖片上傳與預覽能力,我們將進一步完善 AI 對話框的交互體驗,實現圖文混合消息的發送。效果如下:
一、功能需求分析
本次開發需實現以下核心功能:
- 圖片上傳入口:在語音按鈕右側添加圖片上傳圖標,點擊后觸發文件選擇器。
- 文件驗證:限制僅允許上傳 JPG/PNG 等圖片格式,文件大小不超過 5MB。
- 實時預覽:選擇圖片后,在消息氣泡中立即顯示預覽圖。
- 圖文混合發送:支持同時發送文本與圖片,保持原有對話邏輯。
我們將使用?Tailwind CSS?實現界面布局,通過?原生 JavaScript?處理文件讀取和驗證,確保功能簡潔高效。
二、HTML結構搭建
首先,在 HTML 中添加圖片上傳相關元素。以下是輸入區域的核心代碼:
<!-- 輸入區域 -->
<div class="bg-[var(--bg-primary)] p-4 border-t border-[var(--border-color)]"><div class="flex space-x-2"><!-- 輸入框包裝器 --><div class="input-wrapper relative"><!-- 語音按鈕(左側) --><button id="voiceButton" class="voice-button"><i class="fa fa-microphone"></i></button><!-- 新增圖片上傳按鈕(右側) --><button id="imageUploadButton" class="image-upload-button"><i class="fa fa-image"></i> <!-- Font Awesome圖片圖標 --></button><input id="messageInput"type="text" placeholder="輸入消息..." class="message-input flex-1 w-full p-2 border border-[var(--border-color)] rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500 bg-[var(--bg-secondary)] text-[var(--text-primary)]"></div><!-- 原有發送按鈕(省略) --></div>
</div><!-- 新增文件上傳隱藏輸入 --><input type="file" id="imageInput" accept="image/*" style="display: none;">
關鍵點解析:
- 圖標按鈕布局:
- 語音按鈕(左)和圖片按鈕(右)通過?
relative
?定位包裹在輸入框兩側。 - 使用 Tailwind 的?
flex
?和?space-x-2
?實現水平排列,relative
?確保按鈕可以絕對定位在輸入框兩側。
- 語音按鈕(左)和圖片按鈕(右)通過?
- 隱藏文件輸入框:
<input type="file">
?設置?display: none
?隱藏,通過?accept="image/*"
?限制僅圖片格式可選。id="imageInput"
?用于 JavaScript 中獲取元素。
三、CSS 樣式設計
為了讓按鈕對稱顯示并預留空間,需要調整輸入框和按鈕的樣式。在?<head>
?中添加以下樣式:
<style>
/* 新增圖片上傳 */.image-upload-button {position: absolute; /* 絕對定位 */right: 8px; /* 右側間距 */top: 50%; /* 垂直居中 */transform: translateY(-50%); /* 垂直居中偏移 */width: 32px;height: 32px;display: flex;align-items: center;justify-content: center;cursor: pointer;color: var(--text-secondary); /* 次級文本色 */background: transparent;border: none;z-index: 10; /* 確保層級在輸入框上方 */}.image-upload-button:hover {color: var(--accent-color); /* 懸停時強調色 */}/* 輸入框寬度調整(為上傳按鈕騰出空間) */.message-input {padding-left: 40px !important; /* 原有左側語音按鈕 */padding-right: 40px !important; /* 新增右側上傳按鈕 */}/* 圖片預覽樣式 */.image-preview {max-width: 200px; /* 最大寬度 */max-height: 200px; /* 最大高度 */border-radius: 8px; /* 圓角 */margin-top: 8px; /* 與文本間距 */object-fit: contain; /* 保持比例,避免拉伸 */box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 輕微陰影 */}</style>
設計思路:
- 對稱布局:通過?
position: absolute
?將圖片按鈕定位在輸入框右側,與左側語音按鈕對稱。 - 交互反饋:懸停時顏色變化(
var(--accent-color)
)提示用戶可點擊。 - 預覽控制:
max-width/max-height
?限制圖片顯示區域,object-fit: contain
?確保圖片完整顯示且不變形。
四、圖片上傳功能的實現解析
接下來編寫Javascript核心邏輯代碼,實現文件選擇、驗證、預覽和消息展示。
1. 界面元素與事件綁定
// DOM元素獲取
const imageUploadButton = document.getElementById('imageUploadButton');
const imageInput = document.getElementById('imageInput');
const messageContainer = document.getElementById('messageContainer');
const messageInput = document.getElementById('messageInput');// 按鈕點擊事件綁定
imageUploadButton.addEventListener('click', () => {imageInput.click(); // 觸發隱藏的文件選擇器
});
關鍵點:
- 使用隱藏的
<input type="file">
實現文件選擇 - 視覺上通過圖標按鈕觸發,保持界面整潔
accept="image/*"
屬性在 HTML 中已限制僅允許圖片格式
2. 文件驗證與預覽實現
// 文件選擇事件處理
imageInput.addEventListener('change', (e) => {const file = e.target.files[0];if (!file) return;// 類型驗證const isImage = file.type.startsWith('image/');if (!isImage) {alert('請選擇有效的圖片文件');return;}// 大小驗證const MAX_IMAGE_SIZE = 5 * 1024 * 1024; // 5MBif (file.size > MAX_IMAGE_SIZE) {alert(`圖片大小不能超過 ${MAX_IMAGE_SIZE / (1024 * 1024)}MB`);return;}// 圖片預覽const reader = new FileReader();reader.onload = (event) => {const imagePreview = document.createElement('img');imagePreview.className = 'image-preview'; // 應用Tailwind樣式imagePreview.src = event.target.result; // Base64 URL// 創建包含圖片的消息氣泡const userMessageHtml = `<div class="flex items-start space-x-2 justify-end"><div class="max-w-[70%]"><div class="bg-blue-600 text-white p-4 rounded-lg rounded-tr-none shadow-sm"><div>${messageInput.value}</div> <!-- 保留輸入框文本 -->${imagePreview.outerHTML} <!-- 插入圖片 --><span class="text-xs text-blue-200 mt-1 block">${getCurrentTime()}</span></div></div><div class="w-8 h-8 rounded-full bg-blue-500 flex items-center justify-center"><span class="text-white">我</span></div></div>`;messageContainer.insertAdjacentHTML('beforeend', userMessageHtml);messageInput.value = ''; // 清空輸入框scrollToBottom(); // 滾動到最新消息};reader.readAsDataURL(file); // 讀取文件為Base64
});
技術點詳解:
-
文件驗證邏輯:
file.type
獲取 MIME 類型,驗證是否為圖片file.size
直接獲取字節數,與常量比較- 驗證失敗時通過
alert
提供明確反饋
-
預覽機制:
FileReader
異步讀取文件內容readAsDataURL
將圖片轉為可直接預覽的 Base64 格式- 動態創建
<img>
元素并設置src
屬性
-
樣式控制:
.image-preview
類限制最大尺寸為 200pxobject-fit: contain
保持圖片比例不變形rounded-lg
實現圓角效果增強視覺體驗
3. 圖文混合消息處理
// 消息氣泡HTML結構
const userMessageHtml = `<div class="flex items-start space-x-2 justify-end"><div class="max-w-[70%]"><div class="bg-blue-600 text-white p-4 rounded-lg rounded-tr-none shadow-sm"><div>${messageInput.value}</div> <!-- 文本內容 -->${imagePreview.outerHTML} <!-- 圖片預覽 --><span class="text-xs text-blue-200 mt-1 block">${getCurrentTime()}</span></div></div><div class="w-8 h-8 rounded-full bg-blue-500 flex items-center justify-center"><span class="text-white">我</span></div></div>
`;
設計亮點:
- 文本和圖片自然垂直排列,保持視覺層次
- 使用
max-w-[70%]
限制消息寬度,避免過寬影響閱讀 - 通過
flex items-start
確保頭像與消息頂部對齊 rounded-tr-none
實現對話氣泡的尖角效果
4. AI 回復與界面交互
// 模擬AI回復
setTimeout(() => {addAIResponse("我看到您上傳的圖片了。目前我還不能識別圖片中的文字,不過這是我未來的功能之一!");
}, 1000);// 自動滾動到底部
function scrollToBottom() {messageContainer.scrollTop = messageContainer.scrollHeight;
}
用戶體驗優化:
- 添加延遲模擬 AI 思考過程
- 自動滾動確保最新消息始終可見
- 保持原有語音合成功能不變,支持 AI 回復的語音播放
5. 錯誤處理與用戶反饋
// 文件驗證失敗提示
if (!isImage) {alert('請選擇有效的圖片文件');return;
}if (file.size > MAX_IMAGE_SIZE) {alert(`圖片大小不能超過 ${MAX_IMAGE_SIZE / (1024 * 1024)}MB`);return;
}// 圖片預覽錯誤處理(代碼中未顯式實現,但建議添加)
reader.onerror = () => {alert('圖片預覽失敗,請重試');
};
健壯性保障:
- 提供明確的錯誤類型提示
- 驗證失敗后立即終止流程
UI 細節:
- 精確控制輸入框內邊距,為兩側按鈕留出空間
- 圖片預覽區域限制尺寸同時保持比例
- 懸停效果提供明確的交互反饋
五、功能測試
操作步驟 | 預期結果 |
---|---|
點擊圖片圖標選擇非圖片文件 | 彈出提示 “請選擇有效的圖片文件” |
選擇超過 5MB 的圖片文件 | 彈出提示 “圖片大小不能超過 5MB” |
選擇正常圖片文件 | 消息氣泡中顯示圖片預覽,AI 回復 “我看到你上傳的圖片了...” |
輸入文本并選擇圖片 | 消息氣泡中同時顯示文本和圖片,文本在上、圖片在下 |
五、總結
-
圖標添加:
- 使用 Font Awesome 的
fa-image
圖標(需確保 Font Awesome 已正確引入) - 按鈕位于輸入框右側,與左側語音按鈕對稱
- 使用 Font Awesome 的
-
樣式調整:
- 輸入框左右兩側添加內邊距,為兩個按鈕騰出空間
- 定義圖片預覽樣式,支持最大 200px 顯示區域
- 上傳按鈕懸停時顯示強調色
-
功能實現:
- 點擊圖片圖標觸發隱藏的文件選擇輸入
- 支持 JPG/PNG 等常見圖片格式(通過
accept="image/*"
控制) - 上傳后在消息氣泡中顯示圖片預覽
- 保留原有文本輸入內容,支持圖文混合消息
-
交互優化:
- 圖片上傳后自動滾動到消息底部
- 保持原有語音識別按鈕的交互邏輯不變
- 文件輸入框隱藏處理,保持界面整潔