Skip to content
Draft
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
184 changes: 124 additions & 60 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,73 +1,137 @@
# React + TypeScript + Vite
# DEVELOP 显影前端

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
DEVELOP(显影)是面向图片与视频生成内容的可解释检测与取证演示前端。项目包含用户侧检测流程、图片/视频报告、治理端数据生成、专家库和异常池等页面。

Currently, two official plugins are available:
## 技术栈

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
- React 18
- TypeScript
- Vite
- React Router
- Framer Motion
- Zustand
- CSS Modules

## React Compiler
## 环境要求

The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
建议使用较新的 Node.js 版本。本项目当前验证环境:

## Expanding the ESLint configuration
```bash
node v24.11.1
npm 11.7.0
```

如果本机 Node 版本较旧,建议升级到 Node 20+ 后再安装依赖。

## 安装与运行

进入项目目录:

```bash
cd develop
```

安装依赖:

```bash
npm install
```

If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
启动开发服务器:

```js
export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
```bash
npm run dev
```

// Remove tseslint.configs.recommended and replace with this
tseslint.configs.recommendedTypeChecked,
// Alternatively, use this for stricter rules
tseslint.configs.strictTypeChecked,
// Optionally, add this for stylistic rules
tseslint.configs.stylisticTypeChecked,
Vite 会在终端输出本地访问地址,通常是:

// Other configs...
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
```text
http://localhost:5173/
```

You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:

```js
// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'

export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
// Enable lint rules for React
reactX.configs['recommended-typescript'],
// Enable lint rules for React DOM
reactDom.configs.recommended,
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
## 构建与预览

生产构建:

```bash
npm run build
```

本地预览构建产物:

```bash
npm run preview
```

## 常用路由

- `/`:首页
- `/detect`:检测类型选择
- `/detect/image`:图像取证
- `/detect/video`:视频检测
- `/detect/report/:id`:鉴别报告
- `/admin`:治理中心
- `/admin/pipeline`:数据生成
- `/admin/pipeline/showcase/video`:视频标注解构台
- `/admin/pipeline/showcase/image`:图片标注工作流
- `/admin/experts`:专家库
- `/admin/anomaly`:异常池
- `/dev`:组件展示页

## 推荐演示流程

1. 打开 `/` 查看首页和项目入口。
2. 进入 `/detect/image`,上传图片或使用示例图,等待检测完成。
3. 点击“查看详细报告”,报告会展示本次检测图片、关键证据、语义链和专家网络。
4. 进入 `/detect/video`,等待视频检测完成。
5. 点击“查看完整报告”,报告会展示视频材料和片段级证据。
6. 进入 `/admin` 查看治理端能力,再按需要进入数据生成、专家库和异常池页面。

## 脚本说明

```bash
npm run dev # 启动开发服务器
npm run build # TypeScript 检查并构建生产包
npm run preview # 预览 dist 构建产物
npm run lint # 运行 ESLint
```

## 当前验证状态

最近一次验证:

```bash
npm run build
```

构建通过。

`npm run lint` 当前存在既有规则报错,主要来自以下位置:

- `src/components/GlobalHUD.tsx`:render 中调用 `Math.random`
- `src/pages/AdminAnomaly/index.tsx`:effect 中同步 setState
- `src/pages/AdminPipeline/ImageShowcase.tsx`:render 初始化中调用 `Date.now`

这些 lint 问题不影响 `npm run dev` 和 `npm run build`,但后续如果要把 lint 作为 CI 必过项,需要单独修复。

## 目录说明

```text
src/
App.tsx # 路由入口
components/ # 通用组件与业务组件
data/ # mock 数据与报告快照存储
layouts/ # 管理端布局
pages/ # 页面实现
tokens/ # 全局设计 token
public/
images/ # 图片素材
samples/ # 样本与视频帧素材
videos/ # 视频工作流素材
```

## 注意事项

- 项目代码位于 `develop` 目录,不是仓库根目录的旧前端。
- 不需要后端服务即可运行当前演示,检测结果和报告使用前端 mock 数据与浏览器 `sessionStorage` 快照。
- 图片报告会根据当前上传或示例图片实时生成,不再固定显示模板图。
Binary file added image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/pipeline-products/local_edited.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/pipeline-products/product-01.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/pipeline-products/product-03.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/pipeline-products/product-05.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/images/pipeline-products/product-07.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified public/images/图片检测示例图/image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/samples/fake_seg1s__.mp4
Binary file not shown.
Binary file added public/samples/frames/frame-01.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/samples/frames/frame-02.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/samples/frames/frame-03.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/samples/frames/frame-04.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/samples/frames/frame-05.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/samples/frames/frame-06.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/samples/frames/frame-07.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/samples/frames/frame-08.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/samples/frames/frame-09.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/samples/frames/frame-10.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/samples/frames/frame-11.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/samples/frames/frame-12.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/01-home.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/02-detect-choice.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/03-detect-image.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/04-detect-video.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/05-report.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added screenshots/06-admin-overview.png
Binary file added screenshots/07-admin-pipeline.png
Binary file added screenshots/08-admin-pipeline-video-showcase.png
Binary file added screenshots/10-admin-experts.png
Binary file added screenshots/11-admin-anomaly.png
Binary file added screenshots/12-dev.png
Binary file added screenshots/13-not-found.png
106 changes: 106 additions & 0 deletions src/components/BootSequence.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
.bootScreen {
position: fixed;
inset: 0;
background: #0E0D0B;
z-index: 999999;
display: flex;
align-items: center;
justify-content: center;
color: var(--accent);
font-family: var(--font-mono);
overflow: hidden;
}

.terminal {
width: 80%;
max-width: 800px;
display: flex;
flex-direction: column;
gap: 48px;
position: relative;
z-index: 2;
}

.logo {
font-size: 64px;
font-family: var(--font-serif);
letter-spacing: 0.2em;
color: var(--surface);
text-shadow: 0 0 30px rgba(200, 65, 46, 0.4);
animation: glitch 3s infinite;
}

@keyframes glitch {
0% { transform: translate(0) }
20% { transform: translate(-2px, 1px) }
21% { transform: translate(2px, -1px) }
22% { transform: translate(0) }
100% { transform: translate(0) }
}

.logs {
display: flex;
flex-direction: column;
gap: 12px;
font-size: 16px;
color: var(--accent);
text-shadow: 0 0 10px rgba(200, 65, 46, 0.6);
}

.logLine {
opacity: 0;
animation: typeIn 0.1s forwards;
}

@keyframes typeIn {
to { opacity: 1; }
}

.cursor {
width: 12px;
height: 20px;
background: var(--accent);
animation: blink 1s step-end infinite;
margin-top: 8px;
}

@keyframes blink {
0%, 100% { opacity: 1; }
50% { opacity: 0; }
}

.scanline {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 30vh;
background: linear-gradient(to bottom, transparent, rgba(200, 65, 46, 0.1), transparent);
animation: scan 4s linear infinite;
z-index: 1;
pointer-events: none;
}

@keyframes scan {
0% { transform: translateY(-100vh); }
100% { transform: translateY(200vh); }
}

.gridOverlay {
position: absolute;
inset: 0;
background-image:
linear-gradient(rgba(200, 65, 46, 0.05) 1px, transparent 1px),
linear-gradient(90deg, rgba(200, 65, 46, 0.05) 1px, transparent 1px);
background-size: 40px 40px;
transform: perspective(500px) rotateX(60deg) scale(2);
transform-origin: bottom center;
opacity: 0.3;
z-index: 1;
animation: gridMove 20s linear infinite;
}

@keyframes gridMove {
0% { transform: perspective(500px) rotateX(60deg) translateY(0) scale(2); }
100% { transform: perspective(500px) rotateX(60deg) translateY(40px) scale(2); }
}
56 changes: 56 additions & 0 deletions src/components/BootSequence.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { useEffect, useState } from 'react';
import { motion, AnimatePresence } from 'framer-motion';
import styles from './BootSequence.module.css';

const BOOT_LOGS = [
"> INITIATING OS_KERNEL_V4.2...",
"> ESTABLISHING NEURAL LINK...",
"> SYNCING GLOBAL THREAT DATABASE [██████████] 100%",
"> DECRYPTING SECURE CHANNELS...",
"> LOADING TACTICAL HUD...",
"> ACCESS GRANTED. WELCOME, ADMIN."
];

export function BootSequence() {
const [isVisible, setIsVisible] = useState(true);
const [logs, setLogs] = useState<string[]>([]);

useEffect(() => {
let delay = 200;
BOOT_LOGS.forEach((log) => {
setTimeout(() => {
setLogs((prev) => [...prev, log]);
}, delay);
delay += Math.random() * 250 + 150;
});

setTimeout(() => {
setIsVisible(false);
}, delay + 600);
}, []);

return (
<AnimatePresence>
{isVisible && (
<motion.div
className={styles.bootScreen}
initial={{ opacity: 1 }}
exit={{ opacity: 0, filter: "blur(20px)", scale: 1.1 }}
transition={{ duration: 0.8, ease: "easeInOut" }}
>
<div className={styles.terminal}>
<div className={styles.logo}>ANTIGRAVITY OS</div>
<div className={styles.logs}>
{logs.map((log, i) => (
<div key={i} className={styles.logLine}>{log}</div>
))}
<div className={styles.cursor} />
</div>
</div>
<div className={styles.scanline} />
<div className={styles.gridOverlay} />
</motion.div>
)}
</AnimatePresence>
);
}
Loading