feat: 添加 Admin Dashboard — React 19 SPA,包含 7 个页面
- Dashboard: 健康状态轮询、状态卡片、内存统计、快捷操作 - Login: 二维码展示 + 3 秒自动轮询 + 倒计时 + 登出 - Browser: 探索/搜索/用户三标签页,Feed 网格、详情面板、评论树 - Publish: 图文/视频发布表单,支持标签、可见性、定时发布 - Interactions: 点赞/取消点赞、收藏、评论、回复 + 操作日志 - API Tester: 端点选择器、请求体编辑器、cURL 生成、响应查看、历史记录 - Settings: Token 配置、服务器 URL 设置 后端改动: - app.ts: 生产环境提供 dist/web/ 静态文件服务 + SPA fallback - Dockerfile: 添加 web 构建阶段 - package.json: 添加 build:web、build:all、dev:web 脚本 技术栈: React 19 + TypeScript + Vite 6 + Tailwind CSS(暗色主题) 产物: 85.5 KB gzip JS + 4 KB gzip CSS,零重型依赖
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
import { Card } from '@/components/ui/Card';
|
||||
import { Input } from '@/components/ui/Input';
|
||||
import { Button } from '@/components/ui/Button';
|
||||
import { useAuth } from '@/context/AuthContext';
|
||||
import { useToast } from '@/context/ToastContext';
|
||||
|
||||
export function SettingsPage() {
|
||||
const { token, serverUrl, setToken, setServerUrl } = useAuth();
|
||||
const { toast } = useToast();
|
||||
|
||||
return (
|
||||
<div className="max-w-2xl space-y-6">
|
||||
<h1 className="text-2xl font-bold">Settings</h1>
|
||||
|
||||
{/* Server Connection */}
|
||||
<Card>
|
||||
<h2 className="text-sm font-semibold text-dark-muted uppercase tracking-wider mb-4">Server Connection</h2>
|
||||
<div className="space-y-4">
|
||||
<Input
|
||||
label="Server URL"
|
||||
value={serverUrl}
|
||||
onChange={(e) => setServerUrl(e.target.value)}
|
||||
placeholder="Leave empty for same-origin (default)"
|
||||
/>
|
||||
<p className="text-xs text-dark-muted">
|
||||
Leave empty when the dashboard is served by the same Express server.
|
||||
Set to e.g. <code className="text-dark-accent">http://192.168.1.100:3000</code> for remote servers.
|
||||
</p>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* Authentication */}
|
||||
<Card>
|
||||
<h2 className="text-sm font-semibold text-dark-muted uppercase tracking-wider mb-4">Authentication</h2>
|
||||
<div className="space-y-4">
|
||||
<Input
|
||||
label="Bearer Token"
|
||||
type="password"
|
||||
value={token}
|
||||
onChange={(e) => setToken(e.target.value)}
|
||||
placeholder="Enter your API token"
|
||||
/>
|
||||
<p className="text-xs text-dark-muted">
|
||||
Token from <code className="text-dark-accent">BEARER_TOKEN</code> environment variable or{' '}
|
||||
<code className="text-dark-accent">.social-mcp/bearer-token</code> file.
|
||||
</p>
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
variant="secondary"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
toast('success', 'Settings saved');
|
||||
}}
|
||||
>
|
||||
Save
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => {
|
||||
setToken('');
|
||||
setServerUrl('');
|
||||
toast('info', 'Settings cleared');
|
||||
}}
|
||||
>
|
||||
Clear All
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
|
||||
{/* About */}
|
||||
<Card>
|
||||
<h2 className="text-sm font-semibold text-dark-muted uppercase tracking-wider mb-4">About</h2>
|
||||
<div className="space-y-2 text-sm text-dark-muted">
|
||||
<p><span className="text-dark-text">Social MCP</span> — Multi-platform social media automation</p>
|
||||
<p>Version: 0.1.0</p>
|
||||
<p>Stack: React 19 + TypeScript + Tailwind CSS</p>
|
||||
</div>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user