Guarp 04b2ec88e7 [v0.1.1] 新增功能
- 新增管理员日志上传
2025-02-21 19:52:33 +08:00

359 lines
7.9 KiB
Vue

<script setup>
import Message from "./Message.vue";
import {onMounted, onUnmounted, ref, watch} from "vue";
import api from "../../../utils/axios.js";
import store from "../../../store/index.js";
import swal from "../../../utils/sweetalert.js";
import AuthService from "../../../../services/auth.js";
const messages = ref(store.state.demos.board?.messages || []);
const amount = ref(store.state.demos.board?.amount || 0);
const currentPage = ref(store.state.demos.board?.currentPage || 1);
const pageLoading = ref(false);
const sendCD = ref(0);
const userInput = ref('');
async function refreshBoard(page, pageSize) {
if (!page) {
page = currentPage.value;
}
if (!pageSize) {
pageSize = 10;
}
try {
await api.post(`/viewboard`, {
PAGE: page,
PAGE_SIZE: pageSize
}).then(res => {
messages.value = res.data;
amount.value = Math.ceil(res.amount / pageSize);
store.commit('setDemoValue', {demo: 'board', value: {messages: messages.value}});
store.commit('setDemoValue', {demo: 'board', value: {amount: amount.value}});
})
} catch {
return 1;
}
return 0;
}
async function goPage(page) {
const messageTemp = messages.value
pageLoading.value = true;
currentPage.value = page;
if (await refreshBoard(page) === 0) {
store.commit('setDemoValue', {demo: 'board', value: {currentPage: page}});
pageLoading.value = false;
return;
}
swal.tip('error', '加载留言板失败...')
messages.value = messageTemp;
pageLoading.value = false;
}
async function sendMessage() {
if (sendCD.value !== 0) {
return;
}
if (userInput.value.trim().length === 0) {
swal.tip('info', '不得为空')
return;
}
sendCD.value = 'wait';
try {
const response = await api.post('/postmessage', {
TOKEN: AuthService.getToken(),
CONTENT: userInput.value
});
if (response.code !== 0) {
swal.tip('error', '发送失败');
return;
}
userInput.value = '';
sendCD.value = 5;
store.commit('setDemoValue', {demo: 'board', value: { sendCD: sendCD.value }});
await refreshBoard();
return;
} catch {
swal.tip('error', '网络连接错误...');
}
sendCD.value = 0;
}
async function clickRefresh() {
pageLoading.value = true;
if (await refreshBoard() !== 0) {
swal.tip('error', '刷新失败');
}
pageLoading.value = false;
}
let interval = null; // 定时器引用
function startCountdown() {
if (interval) clearInterval(interval); // 避免重复创建定时器
interval = setInterval(() => {
if (sendCD.value > 0) {
sendCD.value--;
store.commit('setDemoValue', {demo: 'board', value: { sendCD: sendCD.value }});
} else {
clearInterval(interval);
interval = null;
}
}, 1000);
}
// 监听 sendCD 变量
watch(sendCD, (newValue) => {
if (newValue > 0 && !interval) {
startCountdown();
}
});
onMounted(async () => {
sendCD.value = store.state.demos.board?.sendCD || 0;
await refreshBoard();
timer = setInterval(refreshBoard, 7000)
});
let timer
onUnmounted(() => {
clearInterval(timer);
})
</script>
<template>
<div class="container">
<div class="board-body">
<div class="message-container" :class="{loading: pageLoading}">
<Message v-for="msg in messages" :message="msg" @refresh-board="refreshBoard"/>
<div v-if="messages?.length === 0">正在加载...</div>
</div>
<div class="paging-container">
<div class="page-btn" :class="{active: currentPage === 1}" @click="goPage(1)" v-if="amount">1</div>
<span v-if="currentPage > 5">...</span>
<div class="page-btn" v-for="index in ((a, b) => Array.from({ length: b - a + 1 }, (_, i) => a + i))
(currentPage>4?(currentPage - 3):2, currentPage<amount-4?(currentPage + 4):amount-1)"
@click="goPage(index)" :class="{active: currentPage === index}">{{ index }}
</div>
<span v-if="currentPage < amount - 5">...</span>
<div class="page-btn" @click="goPage(amount)" :class="{active: currentPage === amount}" v-if="amount > 1">{{ amount }}</div>
</div>
</div>
<div class="sender-container">
<div class="sender-tips">
<img :src="store.getters.profileImage" alt="Avatar">
<div class="text">
<div>{{ store.state.userInfo.username || '请先登录' }}</div>
<div>{{ '&lt' + store.getters.userRole + '&gt' }}</div>
</div>
<div class="refresh-btn">
<button @click="clickRefresh">刷新</button>
</div>
</div>
<div class="sender-input">
<input class="message-input" v-model="userInput" @keydown.enter="sendMessage" :disabled="!store.state.userInfo.uid">
<button class="send-button" @click="sendMessage" :disabled="sendCD !== 0 || !store.state.userInfo.uid">
{{ sendCD === 0 ? '发送' : sendCD === 'wait' ? '稍等' : `${sendCD} ` }}
</button>
</div>
</div>
</div>
</template>
<style scoped>
.container {
display: flex;
align-items: center;
justify-items: flex-start;
width: 100%;
height: calc(100vh - 130px);
overflow: auto;
}
.board-body {
display: flex;
flex-direction: column;
gap: 20px;
width: 90%;
height: auto;
padding: 20px;
margin-bottom: 150px;
border-radius: 15px;
background: rgba(128, 128, 128, 0.06);
border: cyan solid 1px;
}
.theme-light .board-body {
border: #b2b2b2 solid 1px;
}
.message-container {
display: flex;
flex-direction: column;
justify-content: center;
gap: 15px;
transition: opacity 0.2s ease;
}
.message-container.loading {
opacity: 0.4;
}
.paging-container {
display: flex;
flex-direction: row;
align-items: center;
justify-content: center;
gap: 10px;
}
.page-btn {
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
background: black;
//width: 25px;
height: 25px;
padding: 0 5px;
border-radius: 4px;
border: cyan solid 1px;
}
.theme-light .page-btn {
background-color: white;
border: #b2b2b2 solid 1px;
}
.page-btn.active {
background: cyan;
color: black;
}
.theme-light .page-btn.active {
background: #2a2a2a;
color: white;
}
.sender-container {
margin: 20px;
background-color: #212121;
border: cyan solid 1px;
border-radius: 10px;
position: fixed;
bottom: 0;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 95%;
height: auto;
overflow: hidden;
}
.theme-light .sender-container {
background-color: white;
border: #b2b2b2 solid 1px;
}
.sender-tips {
display: flex;
flex-direction: row;
justify-content: flex-start;
align-items: center;
width: 100%;
}
.sender-tips img {
width: 50px;
height: 50px;
margin: 15px 15px 0;
border-radius: 50%;
}
.sender-tips .text {
display: flex;
flex-direction: column;
}
.refresh-btn {
flex: 1;
margin-right: 15px;
display: flex;
flex-direction: row-reverse;
}
.refresh-btn button {
background-color: #4f4f4f;
color: cyan;
width: 50px;
height: 50px;
margin: 15px 0 0 15px;
border-radius: 50%;
}
.theme-light .refresh-btn button {
background-color: white;
color: #1a1a1a;
border: #1a1a1a solid 1px;
}
.sender-input {
display: flex;
flex-direction: row;
width: 97%;
gap: 10px;
margin: 15px;
transition: all 0.5s ease;
}
/* 输入框样式 */
.message-input {
flex: 1;
padding: 10px;
border: 1px solid #ccc;
border-radius: 5px;
font-size: 16px;
outline: none;
}
/* 发送按钮样式 */
.send-button {
background-color: #007bff;
color: white;
border: none;
padding: 10px 20px;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
transition: all 0.3s ease;
}
.theme-light .send-button {
color: #1a1a1a;
background-color: #ffb74d;
}
/* 鼠标悬停时的按钮样式 */
.send-button:hover {
background-color: #0056b3;
}
.theme-light .send-button:hover {
background-color: #ffb74d;
}
.send-button:active {
transform: scale(0.95);
}
.send-button:disabled {
background-color: #9d9d9d;
}
</style>