<docs> 整理现有的两个Obsidian库得到的新库,后续的日志都基于这个库进行修改

main
rayc 2024-04-22 11:49:47 +08:00
parent acc50a0f9c
commit ff844de607
43 changed files with 981 additions and 32 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
密码记录/

View File

@ -37,7 +37,7 @@
"state": {
"type": "markdown",
"state": {
"file": "后端/极客时间Java实战/分布式服务/分布式服务容错.md",
"file": "README.md",
"mode": "source",
"source": false
}
@ -49,14 +49,14 @@
"state": {
"type": "markdown",
"state": {
"file": "后端/极客时间Java实战/Netty/Netty 实现IM系统.md",
"file": "开发中/本地版本的cos图床.md",
"mode": "source",
"source": false
}
}
}
],
"currentTab": 3
"currentTab": 2
}
],
"direction": "vertical"
@ -122,7 +122,7 @@
"state": {
"type": "backlink",
"state": {
"file": "后端/极客时间Java实战/Netty/Netty 实现IM系统.md",
"file": "README.md",
"collapseAll": false,
"extraContext": false,
"sortOrder": "alphabetical",
@ -139,7 +139,7 @@
"state": {
"type": "outgoing-link",
"state": {
"file": "后端/极客时间Java实战/Netty/Netty 实现IM系统.md",
"file": "README.md",
"linksCollapsed": false,
"unlinkedCollapsed": true
}
@ -162,7 +162,7 @@
"state": {
"type": "outline",
"state": {
"file": "后端/极客时间Java实战/Netty/Netty 实现IM系统.md"
"file": "README.md"
}
}
}
@ -183,30 +183,43 @@
"command-palette:打开命令面板": false
}
},
"active": "b0885c2694804173",
"active": "fcca90a4313bff23",
"lastOpenFiles": [
"后端/极客时间Java实战/Netty/Netty 与 网络通信.md",
"后端/极客时间Java实战/Netty/Netty 实现IM系统.md",
"后端/极客时间Java实战/分布式服务/Zookeeper.md",
"后端/极客时间Java实战/Netty",
"后端/极客时间Java实战/分布式服务",
"后端/极客时间Java实战/分布式服务/Dubbo服务端与客户端通信原理.md",
"后端/极客时间Java实战/分布式服务/分布式服务容错.md",
"后端/极客时间Java实战/分布式服务/Dubbo提供的各种服务引用机制.md",
"未分类日志.md",
"开发中/Vue3 + 腾讯COS文件上传.md",
"工具相关文档/git/Git 笔记.md",
"工具相关文档/git",
"工具相关文档/未命名.md",
"开发愿望清单.md",
"日志检索.md",
"后端/极客时间Java实战/分布式服务/Dubbo.md",
"后端/极客时间Java实战/分布式服务/RPC.md",
"后端/极客时间Java实战",
"VSCode 连接 云服务器.md",
"README.md",
"web/现代WEB布局.md",
"运维",
"基础",
"后端",
"rust",
"android",
"web",
"Welcome.md"
"开发中/本地版本的cos图床.md",
"工具相关文档/VSCode/VSCode 连接 云服务器.md",
"工具相关文档/VSCode/VSCode 文件嵌套.md",
"工具相关文档/VSCode",
"未命名",
"工具相关文档/Obsidian 使用笔记.md",
"开发中/RayC后台开发日志.md",
"gitea.md",
"开发中",
"未分类日志.md",
"语言/Rust/Rust学习笔记一.md",
"博客/Android/相机/Android Camera2 在预览时,录制视频.md",
"博客/docker 安装 wordpress.md",
"Bug日志/后端 -- Bug记录.md",
"极客时间学习/Nginx_geek/核心基础.md",
"语言/Kotlin/2023-11-16.md",
"语言/未命名.md",
"语言/Kotlin",
"语言",
"极客时间学习/Java 实战训练营/分布式服务/分布式服务.md",
"极客时间学习/Java 实战训练营/分布式服务/分布式服务容错.md",
"文档编写/PRD",
"文档编写/PRD.md",
"文档编写",
"工具相关文档",
"UI学习/PS 学习/日志.md",
"web/js/`JS` `setTimeout` 和 `clearTimeout`.md",
"web/css",
"开发资源/SpotifyMusic.md",
"文档编写/PRD/PRD 学习.md"
]
}

View File

@ -0,0 +1,3 @@
```log
```

View File

@ -0,0 +1,9 @@
## nginx 在https的server中访问http 的链接会失败
当我们有一个申请了 `https` 证书的 `server` 时,如果这个 `server` 中的服务使用到了一个 `http` 的链接,会访问失败,例如: 我在一个 `vue` 的项目中室友了 `http` 的链接时,访问会失败
- 解决办法
- 网上的解决方案好像都是对于nginx做代理的后端资源的解决方案是在server当中添加一个响应头的配置但我的是访问的同一个nginx下不同服务的资源目前这种方案没有尝试过
- 对使用 `http``server` 申请一个 `https` 的证书, 我使用的是 `certbot``nginx` 中指定的server 的域名申请证书
```
sudo certbot --nginx --nginx-server=/nginx_config_path -d the_domain_which_need_https
```

View File

@ -1,2 +1 @@
Obsidian git 备份
个人知识库

View File

@ -0,0 +1,9 @@
最近学习vbenjs 发现的一个内存缓存中使用到的具体的要参考vben的cache代码这里只简单记录一下两个的使用办法
`setTimeout` 其实是用来设置延时任务的函数主要作用是在一段时间之后执行任务会返回一个id用来区分不同的任务
```ts
const timeoutId = setTimeout(() => {}, expire)
```
`clearTimeout` 用来清除使用setTimeout创建的延时任务
```typescript
clearTimeout(timeoutId)
```

View File

@ -0,0 +1,355 @@
>写在前面:
> 1. 本文中的方法只是实现在 `Android` 中使用 `Camera2` 的情况下实现一个在预览时实现时评录制。本文中的代码只是一个demo相机相关的流程需要再细化
> 2. 另外,本文中的代码会存在一个问题,预览过程中会出现拉伸,原因是,本例中使用的是全局预览,需要再做适配,后面再补上.
> 3. 本文中的代码,并不规范,只是实现效果,许多地方的异常可能发生的地方,被直接忽略了
### 因为代码比较简单,所以直接给出代码:
```kotlin
class RecordVideoWhilePreviewClient(
val context: Context,
val mTextureView: AutoFitTextureView,
val filePath: String,
val stateListener: CameraStateListener
) {
companion object {
const val TAG = "RecordVideoWhilePreviewClient"
}
private var state: State = State.NEW
val SENSOR_ORIENTATION_DEFAULT_DEGREES = 90
private val SENSOR_ORIENTATION_INVERSE_DEGREES = 270
private val DEAULT_ORIENTATIONS = SparseIntArray().apply {
append(Surface.ROTATION_0, 90)
append(Surface.ROTATION_90, 0)
append(Surface.ROTATION_180, 270)
append(Surface.ROTATION_270, 180)
}
private val INVERSE_ORIENTATIONS = SparseIntArray().apply {
append(Surface.ROTATION_0, 270)
append(Surface.ROTATION_90, 180)
append(Surface.ROTATION_180, 90)
append(Surface.ROTATION_270, 0)
}
private var mBackgroundThread: HandlerThread = HandlerThread(TAG)
private lateinit var mBackHandler: Handler
@Volatile
private var mCameraDevice: CameraDevice? = null
@Volatile
private var mCameraCaptureSession: CameraCaptureSession? = null
@Volatile
private var mCaptureRequest: CaptureRequest.Builder? = null
@Volatile
private var mPreviewSurface: Surface? = null
@Volatile
private var mRecordSurface: Surface? = null
@Volatile
private var mMediaRecorder: MediaRecorder? = null
@Volatile
private var mSensorOrientation: Int = 0
@Volatile
private var mCameraOpenCloseLock = Semaphore(1)
private lateinit var mPreviewSize: Size
private lateinit var mVideoSize: Size
private val mSurfaceTextureListener = object : TextureView.SurfaceTextureListener {
override fun onSurfaceTextureAvailable(texture: SurfaceTexture, width: Int, height: Int) {
openCamera(width, height)
}
override fun onSurfaceTextureSizeChanged(texture: SurfaceTexture, width: Int, height: Int) {
configureTransform(width, height)
}
override fun onSurfaceTextureDestroyed(texture: SurfaceTexture) = true
override fun onSurfaceTextureUpdated(texture: SurfaceTexture) {
} }
private val mCameraStateCallback = object : CameraDevice.StateCallback() {
override fun onOpened(device: CameraDevice) {
mCameraOpenCloseLock.release()
mCameraDevice = device
if (!mTextureView.isAvailable) return
try {
val texture = mTextureView.surfaceTexture!!
// texture.setDefaultBufferSize(, 720)
val previewSurface = Surface(texture)
mPreviewSurface = previewSurface
setupMediaRecorder(1280, 720)
val recordSurface = mRecordSurface!!
mCaptureRequest = device.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW).apply {
addTarget(previewSurface)
addTarget(recordSurface)
}
mCameraDevice?.createCaptureSession(
listOf(previewSurface, recordSurface),
mCaptureSessionStateCallback,
mBackHandler
)
} catch (e: CameraAccessException) {
Log.e(TAG, "onOpened: ")
}
}
override fun onDisconnected(device: CameraDevice) {
mCameraOpenCloseLock.release()
device.close()
mCameraDevice = null
}
override fun onError(device: CameraDevice, error: Int) {
mCameraOpenCloseLock.release()
device.close()
mCameraDevice = null
}
}
private val mCaptureSessionStateCallback = object : CameraCaptureSession.StateCallback() {
override fun onConfigured(session: CameraCaptureSession) {
mCameraCaptureSession = session
val camera = mCameraDevice ?: return
val previewSurface = mPreviewSurface ?: return
val recordSurface = mRecordSurface ?: return
val captureRequest = camera.createCaptureRequest(CameraDevice.TEMPLATE_PREVIEW).apply {
addTarget(previewSurface)
addTarget(recordSurface)
}
mCaptureRequest = captureRequest
session.setRepeatingRequest(captureRequest.build(), mCaptureCallback, mBackHandler)
}
override fun onConfigureFailed(session: CameraCaptureSession) {
Log.e(TAG, "CameraCaptureSession.StateCallback -- onConfigureFailed: ")
}
}
private val mCaptureCallback = object : CameraCaptureSession.CaptureCallback() {
override fun onCaptureCompleted(
session: CameraCaptureSession,
request: CaptureRequest,
result: TotalCaptureResult
) {
super.onCaptureCompleted(session, request, result)
if (state == State.INITIALIZING) {
onStateChange(State.READY)
}
}
}
init {
mBackgroundThread.start()
mBackHandler = Handler(mBackgroundThread.looper)
}
@SuppressLint("MissingPermission")
fun openCamera(width: Int, height: Int) {
val manager = context.getSystemService(Context.CAMERA_SERVICE) as CameraManager
try {
if (!mCameraOpenCloseLock.tryAcquire(2500, TimeUnit.MILLISECONDS)) {
throw RuntimeException("Time out waiting to lock camera opening")
}
val cameraId = manager.cameraIdList[0]
val characteristics = manager.getCameraCharacteristics(cameraId)
val range21 = characteristics.get(CameraCharacteristics.CONTROL_AE_AVAILABLE_TARGET_FPS_RANGES);
val map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP)
?: throw RuntimeException("Cannot get available preview/video sizes")
mSensorOrientation = characteristics.get(CameraCharacteristics.SENSOR_ORIENTATION)!!
mVideoSize = Size(1280, 720)
mPreviewSize = chooseOptimalSize(map.getOutputSizes(SurfaceTexture::class.java), width, height, Size(2400, 1080));
mTextureView.setAspectRatio(mPreviewSize.width, mPreviewSize.height)
configureTransform(width, height)
mMediaRecorder = MediaRecorder()
manager.openCamera(cameraId, mCameraStateCallback, null)
} catch (e: CameraAccessException) {
Log.e(RecordVideoWhilePreview.TAG, "openCamera: Cannot access the camera. \n$e")
} catch (e: NullPointerException) {
Log.e(RecordVideoWhilePreview.TAG, "onRequestPermissionsResult: 没得相机硬件")
} catch (e: InterruptedException) {
throw RuntimeException("Interrupted while trying to lock camera opening.")
}
}
private fun setupMediaRecorder(width: Int, height: Int) {
var mediaRecorder = mMediaRecorder
if (mMediaRecorder == null) {
mediaRecorder = MediaRecorder()
} else {
mediaRecorder?.reset()
}
val rotation = (context as Activity).windowManager.defaultDisplay.rotation
when (mSensorOrientation) {
SENSOR_ORIENTATION_DEFAULT_DEGREES -> {
mediaRecorder?.setOrientationHint(DEAULT_ORIENTATIONS.get(rotation))
}
SENSOR_ORIENTATION_INVERSE_DEGREES -> {
mediaRecorder?.setOrientationHint(INVERSE_ORIENTATIONS.get(rotation))
}
}
var recordSurface = mRecordSurface
if (recordSurface == null) {
recordSurface = MediaCodec.createPersistentInputSurface()
mRecordSurface = recordSurface
}
mediaRecorder?.apply {
setInputSurface(recordSurface!!)
setVideoSource(MediaRecorder.VideoSource.SURFACE)
setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
setOutputFile(filePath)
setVideoEncodingBitRate(1280*720)
setVideoSize(width, height)
setVideoEncoder(MediaRecorder.VideoEncoder.H264)
setCaptureRate(30.0)
setVideoFrameRate(30)
prepare()
}
mMediaRecorder = mediaRecorder
}
private fun chooseOptimalSize(
choices: Array<Size>,
width: Int,
height: Int,
aspectRatio: Size
): Size {
val w = aspectRatio.width
val h = aspectRatio.height
val bigEnough = choices.filter {
it.height == it.width * h / w && it.width >= width && it.height >= height
}
return if (bigEnough.isNotEmpty()) {
Collections.min(bigEnough, CompareSizeByArea())
} else {
choices[0]
}
}
private fun configureTransform(viewWidth: Int, viewHeight: Int) {
val rotation = (context as Activity).windowManager.defaultDisplay.rotation
val matrix = Matrix()
val viewRect = RectF(0f, 0f, viewWidth.toFloat(), viewHeight.toFloat())
val bufferRect = RectF(0f, 0f, mPreviewSize.height.toFloat(), mPreviewSize.width.toFloat())
val centerY = viewRect.centerY()
val centerX = viewRect.centerX()
if (Surface.ROTATION_90 == rotation || Surface.ROTATION_270 == rotation) {
bufferRect.offset(centerX - bufferRect.centerX(), centerY - bufferRect.centerY())
matrix.setRectToRect(viewRect, bufferRect, Matrix.ScaleToFit.FILL)
val scale = Math.max(
viewHeight.toFloat() / mPreviewSize.height,
viewWidth.toFloat() / mPreviewSize.width
)
with(matrix) {
postScale(scale, scale, centerX, centerY)
postRotate((90 * (rotation - 2)).toFloat(), centerX, centerY)
}
}
mTextureView.setTransform(matrix)
}
private fun onStateChange(newState: State) {
state = newState
stateListener.onStateChange(state)
val state = when (state) {
State.NEW -> "STATE.NEW"
State.INITIALIZING -> "STATE.INITIALIZING"
State.READY -> "STATE.READY"
State.RECORDING -> "STATE.RECORDING"
State.COMPETE -> "STATE.COMPLETE"
}
context.showToast(state, Toast.LENGTH_SHORT)
}
fun initialize() {
if (mTextureView.isAvailable) {
openCamera(mTextureView.width, mTextureView.height)
} else {
mTextureView.surfaceTextureListener = mSurfaceTextureListener
}
onStateChange(State.INITIALIZING)
}
fun close() {
mBackgroundThread?.quitSafely()
try {
mBackgroundThread?.join()
} catch (e: InterruptedException) {
Log.e(TAG, "close: ")
}
mPreviewSurface?.release()
mRecordSurface?.release()
mMediaRecorder?.release()
mMediaRecorder = null
}
fun startRecord() {
if (state != State.READY && state != State.COMPETE) return
context.showToast("开始录像", Toast.LENGTH_SHORT)
setupMediaRecorder(1280, 720)
mMediaRecorder?.let {
it.start()
}
onStateChange(State.RECORDING)
}
fun stopRecord() {
if (state != State.RECORDING) return
context.showToast("结束录像", Toast.LENGTH_SHORT)
mMediaRecorder?.let {
it.stop()
it.reset()
}
onStateChange(State.COMPETE)
}
interface CameraStateListener {
fun onStateChange(newState: State)
}
enum class State {
NEW,
INITIALIZING,
READY,
RECORDING,
COMPETE,
}
}
```
### 需要注意的问题:
- 在创建 `MediaRecorder` 的时候,需要设置文件路径,这个时候,会在文件系统中生成一个空文件,等到录制的视频数据写入。
- 但是我们上面的代码中,在 `CameraDevice.StateCallback``onOpened()` 中床创建 `CameraCaptureSession.StateCallback` 后面的过程中需要使用到 用来在 `MediaRecorder``Surface`, 需要提前 `设置好MediaRecorder` 并调用 `prepare` 不然预览会失败
- 所以在第一次会创建一个文件,建议处理好文件的路径,本例目前只有一个文件路径
### 直接总结:
- 本文主要参考的是 [google官方的demo](https://github.com/android/camera-samples/tree/main/Camera2Basic), 官方的预览和录制视频是分开的,导致我一开始以为需要重新创建 `CameraCaptureSession`, 所以一开始,是在 *预览**视频录制* 之间进行切换,但是这个方法在 **切换** 的时候,会有明显的卡顿。
- 最后选择了在预览的 `CameraCaptureSession` 中添加 `MediaRecorder` 用来录制的 `Surface`. 最后实现的效果还是相对理想的,但是会有一个瑕疵,预览的显示和最后录制得到的视频不一致,但是我需要的是最后的结果,屏幕预览的效果,后面再适配一下,是我可以接受的效果

View File

@ -0,0 +1,55 @@
- 使用 docker 运行一个 mysql, 可以自己再创建一个用户授权之后再提供给wordpress使用
``` shell
sudo docker pull mysql
sudo docker run --name=mysql-wp -p 3306:3306 \
-v /local/data/path:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=password \
-d mysql
```
- 安装运行wordpress
``` shell
sudo docker pull wordpress
sudo docker run --name wp -p 1080:80 \
-e WORDPRESS_DB_HOST=mysql_tcp_link
-e WORDPRESS_DB_USER=root
-e WORDPRESS_DB_PASSWORD=password
-d wordpress
```
- 访问服务器ip:1080端口初始化wordpress。因为指定了数据库成功的话会跳过数据的配置部分后面的很简单跟着提示完成即可
- 安装主题如果需要上传主题需要修改wordpress的容器中的php的上传文件大小的配置
```shell
# 默认情况下的上传文件大小是 2M, 可以在 WordPress 的 `媒体->上传文件` 的最下方会显示文件上传限制
sudo docker exec -it `wp_container_id` bash # 进入wordpress容器
cp /usr/local/etc/php/php.ini-production /usr/local/etc/php/php.ini #
vim /usr/local/etc/php/php.ini
# 修改一下几个配置
# memory_limit 500M
# upload_max_filesize=500M
# post_max_size=500M
```
- 安装的主题是 [Sakurairo](https://github.com/mirai-mamori/Sakurairo)
上传成功后可以自动安装,安装的时间不长,后面跟着[官方文档](https://docs.fuukei.org/first-step/theme-install/) 进行配置就可以了
- `Nginx` 配置代理配置之后云服务器防火墙关闭1080端口使用域名进行访问需要现在wordpress中吧域名相关的配置做修改
```nginx
server {
server_name 域名;
listen 80;
access_log logs/wp.access.log;
error_log logs/wp.error.log;
location / {
proxy_pass http://127.0.0.1:1080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Host $http_host;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
- https 配置 使用 certbot 引用let's encrypt 为网站申请证书,记得过期后再次申请
```
sudo certbot --nginx --nginx-server-root=`conf_path` -d 域名
```

View File

@ -0,0 +1 @@
- Socket通信系列

View File

@ -0,0 +1,28 @@
### kotlin 下载慢
- 2023-11-27 -- 国内下载kotlin的速度巨慢
- 解决办法修改settings.gradle.kts , 添加aliyun的依赖源下载时间还是不短但比原本的快
```kotlin
pluginManagement {
repositories {
maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") }
maven { url = uri("https://maven.aliyun.com/repository/spring-plugin") }
maven { url = uri("https://maven.aliyun.com/repository/public") }
maven { url = uri("https://maven.aliyun.com/repository/google") }
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
maven { url = uri("https://maven.aliyun.com/repository/gradle-plugin") }
maven { url = uri("https://maven.aliyun.com/repository/spring-plugin") }
maven { url = uri("https://maven.aliyun.com/repository/public") }
maven { url = uri("https://maven.aliyun.com/repository/google") }
google()
mavenCentral()
}
}
```

View File

@ -0,0 +1,18 @@
### Java 运行的问题
1. 在运行时,发现不能识别 主类的加载,
解决办法:
- 方法一: 清除掉,`.vscode` 文件夹下的 `settings.json``lauch.json`, 退出重新加载,系统编译之后, 选择 `Fix and clean`, 之后再重新加载,问题就消失了,展示没找到其他的解决办法
- 方法二: 在文件查看的侧边栏中的Java Project菜单左侧`...` 选择clean workspace再重载一次项目即可
### Vue + TS
1. 无法找到包:
- 问题描述在Vue3 + TS 的环境中,`can not find modules` , 但是包是已经下载好依赖的
- 解决办法:在`tsconfig.json` 中关闭js的strict
```
{
"compilerOptions": {
"strict": false,
"noImplicitThis": false
}
}
```

17
工作日志/X6 修改.md Normal file
View File

@ -0,0 +1,17 @@
- 界面上方`title_bar` 移动到底部
- 需要修改 activity_main.xml在layout和layout-land
- 主题显示区域的 marginTop 修改为 marginBottom
- Menu也将 marginTop 修改为 marginBottom
- titleBar 修改 marginBottom
- 调整之后menu中唤起的 note_menu_popupwindow 和 measure_menu_popupwindow 需要把 `paddingTop` 修改为 `paddingBottom`
- titlebar小工具只显示 相机和电量
- 需要修改 `fragment_main_titlebar``fragment_main_titlebar_820` `820` 是用于横屏模式
- 把 `<include layout="@layout/other_param_h" />``other_param_h` 的根节点,设置为`visibility="gone"`
- 设置了上面的之后,相机图标会消失
- 需要把相机显示的两个控件的设置为 `layout_width="40.0.dip"`
- Menu + TitleBar 背景颜色修改
- 背景颜色直接修改Menu和TitleBar的背景颜色是分开的
- TGC 只留下TGC一个选项
- 在 `activity_auxiliaire_setting.xml``rg_shortcut_button` 中除了 `tgc` 之外全部都 `visibility="gone"`
- Menu图标修改
- 后期替换图片和xml文件

View File

@ -0,0 +1,8 @@
## 12/31/2023
1. 安装Docker
2. 使用docker 安装mysql
mysql: 配置启动
```shell
sudo docker run --name eacenic-mysql-v2 -e MYSQL_ROOT_PASSWORD=Eci85370978 -v /home/ecs-user/docker/mysql/data:/var/lib/mysql -p 3308:3306 -d mysql
```

View File

@ -0,0 +1,4 @@
### 使用Git作为同步工具
- [使用教程]([Obsidian通过github实现同步Obsidian Git - 知乎 (zhihu.com)](https://zhuanlan.zhihu.com/p/657924375))

View File

@ -0,0 +1,17 @@
在VSCode 的 vscode/settings.json 文件中添加如下规则:
```JSON
{
// 控制相关文件嵌套展示
  "explorer.fileNesting.enabled": true,
  // 默认不展开
  "explorer.fileNesting.expand": false,
  // 嵌套的具体规则
  "explorer.fileNesting.patterns": {
    "*.ts": "$(capture).test.ts, $(capture).test.tsx",
    "*.tsx": "$(capture).test.ts, $(capture).test.tsx",
    "*.env": "$(capture).env.*",
    "CHANGELOG.md": "CHANGELOG*",
    "package.json": "pnpm-lock.yaml,pnpm-workspace.yaml,LICENSE,.gitattributes,.gitignore,.gitpod.yml,CNAME,README*,.npmrc,.browserslistrc",
    ".eslintrc.cjs": ".eslintignore,.prettierignore,.stylelintignore,.commitlintrc.*,.prettierrc.*,.stylelintrc.*"
}
```

View File

@ -0,0 +1,28 @@
- `git fetch`
- `git fetch` 用来同步远程仓库和本地仓库中的git 信息,查看远程仓库的完整分支结构
- `git fetch` 同步远程仓库的全部log信息
- `git log origin`
`git fetch` 只会同步完整分支结构,不会直接将分支内容进行合并,
所以不推荐 `git pull`
- `git push`
- `git push origin` 将当前分支push到远程仓库
- `git push origin dev:dev` 可用于提交本地的新分支到远程分支
### commit 规范
- 基本格式
`<type>(<scope>): subject`
- 说明
- type (必填)
- feat -- 新功能
- fix/to -- 修复bug
- docs -- 文档
- style -- 格式 (不影响代码)
- refactor -- 重构代码变动没有修改功能也不是修复bug
- perf -- (优化, 替身性能,提升交互体验)
- test -- 增加测试
- chore -- 构建过程或辅助工具的变动
- revert -- 版本回退
- merge -- 代码合并
- sync 同步主线或分支的bug
- scope可选 : 说明commit影响的范围
- subject 必填commit 目的的简短描述

View File

@ -0,0 +1,19 @@
- 初始化项目 (2024--0-20)
> Spring Boot: `spring-boot-dependencies:3.1.8`
> druid: `druid-spring-boot-3-starter:1.2.21`
> mysql-connector-java: `mysql-connector-java:8.0.33`
> mybatis-plus: `mybatis-plus-boot-starter:3.5.5`
> hutool: `hutool-all:5.8.25`
> mapstruct: `mapstruct:1.5.5.Final mapstruct-jdk8:1.5.5.Final mapstruct-processor:1.5.5.Final`
- 开发用户管理模块 (目标暂时没有完成)
- 目标
- 用户管理
- 用户的创建和修改
- 角色的增加和删除
- 角色管理
- 角色的创建和修改
- 权限的增加和删除
- 权限初始化时,写在数据库中 不可修改和变更,只允许被角色引用
-

View File

@ -0,0 +1,4 @@
- 使用用户的永久密钥在用户管理中申请
- ==开放cos的CORS==设置CORS 操作范围CORS 来源需要设置
- 按照官方文档中即可上传成功
- ==后面需要改进的地方==创建SpringBoot COS 后台,用来生成临时密钥,通过临时密钥,事项文件上传

View File

@ -0,0 +1,4 @@
- 开通腾讯的COS服务
- 创建Bucket
- 为Bucket设置CORS配置
- 根据官网的 `Javascript SDK` 完成文件的增删改查

16
开发愿望清单.md Normal file
View File

@ -0,0 +1,16 @@
- 个人网站搭建 (先使用WordPress) -- 后面再开发
- 先实现用户管理和腾讯COS文件上传 图床设置到cos中
- 结合 cos 实现图床 -- 桌面端可用(或者web端也可以)先实现web端
- 记账app
- 音乐app -- spotify-web-api-java 玩起来
- python 做一个爬虫工具
- python 用来处理表格,做自动化办公
- 以下内容每天学习一点(知道其中三样)
- rust
- kotlin 协程
- python
- nodejs vue/react/koa
- Java (Spring boot)
- 数据库(Mysql/MongoDB/Redis)后面根据进度学习PostgreSQL
- Android/SpringBoot/等周边框架
- Electron

View File

@ -0,0 +1,3 @@
- clientID: `9c027f3e063a41949ae76e69f54bf6a8`
- ClientSecret: `f43c5aad266d4acfbe3805738c117a2c`
-

View File

@ -0,0 +1,104 @@
## PRD 要素
- 命名编码
- 版本历史
- 引言
- 需求概述
- 功能性说明
- 非功能性说明
---
### 文档标识
- 文档命名形式和编码
XX 产品V1.0PRD_V1
V1.0 是产品编号, PRD_V1 的V1 是PRD版本号
- 版本历史
- 版本号: V1
- 文档编号V1.0
- 文档密级:
- 产品名:
- 编写人:
- 编写日期
- 修订记录
- 版本号:
- 修订人
- 修订日期
- 修订描述
- 目录 -- 使用软件生成
---
### 引言
- 引言
- 产品背景
- 说明该产品的研发的背景、市场趋势、发展前景(搜集并陈述事实,解释信息和活动、预测功能)
- 说明该铲平研发的目的、意义、里程碑式的建设(说明研发的优势)
- 预期读者
- 该文档的阅读对象: 开发、测试、UI、产品
- 产品规划
- 说明该产品每一阶段的迭代目标, 开发及UI初期要达到的效果
- 名词解释
- 对文档中会出现的比较新的名称进行解释
- 该文档的参考资料
---
### 实现PRD文档的几种工具
- word
- 原型工具
- xiaopiu
- Axure
- 墨刀
- figma
- 慕客
---
### 需求描述
- 业务流程
- 组织架构图 -- 包含的模块、和子功能
- 流程图 -- 泳道图(着重关注有判断逻辑和复杂业务逻辑的程序)
- 用户角色
- 用户角色
- 用户描述
- 功能清单
- 功能模块
- 主要功能点
- 优先级 决定开发的顺序
- 运行环境
- 软件运行环境 (浏览器、 操作系统)
- 产品规划
- 对PRD中要开发的内容给出关键里程碑例如需求评审通过的时间、开发完成的时间、上线时间
- 描述产品可能存在的风险、比如性能瓶颈、没有解决的问题,用户不当使用的风险等等
---
### 功能性需求说明
- 简要说明:介绍此功能的用途,包括其来源或背景,能解决哪些问题
- 场景描述,产品 在哪种情况下会被用户使用,就是用户场景模拟
- 用户场景
- 用户描述
- 业务规则:
- 产品在开发时都有相应的业务规则,需要将跪着清晰的描述出来,让开发、测试人员明白,避免产生歧义
- 业务规则必须是完整的、准确的,易懂的。
- 原型图 (涉及到页面交互的部分)
- 前置条件:该需求实现依赖的前提条件。比如上传照片是,需要存有图像文件
- 后置条件:操作引发的后续处理
---
### 非功能性需求
- 性能需求
- 产品使用的并发性能、响应性能、安全性能、预期效果描述
- 需求变更的计划
- 运营需求
- 产品上线后如何运营、目标受众是什么,建议的推广策略、问题反馈途径、风险监控、亮点宣传等等。以及与运营人员的协作方式
- 风险分析: 针对可能出现的问题进行预判和预设解决方案
---
### 铲平设计原则
- 不做高保真
- 不写废话
- 不重复
- 把时间花在产品得核心驱动力上,减少对无用功的投入,降低单调重复的操作频次,才能保证高效产出有价值的牵引力

View File

@ -1,2 +1,49 @@
## 2024-03-08
[[VSCode 连接 云服务器]]
## 2024-01-08
- 学习PS
- 修改X6(eci 工作,逆向,未完成)
## 2024-01-11
- [[腾讯 COS + CDN实现图床]]
- [[腾讯 COS + Spring Boot 上传下载]]
## 2024-01-14
- [[Vite + VUE3 + TS 配置ESLint + Prettier]]
- [[vue3 + vite 中import path]]
- [[vue3 + vite 不能使用 import.meta]]
- [[box-sizing border-box 失效]]
## 2024-01-15
- [[docker 安装 wordpress]]
## 2024-01-17
- [[Rust学习笔记一]]
## 2024-01-19
- [[Vue3 + 腾讯COS文件上传]]
## 2024-01-20
- [[本地版本的cos图床]]
## 2024-02-20
- [[`JS` `setTimeout``clearTimeout`]]
- JS 的 Reflect(反射)
- [[VSCode 文件嵌套]]
## 2024-04-01
[ViewModel 深度分析](https://juejin.cn/post/7344571269555126335?utm_source=gold_browser_extension)
## 2024-04-01
#### Git 出现错误
> git bash报错fatal: detected dubious ownership in repository at的解决方法
> 在Android Studio中使用commit时遇到的错误
> 原因:网上说,文件夹的所有者和当前用户不一致
> 解决办法git bash中执行
> `git config --global --add safe.directory`
## 2024-04-12
> Android 中的Service是在app的主线程中进行执行的如果在主线程中执行了耗时操作可能导致ANR

View File

@ -0,0 +1,49 @@
## 分布式服务体系
#### 单体系统的问题
1. 业务扩展性 -- 任何业务的调整都需要发布整个系统
2. 性能伸缩性 -- 动态扩容对单体系统而言效率低下
3. 代码复杂度 -- 修改一处代码容易引发连锁问题
- ##### 系统扩展性
当前系统的业务需求发生变化时,对现在的系统改动程度的一种控制能力。改动程度越大,扩展性越差
- ##### 伸缩性
伸缩性,对系统性能的一种控制能力。如果通过简单扩容就能确保系统的性能得到等比例的提升,就认为系统具备较好的伸缩性。
#### 分布式系统
将整个系统拆分成多个能够独立运行的服务,这些服务再物理机上是隔离的,相互之间基于网络进行通信和协调
#### 单体系统的拆分策略
- 纵向拆分:根据业务内容进行拆分,每一个服务都是单独的业务
- 横向拆分:粒度更细,复用和组合业务能力
#### 分布式系统的固有特性
- 网络传输的三态性 -- 成功、失败、超时
- 请求的容错性 -- 调用链路上的异常扩散,雪崩效应
- 系统的异构性 -- 多种不同的技术体系
- 数据的一致性 -- 传统的事务机制无法生效 (什么是传统的事务机制)
#### 分布式核心技术点
- 可用 -- 降级、限流、集群和负载均衡
- 扩展 -- SPI机制、异步消息
- 性能 -- 异步化、资源重用
- 治理 -- 服务注册与发现机制
#### 分布式系统组成结构
- 功能性组件
- 网络通信
- 序列化
- 传输协议
- 服务调用
- 非功能性组件
- 服务治理
- 服务路由
- 服务容错
- 服务监控
## RPC架构
`remote process call`, 远程过程调用,分布式的基础
分布式系统基本功能组件:
- 网络通信
- 序列化/反序列化
- 传输协议
- 服务调用

View File

@ -0,0 +1,65 @@
### 进程结构
- 单进程结构
- 多进程结构(默认配置-- 更适合工作环境):多线程情况下,一个线程(请求)引起的错误会影响整个进程,保证高可用性(一个请求失败后,不影响其他请求)
- woker 进程
- cache 进程
> 1. master 进程
> 2. work 进程
> 3. Cache Manager
> 4. Cache Loader
> Master 进程用来管理work进程 work进程用来处理实际的请求Cache Loader 用来加载缓存Cache Manager 用来管理缓存
> work进程需要使用cache进程
> 在 配置work 进程数时需要把work进程数配置到和CPU核心数一样还要为每个work进程绑定核心 提高work进程的处理的能力和稳定性。
### 进程管理 -- 信号
#### Master 进程
1. 监控 Worker 进程
- CHLD -- worker 进程结束的时候会向master 发送 `CHLD` 信号用来监听worker进程在必要的时候拉起worker进程
2. 管理 Worker 进程
3. 接收信号
- TERM, INT -- 理解停止
- QUIT -- 不影响用户的情况下,停止
- HUP -- 重载配置文件
- USR1 -- 重新打开日志文件, 做日志文件的切割
- USR2 --
- WINCH
> USR2 和 WINCH 只能通过进程号 直接向master进程发送其他的可以使用nginx的命令行实现
#### Worker 进程 -- 通常不给worker进程发送信号
1. 接收信号
- TREM, INT
- QUIT
- USR1
- WINCH
#### Nginx 命令行
- reload: HUP
- reopen: USR1
- stop: TERM
- quit: QUIT
### reload 流程
- 向master 发送 HUP 信号
- master 检查配置文件语法正确性
- master 打开新的监听端口
- master 用 新的配置文件 启动新的worker进程
- master 向老的worker子进程发送发动QUIT信号
- 老的worker进程关闭监听句柄处理完当前连接后结束进程超时会被强制退出, 时间是由master进程决定的
### 热升级流程
### worker进程优雅的结束
1. 设置定时器 -- worker_shutdown_timeout
2. 关闭监听句柄 -- 不再处理新的连接
4. 关闭空闲连接 -- 从线程池中处理
5. 在循环中等待全部连接关闭 (或者超时,被强制关闭)
6. 退出进程
### 网络收发 与 Nginx 事件间的关系

View File

@ -0,0 +1,26 @@
项目基本环境
> `vite@5.0.8`
> `vue@3.3.11`
> `typescript@5.2.2`
> `eslint@8.56.0`
> `prettier@3.2.2`
- 创建项目
```shell
pnpm create vite@latest project-name -- --template vue-ts
```
- 配置 `ESLint`
- 安装ESLint
```shell
pnpm add -D eslint
```
- 配置 ESLint
```
npx eslint --init
```
选择的时候,直接选就可以了,最后默认安装推荐依赖即可
- 配置 Prettier
- 安装
```
pnpm add -D prettier
```
然后添加 `.prettierc.json` 文件保存格式信息

View File

@ -0,0 +1 @@
VSCode 的bug关闭VSCode然后重启就可以了

View File

@ -0,0 +1 @@
需要安装 `@types/node` 的依赖

View File

@ -0,0 +1,5 @@
通过 `COS``CND` 实现一个基本的图床
- 开通之后创建 `Bucket`
- 开通`CDN` 创建域名,这里用的自己服务器的域名的二级域名(在腾讯注册的,直接用就行,其他的域名不清楚),一路默认配置,就可以直接用,
- 设置了一个上线
- 设置了智能压缩,但是没有生效

View File

@ -0,0 +1,10 @@
- 需要引入 `cos``SDK`
```xml
<dependency>
<groupId>com.qcloud</groupId>
    <artifactId>cos_api</artifactId>
<version>5.6.155</version>
</dependency>
```
- 需要使用 `api` 的 的 `accessKey``secretKey` ,使用临时密钥失败,不知道是不是没申请对,一直是 `InvalidAccessKey`

View File

@ -0,0 +1,8 @@
## Bug:
### Kotlin 在 做 val 声明的对象 作为参数传递时,对象内的属性的值如果被修改,则原有对象的值也会产生变化,反之亦然。
### 今天遇到的问题时,
- 我在`FragmentA` 中将 `ObjectA` 写入到 `FragmentA``FragmentB` 两个页面共享的 一个 `ViewModel` 中,
- 然后修改原来在 `ObjectA` 的属性值,之后进入到 `FragmentB` 中 (这么做的原因是因为每一次进入`FragmentA` 都需要 `ObjectA` 的属性值得到更新,但是放在启动 `FragmentB` 之前就直接清除了,这么做,导致了,后面的问题)
- 最后在 `FragmentB` 中获取到错误的值
#### 解决办法:
- 把 `val` 改成 `var`, 或者修改 `Object` 清除属性值的时间点,把清除操作放到进入`FragmentA` 开始运行时的回调当中

View File

@ -0,0 +1,22 @@
## 基础扫盲
- 基本数据类型
- 语法
- 复合类型
- 分支,流程控制(分支、循环)
- 函数 + 模块
- 测试
## 所有权 -- Rust 的地基
![所有权 1](https://static001.geekbang.org/resource/image/7f/37/7f78de64bb2756d7137124ce18886a37.jpg?wh=2178x1697)
主要需要把握几个点
- 变量的可变与不可变的区别
- 变量的作用域
- 变量对应的资源的所有权 所有权相关的 `Copy``Move` 两个概念,函数传参,如果不使用引用,会发生所有权转移,需要再函数最后交回所有权(不绝对)
![引用2](https://static001.geekbang.org/resource/image/41/8d/41cf986d8da00cce53436aba30e89e8d.jpg?wh=1732x1398)
需要把握的几个点:
- 引用存在的意义
- 可变引用和不可变引用
- 可变借用和不可变借用的作用域冲突问题,借用的几个重要原则
- 使用借用作为函数形参的