2026-04-19 21:34:14 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* YichensBoard - 一尘看板页面
|
2026-04-19 23:52:57 +08:00
|
|
|
|
* Version: 0.0.2
|
|
|
|
|
|
* 更新:新增号码特色筛选按钮(带4、无4、无47等)
|
2026-04-19 21:34:14 +08:00
|
|
|
|
*/
|
|
|
|
|
|
|
2026-04-06 21:17:15 +08:00
|
|
|
|
import React, { useState, useEffect } from 'react'
|
|
|
|
|
|
|
|
|
|
|
|
export default function YichensBoard() {
|
2026-04-06 23:22:57 +08:00
|
|
|
|
const [todayStats, setTodayStats] = useState({ total: 0, deals: 0, wants: 0, others: 0 })
|
|
|
|
|
|
const [todayCategory, setTodayCategory] = useState([])
|
2026-04-06 21:17:15 +08:00
|
|
|
|
const [posts, setPosts] = useState([])
|
2026-04-08 22:17:55 +08:00
|
|
|
|
const [loading, setLoading] = useState(true)
|
|
|
|
|
|
const [error, setError] = useState(null)
|
2026-04-06 21:17:15 +08:00
|
|
|
|
const [expandedPosts, setExpandedPosts] = useState({})
|
|
|
|
|
|
const [postTypeFilter, setPostTypeFilter] = useState('all')
|
2026-04-06 23:22:57 +08:00
|
|
|
|
const [categoryFilter, setCategoryFilter] = useState('')
|
2026-04-19 23:52:57 +08:00
|
|
|
|
const [numberFilter, setNumberFilter] = useState('')
|
2026-04-06 23:22:57 +08:00
|
|
|
|
const [page, setPage] = useState(1)
|
|
|
|
|
|
const [totalPosts, setTotalPosts] = useState(0)
|
2026-04-07 13:07:20 +08:00
|
|
|
|
const [searchKeyword, setSearchKeyword] = useState('')
|
2026-04-06 21:17:15 +08:00
|
|
|
|
|
2026-04-06 23:22:57 +08:00
|
|
|
|
const today = new Date()
|
|
|
|
|
|
const dateStr = today.getFullYear() + '/' + (today.getMonth() + 1) + '/' + today.getDate()
|
2026-04-06 21:17:15 +08:00
|
|
|
|
|
2026-04-08 22:17:55 +08:00
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
console.log('YichensBoard: 开始加载数据')
|
|
|
|
|
|
fetchTodayStats()
|
|
|
|
|
|
}, [])
|
2026-04-06 23:22:57 +08:00
|
|
|
|
|
|
|
|
|
|
const fetchTodayStats = async () => {
|
|
|
|
|
|
try {
|
2026-04-08 22:17:55 +08:00
|
|
|
|
console.log('YichensBoard: 请求 /api/yichens/stats/today')
|
|
|
|
|
|
const res = await fetch('/api/yichens/stats/today')
|
|
|
|
|
|
if (!res.ok) throw new Error('stats API error: ' + res.status)
|
|
|
|
|
|
const data = await res.json()
|
|
|
|
|
|
console.log('YichensBoard: stats data', data)
|
|
|
|
|
|
setTodayStats(data)
|
|
|
|
|
|
} catch(e) {
|
|
|
|
|
|
console.error('YichensBoard: fetchTodayStats error', e)
|
|
|
|
|
|
setError(e.message)
|
|
|
|
|
|
}
|
2026-04-06 21:17:15 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-04-08 22:40:46 +08:00
|
|
|
|
const fetchPosts = async (p, cat, kw) => {
|
2026-04-06 21:17:15 +08:00
|
|
|
|
setLoading(true)
|
2026-04-08 22:17:55 +08:00
|
|
|
|
setError(null)
|
2026-04-06 23:22:57 +08:00
|
|
|
|
const currentPage = p !== undefined ? p : page
|
|
|
|
|
|
const currentCat = cat !== undefined ? cat : categoryFilter
|
2026-04-08 22:40:46 +08:00
|
|
|
|
const searchKw = kw !== undefined ? kw : searchKeyword
|
2026-04-06 23:22:57 +08:00
|
|
|
|
|
2026-04-08 22:40:46 +08:00
|
|
|
|
let url = '/api/yichens/posts?limit=390&offset=' + ((currentPage - 1) * 390)
|
2026-04-06 23:22:57 +08:00
|
|
|
|
if (postTypeFilter === 'deal') url += '&post_type=deal'
|
|
|
|
|
|
else if (postTypeFilter === 'want') url += '&post_type=want'
|
|
|
|
|
|
else if (postTypeFilter === 'other') url += '&post_type=normal'
|
2026-04-08 22:40:46 +08:00
|
|
|
|
if (searchKw && searchKw.trim()) url += '&keyword=' + encodeURIComponent(searchKw.trim())
|
2026-04-08 22:17:55 +08:00
|
|
|
|
|
2026-04-06 21:17:15 +08:00
|
|
|
|
try {
|
2026-04-08 22:17:55 +08:00
|
|
|
|
console.log('YichensBoard: 请求 posts', url)
|
2026-04-06 21:17:15 +08:00
|
|
|
|
const res = await fetch(url)
|
2026-04-08 22:17:55 +08:00
|
|
|
|
if (!res.ok) throw new Error('posts API error: ' + res.status)
|
2026-04-06 23:22:57 +08:00
|
|
|
|
let data = await res.json() || []
|
2026-04-09 15:36:14 +08:00
|
|
|
|
// 确保data是数组
|
|
|
|
|
|
if (!Array.isArray(data)) {
|
|
|
|
|
|
data = data.posts || data.data || []
|
|
|
|
|
|
}
|
|
|
|
|
|
console.log('YichensBoard: posts data count', data.length)
|
|
|
|
|
|
if (currentCat && Array.isArray(data)) {
|
|
|
|
|
|
if (currentCat === '龙') {
|
|
|
|
|
|
data = data.filter(p => p.category && (p.category.includes('龙') || p.category.includes('纪念钞')))
|
|
|
|
|
|
} else if (currentCat === '蛇') {
|
|
|
|
|
|
data = data.filter(p => p.category && p.category.includes('蛇'))
|
|
|
|
|
|
} else if (currentCat === '马') {
|
|
|
|
|
|
data = data.filter(p => p.category && p.category.includes('马'))
|
|
|
|
|
|
} else if (currentCat === '其他') {
|
|
|
|
|
|
data = data.filter(p => p.category && !p.category.includes('龙') && !p.category.includes('纪念钞') && !p.category.includes('蛇') && !p.category.includes('马'))
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-19 23:52:57 +08:00
|
|
|
|
// 号码特色筛选(根据标题和内容关键字)
|
|
|
|
|
|
if (numberFilter && Array.isArray(data)) {
|
|
|
|
|
|
const filterKeywords = {
|
|
|
|
|
|
'带4': ['带4', '带四', '通货', '标四'],
|
|
|
|
|
|
'无4': ['无4', '无四', '带7'],
|
|
|
|
|
|
'无47': ['无47', '无四七', '永恒'],
|
|
|
|
|
|
'无247': ['无247', '无二四七', '天马', '金山'],
|
|
|
|
|
|
'无347': ['无347', '无三四七', '钻石', '如意', '朦胧', '金马'],
|
|
|
|
|
|
'年份': ['年份', '生日', '生日号', '纪念'],
|
|
|
|
|
|
'特色': ['倒置', '圆圆', '豹子', '老虎', '狮子', '大象', '龙三', '龙二']
|
|
|
|
|
|
}
|
|
|
|
|
|
const kw = filterKeywords[numberFilter] || []
|
|
|
|
|
|
if (kw.length > 0) {
|
|
|
|
|
|
data = data.filter(p => {
|
|
|
|
|
|
const text = (p.title || '') + (p.content || '') + (p.description || '')
|
|
|
|
|
|
return kw.some(k => text.includes(k))
|
|
|
|
|
|
})
|
2026-04-06 23:22:57 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-04-19 23:52:57 +08:00
|
|
|
|
// 确保data是数组
|