v1.2.101 - 寻配号网络数据匹配修复

- 修复寻配号列表API: /api/seek/list -> /api/information/seek/list
- 修复page_size限制: 500 -> 100
- 修复录入成功后serialDigits未重置导致崩溃问题
- 优化包装类型和成交平台同一行显示
This commit is contained in:
龙大 2026-04-16 15:59:41 +08:00
parent 4c92f4e070
commit 7939abc60a
5 changed files with 143 additions and 40 deletions

View File

@ -1 +1 @@
1.2.100
1.2.101

View File

@ -76,6 +76,8 @@ class InformationResponse(BaseModel):
collection_number: Optional[str] = None
# 匹配数量(我的藏品中满足条件的数量)
matched_count: Optional[int] = 0
# 网络匹配数量coolbot_data数据库中满足条件的数量
network_matched_count: Optional[int] = 0
class Config:
from_attributes = True
@ -115,6 +117,11 @@ def get_information_list(
if item.info_type == 'seek' and item.expect_number and current_user:
matched_count = match_collections_count(db, current_user.f99_90_id, item.expect_number)
# 计算网络匹配数量coolbot_data数据库
network_matched_count = 0
if item.info_type == 'seek' and item.expect_number:
network_matched_count = match_collections_count_from_coolbot(item.expect_number)
result.append(InformationResponse(
id=item.id,
user_id=item.user_id,
@ -144,6 +151,7 @@ def get_information_list(
collection_version=item.collection.f02_11_version if item.collection else None,
collection_number=item.collection.f02_10_prefix_serial if item.collection else None,
matched_count=matched_count,
network_matched_count=network_matched_count,
))
return result

View File

@ -1 +1 @@
VERSION=1.2.100
export const APP_VERSION = '1.2.101'

View File

@ -75,6 +75,7 @@ export default function Add() {
//
const [dealForm, setDealForm] = useState({
serial: '',
serialDigits: ['','','','','','','','','',''], // 10
category: '',
packaging: '标十',
price: '',
@ -730,9 +731,100 @@ export default function Add() {
<div>
<div style={{ marginBottom: '12px' }}>
<div style={{ color: '#94a3b8', fontSize: '13px', marginBottom: '6px' }}>冠字号 *</div>
<input value={dealForm.serial} onChange={(e) => setDealForm({...dealForm, serial: e.target.value.toUpperCase(), category: autoCategory(e.target.value)})}
placeholder="J0xxxxxxxx"
style={{ width: '100%', padding: '12px', background: 'rgba(255,255,255,0.05)', border: '1px solid rgba(255,255,255,0.1)', borderRadius: '8px', color: '#fff', fontSize: '15px' }} />
{/* 冠字号每位单独输入框 - 共10位J0可编辑后面8位数字 */}
<div style={{ display: 'flex', gap: '4px', justifyContent: 'center' }}>
{/* 第1位: J - 可编辑 */}
<input value={dealForm.serialDigits[0] || 'J'}
onChange={(e) => {
const val = e.target.value.replace(/[^Jj]/g, '').slice(-1).toUpperCase()
const newDigits = [...dealForm.serialDigits]
newDigits[0] = val || 'J'
const fullSerial = (newDigits[0] || 'J') + (newDigits[1] || '0') + newDigits.slice(2).join('')
setDealForm({...dealForm, serialDigits: newDigits, serial: fullSerial, category: autoCategory(fullSerial)})
}}
maxLength={1}
style={{
width: '32px', height: '44px', textAlign: 'center',
background: 'rgba(251,191,36,0.2)', border: '1px solid rgba(251,191,36,0.3)',
borderRadius: '6px', color: '#fbbf24', fontSize: '16px', fontWeight: 'bold'
}}
/>
{/* 第2位: 0 - 可编辑 */}
<input value={dealForm.serialDigits[1] || '0'}
onChange={(e) => {
const val = e.target.value.replace(/[^0]/g, '').slice(-1)
const newDigits = [...dealForm.serialDigits]
newDigits[1] = val || '0'
const fullSerial = (newDigits[0] || 'J') + (newDigits[1] || '0') + newDigits.slice(2).join('')
setDealForm({...dealForm, serialDigits: newDigits, serial: fullSerial, category: autoCategory(fullSerial)})
}}
maxLength={1}
style={{
width: '32px', height: '44px', textAlign: 'center',
background: 'rgba(251,191,36,0.2)', border: '1px solid rgba(251,191,36,0.3)',
borderRadius: '6px', color: '#fbbf24', fontSize: '16px', fontWeight: 'bold'
}}
/>
{/* 后面8位数字输入 - 带自动跳转 */}
{dealForm.serialDigits.slice(2).map((digit, idx) => {
const realIdx = idx + 2 // (2-9)
return (
<input key={realIdx} value={digit}
data-real-idx={realIdx}
onChange={(e) => {
const val = e.target.value.replace(/\D/g, '').slice(-1)
const newDigits = [...dealForm.serialDigits]
newDigits[realIdx] = val
const fullSerial = newDigits[0] + newDigits[1] + newDigits.slice(2).join('')
setDealForm({
...dealForm,
serialDigits: newDigits,
serial: fullSerial,
category: autoCategory(fullSerial)
})
// +1
if (val && realIdx < 9) {
setTimeout(() => {
const inputs = document.querySelectorAll('[data-real-idx]')
const nextInput = inputs[idx + 1] // idxrealIdx
if (nextInput) nextInput.focus()
}, 10)
}
}}
onKeyDown={(e) => {
// 退
if (e.key === 'Backspace' && !e.target.value && realIdx > 2) {
setTimeout(() => {
const inputs = document.querySelectorAll('[data-real-idx]')
const prevInput = inputs[idx - 1]
if (prevInput) prevInput.focus()
}, 10)
}
}}
maxLength={1}
placeholder="×"
style={{
width: '32px', height: '44px', textAlign: 'center',
background: 'rgba(255,255,255,0.05)', border: '1px solid rgba(255,255,255,0.1)',
borderRadius: '6px', color: '#fff', fontSize: '16px', fontWeight: 'bold'
}}
/>
)
})}
</div>
{/* 快捷清除按钮 */}
<div style={{ display: 'flex', justifyContent: 'space-between', marginTop: '8px' }}>
<button type="button" onClick={() => setDealForm({...dealForm, serial: '', serialDigits: ['','','','','','','','','',''], category: ''})}
style={{ padding: '4px 12px', background: 'rgba(255,255,255,0.1)', border: 'none', borderRadius: '4px', color: '#94a3b8', fontSize: '12px', cursor: 'pointer' }}>
清空
</button>
<div style={{ color: '#64748b', fontSize: '12px' }}>
已输入: {dealForm.serialDigits.filter(d => d).length}/8
</div>
</div>
</div>
{dealForm.category && (
@ -741,19 +833,8 @@ export default function Add() {
<div style={{ fontSize: '14px', color: '#fbbf24', fontWeight: 'bold' }}>{dealForm.category}</div>
</div>
)}
<div style={{ marginBottom: '12px' }}>
<div style={{ color: '#94a3b8', fontSize: '13px', marginBottom: '6px' }}>包装类型</div>
<div style={{ display: 'flex', gap: '8px' }}>
{['单张', '标十', '标百'].map(p => (
<button key={p} onClick={() => setDealForm({...dealForm, packaging: p})}
style={{ flex: 1, padding: '10px', background: dealForm.packaging === p ? '#fbbf24' : 'rgba(255,255,255,0.05)', color: dealForm.packaging === p ? '#1e293b' : '#fff', border: 'none', borderRadius: '8px', fontSize: '13px', fontWeight: '600', cursor: 'pointer' }}>
{p}
</button>
))}
</div>
</div>
{/* 成交价格 - 调整到冠字号下面 */}
<div style={{ marginBottom: '12px' }}>
<div style={{ color: '#94a3b8', fontSize: '13px', marginBottom: '6px' }}>成交价格 *</div>
<input type="number" value={dealForm.price} onChange={(e) => setDealForm({...dealForm, price: e.target.value})}
@ -761,20 +842,34 @@ export default function Add() {
style={{ width: '100%', padding: '12px', background: 'rgba(255,255,255,0.05)', border: '1px solid rgba(255,255,255,0.1)', borderRadius: '8px', color: '#fff', fontSize: '15px' }} />
</div>
<div style={{ marginBottom: '12px' }}>
<div style={{ color: '#94a3b8', fontSize: '13px', marginBottom: '6px' }}>成交平台 *</div>
<select value={dealForm.platform} onChange={(e) => setDealForm({...dealForm, platform: e.target.value})}
style={{ width: '100%', padding: '12px', background: 'rgba(255,255,255,0.05)', border: '1px solid rgba(255,255,255,0.1)', borderRadius: '8px', color: '#fff', fontSize: '15px' }}>
<option value="淘宝">淘宝</option>
<option value="咸鱼">咸鱼</option>
<option value="抖音">抖音</option>
<option value="快手">快手</option>
<option value="微拍堂">微拍堂</option>
<option value="拼多多">拼多多</option>
<option value="一尘">一尘</option>
<option value="爱藏">爱藏</option>
<option value="其他">其他</option>
</select>
{/* 成交价格和成交平台同一行 */}
<div style={{ display: 'flex', gap: '12px', marginBottom: '12px' }}>
<div style={{ flex: 1 }}>
<div style={{ color: '#94a3b8', fontSize: '13px', marginBottom: '6px' }}>包装类型</div>
<div style={{ display: 'flex', gap: '4px' }}>
{['单张', '标十', '标百'].map(p => (
<button key={p} onClick={() => setDealForm({...dealForm, packaging: p})}
style={{ flex: 1, padding: '10px 4px', background: dealForm.packaging === p ? '#fbbf24' : 'rgba(255,255,255,0.05)', color: dealForm.packaging === p ? '#1e293b' : '#fff', border: 'none', borderRadius: '6px', fontSize: '12px', fontWeight: '600', cursor: 'pointer' }}>
{p}
</button>
))}
</div>
</div>
<div style={{ flex: 1 }}>
<div style={{ color: '#94a3b8', fontSize: '13px', marginBottom: '6px' }}>成交平台 *</div>
<select value={dealForm.platform} onChange={(e) => setDealForm({...dealForm, platform: e.target.value})}
style={{ width: '100%', padding: '10px', background: 'rgba(255,255,255,0.05)', border: '1px solid rgba(255,255,255,0.1)', borderRadius: '8px', color: '#fff', fontSize: '14px' }}>
<option value="淘宝">淘宝</option>
<option value="咸鱼">咸鱼</option>
<option value="抖音">抖音</option>
<option value="快手">快手</option>
<option value="微拍堂">微拍堂</option>
<option value="拼多多">拼多多</option>
<option value="一尘">一尘</option>
<option value="爱藏">爱藏</option>
<option value="其他">其他</option>
</select>
</div>
</div>
<div style={{ display: 'flex', gap: '12px', marginBottom: '12px' }}>
@ -863,7 +958,7 @@ export default function Add() {
})
if (response.ok) {
alert('行情录入成功!')
setDealForm({ serial: '', category: '', packaging: '标十', price: '', platform: '抖音', seller: '', buyer: '', date: new Date().toISOString().split('T')[0] })
setDealForm({ serial: '', serialDigits: ['','','','','','','','','',''], category: '', packaging: '标十', price: '', platform: '抖音', seller: '', buyer: '', date: new Date().toISOString().split('T')[0] })
} else {
const data = await response.json()
alert('录入失败: ' + (data.detail || '未知错误'))

View File

@ -79,21 +79,21 @@ export default function News() {
const headers = token ? { Authorization: `Bearer ${token}` } : {}
// URL
// 使APIseekdeal
// 使 information/list
let url = activeTab === 'yichen'
? `${API_BASE}/api/information/list?info_type=${activeTab}`
: activeTab === 'seek'
? `${API_BASE}/api/seek/list`
? `${API_BASE}/api/information/list?info_type=seek`
: `${API_BASE}/api/deal/list`
// 500
// 100100
if (activeTab === 'deal') {
url += (url.includes('?') ? '&' : '?') + 'page_size=500'
url += (url.includes('?') ? '&' : '?') + 'page_size=100'
if (dealDate) {
url += '&deal_date=' + dealDate
}
} else if (activeTab === 'seek') {
url += (url.includes("?") ? "&" : "?") + "page=" + currentPage + "&page_size=500"
url += (url.includes("?") ? "&" : "?") + "page=" + currentPage + "&page_size=100"
}
const res = await fetch(url, { headers })
@ -290,7 +290,7 @@ export default function News() {
const token = localStorage.getItem('token')
if (!token) { alert('请先登录'); return }
try {
const res = await fetch(`${API_BASE}/api/seek/list`, {
const res = await fetch(`${API_BASE}/api/information/seek/list`, {
headers: { Authorization: `Bearer ${token}` }
})
const data = await res.json()
@ -306,7 +306,7 @@ export default function News() {
const token = localStorage.getItem('token')
if (!token) { alert('请先登录'); return }
try {
const res = await fetch(`${API_BASE}/api/seek/list`, {
const res = await fetch(`${API_BASE}/api/information/seek/list`, {
headers: { Authorization: `Bearer ${token}` }
})
const data = await res.json()