Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
name: CI

on:
push:
branches: [main]
pull_request:
branches: [main]

permissions:
contents: read

concurrency:
group: ci-${{ github.ref }}
cancel-in-progress: true

jobs:
ci:
runs-on: ubuntu-latest

env:
NEXT_TELEMETRY_DISABLED: '1'
DATABASE_URL: postgresql://user:pass@localhost:5432/placeholder
JWT_SECRET: ci-placeholder-secret-at-least-32-characters
SITE_ORIGIN: https://example.invalid

steps:
- uses: actions/checkout@v4

- uses: actions/setup-node@v4
with:
node-version: '20'
cache: npm

- name: Restore Next.js build cache
uses: actions/cache@v4
with:
path: .next/cache
key: nextjs-${{ hashFiles('package-lock.json') }}-${{ hashFiles('**/*.js', '**/*.jsx', '**/*.ts', '**/*.tsx') }}
restore-keys: |
nextjs-${{ hashFiles('package-lock.json') }}-

- run: npm ci

- name: Generate Prisma Client
run: npm run prisma:generate

- run: npm run lint

- run: npm run typecheck

- run: npm test

- run: npm run test:ftml

- run: npm run build

- name: knip (informational)
run: npx --yes knip --no-exit-code --reporter compact
65 changes: 33 additions & 32 deletions components/Header.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React, { useState, useEffect } from 'react';
import Link from 'next/link';
const config = require('../wikitdb.config.js');

// 高清矢量 Logo 组件
Expand Down Expand Up @@ -88,32 +89,32 @@ const Header = () => {
</button>
</div>
<div className="flex flex-1 items-center justify-center sm:items-stretch sm:justify-start">
<a href="/" className="flex shrink-0 items-center gap-2.5">
<Link href="/" className="flex shrink-0 items-center gap-2.5">
<HighDefLogoSVG className="h-10 w-10 drop-shadow-md" />
<span className="font-bold text-gray-900 dark:text-white text-lg tracking-wide">{config.SITE_NAME}</span>
</a>
</Link>
<div className="hidden sm:ml-6 sm:block">
<div className="flex space-x-4 items-center h-full">
<a href="/pages" className="rounded-md px-3 py-2 text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-white/5 hover:text-gray-900 dark:hover:text-white transition-colors">
<Link href="/pages" className="rounded-md px-3 py-2 text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-white/5 hover:text-gray-900 dark:hover:text-white transition-colors">
<i className="fa-solid fa-file"></i> 页面
</a>
<a href="/authors" className="rounded-md px-3 py-2 text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-white/5 hover:text-gray-900 dark:hover:text-white transition-colors">
</Link>
<Link href="/authors" className="rounded-md px-3 py-2 text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-white/5 hover:text-gray-900 dark:hover:text-white transition-colors">
<i className="fa-solid fa-user"></i> 作者
</a>
<a href="/tools" className="rounded-md px-3 py-2 text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-white/5 hover:text-gray-900 dark:hover:text-white transition-colors">
</Link>
<Link href="/tools" className="rounded-md px-3 py-2 text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-white/5 hover:text-gray-900 dark:hover:text-white transition-colors">
<i className="fa-solid fa-toolbox"></i> 工具
</a>
</Link>
{isStaff && (
<a href="/staff-panel" className="rounded-md px-3 py-2 text-sm font-medium text-emerald-500 hover:bg-emerald-500/10 transition-colors">
<Link href="/staff-panel" className="rounded-md px-3 py-2 text-sm font-medium text-emerald-500 hover:bg-emerald-500/10 transition-colors">
<i className="fa-solid fa-user-shield"></i> 职员面板
</a>
</Link>
)}
<a href="/forums" className="rounded-md px-3 py-2 text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-white/5 hover:text-gray-900 dark:hover:text-white transition-colors">
<Link href="/forums" className="rounded-md px-3 py-2 text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-white/5 hover:text-gray-900 dark:hover:text-white transition-colors">
<i className="fa-solid fa-comments"></i> 论坛
</a>
<a href="/about" className="rounded-md px-3 py-2 text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-white/5 hover:text-gray-900 dark:hover:text-white transition-colors">
</Link>
<Link href="/about" className="rounded-md px-3 py-2 text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-white/5 hover:text-gray-900 dark:hover:text-white transition-colors">
<i className="fa-solid fa-circle-info"></i> 关于
</a>
</Link>
</div>
</div>
</div>
Expand All @@ -131,8 +132,8 @@ const Header = () => {
</>
) : (
<>
<a href="/login" className="text-sm font-medium text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors">登录</a>
<a href="/register" className="rounded-md bg-indigo-600 px-3 py-2 text-sm font-medium text-white hover:bg-indigo-700 transition-all shadow-md hover:shadow-indigo-500/20">注册</a>
<Link href="/login" className="text-sm font-medium text-gray-600 dark:text-gray-300 hover:text-gray-900 dark:hover:text-white transition-colors">登录</Link>
<Link href="/register" className="rounded-md bg-indigo-600 px-3 py-2 text-sm font-medium text-white hover:bg-indigo-700 transition-all shadow-md hover:shadow-indigo-500/20">注册</Link>
</>
)}
</div>
Expand All @@ -142,27 +143,27 @@ const Header = () => {
<div className={`${isMobileMenuOpen ? 'block' : 'hidden'} sm:hidden border-t border-gray-100 dark:border-gray-700`} id="mobile-menu">
<div className="space-y-1 px-2 pt-2 pb-3 bg-white dark:bg-gray-900">
<div className="grid grid-cols-2 gap-2">
<a href="/pages" className="rounded-md px-3 py-2 text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-white/5 hover:text-gray-900 dark:hover:text-white">
<Link href="/pages" className="rounded-md px-3 py-2 text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-white/5 hover:text-gray-900 dark:hover:text-white">
<i className="fa-solid fa-file"></i> 页面
</a>
</Link>
{/* ... 其他链接同理 ... */}
<a href="/authors" className="rounded-md px-3 py-2 text-sm font-medium text-gray-300 hover:bg-white/5 hover:text-white">
<Link href="/authors" className="rounded-md px-3 py-2 text-sm font-medium text-gray-300 hover:bg-white/5 hover:text-white">
<i className="fa-solid fa-user"></i> 作者
</a>
<a href="/tools" className="rounded-md px-3 py-2 text-sm font-medium text-gray-300 hover:bg-white/5 hover:text-white">
</Link>
<Link href="/tools" className="rounded-md px-3 py-2 text-sm font-medium text-gray-300 hover:bg-white/5 hover:text-white">
<i className="fa-solid fa-toolbox"></i> 工具
</a>
</Link>
{isStaff && (
<a href="/staff-panel" className="rounded-md px-3 py-2 text-sm font-medium text-emerald-400 hover:bg-emerald-500/10 hover:text-emerald-300">
<Link href="/staff-panel" className="rounded-md px-3 py-2 text-sm font-medium text-emerald-400 hover:bg-emerald-500/10 hover:text-emerald-300">
<i className="fa-solid fa-user-shield"></i> 职员面板
</a>
</Link>
)}
<a href="/forums" className="rounded-md px-3 py-2 text-sm font-medium text-gray-300 hover:bg-white/5 hover:text-white">
<Link href="/forums" className="rounded-md px-3 py-2 text-sm font-medium text-gray-300 hover:bg-white/5 hover:text-white">
<i className="fa-solid fa-comments"></i> 论坛
</a>
<a href="/about" className="rounded-md px-3 py-2 text-sm font-medium text-gray-300 hover:bg-white/5 hover:text-white">
</Link>
<Link href="/about" className="rounded-md px-3 py-2 text-sm font-medium text-gray-300 hover:bg-white/5 hover:text-white">
<i className="fa-solid fa-circle-info"></i> 关于
</a>
</Link>
</div>

<div className="mt-4 border-t border-gray-700 pt-4 pb-2">
Expand All @@ -178,12 +179,12 @@ const Header = () => {
</div>
) : (
<div className="grid grid-cols-2 gap-2">
<a href="/login" className="text-center rounded-md border border-gray-600 px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700">
<Link href="/login" className="text-center rounded-md border border-gray-600 px-3 py-2 text-sm font-medium text-gray-300 hover:bg-gray-700">
登录
</a>
<a href="/register" className="text-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-medium text-white hover:bg-indigo-700">
</Link>
<Link href="/register" className="text-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-medium text-white hover:bg-indigo-700">
注册
</a>
</Link>
</div>
)}
</div>
Expand Down
8 changes: 8 additions & 0 deletions eslint.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { FlatCompat } from '@eslint/eslintrc';

const compat = new FlatCompat({ baseDirectory: import.meta.dirname });

export default [
{ ignores: ['.next/**', 'node_modules/**', 'public/vendor/**', 'others/**'] },
...compat.config({ extends: ['next/core-web-vitals'] }),
];
Loading
Loading