diff --git a/config/CHANGELOG.md b/config/CHANGELOG.md index 43ec04c..e42ebb8 100644 --- a/config/CHANGELOG.md +++ b/config/CHANGELOG.md @@ -1,5 +1,28 @@ # 版本更新记录 +## v0.2.7 (2026-07-19) - 龙钞宣传功能 + +### 前端更新 +- **Wiki.jsx (新增)** + - 龙钞百科页面,包含:什么是龙钞、号码分类、术语解释、评级知识、保养指南、交易指南 + - 新手入门必备指南 + +- **SharePoster.jsx (新增)** + - 藏品分享海报组件 + - 一键生成精美海报,朋友圈分享 + +- **List.jsx** + - 新增分享按钮,每个藏品卡片右上角显示"📤 分享"按钮 + - 点击生成精美海报,保存到相册 + +- **Home.jsx** + - 快捷操作新增"📚 龙钞百科"入口 + +### 依赖更新 +- 新增 html2canvas 库,用于生成海报图片 + +--- + ## v0.2.5 (2026-05-13) ### 前端更新 diff --git a/config/VERSION.json b/config/VERSION.json index cfd8c15..b052deb 100644 --- a/config/VERSION.json +++ b/config/VERSION.json @@ -1,14 +1,17 @@ { - "version": "0.2.6", - "updated": "2026-06-13", + "version": "0.2.7", + "updated": "2026-07-19", "modules": { "frontend": { - "version": "0.2.2", + "version": "0.2.3", "pages": { "Login": "0.0.2", "Add": "0.0.2", "News": "0.1.2", - "YichensBoard": "0.0.5" + "YichensBoard": "0.0.5", + "Wiki": "1.0.0", + "SharePoster": "1.0.0", + "List": "0.1.7" } }, "backend": { diff --git a/frontend/package-lock.json b/frontend/package-lock.json index f22a1fc..68a70be 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -9,6 +9,7 @@ "version": "1.2.82", "dependencies": { "axios": "^1.7.9", + "html2canvas": "^1.4.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^7.1.0" @@ -1239,6 +1240,15 @@ "proxy-from-env": "^1.1.0" } }, + "node_modules/base64-arraybuffer": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz", + "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + } + }, "node_modules/baseline-browser-mapping": { "version": "2.10.8", "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.8.tgz", @@ -1352,6 +1362,15 @@ "url": "https://opencollective.com/express" } }, + "node_modules/css-line-break": { + "version": "2.1.0", + "resolved": "https://registry.npmmirror.com/css-line-break/-/css-line-break-2.1.0.tgz", + "integrity": "sha512-FHcKFCZcAha3LwfVBhCQbW2nCNbkZXn7KVUJcsT5/P8YmfsVja0FMPJr0B903j/E69HUphKiV9iQArX8SDYA4w==", + "license": "MIT", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/debug": { "version": "4.4.3", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", @@ -1673,6 +1692,19 @@ "node": ">= 0.4" } }, + "node_modules/html2canvas": { + "version": "1.4.1", + "resolved": "https://registry.npmmirror.com/html2canvas/-/html2canvas-1.4.1.tgz", + "integrity": "sha512-fPU6BHNpsyIhr8yyMpTLLxAbkaK8ArIBcmZIRiBLiDhjeqvXolaEmDGmELFuX9I4xDcaKKcJl+TKZLqruBbmWA==", + "license": "MIT", + "dependencies": { + "css-line-break": "^2.1.0", + "text-segmentation": "^1.0.3" + }, + "engines": { + "node": ">=8.0.0" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -1998,6 +2030,15 @@ "node": ">=0.10.0" } }, + "node_modules/text-segmentation": { + "version": "1.0.3", + "resolved": "https://registry.npmmirror.com/text-segmentation/-/text-segmentation-1.0.3.tgz", + "integrity": "sha512-iOiPUo/BGnZ6+54OsWxZidGCsdU8YbE4PSpdPinp7DeMtUJNJBoJ/ouUSTJjHkh1KntHaltHl/gDs2FC4i5+Nw==", + "license": "MIT", + "dependencies": { + "utrie": "^1.0.2" + } + }, "node_modules/tinyglobby": { "version": "0.2.15", "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", @@ -2046,6 +2087,15 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/utrie": { + "version": "1.0.2", + "resolved": "https://registry.npmmirror.com/utrie/-/utrie-1.0.2.tgz", + "integrity": "sha512-1MLa5ouZiOmQzUbjbu9VmjLzn1QLXBhwpUa7kdLUQK+KQ5KA9I1vk5U4YHe/X2Ch7PYnJfWuWT+VbuxbGwljhw==", + "license": "MIT", + "dependencies": { + "base64-arraybuffer": "^1.0.2" + } + }, "node_modules/vite": { "version": "6.4.2", "resolved": "https://registry.npmmirror.com/vite/-/vite-6.4.2.tgz", diff --git a/frontend/package.json b/frontend/package.json index 1826e55..d9e9fe1 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -10,6 +10,7 @@ }, "dependencies": { "axios": "^1.7.9", + "html2canvas": "^1.4.1", "react": "^18.3.1", "react-dom": "^18.3.1", "react-router-dom": "^7.1.0" diff --git a/frontend/src/App.jsx b/frontend/src/App.jsx index f0edd39..c8d85b5 100644 --- a/frontend/src/App.jsx +++ b/frontend/src/App.jsx @@ -10,6 +10,7 @@ import Login from './pages/Login' import Detail from './pages/Detail' import Edit from './pages/Edit' import Admin from './pages/Admin' +import Wiki from './pages/Wiki' export default function App() { const [path, setPath] = useState(window.location.hash.slice(1) || '/') @@ -38,6 +39,7 @@ export default function App() { if (basePath === '/login') return if (basePath === '/settings') return if (basePath === '/admin') return + if (basePath === '/wiki') return if (basePath.startsWith('/edit')) return if (basePath.startsWith('/detail')) return return diff --git a/frontend/src/components/SharePoster.jsx b/frontend/src/components/SharePoster.jsx new file mode 100644 index 0000000..d1b4715 --- /dev/null +++ b/frontend/src/components/SharePoster.jsx @@ -0,0 +1,404 @@ +/** + * SharePoster - 藏品分享海报组件 + * 生成精美的藏品分享图片,用于朋友圈分享 + * Version: 1.0.0 + */ + +import React, { useState, useRef } from 'react' +import html2canvas from 'html2canvas' + +export default function SharePoster({ collection, onClose }) { + const posterRef = useRef(null) + const [generating, setGenerating] = useState(false) + const [generated, setGenerated] = useState(false) + + // 获取号码分类颜色 + const getNumberCategoryColor = (cat) => { + const colors = { + '圆圆号': '#ef4444', + '倒置号': '#f97316', + '金马王': '#eab308', + '金马号': '#84cc16', + '金山王': '#22c55e', + '天马王': '#14b8a6', + '金山号': '#06b6d4', + '天马号': '#0ea5e9', + '朦胧王': '#3b82f6', + '朦胧号': '#6366f1', + '如意号': '#8b5cf6', + '钻石号': '#a855f7', + '永恒号': '#d946ef', + '带7号': '#ec4899', + '带4号': '#f43f5e', + } + return colors[cat] || '#94a3b8' + } + + // 获取状态颜色 + const getStatusColor = (status) => { + const colors = { + 'in_collection': '#22c55e', + 'selling': '#f59e0b', + 'sold': '#ef4444', + 'grading': '#06b6d4', + 'repairing': '#8b5cf6', + 'transit': '#6366f1', + 'seeking': '#f97316', + 'other': '#94a3b8' + } + return colors[status] || '#94a3b8' + } + + // 获取状态文字 + const getStatusText = (status) => { + const texts = { + 'in_collection': '收藏中', + 'selling': '出售中', + 'sold': '已售', + 'grading': '送评中', + 'repairing': '修复中', + 'transit': '在途中', + 'seeking': '寻号中', + 'other': '其他' + } + return texts[status] || status + } + + // 格式化冠字号 + const formatPrefixSerial = (ps) => { + if (!ps) return '-' + const match = ps.match(/^([A-Z]+)(\d+)$/i) + if (match) { + return match[1].toUpperCase() + ' ' + match[2].match(/.{1,4}/g).join(' ') + } + return ps + } + + // 生成海报图片 + const generatePoster = async () => { + if (!posterRef.current) return + + setGenerating(true) + try { + const canvas = await html2canvas(posterRef.current, { + scale: 2, + backgroundColor: '#0f172a', + useCORS: true, + allowTaint: true + }) + + // 转换为图片并下载 + const link = document.createElement('a') + link.download = `龙钞-${collection.code || collection.prefixSerial || '藏品'}.png` + link.href = canvas.toDataURL('image/png') + link.click() + + setGenerated(true) + } catch (e) { + console.error('生成海报失败:', e) + alert('生成海报失败,请重试') + } + setGenerating(false) + } + + return ( +
+ {/* 标题栏 */} +
+

📤 生成分享海报

+ +
+ + {/* 海报预览区域 */} +
+ {/* 背景装饰 */} +
+ + {/* 头部 */} +
+
+ 🐉 甲辰龙钞 +
+
+ 一甲辰藏品管理系统 +
+
+ + {/* 分割线 */} +
+ + {/* 藏品信息 */} +
+ {/* 冠字号 - 大字体 */} +
+
冠字号
+
+ {formatPrefixSerial(collection.prefixSerial)} +
+ {collection.code && ( +
+ 编号: {collection.code} +
+ )} +
+ + {/* 基本信息网格 */} +
+
+
版别
+
{collection.version || '-'}
+
+
+
包装
+
{collection.packaging || '-'}
+
+
+
珍惜度
+
{collection.rarity || '-'}
+
+
+
状态
+
+ {getStatusText(collection.status)} +
+
+
+ + {/* 号码分类标签 */} + {collection.numberCategory && ( +
+ + ⭐ {collection.numberCategory} + +
+ )} + + {/* 评级信息 */} + {collection.isGraded && ( +
+ {collection.gradingCompany && ( + + {collection.gradingCompany} + + )} + {collection.gradingScore && ( + + {collection.gradingScore}分 + + )} + {collection.threeStar && ( + + ★★★ + + )} +
+ )} + + {/* 价格信息 */} +
+
+
成本
+
+ {collection.costPrice ? `¥${collection.costPrice}` : '-'} +
+
+
+
目标价
+
+ {collection.targetPrice ? `¥${collection.targetPrice}` : '-'} +
+
+
+
售价
+
+ {collection.goalPrice ? `¥${collection.goalPrice}` : '-'} +
+
+
+
+ + {/* 底部 */} +
+
+ 长按识别二维码了解更多 +
+
+ 🐉 + jiachenlong.com +
+
+
+ + {/* 操作按钮 */} +
+ + +
+
+ ) +} diff --git a/frontend/src/pages/Home.jsx b/frontend/src/pages/Home.jsx index 1c3b650..c4724b5 100644 --- a/frontend/src/pages/Home.jsx +++ b/frontend/src/pages/Home.jsx @@ -241,6 +241,21 @@ export default function Home() {
我的认购
认购群入口
+
window.location.hash = '#/wiki'} style={{ + background: 'linear-gradient(135deg, rgba(251,191,36,0.15) 0%, rgba(251,191,36,0.05) 100%)', + borderRadius: '12px', + padding: '12px 16px', + border: '1px solid rgba(251,191,36,0.2)', + cursor: 'pointer', + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + justifyContent: 'center', + textAlign: 'center' + }}> +
📚 龙钞百科
+
新手入门指南
+
diff --git a/frontend/src/pages/List.jsx b/frontend/src/pages/List.jsx index d7f9a13..5c12aac 100644 --- a/frontend/src/pages/List.jsx +++ b/frontend/src/pages/List.jsx @@ -1,11 +1,12 @@ /** * List - 藏品列表页面 - * Version: 0.1.6 - * 更新:新增成交行情页面筛选功能(版别、包装类型、号码分类) + * Version: 0.1.7 + * 更新:新增分享海报功能 */ import React, { useState, useEffect } from 'react' import { APP_VERSION } from '../config/version' +import SharePoster from '../components/SharePoster' const API_BASE = localStorage.getItem('API_BASE') || '' export default function List() { @@ -34,6 +35,7 @@ export default function List() { const [dealVersionFilter, setDealVersionFilter] = useState('') // 版别筛选 const [dealPackagingFilter, setDealPackagingFilter] = useState('') // 包装类型筛选 const [dealNumberCatFilter, setDealNumberCatFilter] = useState('') // 号码分类筛选 + const [shareCollection, setShareCollection] = useState(null) // 分享弹窗 useEffect(() => { // 检查是否管理员 @@ -497,7 +499,26 @@ export default function List() { } const ListItem = ({ item }) => ( -
goDetail(item.id)} style={{ background: 'rgba(255,255,255,0.03)', border: '1px solid rgba(255,255,255,0.05)', borderRadius: '12px', padding: '10px', marginBottom: '8px', cursor: 'pointer' }}> +
goDetail(item.id)} style={{ background: 'rgba(255,255,255,0.03)', border: '1px solid rgba(255,255,255,0.05)', borderRadius: '12px', padding: '10px', marginBottom: '8px', cursor: 'pointer', position: 'relative' }}> + {/* 分享按钮 */} + {/* 第1行:编号 + 冠字号 + 包装(蓝色) | 状态 + 持仓类型 + 珍惜度(紫色) */}
@@ -1116,6 +1137,14 @@ function DealListItem({ deal, onRefresh }) { {/* 版本号显示 */}
v0.0.1
+ + {/* 分享海报弹窗 */} + {shareCollection && ( + setShareCollection(null)} + /> + )}
) } diff --git a/frontend/src/pages/Wiki.jsx b/frontend/src/pages/Wiki.jsx new file mode 100644 index 0000000..9a951af --- /dev/null +++ b/frontend/src/pages/Wiki.jsx @@ -0,0 +1,401 @@ +/** + * Wiki - 龙钞百科页面 + * Version: 1.0.0 + * 新手入门知识、号码分类、术语解释 + */ + +import React, { useState } from 'react' +import { APP_VERSION } from '../config/version' + +export default function Wiki() { + const [activeSection, setActiveSection] = useState('intro') + + // 百科内容数据 + const sections = { + intro: { + title: '🐉 什么是龙钞', + content: ` +## 中国人民银行龙钞纪念钞 + +**龙钞**(全称:第24届冬季奥林匹克运动会纪念钞)是中国人民银行于2022年发行的纪念钞,包含**冰上运动**和**雪上运动**两枚一套。 + +### 基本信息 + +| 项目 | 内容 | +|------|------| +| 发行时间 | 2022年12月 | +| 发行量 | 2亿套 | +| 面值 | 20元 | +| 规格 | 145mm × 70mm | + +### 收藏价值 + +1. **题材热门** - 冬奥会是国际大型赛事,题材热度高 +2. **发行量适中** - 2亿的发行量在纪念钞中属于中等 +3. **设计精美** - 首次采用塑料基片+纸基的组合设计 +4. **号码玩法多** - 冠字号+8位数字,组合丰富多样 + ` + }, + category: { + title: '🔢 号码分类', + content: ` +## 龙钞号码分类大全 + +### 顶级号码(收藏价值最高) + +| 分类 | 条件 | 优先级 | +|------|------|--------| +| 🏆 圆圆号 | 不含0、1、2、3、4、5、7 | 1 | +| 🔄 倒置号 | 不含2、3、4、5、7 | 2 | +| 🐎 金马王 | 不含1、2、3、4、7 | 3 | +| 🐎 金马号 | 不含2、3、4、7 | 4 | +| ⛰️ 金山王 | 不含1、2、4、5、7 | 5 | +| ⛰️ 天马王 | 不含1、2、4、7 | 6 | + +### 高级号码 + +| 分类 | 条件 | 备注 | +|------|------|------| +| 🏔️ 金山号 | 不含2、4、5、7 | | +| 🐎 天马号 | 不含2、4、7 | | +| 🌫️ 朦胧王 | 不含1、3、4、5、7 | | +| 🌫️ 朦胧号 | 不含3、4、5、7 | | +| 💎 如意号 | 不含1、3、4、7 | | +| 💎 钻石号 | 不含3、4、7 | | +| ♾️ 永恒号 | 不含4、7 | | + +### 普通号码 + +| 分类 | 条件 | 备注 | +|------|------|------| +| 🔥 带7号 | 不含4 | 不带4的号码 | +| ⚠️ 带4号 | 包含4 | 传统说法带4不太好 | + +### 分类说明 + +- **"无X"规则**:号码中不包含数字X +- **就高不就低**:同时满足多个条件时,按最高价值分类 +- **散钞看8位**:散钞看全部8位数字 +- **标十看7位**:标十看后7位 +- **标百看6位**:标百看后6位 + ` + }, + terms: { + title: '📖 术语解释', + content: ` +## 收藏术语大全 + +### 基础术语 + +| 术语 | 解释 | +|------|------| +| 冠字号 | J+8位数字,如J01234567 | +| 散钞 | 单张收藏的钞票 | +| 标十 | 10连号,一刀 | +| 标百 | 100连号,一捆 | +| 整刀 | 100张连号 | +| 整捆 | 1000张连号 | + +### 评级术语 + +| 术语 | 解释 | +|------|------| +| 评级 | 由专业机构鉴定真伪、品相 | +| 评级公司 | PCGS、NGC、PMG等 | +| 分数 | 评级公司给出的品相分数(70-100) | +| 69+ | 顶级分数,收藏价值高 | +| 68 | 高分,品相极佳 | +| 67 | 不错,品相良好 | + +### 状态术语 + +| 术语 | 解释 | +|------|------| +| 自持 | 自己收藏 | +| 寄存 | 存放在别人那里 | +| 寄售 | 委托他人代卖 | +| 送评 | 送去评级公司评级 | +| 修复 | 经过专业修复 | + +### 价格术语 + +| 术语 | 解释 | +|------|------| +| 成本价 | 入手的价格 | +| 目标价 | 预期出售价格 | +| 成交价 | 实际交易价格 | +| 行情 | 当前市场的买卖价格 | + ` + }, + grade: { + title: '⭐ 评级知识', + content: ` +## 评级公司介绍 + +### 国际三大评级公司 + +#### 1. PCGS(美国) +- 成立于1986年 +- 业界权威,评级标准严格 +- 特别擅长现代币评级 + +#### 2. NGC(美国) +- 成立于1987年 +- 评级数量大 +- 封装设计美观 + +#### 3. PMG(美国) +- 专注于纸币评级 +- 评级标准清晰 +- 国内认知度高 + +### 评分标准 + +| 分数 | 描述 | 等级 | +|------|------|------| +| 70 | 完美未流通 | Gem MS | +| 69 | 接近完美 | Gem MS | +| 68 | 极美 | MS | +| 67 | 精美 | MS | +| 66 | 优美 | MS | +| 65 | 精美 | MS | + +### 评级建议 + +1. **高端收藏** - 建议送评69分以上 +2. **普通收藏** - 67-68分性价比高 +3. **投资需求** - 选择68分以上的评级钞 + +### 注意事项 + +- 评级有风险,可能降级 +- 评级费用几十到几百元不等 +- 评级周期通常2-4周 + ` + }, + care: { + title: '💎 保养指南', + content: ` +## 龙钞保养指南 + +### 存放环境 + +#### 温度与湿度 +- **最佳温度**:18-25°C +- **最佳湿度**:40-55% +- 避免温差大的环境 +- 避免潮湿(易发霉) + +#### 存放方式 +- 使用专用纸币保护套 +- 避免直接用手触摸 +- 远离阳光直射 +- 远离热源(暖气、空调) + +### 注意事项 + +#### ❌ 禁止行为 +- 用手指直接触摸钞面 +- 折叠、弯曲钞票 +- 在钞面上写字 +- 暴露在潮湿环境中 +- 靠近化学物品 + +#### ✅ 正确做法 +- 佩戴手套操作 +- 使用镊子夹取 +- 平放保存 +- 定期检查状态 +- 使用干燥剂 + +### 常见问题 + +**Q: 钞票有折痕怎么办?** +A: 建议送专业修复,或评级遮盖瑕疵 + +**Q: 钞票发黄怎么办?** +A: 避免潮湿环境,可使用干燥剂 + +**Q: 如何判断品相?** +A: 对光查看是否有磨损、污渍、折痕 + ` + }, + platform: { + title: '🛒 交易指南', + content: ` +## 交易注意事项 + +### 交易平台 + +1. **专业钱币交易平台** + - 一尘网 + - 华夏收藏网 + - 钱币天堂 + +2. **二手交易平台** + - 闲鱼(需谨慎) + +3. **微信群交易** + - 诚信商家直供 + - 群内私下交易 + +### 防骗指南 + +#### ⚠️ 常见骗局 +- 低价诱惑先款后货 +- 假称货在朋友处 +- 改号、换号 +- 假评级假分数 + +#### ✅ 安全交易 +1. **走平台交易** + - 使用有保障的平台 + - 保留交易凭证 + +2. **先看后买** + - 要求实拍视频 + - 确认号码无误 + +3. **金额较大** + - 建议走中介 + - 或面交交易 + +### 价格参考 + +- **散钞**:面值+10~50元 +- **标十**:150-300元 +- **标百**:1500-3000元 +- **特殊号码**:价格面议 + +### 投资建议 + +1. 理性投资,量力而行 +2. 注重品相,号码为辅 +3. 长期持有,静待升值 +4. 分散投资,不要all in + ` + } + } + + // 渲染Markdown内容(简化版) + const renderContent = (content) => { + const lines = content.trim().split('\n') + return lines.map((line, idx) => { + // 标题 + if (line.startsWith('## ')) { + return

{line.replace('## ', '')}

+ } + // 小标题 + if (line.startsWith('### ')) { + return

{line.replace('### ', '')}

+ } + // 表格 + if (line.startsWith('|') && !line.startsWith('|---')) { + const cells = line.split('|').filter(c => c.trim()) + if (cells.length > 1) { + const isHeader = idx > 0 && lines[idx-1]?.includes('---') + return ( +
+ {cells.map((cell, i) => ( +
+ {cell.trim()} +
+ ))} +
+ ) + } + return null + } + // 无序列表 + if (line.startsWith('- ') || line.startsWith('1. ')) { + const text = line.replace(/^[-1-9.]\s*/, '') + return
{text}
+ } + // 普通段落 + if (line.trim()) { + // 处理加粗 + let text = line.replace(/\*\*(.*?)\*\*/g, '$1') + return

+ } + return null + }) + } + + return ( +

+ {/* 头部 */} +
+
+
+ +

📚 龙钞百科

+
+ v{APP_VERSION} +
+ + {/* 简介文字 */} +

+ 新手入门指南 · 号码分类 · 术语解释 · 保养知识 +

+
+ + {/* 导航标签 */} +
+ {Object.entries(sections).map(([key, section]) => ( + + ))} +
+ + {/* 内容区域 */} +
+
+ {renderContent(sections[activeSection].content)} +
+
+ + {/* 底部提示 */} +
+ + 💡 了解更多,请访问 jiachenlong.com + +
+
+ ) +}