Skip to content

Commit ab8f698

Browse files
Merge pull request #54 from easyshellworld/dev
add QRBulkGenerator
2 parents 2d6769e + 013c307 commit ab8f698

8 files changed

Lines changed: 740 additions & 114 deletions

File tree

README.md

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ npm install
174174

175175
**3.2 配置应用环境变量**
176176

177-
创建 `.env.local``.env` 文件并配置以下内容:
177+
创建 `.env` 文件并配置以下内容:
178178

179179
```env
180180
# 数据库配置
@@ -184,16 +184,15 @@ DATABASE_URL="your_database_url"
184184
NEXTAUTH_SECRET="your_nextauth_secret"
185185
NEXTAUTH_URL="http://localhost:3000"
186186
187-
# Polkadot Hub Testnet 配置
188-
NEXT_PUBLIC_CHAIN_ID="polkadot-hub-testnet"
189-
NEXT_PUBLIC_RPC_URL="your_rpc_url"
187+
# 配置网站基本链接
188+
NEXT_PUBLIC_ARROW_TOWER_BASE_URL="https://arrowtower.netlify.app/"
190189
191190
# 智能合约地址
192191
NEXT_PUBLIC_MINTER_CONTRACT="0x079098fb8e901DE45AB510fA669bdE793DfEBD50"
193192
NEXT_PUBLIC_NFT_CONTRACT="0x9373197B94f4633FBc121532F3cF3948FD4a5a15"
194193
195194
# 后端铸造私钥(仅服务端)
196-
MINTER_PRIVATE_KEY="your_private_key"
195+
PRIVATE_KEY="your_private_key"
197196
```
198197

199198
**3.3 初始化数据库**

data/arrowtower.db

0 Bytes
Binary file not shown.

package-lock.json

Lines changed: 130 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
"@radix-ui/react-tabs": "^1.1.13",
2424
"@radix-ui/react-tooltip": "^1.2.8",
2525
"@tanstack/react-query": "^5.90.2",
26+
"@types/qrcode": "^1.5.5",
2627
"bullmq": "^5.61.0",
2728
"class-variance-authority": "^0.7.1",
2829
"clsx": "^2.1.1",
@@ -32,6 +33,7 @@
3233
"next": "15.5.4",
3334
"next-auth": "^4.24.11",
3435
"next-themes": "^0.4.6",
36+
"qrcode": "^1.5.4",
3537
"react": "19.1.0",
3638
"react-dom": "19.1.0",
3739
"sonner": "^2.0.7",

src/app/admin/page.tsx

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,12 @@ import { ArrowTowerHeader } from '@/components/maps/ArrowTowerHeader';
77
import { AdminTable } from '@/components/admin/AdminTable';
88
import { AdminModal } from '@/components/admin/AdminModal';
99
import { ChainStats } from '@/components/admin/ChainStats';
10+
import { QRBulkGenerator } from '@/components/admin/QRBulkGenerator';
1011
import { Card } from '@/components/ui/card';
1112
import { Button } from '@/components/ui/button';
1213
import { Badge } from '@/components/ui/badge';
1314

14-
type TabType = 'chain' | 'users' | 'routes' | 'pois' | 'checkins' | 'vouchers';
15+
type TabType = 'chain' | 'users' | 'routes' | 'pois' | 'checkins' | 'vouchers' | 'qr_bulk';
1516

1617
interface User {
1718
id: string;
@@ -99,14 +100,15 @@ export default function AdminDashboard() {
99100

100101
// 加载数据
101102
const fetchData = async (type: TabType) => {
102-
if (type === 'chain') return; // 链上数据由组件自己处理
103+
if (type === 'chain' || type === 'qr_bulk') return; // 这些标签页有自己的数据处理逻辑
103104

104105
setLoading(true);
105106
setError(null);
106107

107108
try {
108109
const endpoints: Record<TabType, string> = {
109110
chain: '',
111+
qr_bulk: '',
110112
users: '/api/admin/users',
111113
routes: '/api/admin/routes',
112114
pois: '/api/admin/pois',
@@ -158,6 +160,7 @@ export default function AdminDashboard() {
158160

159161
const defaults: Record<TabType, any> = {
160162
chain: {},
163+
qr_bulk: {},
161164
users: {
162165
id: crypto.randomUUID(),
163166
walletAddress: '',
@@ -202,11 +205,12 @@ export default function AdminDashboard() {
202205

203206
// 删除
204207
const handleDelete = async (item: any) => {
205-
if (!confirm('确定要删除吗此操作不可恢复')) return;
208+
if (!confirm('确定要删除吗?此操作不可恢复!')) return;
206209

207210
try {
208211
const endpoints: Record<TabType, string> = {
209212
chain: '',
213+
qr_bulk: '',
210214
users: `/api/admin/users/${item.id}`,
211215
routes: `/api/admin/routes/${item.id}`,
212216
pois: `/api/admin/pois/${item.id}`,
@@ -235,6 +239,7 @@ export default function AdminDashboard() {
235239
try {
236240
const endpoints: Record<TabType, string> = {
237241
chain: '',
242+
qr_bulk: '',
238243
users: modalType === 'create' ? '/api/admin/users' : `/api/admin/users/${currentId}`,
239244
routes: modalType === 'create' ? '/api/admin/routes' : `/api/admin/routes/${currentId}`,
240245
pois: modalType === 'create' ? '/api/admin/pois' : `/api/admin/pois/${currentId}`,
@@ -269,6 +274,7 @@ export default function AdminDashboard() {
269274
const getModalFields = () => {
270275
const fieldsMap: Record<TabType, any[]> = {
271276
chain: [],
277+
qr_bulk: [],
272278
users: [
273279
{ name: 'id', label: '用户ID', type: 'text', required: true, disabled: modalType === 'update' },
274280
{ name: 'walletAddress', label: '钱包地址', type: 'text', required: true, disabled: modalType === 'update' },
@@ -336,6 +342,7 @@ export default function AdminDashboard() {
336342
const getTableColumns = () => {
337343
const columnsMap: Record<TabType, any[]> = {
338344
chain: [],
345+
qr_bulk: [],
339346
users: [
340347
{ key: 'avatar', label: '头像', render: (val: string) => (
341348
<img src={val || '/default-avatar.png'} alt="avatar" className="w-10 h-10 rounded-full border-2 border-emerald-200" />
@@ -423,6 +430,7 @@ export default function AdminDashboard() {
423430
{ id: 'users', label: '用户管理', icon: '👥' },
424431
{ id: 'routes', label: '路线管理', icon: '🗺️' },
425432
{ id: 'pois', label: '打卡点管理', icon: '📍' },
433+
{ id: 'qr_bulk', label: '打卡点二维码', icon: '🔳' },
426434
{ id: 'checkins', label: '打卡记录', icon: '✅' },
427435
{ id: 'vouchers', label: 'NFT凭证', icon: '🎨' }
428436
];
@@ -456,8 +464,15 @@ export default function AdminDashboard() {
456464
{/* 内容区域 */}
457465
{activeTab === 'chain' ? (
458466
<ChainStats />
467+
) : activeTab === 'qr_bulk' ? (
468+
<QRBulkGenerator
469+
pois={pois}
470+
loading={loading}
471+
error={error}
472+
onRefresh={() => fetchData('pois')}
473+
/>
459474
) : (
460-
<AdminTable
475+
<AdminTable<User | Route | POI | Checkin | Voucher>
461476
title={tabs.find(t => t.id === activeTab)?.label || ''}
462477
icon={tabs.find(t => t.id === activeTab)?.icon || ''}
463478
data={
@@ -482,6 +497,7 @@ export default function AdminDashboard() {
482497
onDelete={handleDelete}
483498
onRefresh={() => fetchData(activeTab)}
484499
addButtonText="新增"
500+
showQRButton={activeTab === 'pois'}
485501
/>
486502
)}
487503

0 commit comments

Comments
 (0)