Skip to content
This repository was archived by the owner on Nov 2, 2024. It is now read-only.

Commit 4b3303f

Browse files
wibus-weettimochan
andauthored
docs(docs): deploy documentaion (#6)
Co-authored-by: timochan <[email protected]>
1 parent b553db0 commit 4b3303f

File tree

13 files changed

+600
-67
lines changed

13 files changed

+600
-67
lines changed
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
import { useState } from 'react';
2+
import copy from 'copy-to-clipboard';
3+
4+
export function EnvVariableConfig({ variableNames }) {
5+
const [values, setValues] = useState(Array(variableNames.length).fill(''));
6+
7+
const handleCopy = () => {
8+
const envContent = variableNames.map((name, index) => `${name.key}=${values[index]}`).join('\n');
9+
copy(envContent);
10+
};
11+
12+
const handleChange = (index, value) => {
13+
const newValues = [...values];
14+
newValues[index] = value;
15+
setValues(newValues);
16+
};
17+
18+
return (
19+
<div className="p-4 mt-2">
20+
{variableNames.map((name, index) => (
21+
<div key={`${name.key}`} className="flex items-center space-x-4 mb-4">
22+
<input
23+
type="text"
24+
className="border rounded px-2 py-2 w-1/2 bg-transparent focus:outline-none focus:border-black hover:border-white-400 transition duration-300 font-[400] font-sans text-sm cursor-not-allowed"
25+
value={name.name || name.key}
26+
data-tip={name.key}
27+
onMouseOver={(e: any) => {
28+
e.target.style.color = 'transparent';
29+
setTimeout(() => {
30+
e.target.style.color = 'inherit';
31+
e.target.value = e.target.dataset.tip;
32+
}, 300);
33+
}}
34+
onMouseLeave={(e: any) => {
35+
e.target.style.color = 'transparent';
36+
setTimeout(() => {
37+
e.target.style.color = 'inherit';
38+
e.target.value = name.name || name.key;
39+
}, 300);
40+
}}
41+
disabled
42+
/>
43+
<input
44+
type="text"
45+
// :focus-visible outline none
46+
className="border rounded px-2 py-2 w-1/2 focus:outline-none focus:border-black hover:border-gray-400 transition duration-300 font-[400] font-sans text-sm" style={{ outline: "none", boxShadow: "none" }}
47+
placeholder={`Enter value...`}
48+
value={values[index]}
49+
onChange={(e) => handleChange(index, e.target.value)}
50+
/>
51+
</div>
52+
))}
53+
<div className="flex items-center justify-between mb-4">
54+
<h2 className="sr-only">环境变量配置</h2>
55+
<button
56+
type="button"
57+
className="border bg-black w-full text-white px-4 py-2 rounded-lg text-sm transform transition-all duration-300 focus:outline-none hover:bg-gray-700"
58+
onClick={handleCopy}
59+
>
60+
复制
61+
</button>
62+
</div>
63+
</div>
64+
);
65+
}

components/Icons/Docker.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { SVGProps } from "react";
2+
3+
export function UimDocker(props: SVGProps<SVGSVGElement>) {
4+
return (
5+
<svg xmlns="http://www.w3.org/2000/svg" width="1.5em" height="1.5em" viewBox="0 0 24 24" {...props}><path fill="currentColor" d="M21.805 10.077a2.627 2.627 0 0 0-1.632-.427a5.189 5.189 0 0 0-.844.074A3.18 3.18 0 0 0 17.9 7.581l-.287-.167l-.186.27a3.967 3.967 0 0 0-.51 1.187a2.819 2.819 0 0 0 .334 2.217a3.936 3.936 0 0 1-1.457.352H2.623a.622.622 0 0 0-.622.622a9.386 9.386 0 0 0 .575 3.385a5.078 5.078 0 0 0 2.004 2.607A8.868 8.868 0 0 0 8.977 19a13.486 13.486 0 0 0 2.44-.223a10.068 10.068 0 0 0 3.19-1.16a8.734 8.734 0 0 0 2.17-1.78a11.81 11.81 0 0 0 2.125-3.664h.185a3.052 3.052 0 0 0 2.236-.844a2.47 2.47 0 0 0 .594-.872l.083-.241Z"></path><path fill="currentColor" d="M3.847 11.06H5.61a.156.156 0 0 0 .157-.158V9.325a.156.156 0 0 0-.157-.157H3.847a.156.156 0 0 0-.158.157v1.577a.162.162 0 0 0 .158.158Zm2.43 0H8.04a.156.156 0 0 0 .157-.158V9.325a.156.156 0 0 0-.157-.157H6.277a.156.156 0 0 0-.157.157v1.577a.162.162 0 0 0 .157.158m2.477 0h1.762a.156.156 0 0 0 .158-.158V9.325a.156.156 0 0 0-.158-.157H8.754a.156.156 0 0 0-.158.157v1.577a.151.151 0 0 0 .158.158Zm2.44 0h1.762a.156.156 0 0 0 .158-.158V9.325a.156.156 0 0 0-.158-.157h-1.762a.156.156 0 0 0-.158.157v1.577a.156.156 0 0 0 .158.158ZM6.277 8.806H8.04a.163.163 0 0 0 .157-.158V7.071a.156.156 0 0 0-.157-.157H6.277a.156.156 0 0 0-.157.157v1.577a.17.17 0 0 0 .157.158m2.477 0h1.762a.163.163 0 0 0 .158-.158V7.071a.156.156 0 0 0-.158-.157H8.754a.156.156 0 0 0-.158.157v1.577a.156.156 0 0 0 .158.158m2.44 0h1.762a.163.163 0 0 0 .158-.158V7.071a.163.163 0 0 0-.158-.157h-1.762a.156.156 0 0 0-.158.157v1.577a.163.163 0 0 0 .158.158m0-2.263h1.762a.156.156 0 0 0 .158-.158V4.808a.163.163 0 0 0-.158-.158h-1.762a.156.156 0 0 0-.158.158v1.577a.163.163 0 0 0 .158.158m2.458 4.517h1.762a.156.156 0 0 0 .158-.158V9.325a.156.156 0 0 0-.158-.157h-1.762a.156.156 0 0 0-.158.157v1.577a.162.162 0 0 0 .158.158" opacity=".25"></path></svg>
6+
)
7+
}

components/Icons/MoneyBillStack.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { SVGProps } from "react";
2+
3+
export function UilMoneyBillStack(props: SVGProps<SVGSVGElement>) {
4+
return (
5+
<svg xmlns="http://www.w3.org/2000/svg" width="1.3em" height="1.3em" viewBox="0 0 24 24" {...props}><path fill="currentColor" d="M20 1H4a3 3 0 0 0-3 3v16a3 3 0 0 0 3 3h16a3 3 0 0 0 3-3V4a3 3 0 0 0-3-3ZM8 21H4a1 1 0 0 1-1-1v-1.18A3 3 0 0 0 4 19h4Zm0-4H4a1 1 0 0 1-1-1v-1.18A3 3 0 0 0 4 15h4Zm0-4H4a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h4Zm6 8h-4v-6h4Zm0-8h-4V3h4Zm7 7a1 1 0 0 1-1 1h-4v-2h4a3 3 0 0 0 1-.18Zm0-4a1 1 0 0 1-1 1h-4v-2h4a3 3 0 0 0 1-.18Zm0-4a1 1 0 0 1-1 1h-4V3h4a1 1 0 0 1 1 1Zm-3-5a1 1 0 1 0 1 1a1 1 0 0 0-1-1ZM6 9a1 1 0 1 0-1-1a1 1 0 0 0 1 1Z"></path></svg>
6+
)
7+
}

components/Icons/PaintTool.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { SVGProps } from "react";
2+
3+
export function UilPaintTool(props: SVGProps<SVGSVGElement>) {
4+
return (
5+
<svg xmlns="http://www.w3.org/2000/svg" width="1.5em" height="1.5em" viewBox="0 0 24 24" {...props}><path fill="currentColor" d="M18 1h-8a3 3 0 0 0-3 3H6a3 3 0 0 0-3 3v3a3 3 0 0 0 3 3h6a1 1 0 0 1 1 1v1a2 2 0 0 0-2 2v4a2 2 0 0 0 2 2h2a2 2 0 0 0 2-2v-4a2 2 0 0 0-2-2v-1a3 3 0 0 0-3-3H6a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h1a3 3 0 0 0 3 3h8a3 3 0 0 0 3-3V4a3 3 0 0 0-3-3Zm-3 16v4h-2v-4Zm4-11a1 1 0 0 1-1 1h-8a1 1 0 0 1-1-1V4a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1Z"></path></svg>
6+
)
7+
}

components/Icons/Star.tsx

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import { SVGProps } from "react";
2+
3+
4+
export function UimStar(props: SVGProps<SVGSVGElement>) {
5+
return (
6+
<svg xmlns="http://www.w3.org/2000/svg" width="1.5em" height="1.5em" viewBox="0 0 24 24" {...props}><path fill="currentColor" d="M17.562 21.56a1.003 1.003 0 0 1-.465-.115L12 18.765l-5.097 2.68a1 1 0 0 1-1.451-1.054l.973-5.676l-4.123-4.02a1 1 0 0 1 .554-1.705l5.699-.828l2.548-5.164a1.042 1.042 0 0 1 1.794 0l2.548 5.164l5.699.828a1 1 0 0 1 .554 1.706l-4.123 4.019l.973 5.676a1 1 0 0 1-.986 1.169Z"></path></svg>
7+
)
8+
}

pages/_meta.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818
"themes": {
1919
"type": "page",
2020
"title": "前端主题",
21-
"href": "/themes",
2221
"theme": {
2322
"layout": "raw"
2423
}

pages/docs/_meta.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"index": "引言",
3+
"features": "主要功能",
4+
"-- advanced": {
5+
"type": "separator",
6+
"title": "部署"
7+
},
8+
"docker": "Docker 部署",
9+
"scripts": "预设脚本部署",
10+
"advanced": "进阶部署"
11+
}

pages/docs/advanced.mdx

Lines changed: 263 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,263 @@
1+
# 进阶部署
2+
3+
import { Callout } from 'nextra/components';
4+
5+
<Callout type="error">
6+
在您进行进阶部署前,我们给予最后的警告:如果你**不是开发者**,或者**不想折腾**,请不要选择**进阶部署**,因为它需要你具备一定的开发能力。
7+
8+
由于自身技术原因导致的问题,我们将**不会提供任何技术支持**。情节严重者,我们将**永久拉黑**您的账号。
9+
</Callout>
10+
11+
## 要求
12+
13+
- 已安装 [Node.js](https://nodejs.org/zh-cn/) 16.0.0 或以上版本
14+
- 已安装 [Git](https://git-scm.com/downloads), [PNPM](https://pnpm.io/installation), [PM2](https://pm2.keymetrics.io/docs/usage/quick-start/)
15+
- 已安装 [MongoDB](https://www.mongodb.com/try/download/community), [Redis](https://redis.io/download) 并正常运行
16+
17+
import { Steps } from 'nextra/components';
18+
19+
<Steps>
20+
### 1. 克隆并安装
21+
22+
```bash
23+
git clone https://github.com/mx-space/core.git --depth=1
24+
cd core
25+
pnpm i
26+
```
27+
28+
### 2. 构建 & Bundle
29+
30+
```bash
31+
pnpm build
32+
pnpm bundle
33+
```
34+
35+
### 3. 配置 ecosystem.config.js
36+
37+
<Configurator
38+
args={['--color', '--encrypt_enable']}
39+
env={{
40+
MX_ENCRYPT_KEY: {
41+
type: 'password',
42+
tip: '加密密钥,可选',
43+
default: 'mx-space',
44+
},
45+
PORT: {
46+
type: 'number',
47+
tip: '服务端口,可选',
48+
default: 3000,
49+
},
50+
ALLOWED_ORIGINS: {
51+
type: 'text',
52+
tip: '允许跨域的域名,多个域名用逗号分隔',
53+
default: 'innei.ren,www.innei.ren',
54+
},
55+
JWT_SECRET: {
56+
type: 'password',
57+
tip: 'JWT 密钥,用于生成 JWT Token,可选',
58+
default: 'asdoiasjdoiasjdioasjdioasjdio',
59+
},
60+
}}
61+
template={`const { cpus } = require('os')
62+
const { execSync } = require('child_process')
63+
const nodePath = execSync(\`npm root --quiet -g\`, { encoding: 'utf-8' }).split(
64+
'\n',
65+
)[0]
66+
const cpuLen = cpus().length
67+
module.exports = {
68+
apps: [
69+
{
70+
name: 'mx-server',
71+
script: 'out/index.js',
72+
autorestart: true,
73+
exec_mode: 'cluster',
74+
watch: false,
75+
instances: cpuLen,
76+
max_memory_restart: '520M',
77+
args: '',
78+
env: {
79+
NODE_ENV: 'production',
80+
NODE_PATH: nodePath,
81+
MX_ENCRYPT_KEY: process.env.MX_ENCRYPT_KEY,
82+
PORT: process.env.PORT,
83+
},
84+
},
85+
],
86+
}
87+
`}
88+
/>
89+
90+
### 4. 启动
91+
92+
1. 进入 `./apps/core/out`,创建一个 `ecosystem.config.js` 文件
93+
2. 将上方复制的内容黏贴进去,然后执行以下命令启动服务
94+
95+
```bash
96+
pm2 start ecosystem.config.js
97+
```
98+
99+
### 5. 反向代理 or ...
100+
101+
剩下的就是你的事了,你可以使用 [Nginx](https://nginx.org/en/download.html) 或者 [Caddy](https://caddyserver.com/download) 等反向代理工具,也可以使用 [Cloudflare](https://www.cloudflare.com/) 等 CDN 服务。本文不再赘述。
102+
103+
</Steps>
104+
105+
106+
107+
108+
import { useState, useEffect } from 'react';
109+
import copy from 'copy-to-clipboard';
110+
111+
export const Configurator = ({ args, template, env }) => {
112+
const [selectedArgs, setSelectedArgs] = useState([]);
113+
const [envValues, setEnvValues] = useState(
114+
Object.keys(env).map((key) => env[key].default)
115+
);
116+
const [nowTemplate, setNowTemplate] = useState(template);
117+
118+
const handleToggleArg = (arg) => {
119+
if (selectedArgs.includes(arg)) {
120+
setSelectedArgs(selectedArgs.filter((item) => item !== arg));
121+
} else {
122+
setSelectedArgs([...selectedArgs, arg]);
123+
}
124+
};
125+
126+
const handleChange = (index, value) => {
127+
const updatedEnvValues = [...envValues];
128+
updatedEnvValues[index] = value;
129+
setEnvValues(updatedEnvValues);
130+
};
131+
132+
const handleCopyToClipboard = () => {
133+
copy(updatedEnvTemplate);
134+
};
135+
136+
useEffect(() => {
137+
const updatedTemplate = nowTemplate.replace(
138+
/args:\s*'([^']*)'/,
139+
`args: '${selectedArgs.join(' ')}'`
140+
);
141+
const updatedEnvTemplate = updatedTemplate.replace(
142+
/env:\s*{([^}]*)}/,
143+
`env: {
144+
${Object.keys(env)
145+
.map((key, index) => `${key}: '${envValues[index]}'`)
146+
.join(', \n ')}
147+
}`
148+
);
149+
setNowTemplate(updatedEnvTemplate);
150+
}, [selectedArgs, envValues]);
151+
152+
return (
153+
<div>
154+
<div className="p-4 mt-2">
155+
156+
<div id="config" className="border rounded-lg overflow-hidden h-12 mb-4" style={{
157+
height: "66.4px",
158+
transition: 'height 0.5s ease-in-out',
159+
}}>
160+
<div className="flex cursor-pointer items-center justify-between bg-gray-100 p-4" onClick={() => {
161+
const config = document.getElementById('config');
162+
const h12Exist = config.classList.contains('h-12'); // 12 在那就是未展开, auto 就是展开
163+
if (!h12Exist) {
164+
const height = config.scrollHeight;
165+
for (let i = 0; i < 11; i++) {
166+
if (i === 10) {
167+
setTimeout(() => {
168+
config.style.height = '66.4px';
169+
}, i * 50);
170+
break;
171+
}
172+
setTimeout(() => {
173+
config.style.height = `${height - (height / 10) * i}px`;
174+
}, i * 50);
175+
}
176+
config.classList.add('h-12');
177+
} else { // 收起
178+
const height = config.scrollHeight;
179+
for (let i = 0; i < 11; i++) {
180+
setTimeout(() => {
181+
config.style.height = `${(height / 10) * i}px`;
182+
}, i * 50);
183+
}
184+
config.classList.remove('h-12');
185+
}
186+
}}>
187+
<h2 className="text-sm text-gray-500">
188+
<span className="text-black">ecosystem.config.js</span> 配置文件 (点击展开)
189+
</h2>
190+
<button
191+
type="button"
192+
className="text-gray-500 focus:outline-none hover:text-black transition duration-300"
193+
>
194+
<svg
195+
xmlns="http://www.w3.org/2000/svg"
196+
className="h-4 w-4"
197+
viewBox="0 0 20 20"
198+
fill="currentColor"
199+
>
200+
<path
201+
fillRule="evenodd"
202+
d="M10 12a2 2 0 100-4 2 2 0 000 4z"
203+
clipRule="evenodd"
204+
/>
205+
<path
206+
fillRule="evenodd"
207+
d="M10 2a8 8 0 100 16 8 8 0 000-16zM2 10a8 8 0 1116 0 8 8 0 01-16 0z"
208+
clipRule="evenodd"
209+
/>
210+
</svg>
211+
</button>
212+
</div>
213+
<div className="p-4">
214+
<pre className="rounded-lg text-sm">
215+
<code>{nowTemplate}</code>
216+
</pre>
217+
</div>
218+
</div>
219+
<h2 className="text-xl font-semibold mb-4">环境变量</h2>
220+
{Object.keys(env).map((key, index) => (
221+
<div key={key} className="flex items-center space-x-4 mb-4">
222+
<input
223+
type="text"
224+
className="border rounded px-2 py-2 w-1/2 bg-transparent focus:outline-none focus:border-black hover:border-white-400 transition duration-300 font-[400] font-sans text-sm cursor-not-allowed"
225+
value={`${key} (${env[key].tip})`}
226+
disabled
227+
/>
228+
<input
229+
type={env[key].type}
230+
className="border rounded px-2 py-2 w-1/2 focus:outline-none focus:border-black hover:border-gray-400 transition duration-300 font-[400] font-sans text-sm" style={{ outline: "none", boxShadow: "none" }}
231+
placeholder={`Enter value...`}
232+
value={envValues[Object.keys(env).indexOf(key)]}
233+
onChange={(e) => handleChange(index, e.target.value)}
234+
/>
235+
</div>
236+
))}
237+
</div>
238+
<div className="flex p-4">
239+
<h2 className="text-xl font-semibold mb-4">配置选项</h2>
240+
{args.map((arg) => (
241+
<button
242+
key={arg}
243+
className={`border rounded px-2 py-2 mr-4 mb-4 focus:outline-none focus:border-black hover:border-gray-400 transition duration-300 font-[400] font-sans text-sm ${
244+
selectedArgs.includes(arg) ? 'bg-gray-200' : 'bg-transparent'
245+
}`}
246+
onClick={() => handleToggleArg(arg)}
247+
>
248+
{arg}
249+
</button>
250+
))}
251+
</div>
252+
253+
254+
<button
255+
type="button"
256+
className="border bg-black w-full text-white px-4 py-2 rounded-lg text-sm transform transition-all duration-300 focus:outline-none hover:bg-gray-700"
257+
onClick={handleCopyToClipboard}
258+
>
259+
复制
260+
</button>
261+
</div>
262+
);
263+
};

0 commit comments

Comments
 (0)