u
No files matched your search
@@ -49,5 +49,9 @@
|
|||||||
"scss",
|
"scss",
|
||||||
"pcss",
|
"pcss",
|
||||||
"postcss"
|
"postcss"
|
||||||
]
|
],
|
||||||
|
|
||||||
|
"markdown.copyFiles.destination": {
|
||||||
|
"**/*.md": "${documentDirName}/assets/${unixTime}.${fileExtName}"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
## 设置页面背景色
|
||||||
|
|
||||||
|
在 `pages.json` 中设置 `backgroundColor` 并未生效。
|
||||||
|
|
||||||
|
设置全局背景色在 `App.vue` 中进行设置
|
||||||
|
|
||||||
|
```css
|
||||||
|
<!--此标签需要新建,不要和样式搞在一起-->
|
||||||
|
<style>
|
||||||
|
page {
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
设置单个页面背景色就在对应的页面中设置
|
||||||
|
|
||||||
|
```css
|
||||||
|
<!--此标签需要新建,不要和样式搞在一起-->
|
||||||
|
<style scoped>
|
||||||
|
page {
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
``` css
|
||||||
|
<style>
|
||||||
|
page {
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
```
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
## 白屏问题
|
||||||
|
|
||||||
|
环境:
|
||||||
|
|
||||||
|
- 浏览器:Chrome56
|
||||||
|
- Unibest:快速开发框架,官网:https://unibest.tech/
|
||||||
|
|
||||||
|
出现白屏参考上面的方案。
|
||||||
|
|
||||||
|
使用的是 Vscode 模板的话,直接参考 [vue3\_低版本浏览器适配.md](..\vue\vue3\vue3_低版本浏览器适配.md)
|
||||||
|
|
||||||
|
使用的是 Hbuilderx 模板的话,在根目录下添加`vite.config.js`文件
|
||||||
|
|
||||||
|
```js
|
||||||
|
import Uni from '@dcloudio/vite-plugin-uni'
|
||||||
|
import legacy from '@vitejs/plugin-legacy'
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
plugins: [
|
||||||
|
uni(),
|
||||||
|
legacyPlugin({
|
||||||
|
// 配置参考上面的 md 文件
|
||||||
|
})
|
||||||
|
]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## 原生Tabbar遮挡
|
||||||
|
|
||||||
|
如果Uniapp原生的Tabbar会遮挡一部分内容,这是因为部分低版本浏览器可能不支持 `env` 计算函数,所以导致整个样式设置失效。
|
||||||
|
|
||||||
|
**解决方案:**
|
||||||
|
|
||||||
|
新建 `/hooks/useSafeAreaBottom` 文件夹
|
||||||
|
|
||||||
|
在该目录下新建 `index.ts` 和 `index.css` 文件,添加一下内容
|
||||||
|
`index.css`:
|
||||||
|
|
||||||
|
```css
|
||||||
|
.safe-area-bottom {
|
||||||
|
padding-bottom: 50px;
|
||||||
|
padding-bottom: calc(50px + constant(safe-area-inset-bottom));
|
||||||
|
padding-bottom: calc(50px + env(safe-area-inset-bottom));
|
||||||
|
}
|
||||||
|
// 设置为50px是因为Uniapp的tabber的高度固定为50px。
|
||||||
|
```
|
||||||
|
|
||||||
|
`index.ts`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import './index.css'
|
||||||
|
|
||||||
|
export function useSafeAreaBottom(): {
|
||||||
|
safeAreaInsets: UniApp.GetSystemInfoResult['safeAreaInsets']
|
||||||
|
needSafeAreaBottom: boolean
|
||||||
|
} {
|
||||||
|
const systemInfo = uni.getSystemInfoSync()
|
||||||
|
|
||||||
|
const safeAreaInsets: UniApp.GetSystemInfoResult['safeAreaInsets']
|
||||||
|
= systemInfo.safeAreaInsets ?? {
|
||||||
|
top: 0,
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
// ✅ 仅检测是否支持 env(safe-area-inset-bottom)
|
||||||
|
const supportsEnv
|
||||||
|
= typeof window !== 'undefined'
|
||||||
|
&& 'CSS' in window
|
||||||
|
&& typeof CSS.supports === 'function'
|
||||||
|
&& CSS.supports('padding-bottom', 'env(safe-area-inset-bottom)')
|
||||||
|
|
||||||
|
const needSafeAreaBottom = !supportsEnv
|
||||||
|
|
||||||
|
return {
|
||||||
|
safeAreaInsets,
|
||||||
|
needSafeAreaBottom,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
使用:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<view
|
||||||
|
:class="{ 'safe-area-bottom': needSafeAreaBottom }"
|
||||||
|
:style="{ marginTop: safeAreaInsets.top + 'px' }"
|
||||||
|
>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { useSafeAreaBottom } from '@/hooks/useSafeAreaBottom/index'
|
||||||
|
|
||||||
|
const { safeAreaInsets, needSafeAreaBottom } = useSafeAreaBottom()
|
||||||
|
</script>
|
||||||
|
```
|
||||||
@@ -0,0 +1,381 @@
|
|||||||
|
> 背景:现在使用 HBuilderX 打自定义基座的话,一个账号会有限制次数。并且时间过慢。
|
||||||
|
|
||||||
|
## 1. 安装 Android Studio
|
||||||
|
|
||||||
|
使用该工具进行自定义基座。
|
||||||
|
|
||||||
|
下载地址:https://developer.android.com/studio?hl=zh-cn
|
||||||
|
|
||||||
|
按照顺序安装即可,注意SDK的位置不要安装到C盘
|
||||||
|
|
||||||
|
## 2. 下载 HBuilderX 离线SDK
|
||||||
|
|
||||||
|
下载地址:https://nativesupport.dcloud.net.cn/AppDocs/download/android.html
|
||||||
|
|
||||||
|
**注意:下载的 SDK 的版本需要与 HBuilderX 的版本保持一致。**
|
||||||
|
|
||||||
|
历史版本:https://pan.baidu.com/share/init?surl=KtOCtMZJSgfAayHNjTpdTg&pwd=4hvi
|
||||||
|
|
||||||
|
## 3. 导入 HBuilder-Integrate-AS 项目到 Android Studio
|
||||||
|
|
||||||
|
解压从 HBuilderX 下载后的 Android-SDK,使用 Android Studio 打开解压后的 HBuilder-Integrate-AS 项目。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
导入成功后,会发现目录只有部分内容。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
这时候需要将 Android 更新为 Project 既可查看到项目全部内容
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
修改后的效果
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 4. 配置 Andriod Studio
|
||||||
|
|
||||||
|
配置 JDK ,配置路径:Settings - Build - Build Tools - Gradle
|
||||||
|
|
||||||
|
将 Gradle JDK 的路径修改为本地的路径,修改后点击 `Apply` 即可。注意:JDK 的版本需要和 Gradle 的版本进行适配,如果不适配那么运行的时候也会有详细的报错信息。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 5. Uniapp开发者中心 申请相关信息
|
||||||
|
|
||||||
|
### 5.1 创建应用
|
||||||
|
|
||||||
|
首先根据应用名称检查是否已经存在当前的项目。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
有过没有的话则点击右上角的 `创建应用` 按钮进行创建:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
创建成功后会添加到 **我的应用** 列表中
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
点击对应的 **应用名称** 即可进入对应的应用
|
||||||
|
|
||||||
|
### 5.2 申请云端证书
|
||||||
|
|
||||||
|
点击创建证书
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
因为需要时间,过段时间刷新即可
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
创建成功后,点击 **证书详情 ** 这里面有需要的一些信息。
|
||||||
|
|
||||||
|
需要的有 别名、MD5、SHA1、SHA256
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
同时还需要证书密码,点击 **查看证书密码 ** 即可获取到。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
现在记录的信息有: 别名、MD5、SHA1、SHA256、证书密码
|
||||||
|
|
||||||
|
注意下载申请过的证书,后面需要用到
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 5.3 新增平台信息
|
||||||
|
|
||||||
|
进入 **各平台信息** ,点击 **新增** 按钮
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
填写以下信息,注意填写包名(任意),该包名后面使用到。这个时候 SHA1、MD5、SHA256 就是在 [5.2 申请云端证书](#52-申请云端证书) 章节申请的信息。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
创建成功后就会显示
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
创建离线Key,点击刚刚创建的平台信息的 创建离线Key 按钮
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
点击进行创建,创建成功后,会显示 **查看离线Key**
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
点击查看对应的离线Key,主要保留该值,后面会用到
|
||||||
|
|
||||||
|
## 6. 配置导入过的 HBuilder-Integrate-AS 项目
|
||||||
|
|
||||||
|
配置 `HBuilder-Integrate-AS\simpleDemo\build.gradle` ,这些修改的信息 已经都在 [5. Uniapp开发者中心 申请相关信息](#5-Uniapp开发者中心 申请相关信息) 申请过了,我已标注。注意下载云端证书,并放到 simpleDemo 目录下。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
替换 离线Key(该值就在 [5.3 新增平台信息](#53-新增平台信息) 申请过了),配置 `HBuilder-Integrate-AS\simpleDemo\src\main\AndroidManifest.xml` 文件。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
配置 `HBuilder-Integrate-AS\simpleDemo\src\main\assets\data\dcloud_control.xml` ,替换自己项目的appid。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 7. Hbuilder X 导出本地打包资源
|
||||||
|
|
||||||
|
注意 APPID 需要和创建应用的 appid 保持一致。如果不一致,可以去源码视图进行修改
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
导出成功后,路径参考:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
复制 **resources** 文件夹下面文件夹,然后替换 **HBuilder-Integrate-AS** 项目中的 `HBuilder-Integrate-AS\simpleDemo\src\main\assets\apps\__UNI__A` 目录,将 `__UNI__A` 文件夹替换为导出的 `__UNI__9063282` 文件夹,替换后如下:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
确保 应用版本名称 和 应用版本号保持一致
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 8. 运行项目
|
||||||
|
|
||||||
|
先进行加载配置好的项目
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
加载成功后即可出现蓝色运行按钮,点击运行即可
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 9. 导入原生插件
|
||||||
|
|
||||||
|
> 如果不需要该步可以忽略,不影响自定义基座。
|
||||||
|
|
||||||
|
参考网站:https://zh.uniapp.dcloud.io/plugin/native-plugin.html#%E6%9C%AC%E5%9C%B0%E6%8F%92%E4%BB%B6-%E9%9D%9E%E5%86%85%E7%BD%AE%E5%8E%9F%E7%94%9F%E6%8F%92%E4%BB%B6
|
||||||
|
|
||||||
|
### 9.1 下载插件
|
||||||
|
|
||||||
|
这里用 **DCloud-RichAlert** 举例,插件下载地址:https://ext.dcloud.net.cn/plugin?id=36
|
||||||
|
|
||||||
|
下载完毕后,新建 **nativeplugins** 文件夹,将解压后的插件放到该文件夹下面
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
9.2 配置本地插件
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
选择插件
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
配置成功页面
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
然后就可以使用啦,在页面中添加测试代码
|
||||||
|
|
||||||
|
```html
|
||||||
|
<template>
|
||||||
|
<view class="content">
|
||||||
|
<image class="logo" src="/static/logo.png"></image>
|
||||||
|
<view class="text-area">
|
||||||
|
<text class="title">{{title}}</text>
|
||||||
|
</view>
|
||||||
|
</view>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
title: 'Hello',
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onLoad() {
|
||||||
|
const dcRichAlert = uni.requireNativePlugin('DCloud-RichAlert')
|
||||||
|
dcRichAlert.show(
|
||||||
|
{
|
||||||
|
position: 'bottom',
|
||||||
|
title: '提示信息',
|
||||||
|
titleColor: '#FF0000',
|
||||||
|
content:
|
||||||
|
"<a href='https://uniapp.dcloud.io/' value='Hello uni-app'>uni-app</a> 是一个使用 Vue.js 开发跨平台应用的前端框架!\n免费的\n免费的\n免费的\n重要的事情说三遍",
|
||||||
|
contentAlign: 'left',
|
||||||
|
checkBox: {
|
||||||
|
title: '不再提示',
|
||||||
|
isSelected: true,
|
||||||
|
},
|
||||||
|
buttons: [
|
||||||
|
{
|
||||||
|
title: '取消',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '否',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '确认',
|
||||||
|
titleColor: '#3F51B5',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
(result) => {
|
||||||
|
switch (result.type) {
|
||||||
|
case 'button':
|
||||||
|
console.log('callback---button--' + result.index)
|
||||||
|
break
|
||||||
|
case 'checkBox':
|
||||||
|
console.log('callback---checkBox--' + result.isSelected)
|
||||||
|
break
|
||||||
|
case 'a':
|
||||||
|
console.log('callback---a--' + JSON.stringify(result))
|
||||||
|
break
|
||||||
|
case 'backCancel':
|
||||||
|
console.log('callback---backCancel--')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
},
|
||||||
|
)
|
||||||
|
},
|
||||||
|
methods: {},
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
当然,现在还没有结束,如果需要在本地看到效果,需要重复 [7. Hbuilder X 导出本地打包资源](#7-Hbuilder X 导出本地打包资源) 步骤,将新的打包资源将旧的替换掉。
|
||||||
|
|
||||||
|
### 9.3 配置项目
|
||||||
|
|
||||||
|
**重要的下一步**,将 `nativeplugins\DCloud-RichAlert\android\uniplugin_richalert.aar` 复制到 `HBuilder-Integrate-AS\simpleDemo\libs` 文件夹下。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
然后呢,还没有结束哦。
|
||||||
|
|
||||||
|
在assets目录下创建 **dcloud_uniplugins.json** 文件,添加以下内容
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"nativePlugins": [
|
||||||
|
{
|
||||||
|
"plugins": [
|
||||||
|
{
|
||||||
|
"type": "module",
|
||||||
|
"name": "DCloud-RichAlert",
|
||||||
|
"class": "uni.dcloud.io.uniplugin_richalert.RichAlertWXModule"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|

|
||||||
|
|
||||||
|
### 9.4 配置gradle文件
|
||||||
|
|
||||||
|
添加制定依赖。
|
||||||
|
|
||||||
|
```
|
||||||
|
dependencies {
|
||||||
|
implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'], exclude: [])
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||||
|
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
|
||||||
|
implementation 'androidx.core:core:1.1.0'
|
||||||
|
implementation "androidx.fragment:fragment:1.1.0"
|
||||||
|
implementation 'androidx.recyclerview:recyclerview:1.1.0'
|
||||||
|
implementation 'com.facebook.fresco:fresco:2.5.0'
|
||||||
|
implementation "com.facebook.fresco:animated-gif:2.5.0"
|
||||||
|
implementation 'com.github.bumptech.glide:glide:4.9.0'
|
||||||
|
implementation 'com.alibaba:fastjson:1.2.83'
|
||||||
|
implementation 'androidx.webkit:webkit:1.5.0'
|
||||||
|
// 基座需要,必须添加。主要是这个是
|
||||||
|
implementation 'com.github.bumptech.glide:glide:4.9.0'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 9.5 运行项目
|
||||||
|
|
||||||
|
然后就是可以重新运行项目啦。运行成功的结果如下:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 10. 自定义基座
|
||||||
|
|
||||||
|
### 10.1 Debug 配置
|
||||||
|
|
||||||
|
修改 `HBuilder-Integrate-AS\simpleDemo\src\main\assets\data\dcloud_control.xml` 文件,设置 Debug 模式:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<hbuilder debug="true" syncDebug="true">
|
||||||
|
<apps>
|
||||||
|
<app appid="__UNI__ID" appver=""/>
|
||||||
|
</apps>
|
||||||
|
</hbuilder>
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
修改 `HBuilder-Integrate-AS\simpleDemo\build.gradle` 在该文件中添加 **okhttp3** 依赖
|
||||||
|
|
||||||
|
```
|
||||||
|
dependencies {
|
||||||
|
implementation "com.alibaba:fastjson:1.2.83"
|
||||||
|
implementation "com.squareup.okhttp3:okhttp:3.12.12"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 10.2 导入 Debug SDK
|
||||||
|
|
||||||
|
需要导入的 SDK 位于 `Android-SDK@4.66.82418_20250520\SDK\libs` 中
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
将 **debug-server-release.aar** 复制到 **libs** 下面
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 10.3 生成APK文件
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
生成后会生成在 debug 目录下
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 10.4 复制APK文件到HBuilderX中
|
||||||
|
|
||||||
|
1. 在HBuilderX项目中创建创建 unpackage 目录,在 unpackage 目录中创建 debug 目录,将上述生成的APK文件拷贝到debug目录中。
|
||||||
|
2. **重命名**文件为 **android_debug.apk**,目录结构参考下图
|
||||||
|

|
||||||
|
|
||||||
|
### 10.5 运行自定义基座
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
选择自定义基座
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
点击运行,运行结果如下:
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
同时能支持 **热更新** 。修改下,查看效果吧。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 11. 模块及三方 SDK 配置
|
||||||
|
|
||||||
|
参考官网:https://nativesupport.dcloud.net.cn/AppDocs/usemodule/androidModuleConfig/others.html
|
||||||
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 22 KiB |
|
After Width: | Height: | Size: 55 KiB |
|
After Width: | Height: | Size: 131 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 69 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 51 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 208 KiB |
|
After Width: | Height: | Size: 212 KiB |
|
After Width: | Height: | Size: 111 KiB |
|
After Width: | Height: | Size: 128 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 41 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 105 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 137 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 114 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 47 KiB |
|
After Width: | Height: | Size: 124 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 39 KiB |
|
After Width: | Height: | Size: 117 KiB |
|
After Width: | Height: | Size: 49 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 94 KiB |
|
After Width: | Height: | Size: 26 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 48 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 17 KiB |
@@ -0,0 +1,65 @@
|
|||||||
|
环境:
|
||||||
|
- 浏览器:Chrome56
|
||||||
|
- Vue:^3.5.15
|
||||||
|
- Vite:6.3.5
|
||||||
|
|
||||||
|
解决方案:
|
||||||
|
|
||||||
|
`@vitejs/plugin-legacy` ,该包是Vite提供的一个插件,为打包后的文件提供传统浏览器兼容性支持。官网:https://github.com/vitejs/vite/tree/main/packages/plugin-legacy
|
||||||
|
|
||||||
|
`terser`,主要用于压缩代码,还有代码混淆、源码映射等功能。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm i @vitejs/plugin-legacy terser -D
|
||||||
|
```
|
||||||
|
|
||||||
|
安装上述依赖后,在 `vite.config.ts/js` 中添加以下内容:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import legacy from '@vitejs/plugin-legacy'
|
||||||
|
// 在插件处添加一下功能
|
||||||
|
plugins: [
|
||||||
|
legacy({
|
||||||
|
// 目标浏览器环境,'defaults' 是浏览器列表默认设置,支持 Chrome 56 及以上
|
||||||
|
targets: ['defaults', 'Chrome >= 56'],
|
||||||
|
|
||||||
|
// 额外引入的兼容性 polyfill,这里加入了对 generator 函数的支持
|
||||||
|
additionalLegacyPolyfills: ['regenerator-runtime/runtime'],
|
||||||
|
|
||||||
|
// 是否生成兼容旧浏览器的代码块(chunk)
|
||||||
|
renderLegacyChunks: true,
|
||||||
|
|
||||||
|
// 需要引入的具体 polyfill 列表,确保目标环境缺失的 API 得到支持
|
||||||
|
polyfills: [
|
||||||
|
'es.symbol', // Symbol 支持
|
||||||
|
'es.array.filter', // Array.prototype.filter 支持
|
||||||
|
'es.promise', // Promise 支持
|
||||||
|
'es.promise.finally', // Promise.prototype.finally 支持
|
||||||
|
'es.object.assign', // Object.assign 支持
|
||||||
|
'es.map', // Map 支持
|
||||||
|
'es.set', // Set 支持
|
||||||
|
'es.array.for-each', // Array.prototype.forEach 支持
|
||||||
|
'es.object.define-properties', // Object.defineProperties 支持
|
||||||
|
'es.object.define-property', // Object.defineProperty 支持
|
||||||
|
'es.object.get-own-property-descriptor', // Object.getOwnPropertyDescriptor 支持
|
||||||
|
'es.object.get-own-property-descriptors', // Object.getOwnPropertyDescriptors 支持
|
||||||
|
'es.object.keys', // Object.keys 支持
|
||||||
|
'es.object.to-string', // Object.prototype.toString 支持
|
||||||
|
'web.dom-collections.for-each', // DOM 集合的 forEach 支持
|
||||||
|
'esnext.global-this', // 全局变量 globalThis 支持
|
||||||
|
'esnext.string.match-all', // String.prototype.matchAll 支持
|
||||||
|
'es.array.iterator', // 数组迭代器支持
|
||||||
|
'es.string.includes', // String.prototype.includes 支持
|
||||||
|
'es.string.starts-with', // String.prototype.startsWith 支持
|
||||||
|
'es.object.values', // Object.values 支持
|
||||||
|
],
|
||||||
|
}),
|
||||||
|
]
|
||||||
|
```
|
||||||
|
|
||||||
|
`targets` 可以参考:[Browserslist官网](https://github.com/browserslist/browserslist) 查询
|
||||||
|
|
||||||
|
**注意该方案只在打包后生效。**
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,271 @@
|
|||||||
|
## 1. 准备一个 github 仓库
|
||||||
|
|
||||||
|
> 新建 或 已存在 的库都可以
|
||||||
|
|
||||||
|
修改配置:`/Settings/General`
|
||||||
|
|
||||||
|
保证仓库的 Danger Zone - visibility 是 public的
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
开启 Features - Discussions 功能
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 2. 配置 [giscus](https://github.com/apps/giscus)
|
||||||
|
|
||||||
|
在 github 中开启 giscus 功能,可根据需求选择指定的仓库或公共仓库
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
开启完毕后进入 [giscus](https://github.com/apps/giscus) 的官网,然后按照顺序配置:
|
||||||
|
|
||||||
|
1. 选择语言
|
||||||
|
2. **仓库**:输入刚刚准备好的 github 仓库地址
|
||||||
|
3. **页面 ↔️ discussion 映射关系** 选择 **Discussion 的标题包含页面的 pathname**
|
||||||
|
4. **Discussion 分类** 选择第一个 **Announcements**
|
||||||
|
5. 其他保持默认即可
|
||||||
|
|
||||||
|
然后下滑找到 **启用 giscus** 模块,里面的 `<script>` 信息需要用到,类似:
|
||||||
|
|
||||||
|
```html
|
||||||
|
<script src="https://giscus.app/client.js"
|
||||||
|
data-repo="xxxxx"
|
||||||
|
data-repo-id="xxxx"
|
||||||
|
data-category="xxxx"
|
||||||
|
data-category-id="xxxxx"
|
||||||
|
data-mapping="pathname"
|
||||||
|
data-reactions-enabled="1"
|
||||||
|
data-emit-metadata="0"
|
||||||
|
data-input-position="bottom"
|
||||||
|
data-theme="light"
|
||||||
|
data-lang="zh-CN"
|
||||||
|
crossorigin="anonymous"
|
||||||
|
async>
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. 在项目中启用
|
||||||
|
|
||||||
|
### 3.1 开启博客评论
|
||||||
|
|
||||||
|
```bash
|
||||||
|
pnpm swizzle @docusaurus/theme-classic BlogPostPage
|
||||||
|
```
|
||||||
|
|
||||||
|
- 选择 Eject (Unsafe) 回车
|
||||||
|
- 选择 YES: I know what I am doing! 回车
|
||||||
|
- 这时你的项目目录下src/theme/BlogPostPage生成了自定义主题的文件
|
||||||
|
|
||||||
|
添加依赖
|
||||||
|
```bash
|
||||||
|
pnpm add @docusaurus/theme-common @docusaurus/plugin-content-blog
|
||||||
|
```
|
||||||
|
|
||||||
|
下一步修改文件代码
|
||||||
|
|
||||||
|
下面三处标注是我们要修改添加代码的地方。 注意版本不同配置可能存在差异 根据标注自己找放评论的位置。
|
||||||
|
|
||||||
|
```js title="/src/theme/BlogPostPage/index.js"
|
||||||
|
import { HtmlClassNameProvider, ThemeClassNames } from '@docusaurus/theme-common'
|
||||||
|
|
||||||
|
import { BlogPostProvider, useBlogPost } from '@docusaurus/theme-common/internal'
|
||||||
|
import BlogLayout from '@theme/BlogLayout'
|
||||||
|
import BlogPostItem from '@theme/BlogPostItem'
|
||||||
|
import BlogPostPageMetadata from '@theme/BlogPostPage/Metadata'
|
||||||
|
import BlogPostPaginator from '@theme/BlogPostPaginator'
|
||||||
|
import TOC from '@theme/TOC'
|
||||||
|
import clsx from 'clsx'
|
||||||
|
// highlight-start
|
||||||
|
import React, { useEffect, useRef } from 'react'
|
||||||
|
// highlight-end
|
||||||
|
|
||||||
|
function BlogPostPageContent({ sidebar, children }) {
|
||||||
|
const { metadata, toc } = useBlogPost()
|
||||||
|
const { nextItem, prevItem, frontMatter } = metadata
|
||||||
|
const {
|
||||||
|
hide_table_of_contents: hideTableOfContents,
|
||||||
|
toc_min_heading_level: tocMinHeadingLevel,
|
||||||
|
toc_max_heading_level: tocMaxHeadingLevel,
|
||||||
|
} = frontMatter
|
||||||
|
|
||||||
|
// highlight-start
|
||||||
|
const commentElement = useRef(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Update the document title using the browser API
|
||||||
|
let s = document.createElement('script')
|
||||||
|
s.src = 'https://giscus.app/client.js'
|
||||||
|
s.setAttribute('data-repo', '[你的仓库]')
|
||||||
|
s.setAttribute('data-repo-id', '[你的仓库 ID]=')
|
||||||
|
s.setAttribute('data-category', '[你的分类名]')
|
||||||
|
s.setAttribute('data-category-id', '[你的分类 ID]')
|
||||||
|
s.setAttribute('data-mapping', 'pathname')
|
||||||
|
s.setAttribute('data-reactions-enabled', '1')
|
||||||
|
s.setAttribute('data-emit-metadata', '0')
|
||||||
|
s.setAttribute('data-input-position', 'bottom')
|
||||||
|
s.setAttribute('data-theme', document.documentElement.getAttribute('data-theme'))
|
||||||
|
s.setAttribute('data-lang', 'zh-CN')
|
||||||
|
s.setAttribute('crossorigin', 'anonymous')
|
||||||
|
s.async = true
|
||||||
|
commentElement.current.appendChild(s)
|
||||||
|
}, [])
|
||||||
|
// highlight-end
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BlogLayout
|
||||||
|
sidebar={sidebar}
|
||||||
|
toc={
|
||||||
|
!hideTableOfContents && toc.length > 0
|
||||||
|
? (
|
||||||
|
<TOC
|
||||||
|
toc={toc}
|
||||||
|
minHeadingLevel={tocMinHeadingLevel}
|
||||||
|
maxHeadingLevel={tocMaxHeadingLevel}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<BlogPostItem>{children}</BlogPostItem>
|
||||||
|
|
||||||
|
{(nextItem || prevItem) && (
|
||||||
|
<BlogPostPaginator nextItem={nextItem} prevItem={prevItem} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
// highlight-start
|
||||||
|
<div style={{ marginTop: '20px' }} ref={commentElement}></div>
|
||||||
|
// highlight-end
|
||||||
|
|
||||||
|
</BlogLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function BlogPostPage(props) {
|
||||||
|
const BlogPostContent = props.content
|
||||||
|
return (
|
||||||
|
<BlogPostProvider content={props.content} isBlogPostPage>
|
||||||
|
<HtmlClassNameProvider
|
||||||
|
className={clsx(
|
||||||
|
ThemeClassNames.wrapper.blogPages,
|
||||||
|
ThemeClassNames.page.blogPostPage,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<BlogPostPageMetadata />
|
||||||
|
<BlogPostPageContent sidebar={props.sidebar}>
|
||||||
|
<BlogPostContent />
|
||||||
|
</BlogPostPageContent>
|
||||||
|
</HtmlClassNameProvider>
|
||||||
|
</BlogPostProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3.2 开启文档评论
|
||||||
|
```bash
|
||||||
|
pnpm swizzle @docusaurus/theme-classic DocItem/Layout
|
||||||
|
```
|
||||||
|
|
||||||
|
- 选择 Eject (Unsafe) 回车
|
||||||
|
- 选择 YES: I know what I am doing! 回车
|
||||||
|
- 这时你的项目目录下src/theme/BlogPostPage生成了自定义主题的文件
|
||||||
|
|
||||||
|
添加依赖
|
||||||
|
```bash
|
||||||
|
pnpm add @docusaurus/plugin-content-docs
|
||||||
|
```
|
||||||
|
|
||||||
|
下一步修改文件代码
|
||||||
|
|
||||||
|
下面三处标注是我们要修改添加代码的地方。 注意版本不同配置可能存在差异 根据标注自己找放评论的位置。
|
||||||
|
|
||||||
|
```js title="/src/theme/DocItem/Layout/index.js"
|
||||||
|
import { useDoc } from '@docusaurus/plugin-content-docs/client'
|
||||||
|
import { useWindowSize } from '@docusaurus/theme-common'
|
||||||
|
import ContentVisibility from '@theme/ContentVisibility'
|
||||||
|
import DocBreadcrumbs from '@theme/DocBreadcrumbs'
|
||||||
|
import DocItemContent from '@theme/DocItem/Content'
|
||||||
|
import DocItemFooter from '@theme/DocItem/Footer'
|
||||||
|
import DocItemPaginator from '@theme/DocItem/Paginator'
|
||||||
|
import DocItemTOCDesktop from '@theme/DocItem/TOC/Desktop'
|
||||||
|
import DocItemTOCMobile from '@theme/DocItem/TOC/Mobile'
|
||||||
|
import DocVersionBadge from '@theme/DocVersionBadge'
|
||||||
|
import DocVersionBanner from '@theme/DocVersionBanner'
|
||||||
|
import clsx from 'clsx'
|
||||||
|
// highlight-start
|
||||||
|
import React, { useEffect, useRef } from 'react'
|
||||||
|
// highlight-end
|
||||||
|
import styles from './styles.module.css'
|
||||||
|
/**
|
||||||
|
* Decide if the toc should be rendered, on mobile or desktop viewports
|
||||||
|
*/
|
||||||
|
function useDocTOC() {
|
||||||
|
const { frontMatter, toc } = useDoc()
|
||||||
|
const windowSize = useWindowSize()
|
||||||
|
const hidden = frontMatter.hide_table_of_contents
|
||||||
|
const canRender = !hidden && toc.length > 0
|
||||||
|
const mobile = canRender ? <DocItemTOCMobile /> : undefined
|
||||||
|
const desktop
|
||||||
|
= canRender && (windowSize === 'desktop' || windowSize === 'ssr')
|
||||||
|
? (
|
||||||
|
<DocItemTOCDesktop />
|
||||||
|
)
|
||||||
|
: undefined
|
||||||
|
return {
|
||||||
|
hidden,
|
||||||
|
mobile,
|
||||||
|
desktop,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default function DocItemLayout({ children }) {
|
||||||
|
const docTOC = useDocTOC()
|
||||||
|
const { metadata } = useDoc()
|
||||||
|
|
||||||
|
// highlight-start
|
||||||
|
const commentElement = useRef(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Update the document title using the browser API
|
||||||
|
let s = document.createElement('script')
|
||||||
|
s.src = 'https://giscus.app/client.js'
|
||||||
|
s.setAttribute('data-repo', '[你的仓库]')
|
||||||
|
s.setAttribute('data-repo-id', '[你的仓库 ID]=')
|
||||||
|
s.setAttribute('data-category', '[你的分类名]')
|
||||||
|
s.setAttribute('data-category-id', '[你的分类 ID]')
|
||||||
|
s.setAttribute('data-mapping', 'pathname')
|
||||||
|
s.setAttribute('data-reactions-enabled', '1')
|
||||||
|
s.setAttribute('data-emit-metadata', '0')
|
||||||
|
s.setAttribute('data-input-position', 'bottom')
|
||||||
|
s.setAttribute('data-theme', document.documentElement.getAttribute('data-theme'))
|
||||||
|
s.setAttribute('data-lang', 'zh-CN')
|
||||||
|
s.setAttribute('crossorigin', 'anonymous')
|
||||||
|
s.async = true
|
||||||
|
commentElement.current.appendChild(s)
|
||||||
|
}, [])
|
||||||
|
// highlight-end
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="row">
|
||||||
|
<div className={clsx('col', !docTOC.hidden && styles.docItemCol)}>
|
||||||
|
<ContentVisibility metadata={metadata} />
|
||||||
|
<DocVersionBanner />
|
||||||
|
<div className={styles.docItemContainer}>
|
||||||
|
<article>
|
||||||
|
<DocBreadcrumbs />
|
||||||
|
<DocVersionBadge />
|
||||||
|
{docTOC.mobile}
|
||||||
|
<DocItemContent>{children}</DocItemContent>
|
||||||
|
|
||||||
|
// highlight-start
|
||||||
|
<div style={{ marginTop: '20px' }} ref={commentElement}></div>
|
||||||
|
// highlight-end
|
||||||
|
|
||||||
|
<DocItemFooter />
|
||||||
|
</article>
|
||||||
|
<DocItemPaginator />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{docTOC.desktop && <div className="col col--3">{docTOC.desktop}</div>}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
```
|
||||||
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 5.8 KiB |
|
After Width: | Height: | Size: 40 KiB |
@@ -0,0 +1,37 @@
|
|||||||
|
[nvm](https://nvm.uihtm.com/) 全英文也叫node.js version management,是一个nodejs的版本管理工具。nvm和n都是node.js版本管理工具,为了解决node.js各种版本存在不兼容现象可以通过它可以安装和切换不同版本的node.js。
|
||||||
|
|
||||||
|
## Windows 安装
|
||||||
|
|
||||||
|
前往 https://nvm.uihtm.com/doc/download-nvm.html 进行下载安装。
|
||||||
|
|
||||||
|
**配置路径**
|
||||||
|
|
||||||
|
```txt title="nvm/settings.txt"
|
||||||
|
root: D:\devtool\nvm
|
||||||
|
path: D:\devtool\nodejs
|
||||||
|
```
|
||||||
|
|
||||||
|
**配置镜像源**
|
||||||
|
|
||||||
|
```txt title="nvm/settings.txt"
|
||||||
|
node_mirror: http://npmmirror.com/mirrors/node/
|
||||||
|
npm_mirror: http://registry.npmmirror.com/mirrors/npm/
|
||||||
|
```
|
||||||
|
|
||||||
|
打开 cmd 输入 `nvm` 检查是否安装成功
|
||||||
|
|
||||||
|
## Linux 安装
|
||||||
|
|
||||||
|
## 常用命令
|
||||||
|
|
||||||
|
- `nvm list available`:查看所有可用的 Node.js 版本
|
||||||
|
- `nvm install <version>`:安装指定版本的 Node.js,例如:`nvm install 8.12.0`
|
||||||
|
- `nvm uninstall <version>`:卸载指定版本的 Node.js,适用于卸载失败时的恢复
|
||||||
|
- `nvm use <version>`:切换到指定的 Node.js 版本,例如 `nvm use 18.16.0`
|
||||||
|
- `nvm list`:查看已安装的 Node.js 版本
|
||||||
|
- `nvm off`:禁用 Node.js 版本管理(不卸载任何东西)
|
||||||
|
- `nvm on`:启用 Node.js 版本管理
|
||||||
|
- `nvm ls`:显示所有已安装的 Node.js 版本
|
||||||
|
- `nvm list available`:显示可以安装的所有 Node.js 版本
|
||||||
|
- `nvm v`:显示当前安装的 nvm 版本
|
||||||
|
- `nvm install stable`:安装最新的稳定版 Node.js
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"label": "包管理器",
|
||||||
|
"position": 3,
|
||||||
|
"link": {
|
||||||
|
"type": "generated-index"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 75 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 83 KiB |
|
After Width: | Height: | Size: 3.3 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
@@ -0,0 +1,30 @@
|
|||||||
|
## 本地证书
|
||||||
|
|
||||||
|
### [mkcer](https://github.com/FiloSottile/mkcert/releases)
|
||||||
|
|
||||||
|
打开 cmd 执行命令
|
||||||
|
|
||||||
|
```bash
|
||||||
|
mkcert-v1.4.4-windows-amd64.exe -install
|
||||||
|
```
|
||||||
|
|
||||||
|
点击 是 即可
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
安装成功后会提示
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
生成证书
|
||||||
|
```bash
|
||||||
|
mkcert-v1.4.4-windows-amd64.exe localhost 127.0.0.1 ::1 192.168.1.131
|
||||||
|
```
|
||||||
|
成功提示
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
这样就成功啦,然后生成的证书在 **mkcert-v1.4.4-windows-amd64.exe** 的同级目录下
|
||||||
|
|
||||||
|
### openssl
|
||||||
|
参考:https://xinyufeng.net/2024/08/16/%E5%9C%A8-Windows-%E4%B8%8A%E7%94%9F%E6%88%90%E6%9C%AC%E5%9C%B0-SSL-%E8%AF%81%E4%B9%A6%E5%B9%B6%E4%BD%BF%E7%94%A8-HTTPS-%E8%AE%BF%E9%97%AE%E6%9C%AC%E5%9C%B0-Nginx-%E6%9C%8D%E5%8A%A1%E5%99%A8/
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
## 配置 https
|
||||||
|
参考配置
|
||||||
|
|
||||||
|
```
|
||||||
|
#user nobody;
|
||||||
|
worker_processes 1;
|
||||||
|
|
||||||
|
events {
|
||||||
|
worker_connections 1024;
|
||||||
|
}
|
||||||
|
|
||||||
|
http {
|
||||||
|
// ...
|
||||||
|
server {
|
||||||
|
listen 443 ssl;
|
||||||
|
server_name 192.168.1.1;
|
||||||
|
|
||||||
|
// highlight-start
|
||||||
|
ssl_certificate D:/Devtool/localhost+3.pem;
|
||||||
|
ssl_certificate_key D:/Devtool/localhost+3-key.pem;
|
||||||
|
|
||||||
|
ssl_session_cache shared:SSL:1m;
|
||||||
|
ssl_session_timeout 5m;
|
||||||
|
|
||||||
|
ssl_protocols TLSv1.2 TLSv1.3;
|
||||||
|
ssl_ciphers HIGH:!aNULL:!MD5;
|
||||||
|
ssl_prefer_server_ciphers on;
|
||||||
|
// highlight-end
|
||||||
|
|
||||||
|
location / {
|
||||||
|
root html;
|
||||||
|
index index.html index.htm;
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -96,6 +96,16 @@ const config: Config = {
|
|||||||
label: 'ReactNative',
|
label: 'ReactNative',
|
||||||
sidebarId: 'ReactNativeSidebar',
|
sidebarId: 'ReactNativeSidebar',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: 'docSidebar',
|
||||||
|
label: 'Vue',
|
||||||
|
sidebarId: 'VueSidebar',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'docSidebar',
|
||||||
|
label: 'Uniapp',
|
||||||
|
sidebarId: 'UniappSidebar',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -118,6 +128,16 @@ const config: Config = {
|
|||||||
label: 'Docker',
|
label: 'Docker',
|
||||||
sidebarId: 'DockerSidebar',
|
sidebarId: 'DockerSidebar',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
type: 'docSidebar',
|
||||||
|
label: '包管理器',
|
||||||
|
sidebarId: 'PackageManageSidebar',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'docSidebar',
|
||||||
|
label: 'Web 和 应用服务器',
|
||||||
|
sidebarId: 'ServerSidebar',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -12,5 +12,6 @@ export default antfu({
|
|||||||
],
|
],
|
||||||
rules: {
|
rules: {
|
||||||
'@typescript-eslint/no-require-imports': 'off',
|
'@typescript-eslint/no-require-imports': 'off',
|
||||||
|
'no-unused-vars': 'off',
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -19,7 +19,10 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@docusaurus/core": "3.9.2",
|
"@docusaurus/core": "3.9.2",
|
||||||
|
"@docusaurus/plugin-content-blog": "^3.9.2",
|
||||||
|
"@docusaurus/plugin-content-docs": "^3.9.2",
|
||||||
"@docusaurus/preset-classic": "3.9.2",
|
"@docusaurus/preset-classic": "3.9.2",
|
||||||
|
"@docusaurus/theme-common": "^3.9.2",
|
||||||
"@mdx-js/react": "^3.0.0",
|
"@mdx-js/react": "^3.0.0",
|
||||||
"clsx": "^2.0.0",
|
"clsx": "^2.0.0",
|
||||||
"prism-react-renderer": "^2.3.0",
|
"prism-react-renderer": "^2.3.0",
|
||||||
|
|||||||
@@ -11,9 +11,18 @@ importers:
|
|||||||
'@docusaurus/core':
|
'@docusaurus/core':
|
||||||
specifier: 3.9.2
|
specifier: 3.9.2
|
||||||
version: 3.9.2(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.6.3)
|
version: 3.9.2(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.6.3)
|
||||||
|
'@docusaurus/plugin-content-blog':
|
||||||
|
specifier: ^3.9.2
|
||||||
|
version: 3.9.2(@docusaurus/plugin-content-docs@3.9.2(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.6.3))(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.6.3)
|
||||||
|
'@docusaurus/plugin-content-docs':
|
||||||
|
specifier: ^3.9.2
|
||||||
|
version: 3.9.2(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.6.3)
|
||||||
'@docusaurus/preset-classic':
|
'@docusaurus/preset-classic':
|
||||||
specifier: 3.9.2
|
specifier: 3.9.2
|
||||||
version: 3.9.2(@algolia/client-search@5.46.2)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.3))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(search-insights@2.17.3)(typescript@5.6.3)
|
version: 3.9.2(@algolia/client-search@5.46.2)(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.3))(@types/react@19.2.7)(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(search-insights@2.17.3)(typescript@5.6.3)
|
||||||
|
'@docusaurus/theme-common':
|
||||||
|
specifier: ^3.9.2
|
||||||
|
version: 3.9.2(@docusaurus/plugin-content-docs@3.9.2(@mdx-js/react@3.1.1(@types/react@19.2.7)(react@19.2.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)(typescript@5.6.3))(react-dom@19.2.3(react@19.2.3))(react@19.2.3)
|
||||||
'@mdx-js/react':
|
'@mdx-js/react':
|
||||||
specifier: ^3.0.0
|
specifier: ^3.0.0
|
||||||
version: 3.1.1(@types/react@19.2.7)(react@19.2.3)
|
version: 3.1.1(@types/react@19.2.7)(react@19.2.3)
|
||||||
@@ -8627,7 +8636,7 @@ snapshots:
|
|||||||
|
|
||||||
'@types/sax@1.2.7':
|
'@types/sax@1.2.7':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/node': 17.0.45
|
'@types/node': 25.0.3
|
||||||
|
|
||||||
'@types/semver@7.7.1': {}
|
'@types/semver@7.7.1': {}
|
||||||
|
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
import type { SidebarsConfig } from "@docusaurus/plugin-content-docs";
|
import type { SidebarsConfig } from '@docusaurus/plugin-content-docs'
|
||||||
|
|
||||||
const sidebars: SidebarsConfig = {
|
const sidebars: SidebarsConfig = {
|
||||||
// coding
|
// coding
|
||||||
JavaSidebar: [{ type: "autogenerated", dirName: "coding/java" }],
|
JavaSidebar: [{ type: 'autogenerated', dirName: 'coding/java' }],
|
||||||
ReactNativeSidebar: [{ type: "autogenerated", dirName: "coding/react-native" }],
|
ReactNativeSidebar: [{ type: 'autogenerated', dirName: 'coding/react-native' }],
|
||||||
|
UniappSidebar: [{ type: 'autogenerated', dirName: 'coding/uniapp' }],
|
||||||
|
VueSidebar: [{ type: 'autogenerated', dirName: 'coding/vue' }],
|
||||||
|
|
||||||
// dev-tools
|
// dev-tools
|
||||||
DocusaurusSidebar: [{ type: "autogenerated", dirName: "dev-tools/docusaurus" }],
|
DocusaurusSidebar: [{ type: 'autogenerated', dirName: 'dev-tools/docusaurus' }],
|
||||||
GitSidebar: [{ type: "autogenerated", dirName: "dev-tools/git" }],
|
GitSidebar: [{ type: 'autogenerated', dirName: 'dev-tools/git' }],
|
||||||
DockerSidebar: [{ type: "autogenerated", dirName: "dev-tools/docker" }],
|
DockerSidebar: [{ type: 'autogenerated', dirName: 'dev-tools/docker' }],
|
||||||
|
PackageManageSidebar: [{ type: 'autogenerated', dirName: 'dev-tools/package-manage' }],
|
||||||
|
ServerSidebar: [{ type: 'autogenerated', dirName: 'dev-tools/server' }],
|
||||||
// database
|
// database
|
||||||
PostgreSQLSidebar: [{ type: "autogenerated", dirName: "database/postgresql" }],
|
PostgreSQLSidebar: [{ type: 'autogenerated', dirName: 'database/postgresql' }],
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
export default sidebars;
|
}
|
||||||
|
|
||||||
|
export default sidebars
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import {PageMetadata} from '@docusaurus/theme-common';
|
||||||
|
import {useBlogPost} from '@docusaurus/plugin-content-blog/client';
|
||||||
|
export default function BlogPostPageMetadata() {
|
||||||
|
const {assets, metadata} = useBlogPost();
|
||||||
|
const {title, description, date, tags, authors, frontMatter} = metadata;
|
||||||
|
const {keywords} = frontMatter;
|
||||||
|
const image = assets.image ?? frontMatter.image;
|
||||||
|
return (
|
||||||
|
<PageMetadata
|
||||||
|
title={frontMatter.title_meta ?? title}
|
||||||
|
description={description}
|
||||||
|
keywords={keywords}
|
||||||
|
image={image}>
|
||||||
|
<meta property="og:type" content="article" />
|
||||||
|
<meta property="article:published_time" content={date} />
|
||||||
|
{/* TODO double check those article meta array syntaxes, see https://ogp.me/#array */}
|
||||||
|
{authors.some((author) => author.url) && (
|
||||||
|
<meta
|
||||||
|
property="article:author"
|
||||||
|
content={authors
|
||||||
|
.map((author) => author.url)
|
||||||
|
.filter(Boolean)
|
||||||
|
.join(',')}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
{tags.length > 0 && (
|
||||||
|
<meta
|
||||||
|
property="article:tag"
|
||||||
|
content={tags.map((tag) => tag.label).join(',')}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</PageMetadata>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
import Head from '@docusaurus/Head'
|
||||||
|
import { useBlogPostStructuredData } from '@docusaurus/plugin-content-blog/client'
|
||||||
|
import React from 'react'
|
||||||
|
|
||||||
|
export default function BlogPostStructuredData() {
|
||||||
|
const structuredData = useBlogPostStructuredData()
|
||||||
|
return (
|
||||||
|
<Head>
|
||||||
|
<script type="application/ld+json">
|
||||||
|
{JSON.stringify(structuredData)}
|
||||||
|
</script>
|
||||||
|
</Head>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
import {
|
||||||
|
BlogPostProvider,
|
||||||
|
useBlogPost,
|
||||||
|
} from '@docusaurus/plugin-content-blog/client'
|
||||||
|
import { HtmlClassNameProvider, ThemeClassNames } from '@docusaurus/theme-common'
|
||||||
|
import BlogLayout from '@theme/BlogLayout'
|
||||||
|
import BlogPostItem from '@theme/BlogPostItem'
|
||||||
|
import BlogPostPageMetadata from '@theme/BlogPostPage/Metadata'
|
||||||
|
import BlogPostPageStructuredData from '@theme/BlogPostPage/StructuredData'
|
||||||
|
import BlogPostPaginator from '@theme/BlogPostPaginator'
|
||||||
|
import ContentVisibility from '@theme/ContentVisibility'
|
||||||
|
import TOC from '@theme/TOC'
|
||||||
|
import clsx from 'clsx'
|
||||||
|
import React, { useEffect, useRef } from 'react'
|
||||||
|
|
||||||
|
function BlogPostPageContent({ sidebar, children }) {
|
||||||
|
const { metadata, toc } = useBlogPost()
|
||||||
|
const { nextItem, prevItem, frontMatter } = metadata
|
||||||
|
const {
|
||||||
|
hide_table_of_contents: hideTableOfContents,
|
||||||
|
toc_min_heading_level: tocMinHeadingLevel,
|
||||||
|
toc_max_heading_level: tocMaxHeadingLevel,
|
||||||
|
} = frontMatter
|
||||||
|
|
||||||
|
const commentElement = useRef(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Update the document title using the browser API
|
||||||
|
let s = document.createElement('script')
|
||||||
|
s.src = 'https://giscus.app/client.js'
|
||||||
|
s.setAttribute('data-repo', 'oneao/docs')
|
||||||
|
s.setAttribute('data-repo-id', 'R_kgDOQ1seUQ')
|
||||||
|
s.setAttribute('data-category', 'Announcements')
|
||||||
|
s.setAttribute('data-category-id', 'DIC_kwDOQ1seUc4C0swY')
|
||||||
|
s.setAttribute('data-mapping', 'pathname')
|
||||||
|
s.setAttribute('data-reactions-enabled', '1')
|
||||||
|
s.setAttribute('data-emit-metadata', '0')
|
||||||
|
s.setAttribute('data-input-position', 'bottom')
|
||||||
|
s.setAttribute('data-theme', document.documentElement.getAttribute('data-theme'))
|
||||||
|
s.setAttribute('data-lang', 'zh-CN')
|
||||||
|
s.setAttribute('crossorigin', 'anonymous')
|
||||||
|
s.async = true
|
||||||
|
commentElement.current.appendChild(s)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<BlogLayout
|
||||||
|
sidebar={sidebar}
|
||||||
|
toc={
|
||||||
|
!hideTableOfContents && toc.length > 0
|
||||||
|
? (
|
||||||
|
<TOC
|
||||||
|
toc={toc}
|
||||||
|
minHeadingLevel={tocMinHeadingLevel}
|
||||||
|
maxHeadingLevel={tocMaxHeadingLevel}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
|
>
|
||||||
|
<ContentVisibility metadata={metadata} />
|
||||||
|
|
||||||
|
<BlogPostItem>{children}</BlogPostItem>
|
||||||
|
|
||||||
|
{(nextItem || prevItem) && (
|
||||||
|
<BlogPostPaginator nextItem={nextItem} prevItem={prevItem} />
|
||||||
|
)}
|
||||||
|
|
||||||
|
<div style={{ marginTop: '20px' }} ref={commentElement}></div>
|
||||||
|
</BlogLayout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
export default function BlogPostPage(props) {
|
||||||
|
const BlogPostContent = props.content
|
||||||
|
return (
|
||||||
|
<BlogPostProvider content={props.content} isBlogPostPage>
|
||||||
|
<HtmlClassNameProvider
|
||||||
|
className={clsx(
|
||||||
|
ThemeClassNames.wrapper.blogPages,
|
||||||
|
ThemeClassNames.page.blogPostPage,
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
<BlogPostPageMetadata />
|
||||||
|
<BlogPostPageStructuredData />
|
||||||
|
<BlogPostPageContent sidebar={props.sidebar}>
|
||||||
|
<BlogPostContent />
|
||||||
|
</BlogPostPageContent>
|
||||||
|
</HtmlClassNameProvider>
|
||||||
|
</BlogPostProvider>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
import { useDoc } from '@docusaurus/plugin-content-docs/client'
|
||||||
|
import { useWindowSize } from '@docusaurus/theme-common'
|
||||||
|
import ContentVisibility from '@theme/ContentVisibility'
|
||||||
|
import DocBreadcrumbs from '@theme/DocBreadcrumbs'
|
||||||
|
import DocItemContent from '@theme/DocItem/Content'
|
||||||
|
import DocItemFooter from '@theme/DocItem/Footer'
|
||||||
|
import DocItemPaginator from '@theme/DocItem/Paginator'
|
||||||
|
import DocItemTOCDesktop from '@theme/DocItem/TOC/Desktop'
|
||||||
|
import DocItemTOCMobile from '@theme/DocItem/TOC/Mobile'
|
||||||
|
import DocVersionBadge from '@theme/DocVersionBadge'
|
||||||
|
import DocVersionBanner from '@theme/DocVersionBanner'
|
||||||
|
import clsx from 'clsx'
|
||||||
|
import React, { useEffect, useRef } from 'react'
|
||||||
|
import styles from './styles.module.css'
|
||||||
|
/**
|
||||||
|
* Decide if the toc should be rendered, on mobile or desktop viewports
|
||||||
|
*/
|
||||||
|
function useDocTOC() {
|
||||||
|
const { frontMatter, toc } = useDoc()
|
||||||
|
const windowSize = useWindowSize()
|
||||||
|
const hidden = frontMatter.hide_table_of_contents
|
||||||
|
const canRender = !hidden && toc.length > 0
|
||||||
|
const mobile = canRender ? <DocItemTOCMobile /> : undefined
|
||||||
|
const desktop
|
||||||
|
= canRender && (windowSize === 'desktop' || windowSize === 'ssr')
|
||||||
|
? (
|
||||||
|
<DocItemTOCDesktop />
|
||||||
|
)
|
||||||
|
: undefined
|
||||||
|
return {
|
||||||
|
hidden,
|
||||||
|
mobile,
|
||||||
|
desktop,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export default function DocItemLayout({ children }) {
|
||||||
|
const docTOC = useDocTOC()
|
||||||
|
const { metadata } = useDoc()
|
||||||
|
|
||||||
|
const commentElement = useRef(null)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// Update the document title using the browser API
|
||||||
|
let s = document.createElement('script')
|
||||||
|
s.src = 'https://giscus.app/client.js'
|
||||||
|
s.setAttribute('data-repo', 'oneao/docs')
|
||||||
|
s.setAttribute('data-repo-id', 'R_kgDOQ1seUQ')
|
||||||
|
s.setAttribute('data-category', 'Announcements')
|
||||||
|
s.setAttribute('data-category-id', 'DIC_kwDOQ1seUc4C0swY')
|
||||||
|
s.setAttribute('data-mapping', 'pathname')
|
||||||
|
s.setAttribute('data-reactions-enabled', '1')
|
||||||
|
s.setAttribute('data-emit-metadata', '0')
|
||||||
|
s.setAttribute('data-input-position', 'bottom')
|
||||||
|
s.setAttribute('data-theme', document.documentElement.getAttribute('data-theme'))
|
||||||
|
s.setAttribute('data-lang', 'zh-CN')
|
||||||
|
s.setAttribute('crossorigin', 'anonymous')
|
||||||
|
s.async = true
|
||||||
|
commentElement.current.appendChild(s)
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div className="row">
|
||||||
|
<div className={clsx('col', !docTOC.hidden && styles.docItemCol)}>
|
||||||
|
<ContentVisibility metadata={metadata} />
|
||||||
|
<DocVersionBanner />
|
||||||
|
<div className={styles.docItemContainer}>
|
||||||
|
<article>
|
||||||
|
<DocBreadcrumbs />
|
||||||
|
<DocVersionBadge />
|
||||||
|
{docTOC.mobile}
|
||||||
|
<DocItemContent>{children}</DocItemContent>
|
||||||
|
<div style={{ marginTop: '20px' }} ref={commentElement}></div>
|
||||||
|
<DocItemFooter />
|
||||||
|
</article>
|
||||||
|
<DocItemPaginator />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{docTOC.desktop && <div className="col col--3">{docTOC.desktop}</div>}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
.docItemContainer header + *,
|
||||||
|
.docItemContainer article > *:first-child {
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 997px) {
|
||||||
|
.docItemCol {
|
||||||
|
max-width: 75% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -350,6 +350,7 @@ public class EmailManagementServiceImpl implements EmailManagementService {
|
|||||||
if (!attachments.isEmpty()) allAttachments.addAll(attachments);
|
if (!attachments.isEmpty()) allAttachments.addAll(attachments);
|
||||||
|
|
||||||
current++;
|
current++;
|
||||||
|
|
||||||
double progress = Math.round(current * 1000.0 / total) / 1000.0;
|
double progress = Math.round(current * 1000.0 / total) / 1000.0;
|
||||||
String title = isIncremental ? "增量拉取中" : "首次拉取最新邮件中";
|
String title = isIncremental ? "增量拉取中" : "首次拉取最新邮件中";
|
||||||
String msg = String.format("正在处理第 %d 封邮件,共 %d 封", current, total);
|
String msg = String.format("正在处理第 %d 封邮件,共 %d 封", current, total);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
server:
|
server:
|
||||||
port: 8081
|
port: 8088
|
||||||
spring:
|
spring:
|
||||||
datasource:
|
datasource:
|
||||||
type: com.alibaba.druid.pool.DruidDataSource
|
type: com.alibaba.druid.pool.DruidDataSource
|
||||||
|
|||||||
@@ -40,4 +40,4 @@ email:
|
|||||||
storage:
|
storage:
|
||||||
base-path: D:/data/email
|
base-path: D:/data/email
|
||||||
static-path: /static/email
|
static-path: /static/email
|
||||||
server-url: http://127.0.0.1:8081
|
server-url: http://127.0.0.1:8088
|
||||||
@@ -1 +1 @@
|
|||||||
VITE_SERVER_BASEURL = 'http://127.0.0.1:8081'
|
VITE_SERVER_BASEURL = 'http://127.0.0.1:8088'
|
||||||
@@ -99,7 +99,7 @@ const init = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 只在执行“插入表格”命令时添加样式
|
// 只在执行“插入表格”命令时添加样式
|
||||||
editor.on("ExecCommand", (e: any) => {
|
editor.on("ExecCommand", (e: any) => {
|
||||||
if (e.command === "mceInsertTable") {
|
if (e.command === "mceInsertTable") {
|
||||||
// 延迟一下让表格插入完毕
|
// 延迟一下让表格插入完毕
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
|||||||