feat: Add company introduction, about us, feature descriptions, user agreement, and privacy policy documents
- Created company introduction document with details about the studio, contact information, and business scope. - Added an "About Us" document outlining the team's mission, vision, and contact details. - Developed a comprehensive feature introduction for the kevisual assistant, detailing various functionalities. - Established a user agreement outlining terms of use, intellectual property rights, and privacy policy. - Implemented a privacy policy document explaining information collection, usage, and security measures. feat: Enhance the skill-beautiful app with interactive features and improved UI - Integrated THREE.js for 3D rendering and added control modules for user interaction. - Created a dynamic information panel with CSS3D rendering for better user experience. - Implemented particle systems and lighting effects to enhance visual appeal. - Added keyboard controls for camera manipulation and information display toggling. fix: Update routing and rendering logic in the app provider - Adjusted the app provider to ensure proper cleanup of resources on component unmount. - Improved the layout and styling of the main application container for better responsiveness. chore: Set up info page with proper metadata and styling - Created an info page with relevant metadata for SEO and user engagement. - Imported necessary styles for consistent design across the application.
This commit is contained in:
6
.vscode/settings.json
vendored
6
.vscode/settings.json
vendored
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"workbench.editorAssociations": {
|
||||
// "*.md": "vscode.markdown.preview.editor" // 预览打开
|
||||
"*.md": "default" // 默认打开
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 74 KiB After Width: | Height: | Size: 74 KiB |
|
Before Width: | Height: | Size: 464 KiB After Width: | Height: | Size: 464 KiB |
@@ -1,43 +1,33 @@
|
||||
# Astro Starter Kit: Minimal
|
||||
# 可视化助手
|
||||
|
||||
```sh
|
||||
pnpm create astro@latest -- --template minimal
|
||||
```
|
||||
## 我期望实现的功能
|
||||
|
||||
> 🧑🚀 **Seasoned astronaut?** Delete this file. Have fun!
|
||||
人在网络上生活的方面的所有内容,都能更好地被管理和使用。学习、工作、娱乐、社交等各个方面的内容,都能被整合在自己的可视化的空间中。这空间具备自执行的能力,能主动帮助人完成各项任务,操作系统,浏览器,应用程序。
|
||||
|
||||
## 🚀 Project Structure
|
||||
## 方向
|
||||
|
||||
Inside of your Astro project, you'll see the following folders and files:
|
||||
### 1. 知识库
|
||||
|
||||
```text
|
||||
/
|
||||
├── public/
|
||||
├── src/
|
||||
│ └── pages/
|
||||
│ └── index.astro
|
||||
└── package.json
|
||||
```
|
||||
构建一个个人知识库,能存储和管理各种类型的信息,包括文本、图片、音频、视频等。知识库支持标签、分类、搜索等功能,方便用户快速找到所需信息。非文本,则需要转换为文本进行存储和管理。
|
||||
|
||||
Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name.
|
||||
### 2. 代码编辑器
|
||||
|
||||
There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components.
|
||||
一切底层运行必开发,如果没有开发环境,那么就需要一个云端代码编辑器,能让用户在浏览器中编写代码,并且能运行和调试代码。
|
||||
|
||||
Any static assets, like images, can be placed in the `public/` directory.
|
||||
### 3. 可视化编程
|
||||
|
||||
## 🧞 Commands
|
||||
对话式编程,图形化编程,模块化编程,积木式编程等方式,让用户能更方便地创建程序。
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
### 4. 数据存储
|
||||
|
||||
| Command | Action |
|
||||
| :------------------------ | :----------------------------------------------- |
|
||||
| `pnpm install` | Installs dependencies |
|
||||
| `pnpm dev` | Starts local dev server at `localhost:4321` |
|
||||
| `pnpm build` | Build your production site to `./dist/` |
|
||||
| `pnpm preview` | Preview your build locally, before deploying |
|
||||
| `pnpm astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| `pnpm astro -- --help` | Get help using the Astro CLI |
|
||||
云端如何对个人用户来说,如何存储数据,想实现的功能,网页如何更简便获取数据。
|
||||
|
||||
### 5. 自动化任务
|
||||
|
||||
描述一个简单的需求,自动根据需求生成功能。
|
||||
|
||||
### 6. AI 交互
|
||||
|
||||
通过自然语言与 AI 进行交互,完成各种任务,如信息查询、内容生成、数据分析等。AI 能理解用户的意图,并提供相应的帮助和建议。
|
||||
|
||||
## 👀 Want to learn more?
|
||||
|
||||
Feel free to check [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat).
|
||||
|
||||
@@ -11,11 +11,13 @@
|
||||
"pub": "envision deploy ./dist -k official -v 0.0.4 -u -o root"
|
||||
},
|
||||
"dependencies": {
|
||||
"astro": "^5.12.3"
|
||||
"astro": "^5.16.6",
|
||||
"three": "^0.182.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@astrojs/mdx": "^4.3.1",
|
||||
"@astrojs/react": "^4.3.0",
|
||||
"@astrojs/sitemap": "^3.4.1"
|
||||
"@astrojs/mdx": "^4.3.13",
|
||||
"@astrojs/react": "^4.4.2",
|
||||
"@astrojs/sitemap": "^3.6.0",
|
||||
"@types/three": "^0.182.0"
|
||||
}
|
||||
}
|
||||
10
official/src/apps/beian.tsx
Normal file
10
official/src/apps/beian.tsx
Normal file
@@ -0,0 +1,10 @@
|
||||
export const Beian = () => {
|
||||
return <div
|
||||
className='mt-12 pt-8 border-t border-gray-800 text-center text-gray-400 fixed bottom-0 w-full bg-black'
|
||||
onClick={() => {
|
||||
window.open('https://beian.miit.gov.cn/', '_blank');
|
||||
}}>
|
||||
<p>浙ICP备2025158778号</p>
|
||||
<p>© 2025 杭州余杭逸文设计工作室. All rights reserved.</p>
|
||||
</div>
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Mail, Phone, MapPin, Book, Globe, Brain, Save } from 'lucide-react';
|
||||
import { Mail, Phone, MapPin, Book, Globe, Brain, Save, Database, Bot, Code2, Workflow, Sparkles } from 'lucide-react';
|
||||
import { ToastContainer } from 'react-toastify';
|
||||
import { Provider } from './Provider';
|
||||
import Logo from './assets/logo-1.png';
|
||||
@@ -16,7 +16,7 @@ export const Main = () => {
|
||||
<div className='min-h-screen bg-gray-50'>
|
||||
{/* Hero Section */}
|
||||
<div className=''>
|
||||
<nav className='px-4 mx-auto h-16 flex justify-between items-center bg-white border-b border-b-gray-200 w-full'>
|
||||
<nav className='px-4 mx-auto h-16 flex justify-between items-center bg-white border-b border-b-gray-200 w-full mr-20'>
|
||||
<div
|
||||
className='flex items-center space-x-4 cursor-pointer'
|
||||
onClick={() => {
|
||||
@@ -29,108 +29,104 @@ export const Main = () => {
|
||||
className='hover:text-gray-400 cursor-pointer'
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
const url = new URL('/root/center/', getOrigin());
|
||||
const url = new URL('/root/home/', getOrigin());
|
||||
window.open(url.toString(), '_blank');
|
||||
}}>
|
||||
管理中心
|
||||
</a>
|
||||
<a href='#features' className='hover:text-gray-400 cursor-pointer'>
|
||||
功能
|
||||
</a>
|
||||
<a href='#contact' className='hover:text-gray-400 cursor-pointer'>
|
||||
联系方式
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
<article className='container mx-auto px-6 py-10 bg-gray-50'>
|
||||
<div className='mx-auto bg-white p-8 py-10 rounded-lg shadow-lg'>
|
||||
<h2 className='text-3xl font-bold mb-8 text-center'>网页部署平台</h2>
|
||||
<p className='text-gray-700 mb-6'>
|
||||
Kevisual设计助手提供强大的网页部署平台,让您轻松管理自己的博客和自定义网页。无论是个人博客、AI生成的网页,还是专业项目,都能通过我们的平台进行高效管理。
|
||||
<article className='container mx-auto px-6 py-16 bg-gray-50'>
|
||||
{/* 主标题区域 */}
|
||||
<div className='text-center mb-16'>
|
||||
<h1 className='text-5xl font-bold text-gray-900 mb-6'>可视化助手</h1>
|
||||
<p className='text-xl text-gray-600 max-w-4xl mx-auto leading-relaxed'>
|
||||
人在网络上生活的方面的所有内容,都能更好地被管理和使用。学习、工作、娱乐、社交等各个方面的内容,都能被整合在自己的可视化的空间中。这空间具备自执行的能力,能主动帮助人完成各项任务,操作系统,浏览器,应用程序。
|
||||
</p>
|
||||
<div className='grid md:grid-cols-2 gap-8 mt-10'>
|
||||
<div>
|
||||
<h3 className='text-xl font-semibold mb-4'>功能亮点</h3>
|
||||
<ul className='list-disc pl-5 space-y-2 text-gray-600'>
|
||||
<li>类似图床的文件管理系统,高效整理各类资源</li>
|
||||
<li>一键创建、删除和管理多个站点</li>
|
||||
<li>支持自定义域名,打造专属网络形象</li>
|
||||
<li>权限控制系统,可设置为仅自己可访问或公开共享</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{/* 功能方向卡片 */}
|
||||
<div className='mb-12'>
|
||||
<h2 className='text-3xl font-bold text-gray-900 text-center mb-12'>核心功能方向</h2>
|
||||
<div className='grid md:grid-cols-2 lg:grid-cols-3 gap-8 max-w-7xl mx-auto'>
|
||||
{/* 知识库 */}
|
||||
<div className='bg-white rounded-xl shadow-lg p-8 hover:shadow-xl transition-shadow duration-300 border border-gray-100'>
|
||||
<div className='bg-linear-to-br from-blue-500 to-blue-600 w-14 h-14 rounded-lg flex items-center justify-center mb-6'>
|
||||
<Database className='w-7 h-7 text-white' />
|
||||
</div>
|
||||
<h3 className='text-2xl font-bold text-gray-900 mb-4'>知识库</h3>
|
||||
<p className='text-gray-600 leading-relaxed'>
|
||||
构建一个个人知识库,能存储和管理各种类型的信息,包括文本、图片、音频、视频等。知识库支持标签、分类、搜索等功能,方便用户快速找到所需信息。非文本,则需要转换为文本进行存储和管理。
|
||||
</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 className='text-xl font-semibold mb-4'>使用场景</h3>
|
||||
<ul className='list-disc pl-5 space-y-2 text-gray-600'>
|
||||
<li>个人博客与作品集展示</li>
|
||||
<li className='text-blue-600 hover:underline cursor-pointer' onClick={openEditor}>
|
||||
临时网页快速部署
|
||||
</li>
|
||||
<li>AI生成内容的发布与管理</li>
|
||||
<li>小型项目的在线展示</li>
|
||||
</ul>
|
||||
|
||||
{/* 代码编辑器 */}
|
||||
<div className='bg-white rounded-xl shadow-lg p-8 hover:shadow-xl transition-shadow duration-300 border border-gray-100'>
|
||||
<div className='bg-linear-to-br from-purple-500 to-purple-600 w-14 h-14 rounded-lg flex items-center justify-center mb-6'>
|
||||
<Code2 className='w-7 h-7 text-white' />
|
||||
</div>
|
||||
<h3 className='text-2xl font-bold text-gray-900 mb-4'>代码编辑器</h3>
|
||||
<p className='text-gray-600 leading-relaxed'>
|
||||
一切底层运行必开发,如果没有开发环境,那么就需要一个云端代码编辑器,能让用户在浏览器中编写代码,并且能运行和调试代码。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 可视化编程 */}
|
||||
<div className='bg-white rounded-xl shadow-lg p-8 hover:shadow-xl transition-shadow duration-300 border border-gray-100'>
|
||||
<div className='bg-linear-to-br from-green-500 to-green-600 w-14 h-14 rounded-lg flex items-center justify-center mb-6'>
|
||||
<Workflow className='w-7 h-7 text-white' />
|
||||
</div>
|
||||
<h3 className='text-2xl font-bold text-gray-900 mb-4'>可视化编程</h3>
|
||||
<p className='text-gray-600 leading-relaxed'>
|
||||
对话式编程,图形化编程,模块化编程,积木式编程等方式,让用户能更方便地创建程序。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 数据存储 */}
|
||||
<div className='bg-white rounded-xl shadow-lg p-8 hover:shadow-xl transition-shadow duration-300 border border-gray-100'>
|
||||
<div className='bg-linear-to-br from-orange-500 to-orange-600 w-14 h-14 rounded-lg flex items-center justify-center mb-6'>
|
||||
<Save className='w-7 h-7 text-white' />
|
||||
</div>
|
||||
<h3 className='text-2xl font-bold text-gray-900 mb-4'>数据存储</h3>
|
||||
<p className='text-gray-600 leading-relaxed'>
|
||||
云端如何对个人用户来说,如何存储数据,想实现的功能,网页如何更简便获取数据。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* 自动化任务 */}
|
||||
<div className='bg-white rounded-xl shadow-lg p-8 hover:shadow-xl transition-shadow duration-300 border border-gray-100'>
|
||||
<div className='bg-linear-to-br from-pink-500 to-pink-600 w-14 h-14 rounded-lg flex items-center justify-center mb-6'>
|
||||
<Sparkles className='w-7 h-7 text-white' />
|
||||
</div>
|
||||
<h3 className='text-2xl font-bold text-gray-900 mb-4'>自动化任务</h3>
|
||||
<p className='text-gray-600 leading-relaxed'>
|
||||
描述一个简单的需求,自动根据需求生成功能。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* AI 交互 */}
|
||||
<div className='bg-white rounded-xl shadow-lg p-8 hover:shadow-xl transition-shadow duration-300 border border-gray-100'>
|
||||
<div className='bg-linear-to-br from-cyan-500 to-cyan-600 w-14 h-14 rounded-lg flex items-center justify-center mb-6'>
|
||||
<Bot className='w-7 h-7 text-white' />
|
||||
</div>
|
||||
<h3 className='text-2xl font-bold text-gray-900 mb-4'>AI 交互</h3>
|
||||
<p className='text-gray-600 leading-relaxed'>
|
||||
通过自然语言与 AI 进行交互,完成各种任务,如信息查询、内容生成、数据分析等。AI 能理解用户的意图,并提供相应的帮助和建议。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div className='mt-8 text-center'>
|
||||
<a href='./docs/features' className='inline-flex items-center text-blue-600 hover:underline font-medium cursor-not-allowed'>
|
||||
了解更多功能
|
||||
<svg className='w-4 h-4 ml-1' fill='none' stroke='currentColor' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'>
|
||||
<path strokeLinecap='round' strokeLinejoin='round' strokeWidth='2' d='M9 5l7 7-7 7'></path>
|
||||
</svg>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* 愿景声明 */}
|
||||
<div className='mt-20 bg-linear-to-r from-indigo-600 to-purple-600 rounded-2xl p-12 text-center text-white shadow-2xl'>
|
||||
<h2 className='text-3xl font-bold mb-4'>打造你的数字生活空间</h2>
|
||||
<p className='text-lg opacity-90 max-w-3xl mx-auto'>
|
||||
让技术更好地服务于人,让每个人都能轻松管理和掌控自己的数字世界
|
||||
</p>
|
||||
</div>
|
||||
</article>
|
||||
{/* Features Section */}
|
||||
<section id='features' className='container mx-auto px-6 py-10 bg-gray-50'>
|
||||
<div className='mx-auto bg-white p-8 py-10 rounded-lg shadow-lg'>
|
||||
<h2 className='text-3xl font-bold text-center mb-16'>核心功能</h2>
|
||||
|
||||
<div className='grid md:grid-cols-3 gap-12'>
|
||||
<div className='p-6 rounded-lg shadow-lg bg-white'>
|
||||
<Globe className='w-12 h-12 text-blue-600 mb-4' />
|
||||
<h3 className='text-xl font-semibold mb-4'>网页部署平台</h3>
|
||||
<p className='text-gray-600'>轻松管理您的博客和自定义网页,支持文件管理、站点创建和域名自定义</p>
|
||||
</div>
|
||||
|
||||
<div className='p-6 rounded-lg shadow-lg bg-white'>
|
||||
<Brain className='w-12 h-12 text-blue-600 mb-4' />
|
||||
<h3 className='text-xl font-semibold mb-4'>应用共享</h3>
|
||||
<p className='text-gray-600'>根据用户需求,某一些应用只能自己访问或者共享</p>
|
||||
</div>
|
||||
|
||||
<div className='p-6 rounded-lg shadow-lg bg-white'>
|
||||
<Book className='w-12 h-12 text-blue-600 mb-4' />
|
||||
<h3 className='text-xl font-semibold mb-4'>临时网页</h3>
|
||||
<p className='text-gray-600'>当个网页助手,帮助您快速生成临时网页</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Contact Section */}
|
||||
<section id='contact' className='container mx-auto px-6 py-10 bg-gray-50'>
|
||||
<div className='mx-auto bg-white p-8 py-10 rounded-lg shadow-lg'>
|
||||
<h2 className='text-3xl font-bold text-center mb-16'>联系我们</h2>
|
||||
<div className='max-w-2xl mx-auto w-[300px]'>
|
||||
<div className='space-y-6'>
|
||||
<div className='flex items-center space-x-4'>
|
||||
<Mail className='w-6 h-6 text-blue-600' />
|
||||
<span>kevisual@kevisual.cn</span>
|
||||
</div>
|
||||
<div className='flex items-center space-x-4'>
|
||||
<Phone className='w-6 h-6 text-blue-600' />
|
||||
<span>18324451015</span>
|
||||
</div>
|
||||
<div className='flex items-center space-x-4'>
|
||||
<MapPin className='w-6 h-6 text-blue-600' />
|
||||
<span>浙江省杭州市拱墅区杭州北部软件园</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{/* Footer */}
|
||||
<footer className='bg-gray-900 text-white py-12'>
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import ConfigProvider from 'antd/lib/config-provider';
|
||||
import '@ant-design/v5-patch-for-react-19';
|
||||
|
||||
export const Provider = ({ children }: { children: React.ReactNode }) => {
|
||||
return (
|
||||
|
||||
676
official/src/apps/skill-beautiful/app.ts
Normal file
676
official/src/apps/skill-beautiful/app.ts
Normal file
@@ -0,0 +1,676 @@
|
||||
import * as THREE from 'three';
|
||||
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';
|
||||
import { CSS3DRenderer, CSS3DObject } from 'three/examples/jsm/renderers/CSS3DRenderer.js';
|
||||
|
||||
// ============ 控制模块配置 ============
|
||||
interface ControlOptions {
|
||||
scene: THREE.Scene;
|
||||
camera: THREE.Camera;
|
||||
renderer: THREE.WebGLRenderer;
|
||||
}
|
||||
|
||||
interface ControlState {
|
||||
autoRotate: boolean;
|
||||
showHelp: boolean;
|
||||
showInfo: boolean;
|
||||
}
|
||||
|
||||
const createControlModule = (opts: ControlOptions) => {
|
||||
const { scene, camera, renderer } = opts;
|
||||
|
||||
// 轨道控制器
|
||||
const controls = new OrbitControls(camera as THREE.PerspectiveCamera, renderer.domElement);
|
||||
controls.enableDamping = true; // 启用阻尼效果
|
||||
controls.dampingFactor = 0.05;
|
||||
controls.rotateSpeed = 0.5;
|
||||
controls.zoomSpeed = 1.0;
|
||||
controls.panSpeed = 0.8;
|
||||
|
||||
// 限制范围
|
||||
controls.minDistance = 5;
|
||||
controls.maxDistance = 30;
|
||||
controls.maxPolarAngle = Math.PI / 2 - 0.1; // 防止看到地面以下
|
||||
controls.minPolarAngle = Math.PI / 6;
|
||||
|
||||
// 目标点
|
||||
controls.target.set(0, 2, 0);
|
||||
|
||||
// 控制状态
|
||||
const state: ControlState = {
|
||||
autoRotate: false,
|
||||
showHelp: false,
|
||||
showInfo: false
|
||||
};
|
||||
|
||||
// 键盘控制
|
||||
const handleKeyPress = (event: KeyboardEvent) => {
|
||||
switch (event.key.toLowerCase()) {
|
||||
case 'r':
|
||||
// 重置视角
|
||||
(camera as THREE.PerspectiveCamera).position.set(0, 8, 12);
|
||||
controls.target.set(0, 2, 0);
|
||||
break;
|
||||
case 'a':
|
||||
// 切换自动旋转
|
||||
state.autoRotate = !state.autoRotate;
|
||||
controls.autoRotate = state.autoRotate;
|
||||
console.log(`自动旋转: ${state.autoRotate ? '开启' : '关闭'}`);
|
||||
break;
|
||||
case 'h':
|
||||
// 切换帮助信息
|
||||
state.showHelp = !state.showHelp;
|
||||
break;
|
||||
case 'i':
|
||||
// 切换详细信息
|
||||
state.showInfo = !state.showInfo;
|
||||
break;
|
||||
case 'arrowup':
|
||||
// 向上平移视角
|
||||
controls.target.y += 0.5;
|
||||
break;
|
||||
case 'arrowdown':
|
||||
// 向下平移视角
|
||||
controls.target.y -= 0.5;
|
||||
break;
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener('keydown', handleKeyPress);
|
||||
|
||||
// 创建帮助面板
|
||||
const createHelpPanel = () => {
|
||||
const panel = document.createElement('div');
|
||||
panel.id = 'help-panel';
|
||||
panel.style.cssText = `
|
||||
position: fixed;
|
||||
top: 20px;
|
||||
right: 20px;
|
||||
background: rgba(10, 10, 26, 0.9);
|
||||
border: 1px solid rgba(0, 255, 255, 0.3);
|
||||
border-radius: 10px;
|
||||
padding: 20px;
|
||||
color: #00ffff;
|
||||
font-family: 'Microsoft YaHei', sans-serif;
|
||||
font-size: 14px;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 0 20px rgba(0, 255, 255, 0.2);
|
||||
display: none;
|
||||
`;
|
||||
|
||||
panel.innerHTML = `
|
||||
<div style="margin-bottom: 15px; font-size: 16px; font-weight: bold; color: #ff00ff;">
|
||||
🎮 控制说明
|
||||
</div>
|
||||
<div style="line-height: 1.8;">
|
||||
<div>🖱️ <strong>鼠标左键</strong>: 旋转视角</div>
|
||||
<div>🖱️ <strong>鼠标右键</strong>: 平移视角</div>
|
||||
<div>🖱️ <strong>滚轮</strong>: 缩放</div>
|
||||
<div>⌨️ <strong>R键</strong>: 重置视角</div>
|
||||
<div>⌨️ <strong>A键</strong>: 自动旋转开关</div>
|
||||
<div>⌨️ <strong>H键</strong>: 显示/隐藏帮助</div>
|
||||
<div>⌨️ <strong>↑/↓</strong>: 上下移动视角</div>
|
||||
<div>🔗 <strong>右侧按钮</strong>: 显示/隐藏信息面板</div>
|
||||
</div>
|
||||
`;
|
||||
|
||||
document.body.appendChild(panel);
|
||||
return panel;
|
||||
};
|
||||
|
||||
const helpPanel = createHelpPanel();
|
||||
|
||||
// 更新帮助面板显示
|
||||
const updateHelpPanel = () => {
|
||||
helpPanel.style.display = state.showHelp ? 'block' : 'none';
|
||||
};
|
||||
|
||||
// 监听H键切换帮助面板
|
||||
const originalHandleKeyPress = handleKeyPress;
|
||||
window.removeEventListener('keydown', originalHandleKeyPress);
|
||||
window.addEventListener('keydown', handleKeyPress);
|
||||
|
||||
// 创建信息面板
|
||||
const createInfoPanel = () => {
|
||||
const panel = document.createElement('div');
|
||||
panel.id = 'info-panel';
|
||||
panel.style.cssText = `
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
left: 20px;
|
||||
background: rgba(10, 10, 26, 0.9);
|
||||
border: 1px solid rgba(255, 0, 255, 0.3);
|
||||
border-radius: 10px;
|
||||
padding: 15px;
|
||||
color: #ff00ff;
|
||||
font-family: 'Microsoft YaHei', sans-serif;
|
||||
font-size: 12px;
|
||||
z-index: 1000;
|
||||
box-shadow: 0 0 20px rgba(255, 0, 255, 0.2);
|
||||
display: none;
|
||||
`;
|
||||
|
||||
const updateInfo = () => {
|
||||
const camPos = (camera as THREE.PerspectiveCamera).position;
|
||||
panel.innerHTML = `
|
||||
<div style="font-weight: bold; margin-bottom: 10px; color: #00ffff;">
|
||||
📊 相机信息
|
||||
</div>
|
||||
<div style="line-height: 1.6;">
|
||||
<div>位置 X: ${camPos.x.toFixed(2)}</div>
|
||||
<div>位置 Y: ${camPos.y.toFixed(2)}</div>
|
||||
<div>位置 Z: ${camPos.z.toFixed(2)}</div>
|
||||
<div>目标: (${controls.target.x.toFixed(2)}, ${controls.target.y.toFixed(2)}, ${controls.target.z.toFixed(2)})</div>
|
||||
<div>自动旋转: ${state.autoRotate ? '✅' : '❌'}</div>
|
||||
</div>
|
||||
`;
|
||||
};
|
||||
|
||||
document.body.appendChild(panel);
|
||||
|
||||
return { panel, updateInfo };
|
||||
};
|
||||
|
||||
const { panel: infoPanel, updateInfo: updateInfoPanel } = createInfoPanel();
|
||||
|
||||
// 返回控制接口
|
||||
return {
|
||||
controls,
|
||||
state,
|
||||
|
||||
// 在动画循环中调用
|
||||
update: () => {
|
||||
controls.update();
|
||||
|
||||
if (state.showInfo) {
|
||||
updateInfoPanel();
|
||||
}
|
||||
|
||||
updateHelpPanel();
|
||||
},
|
||||
|
||||
// 清理
|
||||
dispose: () => {
|
||||
window.removeEventListener('keydown', handleKeyPress);
|
||||
controls.dispose();
|
||||
helpPanel.remove();
|
||||
infoPanel.remove();
|
||||
}
|
||||
};
|
||||
};
|
||||
export const render = () => {
|
||||
// 场景设置
|
||||
const container = document.getElementById('container');
|
||||
if (!container) return;
|
||||
|
||||
const scene = new THREE.Scene();
|
||||
scene.background = new THREE.Color(0x0a0a1a);
|
||||
scene.fog = new THREE.Fog(0x0a0a1a, 10, 50);
|
||||
|
||||
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
|
||||
camera.position.set(0, 8, 12);
|
||||
camera.lookAt(0, 2, 0);
|
||||
|
||||
const renderer = new THREE.WebGLRenderer({ antialias: true });
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
renderer.setPixelRatio(window.devicePixelRatio);
|
||||
renderer.shadowMap.enabled = true;
|
||||
renderer.shadowMap.type = THREE.PCFSoftShadowMap;
|
||||
container.innerHTML = '';
|
||||
container.appendChild(renderer.domElement);
|
||||
|
||||
// 创建 CSS3D 渲染器(用于 HTML/CSS 元素)
|
||||
const cssRenderer = new CSS3DRenderer();
|
||||
cssRenderer.setSize(window.innerWidth, window.innerHeight);
|
||||
cssRenderer.domElement.style.position = 'absolute';
|
||||
cssRenderer.domElement.style.top = '0';
|
||||
cssRenderer.domElement.style.left = '0';
|
||||
cssRenderer.domElement.style.pointerEvents = 'none'; // 允许点击穿透到 WebGL
|
||||
container.appendChild(cssRenderer.domElement);
|
||||
|
||||
// ============ 模块1:流光旋转地面 ============
|
||||
const groundGeometry = new THREE.PlaneGeometry(60, 60, 100, 100);
|
||||
|
||||
// 创建流光效果的着色器材质
|
||||
const groundMaterial = new THREE.ShaderMaterial({
|
||||
uniforms: {
|
||||
time: { value: 0 },
|
||||
color1: { value: new THREE.Color(0x00ffff) },
|
||||
color2: { value: new THREE.Color(0xff00ff) },
|
||||
color3: { value: new THREE.Color(0x0066ff) }
|
||||
},
|
||||
vertexShader: `
|
||||
varying vec2 vUv;
|
||||
varying float vElevation;
|
||||
uniform float time;
|
||||
|
||||
void main() {
|
||||
vUv = uv;
|
||||
|
||||
vec3 pos = position;
|
||||
float elevation = sin(pos.x * 0.3 + time) * 0.3 +
|
||||
sin(pos.y * 0.2 + time * 0.8) * 0.2 +
|
||||
sin((pos.x + pos.y) * 0.1 + time * 1.2) * 0.15;
|
||||
vElevation = elevation;
|
||||
pos.z += elevation;
|
||||
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(pos, 1.0);
|
||||
}
|
||||
`,
|
||||
fragmentShader: `
|
||||
varying vec2 vUv;
|
||||
varying float vElevation;
|
||||
uniform float time;
|
||||
uniform vec3 color1;
|
||||
uniform vec3 color2;
|
||||
uniform vec3 color3;
|
||||
|
||||
void main() {
|
||||
vec2 center = vec2(0.5, 0.5);
|
||||
float dist = distance(vUv, center);
|
||||
|
||||
// 旋转流光效果
|
||||
float angle = atan(vUv.y - 0.5, vUv.x - 0.5);
|
||||
float rotatingAngle = angle + time * 0.5;
|
||||
|
||||
// 多层流光
|
||||
float light1 = sin(rotatingAngle * 3.0 + dist * 20.0 - time * 2.0) * 0.5 + 0.5;
|
||||
float light2 = sin(rotatingAngle * 5.0 - dist * 15.0 + time * 1.5) * 0.5 + 0.5;
|
||||
float light3 = sin(dist * 30.0 - time * 3.0) * 0.5 + 0.5;
|
||||
|
||||
// 流光线条
|
||||
float lines = smoothstep(0.4, 0.6, light1) * smoothstep(0.6, 0.4, light1);
|
||||
lines += smoothstep(0.45, 0.55, light2) * smoothstep(0.55, 0.45, light2) * 0.5;
|
||||
|
||||
// 距离衰减
|
||||
float fade = 1.0 - smoothstep(0.0, 0.5, dist);
|
||||
|
||||
// 颜色混合
|
||||
vec3 color = mix(color1, color2, light3);
|
||||
color = mix(color, color3, light2 * 0.5);
|
||||
|
||||
// 添加发光
|
||||
float glow = lines * 2.0 * fade;
|
||||
color += glow * color1;
|
||||
|
||||
// 基础网格
|
||||
float gridX = step(0.98, fract(vUv.x * 40.0));
|
||||
float gridY = step(0.98, fract(vUv.y * 40.0));
|
||||
float grid = max(gridX, gridY) * 0.1 * fade;
|
||||
|
||||
color += grid * vec3(0.2, 0.4, 0.6);
|
||||
|
||||
// 边缘渐隐
|
||||
float edgeFade = smoothstep(0.5, 0.3, dist);
|
||||
|
||||
gl_FragColor = vec4(color * edgeFade, edgeFade * 0.9);
|
||||
}
|
||||
`,
|
||||
transparent: true,
|
||||
side: THREE.DoubleSide
|
||||
});
|
||||
|
||||
const ground = new THREE.Mesh(groundGeometry, groundMaterial);
|
||||
ground.rotation.x = -Math.PI / 2;
|
||||
ground.receiveShadow = true;
|
||||
scene.add(ground);
|
||||
|
||||
// ============ 添加信息面板模块(使用 CSS3DObject,居中显示)============
|
||||
const createIframePanel3D = (camera: THREE.PerspectiveCamera, controls: OrbitControls) => {
|
||||
// ============ 相机移动配置 ============
|
||||
// 可调整的目标相机位置参数
|
||||
const cameraTargetConfig = {
|
||||
position: {
|
||||
x: 0, // 相机目标位置 X
|
||||
y: 3.5, // 相机目标位置 Y(与面板中心对齐)
|
||||
z: 8 // 相机目标位置 Z(距离面板的距离,可调整)
|
||||
},
|
||||
target: {
|
||||
x: 0, // 控制器目标点 X(面板中心)
|
||||
y: 3.5, // 控制器目标点 Y(面板中心高度)
|
||||
z: 0 // 控制器目标点 Z(面板中心)
|
||||
},
|
||||
duration: 1500 // 动画持续时间(毫秒),可调整
|
||||
};
|
||||
|
||||
// 平滑移动相机到目标位置的函数
|
||||
const moveCameraToPanel = () => {
|
||||
const startPosition = {
|
||||
x: camera.position.x,
|
||||
y: camera.position.y,
|
||||
z: camera.position.z
|
||||
};
|
||||
const startTarget = {
|
||||
x: controls.target.x,
|
||||
y: controls.target.y,
|
||||
z: controls.target.z
|
||||
};
|
||||
|
||||
const startTime = Date.now();
|
||||
|
||||
const animateCamera = () => {
|
||||
const elapsed = Date.now() - startTime;
|
||||
const progress = Math.min(elapsed / cameraTargetConfig.duration, 1);
|
||||
|
||||
// 使用缓动函数(easeInOutCubic)
|
||||
const easeProgress = progress < 0.5
|
||||
? 4 * progress * progress * progress
|
||||
: 1 - Math.pow(-2 * progress + 2, 3) / 2;
|
||||
|
||||
// 插值更新相机位置
|
||||
camera.position.x = startPosition.x + (cameraTargetConfig.position.x - startPosition.x) * easeProgress;
|
||||
camera.position.y = startPosition.y + (cameraTargetConfig.position.y - startPosition.y) * easeProgress;
|
||||
camera.position.z = startPosition.z + (cameraTargetConfig.position.z - startPosition.z) * easeProgress;
|
||||
|
||||
// 插值更新控制器目标点
|
||||
controls.target.x = startTarget.x + (cameraTargetConfig.target.x - startTarget.x) * easeProgress;
|
||||
controls.target.y = startTarget.y + (cameraTargetConfig.target.y - startTarget.y) * easeProgress;
|
||||
controls.target.z = startTarget.z + (cameraTargetConfig.target.z - startTarget.z) * easeProgress;
|
||||
|
||||
controls.update();
|
||||
|
||||
if (progress < 1) {
|
||||
requestAnimationFrame(animateCamera);
|
||||
}
|
||||
};
|
||||
|
||||
animateCamera();
|
||||
};
|
||||
|
||||
// 创建 HTML 元素
|
||||
const div = document.createElement('div');
|
||||
div.style.cssText = `
|
||||
width: 1400px;
|
||||
height: 700px;
|
||||
background: rgba(10, 10, 26, 0.95);
|
||||
border: 2px solid rgba(0, 255, 255, 0.5);
|
||||
border-radius: 15px;
|
||||
box-shadow: 0 0 30px rgba(0, 255, 255, 0.3), inset 0 0 20px rgba(0, 255, 255, 0.1);
|
||||
overflow: hidden;
|
||||
`;
|
||||
|
||||
// 创建标题栏
|
||||
const header = document.createElement('div');
|
||||
header.style.cssText = `
|
||||
background: linear-gradient(90deg, rgba(0, 255, 255, 0.2), rgba(255, 0, 255, 0.2));
|
||||
padding: 12px 15px;
|
||||
border-bottom: 1px solid rgba(0, 255, 255, 0.3);
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const title = document.createElement('div');
|
||||
title.textContent = '我的信息面板';
|
||||
title.style.cssText = `
|
||||
color: #00ffff;
|
||||
font-family: 'Microsoft YaHei', sans-serif;
|
||||
font-size: 16px;
|
||||
font-weight: bold;
|
||||
text-shadow: 0 0 10px rgba(0, 255, 255, 0.5);
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
transition: all 0.3s;
|
||||
`;
|
||||
|
||||
// 鼠标悬停效果
|
||||
title.onmouseover = () => {
|
||||
title.style.color = '#ff00ff';
|
||||
title.style.textShadow = '0 0 15px rgba(255, 0, 255, 0.8)';
|
||||
};
|
||||
title.onmouseout = () => {
|
||||
title.style.color = '#00ffff';
|
||||
title.style.textShadow = '0 0 10px rgba(0, 255, 255, 0.5)';
|
||||
};
|
||||
|
||||
// 点击标题时移动相机到面板前方
|
||||
title.onclick = () => {
|
||||
moveCameraToPanel();
|
||||
};
|
||||
|
||||
const closeButton = document.createElement('button');
|
||||
closeButton.textContent = '✕';
|
||||
closeButton.style.cssText = `
|
||||
background: rgba(255, 0, 100, 0.3);
|
||||
border: 1px solid rgba(255, 0, 100, 0.5);
|
||||
color: #fff;
|
||||
width: 28px;
|
||||
height: 28px;
|
||||
border-radius: 5px;
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
transition: all 0.2s;
|
||||
`;
|
||||
closeButton.onmouseover = () => {
|
||||
closeButton.style.background = 'rgba(255, 0, 100, 0.6)';
|
||||
};
|
||||
closeButton.onmouseout = () => {
|
||||
closeButton.style.background = 'rgba(255, 0, 100, 0.3)';
|
||||
};
|
||||
closeButton.onclick = () => {
|
||||
// 隐藏面板
|
||||
css3dObject.visible = false;
|
||||
};
|
||||
|
||||
header.appendChild(title);
|
||||
header.appendChild(closeButton);
|
||||
|
||||
// 创建 iframe 容器
|
||||
const iframeContainer = document.createElement('div');
|
||||
iframeContainer.style.cssText = `
|
||||
width: 100%;
|
||||
height: calc(100% - 50px);
|
||||
position: relative;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
`;
|
||||
|
||||
// 创建 iframe
|
||||
const iframe = document.createElement('iframe');
|
||||
iframe.src = '/info/';
|
||||
iframe.style.cssText = `
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
border: none;
|
||||
background: transparent;
|
||||
`;
|
||||
|
||||
iframeContainer.appendChild(iframe);
|
||||
|
||||
// 添加发光装饰角
|
||||
const corners = ['top-left', 'top-right', 'bottom-left', 'bottom-right'];
|
||||
corners.forEach(corner => {
|
||||
const cornerEl = document.createElement('div');
|
||||
cornerEl.style.cssText = `
|
||||
position: absolute;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border: 2px solid #00ffff;
|
||||
${corner.includes('top') ? 'top: -2px;' : 'bottom: -2px;'}
|
||||
${corner.includes('left') ? 'left: -2px;' : 'right: -2px;'}
|
||||
${corner.includes('top') ? corner.includes('left') ? 'border-right: none;' : 'border-left: none;' : corner.includes('left') ? 'border-right: none;' : 'border-left: none;'}
|
||||
${corner.includes('top') ? corner.includes('left') ? 'border-bottom: none;' : 'border-bottom: none;' : corner.includes('left') ? 'border-top: none;' : 'border-top: none;'}
|
||||
box-shadow: 0 0 10px rgba(0, 255, 255, 0.5);
|
||||
`;
|
||||
div.appendChild(cornerEl);
|
||||
});
|
||||
|
||||
div.appendChild(header);
|
||||
div.appendChild(iframeContainer);
|
||||
|
||||
// 创建 CSS3DObject
|
||||
const css3dObject = new CSS3DObject(div);
|
||||
css3dObject.position.set(0, 3.5, 0); // 居中显示
|
||||
css3dObject.rotation.y = 0; // 面向正前方
|
||||
css3dObject.scale.set(0.01, 0.01, 0.01); // 缩放以适应场景
|
||||
|
||||
scene.add(css3dObject);
|
||||
|
||||
// 添加打开按钮(固定在屏幕上)
|
||||
const openButton = document.createElement('button');
|
||||
openButton.id = 'open-iframe-btn';
|
||||
openButton.textContent = '🔗 打开信息面板';
|
||||
openButton.style.cssText = `
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
right: 20px;
|
||||
transform: translateY(-50%);
|
||||
background: linear-gradient(135deg, rgba(0, 255, 255, 0.2), rgba(255, 0, 255, 0.2));
|
||||
border: 2px solid rgba(0, 255, 255, 0.5);
|
||||
color: #00ffff;
|
||||
padding: 12px 24px;
|
||||
border-radius: 25px;
|
||||
cursor: pointer;
|
||||
font-family: 'Microsoft YaHei', sans-serif;
|
||||
font-size: 14px;
|
||||
font-weight: bold;
|
||||
text-shadow: 0 0 10px rgba(0, 255, 255, 0.5);
|
||||
box-shadow: 0 0 20px rgba(0, 255, 255, 0.3);
|
||||
transition: all 0.3s;
|
||||
z-index: 50;
|
||||
pointer-events: auto;
|
||||
`;
|
||||
openButton.onmouseover = () => {
|
||||
openButton.style.background = 'linear-gradient(135deg, rgba(0, 255, 255, 0.4), rgba(255, 0, 255, 0.4))';
|
||||
openButton.style.transform = 'translateY(-50%) scale(1.05)';
|
||||
};
|
||||
openButton.onmouseout = () => {
|
||||
openButton.style.background = 'linear-gradient(135deg, rgba(0, 255, 255, 0.2), rgba(255, 0, 255, 0.2))';
|
||||
openButton.style.transform = 'translateY(-50%) scale(1)';
|
||||
};
|
||||
openButton.onclick = () => {
|
||||
css3dObject.visible = !css3dObject.visible;
|
||||
};
|
||||
|
||||
document.body.appendChild(openButton);
|
||||
|
||||
return {
|
||||
css3dObject,
|
||||
openButton,
|
||||
dispose: () => {
|
||||
scene.remove(css3dObject);
|
||||
openButton.remove();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// ============ 控制模块初始化 ============
|
||||
const controlModule = createControlModule({
|
||||
scene,
|
||||
camera,
|
||||
renderer
|
||||
});
|
||||
|
||||
// 创建信息面板(传入 camera 和 controls)
|
||||
const iframePanel3D = createIframePanel3D(camera, controlModule.controls);
|
||||
|
||||
// ============ 灯光系统 ============
|
||||
const ambientLight = new THREE.AmbientLight(0x222244, 0.5);
|
||||
scene.add(ambientLight);
|
||||
|
||||
// 主光源
|
||||
const mainLight = new THREE.PointLight(0x00ffff, 2, 50);
|
||||
mainLight.position.set(5, 10, 5);
|
||||
mainLight.castShadow = true;
|
||||
scene.add(mainLight);
|
||||
|
||||
// 辅助光源
|
||||
const auxLight = new THREE.PointLight(0xff00ff, 1.5, 50);
|
||||
auxLight.position.set(-5, 8, -5);
|
||||
scene.add(auxLight);
|
||||
|
||||
// 聚光灯照亮广告牌
|
||||
const spotLight = new THREE.SpotLight(0xffffff, 3);
|
||||
spotLight.position.set(0, 15, 0);
|
||||
spotLight.angle = Math.PI / 6;
|
||||
spotLight.penumbra = 0.5;
|
||||
spotLight.castShadow = true;
|
||||
scene.add(spotLight);
|
||||
|
||||
// ============ 粒子系统 ============
|
||||
const particleCount = 500;
|
||||
const particleGeometry = new THREE.BufferGeometry();
|
||||
const positions = new Float32Array(particleCount * 3);
|
||||
const colors = new Float32Array(particleCount * 3);
|
||||
|
||||
for (let i = 0; i < particleCount; i++) {
|
||||
positions[i * 3] = (Math.random() - 0.5) * 50;
|
||||
positions[i * 3 + 1] = Math.random() * 10;
|
||||
positions[i * 3 + 2] = (Math.random() - 0.5) * 50;
|
||||
|
||||
const color = new THREE.Color();
|
||||
color.setHSL(Math.random() * 0.2 + 0.5, 1, 0.5);
|
||||
colors[i * 3] = color.r;
|
||||
colors[i * 3 + 1] = color.g;
|
||||
colors[i * 3 + 2] = color.b;
|
||||
}
|
||||
|
||||
particleGeometry.setAttribute('position', new THREE.BufferAttribute(positions, 3));
|
||||
particleGeometry.setAttribute('color', new THREE.BufferAttribute(colors, 3));
|
||||
|
||||
const particleMaterial = new THREE.PointsMaterial({
|
||||
size: 0.1,
|
||||
vertexColors: true,
|
||||
transparent: true,
|
||||
opacity: 0.8,
|
||||
blending: THREE.AdditiveBlending
|
||||
});
|
||||
|
||||
const particles = new THREE.Points(particleGeometry, particleMaterial);
|
||||
scene.add(particles);
|
||||
|
||||
// ============ 动画循环 ============
|
||||
let time = 0;
|
||||
|
||||
const animate = () => {
|
||||
requestAnimationFrame(animate);
|
||||
time += 0.016;
|
||||
|
||||
// 更新地面着色器时间
|
||||
groundMaterial.uniforms.time.value = time;
|
||||
|
||||
// 粒子动画
|
||||
const particlePositions = particleGeometry.attributes.position.array as Float32Array;
|
||||
for (let i = 0; i < particleCount; i++) {
|
||||
particlePositions[i * 3 + 1] += 0.02;
|
||||
if (particlePositions[i * 3 + 1] > 10) {
|
||||
particlePositions[i * 3 + 1] = 0;
|
||||
}
|
||||
}
|
||||
particleGeometry.attributes.position.needsUpdate = true;
|
||||
|
||||
// 灯光旋转
|
||||
mainLight.position.x = Math.sin(time * 0.5) * 8;
|
||||
mainLight.position.z = Math.cos(time * 0.5) * 8;
|
||||
|
||||
auxLight.position.x = Math.sin(time * 0.3 + Math.PI) * 8;
|
||||
auxLight.position.z = Math.cos(time * 0.3 + Math.PI) * 8;
|
||||
|
||||
// 更新控制模块
|
||||
controlModule.update();
|
||||
|
||||
// 渲染 WebGL 和 CSS3D
|
||||
renderer.render(scene, camera);
|
||||
cssRenderer.render(scene, camera);
|
||||
};
|
||||
|
||||
animate();
|
||||
|
||||
// ============ 窗口自适应 ============
|
||||
const handleResize = () => {
|
||||
camera.aspect = window.innerWidth / window.innerHeight;
|
||||
camera.updateProjectionMatrix();
|
||||
renderer.setSize(window.innerWidth, window.innerHeight);
|
||||
cssRenderer.setSize(window.innerWidth, window.innerHeight);
|
||||
};
|
||||
|
||||
window.addEventListener('resize', handleResize);
|
||||
|
||||
// 返回清理函数
|
||||
return () => {
|
||||
window.removeEventListener('resize', handleResize);
|
||||
controlModule.dispose();
|
||||
iframePanel3D.dispose();
|
||||
renderer.dispose();
|
||||
groundMaterial.dispose();
|
||||
particleMaterial.dispose();
|
||||
};
|
||||
};
|
||||
37
official/src/apps/skill-beautiful/index.tsx
Normal file
37
official/src/apps/skill-beautiful/index.tsx
Normal file
@@ -0,0 +1,37 @@
|
||||
import { ToastContainer } from "react-toastify";
|
||||
import { render } from "./app.ts";
|
||||
import { useEffect } from "react";
|
||||
|
||||
export const AppProvider = () => {
|
||||
return (
|
||||
<>
|
||||
<ToastContainer autoClose={2000}></ToastContainer>
|
||||
<App />
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const App = () => {
|
||||
useEffect(() => {
|
||||
const cleanup = render();
|
||||
return () => {
|
||||
cleanup?.();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div
|
||||
id='container'
|
||||
style={{
|
||||
width: '100vw',
|
||||
height: '100vh',
|
||||
overflow: 'hidden',
|
||||
margin: 0,
|
||||
padding: 0,
|
||||
position: 'fixed',
|
||||
top: 0,
|
||||
left: 0
|
||||
}}
|
||||
/>
|
||||
);
|
||||
};
|
||||
@@ -1,6 +1,7 @@
|
||||
---
|
||||
import '../apps/index/index.css';
|
||||
import { App } from '../apps/index/App.tsx';
|
||||
// import { App as AppProvider } from '../apps/index/App.tsx';
|
||||
import { AppProvider } from '../apps/skill-beautiful/index.tsx';
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
@@ -11,11 +12,11 @@ import { App } from '../apps/index/App.tsx';
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
|
||||
<meta name='description' content='Kevisual 是一个专注于可视化设计, AI使用助手的工作室' />
|
||||
<meta name='generator' content={Astro.generator} />
|
||||
<meta name="baidu-site-verification" content="codeva-qAEXUzv0tn" />
|
||||
<meta name='baidu-site-verification' content='codeva-qAEXUzv0tn' />
|
||||
<title>逸文设计工作室</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<App client:only />
|
||||
<AppProvider client:only />
|
||||
</body>
|
||||
</html>
|
||||
|
||||
21
official/src/pages/info.astro
Normal file
21
official/src/pages/info.astro
Normal file
@@ -0,0 +1,21 @@
|
||||
---
|
||||
import '../apps/index/index.css';
|
||||
import { App as AppProvider } from '../apps/index/App.tsx';
|
||||
---
|
||||
|
||||
<!doctype html>
|
||||
<html lang='zh-CN'>
|
||||
<head>
|
||||
<meta charset='UTF-8' />
|
||||
<link rel='icon' type='image/svg+xml' href='https://kevisual.cn/root/center/panda.jpg' />
|
||||
<meta name='viewport' content='width=device-width, initial-scale=1.0' />
|
||||
<meta name='description' content='Kevisual 是一个专注于可视化设计, AI使用助手的工作室' />
|
||||
<meta name='generator' content={Astro.generator} />
|
||||
<meta name='baidu-site-verification' content='codeva-qAEXUzv0tn' />
|
||||
<title>逸文设计工作室</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<AppProvider client:only />
|
||||
</body>
|
||||
</html>
|
||||
26
package.json
26
package.json
@@ -16,24 +16,24 @@
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@ant-design/v5-patch-for-react-19": "^1.0.3",
|
||||
"@kevisual/query": "^0.0.29",
|
||||
"antd": "^5.26.2",
|
||||
"@kevisual/query": "^0.0.33",
|
||||
"antd": "^6.1.2",
|
||||
"clsx": "^2.1.1",
|
||||
"lucide-react": "^0.522.0",
|
||||
"react": "^19.1.0",
|
||||
"react-dom": "^19.1.0",
|
||||
"rollup-plugin-visualizer": "^6.0.3"
|
||||
"lucide-react": "^0.562.0",
|
||||
"react": "^19.2.3",
|
||||
"react-dom": "^19.2.3",
|
||||
"rollup-plugin-visualizer": "^6.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@kevisual/cache": "^0.0.3",
|
||||
"@kevisual/cache": "^0.0.4",
|
||||
"@kevisual/codemirror": "^0.0.12",
|
||||
"@tailwindcss/vite": "^4.1.10",
|
||||
"@types/react": "^19.1.8",
|
||||
"@types/react-dom": "^19.1.6",
|
||||
"@vitejs/plugin-react": "^4.6.0",
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"@types/react": "^19.2.7",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
"@vitejs/plugin-react": "^5.1.2",
|
||||
"react-feather": "^2.0.10",
|
||||
"react-toastify": "^11.0.5",
|
||||
"tailwindcss": "^4.1.10",
|
||||
"vite": "^7.0.0"
|
||||
"tailwindcss": "^4.1.18",
|
||||
"vite": "^7.3.0"
|
||||
}
|
||||
}
|
||||
5844
pnpm-lock.yaml
generated
5844
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user