1
0

update for astro

This commit is contained in:
2025-07-26 15:31:43 +08:00
parent 90126beb35
commit 51733f3f2e
50 changed files with 8300 additions and 12 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 464 KiB

View File

@@ -0,0 +1,19 @@
## 公司介绍
公司名称:杭州余杭逸文设计工作室(个体工商户)
公司地址:浙江省杭州市余杭区闲林街道天日山西路 230 号 A 区 3 楼 2954 室
公司邮箱: kevisual@kevisual.cn
公司经营范围网站部署笔记ai 助手,计算机软件开发。
公司网页: https://www.kevisual.cn
公司 logo 图片:![logo](https://kevisual.cn/root/center/panda.png)
公司营业执照: ![营业执照](https://kevisual.cn/api/s1/share/root/upload/1.0.0/营业执照.jpg)
举报邮箱: feedback@kevisual.cn
备案号:浙 ICP 备 2025158778 号

25
backup/docs/关于.md Normal file
View File

@@ -0,0 +1,25 @@
# 关于我们
我们是一个独立开发团队,致力于提供高质量的软件产品。我们的团队成员都是经验丰富的开发者,他们有着对技术的深刻理解和创新能力。
我们的使命是:
1. 提供高质量的软件产品
2. 不断创新,满足用户需求
3. 提供优质的售后服务
4. 保护用户隐私
我们的愿景是:
1. 创立更简单,方便的网页助手,让生活更美好。
2. 成为用户信赖的软件品牌
3. 不断创新,满足用户需求
4. 提供优质的售后服务
联系信息:
邮箱feedback@kevisual.cn
电话18324451015
地址:浙江省杭州市余杭区闲林街道天日山西路 230 号 A 区 3 楼 2954 室

View File

@@ -0,0 +1,48 @@
# kevisual 助手
加速你的工作,生活,学习。
## 功能介绍
### 1. 网页部署平台
任何人的自己的博客,自定义的 ai 创建的网页,都可以通过这个平台,来管理自己的网页。
实现了:
- 类似图床的文件管理
- 站点的创建,删除
- 域名自定义
#### 1.1. 用户的用户管理 web 网站
![图片1](https://kevisual.cn/root/official/docs/assets/feature/user-apps.png)
可以配置只自己可以访问。
#### 1.2. 文件管理
![图片2](https://kevisual.cn/root/official/docs/assets/feature/user-files.png)
配置自己的文件的目录
### 2. AI Mark 推荐
大模型汇总了大量信息,但在具体应用时,用户需要一个精炼的知识库来找到解决方案。因此,我们计划创建一个网站助手工具库。当用户提出问题时,工具库可以提供快捷方式或直接实现解决方案。我们来提炼这个资料库。
例如,我们将收录一些可自行部署的软件和开源项目,如 GitHub 上的优秀项目vaultwarden密码管理、memos笔记等。
由于应用种类繁多,我们需要一个便捷的入口来快速访问这些工具。
TODO
### 2. 笔记助手
快速将内容粘贴到视觉程序库中,通过 AI 创造性地生成美观的内容并进行可视化。便捷地创建个人笔记,加速思考,快速生成笔记和网页。
TODO:
### 3. 资料库 AI
搭建自己的资料库。
TODO:

View File

@@ -0,0 +1,20 @@
# 用户协议
欢迎使用本网站。在使用本网站之前,请仔细阅读以下用户协议条款。访问或使用本网站即表示您同意遵守本协议。
## 1. 使用条款
用户在使用本网站时,必须遵守所有适用的法律法规。用户不得利用本网站从事任何非法活动。
## 2. 知识产权
本网站的所有内容,包括但不限于文本、图像、标识和软件,均受版权法和其他知识产权法的保护。未经授权,用户不得复制、分发或以其他方式使用本网站的内容。
## 3. 责任限制
本网站不对因使用或无法使用本网站而导致的任何直接、间接、偶然、特殊或后果性损害承担责任。
## 4. 隐私政策
用户的隐私对我们非常重要。请参阅我们的隐私政策以了解更多信息。
## 5. 修改和终止
本网站保留随时修改或终止本协议的权利。修改后的协议将在本网站上发布,并立即生效。
感谢您使用本网站。如有任何问题,请联系我们。

View File

@@ -0,0 +1,31 @@
# 隐私政策
杭州余杭逸文设计工作室(个体工商户)(以下简称"我们")非常重视用户的隐私。请仔细阅读以下隐私政策,以了解我们如何收集、使用和保护您的信息。
## 1. 信息收集
我们可能会收集以下类型的信息:
- 联系信息:如您的姓名、电子邮件地址。
- 使用信息:如您访问我们网站的频率、使用的功能等。
## 2. 信息使用
我们收集的信息将用于以下目的:
- 提供和改进我们的服务。
- 处理您的请求和反馈。
- 发送重要通知和更新。
## 3. 信息共享
我们不会与第三方共享您的个人信息,除非:
- 获得您的明确同意。
- 法律要求或允许。
## 4. 信息安全
我们采取合理的措施保护您的信息免受未经授权的访问、使用或披露。
## 5. 隐私政策的变更
我们可能会不时更新本隐私政策。任何更改将在我们的网站上发布,并立即生效。
如有任何问题或建议,请通过以下方式联系我们:
- 公司邮箱envision@kevisual.cn
- 举报邮箱feedback@kevisual.cn
感谢您信任我们。

16
backup/index.html Normal file
View File

@@ -0,0 +1,16 @@
<!doctype html>
<html lang="en">
<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" />
<title>逸文设计工作室</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="./src/main.tsx"></script>
</body>
</html>

39
backup/package.json Normal file
View File

@@ -0,0 +1,39 @@
{
"name": "@kevisual/official-website",
"version": "0.0.2",
"description": "",
"main": "index.js",
"basename": "/root/official",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"pub": "envision deploy ./dist -k official -v 0.0.2 -u -o root"
},
"keywords": [],
"author": "abearxiong <xiongxiao@xiongxiao.me>",
"license": "MIT",
"type": "module",
"dependencies": {
"@ant-design/v5-patch-for-react-19": "^1.0.3",
"@kevisual/query": "^0.0.29",
"antd": "^5.26.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"
},
"devDependencies": {
"@kevisual/cache": "^0.0.3",
"@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",
"react-feather": "^2.0.10",
"react-toastify": "^11.0.5",
"tailwindcss": "^4.1.10",
"vite": "^7.0.0"
}
}

2939
backup/pnpm-lock.yaml generated Normal file

File diff suppressed because it is too large Load Diff

266
backup/src/App.tsx Normal file
View File

@@ -0,0 +1,266 @@
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';
// @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 { 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;
};
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=''>
<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'
onClick={() => {
window.open(url, '_blank');
}}>
<img src={Logo} alt='可视化助手 Logo' className='h-10 w-30 ' />
</div>
<div className='hidden md:flex space-x-6'>
<a
className='hover:text-gray-400 cursor-pointer'
onClick={(e) => {
e.preventDefault();
const url = new URL('/root/center/', 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>
</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>
<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>
{/* Features Section */}
<section id='features' className='py-20 bg-white'>
<div className='container mx-auto px-6'>
<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='py-20 bg-white'>
<div className='container mx-auto px-6'>
<h2 className='text-3xl font-bold text-center mb-16'></h2>
<div className='max-w-2xl mx-auto w-[200px]'>
<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'>
<div className='container mx-auto px-6'>
<div className='grid md:grid-cols-4 gap-8'>
<div>
<h3 className='text-lg font-semibold mb-4'>Kevisual </h3>
<p className='text-gray-400'></p>
</div>
<div>
<h3 className='text-lg font-semibold mb-4'></h3>
<ul className='space-y-2 text-gray-400'>
<li>
<a href='#features' className='hover:text-white'>
</a>
</li>
<li>
<a href='#contact' className='hover:text-white'>
</a>
</li>
</ul>
</div>
<div>
<h3 className='text-lg font-semibold mb-4'></h3>
<ul className='space-y-2 text-gray-400'>
<li>
<a href='./privacy' className='hover:text-white'>
</a>
</li>
<li>
<a href='./terms' className='hover:text-white'>
</a>
</li>
</ul>
</div>
<div>
<h3 className='text-lg font-semibold mb-4'></h3>
<div className='flex space-x-4'>
<a href='mailto:feedback@kevisual.cn' className='text-gray-400 hover:text-white cursor-pointer'>
<Mail className='w-6 h-6' />
</a>
<a href='tel:18324451015' className='text-gray-400 hover:text-white cursor-pointer'>
<Phone className='w-6 h-6' />
</a>
<a
className='text-gray-400 hover:text-white cursor-pointer'
onClick={(e) => {
e.preventDefault();
toastWeChat();
}}>
<WeChat className='w-6 h-6' />
</a>
</div>
</div>
</div>
<div
className='mt-12 pt-8 border-t border-gray-800 text-center text-gray-400'
onClick={() => {
window.open('https://beian.miit.gov.cn/', '_blank');
}}>
<p>ICP备2025158778号</p>
<p>© 2025 . All rights reserved.</p>
</div>
</div>
</footer>
</div>
);
};
export const App = () => {
return (
<>
<Provider>
<ToastContainer autoClose={2000}></ToastContainer>
<Main />
</Provider>
</>
);
};

19
backup/src/Provider.tsx Normal file
View File

@@ -0,0 +1,19 @@
import ConfigProvider from 'antd/lib/config-provider';
import '@ant-design/v5-patch-for-react-19';
export const Provider = ({ children }: { children: React.ReactNode }) => {
return (
<ConfigProvider
theme={{
token: {
colorPrimary: '#1677ff',
colorTextBase: '#ffffff',
colorBgBase: '#1f1f1f',
colorBgContainer: '#2c2c2c',
colorBorder: '#3a3a3a',
},
}}>
{children}
</ConfigProvider>
);
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 KiB

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,24 @@
export const Github = () => {
return (
<svg aria-hidden='true' height='24' viewBox='0 0 24 24' version='1.1' width='24' data-view-component='true' className='octicon octicon-mark-github'>
<path d='M12 1C5.923 1 1 5.923 1 12c0 4.867 3.149 8.979 7.521 10.436.55.096.756-.233.756-.522 0-.262-.013-1.128-.013-2.049-2.764.509-3.479-.674-3.699-1.292-.124-.317-.66-1.293-1.127-1.554-.385-.207-.936-.715-.014-.729.866-.014 1.485.797 1.691 1.128.99 1.663 2.571 1.196 3.204.907.096-.715.385-1.196.701-1.471-2.448-.275-5.005-1.224-5.005-5.432 0-1.196.426-2.186 1.128-2.956-.111-.275-.496-1.402.11-2.915 0 0 .921-.288 3.024 1.128a10.193 10.193 0 0 1 2.75-.371c.936 0 1.871.123 2.75.371 2.104-1.43 3.025-1.128 3.025-1.128.605 1.513.221 2.64.111 2.915.701.77 1.127 1.747 1.127 2.956 0 4.222-2.571 5.157-5.019 5.432.399.344.743 1.004.743 2.035 0 1.471-.014 2.654-.014 3.025 0 .289.206.632.756.522C19.851 20.979 23 16.854 23 12c0-6.077-4.922-11-11-11Z'></path>
</svg>
);
};
export const WeChat = (props: React.SVGProps<SVGSVGElement>) => {
return (
<div className={'relative ' + props.className}>
<svg viewBox='0 0 1024 1024' version='1.1' xmlns='http://www.w3.org/2000/svg' className='w-8 h-8 absolute -top-1 left-0'>
<path
fill='currentColor'
d='M289.8 367.2c0-13.6 7.8-25.4 19.8-31.2 21.3-10.2 49.2 3.5 49.2 32.5 0 18-16 33.5-34.2 33.5-19.4 0-34.8-15.3-34.8-34.8z m174.2 0.7c0-13.7 8.5-26.2 18.9-31.4 12.7-6.3 28.1-4.6 38.6 4.8 11.8 10.5 15 29.4 7.8 42.3-14.3 25.5-49.9 24.2-61.9-1.7-1.5-3.4-3.4-9.6-3.4-14zM149.9 433c0 27.3 2.4 43 10.7 66.7 8.4 24 24 49.6 41.4 68.3 1.6 1.7 2.1 2.7 3.9 4.5l22 20.6c1.6 1.3 3.1 2.4 4.7 3.7 1.7 1.3 2.9 2.3 4.7 3.7 14.3 10.7 10.8 17.2 5.3 36.7l-8.1 30c-2.8 9.5 1.9 14.7 8.2 14.4 4.1-0.2 20.8-10.9 24.6-13.1l40.6-23.3c11.2-5 19-0.9 32.4 2.5 18.6 4.7 28.6 5.3 47.5 7.3l38.1 0.4c-0.8-9.7-8.4-17.1-8.4-58.5 0-16 3.9-33.9 7.8-46.4 5.7-18 16.3-38.3 27.8-53.5l18.8-21.9 14.2-12.9c2.7-2.3 5-4.1 7.8-6.4l39.3-24.6c39.3-18.7 75.6-28.5 124.9-28.5l9.7 0.7c3.1-0.2 3 1.2-0.6-13.1-4.4-17.7-12.1-35.2-21.5-50.8-12.7-21.2-22.5-31.3-39.1-47.9-15.6-15.6-41.7-32.5-60.6-42-15.7-7.8-25.1-11.3-41.7-16.9-14.8-5-30.2-8.1-47.2-10.8-8.6-1.4-17.5-1.9-26.2-2.9-4.5-0.5-10.1 0.2-14.7-0.1-43.9-2.5-103.7 11.4-141.6 31.8-1.9 1-2.5 1.5-4.5 2.6l-23 13.8c-12.4 9.4-20.3 13.9-32.6 26.1l-27.1 30.9c-20.5 30.3-37.5 64.8-37.5 108.9z'
p-id='1534'></path>
<path
fill='currentColor'
d='M554.2 543.9c0-16.4 12.2-29 29.7-29 23 0 35.1 27 22.9 44.9-0.7 1-0.7 0.8-1.4 1.8-0.9 1.2-0.8 1.2-1.7 2.2-1.9 2.1-5.3 4.3-8 5.6-11 5.3-23.7 3.6-32.4-4.8-5-5-9.1-11.6-9.1-20.7z m172.2-29h3.9c12.9 0 26.4 13 26.4 25.8 0 9.7-0.7 16-8.5 23.7-21.5 21.1-58.7-3-46.5-31.6 2.8-6.6 7.2-11.6 13.5-14.9 2.9-1.5 7.1-3 11.2-3z m-288.9 81.2c0 22.7 0.9 30.3 6.8 51.2 4.8 16.9 14.2 34 24.1 48.1l10.8 13.7c4.5 4.6 9.7 11.1 14.6 15.1 1.6 1.3 2 1.4 3.5 2.9 5.9 5.9 19.5 15.3 27.3 20.3 2.5 1.6 5.2 3.2 7.7 4.6 32.4 18.5 75.8 31.6 113.5 31.6 32.4 0 45.6-0.6 76.6-8.5 14.5-3.7 16.8-2.2 29.6 5.5l39.5 23c8.3 4.8 13.8-1.8 12.4-7.9l-2.6-9.7c-1.7-6.8-3.5-13.2-5.3-19.9-2.6-10-7.3-19.7 2.6-27 18.5-13.6 30.2-25.7 43.8-43.8 19.1-25.3 31.5-61.5 31.5-93.6 0-7.2-1-16.1-1.9-22.6-3.8-27.5-17.1-56.9-34.4-77.8l-24.5-25.8c-2.3-2.1-4.7-3.6-7.1-5.8-5.6-5-22.9-16.3-29.7-19.9-74.4-39.8-165.2-41.3-239.4-1.3-5.3 2.8-10.4 5.9-15.3 9.2-5.5 3.7-16.7 11.4-21.5 15.9-1.2 1.2-1.5 1.6-3 2.8-1.7 1.3-2 1.5-3.4 3-14.7 14.9-22 21.8-33.4 40.8-12.3 20.7-22.8 50.2-22.8 75.9z'
p-id='1535'></path>
</svg>
</div>
);
};

View File

@@ -0,0 +1,51 @@
import { createEditor } from '@kevisual/codemirror';
import { Chain } from '@kevisual/codemirror/utils';
import { useEffect, useRef } from 'react';
import { CacheWorkspace } from '@kevisual/cache';
export const chain = new Chain();
type TextEditorProps = {
content: string;
chain?: Chain;
onChange?: (content: string) => void;
};
export const TextEditor = ({ content, chain, onChange }: TextEditorProps) => {
const editorElRef = useRef<HTMLDivElement>(null);
const editorRef = useRef<ReturnType<typeof createEditor>>(null);
useEffect(() => {
initEditor();
return () => {
if (editorRef.current) {
chain?.destroy?.();
}
};
}, []);
useEffect(() => {
if (editorRef.current) {
chain?.setContent?.(content);
}
}, [content]);
const initEditor = async () => {
if (!editorElRef.current) return;
const cache = new CacheWorkspace();
const editor = createEditor(editorElRef.current, {
type: 'html',
onChange: (value) => {
cache.set('editor-content-home', value);
onChange?.(value);
},
});
const value = await cache.get('editor-content-home');
const cmScroller = editorElRef.current.querySelector('.cm-scroller');
if (cmScroller) {
cmScroller.classList.add('scrollbar');
}
chain?.setEditor?.(editor);
editorRef.current = editor;
if (value) {
chain?.setContent?.(value);
}
};
return <div className='h-full overflow-hidden' ref={editorElRef}></div>;
};

1
backup/src/index.css Normal file
View File

@@ -0,0 +1 @@
@import 'tailwindcss';

9
backup/src/main.tsx Normal file
View File

@@ -0,0 +1,9 @@
import { createRoot } from 'react-dom/client';
import { App } from './App';
import './index.css';
const root = createRoot(document.getElementById('root') as HTMLElement);
root.render(<App />);

View File

@@ -0,0 +1,51 @@
import Modal from 'antd/es/modal/Modal';
import Form, { useForm } from 'antd/es/form/Form';
import FormItem from 'antd/es/form/FormItem';
import Input from 'antd/es/input';
import { useEffect } from 'react';
type CodeDescModalProps = {
open: boolean;
onClose: () => void;
onSubmit?: (values: { title: string; description: string }) => void;
initialValues?: { title: string; description: string };
};
export const CodeDescModal = (props: CodeDescModalProps) => {
const [form] = useForm();
useEffect(() => {
if (!props.open) {
return;
}
if (props.initialValues) {
form.setFieldsValue(props.initialValues || { title: '', description: '' });
}
}, [props.open, props.initialValues, form]);
return (
<Modal title='代码描述' open={props.open} onCancel={props.onClose} footer={null}>
<p className='text-gray-500 text-sm mb-4'>30</p>
<Form form={form} layout='vertical'>
<FormItem label='标题' name='title'>
<Input />
</FormItem>
<FormItem label='描述' name='description'>
<Input.TextArea rows={4} />
</FormItem>
</Form>
<div className='flex justify-end mt-4'>
<button
className='px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 cursor-pointer'
onClick={() => {
form.validateFields().then((values) => {
props.onSubmit?.(values);
props.onClose();
});
}}>
</button>
<button className='ml-2 px-4 py-2 bg-gray-300 text-gray-700 rounded hover:bg-gray-400 cursor-pointer' onClick={props.onClose}>
</button>
</div>
</Modal>
);
};

View File

@@ -0,0 +1,35 @@
import { EvWechat } from '../components/EvWechat';
import { toast } from 'react-toastify';
export const RedirectSuccess = ({ url }: { url: string }) => {
return (
<div className='flex flex-col items-center justify-center p-2'>
<div className='flex flex-col gap-2 mb-3'>
<div className=' font-semibold'></div>
<a
href={url}
className='text-blue-600 hover:text-blue-800 transition-colors duration-200 hover:underline block truncate'
target='_blank'
rel='noopener noreferrer'>
</a>
</div>
</div>
);
};
export const toastSuccess = (url: string) => {
toast.success(<RedirectSuccess url={url} />, {
autoClose: 5000,
className: 'rounded-md shadow-lg',
// icon: false,
});
};
export const toastWeChat = () => {
toast.success(<EvWechat />, {
autoClose: 10000,
className: 'rounded-md shadow-lg',
icon: false,
});
};

View File

@@ -0,0 +1,3 @@
import { QueryClient } from '@kevisual/query';
export const query = new QueryClient();

43
backup/tsconfig.app.json Normal file
View File

@@ -0,0 +1,43 @@
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": [
"ES2020",
"DOM",
"DOM.Iterable"
],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
// "jsx": "react",
// "jsxFragmentFactory": "Fragment",
// "jsxFactory": "h",
"jsx": "react-jsx",
"baseUrl": "./",
"typeRoots": [
"node_modules/@types",
"node_modules/@kevisual/types",
],
"paths": {
"@/*": [
"src/*"
]
},
/* Linting */
"strict": true,
"noImplicitAny": false,
"noUnusedLocals": false,
"noUnusedParameters": false,
"noFallthroughCasesInSwitch": true
},
"include": [
"src",
"typings.d.ts"
]
}

7
backup/tsconfig.json Normal file
View File

@@ -0,0 +1,7 @@
{
"files": [],
"references": [
{ "path": "./tsconfig.app.json" },
{ "path": "./tsconfig.node.json" }
]
}

22
backup/tsconfig.node.json Normal file
View File

@@ -0,0 +1,22 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2023"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"isolatedModules": true,
"moduleDetection": "force",
"noEmit": true,
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["vite.config.ts"]
}

24
backup/vite.config.mjs Normal file
View File

@@ -0,0 +1,24 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import tailwindcss from '@tailwindcss/vite';
// import { visualizer } from "rollup-plugin-visualizer";
// https://vitejs.dev/config/
const isDev = process.env.NODE_ENV === 'development';
export default defineConfig({
plugins: [react(), tailwindcss()],
base: isDev ? '/' : './', //'/root/official/',
optimizeDeps: {
exclude: ['lucide-react'],
},
server: {
proxy: {
'/api': {
target: 'http://localhost:4005',
changeOrigin: true,
secure: false,
rewrite: (path) => path.replace(/^\/api/, '/api'),
},
},
},
});