1
0
This commit is contained in:
熊潇 2025-07-27 01:15:28 +08:00
parent 51733f3f2e
commit 2bc8822f60
5 changed files with 184 additions and 101 deletions

View File

@ -25,7 +25,7 @@ export default defineConfig({
// ...
site: 'https://www.kevisual.cn/',
// base: isDev ? undefined : pkgs.basename,
base: './',
base: isDev ? undefined : './',
integrations: [
mdx(),
react(), //

View File

@ -1,54 +1,21 @@
import { Mail, Phone, MapPin, Book, Globe, Brain, Save } from 'lucide-react';
import { chain, TextEditor } from './components/TextEditor';
import { toast, ToastContainer } from 'react-toastify';
import { ToastContainer } from 'react-toastify';
import { Provider } from './Provider';
// @ts-ignore
import Logo from './assets/logo-1.png';
import { useState } from 'react';
import { CodeDescModal } from './modules/CodeDescModal';
import { query } from './modules/query.ts';
import { toastSuccess, toastWeChat } from './modules/RedirectSuccess.tsx';
import { toastWeChat } from './modules/RedirectSuccess.tsx';
import { WeChat } from './components/Icon.tsx';
const getOrigin = () => {
let origin = window.location.origin;
if (origin.includes('www.kevisual.cn')) {
origin = origin.replace('www.kevisual.cn', 'kevisual.cn');
}
return origin;
import { getOrigin } from './modules/get-origin.ts';
export const openEditor = () => {
window.open('./editor');
};
export const Main = () => {
const [showPreview, setShowPreview] = useState(false);
const [html, setHtml] = useState<string>('');
const [open, setOpen] = useState(false);
const [resultUrl, setResultUrl] = useState<string>('');
const [url] = useState<string>('https://kevisual.cn');
const onSubmit = async (values: { title: string; description: string }) => {
setResultUrl('');
const uploadData = {
title: values?.title,
description: values?.description,
content: chain.getContent(),
};
const res = await query.post({
path: 'app',
key: 'public-upload-html',
data: uploadData,
});
if (res.code === 200) {
const url = res.data?.url;
if (url) {
let origin = getOrigin();
const newUrl = new URL(url, origin);
// toast.success('创建成功, 访问地址' + newUrl.toString(), { autoClose: 3000 });
toastSuccess(newUrl.toString());
setResultUrl(newUrl.toString());
}
}
};
return (
<div className='min-h-screen bg-gray-50'>
{/* Hero Section */}
<header className=''>
<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'>
<div
className='flex items-center space-x-4 cursor-pointer'
@ -56,8 +23,6 @@ export const Main = () => {
window.open(url, '_blank');
}}>
<img src={Logo.src} alt='可视化助手 Logo' className='h-10 w-30 ' />
<span className='text-xl font-semibold text-gray-400 cursor-default'>Kevisual </span>
</div>
<div className='hidden md:flex space-x-6'>
<a
@ -77,66 +42,49 @@ export const Main = () => {
</a>
</div>
</nav>
</header>
<main
className='flex flex-col overflow-hidden'
style={{
height: 'calc(100vh - 64px)',
}}>
<nav className='h-12 bg-white flex'>
<button
className='flex items-center px-4 h-full bg-white border-b border-b-gray-200 hover:bg-gray-50 cursor-pointer'
onClick={() => {
const content = chain.getContent();
if (!content) {
toast.error('内容不能为空', { position: 'top-center', autoClose: 1000 });
return;
}
setOpen(true);
}}>
<span className='text-gray-700'></span>
<Save className='ml-2 w-4 h-4 text-gray-500' />
</button>
</div>
<button
className='flex items-center px-4 h-full bg-white border-b border-b-gray-200 hover:bg-gray-50 cursor-pointer'
style={{
backgroundColor: showPreview ? '#f0f0f0' : 'white',
}}
onClick={() => {
setShowPreview(!showPreview);
}}>
<span className='text-gray-700'></span>
<Globe className='ml-2 w-4 h-4 text-gray-500' />
</button>
</nav>
<div className='p-2 rounded shadow flex' style={{ height: 'calc(100% - 48px - 48px)' }}>
<div className='h-full overflow-auto flex-1'>
<TextEditor content={''} chain={chain} onChange={setHtml} />
<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生成的网页
</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>
{showPreview && (
<div className='w-1/2 shrink-1 border-l border-gray-200 h-full overflow-auto'>
<iframe className='w-full h-full border-0' srcDoc={html} title='预览' sandbox='allow-scripts allow-same-origin allow-popups' />
<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>
)}
</div>
<footer className='h-12'>
{!resultUrl && <div className='flex items-center h-full text-gray-500 px-2 italic'> HTML </div>}
{resultUrl && (
<div className='flex items-center gap-2 px-4 h-full bg-white border-t border-t-gray-200'>
<span className='text-gray-700'>:</span>
<a href={resultUrl} target='_blank' rel='noopener noreferrer' className='text-blue-600 hover:underline'>
{resultUrl}
<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>
)}
</footer>
<CodeDescModal open={open} onClose={() => setOpen(false)} onSubmit={onSubmit} />
</main>
</div>
</article>
{/* Features Section */}
<section id='features' className='py-20 bg-white'>
<div className='container mx-auto px-6'>
<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'>
@ -162,8 +110,8 @@ export const Main = () => {
</section>
{/* Contact Section */}
<section id='contact' className='py-20 bg-white'>
<div className='container mx-auto px-6'>
<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'>

View File

@ -0,0 +1,107 @@
import { Mail, Phone, MapPin, Book, Globe, Brain, Save } from 'lucide-react';
import { chain, TextEditor } from './components/TextEditor';
import { toast, ToastContainer } from 'react-toastify';
import { Provider } from './Provider';
import { useState } from 'react';
import { CodeDescModal } from './modules/CodeDescModal';
import { query } from './modules/query.ts';
import { toastSuccess, toastWeChat } from './modules/RedirectSuccess.tsx';
import { getOrigin } from './modules/get-origin.ts';
export const Editor = () => {
const [showPreview, setShowPreview] = useState(false);
const [html, setHtml] = useState<string>('');
const [open, setOpen] = useState(false);
const [resultUrl, setResultUrl] = useState<string>('');
const [url] = useState<string>('https://kevisual.cn');
const onSubmit = async (values: { title: string; description: string }) => {
setResultUrl('');
const uploadData = {
title: values?.title,
description: values?.description,
content: chain.getContent(),
};
const res = await query.post({
path: 'app',
key: 'public-upload-html',
data: uploadData,
});
if (res.code === 200) {
const url = res.data?.url;
if (url) {
let origin = getOrigin();
const newUrl = new URL(url, origin);
// toast.success('创建成功, 访问地址' + newUrl.toString(), { autoClose: 3000 });
toastSuccess(newUrl.toString());
setResultUrl(newUrl.toString());
}
}
};
return (
<main
className='flex flex-col overflow-hidden'
style={{
height: 'calc(100vh - 64px)',
}}>
<nav className='h-12 bg-white flex'>
<button
className='flex items-center px-4 h-full bg-white border-b border-b-gray-200 hover:bg-gray-50 cursor-pointer'
onClick={() => {
const content = chain.getContent();
if (!content) {
toast.error('内容不能为空', { position: 'top-center', autoClose: 1000 });
return;
}
setOpen(true);
}}>
<span className='text-gray-700'></span>
<Save className='ml-2 w-4 h-4 text-gray-500' />
</button>
<button
className='flex items-center px-4 h-full bg-white border-b border-b-gray-200 hover:bg-gray-50 cursor-pointer'
style={{
backgroundColor: showPreview ? '#f0f0f0' : 'white',
}}
onClick={() => {
setShowPreview(!showPreview);
}}>
<span className='text-gray-700'></span>
<Globe className='ml-2 w-4 h-4 text-gray-500' />
</button>
</nav>
<div className='p-2 rounded shadow flex' style={{ height: 'calc(100% - 48px - 48px)' }}>
<div className='h-full overflow-auto flex-1'>
<TextEditor content={''} chain={chain} onChange={setHtml} />
</div>
{showPreview && (
<div className='w-1/2 shrink-1 border-l border-gray-200 h-full overflow-auto'>
<iframe className='w-full h-full border-0' srcDoc={html} title='预览' sandbox='allow-scripts allow-same-origin allow-popups' />
</div>
)}
</div>
<footer className='h-12'>
{!resultUrl && <div className='flex items-center h-full text-gray-500 px-2 italic'> HTML </div>}
{resultUrl && (
<div className='flex items-center gap-2 px-4 h-full bg-white border-t border-t-gray-200'>
<span className='text-gray-700'>:</span>
<a href={resultUrl} target='_blank' rel='noopener noreferrer' className='text-blue-600 hover:underline'>
{resultUrl}
</a>
</div>
)}
</footer>
<CodeDescModal open={open} onClose={() => setOpen(false)} onSubmit={onSubmit} />
</main>
);
};
export const App = () => {
return (
<>
<Provider>
<ToastContainer autoClose={2000}></ToastContainer>
<Editor />
</Provider>
</>
);
};

View File

@ -0,0 +1,7 @@
export const getOrigin = () => {
let origin = window.location.origin;
if (origin.includes('www.kevisual.cn')) {
origin = origin.replace('www.kevisual.cn', 'kevisual.cn');
}
return origin;
};

View File

@ -0,0 +1,21 @@
---
import '../apps/index/index.css';
import { App } from '../apps/index/Editor.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>
<App client:only />
</body>
</html>