2026-03-26 15:32:27 +08:00
|
|
|
|
import React, { useState, useEffect } from 'react'
|
|
|
|
|
|
|
2026-03-29 17:04:09 +08:00
|
|
|
|
// 信息页面 - 寻配号发布和发布管理(包含寻号/行情区分)
|
2026-03-26 15:32:27 +08:00
|
|
|
|
export default function Info() {
|
2026-03-29 16:20:51 +08:00
|
|
|
|
// 检查登录状态,未登录则跳转到登录页
|
|
|
|
|
|
if (!localStorage.getItem('token')) {
|
|
|
|
|
|
window.location.hash = '#/login'
|
|
|
|
|
|
return null
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-29 17:04:09 +08:00
|
|
|
|
// 顶部tab:寻配号发布 / 发布管理
|
2026-03-31 01:22:34 +08:00
|
|
|
|
const [activeTab, setActiveTab] = useState('manage')
|
2026-03-26 15:32:27 +08:00
|
|
|
|
const [showPublish, setShowPublish] = useState(false)
|
2026-03-29 17:09:10 +08:00
|
|
|
|
const [publishType, setPublishType] = useState('deal') // 'seek' 或 'deal'
|
2026-03-26 15:32:27 +08:00
|
|
|
|
const [myList, setMyList] = useState([])
|
|
|
|
|
|
const [loading, setLoading] = useState(false)
|
2026-03-26 20:26:51 +08:00
|
|
|
|
const [editingItem, setEditingItem] = useState(null)
|
2026-03-29 17:04:09 +08:00
|
|
|
|
const [filterType, setFilterType] = useState('all') // all/seek/deal
|
2026-03-31 01:22:34 +08:00
|
|
|
|
const [expandedItems, setExpandedItems] = useState({}) // 展开状态
|
2026-03-26 15:32:27 +08:00
|
|
|
|
|
|
|
|
|
|
const [formData, setFormData] = useState({
|
2026-03-26 23:06:47 +08:00
|
|
|
|
edition: '龙钞', type: '标百', isGraded: true, category: '成交', source: '直播', title: ''
|
2026-03-26 15:32:27 +08:00
|
|
|
|
})
|
2026-03-29 17:04:09 +08:00
|
|
|
|
|
2026-03-29 17:09:10 +08:00
|
|
|
|
// 寻配号发布表单
|
2026-03-29 17:04:09 +08:00
|
|
|
|
const [seekForm, setSeekForm] = useState({
|
2026-03-29 17:09:10 +08:00
|
|
|
|
edition: '龙钞', price: '', features: '', contact: '', content: '', title: ''
|
2026-03-29 17:04:09 +08:00
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
const API_BASE = localStorage.getItem('API_BASE') || ''
|
2026-03-26 15:32:27 +08:00
|
|
|
|
|
2026-03-31 01:22:34 +08:00
|
|
|
|
// 切换展开/收起
|
|
|
|
|
|
const toggleExpand = (itemId) => {
|
|
|
|
|
|
setExpandedItems(prev => ({
|
|
|
|
|
|
...prev,
|
|
|
|
|
|
[itemId]: !prev[itemId]
|
|
|
|
|
|
}))
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-26 20:26:51 +08:00
|
|
|
|
useEffect(() => {
|
2026-03-29 15:03:52 +08:00
|
|
|
|
if (activeTab === 'manage') fetchMyList()
|
2026-03-26 20:26:51 +08:00
|
|
|
|
}, [activeTab])
|
|
|
|
|
|
|
2026-03-26 15:32:27 +08:00
|
|
|
|
useEffect(() => {
|
2026-03-29 17:09:10 +08:00
|
|
|
|
// 自动生成行情标题
|
|
|
|
|
|
const now = new Date()
|
|
|
|
|
|
const date = `${now.getFullYear()}/${now.getMonth()+1}/${now.getDate()}`
|
|
|
|
|
|
const grade = formData.isGraded ? '(评级币)' : '(裸钞)'
|
|
|
|
|
|
const title = `「${date} ${formData.edition} ${formData.type} ${formData.category} 行情信息${grade}」`
|
|
|
|
|
|
setFormData(prev => ({ ...prev, title }))
|
|
|
|
|
|
}, [formData.edition, formData.type, formData.isGraded, formData.category])
|
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
// 自动生成寻配号标题
|
2026-03-29 17:04:09 +08:00
|
|
|
|
if (seekForm.edition || seekForm.features) {
|
2026-03-29 17:09:10 +08:00
|
|
|
|
const title = `「寻号 ${seekForm.edition} J0${seekForm.features || 'XXXXXXXX'}」`
|
2026-03-29 17:04:09 +08:00
|
|
|
|
setSeekForm(prev => ({ ...prev, title }))
|
|
|
|
|
|
}
|
|
|
|
|
|
}, [seekForm.edition, seekForm.features])
|
2026-03-26 15:32:27 +08:00
|
|
|
|
|
|
|
|
|
|
const fetchMyList = async () => {
|
|
|
|
|
|
setLoading(true)
|
|
|
|
|
|
try {
|
|
|
|
|
|
const token = localStorage.getItem('token')
|
2026-03-31 01:22:34 +08:00
|
|
|
|
const res = await fetch(`${API_BASE}/api/information/list`, {
|
2026-03-29 17:04:09 +08:00
|
|
|
|
headers: { Authorization: `Bearer ${token}` }
|
|
|
|
|
|
})
|
|
|
|
|
|
if (res.ok) {
|
|
|
|
|
|
const data = await res.json()
|
|
|
|
|
|
setMyList(data || [])
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
console.error(e)
|
|
|
|
|
|
}
|
2026-03-26 15:32:27 +08:00
|
|
|
|
setLoading(false)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-29 17:04:09 +08:00
|
|
|
|
// 发布寻配号
|
|
|
|
|
|
const handlePublishSeek = async () => {
|
|
|
|
|
|
if (!seekForm.contact) {
|
|
|
|
|
|
alert('请填写联系方式')
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
2026-03-26 15:32:27 +08:00
|
|
|
|
try {
|
|
|
|
|
|
const token = localStorage.getItem('token')
|
2026-03-26 20:26:51 +08:00
|
|
|
|
const res = await fetch(`${API_BASE}/api/information/`, {
|
2026-03-29 17:04:09 +08:00
|
|
|
|
method: 'POST',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
'Authorization': `Bearer ${token}`,
|
|
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
|
|
},
|
|
|
|
|
|
body: JSON.stringify({
|
|
|
|
|
|
title: seekForm.title,
|
|
|
|
|
|
content: document.getElementById('seekContent')?.value || seekForm.content,
|
|
|
|
|
|
info_type: 'seek',
|
|
|
|
|
|
expect_category: seekForm.edition,
|
|
|
|
|
|
expect_number: seekForm.features ? `J0${seekForm.features}` : null
|
|
|
|
|
|
})
|
|
|
|
|
|
})
|
|
|
|
|
|
const data = await res.json()
|
|
|
|
|
|
if (data.id || data.code === 0) {
|
|
|
|
|
|
alert('发布成功!')
|
|
|
|
|
|
setShowPublish(false)
|
2026-03-29 17:09:10 +08:00
|
|
|
|
setSeekForm({ edition: '龙钞', price: '', features: '', contact: '', content: '', title: '' })
|
2026-03-29 17:04:09 +08:00
|
|
|
|
const contentEl = document.getElementById('seekContent')
|
|
|
|
|
|
if (contentEl) contentEl.value = ''
|
|
|
|
|
|
fetchMyList()
|
|
|
|
|
|
} else {
|
|
|
|
|
|
alert(data.message || '发布失败')
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
alert('发布失败: ' + e.message)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-29 17:09:10 +08:00
|
|
|
|
// 发布行情(新增发布默认是行情)
|
2026-03-29 17:04:09 +08:00
|
|
|
|
const handlePublishDeal = async () => {
|
|
|
|
|
|
const content = document.getElementById('publishContent')?.value || ''
|
|
|
|
|
|
if (!formData.title) {
|
|
|
|
|
|
alert('请填写标题')
|
|
|
|
|
|
return
|
|
|
|
|
|
}
|
|
|
|
|
|
try {
|
|
|
|
|
|
const token = localStorage.getItem('token')
|
|
|
|
|
|
const res = await fetch(`${API_BASE}/api/information/`, {
|
|
|
|
|
|
method: 'POST',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
'Authorization': `Bearer ${token}`,
|
|
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
|
|
},
|
|
|
|
|
|
body: JSON.stringify({
|
|
|
|
|
|
title: formData.title,
|
|
|
|
|
|
content: content,
|
|
|
|
|
|
info_type: formData.category === '成交' ? 'deal' : 'seek'
|
|
|
|
|
|
})
|
2026-03-26 15:32:27 +08:00
|
|
|
|
})
|
|
|
|
|
|
const data = await res.json()
|
|
|
|
|
|
if (data.id || data.code === 0) {
|
|
|
|
|
|
alert('发布成功!')
|
|
|
|
|
|
setShowPublish(false)
|
2026-03-26 23:06:47 +08:00
|
|
|
|
setFormData({ edition: '龙钞', type: '标百', isGraded: true, category: '成交', source: '直播', title: '' })
|
2026-03-29 17:04:09 +08:00
|
|
|
|
const contentEl = document.getElementById('publishContent')
|
|
|
|
|
|
if (contentEl) contentEl.value = ''
|
2026-03-26 15:32:27 +08:00
|
|
|
|
fetchMyList()
|
2026-03-29 17:04:09 +08:00
|
|
|
|
} else {
|
|
|
|
|
|
alert(data.message || '发布失败')
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
alert('发布失败: ' + e.message)
|
|
|
|
|
|
}
|
2026-03-26 20:26:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-29 17:04:09 +08:00
|
|
|
|
// 删除
|
2026-03-26 20:26:51 +08:00
|
|
|
|
const handleDelete = async (id) => {
|
|
|
|
|
|
if (!confirm('确定删除这条信息吗?')) return
|
|
|
|
|
|
try {
|
|
|
|
|
|
const token = localStorage.getItem('token')
|
2026-03-29 17:04:09 +08:00
|
|
|
|
const res = await fetch(`${API_BASE}/api/information/${id}`, {
|
|
|
|
|
|
method: 'DELETE',
|
|
|
|
|
|
headers: { Authorization: `Bearer ${token}` }
|
|
|
|
|
|
})
|
|
|
|
|
|
if (res.ok) {
|
|
|
|
|
|
alert('删除成功')
|
|
|
|
|
|
fetchMyList()
|
|
|
|
|
|
} else {
|
|
|
|
|
|
alert('删除失败')
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
alert('删除失败: ' + e.message)
|
|
|
|
|
|
}
|
2026-03-26 15:32:27 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-29 17:04:09 +08:00
|
|
|
|
// 编辑
|
|
|
|
|
|
const handleEdit = (item) => {
|
|
|
|
|
|
setEditingItem({ id: item.id, title: item.title, content: item.content })
|
|
|
|
|
|
}
|
2026-03-26 15:32:27 +08:00
|
|
|
|
|
2026-03-29 17:04:09 +08:00
|
|
|
|
const saveEdit = async () => {
|
2026-03-26 20:26:51 +08:00
|
|
|
|
if (!editingItem) return
|
|
|
|
|
|
try {
|
|
|
|
|
|
const token = localStorage.getItem('token')
|
|
|
|
|
|
const res = await fetch(`${API_BASE}/api/information/${editingItem.id}`, {
|
2026-03-29 17:04:09 +08:00
|
|
|
|
method: 'PUT',
|
|
|
|
|
|
headers: {
|
|
|
|
|
|
'Authorization': `Bearer ${token}`,
|
|
|
|
|
|
'Content-Type': 'application/json'
|
|
|
|
|
|
},
|
2026-03-26 20:26:51 +08:00
|
|
|
|
body: JSON.stringify({ title: editingItem.title, content: editingItem.content })
|
|
|
|
|
|
})
|
2026-03-29 17:04:09 +08:00
|
|
|
|
if (res.ok) {
|
|
|
|
|
|
alert('保存成功')
|
|
|
|
|
|
setEditingItem(null)
|
|
|
|
|
|
fetchMyList()
|
|
|
|
|
|
} else {
|
|
|
|
|
|
alert('保存失败')
|
|
|
|
|
|
}
|
|
|
|
|
|
} catch (e) {
|
|
|
|
|
|
alert('保存失败: ' + e.message)
|
|
|
|
|
|
}
|
2026-03-26 20:26:51 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-03-29 17:04:09 +08:00
|
|
|
|
const getUserPhone = () => {
|
|
|
|
|
|
try {
|
|
|
|
|
|
const user = JSON.parse(localStorage.getItem('user') || '{}')
|
|
|
|
|
|
return user.phone || user.phoneNumber || user.mobile || user.tel || ''
|
|
|
|
|
|
} catch {
|
|
|
|
|
|
return ''
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-03-26 15:32:27 +08:00
|
|
|
|
|
2026-03-29 17:04:09 +08:00
|
|
|
|
useEffect(() => {
|
|
|
|
|
|
setSeekForm(prev => ({ ...prev, contact: getUserPhone() }))
|
|
|
|
|
|
}, [])
|
2026-03-26 15:32:27 +08:00
|
|
|
|
|
2026-03-29 17:04:09 +08:00
|
|
|
|
// 格式化日期
|
|
|
|
|
|
const formatDate = (date) => {
|
|
|
|
|
|
if (!date) return '-'
|
|
|
|
|
|
return new Date(date).toLocaleString('zh-CN').slice(0, 16)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 过滤后的列表
|
|
|
|
|
|
const filteredList = myList.filter(item => filterType === 'all' || item.info_type === filterType)
|
2026-03-26 15:32:27 +08:00
|
|
|
|
|
|
|
|
|
|
return (
|
2026-03-26 20:26:51 +08:00
|
|
|
|
<div style={{ minHeight: '100vh', background: 'linear-gradient(180deg, #0f172a 0%, #1e293b 100%)', paddingBottom: '80px' }}>
|
2026-03-29 17:04:09 +08:00
|
|
|
|
{/* 顶部 Tab 切换 */}
|
2026-03-29 15:03:52 +08:00
|
|
|
|
<div style={{ position: 'sticky', top: 0, background: 'rgba(15,23,42,0.95)', backdropFilter: 'blur(10px)', padding: '16px 20px', borderBottom: '1px solid #1e293b', zIndex: 100 }}>
|
|
|
|
|
|
<div style={{ display: 'flex', gap: '8px', background: '#1e293b', borderRadius: '12px', padding: '4px' }}>
|
2026-03-29 17:04:09 +08:00
|
|
|
|
{[
|
|
|
|
|
|
{ key: 'manage', label: '📋 发布管理' }
|
|
|
|
|
|
].map(tab => (
|
|
|
|
|
|
<div
|
|
|
|
|
|
key={tab.key}
|
|
|
|
|
|
onClick={() => setActiveTab(tab.key)}
|
|
|
|
|
|
style={{
|
|
|
|
|
|
flex: 1,
|
|
|
|
|
|
padding: '12px 16px',
|
|
|
|
|
|
borderRadius: '10px',
|
|
|
|
|
|
background: activeTab === tab.key ? 'linear-gradient(135deg, #3b82f6 0%, #2563eb 100%)' : 'transparent',
|
|
|
|
|
|
color: activeTab === tab.key ? '#fff' : '#9ca3af',
|
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
|
textAlign: 'center',
|
|
|
|
|
|
fontSize: '14px',
|
|
|
|
|
|
fontWeight: '600',
|
|
|
|
|
|
transition: 'all 0.3s'
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
{tab.label}
|
2026-03-29 15:03:52 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
2026-03-26 15:32:27 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-03-26 20:26:51 +08:00
|
|
|
|
<div style={{ padding: '20px' }}>
|
2026-03-31 01:22:34 +08:00
|
|
|
|
{/* 寻配号发布页 - 已删除 */}
|
|
|
|
|
|
{false && (
|
2026-03-29 17:09:10 +08:00
|
|
|
|
<div style={{ background: 'linear-gradient(145deg, #1f2937 0%, #111827 100%)', borderRadius: '16px', padding: '20px', border: '1px solid #374151', boxShadow: '0 4px 20px rgba(0,0,0,0.3)' }}>
|
|
|
|
|
|
<h3 style={{ color: '#f9fafb', margin: '0 0 20px 0', fontSize: '18px', fontWeight: '600' }}>🔍 寻配号发布</h3>
|
|
|
|
|
|
|
|
|
|
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<label style={{ color: '#9ca3af', fontSize: '13px', display: 'block', marginBottom: '8px' }}>版别</label>
|
|
|
|
|
|
<div style={{ display: 'flex', gap: '8px' }}>
|
|
|
|
|
|
{['龙钞', '马钞', '蛇钞'].map(ed => {
|
|
|
|
|
|
const selected = seekForm.edition === ed
|
|
|
|
|
|
return (
|
|
|
|
|
|
<button
|
|
|
|
|
|
key={ed}
|
|
|
|
|
|
onClick={() => setSeekForm({ ...seekForm, edition: ed })}
|
|
|
|
|
|
style={{
|
|
|
|
|
|
flex: 1,
|
|
|
|
|
|
padding: '10px',
|
|
|
|
|
|
borderRadius: '8px',
|
|
|
|
|
|
border: selected ? '2px solid #10b981' : '1px solid #374151',
|
|
|
|
|
|
background: selected ? 'rgba(16,185,129,0.15)' : '#1f2937',
|
|
|
|
|
|
color: selected ? '#10b981' : '#d1d5db',
|
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
|
fontSize: '14px',
|
|
|
|
|
|
fontWeight: '500'
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
{ed}
|
|
|
|
|
|
</button>
|
|
|
|
|
|
)
|
|
|
|
|
|
})}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<label style={{ color: '#9ca3af', fontSize: '13px', display: 'block', marginBottom: '8px' }}>号码特征(8位)</label>
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
value={seekForm.features}
|
|
|
|
|
|
onChange={e => setSeekForm({ ...seekForm, features: e.target.value.toUpperCase().slice(0, 8) })}
|
|
|
|
|
|
placeholder="输入号码特征,如:12345678"
|
|
|
|
|
|
maxLength={8}
|
|
|
|
|
|
style={{ width: '100%', padding: '12px', background: '#1f2937', border: '1px solid #374151', borderRadius: '10px', color: '#fff', fontSize: '14px', boxSizing: 'border-box' }}
|
|
|
|
|
|
/>
|
|
|
|
|
|
<div style={{ color: '#6b7280', fontSize: '11px', marginTop: '4px' }}>X=任意数字 A=非4 B=非47 C=非347 D=非247</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<label style={{ color: '#9ca3af', fontSize: '13px', display: 'block', marginBottom: '8px' }}>标题(自动生成)</label>
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
value={seekForm.title}
|
|
|
|
|
|
readOnly
|
|
|
|
|
|
style={{ width: '100%', padding: '12px', background: '#1f2937', border: '1px solid #374151', borderRadius: '10px', color: '#10b981', fontSize: '14px', boxSizing: 'border-box' }}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<label style={{ color: '#9ca3af', fontSize: '13px', display: 'block', marginBottom: '8px' }}>正文</label>
|
|
|
|
|
|
<textarea
|
|
|
|
|
|
id="seekContent"
|
|
|
|
|
|
placeholder="请输入详细信息..."
|
|
|
|
|
|
style={{ width: '100%', padding: '12px', background: '#1f2937', border: '1px solid #374151', borderRadius: '10px', color: '#fff', fontSize: '14px', boxSizing: 'border-box', resize: 'vertical', minHeight: '80px' }}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<div>
|
|
|
|
|
|
<label style={{ color: '#ef4444', fontSize: '13px', display: 'block', marginBottom: '8px' }}>联系方式 *</label>
|
|
|
|
|
|
<input
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
value={seekForm.contact}
|
|
|
|
|
|
onChange={e => setSeekForm({ ...seekForm, contact: e.target.value })}
|
|
|
|
|
|
placeholder="请输入手机号或微信"
|
|
|
|
|
|
style={{ width: '100%', padding: '12px', background: '#1f2937', border: '1px solid #374151', borderRadius: '10px', color: '#fff', fontSize: '14px', boxSizing: 'border-box' }}
|
|
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
<button
|
|
|
|
|
|
onClick={handlePublishSeek}
|
|
|
|
|
|
style={{
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
padding: '14px',
|
|
|
|
|
|
background: 'linear-gradient(135deg, #10b981 0%, #059669 100%)',
|
|
|
|
|
|
border: 'none',
|
|
|
|
|
|
borderRadius: '10px',
|
|
|
|
|
|
color: '#fff',
|
|
|
|
|
|
fontSize: '16px',
|
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
|
cursor: 'pointer'
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
🚀 发布寻配号
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
2026-03-26 23:06:47 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
2026-03-26 15:32:27 +08:00
|
|
|
|
|
2026-03-29 17:04:09 +08:00
|
|
|
|
{/* 发布管理页 */}
|
2026-03-29 15:03:52 +08:00
|
|
|
|
{activeTab === 'manage' && (
|
2026-03-26 23:06:47 +08:00
|
|
|
|
<div>
|
2026-03-29 17:09:10 +08:00
|
|
|
|
{/* 新增发布区域 - 发布行情信息 */}
|
2026-03-29 17:04:09 +08:00
|
|
|
|
<div style={{ background: 'linear-gradient(145deg, #1f2937 0%, #111827 100%)', borderRadius: '16px', padding: '20px', marginBottom: '16px', border: '1px solid #374151', boxShadow: '0 4px 20px rgba(0,0,0,0.3)' }}>
|
|
|
|
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: '16px' }}>
|
|
|
|
|
|
<h3 style={{ color: '#f9fafb', margin: 0, fontSize: '16px', fontWeight: '600' }}>📋 发布管理</h3>
|
|
|
|
|
|
<button
|
|
|
|
|
|
onClick={() => setShowPublish(!showPublish)}
|
|
|
|
|
|
style={{
|
2026-03-29 17:09:10 +08:00
|
|
|
|
padding: '10px 20px',
|
|
|
|
|
|
background: showPublish ? 'rgba(108,114,132,0.5)' : 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
|
2026-03-29 17:04:09 +08:00
|
|
|
|
border: 'none',
|
2026-03-29 17:09:10 +08:00
|
|
|
|
borderRadius: '10px',
|
2026-03-29 17:04:09 +08:00
|
|
|
|
color: '#fff',
|
|
|
|
|
|
cursor: 'pointer',
|
2026-03-29 17:09:10 +08:00
|
|
|
|
fontSize: '14px',
|
|
|
|
|
|
fontWeight: '600'
|
2026-03-29 17:04:09 +08:00
|
|
|
|
}}
|
|
|
|
|
|
>
|
2026-03-29 17:09:10 +08:00
|
|
|
|
{showPublish ? '✕ 收起' : '+ 💰 新增行情发布'}
|
2026-03-26 23:06:47 +08:00
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-03-29 17:09:10 +08:00
|
|
|
|
{/* 行情发布表单 */}
|
2026-03-26 23:06:47 +08:00
|
|
|
|
{showPublish && (
|
|
|
|
|
|
<div style={{ background: '#0f172a', borderRadius: '12px', padding: '16px', marginBottom: '16px' }}>
|
2026-03-29 17:09:10 +08:00
|
|
|
|
<div style={{ color: '#f59e0b', fontSize: '14px', fontWeight: '600', marginBottom: '16px' }}>💰 发布行情信息</div>
|
|
|
|
|
|
|
2026-03-29 17:04:09 +08:00
|
|
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
|
2026-03-29 17:09:10 +08:00
|
|
|
|
<div style={{ display: 'flex', gap: '12px' }}>
|
|
|
|
|
|
<div style={{ flex: 2 }}>
|
|
|
|
|
|
<label style={{ color: '#9ca3af', fontSize: '12px', display: 'block', marginBottom: '6px' }}>版别</label>
|
|
|
|
|
|
<div style={{ display: 'flex', gap: '6px' }}>
|
|
|
|
|
|
{['龙钞', '马钞', '蛇钞', '其他'].map(ed => (
|
2026-03-29 17:04:09 +08:00
|
|
|
|
<button
|
|
|
|
|
|
key={ed}
|
2026-03-29 17:09:10 +08:00
|
|
|
|
onClick={() => setFormData({ ...formData, edition: ed })}
|
2026-03-29 17:04:09 +08:00
|
|
|
|
style={{
|
|
|
|
|
|
flex: 1,
|
|
|
|
|
|
padding: '8px',
|
|
|
|
|
|
borderRadius: '6px',
|
2026-03-29 17:09:10 +08:00
|
|
|
|
border: formData.edition === ed ? '2px solid #f59e0b' : '1px solid #374151',
|
|
|
|
|
|
background: formData.edition === ed ? 'rgba(245,158,11,0.15)' : '#1f2937',
|
|
|
|
|
|
color: formData.edition === ed ? '#f59e0b' : '#d1d5db',
|
2026-03-29 17:04:09 +08:00
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
|
fontSize: '12px'
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
{ed}
|
|
|
|
|
|
</button>
|
2026-03-29 17:09:10 +08:00
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
2026-03-26 23:06:47 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-03-29 17:04:09 +08:00
|
|
|
|
|
2026-03-29 17:09:10 +08:00
|
|
|
|
<div style={{ display: 'flex', gap: '12px' }}>
|
|
|
|
|
|
<div style={{ flex: 2 }}>
|
|
|
|
|
|
<label style={{ color: '#9ca3af', fontSize: '12px', display: 'block', marginBottom: '6px' }}>类型</label>
|
|
|
|
|
|
<div style={{ display: 'flex', gap: '6px' }}>
|
|
|
|
|
|
{['标百', '标十', '单张'].map(t => (
|
|
|
|
|
|
<button
|
|
|
|
|
|
key={t}
|
|
|
|
|
|
onClick={() => setFormData({ ...formData, type: t })}
|
|
|
|
|
|
style={{
|
|
|
|
|
|
flex: 1,
|
|
|
|
|
|
padding: '8px',
|
|
|
|
|
|
borderRadius: '6px',
|
|
|
|
|
|
border: formData.type === t ? '2px solid #f59e0b' : '1px solid #374151',
|
|
|
|
|
|
background: formData.type === t ? 'rgba(245,158,11,0.15)' : '#1f2937',
|
|
|
|
|
|
color: formData.type === t ? '#f59e0b' : '#d1d5db',
|
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
|
fontSize: '12px'
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
{t}
|
|
|
|
|
|
</button>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
<div style={{ flex: 1 }}>
|
|
|
|
|
|
<label style={{ color: '#9ca3af', fontSize: '12px', display: 'block', marginBottom: '6px' }}>是否评级</label>
|
|
|
|
|
|
<button
|
|
|
|
|
|
onClick={() => setFormData({ ...formData, isGraded: !formData.isGraded })}
|
|
|
|
|
|
style={{
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
padding: '8px',
|
|
|
|
|
|
borderRadius: '6px',
|
|
|
|
|
|
border: formData.isGraded ? '2px solid #f59e0b' : '1px solid #374151',
|
|
|
|
|
|
background: formData.isGraded ? 'rgba(245,158,11,0.15)' : '#1f2937',
|
|
|
|
|
|
color: formData.isGraded ? '#f59e0b' : '#d1d5db',
|
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
|
fontSize: '12px'
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
{formData.isGraded ? '✓ 评级币' : '○ 裸钞'}
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
2026-03-26 15:32:27 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
|
2026-03-29 17:04:09 +08:00
|
|
|
|
<div>
|
2026-03-29 17:09:10 +08:00
|
|
|
|
<label style={{ color: '#9ca3af', fontSize: '12px', display: 'block', marginBottom: '6px' }}>分类</label>
|
|
|
|
|
|
<div style={{ display: 'flex', gap: '8px' }}>
|
|
|
|
|
|
{[{value:'成交',label:'💰 成交'},{value:'求购',label:'🔍 求购'},{value:'出售',label:'💵 出售'}].map(opt => (
|
|
|
|
|
|
<button
|
|
|
|
|
|
key={opt.value}
|
|
|
|
|
|
onClick={() => setFormData({ ...formData, category: opt.value })}
|
|
|
|
|
|
style={{
|
|
|
|
|
|
flex: 1,
|
|
|
|
|
|
padding: '10px',
|
|
|
|
|
|
borderRadius: '8px',
|
|
|
|
|
|
border: formData.category === opt.value ? '2px solid #f59e0b' : '1px solid #374151',
|
|
|
|
|
|
background: formData.category === opt.value ? 'rgba(245,158,11,0.15)' : '#1f2937',
|
|
|
|
|
|
color: formData.category === opt.value ? '#f59e0b' : '#d1d5db',
|
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
|
fontSize: '13px',
|
|
|
|
|
|
fontWeight: '500'
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
{opt.label}
|
|
|
|
|
|
</button>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
2026-03-29 17:04:09 +08:00
|
|
|
|
</div>
|
2026-03-26 15:32:27 +08:00
|
|
|
|
|
2026-03-29 17:04:09 +08:00
|
|
|
|
<div>
|
2026-03-29 17:09:10 +08:00
|
|
|
|
<label style={{ color: '#9ca3af', fontSize: '12px', display: 'block', marginBottom: '6px' }}>标题(自动生成)</label>
|
2026-03-29 17:04:09 +08:00
|
|
|
|
<input
|
|
|
|
|
|
type="text"
|
2026-03-29 17:09:10 +08:00
|
|
|
|
value={formData.title}
|
|
|
|
|
|
readOnly
|
|
|
|
|
|
style={{ width: '100%', padding: '12px', background: '#1f2937', border: '1px solid #374151', borderRadius: '10px', color: '#10b981', fontSize: '14px', boxSizing: 'border-box' }}
|
2026-03-29 17:04:09 +08:00
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2026-03-26 15:32:27 +08:00
|
|
|
|
|
2026-03-29 17:04:09 +08:00
|
|
|
|
<div>
|
|
|
|
|
|
<label style={{ color: '#9ca3af', fontSize: '12px', display: 'block', marginBottom: '6px' }}>正文</label>
|
|
|
|
|
|
<textarea
|
2026-03-29 17:09:10 +08:00
|
|
|
|
id="publishContent"
|
|
|
|
|
|
placeholder="请输入行情详细信息..."
|
|
|
|
|
|
style={{ width: '100%', padding: '12px', background: '#1f2937', border: '1px solid #374151', borderRadius: '10px', color: '#fff', fontSize: '14px', boxSizing: 'border-box', resize: 'vertical', minHeight: '80px' }}
|
2026-03-29 17:04:09 +08:00
|
|
|
|
/>
|
|
|
|
|
|
</div>
|
2026-03-26 15:32:27 +08:00
|
|
|
|
|
2026-03-29 17:09:10 +08:00
|
|
|
|
<button
|
|
|
|
|
|
onClick={handlePublishDeal}
|
|
|
|
|
|
style={{
|
|
|
|
|
|
width: '100%',
|
|
|
|
|
|
padding: '14px',
|
|
|
|
|
|
background: 'linear-gradient(135deg, #f59e0b 0%, #d97706 100%)',
|
|
|
|
|
|
border: 'none',
|
|
|
|
|
|
borderRadius: '10px',
|
|
|
|
|
|
color: '#fff',
|
|
|
|
|
|
fontSize: '15px',
|
|
|
|
|
|
fontWeight: 'bold',
|
|
|
|
|
|
cursor: 'pointer'
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
🚀 提交发布
|
|
|
|
|
|
</button>
|
2026-03-29 17:04:09 +08:00
|
|
|
|
</div>
|
2026-03-26 20:26:51 +08:00
|
|
|
|
</div>
|
2026-03-26 23:06:47 +08:00
|
|
|
|
)}
|
2026-03-29 17:04:09 +08:00
|
|
|
|
</div>
|
2026-03-26 15:32:27 +08:00
|
|
|
|
|
2026-03-29 17:04:09 +08:00
|
|
|
|
{/* 列表过滤:全部 / 寻号 / 行情 */}
|
|
|
|
|
|
<div style={{ display: 'flex', gap: '8px', marginBottom: '16px' }}>
|
|
|
|
|
|
<button
|
|
|
|
|
|
onClick={() => setFilterType('all')}
|
|
|
|
|
|
style={{
|
|
|
|
|
|
padding: '8px 16px',
|
|
|
|
|
|
background: filterType === 'all' ? '#3b82f6' : '#374151',
|
|
|
|
|
|
border: 'none',
|
|
|
|
|
|
borderRadius: '6px',
|
|
|
|
|
|
color: '#fff',
|
|
|
|
|
|
fontSize: '13px',
|
|
|
|
|
|
cursor: 'pointer'
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
全部
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
onClick={() => setFilterType('seek')}
|
|
|
|
|
|
style={{
|
|
|
|
|
|
padding: '8px 16px',
|
|
|
|
|
|
background: filterType === 'seek' ? '#10b981' : '#374151',
|
|
|
|
|
|
border: 'none',
|
|
|
|
|
|
borderRadius: '6px',
|
|
|
|
|
|
color: '#fff',
|
|
|
|
|
|
fontSize: '13px',
|
|
|
|
|
|
cursor: 'pointer'
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
🔍 寻号
|
|
|
|
|
|
</button>
|
|
|
|
|
|
<button
|
|
|
|
|
|
onClick={() => setFilterType('deal')}
|
|
|
|
|
|
style={{
|
|
|
|
|
|
padding: '8px 16px',
|
|
|
|
|
|
background: filterType === 'deal' ? '#f59e0b' : '#374151',
|
|
|
|
|
|
border: 'none',
|
|
|
|
|
|
borderRadius: '6px',
|
|
|
|
|
|
color: '#fff',
|
|
|
|
|
|
fontSize: '13px',
|
|
|
|
|
|
cursor: 'pointer'
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
💰 行情
|
|
|
|
|
|
</button>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{/* 发布列表 */}
|
|
|
|
|
|
{loading ? (
|
|
|
|
|
|
<div style={{ color: '#9ca3af', textAlign: 'center', padding: '30px' }}>加载中...</div>
|
|
|
|
|
|
) : filteredList.length === 0 ? (
|
|
|
|
|
|
<div style={{ color: '#9ca3af', textAlign: 'center', padding: '30px', fontSize: '14px' }}>暂无发布记录</div>
|
|
|
|
|
|
) : (
|
|
|
|
|
|
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
|
|
|
|
|
|
{filteredList.map(item => (
|
2026-03-31 01:22:34 +08:00
|
|
|
|
<div key={item.id} style={{ background: '#1e293b', borderRadius: '12px', padding: '16px', border: '1px solid #334155' }}>
|
|
|
|
|
|
{/* 标题行 */}
|
2026-03-29 17:04:09 +08:00
|
|
|
|
<div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: '8px' }}>
|
2026-03-31 01:22:34 +08:00
|
|
|
|
<div style={{ color: '#fbbf24', fontSize: '15px', fontWeight: '600', flex: 1 }}>{item.title}</div>
|
2026-03-29 17:04:09 +08:00
|
|
|
|
<span style={{
|
|
|
|
|
|
background: item.info_type === 'deal' ? 'rgba(245,158,11,0.2)' : 'rgba(16,185,129,0.2)',
|
|
|
|
|
|
color: item.info_type === 'deal' ? '#f59e0b' : '#10b981',
|
|
|
|
|
|
padding: '4px 10px',
|
|
|
|
|
|
borderRadius: '20px',
|
|
|
|
|
|
fontSize: '12px'
|
|
|
|
|
|
}}>
|
|
|
|
|
|
{item.info_type === 'deal' ? '💰 行情' : '🔍 寻号'}
|
|
|
|
|
|
</span>
|
|
|
|
|
|
</div>
|
2026-03-31 01:22:34 +08:00
|
|
|
|
{/* 日期+用户名 */}
|
|
|
|
|
|
<div style={{ color: '#64748b', fontSize: '12px', marginBottom: '8px' }}>
|
|
|
|
|
|
📅 {formatDate(item.created_at)} | 👤 {item.user_name || '匿名用户'}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
{/* 正文 - 默认收起,点击展开 */}
|
|
|
|
|
|
{item.content && (
|
|
|
|
|
|
<div style={{ marginBottom: '12px' }}>
|
|
|
|
|
|
<div
|
|
|
|
|
|
onClick={() => toggleExpand(item.id)}
|
|
|
|
|
|
style={{
|
|
|
|
|
|
color: '#10b981',
|
|
|
|
|
|
fontSize: '13px',
|
|
|
|
|
|
cursor: 'pointer',
|
|
|
|
|
|
display: 'flex',
|
|
|
|
|
|
alignItems: 'center',
|
|
|
|
|
|
gap: '6px',
|
|
|
|
|
|
padding: '8px 12px',
|
|
|
|
|
|
background: 'rgba(16,185,129,0.1)',
|
|
|
|
|
|
borderRadius: '6px',
|
|
|
|
|
|
border: '1px solid rgba(16,185,129,0.2)'
|
|
|
|
|
|
}}
|
|
|
|
|
|
>
|
|
|
|
|
|
<span style={{ fontSize: '16px' }}>{expandedItems[item.id] ? '▼' : '▶'}</span>
|
|
|
|
|
|
<span>{expandedItems[item.id] ? '收起详情' : '展开查看详情'}</span>
|
|
|
|
|
|
</div>
|
|
|
|
|
|
{expandedItems[item.id] && (
|
|
|
|
|
|
<div style={{
|
|
|
|
|
|
color: '#e2e8f0',
|
|
|
|
|
|
fontSize: '14px',
|
|
|
|
|
|
lineHeight: '1.8',
|
|
|
|
|
|
marginTop: '12px',
|
|
|
|
|
|
background: 'rgba(255,255,255,0.03)',
|
|
|
|
|
|
padding: '12px',
|
|
|
|
|
|
borderRadius: '8px',
|
|
|
|
|
|
borderLeft: '3px solid #10b981'
|
|
|
|
|
|
}}>
|
|
|
|
|
|
{item.content.split('\n').map((line, i) => (
|
|
|
|
|
|
<div key={i} style={{ marginBottom: i < item.content.split('\n').length - 1 ? '6px' : 0 }}>
|
|
|
|
|
|
{line || ' '}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
|
|
|
|
|
{/* 操作按钮 */}
|
|
|
|
|
|
<div style={{ display: 'flex', justifyContent: 'flex-end', alignItems: 'center', marginTop: '8px' }}>
|
2026-03-29 17:04:09 +08:00
|
|
|
|
<div style={{ display: 'flex', gap: '8px' }}>
|
|
|
|
|
|
<button onClick={() => handleEdit(item)} style={{ padding: '6px 12px', borderRadius: '6px', border: '1px solid #3b82f6', background: 'transparent', color: '#3b82f6', cursor: 'pointer', fontSize: '12px' }}>✏️ 编辑</button>
|
|
|
|
|
|
<button onClick={() => handleDelete(item.id)} style={{ padding: '6px 12px', borderRadius: '6px', border: '1px solid #ef4444', background: 'transparent', color: '#ef4444', cursor: 'pointer', fontSize: '12px' }}>🗑️ 删除</button>
|
2026-03-26 20:26:51 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-03-29 17:04:09 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
))}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
2026-03-26 20:26:51 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</div>
|
2026-03-26 15:32:27 +08:00
|
|
|
|
|
2026-03-26 20:26:51 +08:00
|
|
|
|
{/* 编辑弹窗 */}
|
|
|
|
|
|
{editingItem && (
|
2026-03-29 17:04:09 +08:00
|
|
|
|
<div style={{ position: 'fixed', top: 0, left: 0, right: 0, bottom: 0, background: 'rgba(0,0,0,0.8)', display: 'flex', alignItems: 'center', justifyContent: 'center', zIndex: 1000, padding: '20px' }}>
|
2026-03-26 23:06:47 +08:00
|
|
|
|
<div style={{ background: '#1f2937', borderRadius: '16px', padding: '24px', width: '100%', maxWidth: '420px', border: '1px solid #374151' }}>
|
2026-03-26 20:26:51 +08:00
|
|
|
|
<h3 style={{ color: '#f9fafb', marginBottom: '20px', fontSize: '18px', fontWeight: '600' }}>✏️ 编辑信息</h3>
|
|
|
|
|
|
<div style={{ marginBottom: '16px' }}>
|
|
|
|
|
|
<label style={{ color: '#9ca3af', fontSize: '13px', display: 'block', marginBottom: '8px' }}>标题</label>
|
2026-03-29 17:04:09 +08:00
|
|
|
|
<input
|
|
|
|
|
|
type="text"
|
|
|
|
|
|
value={editingItem.title}
|
|
|
|
|
|
onChange={e => setEditingItem({ ...editingItem, title: e.target.value })}
|
|
|
|
|
|
style={{ width: '100%', padding: '12px', background: '#0f172a', border: '1px solid #374151', borderRadius: '8px', color: '#fff', boxSizing: 'border-box', fontSize: '14px' }}
|
|
|
|
|
|
/>
|
2026-03-26 15:32:27 +08:00
|
|
|
|
</div>
|
2026-03-26 20:26:51 +08:00
|
|
|
|
<div style={{ marginBottom: '20px' }}>
|
|
|
|
|
|
<label style={{ color: '#9ca3af', fontSize: '13px', display: 'block', marginBottom: '8px' }}>内容</label>
|
2026-03-29 17:04:09 +08:00
|
|
|
|
<textarea
|
|
|
|
|
|
value={editingItem.content}
|
|
|
|
|
|
onChange={e => setEditingItem({ ...editingItem, content: e.target.value })}
|
|
|
|
|
|
rows={4}
|
|
|
|
|
|
style={{ width: '100%', padding: '12px', background: '#0f172a', border: '1px solid #374151', borderRadius: '8px', color: '#fff', boxSizing: 'border-box', fontSize: '14px', resize: 'vertical' }}
|
|
|
|
|
|
/>
|
2026-03-26 15:32:27 +08:00
|
|
|
|
</div>
|
2026-03-26 20:26:51 +08:00
|
|
|
|
<div style={{ display: 'flex', gap: '12px' }}>
|
2026-03-29 17:04:09 +08:00
|
|
|
|
<button onClick={saveEdit} style={{ flex: 1, padding: '12px', background: '#10b981', border: 'none', borderRadius: '8px', color: '#fff', cursor: 'pointer', fontSize: '14px', fontWeight: '600' }}>💾 保存</button>
|
|
|
|
|
|
<button onClick={() => setEditingItem(null)} style={{ flex: 1, padding: '12px', border: '1px solid #374151', borderRadius: '8px', background: 'transparent', color: '#9ca3af', cursor: 'pointer', fontSize: '14px' }}>取消</button>
|
2026-03-26 20:26:51 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
</div>
|
2026-03-26 15:32:27 +08:00
|
|
|
|
</div>
|
|
|
|
|
|
)}
|
|
|
|
|
|
</div>
|
|
|
|
|
|
)
|
2026-03-29 17:09:10 +08:00
|
|
|
|
}
|