diff --git a/frontend/src/pages/Info.jsx b/frontend/src/pages/Info.jsx
index 68d307c..64780ad 100644
--- a/frontend/src/pages/Info.jsx
+++ b/frontend/src/pages/Info.jsx
@@ -1,25 +1,20 @@
import React, { useState, useEffect } from 'react'
-// 信息发布页面 - 仅信息员/管理员可用
export default function Info() {
const [activeTab, setActiveTab] = useState('publish')
const [showPublish, setShowPublish] = useState(false)
const [myList, setMyList] = useState([])
const [loading, setLoading] = useState(false)
+ const [editingItem, setEditingItem] = useState(null)
- // 表单数据
const [formData, setFormData] = useState({
- edition: '龙钞',
- type: '标百',
- isGraded: true,
- category: '成交',
- source: '直播',
- prices: {},
- title: '',
- content: ''
+ edition: '龙钞', type: '标百', isGraded: true, category: '成交', source: '直播', title: '', content: ''
})
- // 自动生成标题
+ useEffect(() => {
+ if (activeTab === 'manage') fetchMyList()
+ }, [activeTab])
+
useEffect(() => {
const now = new Date()
const date = `${now.getFullYear()}/${now.getMonth() + 1}/${now.getDate()}`
@@ -30,121 +25,66 @@ export default function Info() {
const API_BASE = localStorage.getItem('API_BASE') || ''
- // 获取我的发布列表
- useEffect(() => {
- if (activeTab === 'manage') {
- fetchMyList()
- }
- }, [activeTab])
-
const fetchMyList = async () => {
setLoading(true)
try {
const token = localStorage.getItem('token')
- const res = await fetch(`${API_BASE}/api/information/my`, {
- headers: { Authorization: `Bearer ${token}` }
- })
- const data = await res.json()
- setMyList(data || [])
- } catch (e) {
- console.error(e)
- }
+ const res = await fetch(`${API_BASE}/api/information/my/list`, { headers: { Authorization: `Bearer ${token}` } })
+ setMyList(res.ok ? await res.json() : [])
+ } catch (e) { console.error(e) }
setLoading(false)
}
- // 发布信息
const handlePublish = async () => {
- if (!formData.title) {
- alert('请填写标题')
- return
- }
-
+ if (!formData.title) { alert('请填写标题'); return }
try {
const token = localStorage.getItem('token')
- const gradeNote = formData.isGraded ? '(评级币)' : '(裸钞)'
-
- let priceContent = ''
- if (formData.prices && Object.keys(formData.prices).length > 0) {
- priceContent = '\n价格:'
- const priceLabels = {
- price_4: '带4',
- price_no4: '无4',
- price_no47: '无47',
- price_no347: '无347',
- price_no1347: '无1347',
- price_no247: '无247',
- price_no1247: '无1247',
- price_no12347: '无12347'
- }
- Object.entries(formData.prices).forEach(([key, value]) => {
- if (value) {
- priceContent += `${priceLabels[key] || key}:¥${value} `
- }
- })
- }
-
- const res = await fetch(`${API_BASE}/api/information/publish`, {
- method: 'POST',
- headers: {
- 'Authorization': `Bearer ${token}`,
- 'Content-Type': 'application/json'
- },
- body: JSON.stringify({
- title: formData.title,
- content: formData.content + priceContent,
- info_type: formData.category === '成交' ? 'deal' : 'seek'
- })
+ 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: formData.content, info_type: formData.category === '成交' ? 'deal' : 'seek' })
})
-
const data = await res.json()
if (data.id || data.code === 0) {
alert('发布成功!')
setShowPublish(false)
- setFormData({
- edition: '龙钞',
- type: '标百',
- isGraded: true,
- category: '成交',
- source: '直播',
- prices: {},
- title: '',
- content: ''
- })
+ setFormData({ edition: '龙钞', type: '标百', isGraded: true, category: '成交', source: '直播', title: '', content: '' })
fetchMyList()
- } else {
- alert(data.message || '发布失败')
- }
- } catch (e) {
- alert('发布失败: ' + e.message)
- }
+ } else { alert(data.message || '发布失败') }
+ } catch (e) { alert('发布失败: ' + e.message) }
}
- // Tab切换
- const tabs = [
- { key: 'publish', label: '📝 发布行情' },
- { key: 'manage', label: '📋 发布管理' }
- ]
+ const handleDelete = async (id) => {
+ if (!confirm('确定删除这条信息吗?')) return
+ try {
+ const token = localStorage.getItem('token')
+ 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) }
+ }
- // 按钮选择组件
- const ButtonGroup = ({ options, value, onChange, label }) => (
-
- {label &&
}
-
+ const handleEdit = (item) => setEditingItem({ id: item.id, title: item.title, content: item.content })
+
+ const handleSaveEdit = async () => {
+ if (!editingItem) return
+ try {
+ const token = localStorage.getItem('token')
+ const res = await fetch(`${API_BASE}/api/information/${editingItem.id}`, {
+ method: 'PUT', headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json' },
+ body: JSON.stringify({ title: editingItem.title, content: editingItem.content })
+ })
+ if (res.ok) { alert('保存成功'); setEditingItem(null); fetchMyList() } else { alert('保存失败') }
+ } catch (e) { alert('保存失败: ' + e.message) }
+ }
+
+ const BtnGroup = ({ options, value, onChange, label }) => (
+
+
{label}
+
{options.map(opt => (
-
)
- // 价格网格
- const PriceGrid = () => {
- const priceItems = [
- { key: 'price_4', label: '带4' },
- { key: 'price_no4', label: '无4' },
- { key: 'price_no47', label: '无47' },
- { key: 'price_no347', label: '无347' },
- { key: 'price_no1347', label: '无1347' },
- { key: 'price_no247', label: '无247' },
- { key: 'price_no1247', label: '无1247' },
- { key: 'price_no12347', label: '无12347' }
- ]
-
- return (
-
-
-
- {priceItems.map(item => (
-
-
-
setFormData({
- ...formData,
- prices: {...formData.prices, [item.key]: e.target.value}
- })}
- placeholder="¥"
- style={{
- width: '100%',
- padding: '8px',
- background: '#0f172a',
- border: '1px solid #334155',
- borderRadius: '4px',
- color: '#fff',
- boxSizing: 'border-box',
- fontSize: '13px'
- }}
- />
+ const Card = ({ children, title, action }) => (
+
+ {title &&
+
{title}
+ {action}
+ }
+ {children}
+
+ )
+
+ const formatDate = (d) => d ? new Date(d).toLocaleString('zh-CN').slice(0, 16) : '-'
+
+ return (
+
+ {/* 顶部标签 */}
+
+
+ {[{ key: 'publish', label: '📝 发布行情', icon: '📝' }, { key: 'manage', label: '📋 发布管理', icon: '📋' }].map(t => (
+
setActiveTab(t.key)}
+ style={{ flex: 1, padding: '12px 16px', borderRadius: '10px', background: activeTab === t.key ? 'linear-gradient(135deg, #3b82f6 0%, #2563eb 100%)' : 'transparent',
+ color: activeTab === t.key ? '#fff' : '#9ca3af', cursor: 'pointer', textAlign: 'center', fontSize: '14px', fontWeight: '600', transition: 'all 0.3s', boxShadow: activeTab === t.key ? '0 2px 10px rgba(59,130,246,0.4)' : 'none' }}>
+ {t.label}
))}
- )
- }
- const formatDate = (dateStr) => {
- if (!dateStr) return '-'
- const date = new Date(dateStr)
- return `${date.getMonth() + 1}/${date.getDate()} ${date.getHours()}:${String(date.getMinutes()).padStart(2, '0')}`
- }
+
+ {activeTab === 'publish' && (
+
+ {/* 新增按钮 */}
+
+ setShowPublish(!showPublish)}
+ style={{ background: showPublish ? 'linear-gradient(135deg, #6b7280 0%, #4b5563 100%)' : 'linear-gradient(135deg, #10b981 0%, #059669 100%)',
+ color: '#fff', border: 'none', padding: '12px 24px', borderRadius: '10px', cursor: 'pointer', fontSize: '14px', fontWeight: '600', boxShadow: '0 4px 15px rgba(16,185,129,0.3)', transition: 'all 0.3s' }}>
+ {showPublish ? '✕ 收起表单' : '+ 新增发布'}
+
+
- return (
-
- {/* Tab导航 */}
-
- {tabs.map(tab => (
-
setActiveTab(tab.key)}
- style={{
- padding: '10px 20px',
- borderRadius: '8px',
- background: activeTab === tab.key ? '#3b82f6' : 'transparent',
- color: '#fff',
- cursor: 'pointer',
- whiteSpace: 'nowrap',
- fontSize: '14px'
- }}
- >
- {tab.label}
-
- ))}
-
+ {showPublish && (
+
+ setFormData({...formData, edition: v})} />
- {/* 发布行情 */}
- {activeTab === 'publish' && (
-
-
- setShowPublish(!showPublish)}
- style={{
- background: '#3b82f6',
- color: '#fff',
- border: 'none',
- padding: '10px 20px',
- borderRadius: '8px',
- cursor: 'pointer',
- fontSize: '14px'
- }}
- >
- {showPublish ? '❌ 取消' : '➕ 新增发布'}
-
-
-
- {showPublish && (
-
-
📝 发布行情信息
-
-
setFormData({...formData, edition: v})} />
-
-
-
+
-
-
+
类型
+
{['标百', '标十', '单张'].map(t => (
setFormData({...formData, type: t})}
- style={{ flex: 1, padding: '10px', borderRadius: '6px',
- border: formData.type === t ? '2px solid #fbbf24' : '1px solid #334155',
- background: formData.type === t ? 'rgba(251,191,36,0.2)' : '#0f172a',
- color: '#fff', cursor: 'pointer', fontSize: '13px' }}>
- {t}
-
+ style={{ flex: 1, padding: '10px', borderRadius: '8px', border: formData.type === t ? '2px solid #10b981' : '1px solid #374151',
+ background: formData.type === t ? 'rgba(16,185,129,0.15)' : '#1f2937', color: formData.type === t ? '#10b981' : '#d1d5db', cursor: 'pointer', fontSize: '13px' }}>{t}
))}
-
+
是否评级
setFormData({...formData, isGraded: !formData.isGraded})}
- style={{ width: '100%', padding: '10px', marginTop: '6px', borderRadius: '6px',
- border: formData.isGraded ? '2px solid #fbbf24' : '1px solid #334155',
- background: formData.isGraded ? 'rgba(251,191,36,0.2)' : '#0f172a',
- color: formData.isGraded ? '#fbbf24' : '#94a3b8', cursor: 'pointer', fontSize: '13px' }}>
- {formData.isGraded ? '✅ 评级' : '○ 未评级'}
+ style={{ width: '100%', padding: '10px', borderRadius: '8px', border: formData.isGraded ? '2px solid #10b981' : '1px solid #374151',
+ background: formData.isGraded ? 'rgba(16,185,129,0.15)' : '#1f2937', color: formData.isGraded ? '#10b981' : '#d1d5db', cursor: 'pointer', fontSize: '13px' }}>
+ {formData.isGraded ? '✓ 评级币' : '○ 裸钞'}
-
-
setFormData({...formData, category: v})} />
+ setFormData({...formData, category: v})} />
- setFormData({...formData, source: v})} />
+ setFormData({...formData, source: v})} />
-
-
-
-
-
-
-
-
-
-
-
-
- 📤 提交发布
-
-
- )}
-
- )}
-
- {/* 发布管理 */}
- {activeTab === 'manage' && (
-
-
📋 我的发布
- {loading ? (
-
加载中...
- ) : myList.length === 0 ? (
-
暂无发布记录
- ) : (
-
- {myList.map(item => (
-
-
{item.title}
-
{formatDate(item.created_at)} | {item.info_type === 'deal' ? '💰 成交' : '🔍 求购'}
+
- ))}
+
+
+
+
+ 🚀 提交发布
+
+
+ )}
+
+ )}
+
+ {activeTab === 'manage' && (
+
+
+ {loading ? (
+ ⏳ 加载中...
+ ) : myList.length === 0 ? (
+ 暂无发布记录
+ ) : (
+
+ {myList.map(item => (
+
+
+
{item.title}
+
+ {item.info_type === 'deal' ? '💰 成交' : '🔍 求购'}
+
+
+ {item.content &&
{item.content}
}
+
+
{formatDate(item.created_at)}
+
+ handleEdit(item)} style={{ padding: '8px 16px', borderRadius: '8px', border: '1px solid #3b82f6', background: 'transparent', color: '#3b82f6', cursor: 'pointer', fontSize: '13px' }}>✏️ 编辑
+ handleDelete(item.id)} style={{ padding: '8px 16px', borderRadius: '8px', border: '1px solid #ef4444', background: 'transparent', color: '#ef4444', cursor: 'pointer', fontSize: '13px' }}>🗑️ 删除
+
+
+
+ ))}
+
+ )}
+
+
+ )}
+
+
+ {/* 编辑弹窗 */}
+ {editingItem && (
+
+
+
✏️ 编辑信息
+
+
+ setEditingItem({...editingItem, title: e.target.value})}
+ style={{ width: '100%', padding: '14px', background: '#0f172a', border: '1px solid #374151', borderRadius: '10px', color: '#fff', boxSizing: 'border-box', fontSize: '14px' }} />
- )}
+
+
+
+
+ 💾 保存
+ setEditingItem(null)} style={{ flex: 1, padding: '14px', border: '1px solid #374151', borderRadius: '10px', background: 'transparent', color: '#9ca3af', cursor: 'pointer', fontSize: '14px' }}>取消
+
+
)}