71 | ```
72 |
73 | 此命令将分支指针重置到 `commit-hash`,并丢弃所有未提交的更改。
74 |
75 | ## ssh链接
76 |
77 | ### 生成 SSH 密钥对
78 |
79 | 如果还没有 SSH 密钥,可以通过以下命令生成:
80 |
81 | ```sh
82 | ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
83 | ```
84 |
85 | 按提示操作,生成密钥对后,公钥会保存在 ~/.ssh/id_rsa.pub 中,私钥会保存在 ~/.ssh/id_rsa 中。
86 |
87 | ### 将公钥添加到 GitHub
88 |
89 | * 复制公钥内容:
90 | ```sh
91 | cat ~/.ssh/id_rsa.pub
92 | ```
93 | * 登录 GitHub,进入 `SSH and GPG keys` 页面。
94 | * 点击 "New SSH key",将公钥内容粘贴到 Key 字段中,并设置一个 Title,点击 "Add SSH key"。
95 | * id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。
96 |
97 | ### 配置 Git 使用 SSH
98 |
99 | 确保 Git 使用 SSH 方式连接 GitHub,可以使用以下命令:
100 |
101 | ```sh
102 | cd /path/to/your/repository
103 | git remote set-url origin git@github.com:username/repository.git
104 | ```
--------------------------------------------------------------------------------
/docs/web/basics/hidden.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: CSS处理一行或多行文字超出用省略号
3 | description: CSS处理一行或多行文字超出用省略号
4 | ---
5 |
6 | # CSS处理一行或多行文字超出用省略号
7 |
8 | ## 一行文字
9 |
10 | ```css
11 | {
12 | width: 400px;
13 | white-space: nowrap;
14 | overflow: hidden;
15 | text-overflow: ellipsis;
16 | }
17 | ```
18 | >效果对比:
19 | 时间最会骗人,但也能让你明白,这个世界没有什么是不能失去的,留下的尽力珍惜,得不到的都不重要。
20 | 时间最会骗人,但也能让你明白,这个世界没有什么是不能失去的,留下的尽力珍惜,得不到的都不重要。
21 |
22 | ## 多行文字
23 |
24 | ```css
25 | {
26 | display: -webkit-box;
27 | -webkit-box-orient: vertical;
28 | -webkit-line-clamp: 3;
29 | overflow: hidden;
30 | }
31 | ```
32 | > 效果对比:
33 | 北凉王府龙盘虎踞于清凉山,千门万户,极土木之盛。 作为王朝硕果仅存的异姓王,在庙堂和江湖都是毁誉参半的北凉王徐骁作为一名功勋武臣,可谓得到了皇帝宝座以外所有的东西,在西北三州,他就是当之无愧的主宰,只手遮天,翻云覆雨。 难怪朝廷中与这位异姓王政见不合的大人们私下都会文绉绉骂一声徐蛮子,而一些居心叵测的,更诛心地丢了顶“二皇帝”的帽子。 今天王府很热闹,位高权重的北凉王亲自开了中门,摆开辉煌仪仗,迎接一位仙风道骨的老者,府中下人们只听说是来自道教圣地龙虎山的神仙,相中了痴痴傻傻的小王爷,要收作闭关弟子,这可是天大的福缘,北凉王府都解释成傻人有傻福。 可不是,小王爷自打出生起便没哭过,读书识字一窍不通,六岁才会说话,名字倒是威武气派,徐龙象,传闻还是龙虎山的老神仙当年给取的,说好十二年后再来收徒,这不就如约而至了。 王府内一处院落,龙虎山师祖一级的道门老祖宗捻着一缕雪白胡须,眉头紧皱,背负一柄不常见的小钟馗式桃木剑,配合他的相貌,确实当得出尘二字,谁看都要由衷赞一声世外高人呐。 但此番收徒显然遇到了不小的阻碍,倒不是王府方面有异议,而是他的未来徒弟犟脾气上来了,蹲在一株梨树下,用屁股对付他这个天下道统中论地位能排前三甲的便宜师傅,至于武功嘛,咳咳,前三十总该有的吧。
34 | 北凉王府龙盘虎踞于清凉山,千门万户,极土木之盛。 作为王朝硕果仅存的异姓王,在庙堂和江湖都是毁誉参半的北凉王徐骁作为一名功勋武臣,可谓得到了皇帝宝座以外所有的东西,在西北三州,他就是当之无愧的主宰,只手遮天,翻云覆雨。 难怪朝廷中与这位异姓王政见不合的大人们私下都会文绉绉骂一声徐蛮子,而一些居心叵测的,更诛心地丢了顶“二皇帝”的帽子。 今天王府很热闹,位高权重的北凉王亲自开了中门,摆开辉煌仪仗,迎接一位仙风道骨的老者,府中下人们只听说是来自道教圣地龙虎山的神仙,相中了痴痴傻傻的小王爷,要收作闭关弟子,这可是天大的福缘,北凉王府都解释成傻人有傻福。 可不是,小王爷自打出生起便没哭过,读书识字一窍不通,六岁才会说话,名字倒是威武气派,徐龙象,传闻还是龙虎山的老神仙当年给取的,说好十二年后再来收徒,这不就如约而至了。 王府内一处院落,龙虎山师祖一级的道门老祖宗捻着一缕雪白胡须,眉头紧皱,背负一柄不常见的小钟馗式桃木剑,配合他的相貌,确实当得出尘二字,谁看都要由衷赞一声世外高人呐。 但此番收徒显然遇到了不小的阻碍,倒不是王府方面有异议,而是他的未来徒弟犟脾气上来了,蹲在一株梨树下,用屁股对付他这个天下道统中论地位能排前三甲的便宜师傅,至于武功嘛,咳咳,前三十总该有的吧。
35 |
36 |
37 |
55 |
--------------------------------------------------------------------------------
/docs/other/blog/basics/deploy.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 网站的部署发布
3 | description: 博客的部署发布工作流程,以及详细的介绍
4 | outline: [2, 3]
5 | ---
6 |
7 | # 网站的部署发布
8 |
9 | ## 前置准备工作
10 |
11 | 如果不想花钱可以使用 [`github pages`](/other/blog/up/use-page.html)
12 |
13 | ::: tip 所需
14 | - 云服务器 (年花费200rmb左右)
15 | - 域名 (年花费50rmb左右)
16 | :::
17 |
18 | ## 云服务器
19 |
20 | ::: tip 注意事项
21 | 1. 初次使用云服务器建议先买一年最便宜的华为云试试
22 | 2. 初次购买建议 `windows server` 服务器,可以快速上手。云服务器可以随时刷其他系统,也可以刷 `linux` 系统
23 | 3. 充分掌握云服务器之后再换其他 `linux` 服务器
24 | 3. 服务器配置 `2核2G3M` 够用了
25 | :::
26 |
27 | ::: info 云服务器种类
28 | - `阿里云`
29 | - 有过云服务器使用经验的首选,也是博主现在使用的云服务器厂商
30 | - 个人感觉使用体验最好的
31 | - 服务器限制不多
32 | - `华为云`
33 | - 新用户有个`28rmb/年`
34 | - `腾讯云`
35 | :::
36 |
37 | ### 关于费用问题
38 | - 博主目前服务器年消费在200以内
39 | - 每个服务器厂商也会有新用户活动,但是推荐 *`618`* 或 *`双11`* 活动的时候购买
40 | - 活动买一年用完了就换一家厂商的服务器即可,不行也可以用家人的身份信息购买
41 | - 现在 *`618`* 或 *`双11`* 都有连续几年的服务器便意出售
42 |
43 | ## 域名
44 |
45 | > 推荐第一次使用的话可以先买一个便宜的`.top`,`.dev`等,`华为云`、`阿里云`等均有售卖
46 |
47 | ::: info 云服务器种类
48 | 1. `三大顶级域名`
49 | - `.com` 商业机构(commercial),诸如`apple.com`, `google.com`
50 | - `.net` 网络服务提供商(network)诸如网站后台接口地址
51 | - `.org` 非营利组织(organization) 诸如`vuejs.org`
52 | 2. `国家顶级域名`
53 | - `.cn` 中国
54 | - `.us` 美国
55 | - `.jp` 日本
56 | :::
57 |
58 | ## 配置nginx
59 |
60 | * 建议先用windows电脑本地先熟悉一下 `nginx` 的使用
61 | * 命令都需要在 `nginx文件目录下` 执行
62 |
63 | [官网直通车 🚘](https://nginx.org/en/)
64 |
65 | [nginx的详细使用 🚘](/other/blog/up/use-nginx.html)
66 |
67 | ## 网站备案
68 |
69 | - 服务器是香港或者国外是不需要进行备案的
70 | - 服务器在国内是需要进行备案
71 | - 备案周期大概是 `15-30` 天
72 |
73 | [关于网站如何备案,参考链接 🚘](https://beian.aliyun.com/)
74 |
75 | ## 部署到云服务器
76 |
77 | > 这里假设购买的是 `windows server` 云服务器
78 |
79 | - 买完服务器,在自己电脑操作使用过nginx
80 | - 在服务器下载nginx,在服务器的浏览器里测试nginx是否可用
81 | - 代码上传云服务器,建议通过 `git clone` 的方式
82 | - 这里需要注意 `vitepress` 打包后 `dist打包文件` 也需要上传的代码仓库
83 | - 云服务器电脑安装git工具,拉取代码
84 | - 两种方式启动博客项目
85 | - `方式一:` 将dist目录复制到 `nginx/html` 文件夹下
86 | - `方式二:` 修改nginx配置文件,将项目地址映射到git拉取的dist目录下
87 | - 推荐使用地址映射,可以省去复制粘贴代码,后续升级linux服务器,我们将通过执行脚本方式,`一键完成` 拉取,部署,重载
88 | - 重载nginx,在服务器浏览器访问 `localhost` 看网站效果
89 |
90 | ## 如何使用linux云服务器
91 |
92 | [参考链接](/other/blog/up/use-linux.html)
--------------------------------------------------------------------------------
/docs/web/vue/upload-image/core.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 函数式封装上传图片组件
3 | description: 在vue中使用函数式封装上传图片组件
4 | ---
5 |
6 | # 函数式封装上传图片组件
7 |
8 | > Vue3 + ts函数式封装支持 `函数式|组件` 两种使用方式
9 |
10 | ## 演示
11 |
12 |
13 | {{ disabled ? '上传中...' : '上传' }}
14 |
15 | 清空图片
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
56 |
57 |
67 |
68 | ## 挂载使用
69 |
70 | ### 全局挂载
71 | ```js-vue
72 | // vue2全局挂载
73 | Vue.prototype.$upload = uploadImage
74 |
75 | // vue3全局挂载
76 | app.config.globalProperties.$upload = uploadImage
77 | ```
78 |
79 |
80 | ### 使用
81 | ```js-vue
82 | // vue2
83 | this.$upload().then(()=> {}).catch(err => {})
84 |
85 | // vue3
86 | > 必须使用proxy,正式环境ctx是获取不到的所以不能使用const { ctx } = getCurrentInstance()
87 | const { proxy } = getCurrentInstance()
88 | proxy.$upload().then(()=> {}).catch(err => {})
89 | ```
90 |
91 |
92 | ::: details 源代码
93 | <<< ./upload.js
94 | :::
--------------------------------------------------------------------------------
/docs/web/basics/regExp.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 常用的正则表达式
3 | description: 前端常用的正则表达式
4 | ---
5 |
6 | # 常用的正则表达式
7 |
8 | ## 代码演示
9 |
10 | ::: info 一、开头不为0的数字
11 |
12 |
13 | ```js
14 | oninput="value = value.replace(/[^\d]/gi,'').replace(/^[0]+[0-9]*$/gi,'').substr(0,11)"
15 |
16 | 采用双重replace方法
17 | 1.replace(/[^\d]/gi,'')
18 | 限制用户只能输入数字
19 | 2.replace(/^[0]+[0-9]*$/gi,'')
20 | 限制第一位不能输入0
21 | 3.substr(0,11)
22 | 限制长度11位数
23 |
24 | 还有一种方式,多个value的判断
25 | oninput="if(value<1){value=null};value=value.replace(/[^0-9]/g,'')"
26 | ```
27 | :::
28 |
29 | ::: info 二、输入2位小数
30 |
35 |
36 | ```js
37 | .replace(/[^\d.]/gi, '')
38 | .replace('.', '$#$')
39 | .replace(/\./g, '')
40 | .replace('$#$', '.')
41 | .replace(/^(\-)*(\d+)\.(\d\d).*$/, '$1$2.$3')
42 | ```
43 | :::
44 |
45 | ::: info 三、手机号码格式正则校验
46 |
47 | ```js
48 | /^(13[0-9]|14[01456879]|15[0-35-9]|16[2567]|17[0-8]|18[0-9]|19[0-35-9])\d{8}$/
49 | ```
50 | :::
51 |
52 | ::: info 四、Emoji表情正则校验
53 |
54 | ```js
55 | value = value.replace(/[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF][\u200D|\uFE0F]|[\uD83C|\uD83D|\uD83E][\uDC00-\uDFFF]|[0-9|*|#]\uFE0F\u20E3|[0-9|#]\u20E3|[\u203C-\u3299]\uFE0F\u200D|[\u203C-\u3299]\uFE0F|[\u2122-\u2B55]|\u303D|[\A9|\AE]\u3030|\uA9|\uAE|\u3030/gi, '')
56 | ```
57 | :::
58 |
59 |
--------------------------------------------------------------------------------
/docs/web/wechat/code-watch.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 借助Object.defineProperty实现小程序的watch
3 | description: 微信小程序page没有watch监听,借助Object.defineProperty实现小程序的watch
4 | ---
5 |
6 | # 借助Object.defineProperty实现小程序的watch
7 |
8 | ## 使用示例
9 |
10 | ```js{7-12}
11 | page() {
12 | onLoad(options) {
13 | // 将页面注入到setWatcher中
14 | getApp().setWatcher(this) // [!code --]
15 | },
16 |
17 | watch: {
18 | val(newVal, oldVal) {
19 | console.log('111::', newVal)
20 | },
21 | obj(newVal, oldVal) {
22 | console.log('222::', newVal)
23 | }
24 | }
25 | }
26 | ```
27 |
28 |
29 | ## 封装setWatcher函数
30 |
31 | ```js
32 | // 自定义watch
33 | function setWatcher(page) {
34 | const data = page.data;
35 | const watch = page.watch;
36 | Object.keys(watch).forEach(v => {
37 | const key = v.split('.'); // 将watch中的属性以'.'切分成数组
38 | let nowData = data; // 将data赋值给nowData
39 | for (let i = 0; i < key.length - 1; i++) { // 遍历key数组的元素,除了最后一个!
40 | nowData = nowData[key[i]]; // 将nowData指向它的key属性对象
41 | }
42 | const lastKey = key[key.length - 1];
43 | const watchFun = watch[v].handler || watch[v]; // 兼容带handler和不带handler的两种写法
44 | const deep = watch[v].deep; // 若未设置deep,则为undefine
45 | observe(nowData, lastKey, watchFun, deep, page); // 监听nowData对象的lastKey
46 | })
47 | }
48 |
49 | function observe(obj, key, watchFun, deep, page) {
50 | let val = obj[key];
51 | // 判断deep是true 且 val不能为空 且 typeof val==='object'(数组内数值变化也需要深度监听)
52 | if (deep && val != null && typeof val === 'object') {
53 | Object.keys(val).forEach(childKey => { // 遍历val对象下的每一个key
54 | observe(val, childKey, watchFun, deep, page); // 递归调用监听函数
55 | })
56 | }
57 |
58 | Object.defineProperty(obj, key, {
59 | configurable: true,
60 | enumerable: true,
61 | set: function (value) {
62 | // 用page对象调用,改变函数内this指向,以便this.data访问data内的属性值
63 | watchFun.call(page, value, val); // value是新值,val是旧值
64 | val = value;
65 | if (deep) { // 若是深度监听,重新监听该对象,以便监听其属性。
66 | observe(obj, key, watchFun, deep, page);
67 | }
68 | },
69 | get: function () {
70 | return val;
71 | }
72 | })
73 | }
74 |
75 | module.exports = {
76 | setWatcher
77 | }
78 | ```
79 |
80 | 引入挂载
81 |
82 | ```js
83 | import { setWatcher } from './utils/custom/watch'
84 |
85 | App({
86 | onLaunch() {
87 | },
88 |
89 | // watch 监听的封装,使用需要注入 onLoad(options) { getApp().setWatcher(this) }
90 | setWatcher(pageData) {
91 | setWatcher(pageData)
92 | },
93 |
94 | globalData: {
95 | }
96 | })
97 | ```
--------------------------------------------------------------------------------
/docs/other/tools/link/logo.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: GitHub徽标
3 | description: md文件里边使用GitHub徽标
4 | ---
5 |
6 | # GitHub徽标
7 |
8 | > GitHub Badge 也可以叫它徽章
9 |
10 | `Shields.io` 是一个非常流行的在线服务,它可以帮助你为你的项目生成各种各样的徽章。这些徽章通常被嵌入到项目的 `README` 文件、文档网站或其他地方,用来展示项目的各种信息,比如:
11 |
12 | * **构建状态:** 显示你的项目是否构建成功,以及最近一次构建的时间。
13 |
14 | * **代码覆盖率:** 展示你的代码测试覆盖率,反映代码质量。
15 |
16 | * **许可证信息:** 显示你的项目使用的许可证类型。
17 |
18 | * **依赖版本:** 展示项目所依赖的库和它们的版本。
19 |
20 | * **GitHub 星标数量:** 显示项目在 GitHub 上获得的星标数量。
21 |
22 | * **自定义信息:** 你可以自定义徽章的内容,展示任何你想展示的信息。
23 |
24 | ## Shields.io 的优势
25 |
26 | * **种类丰富:** `Shields.io` 提供了大量的徽章模板,涵盖了项目开发的各个方面。
27 |
28 | * **定制灵活:** 你可以自定义徽章的颜色、样式、大小等,以符合你的项目风格。
29 |
30 | * **易于使用:** `Shields.io` 提供了简单易用的 URL 生成方式,你只需按照格式输入相应的信息,即可生成徽章的 URL。
31 |
32 | * **开源:** `Shields.io` 是一个开源项目,你可以自由地使用和定制它。
33 |
34 | ## GithubLink
35 |
36 | [官网直通车 🚘](https://shields.io)
37 |
38 | * **选择徽章类型:** 在 Shields.io 的官网上,你可以找到各种类型的徽章模板。
39 |
40 | * **自定义徽章:** 根据你的需求,选择合适的颜色、样式和内容。
41 |
42 | * **获取徽章链接:** 系统会生成一个包含徽章信息的 URL。
43 |
44 | * **嵌入到 `Markdown` 中:** 将生成的 URL 嵌入到你的 Markdown 文件中,通常使用以下格式:
45 | - Markdown
46 |
47 | ```md
48 | 
49 | ```
50 |
51 | 
52 |
53 | - html标签
54 |
55 | ```md
56 |
57 | ```
58 |
59 |
60 |
61 | ## 如何使用 Shields.io
62 |
63 | ::: info 使用
64 |
65 | > 支持 .svg,.png等可以自定义
66 |
67 | ```md
68 |
69 | ```
70 |
71 |
72 |
73 | ```html
74 |
75 | ```
76 |
77 |
78 | :::
79 |
80 | ## 为什么使用 Shields.io
81 |
82 | * **提升项目专业度:** 徽章可以让你的项目看起来更加专业和有吸引力。
83 |
84 | * **提供快速信息:** 用户可以通过徽章快速了解项目的相关信息,而无需查看详细的文档。
85 |
86 | * **促进交流:** 徽章可以引发讨论和交流,帮助你获得更多的反馈。
87 |
88 | ## 总结
89 |
90 | `Shields.io` 是一个非常实用的工具,可以帮助你为你的项目增添光彩。通过使用 `Shields.io`,你可以轻松地创建各种各样的徽章,以展示项目的相关信息,提升项目的专业度。
91 |
92 |
--------------------------------------------------------------------------------
/docs/web/basics/reflow-repaint.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 浏览器的回流与重绘
3 | description: 浏览器的回流与重绘
4 | ---
5 |
6 | # 浏览器的回流与重绘
7 |
8 | > 核心就是``标签;只有pdf是可以直接被预览的,word格式需要使用做拼接
9 |
10 |
11 | ## 知识补充
12 |
13 | ::: info `回流必将引起重绘,重绘不一定会引起回流`
14 |
15 | 1.浏览器使用流式布局模型 (Flow Based Layout)
16 | 2.浏览器会把`HTML`解析成`DOM`,把`CSS`解析成`CSSOM`,`DOM`和`CSSOM`合并就产生了`Render` `Tree`。
17 | 3.有了`RenderTree`,我们就知道了所有节点的样式,然后计算他们在页面上的大小和位置,最后把节点绘制到页面上。
18 | 4.由于浏览器使用流式布局,对`Render Tree`的计算通常只需要遍历一次就可以完成,但`table`及其内部元素除外,他们可能需要多次计算,通常要花3倍于同等元素的时间,这也是为什么要避免使用`table`布局的原因之一。
19 |
20 | :::
21 |
22 | ## 回流 (Reflow)
23 | > 也叫重排
24 | ::: info 当`Render Tree`中部分或全部元素的尺寸、结构、或某些属性发生改变时,浏览器重新渲染部分或全部文档的过程称为回流。
25 | > 会导致回流的操作:
26 | ```js
27 | 1.页面首次渲染
28 | 2.浏览器窗口大小发生改变
29 | 3.元素尺寸或位置发生改变
30 | 4.元素内容变化(文字数量或图片大小等等)
31 | 5.元素字体大小变化
32 | 6.添加或者删除可见的DOM元素
33 | 7.激活CSS伪类(例如::hover)
34 | 8.查询某些属性或调用某些方法
35 | ```
36 | > 一些常用且会导致回流的属性和方法:
37 |
38 | `clientWidth`、`clientHeight`、`clientTop`、`clientLeft`
39 | `offsetWidth`、`offsetHeight`、`offsetTop`、`offsetLeft`
40 | `scrollWidth`、`scrollHeight`、`scrollTop`、`scrollLeft`
41 | `scrollIntoView()`、`scrollIntoViewIfNeeded()`
42 | `getComputedStyle()`
43 | `getBoundingClientRect()`
44 | `scrollTo()`
45 | :::
46 |
47 | ## 重绘 (Repaint)
48 |
49 | ::: info 当页面中元素样式的改变并不影响它在文档流中的位置时(例如:`color`、`background-color`、`visibility`等),浏览器会将新样式赋予给元素并重新绘制它,这个过程称为重绘
50 | :::
51 |
52 | ## 性能影响
53 |
54 | ::: info 回流比重绘的代价要更高
55 | 有时即使仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也会产生回流。
56 |
57 | 现代浏览器会对频繁的回流或重绘操作进行优化:
58 |
59 | 浏览器会维护一个队列,把所有引起回流和重绘的操作放入队列中,如果队列中的任务数量或者时间间隔达到一个阈值的,浏览器就会将队列清空,进行一次批处理,这样可以把多次回流和重绘变成一次。
60 |
61 | 当你访问以下属性或方法时,浏览器会立刻清空队列:
62 |
63 | `clientWidth`、`clientHeight`、`clientTop`、`clientLeft`
64 | `offsetWidth`、`offsetHeight`、`offsetTop`、`offsetLeft`
65 | `scrollWidth`、`scrollHeight`、`scrollTop`、`scrollLeft`
66 | `width`、`height`
67 | `getComputedStyle()`
68 | `getBoundingClientRect()`
69 |
70 | 因为队列中可能会有影响到这些属性或方法返回值的操作,即使你希望获取的信息与队列中操作引发的改变无关,浏览器也会强行清空队列,确保你拿到的值是最精确的。
71 | :::
72 |
73 | ## 如何避免
74 |
75 | ::: info CSS
76 | 避免使用`table`布局。
77 | 尽可能在`DOM`树的最末端改变`class`。
78 | 避免设置多层内联样式。
79 | 将动画效果应用到`position`属性为`absolute`或`fixed`的元素上。
80 | 避免使用`CSS`表达式(例如:`calc()`)。
81 | :::
82 |
83 | ::: info JavaScript
84 | 避免频繁操作样式,最好一次性重写`style`属性,或者将样式列表定义为`class`并一次性更改`class`属性。
85 | 避免频繁操作DOM,创建一个`documentFragment`,在它上面应用所有DOM操作,最后再把它添加到文档中。
86 | 也可以先为元素设置`display: none`,操作结束后再把它显示出来。因为在`display`属性为`none`的元素上进行的`DOM`操作不会引发回流和重绘。
87 | 避免频繁读取会引发回流/重绘的属性,如果确实需要多次使用,就用一个变量缓存起来。
88 | 对具有复杂动画的元素使用绝对定位,使它脱离文档流,否则会引起父元素及后续元素频繁回流。
89 | :::
--------------------------------------------------------------------------------
/docs/other/system/linux/release.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: linux发行版
3 | description: linux发行版介绍说明,常见的linux发行版有哪些,以及使用场景
4 | outline: [2, 3]
5 | ---
6 |
7 | # 什么是linux发行版
8 |
9 | `Linux` 发行版,为一般用户预先集成好的Linux操作系统及各种应用软件。一般用户不需要重新编译,在直接安装之后,只需要小幅度更改设置就可以使用,通常以软件包管理系统来进行应用软件的管理。
10 |
11 | ## 国内常见的linux发行版
12 |
13 | * `Debian`
14 |
15 | 稳定
16 |
17 | * `Ubuntu`
18 |
19 | 对开发者友好
20 |
21 | * `CentOS`
22 |
23 | CentOS宣布其传统版本将 `不再继续维护`
24 |
25 | 国内众多公司都有在使用
26 |
27 |
28 | ## Debian
29 |
30 | * 特点:
31 |
32 | * **稳定性**:Debian以稳定性著称,其稳定版本(stable release)经过长时间测试,适合生产环境。
33 |
34 | * **安全性**:Debian拥有严格的软件包审核流程,这有助于提高系统的安全性。
35 |
36 | * **灵活性**:Debian提供了多个分支,包括stable、testing和unstable,用户可以根据需求选择适合自己的分支。
37 |
38 | * **开源原则**:Debian严格遵循自由软件基金会的原则,所有软件包都是自由软件。
39 |
40 | * 适用场景:
41 |
42 | * **关键业务应用**:对于需要高度稳定性的关键业务,Debian是一个不错的选择。
43 |
44 | * **安全敏感环境**:Debian因其严谨的安全策略而成为安全敏感环境的理想选择。
45 |
46 | * **自定义部署**:Debian的灵活性使其适用于各种自定义部署方案。
47 |
48 | ## Ubuntu
49 |
50 | * 特点:
51 |
52 | * **广泛的社区支持**:Ubuntu拥有庞大的用户群和活跃的社区,这使得获取技术支持和解决问题变得相对容易。
53 |
54 | * **软件包丰富**:Ubuntu使用APT作为包管理系统,这意味着用户可以从丰富的软件库中选择需要的软件包进行安装。
55 |
56 | * **更新频繁**:Ubuntu提供短期支持(LTS)和长期支持版本,其中LTS版本每两年发布一次,提供长达五年的支持。
57 |
58 | * **易于使用**:Ubuntu以其用户友好的界面和文档闻名,即使是对Linux不太熟悉的用户也能快速上手。
59 |
60 | * 适用场景:
61 |
62 | * **开发者环境**:Ubuntu非常适合开发者,尤其是Web开发、移动应用开发等领域。
63 |
64 | * **教育和研究机构**:由于其易用性和丰富的文档,Ubuntu在教育领域被广泛应用。
65 |
66 | * **云计算平台**:许多云服务提供商默认支持Ubuntu,因此在云环境中非常流行。
67 |
68 | ## CentOS
69 |
70 | * 特点:
71 |
72 | * **稳定性高**: 基于Red Hat Enterprise Linux (RHEL),经过长时间的测试和验证,系统稳定性非常高,适合用于生产环境。
73 |
74 | * **社区活跃**: 拥有庞大的中文社区,资料丰富,问题容易解决。
75 |
76 | * **兼容性好**: 与RHEL高度兼容,很多企业级软件都支持CentOS。
77 |
78 | * 缺点:
79 |
80 | * **停止更新**: CentOS宣布其传统版本将不再继续维护。
81 |
82 | * **更新较慢**: 由于注重稳定性,更新频率相对较慢,可能导致一些新软件或功能的缺失。
83 |
84 | * **桌面环境不完善**: CentOS的桌面环境相对简单,不如Ubuntu等发行版功能丰富。
85 |
86 | ## 总结
87 |
88 | | 特性 | CentOS | Ubuntu | Debian |
89 | | -- | -- | -- | -- |
90 | | 稳定性 | 高 | 中 | 高 |
91 | | 易用性 | 中 | 高 | 中 |
92 | | 软件源 | 丰富 | 非常丰富 | 丰富 |
93 | | 社区 | 活跃 | 非常活跃 | 活跃 |
94 | | 中文资料 | 丰富 | 丰富 | 较少 |
95 |
96 | * **选择建议:**
97 |
98 | * **注重稳定性,适合生产环境**: CentOS或Debian
99 | * **易用性好,适合新手**: Ubuntu
100 | * **追求自由度和配置灵活度**: Debian
101 |
102 | * **选择时还需要考虑以下因素:**
103 |
104 | * **使用场景**: 不同的使用场景对系统的要求不同。
105 | * **个人偏好**: 不同的用户有不同的偏好。
106 | * **团队技术水平**: 团队的Linux技术水平也会影响选择。
107 |
108 | 总结来说,CentOS、Ubuntu和Debian都是优秀的Linux发行版,没有绝对的好坏,只有最适合你的。
109 |
110 | ### 温馨提示
111 |
112 | * 以上对比仅供参考,实际情况可能有所不同。
113 |
114 | * 建议根据自己的实际需求进行选择。
115 |
116 | * 可以尝试在虚拟机中安装不同的发行版,体验一下再做决定。
--------------------------------------------------------------------------------
/docs/web/basics/code-promise.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Promise理解
3 | description: 认识Promise、理解Promise、使用Promise
4 | outline: [2, 3]
5 | ---
6 |
7 | # Promise理解
8 |
9 | ## 示例
10 |
11 | ::: info 模拟请求:
12 | {{ disabled ? '等待请求中...' : '模拟请求' }}
13 | :::
14 |
15 | ## Promise说明
16 |
17 | ### Promise是什么
18 | * Promise 是一个对象,也是一个构造函数
19 | * Promise 对象是 JavaScript 的异步操作解决方案,为异步操作提供统一接口。
20 |
21 | ### 三种状态
22 |
23 | * 等待中(pending):初始状态,既没有被兑现,也没有被拒绝 常见于(网络请求,网速慢的情况下)。
24 | * 已兑现(fulfilled):意味着操作成功完成 常见于(网络请求成功的情况下)。
25 | * 已拒绝(rejected):意味着操作失败 常见于(网络请求失败的情况下)
26 |
27 | ### 链式调用
28 |
29 | ``` js
30 | Promise.prototype.then()
31 | (常见于)接口返回code==200也只有接口返回状态是200才会进入.then()
32 |
33 | Promise.prototype.catch()
34 | (常见于)接口返回code!=200.catch()
35 |
36 | Promise.prototype.finally()
37 | (现在比较流行做节流处理)接口返回失败和成功都会进入.finally()
38 | ```
39 |
40 | ## 示例源代码
41 |
42 | ::: info 接口请求示范
43 | ``` js
44 | {{ disabled ? '等待请求中...' : '模拟请求' }}
45 |
46 | function newButton() {
47 | // 开启阀门,只有按钮事件执行完毕才会继续执行
48 | disabled.value = true
49 | getDataQuery()
50 | .then(res => {
51 | ElMessage.success(res as string)
52 | })
53 | .catch(() => {
54 | ElMessage.error('接口请求失败')
55 | })
56 | .finally(() => {
57 | disabled.value = false
58 | })
59 | }
60 |
61 | function getDataQuery() {
62 | return new Promise((resolve, reject) => {
63 | setTimeout(() => {
64 | resolve('接口请求成功')
65 | }, 2000)
66 | })
67 | }
68 | ```
69 | :::
70 |
71 |
106 |
107 |
112 |
--------------------------------------------------------------------------------
/docs/.vitepress/config/nav.js:
--------------------------------------------------------------------------------
1 | export default [
2 | {
3 | text: 'chatGPT',
4 | link: '/chatgpt/search.md',
5 | },
6 | {
7 | text: '前端',
8 | items: [
9 | {
10 | text: 'Vue',
11 | link: '/web/vue/plugins',
12 | },
13 | {
14 | text: 'Harmony',
15 | link: '/web/harmony/distinction',
16 | },
17 | {
18 | text: 'WeChat',
19 | link: '/web/wechat/code-watch',
20 | },
21 | {
22 | text: 'H5',
23 | link: '/web/h5/font-deformation',
24 | },
25 | {
26 | text: 'html + cs + js',
27 | link: '/web/basics/regExp',
28 | },
29 | {
30 | text: '前端知识',
31 | link: '/web/knowledge/npm-registry',
32 | },
33 | ],
34 | },
35 | {
36 | text: '后端',
37 | items: [
38 | {
39 | text: '安装软件',
40 | link: '/api/install-software/docker/index.md',
41 | },
42 | {
43 | text: 'NodeJs',
44 | link: '/api/nodejs/sql.md',
45 | },
46 | ],
47 | },
48 | {
49 | text: '其他',
50 | items: [
51 | {
52 | text: '操作系统',
53 | link: '/other/system/win/clear-icon.md',
54 | },
55 | {
56 | text: '开发工具集',
57 | link: '/other/tools/collect.md',
58 | },
59 | {
60 | text: '如何搭建博客',
61 | link: '/other/blog/basics/write.md',
62 | },
63 | ],
64 | },
65 | {
66 | text: '开源',
67 | items: [
68 | {
69 | text: '开源 Api 接口',
70 | link: 'https://www.openapijs.com',
71 | },
72 | {
73 | text: 'Monorepo开发策略',
74 | link: 'https://www.mnrp.top',
75 | },
76 | {
77 | text: '518套简历模版',
78 | link: 'https://github.com/ytlyy1773/curriculum-vitae',
79 | }
80 | ],
81 | },
82 | {
83 | text: '作者相关',
84 | items: [
85 | {
86 | text: '简历',
87 | link: 'http://www.jwblog.cn/resume.pdf',
88 | },
89 | {
90 | text: '联系作者',
91 | link: '/oneself/author.md',
92 | },
93 | {
94 | text: '微信小程序',
95 | link: '/oneself/author-wechat.md',
96 | },
97 | ],
98 | },
99 | ];
100 |
--------------------------------------------------------------------------------
/docs/web/vue/upgradation/up-vite.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Vue2项目打包方式webpack升级vite
3 | description: Vue2项目打包方式webpack升级vite
4 | outline: [2, 3]
5 | ---
6 |
7 | # Vue2项目打包方式webpack升级vite
8 |
9 | ## 配置文件
10 |
11 | ::: info vite.config.ts
12 | ::: details 源代码
13 | <<< ./vite.config.ts
14 | :::
15 |
16 | ## 升级结果
17 |
18 | - 升级完成项目启动由约3min多减少约2s内
19 | - 代码更新效果时间约10s减少到无感
20 | - 代码包体积减少1/4以上
21 | - 打包时间减少2/5左右
22 |
23 | ## 升级流程
24 |
25 | ### 一、安装依赖
26 |
27 | ```js
28 | npm install vue@2.7.14
29 | npm install vite
30 | npm install vite-plugin-vue2
31 | npm install vite-plugin-svg-sprite
32 | npm install vitejs/plugin-legacy
33 | npm install -D sass
34 | ```
35 |
36 | | plugin | 说明 |
37 | | ------------- |:-------------:|
38 | | vue@2.7.14 | vue2已经是最终版了,直接升级到2.7.14,这样才可以兼容vite同样
elementUI应该也是最终版了,建议升级最终版 |
39 | | vite | 使用vite打包 |
40 | | vite-plugin-vue2 | 兼容vue2语法 |
41 | | vitejs/plugin-vue2-jsx | 兼容vue2的jsx语法 |
42 | | vitejs/plugin-legacy | 传统浏览器兼容 |
43 | | sass | vite打包需要安装sass,版本过低的sass需要升级sass版本 |
44 |
45 | ### 二、修改打包命令
46 |
47 | ::: info `package.json` 文件
48 | ```json
49 | "scripts": {
50 | "dev": "vite --mode dev",
51 | "build:dev": "vite build --mode dev",
52 | "build:test": "vite build --mode test"
53 | },
54 | ```
55 | :::
56 |
57 | ### 三、修改vite打包入口
58 |
59 | ::: info `index.html` 修改入口文件
60 | ```html
61 |
62 | ```
63 | :::
64 |
65 | ### 四、根目录新建vite.config.ts文件
66 |
67 | [配置文件请参考 🚘](/web/vue/upgradation/up-vite.html#配置文件)
68 |
69 | ## 遇到的问题
70 |
71 | ### css的 `/deep/`
72 |
73 | * vite打包css不可以使用sass的 `/deep/` 语法
74 | * 全局替换成 `::v-deep`
75 |
76 | ### webpack中使用require引入文件
77 |
78 | vite中需要改成 `import` 引入
79 |
80 | ### svg字体图标的批量导入变更
81 |
82 | ```js
83 | const req = require.context('./svg', false, /\.svg$/)
84 | const requireAll = requireContext => requireContext.keys().map(requireContext)
85 | requireAll(req)
86 | ```
87 |
88 |
89 | ### 盗版浏览器
90 | 升级的项目是对外的,遇到了 `2345浏览器非官网版本` 白屏
91 |
92 | 报错Uncaught ReferenceError: globalThis is not defined
93 |
94 | 粗暴的解决方案(暂未有其他解决方案)
95 |
96 | ```js-vue
97 | // 在index.html文件添加
98 |
103 | ```
104 |
105 |
106 | ## vue2生态升级使用
107 |
108 | ### vue-router的使用
109 |
110 | > vue2可以使用`ref`和`reactive`,没有使用`proxy`实现,还是用了`defineProperty`的`getter, setter`
111 |
112 | ```js-vue{2}
113 |
118 | ```
119 |
120 | 在`vue2.7 + vite`中使用`vue-router`
121 |
122 | ```js-vue{2}
123 |
127 | ```
--------------------------------------------------------------------------------
/docs/other/blog/basics/write.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 怎么写博客
3 | description: 搭建个人博客教程,使用vitepress编写个人博客项目
4 | outline: [2, 3]
5 | ---
6 |
7 | # 怎么写博客
8 |
9 | ## 个人经验
10 | * 一口吃不成一个胖子。第一次写建议想什么写什么,等写的多了再进行 `整合规划`
11 | * `收费项目` 建议用便宜实惠的产品,等博客质量积累起来再去适当 `氪金升级`
12 | * 博客是一个不断积累的过程,可以借鉴其他,但不建议完全照搬,要有自己的想法
13 | * 可以多参考其他 `开源博客` 的内容。[优质博客集 🚘](https://github.com/foru17/front-end-collect?tab=readme-ov-file)
14 |
15 | ### 我的博客大概费用
16 |
17 | > 如果不想花钱可以使用 [`github pages`](/other/blog/up/use-page.html)
18 |
19 | | 项目 | 必要 | 费用 | 备注 |
20 | | :--- | :--- | :--- | :--- |
21 | | 云服务器 | 必要 | `100-260`不等/年 | 建议博客写的适量再去购买,而不是什么都没写就先买服务器,`千里之行始于足下` |
22 | | 域名 | 必要 | `50`左右/年 | --- |
23 | | ssl证书 | 非必需 | `100`左右/3年 | 建议买便宜的就行,也可以不停的用免费适用3个月的,到期继续申请免费试用3个月 |
24 |
25 | ## 常见博客框架
26 |
27 | * `vitepress`
28 | > 由 Vite 和 Vue 驱动的静态站点生成器
29 | * `WordPress`
30 | > 最流行的博客框架,功能丰富、插件众多,适合各种类型的博客。
31 | * `Ghost`
32 | > 轻量级博客框架,注重写作体验,适合个人博客。
33 | * `Jekyll`
34 | > 静态博客框架,速度快、易于部署,适合技术博客。
35 | * `Hexo`
36 | > 基于 Node.js 的静态博客框架,易于使用,适合个人博客和技术博客。
37 | * `Hugo`
38 | > 基于 Go 语言的静态博客框架,速度快、功能强大,适合各种类型的博客。
39 |
40 | ## 技术选型
41 | * `vitepress`:博客框架推荐使用
42 | * `github`:代码仓库强烈推荐使用github
43 | - 多样化的github actions,可以做到`CI/CD`
44 | - 支持github pages
45 | - 后续升级提升都是基于github
46 |
47 | ## vitepress
48 | > 这里我们选择 `vue` 团队出品的 `vitepress`
49 |
50 | [官网直通车 🚘](https://vitepress.dev/zh/)
51 |
52 | ### 需要了解什么?
53 |
54 | > vitepress采用md为主要书写语言,vue语言多为辅助
55 |
56 | 1. `Markdown` 语法
57 | * `markdown` 程序员的必修课
58 | * 轻量级标记语言,极易上手
59 | * 适用所有开发者,代码托管平台 `README.md` 文件语言
60 | * [官方教程 🚘](https://docs.github.com/zh/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/quickstart-for-writing-on-github) 或 自行访问[GitHub 文档](https://docs.github.com/zh) 选择 "入门" > "在 GitHub 上写入"
61 | * md教程推荐 [菜鸟教程 🚘](https://www.runoob.com/markdown/md-tutorial.html)
62 | 2. `Vue` 语法
63 | * [vue官网 🚘](https://cn.vuejs.org/)
64 | 3. `Node` 环境
65 | * vitepress是一个前端框架,需要node环境
66 |
67 | ### 本地开发需要的环境
68 |
69 | - `Node.js` 18 及以上版本。
70 | - 支持 `Markdown` 语法的编辑器,推荐 `Vscode`
71 |
72 | ### 进入开发
73 |
74 | > `vitepress` 官网有详细的操作流程和初始化模版,直接参考官网
75 |
76 | ## 遇到的问题
77 |
78 | > 略微区别于开发单页面应用程序的点
79 |
80 | ### 不同环境打包的问题
81 |
82 | * 正常的环境配置是 `不会生效` 的需要做特殊处理
83 | * github actions的运行环境默认是 Linux
84 | * 这里用 `github actions` 打包举例
85 |
86 | 问题描述:本地使用 `pnpm run build:github` 打包没问题,但是配置了自动化命令的时候就不行了
87 |
88 | ::: tip
89 | * 添加项目依赖 `cross-env`,解决跨平台环境之间的差异而导致的问题
90 | * 修改 `docs/.vitepress/config.mts` 文件下的 `base` 属性
91 | > `deploy.yml` 这是一个github pages的自动化打包配置文件,存放于 `.github/workflows/` 目录下
92 | ```ts
93 | // 环境变量的控制来源子deploy.yml文件
94 | base: process.env.BUILD_ENV === "github" ? "/blog/" : "/"
95 | ```
96 | :::
97 |
98 | 我们可以添加一条命令 `build:github` 本地看github打包效果
99 |
100 | > 验证过后可以删除这个 `build:github` 的命令
101 |
102 | ```sh
103 | "scripts": {
104 | "dev": "vitepress dev docs",
105 | "build": "vitepress build docs",
106 | "build:github": "cross-env BUILD_ENV=github vitepress build docs",
107 | "preview": "vitepress preview docs"
108 | }
109 | ```
110 |
111 | ### 禁止使用index.md
112 |
113 | * 除了首页使用index,其余一律不使用index
114 | * 使用index是一个重定向的目录,seo不会收录这样的目录
115 |
116 | [具体解释请参考seo 🚘](/other/blog/basics/seo-info.html)
117 |
--------------------------------------------------------------------------------
/docs/web/vue/upload-image/upload.js:
--------------------------------------------------------------------------------
1 | import { message } from 'ant-design-vue'
2 |
3 | export const IMAGE_TYPE = ['jpg', 'jpeg', 'png', 'gif']
4 | export const typeMes = '.jpg、.jpeg、.png、.gif'
5 |
6 | // 全局引入,二次封装,只限于上传图片
7 | export function uploadImage() {
8 | return new Promise((resolve, reject) => {
9 | uploadWhole({
10 | multiple: true,
11 | accept: 'image/*',
12 | typeArr: IMAGE_TYPE
13 | })
14 | .then(fileList => {
15 | if (judgeImage(fileList, IMAGE_TYPE)) {
16 | // 临时本地回显,后续调用阿里云对接第三方上传
17 | resolve(fileList)
18 | } else {
19 | message.info(`上传文件类型需满足${typeMes}`)
20 | reject(`上传文件类型需满足${typeMes}`)
21 | }
22 | })
23 | .catch(err => {
24 | reject(err)
25 | })
26 | })
27 | }
28 |
29 | // 核心:上传功能
30 | export function uploadWhole(options = {}) {
31 | return new Promise((resolve, reject) => {
32 | const config = {
33 | accept: '*', // 接受的文件类型
34 | typeArr: [], // 接受的文件类型,格式列表
35 | multiple: false, // 是否多选
36 | size: 10240, // 文件大小限制,单位是kb
37 | limit: 5, // 可选文件个数限制
38 | ...options
39 | }
40 | const input = document.createElement('input')
41 | input.type = 'file'
42 | input.multiple = config.multiple
43 | input.accept = config.accept
44 | input.style.width = '0'
45 | input.style.height = '0'
46 | document.body.appendChild(input)
47 | input.click()
48 | input.oninput = e => {
49 | // 必须做一次拷贝
50 | const list = [...e.target.files]
51 | check(list, config)
52 | .then(() => {
53 | resolve(list)
54 | })
55 | .catch(err => {
56 | message.error(err)
57 | reject(err)
58 | })
59 | }
60 | window.addEventListener(
61 | 'focus',
62 | () => {
63 | setTimeout(() => {
64 | if (!input.value) {
65 | document.body.removeChild(input)
66 | reject('用户取消上传')
67 | }
68 | }, 500)
69 | },
70 | { once: true }
71 | )
72 | })
73 | }
74 |
75 | // 判断是不是图片
76 | function judgeImage(file, typeList = []) {
77 | // file:要判断的文件,typeList:非必需,上传文件类型数组
78 | const list = Array.from(file)
79 | let arr = []
80 | list.forEach(ele => {
81 | arr.push(filterImage(ele))
82 | })
83 | const fileList = arr.filter(ele => {
84 | return typeList.includes(ele)
85 | })
86 | const ifT = arr.length === fileList.length ? true : false
87 | return ifT
88 | }
89 |
90 | // 获取文件类型
91 | export function filterImage(item) {
92 | return item.name.split('.')[item.name.split('.').length - 1]?.toLowerCase()
93 | }
94 |
95 | // 校验
96 | function check(list, config) {
97 | return new Promise((resolve, reject) => {
98 | // 长度校验
99 | if (list.length > config.limit) {
100 | return reject(`上传数量超过${config.limit}个`)
101 | }
102 | // accept校验...
103 | // size校验...
104 | resolve('校验通过')
105 | })
106 | }
--------------------------------------------------------------------------------
/docs/web/vue/dialog/dialogModule.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | ×
4 |
5 | {{ title }}
6 |
7 |
10 |
11 |
{{ LeftText }}
12 |
{{ RightText }}
13 |
14 |
15 |
16 |
17 |
101 |
102 |
135 |
--------------------------------------------------------------------------------
/docs/api/install-software/mysql.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: mac安装mysql
3 | description: 包含Mac、Windows、Linux不同系统安装MySQL详细教程
4 | outline: [2, 3]
5 | ---
6 |
7 | # 安装mysql
8 |
9 | ## mysql常用命令
10 |
11 | ::: info 系统命令
12 | * **Linux**
13 |
14 | 启动 MySQL 服务:
15 | ```sh
16 | sudo systemctl start mysql
17 | ```
18 |
19 | 关闭 MySQL 服务:
20 | ```sh
21 | sudo systemctl stop mysql
22 | ```
23 |
24 | 重启 MySQL 服务:
25 | ```sh
26 | sudo systemctl restart mysql
27 | ```
28 |
29 | * **Mac**
30 |
31 | 启动 MySQL 服务:
32 | ```sh
33 | sudo /usr/local/mysql/support-files/mysql.server start
34 | ```
35 |
36 | 关闭 MySQL 服务:
37 | ```sh
38 | sudo /usr/local/mysql/support-files/mysql.server stop
39 | ```
40 |
41 | 重启 MySQL 服务:
42 | ```sh
43 | sudo /usr/local/mysql/support-files/mysql.server restart
44 | ```
45 |
46 | * **Windos**
47 |
48 | 启动 MySQL 服务:
49 | ```sh
50 | net start mysql
51 | ```
52 |
53 | 关闭 MySQL 服务:
54 | ```sh
55 | net stop mysql
56 | ```
57 |
58 | 重启 MySQL 服务:
59 | ```sh
60 | sudo /usr/local/mysql/support-files/mysql.server restart
61 | ```
62 | :::
63 |
64 | ::: tip 通用
65 | * 连接数据库
66 | ```sh
67 | mysql -u root -p
68 | ```
69 | :::
70 |
71 | ## mac安装mysql
72 |
73 | ### 下载链接
74 |
75 | [官网下载链接 🚘](https://downloads.mysql.com/archives/community/)
76 |
77 | ### 安装步骤
78 |
79 | * 选择自己电脑对应的版本和系统
80 |
81 | 
82 |
83 | * 点击软件安装
84 |
85 | * 安装报错 无法打开“***App”,因为它不是从App Store下载
86 |
87 | [查看解决方案 🚘](/other/system/mac/install-error.html)
88 |
89 | * 安装mysql,设置密码(大于8位数)
90 |
91 | 
92 |
93 | * 一直点击下一步同意即可
94 |
95 | ### 配置mysql环境变量
96 |
97 | * 打开终端,修改环境变量
98 |
99 | ```sh
100 | vim .bash_profile
101 | ```
102 |
103 | 加入:
104 |
105 | ```ini
106 | export PATH=${PATH}:/usr/local/mysql/bin
107 | ```
108 |
109 | .zshrc文件:
110 |
111 | ```sh
112 | vim ~/.zshrc
113 | ```
114 |
115 | 也是加入:
116 |
117 | ```ini
118 | export PATH=${PATH}:/usr/local/mysql/bin
119 | ```
120 |
121 | * 然后执行命令使配置生效
122 |
123 | ```sh
124 | source ~/.zshrc
125 | ```
126 |
127 | * 查看mysql安装生效
128 | - 需要 `重新` 打开一个终端再执行命令
129 | - 执行 `mysql --version` 出现相应的mysql版本号就行
130 |
131 | ### 使用mysql报错
132 |
133 | * 启动mysql报错
134 |
135 | ::: info 启动mysql报错信息
136 | ERROR 2002 (HY000): Can't connect to local MySQL server through socket '/tmp/mysql.sock'
137 | :::
138 |
139 | 确保MySQL配置文件路径正确。打开配置文件并确认以下内容:
140 |
141 | ```sh
142 | sudo nano /usr/local/mysql/my.cnf
143 | ```
144 |
145 | 添加或确认以下内容:
146 |
147 | ```ini
148 | [mysqld]
149 | socket = /usr/local/mysql/mysql.sock
150 | datadir = /usr/local/mysql/data
151 | port = 3306
152 |
153 | [client]
154 | socket = /usr/local/mysql/mysql.sock
155 | port = 3306
156 | ```
157 |
158 |
159 | * 连接mysql报错
160 |
161 | ::: info 启动mysql报错信息
162 | ERROR! The server quit without updating PID file (/usr/local/mysql/data/jiangwandeMac-mini.local.pid).
163 | :::
164 |
165 | 确保MySQL数据目录及其内容具有正确的权限和所有者
166 |
167 | ```sh
168 | sudo chown -R _mysql:_mysql /usr/local/mysql/data
169 | sudo chmod -R 755 /usr/local/mysql/data
170 | ```
--------------------------------------------------------------------------------
/docs/other/blog/up/config-algolia.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: vitepress配置algolia
3 | description: 在vitepress项目里边怎么配置algolia
4 | outline: [2, 3]
5 | ---
6 |
7 | # vitepress配置algolia
8 |
9 | ## 申请algolia资源
10 |
11 | ### 注意事项
12 |
13 | * 您必须是该网站的所有者,或至少有更新其内容的权限
14 | * 网站必须是一个开源项目或技术博客的技术文档
15 | * 第一次注册可能需要一定时间通过,注意邮箱查收相关邮件同意注册
16 |
17 | ### 注册algolia账号
18 |
19 | [algolia官网 🚘](https://dashboard.algolia.com)
20 |
21 | 点击控制台 `Apis keys` 申请Apis keys
22 |
23 | 
24 |
25 | 复制我们需要的内容到vitepress配置文件夹里边
26 |
27 | 
28 |
29 | - `Application ID` 填入 `options.appId`
30 | - `Search-Only API Key` 填入 `options.apiKey`
31 |
32 | ## 配置使用algolia
33 |
34 | > algolia可能需要很久才会自动索引,可以尝试手动索引网站
35 |
36 | ::: tip config.mts/defineConfig配置
37 | ```ts
38 | {
39 | search:
40 | process.env.BUILD_ENV === "github"
41 | ? {
42 | provider: "local",
43 | }
44 | : {
45 | provider: "algolia",
46 | options: {
47 | appId: "2T********3X", // 应用程序 ID
48 | apiKey: "************408f9c****", // 公钥
49 | indexName: "blog",
50 | placeholder: "请输入关键词",
51 | },
52 | },
53 | }
54 | ```
55 | :::
56 |
57 | ## 推送索引自动化脚本
58 |
59 | * 项目根目录下新建algolia的配置文件 `crawlerConfig.json`
60 |
61 | ::: details `crawlerConfig.json` 配置文件
62 | ```json
63 | {
64 | "index_name": "一条懒羊羊",
65 | "start_urls": ["http://www.jwblog.cn"],
66 | "rateLimit": 8,
67 | "maxDepth": 10,
68 | "selectors": {
69 | "lvl0": {
70 | "selector": "",
71 | "defaultValue": "Documentation"
72 | },
73 | "lvl1": ".content h1",
74 | "lvl2": ".content h2",
75 | "lvl3": ".content h3",
76 | "lvl4": ".content h4",
77 | "lvl5": ".content h5",
78 | "content": ".content p, .content li",
79 | "lang": {
80 | "selector": "/html/@lang",
81 | "type": "xpath",
82 | "global": true
83 | }
84 | },
85 | "selectors_exclude": [
86 | "aside",
87 | ".page-footer",
88 | ".next-and-prev-link",
89 | ".table-of-contents"
90 | ],
91 | "custom_settings": {
92 | "attributesForFaceting": ["lang", "tags"]
93 | },
94 | "js_render": true
95 | }
96 | ```
97 | :::
98 |
99 | > 实现自动推送索引到algolia
100 |
101 | * .github/workflows/目录下新建 `algolia.yml` 文件
102 |
103 | ::: info algolia.yml
104 | ```yml
105 | name: algolia # 工作流名称
106 |
107 | on:
108 | push:
109 | branches:
110 | - master # 触发条件:当推送到 master 分支时触发此工作流
111 |
112 | jobs:
113 | algolia:
114 | runs-on: ubuntu-latest # 在最新版本的 Ubuntu 环境中运行此作业
115 |
116 | steps:
117 | - uses: actions/checkout@v3 # 步骤1:使用 GitHub 官方的动作检出代码库
118 |
119 | - name: Get the content of algolia.json as config # 步骤2:读取 crawlerConfig.json 文件内容作为配置
120 | id: algolia_config
121 | run: echo "config=$(cat crawlerConfig.json | jq -r tostring)" >> $GITHUB_OUTPUT
122 | # 读取 crawlerConfig.json 文件的内容并转换为字符串格式,然后将其保存到 GitHub Actions 的输出变量中
123 |
124 | - name: Push indices to Algolia # 步骤3:将索引推送到 Algolia
125 | uses: signcl/docsearch-scraper-action@master
126 | env:
127 | APPLICATION_ID: ${{ secrets.APPLICATION_ID }} # 从 GitHub Secrets 中读取 Algolia 应用程序 ID
128 | API_KEY: ${{ secrets.API_KEY }} # 从 GitHub Secrets 中读取 Algolia API 密钥
129 | CONFIG: ${{ steps.algolia_config.outputs.config }} # 使用上一步骤中读取的配置
130 | # 使用 signcl/docsearch-scraper-action 动作,将配置推送到 Algolia
131 |
132 | ```
133 | :::
134 |
--------------------------------------------------------------------------------
/docs/chatGPT/gptApi.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
🥷
6 |
{{ item.text }}
7 |
8 |
9 |
💻
10 |
{{ item.result }}
11 |
12 |
13 |
14 |
15 |
23 |
24 | {{ loading ? "请求中..." : "⏎" }}
25 |
26 |
27 |
28 |
29 |
84 |
140 |
--------------------------------------------------------------------------------
/docs/other/blog/up/use-github-actions.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 如何使用github actions自动化工作流
3 | description: linux云服务器使用教程
4 | outline: [2, 3]
5 | ---
6 |
7 | # 如何使用github actions自动化工作流
8 |
9 | ## github actions是什么
10 |
11 | GitHub Actions 是一种在 GitHub 上自动执行任务的平台。它允许你将你的工作流自动化,例如:
12 |
13 | * 构建和测试代码
14 | * 部署应用程序
15 | * 发布软件包
16 | * 协作开发
17 |
18 | 以下是使用 GitHub Actions 的一些优势:
19 |
20 | * 自动化任务: 消除手动任务,提高效率。
21 | * 提高代码质量: 自动化构建、测试和部署过程,减少错误和提升代码质量。
22 | * 加速开发流程: 自动化流程,让开发人员专注于更重要的任务。
23 | * 提升团队协作: 方便团队成员在工作流中协作,提高效率。
24 | * 开源和易于使用: GitHub Actions 是开源的,并且提供易于使用的界面。
25 |
26 | ## 已经实现的github actions
27 |
28 | * 同步代码仓库内容到 `gitee` 仓库
29 | * 同步内容索引更新到 `algolia`
30 | * 代码提交自动打包部署 `github pages`
31 | * 代码提交 `linux` 服务器自动打包部署
32 |
33 | ## 怎么配置GitHub Secrets
34 | 1. 进入GitHub仓库设置:
35 | * 打开你的GitHub仓库。
36 | * 点击右上角的 Settings。
37 |
38 | 2. 添加Secrets:
39 | * 在左侧栏中找到 Secrets and variables,然后选择 Actions。
40 | * 点击 New repository secret 来添加新的Secret。
41 |
42 | ### Secrets的示例内容
43 |
44 | > 假设你有一个服务器,IP地址为 192.168.1.100,用户名为 root,密码为 your_password,你需要将这些信息添加为Secrets:
45 |
46 | 1. 添加SSH_HOST:
47 | * Name: SSH_HOST
48 | * Value: 192.168.1.100
49 |
50 | 2. 添加SSH_USER:
51 | * Name: SSH_USER
52 | * Value: root
53 |
54 | 3. 添加SSH_PASSWORD:
55 | * Name: SSH_PASSWORD
56 | * Value: your_password
57 |
58 | ## 执行linux系统脚本
59 |
60 | > 这里假设服务器的脚本已经实现相应的功能了:自动拉取代码、自动打包、自动更新nginx
61 |
62 | 实现效果
63 |
64 | * 编写 `github actions` 配置文件,提交代码自动执行服务器脚本
65 | * 作者只需要关注代码提交,其余均是自动化脚本
66 |
67 | 在你的项目根目录下创建一个 `.github/workflows` 目录,并在其中创建一个 `.yml` 文件来定义GitHub Actions工作流,例如 `run_script.yml`。
68 |
69 | * 由于GitHub Actions运行在Ubuntu环境中,而Ubuntu使用apt-get包管理器而不是yum。为了在Ubuntu环境中运行并安装sshpass和openssh-client,你需要使用适合的包管理器和命令。
70 | * 请注意,使用密码认证相对 `不太安全`,因此要确保密码的复杂性和保密性。同时,为了避免密码泄露,不要在代码中直接包含密码,而是通过 `GitHub Secrets` 来管理。
71 |
72 | ```sh
73 | # 保持命令运行:即使用户退出会话,使用 `nohup` 运行的命令也会继续运行。
74 | nohup /root/update.sh > /root/update_output.log 2>&1
75 | ```
76 |
77 | ::: info run_script.yml 文件
78 | ```yml
79 | name: Run Root Script # 工作流名称
80 |
81 | on:
82 | push:
83 | branches:
84 | - master # 监控 master 分支上的推送事件
85 | workflow_dispatch: # 手动触发工作流
86 |
87 | jobs:
88 | run-script:
89 | runs-on: ubuntu-latest # 使用最新版本的 Ubuntu 作为运行环境
90 |
91 | steps:
92 | - name: Checkout code # 步骤1:检出代码
93 | uses: actions/checkout@v2 # 使用官方的 checkout 动作
94 |
95 | - name: Install SSH client and sshpass # 步骤2:安装 SSH 客户端和 sshpass
96 | run: |
97 | sudo apt-get update # 更新包列表
98 | sudo apt-get install -y openssh-client sshpass # 安装 openssh-client 和 sshpass
99 |
100 | - name: Run script on server # 步骤3:在服务器上运行脚本
101 | env:
102 | SSH_HOST: ${{ secrets.SSH_HOST }} # 从 GitHub Secrets 中读取 SSH 主机名
103 | SSH_USER: ${{ secrets.SSH_USER }} # 从 GitHub Secrets 中读取 SSH 用户名
104 | SSH_PASSWORD: ${{ secrets.SSH_PASSWORD }} # 从 GitHub Secrets 中读取 SSH 密码
105 | run: |
106 | # 使用 sshpass 和 SSH 密码进行 SSH 连接,并在服务器上运行脚本
107 | sshpass -p "$SSH_PASSWORD" ssh -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST 'nohup /root/update.sh > /root/update_output.log 2>&1'
108 |
109 | # 捕获脚本的退出状态
110 | EXIT_STATUS=$?
111 |
112 | # 从服务器获取输出日志文件
113 | sshpass -p "$SSH_PASSWORD" scp -o StrictHostKeyChecking=no $SSH_USER@$SSH_HOST:/root/update_output.log .
114 |
115 | # 显示输出日志文件内容
116 | cat update_output.log
117 |
118 | # 输出脚本执行结果
119 | if [ $EXIT_STATUS -ne 0 ]; then
120 | echo "Script execution failed with exit status $EXIT_STATUS" # 如果脚本执行失败,输出错误状态并退出
121 | exit $EXIT_STATUS
122 | else
123 | echo "Script executed successfully" # 如果脚本执行成功,输出成功消息
124 | fi
125 |
126 | ```
127 | :::
--------------------------------------------------------------------------------
/docs/web/basics/es6-practice.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 优雅的代码-es6实践
3 | description: 优雅的代码-es6实践
4 | ---
5 |
6 | # 优雅的代码-es6实践
7 |
8 | > 代码不规范,亲人两行泪
9 |
10 | ## 简化if( && 或 三元运算符)
11 | ```js
12 | // 第一种情况 (简化if)
13 | if( a === true ) { return console.log('返回是个真') }
14 | // 简写
15 | eg:2
16 | if(a) return console.log('返回是个真')
17 | // 缺点
18 | const a = 'string'; if (a)的值也是true,字符串不是假
19 |
20 | eg:2
21 | a && console.log('返回是个真')
22 | // 缺点
23 | 只能走if循环的true,不能走else
24 |
25 | // 第二种情况 (巧用对象)
26 |
27 | {{ status === 1 ? '杰夫贝佐斯' : '斯嘉丽约翰逊' }}
28 |
29 | 如果status多个呢???
30 | status:1 >>> '杰夫贝佐斯'
31 | status:2 >>> '斯嘉丽约翰逊'
32 | status:3 >>> '贾斯汀比伯'
33 | status:4 >>> '马斯克'
34 | function filterStatus(val: keyof {
35 | 1: number
36 | }) {
37 | const obj = {
38 | 1: '杰夫贝佐斯',
39 | 2: '斯嘉丽约翰逊',
40 | 3: '贾斯汀比伯',
41 | 4: '马斯克'
42 | }
43 | return obj[val] || val
44 | }
45 |
46 | // 第三种情况
47 | if( a > 0 ) { isBoon = true } else { isBoon = false }
48 | // 简写
49 | a > 0 ? (isBoon = true) : (isBoon = false)
50 | 不适合复杂的if判断,不能return,
51 | 如果需要return那就 return isBoon = a > 0 ? true : false
52 |
53 | // 进阶用法
54 | &&= ||= ??=
55 | 1.&&=
56 | if (props.code) {
57 | props.code = 200
58 | }
59 | 简写
60 | props.code &&= 200
61 | 2.||=
62 | if (!props.code) {
63 | props.code = 200
64 | }
65 | 简写
66 | props.code ||= 200
67 | 3.||=
68 | if (props.code === null || props.code === undefined) {
69 | props.code = 200
70 | }
71 | 简写
72 | props.code ??= 200
73 | ```
74 |
75 | ## 批量命名
76 |
77 | > 能用const关键字定义变量就用const关键字
78 |
79 | ```js
80 | let valA = '斯嘉丽约翰逊';
81 | let valB = '艾玛沃特森';
82 | let valC = '泰勒斯威夫特';
83 | let valD = '克里斯汀斯图尔特';
84 | const [ a, b, c, d] = ['斯嘉丽约翰逊', '艾玛沃特森', '泰勒斯威夫特', '克里斯汀斯图尔特']
85 | ```
86 |
87 | ## 解构赋值
88 | * eg1:
89 |
90 | 示例数据
91 |
92 | ```js
93 | const obj = {
94 | name: '杰夫贝佐斯',
95 | age: 48,
96 | }
97 | ```
98 |
99 | ```js
100 | const { name } = obj // 可以避免obj.name,多次使用obj.,来调用name属性,
101 | console.log(name) // 打印结果-- 杰夫贝佐斯
102 | ```
103 |
104 | * eg2:
105 |
106 | ```js
107 | this.name = 'aaa'
108 | this.obj = 'bbb'
109 | this.arr = 'ccc'
110 |
111 | // 正确使用
112 | const { name, obj, arr, ... } = this
113 | name = 'aaa' , obj = 'bbb' , arr = 'ccc'
114 | ```
115 |
116 | * eg3:
117 |
118 | ```js
119 | const ren = {
120 | name: '马斯克',
121 | age: 54,
122 | sex: '男',
123 | identity: '世界首富',
124 | }
125 |
126 | // 解构赋值搭配展开运算符
127 | const { name, ...newObj } = ren
128 | console.log('结构常用变量,剩余变量包装一个新的对象-------',name,newObj) // ↓↓
129 | 结构常用变量,剩余变量包装一个新的对象-------,马斯克, {age: 54,sex: '男',identity: '世界首富',}
130 |
131 | ```
132 |
133 | * eg3:
134 |
135 | ```js
136 | // 多重结构
137 | const moreRen = {
138 | name: '马斯克',
139 | age: 54,
140 | sex: '男',
141 | identity: '世界首富',
142 | company: {
143 | cart: '特斯拉',
144 | space: 'SpaceX'
145 | }
146 | }
147 |
148 | const { company: { cart } } = moreRen
149 | console.log('cart------',cart) // 特斯拉
150 | ```
151 |
152 | ## includes检测
153 |
154 | > 代替if判断,vue路由常用,白名单权限...
155 |
156 | ```js
157 | includes是恒等价于===的逻辑判断
158 | 也就是说 1 === '1' 返回false 等价于 [1].includes('1') 返回false
159 |
160 | eg: 错误示范
161 | if (val === '/login' || val === '/about' || val === '/home' || val === '/index') {
162 | console.log('vue需要放行token白名单的路由')
163 | }
164 |
165 | eg:<正确写法>
166 | const whiteList = [ '/login', '/about', '/home', '/index' ]
167 | whiteList.includes('login') && console.log('vue需要放行token白名单的路由')
168 | ```
169 |
170 | ## 代码规范
171 | ```js
172 | 1.css的命名不能使用驼峰,尽量使用-,或者_拼接
173 | 错误:.mainBox
174 | 正确:.main-box || .main_box
175 |
176 | 2.js的命名尽量使用驼峰,带有语意话的英文单词拼写
177 | 错误:function mainbox () { }
178 | 正确:mainBox () { }
179 | ```
180 |
181 | ## 补充
182 | ```js
183 | 1.不使用第三个变量进行换值操作
184 | let a = 5
185 | let b = 10
186 | [a, b] = [b, a]
187 | console.log('置换之后-----',a,b) // 置换之后-----,10,5
188 | ```
--------------------------------------------------------------------------------
/docs/web/knowledge/use-pm2.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: pm2使用教程
3 | description: pm2是什么,pm2的作用,linux怎么使用pm2
4 | outline: [2, 3]
5 | ---
6 |
7 | # pm2
8 |
9 | [pm2官网](https://pm2.keymetrics.io/)
10 |
11 | **PM2** 是 **node** 进程管理工具,可以利用它来简化很多 node应用管理的繁琐任务,如性能监控、自动重启、负载均衡等
12 |
13 | ## 安装
14 |
15 | **前置条件**
16 |
17 | - 安装pm2需要node环境
18 |
19 | ```sh
20 | $ npm install pm2@latest -g
21 | # or
22 | $ yarn global add pm2
23 | ```
24 |
25 | - 启动
26 |
27 | ```sh
28 | pm2 start app.js
29 | ```
30 |
31 | ## 常用命令
32 |
33 | * **查看进程**: pm2 list
34 |
35 | * **启动所有进程**: pm2 startup
36 |
37 | * **删除某个进程**: pm2 delete <进程ID>
38 |
39 | * **停止某个进程**: pm2 stop <进程ID>
40 |
41 | * **重启所有进程**: pm2 restart all
42 |
43 | * **删除所有进程**: pm2 delete all
44 |
45 | * **停止所有进程**: pm2 stop all
46 |
47 | * **查看日志**: pm2 logs
48 |
49 | * **保存进程列表**: pm2 save
50 |
51 | ## pm2启动项目
52 |
53 | * 普通启动
54 |
55 | ```sh
56 | pnpm run start
57 | ```
58 |
59 | * pm2启动
60 |
61 | ```sh
62 | pm2 start pnpm --name “自定义你的进程名字” -- run [实际执行的命令]
63 | ```
64 |
65 | **示例**
66 |
67 | ```sh
68 | pm2 start pnpm --name "blog" -- run start
69 | ```
70 |
71 | ## 保活
72 |
73 | > 重启服务器,pm2启动的项目可以自行启动,也是我们使用pm2最主要的原因
74 |
75 | ### 配置自动启动项目
76 |
77 | > 配置 PM2 使其在系统重启后自动启动项目
78 |
79 | 执行 `pm2 list` 查看项目已经在pm2启动列表里边
80 |
81 | 执行
82 |
83 | ```sh
84 | pm2 startup systemd
85 | ```
86 |
87 | 这个命令会生成一个 systemd 服务文件,并给出一个命令供你复制和运行。
88 |
89 | ::: details 脚本生成示例
90 | ```sh
91 | pm2 startup systemd
92 | [PM2] Init System found: systemd
93 | Platform systemd
94 | Template
95 | [Unit]
96 | Description=PM2 process manager
97 | Documentation=https://pm2.keymetrics.io/
98 | After=network.target
99 |
100 | [Service]
101 | Type=forking
102 | User=root
103 | LimitNOFILE=infinity
104 | LimitNPROC=infinity
105 | LimitCORE=infinity
106 | Environment=PATH=/root/加密加密加密加密/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin
107 | Environment=PM2_HOME=/root/.pm2
108 | PIDFile=/root/.pm2/pm2.pid
109 | Restart=on-failure
110 |
111 | ExecStart=/加密加密加密加密/ons/node/v18.20.4/lib/node_modules/pm2/bin/pm2 resurrect
112 | ExecReload=/加密加密加密加密/ons/node/v18.20.4/lib/node_modules/pm2/bin/pm2 reload all
113 | ExecStop=/加密加密加密加密/ons/node/v18.20.4/lib/node_modules/pm2/bin/pm2 kill
114 |
115 | [Install]
116 | WantedBy=multi-user.target
117 |
118 | Target path
119 | /etc/systemd/system/pm2-root.service
120 | Command list
121 | [ 'systemctl enable pm2-root' ]
122 | [PM2] Writing init configuration in /etc/systemd/system/pm2-root.service
123 | [PM2] Making script booting at startup...
124 | [PM2] [-] Executing: systemctl enable pm2-root...
125 | [PM2] [v] Command successfully executed.
126 | +---------------------------------------+
127 | [PM2] Freeze a process list on reboot via:
128 | $ pm2 save
129 |
130 | [PM2] Remove init script via:
131 | $ pm2 unstartup systemd
132 | ```
133 |
134 | :::
135 |
136 | 运行以下命令来完成 PM2 的启动配置:
137 |
138 | ```sh
139 | sudo env PATH=$PATH:${环境变量 PATH} ${PM2 的完整路径} startup systemd -u root --hp /root
140 | ```
141 |
142 | **示例**
143 |
144 | ```sh
145 | sudo env PATH=$PATH:/root/加密加密加密加密/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin /加密加密加密加密/ons/node/v18.20.4/lib/node_modules/pm2/bin/pm2 startup systemd -u root --hp /root
146 | ```
147 |
148 | 命令的解析如下
149 |
150 | - sudo: 以超级用户权限运行命令。
151 | - env PATH=$PATH:...: 设置环境变量 PATH,包含了所有必要的目录。
152 | - /root/.nvm/versions/node/v18.20.4/lib/node_modules/pm2/bin/pm2: PM2 的完整路径。
153 | - startup systemd: 指示 PM2 创建 systemd 启动脚本。
154 | - -u root: 指定运行 PM2 的用户为 root。
155 | - --hp /root: 指定 root 用户的主目录。
156 |
157 | 运行这个命令后,PM2 将被配置为在系统启动时自动运行
158 |
159 | 运行保存脚本
160 |
161 | ```sh
162 | pm2 save
163 | ```
164 |
165 | 这将保存当前的 PM2 进程列表,确保在系统重启后这些进程会被自动重启
166 |
167 | 要使 PM2 在系统启动时自动启动,运行
168 |
169 | ```sh
170 | sudo systemctl enable pm2-
171 | ```
172 |
173 | 按照示例需要执行
174 |
175 | ```sh
176 | sudo systemctl enable pm2-root
177 | ```
178 |
--------------------------------------------------------------------------------
/docs/web/vue/local.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: js获取电脑ip
3 | description: 使用javascript获取电脑ip
4 | ---
5 |
6 | # js获取电脑ip
7 |
8 | ## 获取当前电脑内网ip
9 | ```js
10 | function getLocalIp() {
11 | let needHost = ''
12 | try {
13 | // 获得网络接口列表
14 | let network = os.networkInterfaces()
15 | for (let dev in network) {
16 | let iface = network[dev]
17 | for (let i = 0; i < iface.length; i++) {
18 | let alias = iface[i]
19 | if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
20 | needHost = alias.address
21 | }
22 | }
23 | }
24 | } catch (e) {
25 | needHost = 'localhost'
26 | }
27 | return needHost
28 | }
29 | ```
30 |
31 | ## 获取电脑ip,根据ip映射域名
32 |
33 | - 内网开发网络图片(阿里云图片)需要使用域名才可以正常访问
34 | - 映射关系可以放公司内部的服务器里边,可以多个项目使用
35 |
36 | ### 服务器文件内容
37 |
38 | > http://www.cs.com/file/ip.js
39 |
40 | ```js
41 | ipLocal = {
42 | '192.168.1.1' : 'zs.local.net', // 张三的电脑域名
43 | '192.168.1.2' : 'sl.local.net', // 李四的电脑域名
44 | '192.168.1.3' : 'ww.local.net' // 王五的电脑域名
45 | }
46 | ```
47 |
48 | ### vue项目配置文件内容
49 | ::: code-group
50 | ```js-vue [CommonJS]
51 | // 支持require引入的项目使用`CommonJS`
52 | // 新建domainName.js文件
53 | const os = require('os')
54 | const { execSync } = require('child_process')
55 |
56 | function domainName() {
57 | let needHost = '' // 打开的host
58 | try {
59 | // 获得网络接口列表
60 | let network = os.networkInterfaces()
61 | for (let dev in network) {
62 | let iface = network[dev]
63 | for (let i = 0; i < iface.length; i++) {
64 | let alias = iface[i]
65 | if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
66 | needHost = alias.address
67 | }
68 | }
69 | }
70 | } catch (e) {
71 | needHost = 'localhost'
72 | }
73 | try {
74 | const script = execSync('curl http://www.cs.com/file/ip.js').toString()
75 | const obj = eval(script)
76 | return obj[String(needHost)] || 'localhost'
77 | } catch (error) {
78 | return 'localhost'
79 | }
80 | }
81 |
82 | module.exports = {
83 | domainName
84 | }
85 |
86 | // ==== webpack.config.js ====
87 | module.exports = {
88 | // ...
89 | devServer: {
90 | open: true,
91 | host: require('./domainName').domainName() // 替换掉'0.0.0.0'
92 | },
93 | };
94 | ```
95 |
96 | ```js-vue [EsModule]
97 | // 不支持require引入的项目使用`(EsModule)`
98 | import os from 'os'
99 | import { execSync } from 'child_process'
100 |
101 | function domainName() {
102 | let needHost = '' // 打开的host
103 | try {
104 | // 获得网络接口列表
105 | let network = os.networkInterfaces()
106 | for (let dev in network) {
107 | let iface = network[dev]
108 | for (let i = 0; i < iface.length; i++) {
109 | let alias = iface[i]
110 | if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) {
111 | needHost = alias.address
112 | }
113 | }
114 | }
115 | } catch (e) {
116 | needHost = 'localhost'
117 | }
118 | try {
119 | const script = execSync('curl http://www.cs.com/file/ip.js').toString()
120 | const fun = new Function(script + 'return ipLocalMapping')
121 | const obj = fun()
122 | return obj[String(needHost)] || 'localhost'
123 | } catch (error) {
124 | return 'localhost'
125 | }
126 | }
127 |
128 | export default domainName
129 |
130 | // ==== vite.config.js ====
131 | import domainName from './domainName'
132 |
133 | export default defineConfig({
134 | // ...
135 | server: {
136 | host: domainName() // 替换掉'0.0.0.0'
137 | }
138 | })
139 | ```
140 | :::
141 |
--------------------------------------------------------------------------------
/docs/api/install-software/docker/mysql.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Mysql
3 | description: MySQL 是一个广泛使用的开源关系型数据库管理系统(RDBMS)。它以其稳定性、可靠性和高性能而著称,适用于从小型项目到大型企业级应用的各种场景。
4 | outline: [2, 3]
5 | ---
6 |
7 | # Mysql
8 |
9 | ## 链接
10 |
11 | [docker下载Mysql官网](https://hub.docker.com/_/mysql)
12 |
13 | ## 什么是 MySQL
14 |
15 | MySQL 是一个广泛使用的开源关系型数据库管理系统(RDBMS)。它以其稳定性、可靠性和高性能而著称,适用于从小型项目到大型企业级应用的各种场景。
16 |
17 | ## 主要特点
18 |
19 | * 数据存储与管理
20 |
21 | 以表格的形式组织和存储数据,通过行和列的结构清晰地定义数据的属性和值。例如,在一个存储用户信息的表中,可能有 “用户 ID”“姓名”“年龄” 等列,每一行对应一个具体的用户记录。
22 |
23 | * 数据一致性与完整性
24 |
25 | 支持多种约束条件,如主键约束(确保每一行数据的唯一性)、外键约束(建立不同表之间的关联关系)和非空约束等。例如,在订单管理系统中,订单表中的 “订单 ID” 可以设置为主键,确保每个订单都有唯一标识;而订单表中的 “用户 ID” 可以与用户表的 “用户 ID” 建立外键关联,保证数据的一致性和完整性。
26 |
27 | * 高效的查询处理
28 |
29 | 具备强大的查询语言(SQL - Structured Query Language),用户可以通过编写复杂的 SQL 查询语句来快速检索、过滤、排序和聚合数据。例如,要查询某个时间段内销售额超过一定金额的订单信息,可以使用 SQL 语句从订单表中筛选出符合条件的数据。
30 |
31 | * 可扩展性
32 |
33 | 可以方便地进行水平扩展(通过添加更多的服务器节点来分担负载)和垂直扩展(升级服务器的硬件资源,如增加内存、CPU 等)。在面对不断增长的数据量和并发访问量时,能够根据实际需求灵活地调整系统的性能。
34 |
35 | ## 下载Mysql镜像
36 |
37 | ```sh
38 | docker pull mysql
39 | ```
40 |
41 | `检查当前所有Docker下载的镜像`
42 |
43 | ```sh
44 | docker images
45 | ```
46 |
47 | ## 创建Mysql容器
48 |
49 | ### 简单容器
50 |
51 | > 简单的运行 MySQL 容器
52 |
53 | ```sh
54 | docker run -d \
55 | --name mysql-server \
56 | -e MYSQL_ROOT_PASSWORD=123456 \
57 | -p 3306:3306 \
58 | -v /path/to/mysql/data:/data/mysqldata \
59 | --restart=unless-stopped \
60 | mysql:latest
61 | ```
62 |
63 | * `-d`:以守护进程(后台)模式运行容器。
64 |
65 | * `--name mysql-server`:给容器命名为 “mysql-server”。
66 |
67 | * `-e MYSQL_ROOT_PASSWORD=123456`:设置 MySQL 的 root 用户密码为 "12345678a"(实际使用中请设置更复杂的密码)。
68 |
69 | * `-p 3306:3306`:映射容器的 3306 端口到主机的 3306 端口。
70 |
71 | * `--restart=always`:确保容器在 Docker 启动时自动启动。
72 |
73 | * `mysql`:指定使用的 MySQL 镜像(Docker 会从官方仓库拉取最新的 MySQL 镜像,如果本地没有的话)。
74 |
75 | **补充**
76 |
77 | * 1. `--restart=always`
78 |
79 | **含义**:无论容器是正常退出还是异常退出,Docker 都会自动重启该容器。
80 |
81 | **行为**:
82 |
83 | 如果容器因为内部应用崩溃、被用户手动停止(如使用 docker stop 命令)或 Docker 守护进程重启等原因退出,Docker 都会自动重启容器。
84 | 容器会一直运行,直到手动将其删除(docker rm)。
85 |
86 | **适用场景**:适用于需要持续运行的服务,例如数据库服务、Web 服务器等,确保服务始终可用。
87 |
88 | * 2. `--restart=unless-stopped`
89 |
90 | **含义**:容器会在以下情况下自动重启:
91 |
92 | 容器异常退出(例如应用崩溃)。
93 |
94 | Docker 守护进程重启。
95 |
96 | **行为**:
97 |
98 | 如果容器被手动停止(如使用 docker stop 命令),Docker 不会自动重启它。
99 |
100 | 如果容器被手动删除(docker rm),则不会重启。
101 |
102 | 如果 Docker 守护进程重启(例如系统重启),容器会自动启动。
103 |
104 | **适用场景**:适用于需要在系统重启后自动恢复运行,但又允许用户手动停止容器的场景。
105 |
106 | * 3. 总结区别
107 |
108 | `--restart=always`:无论容器是正常退出还是异常退出,都会自动重启。
109 |
110 | `--restart=unless-stopped`:只有在容器异常退出或 Docker 守护进程重启时才会自动重启,手动停止后不会重启。
111 |
112 | ### 企业容器
113 |
114 | > 企业环境中运行 MySQL 容器
115 |
116 | ```sh
117 | docker run -d \
118 | --name mysql \
119 | --restart=always \
120 | -p 3306:3306 \
121 | -v /data/mysql/data:/var/lib/mysql \
122 | -v /data/mysql/conf:/etc/mysql/conf.d \
123 | -v /data/mysql/logs:/var/log/mysql \
124 | -e MYSQL_ROOT_PASSWORD=your_secure_password \
125 | mysql:latest
126 | ```
127 |
128 | **指令解释**
129 |
130 | * `docker run -d`:以守护进程(后台)模式运行容器。
131 |
132 | * `--name mysql`:为容器指定一个容易识别的名称为 “mysql”。
133 |
134 | * `--restart=always`:设置容器在 Docker 守护进程启动时自动启动,即使因为某些原因容器停止了,也会自动重新启动,这确保了开机自启动。
135 |
136 | * `-p 3306:3306`:将容器内的 3306 端口(MySQL 默认端口)映射到宿主机的 3306 端口,使得外部可以访问容器中的 MySQL 服务。
137 |
138 | * `-v /data/mysql/data:/var/lib/mysql`:将宿主机的/data/mysql/data目录挂载到容器内 MySQL 数据存储目录/var/lib/mysql,确保数据持久化存储,防止容器删除后数据丢失。
139 |
140 | * `-v /data/mysql/conf:/etc/mysql/conf.d`:挂载配置文件目录,方便在宿主机上进行 MySQL 配置文件的管理与修改。
141 |
142 | * `-v /data/mysql/logs:/var/log/mysql`:挂载日志目录,便于在宿主机上查看和管理 MySQL 运行过程中产生的日志。
143 |
144 | * `-e MYSQL_ROOT_PASSWORD=your_secure_password`:设置 MySQL 的 root 用户密码,确保数据库的安全性。这里需要将your_secure_password替换为实际的强密码。
145 |
146 | * `mysql:latest`:指定要运行的 MySQL 镜像,这里使用最新版本的 MySQL 镜像。
--------------------------------------------------------------------------------
/docs/other/blog/up/use-page.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 如何使用github pages
3 | description: github page是什么,github page的使用教程
4 | outline: [2, 3]
5 | ---
6 |
7 | # 如何使用github pages
8 |
9 | ## github pages是什么
10 |
11 | > `GitHub Pages` 是 `GitHub` 提供的一个免费服务,用于托管静态网站。你可以用它轻松地创建个人主页、博客、项目页面等
12 |
13 | [官网链接](https://docs.github.com/zh/pages/getting-started-with-github-pages)
14 |
15 | * 首先他是完全免费的,相较其他的同类产品,他能替你省下一笔服务费,节约下的钱可以让你买一些其他的会员服务;
16 | * 无须自己购买云服务进行搭建,只需按步骤一步步操作即可,即使你不懂他的技术细节;
17 | * 支持的功能多,玩法丰富,你可以绑定你的域名、使用免费的 HTTPS、自己 DIY 网站的主题、使用他人开发好的插件等等;
18 | * 当完成搭建后,你只需要专注于文章创作就可以了,其他诸如环境搭建、系统维护、文件存储的事情一概不用操心,都由 GitHub 处理
19 |
20 | ## 尝试使用github pages
21 |
22 | * 在github新建一个空白项目
23 | * 项目初始化完毕后添加一个 `index.html` 文件
24 | ```html
25 |
26 |
27 |
28 |
29 | 一条懒羊羊
30 |
31 |
32 | ```
33 | * 选择 "Setting" -> "Secrets" -> "Code and automation" -> `"Pages"`
34 |
35 | 看到 `Build and deployment` 的 `Source` 存在两个选项
36 | * `Deploy from a branch` 从分支部署
37 | - Branch选择master分支
38 | - 默认他会读取跟目录的 `index.html` 文件,也就是说一个项目跟目录下只能有一个 `index.html` 文件
39 | - 刷新之后在 `GitHub Pages` 页面会出现一个网站,这个网站就是我们发布好的网站
40 | * `GitHub Actions` 自动化部署
41 | > 后续介绍使用
42 |
43 | ## 使用github pages自动化
44 |
45 | > 项目代码提交之后我们可以配置自动化发布 `github pages` 网站
46 |
47 | `1.` 选择 "Setting" -> "Secrets" -> "Code and automation" -> `"Pages"`
48 |
49 | `2.` 看到 `Build and deployment` 的 `Source` 选择 `GitHub Actions` 自动化部署
50 |
51 | ### 自动化脚本
52 |
53 | [vitepress部署脚本说明](https://vitepress.dev/zh/guide/deploy)
54 |
55 | * vitepress项目,`.github/workflows/` 新建 `deploy.yml` 脚本文件
56 | * 基于 `master` 新建分支 `github-pages`
57 | * 配置相关命令权限等
58 | * 构建脚本
59 | * 部署脚本
60 |
61 | > github-pages 分支提交上去之后我们就不需要做任何改动
62 |
63 | ```yml
64 | # 构建 VitePress 站点并将其部署到 GitHub Pages 的示例工作流程
65 | #
66 | name: Deploy VitePress site to Pages
67 |
68 | on:
69 | # 在针对 `main` 分支的推送上运行。如果你
70 | # 使用 `master` 分支作为默认分支,请将其更改为 `master`
71 | push:
72 | branches: [master]
73 |
74 | # 允许你从 Actions 选项卡手动运行此工作流程
75 | workflow_dispatch:
76 |
77 | # 设置 GITHUB_TOKEN 的权限,以允许部署到 GitHub Pages
78 | permissions:
79 | contents: read
80 | pages: write
81 | id-token: write
82 |
83 | # 只允许同时进行一次部署,跳过正在运行和最新队列之间的运行队列
84 | # 但是,不要取消正在进行的运行,因为我们希望允许这些生产部署完成
85 | concurrency:
86 | group: pages
87 | cancel-in-progress: false
88 |
89 | jobs:
90 | # 构建工作
91 | build:
92 | runs-on: ubuntu-latest
93 | steps:
94 | - name: Checkout
95 | uses: actions/checkout@v4
96 | with:
97 | fetch-depth: 0 # 如果未启用 lastUpdated,则不需要
98 | - uses: pnpm/action-setup@v3 # 如果使用 pnpm,请取消注释
99 | with:
100 | version: 8.14.0 # 这里指定 pnpm 的版本
101 | - name: Setup Node
102 | uses: actions/setup-node@v4
103 | with:
104 | node-version: 18.17.1
105 | cache: pnpm # 或 pnpm / yarn
106 | - name: Setup Pages
107 | uses: actions/configure-pages@v4
108 | - name: Install dependencies
109 | run: pnpm install # 或 pnpm install / yarn install / bun install
110 | - name: Build with VitePress
111 | env:
112 | BUILD_ENV: github # 配置环境变量
113 | run: pnpm run build # 打包命令
114 | - name: Upload artifact
115 | uses: actions/upload-pages-artifact@v3
116 | with:
117 | path: docs/.vitepress/dist
118 |
119 | # 部署工作
120 | deploy:
121 | environment:
122 | name: github-pages
123 | url: ${{ steps.deployment.outputs.page_url }}
124 | needs: build
125 | runs-on: ubuntu-latest
126 | name: Deploy
127 | steps:
128 | - name: Deploy to GitHub Pages
129 | id: deployment
130 | uses: actions/deploy-pages@v4
131 | ```
132 |
133 | ### 实现效果
134 |
135 | - 配置完成之后 `master` 分支有提交就会触发脚本自动构建部署网站,也就是实现了 `CD`
136 | - `CD` 即持续交付/部署
137 |
--------------------------------------------------------------------------------
/docs/web/wechat/custom-nav.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 小程序自定义顶部导航栏组件
3 | description: 微信小程序自定义顶部导航栏组件
4 | ---
5 |
6 | # 小程序自定义顶部导航栏组件
7 |
8 | ## 组件源代码
9 |
10 | ::: code-group
11 | ```html
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | {{title}}
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | ```
45 |
46 | ```js
47 | Component({
48 | properties: {
49 | // 标题内容
50 | title: {
51 | type: String,
52 | value: "标题",
53 | },
54 | // 标题居中,默认左对齐
55 | center: {
56 | type: Boolean,
57 | value: false,
58 | },
59 | // 自定义顶部导航栏内容
60 | customMain: {
61 | type: Boolean,
62 | value: false,
63 | },
64 | // 自定义胶囊内容
65 | customCachet: {
66 | type: Boolean,
67 | value: false,
68 | },
69 | // 是否隐藏胶囊站位
70 | hideCachet: {
71 | type: Boolean,
72 | value: false,
73 | },
74 | },
75 | data: {
76 | ztlHeight: 0,
77 | dhlHeight: 0,
78 | zHeight: 0,
79 | rightDistance: 0, // 胶囊左侧应留间距
80 | },
81 | attached: function () {
82 | const system = wx.getSystemInfoSync();
83 | const res = wx.getMenuButtonBoundingClientRect();
84 | const ztlHeight = system.statusBarHeight;
85 | const dhlHeight = res.height + (res.top - ztlHeight) * 2;
86 | const zHeight = ztlHeight + dhlHeight;
87 | const rightDistance = res.width + 6;
88 | this.setData({
89 | ztlHeight,
90 | dhlHeight,
91 | zHeight,
92 | rightDistance
93 | });
94 | },
95 | methods: {},
96 | });
97 |
98 | ```
99 |
100 | ```css
101 | .custom-nav {
102 | width: 100%;
103 | background: #fff;
104 | position: relative;
105 | z-index: 9999;
106 | overflow: hidden;
107 | }
108 |
109 | .custom-nav-box {
110 | position: fixed;
111 | width: 100%;
112 | background: #fff;
113 | z-index: 9999;
114 | border-bottom: 1rpx solid rgba(255, 255, 255, 0.3);
115 | }
116 |
117 | .custom-nav-bar {
118 | position: relative;
119 | z-index: 9;
120 | display: flex;
121 | width: 100%;
122 | align-items: center;
123 | }
124 |
125 | .custom-nav-cont {
126 | position: relative;
127 | display: flex;
128 | width: 750px;
129 | height: 100%;
130 | }
131 |
132 | .custom-nav-cont-box {
133 | flex: 1;
134 | display: flex;
135 | align-items: center;
136 | box-sizing: border-box;
137 | padding-left: 20rpx;
138 | }
139 | .custom-nav-cont-box-img {
140 | height: 40rpx;
141 | width: 20rpx;
142 | }
143 | .custom-nav-cont-box-title {
144 | margin-left: 10px;
145 | font-size: 36rpx;
146 | font-weight: bold;
147 | }
148 | .custom-nav-cont-cachet {
149 | height: 100%;
150 | }
151 |
152 | .custom-nav-cont-box-title-center {
153 | position: absolute;
154 | top: 50%;
155 | left: 50%;
156 | transform: translate(-50%, -50%);
157 | }
158 |
159 | ```
160 | :::
--------------------------------------------------------------------------------
/docs/web/vue/use-computed.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 妙用Computed
3 | description: 在vue中妙用Computed
4 | ---
5 |
6 | # 妙用Computed
7 |
8 | > vue 是`单项数据流`,子组件不能直接修改父组件传过来的 props
9 |
10 | ## 解决方案
11 |
12 | ::: info 使用`computed`拦截`prop`
13 |
14 | > 使用简单,但是无法处理对象
15 |
16 | ```vue
17 |
18 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
59 | :::
60 |
61 | ::: info 使用`Proxy`代理对象
62 | ```vue
63 |
64 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
126 | ```
127 | :::
128 |
129 |
130 | ## 封装成`hook`
131 |
132 | ::: info 封装`useVModle`
133 | ```js
134 | // useVModel.js
135 | import { computed } from "vue";
136 |
137 | export default function useVModle(props, propName, emit) {
138 | return computed({
139 | get() {
140 | return new Proxy(props[propName], {
141 | get(target, key) {
142 | return Reflect.get(target, key)
143 | },
144 | set(target, key, newValue) {
145 | emit('update:' + propName, {
146 | ...target,
147 | [key]: newValue
148 | })
149 | return true
150 | }
151 | })
152 | },
153 | set(value) {
154 | emit('update:' + propName, value)
155 | }
156 | })
157 | }
158 | ```
159 | :::
160 |
161 | ::: info 子组件使用
162 | ```vue
163 |
164 |
165 |
166 |
167 |
168 |
169 |
170 |
185 | ```
186 | :::
187 |
--------------------------------------------------------------------------------
/docs/api/install-software/docker/index.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: Docker
3 | description: Docker 是一个开源的容器化平台。它就像是一个轻量级的、独立运行的软件包,包含了运行某个应用程序所需的所有东西,包括代码、运行环境、系统工具、系统库等。
4 | outline: [2, 3]
5 | ---
6 |
7 | # Docker
8 |
9 | ## 链接
10 |
11 | * [Docker install 官网](https://docs.docker.com/engine/install/)
12 |
13 | * [Docker package 官网](https://hub.docker.com/search)
14 |
15 | ## Docker 简介
16 |
17 | ### 核心概念
18 |
19 | * **容器**
20 |
21 | 容器是 Docker 的核心元素。它就像是一个轻量级的、独立运行的软件包,包含了运行某个应用程序所需的所有东西,包括代码、运行环境、系统工具、系统库等。例如,一个运行着特定版本的 Web 服务器的容器,它能够在不同的计算机环境中保持一致的运行效果。
22 |
23 | * **镜像**
24 |
25 | 镜像是创建容器的基础。可以把它想象成容器的蓝图,它包含了容器启动时所需的文件系统和配置信息。例如,有一个 Ubuntu 操作系统的 Docker 镜像,基于这个镜像可以创建出多个运行 Ubuntu 系统的容器。
26 |
27 | ### 主要优势
28 |
29 | * **可移植性**
30 |
31 | Docker 容器可以在任何安装了 Docker 引擎的环境中运行,无论是开发者的个人电脑、测试服务器还是生产服务器。这使得开发、测试和部署的过程变得更加流畅,消除了传统环境中因操作系统、软件库版本等差异导致的 “在我机器上可以运行” 的问题。
32 |
33 | * **高效利用资源**
34 |
35 | 与传统的虚拟机相比,Docker 容器更加轻量级。多个容器可以共享主机的操作系统内核,不需要为每个容器运行一个完整的操作系统,大大节省了系统资源,使得在相同的硬件资源上可以运行更多的应用程序。
36 |
37 | * **快速部署和启动**
38 |
39 | 容器的启动速度非常快,通常只需要几秒钟。这使得在需要快速扩展应用程序实例的场景下,如应对流量高峰,Docker 能够快速响应,迅速启动新的容器来处理增加的负载。
40 |
41 | ## 安装Docker
42 |
43 | > Ubuntu 上安装 Docker 引擎
44 |
45 | ### 卸载旧版本
46 |
47 | 在安装 Docker Engine 之前,您需要卸载所有有冲突的软件包。
48 |
49 | 发行版维护者在 APT 中提供了 Docker 软件包的非官方发行版。您必须先卸载这些软件包,然后才能安装 Docker Engine 的正式版本。
50 |
51 | 要卸载的非官方软件包包括:
52 |
53 | ```md
54 | docker.io
55 | docker-compose
56 | docker-compose-v2
57 | docker-doc
58 | podman-docker
59 | ```
60 |
61 |
62 | 此外,Docker Engine 依赖于`containerd`和`runc`。Docker Engine 将这些依赖项捆绑为一个包:`containerd.io`。如果您之前安装了`containerd`或`runc`,请卸载它们以避免与 Docker Engine 捆绑的版本冲突。
63 |
64 | 运行以下命令来卸载所有冲突的包:
65 |
66 | ```sh
67 | for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done
68 | ```
69 |
70 | ### 添加Docker的签名密钥
71 |
72 | 在新的主机上首次安装 Docker Engine 之前,您需要设置 Docker 存储库。之后,您可以从存储库安装和更新 Docker。
73 |
74 | * 设置 Docker 的apt存储库
75 |
76 | ```sh
77 | # Add Docker's official GPG key:
78 | sudo apt-get update
79 | sudo apt-get install ca-certificates curl
80 | sudo install -m 0755 -d /etc/apt/keyrings
81 | sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
82 | sudo chmod a+r /etc/apt/keyrings/docker.asc
83 |
84 | # Add the repository to Apt sources:
85 | echo \
86 | "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
87 | $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
88 | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
89 | sudo apt-get update
90 | ```
91 |
92 | ### 查看可安装的Docker版本
93 |
94 | ```sh
95 | apt-cache policy docker-ce
96 | ```
97 |
98 |
99 | ### 安装 Docker 包
100 |
101 | ::: code-group
102 |
103 | ```sh [最新版]
104 | sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
105 | ```
106 |
107 | ```sh [指定版本]
108 | # List the available versions:
109 | apt-cache madison docker-ce | awk '{ print $3 }'
110 |
111 | 5:27.1.1-1~ubuntu.24.04~noble
112 | 5:27.1.0-1~ubuntu.24.04~noble
113 | ...
114 | ```
115 |
116 | :::
117 |
118 | ### 查看安装的Docker版本
119 |
120 | ```sh
121 | sudo docker version
122 | ```
123 |
124 | ## 添加国内镜像源
125 |
126 | 国内使用Docker下载镜像时会出现网速慢的问题,所以需要添加国内镜像源。
127 |
128 | * https://registry.docker - cn.com是 Docker 中国区官方镜像源。
129 | * https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo 和 https://mirror.aliyuncs.com 是阿里云平台。
130 | * https://mirror.ccs.tencentyun.com 是腾讯云平台。
131 | * https://hub-mirror.c.163.com 是网易平台。
132 | * https://docker.mirrors.ustc.edu.cn 是中国科学技术大学平台。
133 |
134 | ### 创建daemon.json文件,并添加镜像地址
135 |
136 | 首先运行 `sudo vim /etc/docker/daemon.json` 来创建daemon.json文件,然后将以下内容复制到 `daemon.json` 文件中。
137 |
138 | ```json
139 | {
140 | "registry-mirrors": [
141 | "https://registry.docker-cn.com",
142 | "https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo",
143 | "https://mirror.ccs.tencentyun.com",
144 | "https://hub-mirror.c.163.com",
145 | "https://docker.mirrors.ustc.edu.cn",
146 | "https://mirror.aliyuncs.com",
147 | "https://hub-mirror.c.163.com",
148 | ]
149 | }
150 | ```
151 |
152 | ### 重启Docker
153 |
154 | ```sh
155 | sudo service docker restart
156 | ```
--------------------------------------------------------------------------------
/docs/web/vue/publish-npm.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: vue组件发布npm
3 | description: 如何开发Vue组件并将其打包发布到npm。包括环境设置、Vue CLI项目创建、组件编码、Webpack配置、本地测试及最终的npm发布流程。
4 | outline: [2, 3]
5 | ---
6 |
7 | # vue组件发布npm
8 |
9 | > 举例vue2的npm组件包发布
10 |
11 | ## 知识科普
12 |
13 | [常见的打包格式](/web/vue/packaging-format)
14 |
15 | ## 环境准备
16 |
17 | * [Nodejs](https://nodejs.org/zh-cn)环境
18 | - 示例使用node14版本
19 | * [Vue CLI](https://cli.vuejs.org/zh/)脚手架
20 | - 安装 `Vue CLI` 脚手架
21 | ```sh
22 | npm install -g @vue/cli
23 | ```
24 |
25 | ## 创建项目
26 |
27 | 通过 `Vue CLI` 新建一个vue2的项目
28 |
29 | ```sh
30 | vue create vue-components-package
31 | ```
32 |
33 | ## 开发组件
34 |
35 | ### 编写vue组件
36 |
37 | ::: info 新建 `src/packages/HelloWorld.vue` 文件
38 |
39 | > 需要注意的是,组件必须有 `name`,这将会是用户使用的组件名称
40 |
41 | ```vue
42 |
43 |
44 |
红色
45 |
text:{{ text }}
46 |
蓝色
47 |
48 |
49 |
50 |
61 |
62 |
71 | ```
72 | :::
73 |
74 | ### 添加打包配置文件
75 |
76 | ::: info 新建 `src/index.js` 文件
77 |
78 | > 需要注意的是,组件必须有 `name`,这将会是用户使用的组件名称
79 |
80 | ```js
81 | import HellowWorld from "@/packages/HellowWorld.vue";
82 |
83 | const components = [HellowWorld];
84 |
85 | const install = (Vue, options) => {
86 | if (install.installed) return;
87 | install.installed = true;
88 | components.forEach((component) => {
89 | Vue.component(component.name, component);
90 | });
91 | };
92 |
93 | // 如果是直接引入的vue.js方式,则会挂到window下
94 | if (typeof window !== "undefined" && window.Vue) {
95 | install(window.Vue);
96 | }
97 |
98 | export default {
99 | // 使用Vue.use必须具有install方法
100 | install,
101 | ...components,
102 | };
103 | ```
104 | :::
105 |
106 | ### 添加打包命令
107 |
108 | 在项目根目录下的 `package.json` 文件添加 `build:package` 打包命令
109 |
110 | ```json
111 | "scripts": {
112 | "serve": "vue-cli-service serve",
113 | "build:package": "vue-cli-service build --target lib --name vue-components-package --dest lib src/index.js"
114 | },
115 | ```
116 |
117 | 这里的 `–target lib` 是 vue-cli 自带的打包命令,此命令会将入口文件打包成一个库码,具体可参考官网说明vue-cli官方文档
118 |
119 | * `–name` 指的是打包后的文件名
120 | * `–dest` 指文件夹的名称
121 |
122 | 紧跟的 `src/index.js` 指的是执行上文新建的index文件,暴露vue的install方法
123 |
124 | ## 验证组件功能和css样式
125 |
126 | * 修改根目录下的 `App.vue` 文件
127 |
128 | ```vue
129 |
130 |
131 |
132 |
133 |
134 |
135 |
147 | ```
148 | * 启动项目
149 | ```sh
150 | npm run serve
151 | ```
152 |
153 | ## 打包
154 |
155 | ```sh
156 | npm run build:package
157 | ```
158 |
159 | 项目打包成功之后会新增 `lib` 文件夹
160 |
161 | lib文件夹下包含多个js文件一个html文件
162 |
163 | ### 添加包文件入口
164 |
165 | 修改 `package.json` 文件
166 |
167 | ```json
168 | "main": "lib/vue-components-package.umd.js"
169 | ```
170 |
171 | ## 调试
172 |
173 | ### 发布本地连接包
174 |
175 | ```sh
176 | npm link
177 | ```
178 |
179 | ### 新建测试项目
180 |
181 | 重新构建一个vue项目用于测试组件包
182 |
183 | 在测试项目的目录终端执行
184 |
185 | ```sh
186 | npm link vue-components-package
187 | ```
188 |
189 | ### 引入开发的组件包
190 |
191 | ::: info 新项目的 main.js 文件引入开发的组件包
192 | ```js
193 | import Vue from "vue";
194 | import App from "./App.vue";
195 |
196 | import HelloWorld from "vue-components-package";
197 | Vue.use(HelloWorld);
198 |
199 | Vue.config.productionTip = false;
200 |
201 | new Vue({
202 | render: (h) => h(App),
203 | }).$mount("#app");
204 | ```
205 | :::
206 |
207 | 在 `App.vue` 中使用
208 |
209 | ```vue
210 |
211 |
212 |
213 |
214 |
215 | ```
216 |
217 | 然后运行项目,看打包内容是否正确
218 |
219 | ```sh
220 | npm run serve
221 | ```
222 |
223 | ### 其他方案
224 |
225 | 新建文件夹 `node_modules/vue-components-package`
226 |
227 | 采用复制的方式把 `lib` 和 `package.json` 文件复制到对应项目的 `node_modules/vue-components-package` 文件夹下
228 |
229 | 修改测试项目跟目录 `package.json` 文件的 `dependencies` 字段,手动添加包信息,注意包名和版本号要和拷贝过来的一致
230 |
231 | ```json
232 | "dependencies": {
233 | "vue-components-package": "^1.0.0",
234 | },
235 | ```
236 |
237 | ## 发布npm包
238 |
239 | [发布npm包教程](/web/knowledge/npm-publish.html)
240 |
--------------------------------------------------------------------------------
/docs/other/blog/up/sync-code.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 代码自动同步多个代码托管平台
3 | description: 一套代码自动同步到多个代码托管平台上,实现一次提交多平台存储
4 | ---
5 |
6 | # 代码自动同步多个代码托管平台
7 |
8 | ## 常见的代码托管平台
9 |
10 | * `GitHub`
11 | - 最大的代码托管平台,拥有庞大的用户群和丰富的功能。
12 | - 拥有免费的公共仓库,以及付费的私有仓库选项。
13 | - 强大的协作功能,支持分支管理、Pull Request、Issue跟踪等。
14 | - 拥有丰富的社区资源,方便学习和解决问题。
15 | - 支持CI/CD流程,方便自动化部署和测试。
16 | * `Gitee`
17 | - 中国本土的代码托管平台,用户界面简洁易用。
18 | - 支持多种语言和项目类型,拥有丰富的开发工具。
19 | - 提供免费的公共仓库和私有仓库选项。
20 | * `GitLab`
21 | - 功能类似于 GitHub,但更加注重安全性、隐私和自主性。
22 | - 提供免费的私有仓库,适合企业内部使用。
23 | - 支持CI/CD流程,方便自动化部署和测试。
24 |
25 | ## Github Actions 自动同步
26 |
27 | > **配置Actions好处是当我们提交代码到github的时候,代码会`自动更新同步`到gitee,便于国内用户访问**
28 |
29 | 我们可以利用 Github Actions,写一个工作流,在发现 Github 博客仓库的 master 分支代码更新后,自动同步当前代码到 Gitee 上。
30 |
31 | 关于 Github Actions 的介绍,可以参考阮一峰老师的 [《GitHub Actions 入门教程》](https://www.ruanyifeng.com/blog/2019/09/getting-started-with-github-actions.html)。
32 |
33 | 为了实现 Gitee 和 Github 的同步,我们需要借助一个 action,还好业界已经有现成的实现了,这里我采用的是 [Hub Mirror Action](https://github.com/Yikun/hub-mirror-action),我们可以看到使用的示例代码:
34 |
35 | ```yml
36 | name: syncToGitee
37 | on:
38 | push:
39 | branches:
40 | - master
41 | jobs:
42 | repo-sync:
43 | runs-on: ubuntu-latest
44 | steps:
45 | - name: Mirror the Github organization repos to Gitee.
46 | uses: Yikun/hub-mirror-action@master
47 | with:
48 | src: 'github/jiangwan1773'
49 | dst: 'gitee/jiangwan1773'
50 | dst_key: ${{ secrets.GITEE_PRIVATE_KEY }}
51 | dst_token: ${{ secrets.GITEE_TOKEN }}
52 | static_list: "blog" # 仓库名字
53 | force_update: true # 强制同步
54 | debug: true # 启用 `debug` 开关
55 | ```
56 |
57 | 其中有四个必填项:
58 | * `src` 表示需要被同步的源端账户名,即我们 `Github` 的账户名,因为我的 Github ID 是 jiangwan1773,所以这里我应该改成 `github/jiangwan1773`。
59 | * `dst` 表示需要同步到的目的端账户名,即我们 `Gitee` 的账户名,因为我的 Gitee ID 也是 jiangwan1773,所以这里我应该改成 `gitee/jiangwan1773`。
60 | * `dst_key` 表示用于在目的端上传代码的私钥,然后将其保存在 `Secrets` 中。
61 | 具体的操作步骤如下:
62 |
63 | 获取私钥:
64 |
65 | ```sh
66 | cat ~/.ssh/id_rsa
67 | ```
68 |
69 | 复制私钥内容,然后在要同步的 Github 仓库中,选择 "Setting" -> "Secrets" -> "Actions secrets and variables" -> "New repository secret"
70 |
71 | 填入 Secret 内容,Name 命名为 "GITEE_PRIVATE_KEY",Value 为复制的内容
72 |
73 | 然后点击 `Add secret` 即可。
74 |
75 | - `dst_token` 创建仓库的API tokens, 用于自动创建不存在的仓库。这里我们从 Gitee 上获取,[gitee地址](https://gitee.com/profile/personal_access_tokens)。生成并复制 Token,然后同样的步骤,保存在 Github 的 Secrets 中,Name 为 `GITEE_TOKEN`
76 |
77 | 那么我们就可以在仓库建立的根目录下,建立目录 `.github/workflows` ,然后创建一个名为 `syncToGitee.yml` 的文件:
78 | ```yml
79 | name: syncToGitee
80 | on:
81 | push:
82 | branches:
83 | - master
84 | jobs:
85 | repo-sync:
86 | runs-on: ubuntu-latest
87 | steps:
88 | - name: Mirror the Github organization repos to Gitee.
89 | uses: Yikun/hub-mirror-action@master
90 | with:
91 | src: 'github/ytlyy1773'
92 | dst: 'gitee/ytlyy1773'
93 | dst_key: ${{ secrets.GITEE_PRIVATE_KEY }}
94 | dst_token: ${{ secrets.GITEE_TOKEN }}
95 | static_list: "blog" # 仓库名字
96 | force_update: true # 强制同步
97 | debug: true # 启用 `debug` 开关
98 | ```
99 |
100 | [怎么配置GitHub Secrets 🚘](/other/blog/up/use-github-actions.html#怎么配置github-secrets)
101 |
102 | ## gitee pages Actions
103 |
104 | - 需要注意 `gitee pages` 目前已经 `停止服务`,具体的启用时间等官方说明
105 | - 以下完整配置注释部分是自动构建 `gitee pages` 的自动化配置
106 |
107 | ```yml
108 | name: syncToGitee
109 | on:
110 | push:
111 | branches:
112 | - master
113 | jobs:
114 | repo-sync:
115 | runs-on: ubuntu-latest
116 | steps:
117 | - name: Mirror the Github organization repos to Gitee.
118 | uses: Yikun/hub-mirror-action@master
119 | with:
120 | src: 'github/jiangwan1773'
121 | dst: 'gitee/jiangwan1773'
122 | dst_key: ${{ secrets.GITEE_PRIVATE_KEY }}
123 | dst_token: ${{ secrets.GITEE_TOKEN }}
124 | static_list: "blog" # 仓库名字
125 | force_update: true # 强制同步
126 | debug: true # 启用 `debug` 开关
127 |
128 | # - name: Build Gitee Pages
129 | # uses: yanglbme/gitee-pages-action@main
130 | # with:
131 | # # 注意替换为你的 Gitee 用户名
132 | # gitee-username: 'jiangwan1773'
133 | # # 注意在 Settings->Secrets 配置 GITEE_PASSWORD
134 | # gitee-password: ${{ secrets.GITEE_PASSWORD }}
135 | # # 注意替换为你的 Gitee 仓库,仓库名严格区分大小写,请准确填写,否则会出错
136 | # gitee-repo: 'jiangwan1773/blog'
137 | # # 要部署的分支,默认是 master,若是其他分支,则需要指定(指定的分支必须存在)
138 | # branch: github-pages
139 | ```
--------------------------------------------------------------------------------
/docs/.vitepress/config.mts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "vitepress";
2 | import nav from "./config/nav";
3 | import sidebar from "./config/sidebar";
4 |
5 | const chineLanguage = {
6 | docFooter: {
7 | prev: "上一篇",
8 | next: "下一篇",
9 | },
10 | sidebarMenuLabel: "菜单",
11 | outline: {
12 | label: "目录",
13 | },
14 | returnToTopLabel: "返回顶部",
15 | };
16 |
17 | export default defineConfig({
18 | title: "一条懒羊羊",
19 | description: "一条懒羊羊的博客,专注于前端开发技术分享,涵盖Vue、Wechat、Node.js、Harmony等框架教程。提供详实的开发工具推荐、Vitepress博客搭建指南、Linux实用技巧和SEO优化策略,帮助开发者提升技能,快速解决开发难题。",
20 | lang: "zh-CN",
21 | head: [
22 | [
23 | "meta",
24 | { name: "author", content: "一条懒羊羊, jiangwan1773@163.com, 中国深圳" },
25 | ],
26 | ["meta", { name: "theme-color", content: "#ffffff" }],
27 | ["link", { rel: "icon", href: "https://www.jwblog.cn/image/favicon.svg", type: "image/svg+xml" }],
28 | ["link", { rel: "icon", href: "https://www.jwblog.cn//image/favicon.png", type: "image/png" }],
29 | ["meta", { name: "og:title", content: "一条懒羊羊" }],
30 | ["meta", { name: "og:image", content: "https://www.jwblog.cn/image/logo.svg" }],
31 | ["meta", { name: "og:description", content: "一条懒羊羊的博客,记录vue, wechat, nodejs, harmony等前端知识。开发推荐使用软件, vitepress博客搭建教程,linux使用教程, 如何深度优化网站seo" }],
32 | [
33 | "meta",
34 | {
35 | name: "google-site-verification",
36 | content: "8-lfYPcn5-i4zwxIJonLSNdzZ02BmOE7_EGEEwEFOa4",
37 | },
38 | ], // jwblog.cn
39 | ["meta", { name: "baidu-site-verification", content: "codeva-dJz0bkO4UV" }], // jwblog.cn
40 | ["meta", { name: "baidu-site-verification", content: "codeva-ntA7Ws8139" }], // jwblog.cn
41 | [
42 | "script",
43 | {
44 | async: "",
45 | src: "https://www.googletagmanager.com/gtag/js?id=G-ZDDKYX0QGS",
46 | },
47 | ],
48 | [
49 | "script",
50 | {},
51 | `window.dataLayer = window.dataLayer || [];
52 | function gtag(){dataLayer.push(arguments);}
53 | gtag('js', new Date());
54 | gtag('config', 'G-ZDDKYX0QGS');`,
55 | ],
56 | ],
57 | sitemap: {
58 | hostname:
59 | process.env.BUILD_ENV === "vercel"
60 | ? "https://jwblog.vercel.app"
61 | : "https://www.jwblog.cn",
62 | },
63 | markdown: {
64 | theme: {
65 | light: 'github-dark',
66 | dark: 'one-dark-pro',
67 | }
68 | },
69 | themeConfig: {
70 | nav,
71 | sidebar,
72 | search:
73 | process.env.BUILD_ENV === "vercel"
74 | ? {
75 | provider: "local",
76 | }
77 | : {
78 | provider: "algolia",
79 | options: {
80 | appId: "2TMERJKE3X",
81 | apiKey: "e1e11e41381126a2bd77c23a3f84168e",
82 | indexName: "一条懒羊羊",
83 | placeholder: "请输入关键词",
84 | },
85 | },
86 | logo: {
87 | src: "https://www.jwblog.cn/image/logo.svg",
88 | width: 24,
89 | height: 24,
90 | },
91 | socialLinks: [
92 | { icon: "github", link: "https://github.com/ytlyy1773/blog.git" },
93 | {
94 | icon: {
95 | svg: '',
96 | },
97 | link: "https://gitee.com/ytlyy1773/blog",
98 | ariaLabel: 'gitee仓库'
99 | },
100 | ],
101 | lastUpdated: {
102 | text: '最后更新于'
103 | },
104 | footer: {
105 | message: `
豫公网安备41132402411828`,
106 | copyright: `豫ICP-备2023019165`,
107 | },
108 | ...chineLanguage,
109 | },
110 | });
111 |
--------------------------------------------------------------------------------
/docs/other/blog/up/use-linux.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 如何使用linux云服务器
3 | description: linux云服务器使用教程
4 | outline: [2, 3]
5 | ---
6 |
7 | # 如何使用linux云服务器
8 |
9 | ## 连接linux服务器
10 |
11 | > 服务器连接linux需要修改一次服务器密码,之后重启实例,注意是重启实例不是重启服务器
12 |
13 | ### 常见连接linux服务器的终端
14 | 1. Windows
15 | - cmd
16 | - powershell
17 | 2. Mac
18 | - 终端
19 | 3. 第三方
20 | - Xshell
21 |
22 | ```sh
23 | # 链接linux服务器命令
24 | ssr root@(ip)
25 | # 示例
26 | ssr root@110.110.110.110
27 | # 清理服务器密钥,可以重新输入服务器密钥
28 | ssh-keygen -R ip
29 | ```
30 |
31 | ### 服务器浏览项目
32 |
33 | > `linux` 没有所谓的图形界面,想要访问网站可以用命令进行访问
34 |
35 | ```sh
36 | curl https://localhost
37 | ```
38 |
39 | ## linu常用命令学习资源
40 |
41 | * [请参考 🚘](/other/system/linux/command.html)
42 | * [菜鸟教程 🚘](https://www.runoob.com/w3cnote/linux-common-command-2.html)
43 | * [45个常用Linux 命令 🚘](https://juejin.cn/post/6844903930166509581)
44 | * [阿里云开发者社区 🚘](https://developer.aliyun.com/article/842453)
45 |
46 | ## linu常见发行版
47 |
48 | > 以下三种博主都有使用过,服务器推荐使用 `Debain`
49 |
50 | - **Debain**
51 |
52 | - **Ubuntu**
53 |
54 | - **CentOs**
55 |
56 | ## Debain/Ubuntu
57 |
58 | ### Ubuntu是什么
59 |
60 | * 著名的Linux发行版之一,基于Debian,以桌面应用为主的Linux发行版
61 | * Ubuntu每六个月(即每年的四月与十月)发布一个新版本,长期支持(LTS)版本每两年发布一次。普通版本一般只支持9个月,但LTS版本一般能提供5年的支持。
62 | * `是目前最多用户的Linux版本`
63 |
64 | ### Ubuntu下载命令
65 | ```sh
66 | apt install packagesName
67 | ```
68 |
69 | > 下载报错
70 |
71 | ```bash
72 | Reading package lists... Done
73 | Building dependency tree... Done
74 | Reading state information... Done
75 | E: Unable to locate package nginx
76 | ```
77 |
78 | 使用 `apt update` 命令更新软件包列表。这将确保你拥有最新的软件包信息,在重新下载包。
79 |
80 | ```bash
81 | apt update
82 | ```
83 |
84 | ### 使用nginx教程
85 |
86 | [请参考 🚘](/other/blog/up/use-nginx.html)
87 |
88 | ## CentOs
89 |
90 | ### CentOs是什么
91 |
92 | * CentOS是Linux发行版之一,它是来自于Red Hat Enterprise Linux依照开放源代码规定发布的源代码所编译而成。
93 | * CentOs广泛用于 Web 服务器、数据库服务器、邮件服务器等
94 | * `CentOs目前已经停止更新`
95 |
96 | ### Ubuntu下载命令
97 |
98 | ```sh
99 | yum install packagesName
100 | ```
101 |
102 | ### CentOs下载git
103 |
104 |
105 | ```sh
106 | yum install git
107 | ```
108 |
109 | ::: tip 文件位置
110 | 安装路径
111 | ```sh
112 | /usr/share/git-core
113 | ```
114 | :::
115 |
116 | ### 使用git教程
117 |
118 | [请参考 🚘](/other/tools/git-command.html)
119 |
120 | ## 编写linux执行脚本
121 |
122 | 这里默认nginx的网页配置指向我们打包后的dist目录
123 |
124 | > 只需执行脚本即可完成项目代码的拉取,nginx的重载
125 |
126 | * root文件下新建脚本文件
127 | ```sh
128 | # 新建脚本文件
129 | touch update.sh
130 | # 编辑脚本
131 | vim update.sh
132 | ```
133 | * 按 i 进入插入模式
134 | * `/usr/local/code/demo` 为项目代码地址
135 | ::: tip 脚本内容
136 | ```sh
137 | cd /usr/local/code/demo && git pull
138 | nginx -s reload
139 | ```
140 | :::
141 | * 报错提示权限不足
142 | ::: warning 处理权限问题
143 | ```sh
144 | chmod +x update.sh
145 | ```
146 | :::
147 | * 配置完毕需要重启服务器实例才会生效
148 | * 执行脚本
149 | ```sh
150 | ./update.sh
151 | ```
152 |
153 | ## github自动执行服务器脚本
154 |
155 | > 通过 `github avtions` 实现代码提交,服务器自动执行脚本更新服务器内容
156 |
157 | [请参考 🚘](/other/blog/up/use-github-actions.html#github执行linux系统脚本)
158 |
159 |
160 | ## 升级脚本
161 |
162 | 执行脚本可以实现的效果
163 |
164 | * 拉取代码
165 | - 这里强烈建议使用 `ssh` 的方式链接github仓库。[ssh链接请参考 🚘](/other/tools/git-command.html#ssh链接)
166 | - 不然使用https的方式 `git pull` 经常失败,导致达不到我们想要的效果
167 | * 使用服务器的node进行打包
168 | * 执行nginx更新命令
169 |
170 | 环境准备
171 |
172 | * 服务器需要下载nvm
173 | * 通过nvm下载打包需要的node
174 | * 打包使用pnpm就下载pnpm
175 |
176 | ::: tip 脚本内容
177 | ```sh
178 | # git pull的时候,代码远端采用ssh绑定
179 | # 通过github actions执行脚本必须显式声明PATH
180 |
181 | # 确保 pnpm 和 Node.js 在 PATH 中
182 | export PATH=/root/.nvm/versions/node/v18.20.3/bin/:$PATH
183 |
184 | # 定义重试函数
185 | retry() {
186 | local n=1
187 | local max=5
188 | local delay=5
189 | while true; do
190 | "$@" && break || {
191 | if [[ $n -lt $max ]]; then
192 | ((n++))
193 | echo "Command failed. Attempt $n/$max:"
194 | sleep $delay;
195 | else
196 | echo "The command has failed after $n attempts."
197 | return 1
198 | fi
199 | }
200 | done
201 | }
202 |
203 | # 拉取代码并重试
204 | retry git -C /path/to/core/blog pull
205 |
206 | # 在脚本开头记录开始时间
207 | echo "Script started at $(date)" >> /var/log/up_script.log
208 | cd /path/to/core/blog && pnpm i && pnpm run build
209 |
210 | # 你的脚本内容
211 | echo "Executing script commands" >> /var/log/up_script.log
212 |
213 | nginx -s reload
214 |
215 | # 在脚本末尾记录结束时间
216 | echo "Script finished at $(date)" >> /var/log/up_script.log
217 | ```
218 | :::
219 |
220 | ## linux常见发行版对比
221 |
222 | | 发行版名称 | 基于 | 桌面环境 | 特点 | 适用人群 |
223 | |---|---|---|---|---|
224 | | **Ubuntu** | Debian | GNOME | 易用性强,软件源丰富,社区活跃,适合新手和开发者 | 桌面用户、开发者、服务器 |
225 | | **CentOS** | Red Hat Enterprise Linux (RHEL) | GNOME | 稳定性高,安全性好,适合服务器 | 服务器管理员、企业用户 |
226 | | **Fedora** | Red Hat Enterprise Linux (RHEL) | GNOME | 最新技术,创新性强,适合开发者和对新技术感兴趣的用户 | 开发者、技术爱好者 |
227 | | **Debian** | 自身 | GNOME | 稳定性高,自由软件的典范,适合追求稳定和自由的用户 | 服务器管理员、开发者 |
228 | | **Linux Mint** | Ubuntu | Cinnamon | 易用性强,外观美观,适合对Windows 用户体验有需求的用户 | 桌面用户 |
229 | | **Arch Linux** | 自身 | 用户自定义 | 灵活性高,可高度定制,适合有经验的Linux 用户 | 高级用户 |
230 | | **Manjaro** | Arch Linux | KDE Plasma | 基于Arch Linux,易用性更好,适合想体验Arch Linux但又不想折腾的用户 | 中级用户 |
231 | | **Kali Linux** | Debian | GNOME | 渗透测试、安全审计,预装大量渗透测试工具 | 安全专业人员、黑客 |
232 | | **openSUSE** | 自身 | KDE Plasma | 社区活跃,易于使用,适合开发者和系统管理员 | 开发者、系统管理员 |
233 |
234 | ### 各发行版特点简述
235 |
236 | * **Ubuntu:** 最受欢迎的Linux发行版之一,易于使用,软件源丰富,社区活跃。
237 | * **CentOS:** 稳定性高,安全性好,适合搭建服务器。
238 | * **Fedora:** 创新性强,经常引入最新的技术,适合开发者。
239 | * **Debian:** 稳定性高,自由软件的典范,适合追求稳定和自由的用户。
240 | * **Linux Mint:** 易用性强,外观美观,适合对Windows 用户体验有需求的用户。
241 | * **Arch Linux:** 灵活性高,可高度定制,适合有经验的Linux 用户。
242 | * **Manjaro:** 基于Arch Linux,易用性更好,适合想体验Arch Linux但又不想折腾的用户。
243 | * **Kali Linux:** 专为渗透测试和安全审计设计的。
244 | * **openSUSE:** 社区活跃,易于使用,适合开发者和系统管理员。
245 |
246 | ### 选择建议
247 |
248 | * **新手:** Ubuntu、Linux Mint
249 | * **服务器:** CentOS、Debian
250 | * **开发者:** Ubuntu、Fedora、openSUSE
251 | * **渗透测试:** Kali Linux
252 | * **追求稳定性:** CentOS、Debian
253 | * **追求个性化:** Arch Linux、Manjaro
254 |
255 | **注意:** 这只是一份简单的对比,每个发行版都有其独特的优势和适用场景。建议你在选择发行版之前,多了解一些相关信息,或者在虚拟机中尝试一下不同的发行版,找到最适合自己的那个。
--------------------------------------------------------------------------------
/docs/public/image/user.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/other/blog/up/use-nginx.md:
--------------------------------------------------------------------------------
1 | ---
2 | title: 怎么使用nginx
3 | description: 不同系统下怎么使用nginx
4 | outline: [2, 3]
5 | ---
6 |
7 | # 怎么使用nginx
8 |
9 | ## nginx介绍
10 |
11 | > Nginx是一个 轻量级/高性能的反向代理Web服务器,它是由C语言写的,所以速度非常快、性能非常优秀。它的主要功能就是反向代理、负载均衡、配置SSL证书、防盗链、解决跨域问题、缓存、限流、动静资源分离等等
12 |
13 | ::: info nginx的常用 `配置文件` 说明
14 | - `nginx.exe` nginx的启动文件,不推荐使用,建议使用命令行启动项目
15 | - `html` html文件夹下是默认的项目路径
16 | - `conf/nginx.conf` nginx的核心配置文件
17 | - `sites-available` Ubunto下的 `nginx server` 配置文件
18 | :::
19 |
20 | ::: tip nginx的 `常用命令`
21 |
22 | > 命令都需要在 `nginx文件目录下` 执行
23 |
24 | ```bash
25 | # windows server 启动 Nginx
26 | start nginx
27 | # linux启动 Nginx
28 | nginx
29 |
30 | # 停止 Nginx
31 | nginx -s stop
32 |
33 | # 重新加载配置(项目需要更新操作执行,最常用)
34 | nginx -s reload
35 | ```
36 | :::
37 |
38 |
39 | ## `windows server` 系统
40 |
41 | ::: info 如何使用nginx
42 | - 进入官网下载好nginx文件,进行解压
43 | - 在nginx文件目录下打开 `cmd` 终端
44 | - 执行命令 `start nginx` 启动nginx
45 | - 打开浏览器访问 `localhost` 可以看到 `Welcome to nginx!` 界面即成功
46 | - 把自己的项目打包后的dist文件内容放入 `nginx/html` 文件夹下
47 | - 执行 `nginx -s reload` 命令
48 | - 刷新 `localhost` 预览自己的博客项目
49 | :::
50 |
51 | ### 借助nginx实现自己的图片服务器
52 | [参考链接](/other/blog/up/setup-oss.html)
53 |
54 |
55 | ## `linux` 系统
56 |
57 | ### Ubuntu下载nginx
58 |
59 | 使用 `apt update` 命令更新软件包列表。这将确保你拥有最新的软件包信息。
60 |
61 | ```sh
62 | apt update
63 | apt install nginx
64 | ```
65 |
66 | ::: tip 文件位置
67 | - 配置文件路径
68 | ```sh
69 | /etc/nginx/nginx.conf
70 | # server配置文件
71 | /etc/nginx/sites-available
72 | ```
73 |
74 | - html默认文件路径
75 | ```sh
76 | /var/www/html
77 | ```
78 | :::
79 |
80 | ### CentOs下载nginx
81 |
82 | ```sh
83 | yum install nginx
84 | ```
85 | ::: tip 文件位置
86 | - 配置文件路径
87 | ```sh
88 | /etc/nginx/nginx.conf
89 | ```
90 |
91 | - html默认文件路径
92 | ```sh
93 | /usr/share/nginx/html
94 | ```
95 | :::
96 |
97 | ### 修改nginx配置
98 |
99 | ```sh
100 | cd /etc/nginx
101 | vim ./nginx.conf
102 | ```
103 | ::: warning vim模式无法编辑,需要进入 `插入模式`
104 | * 要进入插入模式,请按 i 键。
105 | * 要返回命令模式,请按 Esc 键。
106 | :::
107 |
108 | ## nginx配置参考
109 |
110 | Gzip压缩的配置也可以放在http对象下,和放在serve下略有区别
111 |
112 | ```nginx
113 | # Nginx 主配置文件
114 |
115 | # 使用Nginx用户
116 | user nginx;
117 |
118 | # 自动设置工作进程数量
119 | worker_processes auto;
120 |
121 | # 错误日志文件路径
122 | error_log /var/log/nginx/error.log;
123 |
124 | # PID 文件路径
125 | pid /run/nginx.pid;
126 |
127 | # 包含所有Nginx模块配置文件
128 | include /usr/share/nginx/modules/*.conf;
129 |
130 | events {
131 | # 设置每个工作进程的最大连接数
132 | worker_connections 1024;
133 | }
134 |
135 | http {
136 | # 日志格式定义
137 | log_format main '$remote_addr - $remote_user [$time_local] "$request" '
138 | '$status $body_bytes_sent "$http_referer" '
139 | '"$http_user_agent" "$http_x_forwarded_for"';
140 |
141 | # 访问日志文件路径和使用的日志格式
142 | access_log /var/log/nginx/access.log main;
143 |
144 | # 启用高效文件传输
145 | sendfile on;
146 | tcp_nopush on;
147 | tcp_nodelay on;
148 |
149 | # 设置长连接超时时间
150 | keepalive_timeout 65;
151 |
152 | # 增加类型哈希表的最大大小
153 | types_hash_max_size 4096;
154 |
155 | # 包含MIME类型映射表
156 | include /etc/nginx/mime.types;
157 |
158 | # 包含所有Nginx虚拟主机配置文件
159 | include /etc/nginx/conf.d/*.conf;
160 |
161 | server {
162 | # 监听80端口(HTTP)和443端口(HTTPS)
163 | listen 80;
164 | listen 443 ssl;
165 |
166 | # 配置服务器名
167 | server_name www.jwblog.cn;
168 |
169 | # 如果请求的端口不是443,则重定向到HTTPS
170 | if ($server_port !~ 443){
171 | rewrite ^(/.*)$ https://$host$1 permanent;
172 | }
173 |
174 | # SSL证书配置
175 | ssl_certificate cert/full_chain.pem;
176 | ssl_certificate_key cert/private.key;
177 | ssl_prefer_server_ciphers on;
178 |
179 | # 启用Gzip压缩
180 | gzip on;
181 | gzip_static on;
182 | gzip_min_length 1k; # 最小压缩文件大小
183 | gzip_buffers 4 16k; # 压缩缓冲区
184 | gzip_http_version 1.1; # HTTP版本
185 | gzip_comp_level 6; # 压缩级别
186 | gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml;
187 | gzip_vary on; # 根据请求头决定是否压缩
188 | gzip_proxied expired no-cache no-store private auth; # 压缩代理请求
189 | gzip_disable "MSIE [1-6]\."; # 禁用对IE 6及以下版本的压缩
190 |
191 | # 配置静态资源路径(如OSS存储的图片)
192 | location /images {
193 | root /path/to/data/images;
194 | }
195 |
196 | # 配置网站主目录
197 | location / {
198 | root /path/to/code/blog/docs/.vitepress/dist;
199 | index index.html index.htm;
200 | # 处理单页面应用程序的路由问题
201 | try_files $uri $uri/ /index.html;
202 | }
203 | }
204 | }
205 | ```
206 |
207 |
208 | ## nginx常见问题
209 |
210 | ### 页面刷新内容丢失
211 |
212 | > 刷新页面,路由url末尾会多拼接一个/
213 |
214 | ```nginx
215 | server {
216 | listen 80 default_server;
217 | listen [::]:80 default_server;
218 |
219 | root /项目存放路径/open-api-blog/out;
220 |
221 | index index.html;
222 |
223 | # 将所有以斜杠结尾的请求重定向到没有斜杠的URL
224 | location ~ ^(.+)/$ {
225 | return 301 $scheme://$host$1;
226 | }
227 |
228 | location / {
229 | try_files $uri $uri.html $uri/ @remove_slash;
230 | }
231 |
232 | # 处理找不到文件时的情况
233 | location @remove_slash {
234 | rewrite ^(.+)/$ $1 permanent;
235 | }
236 | }
237 | ```
238 |
239 | ### 客户端无法请求接口
240 |
241 | > 在服务器可以访问到相应的接口服务,通过nginx转发的就不可以
242 |
243 | ```nginx
244 | server {
245 | location ^~ /api/ {
246 | proxy_pass http://localhost:3000/;
247 | proxy_set_header Host $host;
248 | proxy_set_header X-Real-IP $remote_addr;
249 | proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
250 | proxy_set_header X-Forwarded-Proto $scheme;
251 | }
252 | }
253 | ```
254 |
255 | 将上边的代码补充道nginx的配置文件中
256 |
257 | location ^~ /api/ 是核心
258 |
259 | * `proxy_pass http://localhost:3000/`;
260 |
261 | 将匹配到的请求代理到 http://127.0.0.1:3000 这个地址。
262 |
263 | 后面的 / 表示将请求的 URI 路径部分完整地传递给后端服务器。
264 |
265 | * `proxy_set_header Host $host`;
266 |
267 | 将原始请求的 Host 头部信息传递给后端服务器,以便后端服务器能够正确地处理请求。
268 |
269 | * `proxy_set_header X-Real-IP $remote_addr`;
270 |
271 | 将客户端的真实 IP 地址添加到 X-Real-IP 头部中,以便后端服务器能够获取客户端的真实 IP 地址。
272 |
273 | * `proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for`;
274 |
275 | 将客户端的 IP 地址以及之前经过的代理服务器的 IP 地址添加到 X-Forwarded-For 头部中。
276 |
277 | * `proxy_set_header X-Forwarded-Proto $scheme`;
278 |
279 | 将客户端使用的协议(http 或 https)添加到 X-Forwarded-Proto 头部中。
--------------------------------------------------------------------------------
/docs/web/vue/preview/preview.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
8 |
11 |
18 |
25 |
![]()
26 |
27 |
28 |
29 |
30 |
31 |
167 |
168 |
272 |
--------------------------------------------------------------------------------
/docs/.vitepress/config/sidebar.js:
--------------------------------------------------------------------------------
1 | export default {
2 | "/web/basics": getWebBasics(),
3 | "/web/vue": getWebVue(),
4 | "/web/harmony": getWebHarmony(),
5 | "/web/wechat": getWebWeChat(),
6 | "/web/knowledge": getKnowledge(),
7 | "/web/h5": getWebH5(),
8 | "/other/tools": getOtherTools(),
9 | "/other/system": getComputerList(),
10 | "/other/blog": getDevelopBlog(),
11 | "/api/install-software": getSoftwareInstallation(),
12 | };
13 |
14 | function getWebBasics() {
15 | return [
16 | {
17 | text: "html+css+javaScript",
18 | collapsed: false,
19 | items: [
20 | { text: "常用的正则表达式使用", link: "/web/basics/regExp" },
21 | { text: "前端加密安全", link: "/web/basics/code-safety" },
22 | { text: "Promise理解", link: "/web/basics/code-promise.md" },
23 | { text: "优雅的代码-es6实践", link: "/web/basics/es6-practice.md" },
24 | { text: "浏览器的回流与重绘", link: "/web/basics/reflow-repaint.md" },
25 | ],
26 | },
27 | {
28 | text: "javaScript",
29 | collapsed: true,
30 | items: [
31 | { text: "JS数组的清空", link: "/web/basics/clear-array.md" },
32 | { text: "JS实现文件下载", link: "/web/basics/download.md" },
33 | { text: "javascript(js)判断对象是否包含某个 key", link: "/web/basics/exist-key.md" },
34 | { text: "js判断内容是不是是NaN", link: "/web/basics/is-NaN.md" },
35 | { text: "JavaScript 实现 Sleep(伪 sleep)", link: "/web/basics/sleep.md" }
36 | ],
37 | },
38 | {
39 | text: "css",
40 | collapsed: true,
41 | items: [
42 | { text: "CSS动画库推荐", link: "/web/basics/css/tool.md" },
43 | { text: "CSS实现0.5px的线", link: "/web/basics/line.md" },
44 | { text: "CSS处理一行或多行文字超出用省略号", link: "/web/basics/hidden.md" },
45 | { text: "CSS解决纯英文文字不会自动换行", link: "/web/basics/wrap.md" },
46 | { text: "CSS清楚浮动", link: "/web/basics/float.md" },
47 | { text: "CSS绘制三角形", link: "/web/basics/triangle.md" },
48 | { text: "CSS控制虚线间距虚线长度", link: "/web/basics/dashed-line.md" },
49 | { text: "CSS使用sass语法", link: "/web/basics/use-sass.md" }
50 | ],
51 | },
52 | {
53 | text: "html",
54 | collapsed: true,
55 | items: [
56 | { text: "HTML元素之间有间隙", link: "/web/basics/gap.md" },
57 | { text: "Html预览word,pdf,excel", link: "/web/basics/preview.md" },
58 | ],
59 | },
60 | ]
61 | }
62 |
63 | function getWebVue() {
64 | return [
65 | {
66 | text: "vue",
67 | collapsed: false,
68 | items: [
69 | { text: "Vue项目常用插件", link: "/web/vue/plugins.md" },
70 | { text: "Vue + ts项目技巧", link: "/web/vue/project-template.md" },
71 | { text: "vue2项目打包方式webpack升级vite", link: "/web/vue/upgradation/up-vite.md" },
72 | { text: "Vue2重置data里边的数据", link: "/web/vue/resetData.md" },
73 | { text: "妙用Computed", link: "/web/vue/use-computed.md" },
74 | { text: "js获取电脑ip", link: "/web/vue/local.md" },
75 | { text: "在css中使用vue的变量", link: "/web/vue/css-use-vue.md" },
76 | { text: "vue中freeze和Readonly的区别", link: "/web/vue/freeze.md" },
77 | { text: "vue组件发布npm", link: "/web/vue/publish-npm.md" },
78 | { text: "常见的打包格式", link: "/web/vue/packaging-format.md" },
79 | ],
80 | },
81 | {
82 | text: "Component",
83 | collapsed: true,
84 | items: [
85 | { text: "Component-封装上传图片", link: "/web/vue/upload-image/core.md" },
86 | { text: "Component-封装dialog弹窗", link: "/web/vue/dialog/core.md" },
87 | { text: "Component-封装图片预览功能", link: "/web/vue/preview/core.md" },
88 | ],
89 | },
90 | {
91 | text: "BUG",
92 | collapsed: true,
93 | items: [
94 | { text: "BUG-el-table设置高度之后合计行不显示解决方法", link: "/web/vue/bug-table.md" },
95 | ],
96 | },
97 | ]
98 | }
99 |
100 |
101 | function getWebHarmony() {
102 | return [
103 | { text: "Harmony 属性和参数的区别", link: "/web/harmony/distinction.md" },
104 | { text: "Harmony 实现双飞翼(圣杯)布局", link: "/web/harmony/holy-grail.md" },
105 | { text: "Harmony 实现宽高等比", link: "/web/harmony/aspect-ratio.md" },
106 | { text: "Harmony 使用Image资源的4种方法", link: "/web/harmony/use-image.md" },
107 | { text: "Harmony 控制组件是否可见", link: "/web/harmony/show.md" },
108 | ]
109 | }
110 |
111 | function getWebWeChat() {
112 | return [
113 | {
114 | text: "微信小程序",
115 | collapsed: false,
116 | items: [
117 | { text: "借助Object.defineProperty实现小程序的watch", link: "/web/wechat/code-watch.md" },
118 | { text: "小程序自定义顶部导航栏组件", link: "/web/wechat/custom-nav.md" },
119 | { text: "小程序生命周期", link: "/web/wechat/life-cycle.md" },
120 | { text: "微信小程序全局添加分享功能", link: "/web/wechat/global-share.md" },
121 | { text: "onShow生命周期拿到onLoad生命周期里边的路由传参", link: "/web/wechat/get-page-options.md" },
122 | { text: "微信小程序出现弹窗页面禁止滚动", link: "/web/wechat/prohibit-scrolling.md" },
123 | { text: "微信request的二次封装", link: "/web/wechat/api-request.md" },
124 | ],
125 | },
126 | ]
127 | }
128 |
129 | function getWebH5() {
130 | return [
131 | {
132 | text: "H5",
133 | collapsed: false,
134 | items: [
135 | { text: "font-size在移动端设备上字体变大的问题", link: "/web/h5/font-deformation.md" },
136 | { text: "iphone单机事件有300毫秒延迟的处理", link: "/web/h5/handle-delay.md" },
137 | { text: "iphone底部安全距离", link: "/web/h5/safe-distance.md" },
138 | { text: "限制浏览器返回", link: "/web/h5/limit-back.md" },
139 | ],
140 | },
141 | ]
142 | }
143 |
144 | function getKnowledge() {
145 | return [
146 | {
147 | text: "前端知识",
148 | items: [
149 | { text: "使用阿里云npm镜像加速", link: "/web/knowledge/npm-registry.md" },
150 | { text: "发布npm包", link: "/web/knowledge/npm-publish.md" },
151 | { text: "pm2使用教程", link: "/web/knowledge/use-pm2.md" },
152 | ],
153 | },
154 | ]
155 | }
156 |
157 | function getOtherTools() {
158 | return [
159 | {
160 | text: "tools",
161 | collapsed: false,
162 | items: [
163 | { text: "电脑工具合集", link: "/other/tools/collect.md" },
164 | { text: "科学上网", link: "/other/tools/internet.md" },
165 | { text: "git命令", link: "/other/tools/git-command.md" },
166 | { text: "GitHub徽标", link: "/other/tools/link/logo.md" }
167 | ],
168 | },
169 | {
170 | text: "前端",
171 | collapsed: false,
172 | items: [
173 | { text: "前端开发工具", link: "/other/tools/web/collect.md" }
174 | ],
175 | },
176 | ]
177 | }
178 |
179 | function getComputerList() {
180 | return [
181 | {
182 | text: "windows",
183 | collapsed: false,
184 | items: [
185 | { text: "如何除去Windows的快捷方式小图标", link: "/other/system/win/clear-icon.md" }
186 | ],
187 | },
188 | {
189 | text: "linux",
190 | collapsed: false,
191 | items: [
192 | { text: "linux发行版", link: "/other/system/linux/release.md" },
193 | { text: "linux常用命令", link: "/other/system/linux/command.md" }
194 | ],
195 | },
196 | {
197 | text: "mac",
198 | collapsed: false,
199 | items: [
200 | { text: "无法安装第三方软件", link: "/other/system/mac/install-error.md" }
201 | ],
202 | }
203 | ]
204 | }
205 |
206 | function getDevelopBlog() {
207 | return [
208 | {
209 | text: "Develop Blog",
210 | collapsed: false,
211 | items: [
212 | { text: "怎么写博客", link: "/other/blog/basics/write.md" },
213 | { text: "网站的部署发布", link: "/other/blog/basics/deploy.md" },
214 | { text: "Seo", link: "/other/blog/basics/seo-info.md" }
215 | ],
216 | },
217 | {
218 | text: "提升相关",
219 | collapsed: false,
220 | items: [
221 | { text: "代码自动同步多个代码托管平台", link: "/other/blog/up/sync-code.md" },
222 | { text: "github pages", link: "/other/blog/up/use-page.md" },
223 | { text: "怎么使用nginx", link: "/other/blog/up/use-nginx.md" },
224 | { text: "网站升级https", link: "/other/blog/up/up-https.md" },
225 | { text: "vitepress配置algolia", link: "/other/blog/up/config-algolia.md" },
226 | { text: "nginx搭建对象存储OSS", link: "/other/blog/up/setup-oss.md" },
227 | { text: "如何使用linux云服务器", link: "/other/blog/up/use-linux.md" },
228 | { text: "如何使用github actions自动化工作流", link: "/other/blog/up/use-github-actions.md" },
229 | ],
230 | },
231 | ]
232 | }
233 |
234 | function getSoftwareInstallation() {
235 | return [
236 | {
237 | text: "docker",
238 | collapsed: false,
239 | items: [
240 | { text: "docker", link: "/api/install-software/docker/index.html" },
241 | { text: "mysql", link: "/api/install-software/docker/mysql.html" },
242 | { text: "redis", link: "/api/install-software/docker/redis.html" },
243 | { text: "mac安装mysql", link: "/api/install-software/mysql.html" }
244 | ],
245 | },
246 | ]
247 | }
248 |
--------------------------------------------------------------------------------
/docs/public/image/favicon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------