2025-05-19 11:14:37 +08:00

260 lines
6.9 KiB
Vue
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.

<template>
<div class="maps">
<div class="page-header">
<h1>最近地图上传</h1>
</div>
<div class="filters">
搜索
<div class="search-box">
<input
type="text"
placeholder="搜索地图..."
v-model="searchValue"
@input="handleSearchInput"
@blur="handleSearchBlur"
>
</div>
玩家数:
<select v-model="playerCountFilter" class="filter-select" @change="handleFilterChange">
<option value="">全部</option>
<option v-for="n in [2,3,4,5,6,7,8]" :key="n" :value="n">{{ n }}人</option>
</select>
分类:
<select v-model="tagFilter" class="filter-select" @change="handleFilterChange">
<option value="">全部</option>
<option v-for="tag in tagOptions" :key="tag" :value="tag">{{ tag }}</option>
</select>
排序:
<select v-model="selectedOrder" class="filter-select" @change="handleFilterChange">
<option v-for="opt in orderOptions" :key="opt.value" :value="opt.value">{{ opt.label }}</option>
</select>
</div>
<div class="table-container">
<table class="maps-table">
<thead>
<tr>
<th>预览图</th>
<th>地图名称</th>
<th>作者</th>
<th>下载次数</th>
<th>收藏次数</th>
<th>玩家数量</th>
<th>创建时间</th>
<th>标签</th>
</tr>
</thead>
<tbody>
<tr v-for="map in maps" :key="map.id" @click="goToMapDetail(map.id)" class="table-row">
<td class="preview-cell">
<img :src="map.thumbnail" :alt="map.chinese_name">
</td>
<td class="map-name">{{ map.chinese_name }}</td>
<td>{{ map.user }}</td>
<td>{{ map.download_count }}</td>
<td>{{ map.favourite_count }}</td>
<td>{{ map.player_count }}</td>
<td>{{ formatDate(map.create_time) }}</td>
<td>
<div class="tags">
<span v-for="tag in map.tags" :key="tag" class="tag">{{ tag }}</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
<!-- 分页控件 -->
<div class="pagination">
<button
class="page-btn"
:disabled="currentPage === 1"
@click="changePage(currentPage - 1)"
>
上一页
</button>
<div class="page-numbers">
<template v-for="(page, index) in displayedPages" :key="index">
<button
v-if="typeof page === 'number'"
class="page-number"
:class="{ active: page === currentPage }"
@click="changePage(page)"
>
{{ page }}
</button>
<span v-else class="page-ellipsis">{{ page }}</span>
</template>
</div>
<button
class="page-btn"
:disabled="!hasNextPage"
@click="changePage(currentPage + 1)"
>
下一页
</button>
<div class="page-jump">
<input
type="number"
v-model="jumpPage"
:min="1"
:max="totalPages"
class="jump-input"
@keyup.enter="handleJumpPage"
>
<button class="jump-btn" @click="handleJumpPage">跳转</button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, computed, onMounted, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { getMaps, getAllTags } from '../../api/maps.js'
import '../../assets/styles/common.css'
import '../../assets/styles/Maps.css'
const router = useRouter()
const maps = ref([])
const currentPage = ref(1)
const totalPages = ref(1)
const hasNextPage = ref(false)
const jumpPage = ref('')
// 排序和筛选相关
const orderOptions = [
{ label: '创建时间降序', value: ' -create_time' },
{ label: '创建时间升序', value: 'create_time' },
{ label: '下载量降序', value: ' -download_count' },
{ label: '下载量升序', value: 'download_count' },
{ label: '收藏数降序', value: ' -favourite_count' },
{ label: '收藏数升序', value: 'favourite_count' }
]
const selectedOrder = ref(' -create_time')
const searchValue = ref('')
const playerCountFilter = ref('')
const tagFilter = ref('')
const tagOptions = ref([])
// 计算显示的页码
const displayedPages = computed(() => {
const pages = []
const total = totalPages.value
const current = currentPage.value
if (total <= 5) {
for (let i = 1; i <= total; i++) {
pages.push(i)
}
} else if (current <= 3) {
pages.push(1, 2, 3, 4, '...', total)
} else if (current >= total - 2) {
pages.push(1, '...')
for (let i = total - 2; i <= total; i++) {
if (i > 1) pages.push(i)
}
} else {
pages.push(1, '...', current - 1, current, current + 1, '...', total)
}
return pages
})
// 获取地图数据
const fetchMaps = async (page = 1) => {
try {
const params = {
page,
search: searchValue.value,
player_count: playerCountFilter.value,
tags: tagFilter.value,
ordering: selectedOrder.value
}
const data = await getMaps(params)
maps.value = data.results
hasNextPage.value = !!data.next
totalPages.value = Math.ceil(data.count / 20)
currentPage.value = page
console.log('分页状态:', {
currentPage: currentPage.value,
totalPages: totalPages.value,
hasNextPage: hasNextPage.value,
resultsCount: data.results.length
})
} catch (error) {
console.error('获取地图列表失败:', error)
}
}
// 处理搜索输入
const handleSearchInput = () => {
if (!searchValue.value) {
fetchMaps(1)
}
}
// 处理搜索框失去焦点
const handleSearchBlur = () => {
if (searchValue.value) {
fetchMaps(1)
}
}
// 处理筛选条件变化
const handleFilterChange = () => {
console.log('筛选条件变化:', {
playerCount: playerCountFilter.value,
tag: tagFilter.value,
order: selectedOrder.value
})
fetchMaps(1)
}
// 处理页码跳转
const handleJumpPage = () => {
const page = parseInt(jumpPage.value)
if (page && page >= 1 && page <= totalPages.value) {
changePage(page)
}
jumpPage.value = ''
}
// 切换页码
const changePage = (page) => {
console.log('尝试切换页码:', page, '当前页码:', currentPage.value, '总页数:', totalPages.value)
if (page < 1 || page > totalPages.value) {
console.log('页码无效:', page)
return
}
currentPage.value = page
fetchMaps(page)
// 滚动到页面顶部
window.scrollTo({ top: 0, behavior: 'smooth' })
}
// 跳转到地图详情
const goToMapDetail = (id) => {
router.push(`/map/${id}`)
}
// 格式化日期
const formatDate = (dateString) => {
return new Date(dateString).toLocaleDateString('zh-CN')
}
onMounted(() => {
console.log('组件挂载')
fetchMaps(1)
getAllTags().then(tags => {
tagOptions.value = tags
})
})
</script>
<style scoped>
</style>