Compare commits
10 Commits
11119d2d61
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e56590bce6 | ||
|
|
6b20ed0511 | ||
|
|
29a097d64f | ||
|
|
39831dcec2 | ||
|
|
4788d3e0f9 | ||
|
|
0993a14b24 | ||
|
|
b9ef2e1205 | ||
|
|
629912f264 | ||
|
|
fdff9bb3ba | ||
|
|
5bd87f532c |
8
.cnb.yml
8
.cnb.yml
@@ -4,11 +4,11 @@ include:
|
||||
|
||||
.common: &common
|
||||
env:
|
||||
TO_REPO: kevisual/cnb
|
||||
TO_REPO: kevisual/blog
|
||||
TO_URL: git.xiongxiao.me
|
||||
KUBECONFIG_CONTEXT: dev-cluster
|
||||
KUBECONFIG_DEPLOYMENT: blog
|
||||
KUBECONFIG_NAMESPACE: default
|
||||
KUBE_CONTEXT: dev-context
|
||||
KUBE_DEPLOYMENT: blog
|
||||
KUBE_NAMESPACE: default
|
||||
imports:
|
||||
- https://cnb.cool/kevisual/env/-/blob/main/.env.development
|
||||
services:
|
||||
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -1 +1,3 @@
|
||||
.pnpm-store
|
||||
|
||||
node_modules
|
||||
@@ -5,6 +5,7 @@
|
||||
"scripts": {
|
||||
"build": "hexo generate",
|
||||
"clean": "hexo clean",
|
||||
"dev": "hexo server",
|
||||
"deploy": "hexo deploy",
|
||||
"server": "hexo server"
|
||||
},
|
||||
|
||||
25
blog/source/_posts/1.md
Normal file
25
blog/source/_posts/1.md
Normal file
@@ -0,0 +1,25 @@
|
||||
---
|
||||
title: 关于博客部署的自动化方案!
|
||||
date: Mon Jan 12 2026 13:22:39 GMT+0800 (China Standard Time)
|
||||
updated: Tue Jan 13 2026 19:19:23 GMT+0800 (China Standard Time)
|
||||
tags: [博客]
|
||||
---
|
||||
|
||||
很多时候,写博客不是一个麻烦的事情,而把博客展示出去的过程才是一个很麻烦的事情。
|
||||
|
||||
更应该专注于写内容,而不是因为一些困难的因素干扰,然后就放弃。
|
||||
|
||||
而我期望的自动化的解决方案,就是任何地方写的内容,如果通过某一种模式去把资料和文档进行同步,或者易于同步,更轻易的得到页面。
|
||||
|
||||
### 那么如何解决一个自动化的问题呢?
|
||||
|
||||
自动写笔记在issus,然后任务集归档。
|
||||
|
||||
1. 没有结束的issue,属于draft,结束的issue属于发布的
|
||||
2. 创建时间是创建时间,更新时间是更新时间。
|
||||
3. 属性中tags
|
||||
4. 属性中链接link
|
||||
5. 属性中封面cover
|
||||
|
||||
存在这是内容
|
||||
|
||||
23
blog/source/_posts/2.md
Normal file
23
blog/source/_posts/2.md
Normal file
@@ -0,0 +1,23 @@
|
||||
---
|
||||
title: 关于项目和代码仓库关联的方案
|
||||
date: Tue Jan 13 2026 16:14:20 GMT+0800 (China Standard Time)
|
||||
updated: Tue Jan 13 2026 19:19:11 GMT+0800 (China Standard Time)
|
||||
tags: [博客]
|
||||
---
|
||||
|
||||
描述:
|
||||
|
||||
任何的项目,是先有需求,再有代码仓库,从左到右的反推的。
|
||||
|
||||
项目管理器,项目和对应仓库绑定,一一绑定。,和对应的开发环境绑定,一一绑定
|
||||
|
||||
## 绑定的类型
|
||||
|
||||
绑定 cnb
|
||||
绑定 gitea
|
||||
绑定 github
|
||||
|
||||
## 比如一个页面,编辑具体需求
|
||||
|
||||
直接转成对应的仓库,直接打开对应的仓库
|
||||
|
||||
33
blog/source/_posts/3.md
Normal file
33
blog/source/_posts/3.md
Normal file
@@ -0,0 +1,33 @@
|
||||
---
|
||||
title: 关于远程编辑器中命令行打开新窗口
|
||||
date: Tue Jan 13 2026 19:16:48 GMT+0800 (China Standard Time)
|
||||
updated: Tue Jan 13 2026 19:17:27 GMT+0800 (China Standard Time)
|
||||
tags: [博客]
|
||||
---
|
||||
|
||||
关于ai编辑器vscode远程开发相关
|
||||
|
||||
比如在src的文件夹下,用code打开src下的module的文件夹这种情况。
|
||||
|
||||
不同的编辑器的注册到命令行的命令不一样。
|
||||
|
||||
### vscode
|
||||
|
||||
打开remote,使用code可以打开新窗口
|
||||
|
||||
### trae(cn)
|
||||
|
||||
打开remote,使用trae打开新窗口
|
||||
|
||||
### codebuddy(cn)
|
||||
|
||||
打开remote,使用buddycn
|
||||
|
||||
### cursor
|
||||
|
||||
打开remote,使用cursor
|
||||
|
||||
### 对应的位置
|
||||
|
||||
`C:\Users\${user}\AppData\Local\Programs`
|
||||
|
||||
14
blog/source/_posts/4.md
Normal file
14
blog/source/_posts/4.md
Normal file
@@ -0,0 +1,14 @@
|
||||
---
|
||||
title: 关于nocodb一个月探索
|
||||
date: Fri Jan 16 2026 15:57:48 GMT+0800 (China Standard Time)
|
||||
updated: Fri Jan 16 2026 22:54:53 GMT+0800 (China Standard Time)
|
||||
tags: [博客]
|
||||
---
|
||||
|
||||
整体研究了一个月的nocodb,因为claudecode编码模式的skill。我感觉整个技术方向,nocodbd的自由度还是太弱了。ai场景下,我需要对每一个数据需要记录吗?不需要的,我只需要把我的知识放进去,然后到某一个时间去拿出来就好了。我需要整理吗?不需要的
|
||||
|
||||
skill很有意思,想方设法写一个模块,直接对话式管理?那不是铁铁的未来的吗
|
||||
|
||||
任何的一个db数据库,skill直连创建应用然后输入输出数据=
|
||||
|
||||
nocodb差在哪里,分享能力太衰弱了
|
||||
45
blog/source/_posts/5.md
Normal file
45
blog/source/_posts/5.md
Normal file
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: Zod Options 与 Description 顺序问题说明
|
||||
date: Fri Jan 16 2026 22:53:08 GMT+0800 (China Standard Time)
|
||||
updated: Fri Jan 16 2026 22:54:40 GMT+0800 (China Standard Time)
|
||||
tags: [博客,资料库]
|
||||
---
|
||||
|
||||
# Zod Options 与 Description 顺序问题说明
|
||||
|
||||
## 问题描述
|
||||
|
||||
在使用 Zod 定义 Schema 时,如果 `.options()` 方法调用位于 `.describe()` 方法之后,会导致设置的 description 信息丢失。
|
||||
|
||||
## 错误示例
|
||||
|
||||
```typescript
|
||||
import { z } from "zod";
|
||||
|
||||
// 错误:options 在 description 后面
|
||||
const schema = z.object({
|
||||
name: z.string().describe("用户名").options({ message: "请输入用户名" }),
|
||||
});
|
||||
```
|
||||
|
||||
在上面的示例中,`describe("用户名")` 设置的描述信息会被后续的 `.options()` 调用覆盖。
|
||||
|
||||
## 正确示例
|
||||
|
||||
```typescript
|
||||
import { z } from "zod";
|
||||
|
||||
// 正确:options 在 description 前面
|
||||
const schema = z.object({
|
||||
name: z.string().options({ message: "请输入用户名" }).describe("用户名"),
|
||||
});
|
||||
```
|
||||
|
||||
## 原因分析
|
||||
|
||||
Zod 的方法链式调用中,`.options()` 会创建新的 schema 实例,导致之前通过 `.describe()` 设置的元数据丢失。
|
||||
|
||||
## 建议
|
||||
|
||||
在 Zod Schema 定义时,应确保 `.options()` 在 `.describe()` 之前调用,以保留描述信息。
|
||||
|
||||
12
blog/source/_posts/6.md
Normal file
12
blog/source/_posts/6.md
Normal file
@@ -0,0 +1,12 @@
|
||||
---
|
||||
title: 关于图片预览问题,cdn和light资源
|
||||
date: Sat Jan 17 2026 20:00:13 GMT+0800 (China Standard Time)
|
||||
updated: Sat Jan 17 2026 20:00:13 GMT+0800 (China Standard Time)
|
||||
tags: 博客
|
||||
---
|
||||
|
||||
对象存储当中,阿里云,腾讯云,火山云,各自的面向公网都是收费,内网流量不需要。
|
||||
|
||||
假如自己有台他们自己的设备,比如2h2g1m这种,限死的实例来说,如果流量从这个方向出。也就不需要再花一笔,流量费。
|
||||
|
||||
所以配置一个数据重定向的功能,就很需要。
|
||||
11
blog/source/_posts/7.md
Normal file
11
blog/source/_posts/7.md
Normal file
@@ -0,0 +1,11 @@
|
||||
---
|
||||
title: 图片转大小网页工具
|
||||
date: Mon Jan 19 2026 03:30:30 GMT+0800 (China Standard Time)
|
||||
updated: Mon Jan 19 2026 03:30:43 GMT+0800 (China Standard Time)
|
||||
tags: [博客,资料库]
|
||||
---
|
||||
|
||||
|
||||
图片工具
|
||||
|
||||
图片转128*128的网页工具: https://www.imageresizer.work/zh/resize-image-to-128x128
|
||||
27
blog/source/_posts/8.md
Normal file
27
blog/source/_posts/8.md
Normal file
@@ -0,0 +1,27 @@
|
||||
---
|
||||
title: 整理一下介绍自己
|
||||
date: Mon Jan 19 2026 21:15:49 GMT+0800 (China Standard Time)
|
||||
updated: Mon Jan 19 2026 21:43:38 GMT+0800 (China Standard Time)
|
||||
tags: [博客]
|
||||
---
|
||||
|
||||
人的自我认知与能力定义并非一成不变,而是随着经验积累和环境变化不断演进。每隔一段时间回望自身,总会发现思维方式、技术判断与价值重心已悄然转变。在此,我对当前阶段的能力进行一次系统性梳理与更新。
|
||||
|
||||
2025年,程序开发的范式发生了深刻变革:编码本身正逐渐从“技术挑战”转变为“基础能力”。真正决定项目成败的关键,已不再是能否写出代码,而是能否构建出有价值的产品,并有效推动其落地与传播。
|
||||
|
||||
### 技术积淀与工程实践
|
||||
|
||||
在长期实践中,我深耕于现代全栈技术体系,形成了稳定高效的技术路径:
|
||||
|
||||
- **前端**:深度掌握 React 生态体系,熟悉组件化架构、状态管理及性能优化,能够快速构建用户体验优良的交互界面。
|
||||
- **后端**:基于 Node.js 构建高可用服务,偏好从原生模块出发,逐步封装出轻量、灵活且可扩展的服务框架。主导设计并实现了一套现代化的 AI 路由框架(AI Router),支持动态逻辑编排与智能响应生成。
|
||||
- **工程化与部署**:具备独立完成项目全生命周期运维的能力,熟练使用 Docker 进行容器化打包,通过 Kubernetes 实现服务编排与弹性伸缩,结合对象存储方案解决静态资源与大文件管理问题。
|
||||
- **代码治理**:擅长对现有项目进行快速分析、重构与功能扩展,能精准识别技术债务并实施模块化改造。习惯将高频操作抽象为工具函数或中间件,提升团队开发效率与代码一致性。
|
||||
|
||||
### 面向 AI 的新工作范式
|
||||
|
||||
当前,我正积极融入以 AI 为核心驱动力的新型开发模式。在这种范式下,核心能力已转向:
|
||||
|
||||
- **需求精准描述**:能够清晰、结构化地表达功能意图,使 AI 理解上下文与边界条件,从而生成高质量初始代码。
|
||||
- **智能辅助实现**:借助大模型快速原型化功能模块,显著缩短开发周期;同时具备强大的调试与纠错能力,能高效识别并修复 AI 输出中的逻辑错误或潜在风险。
|
||||
- **引导式开发控制**:通过持续反馈与迭代提示,引导 AI 按照预期方向演进代码,确保输出符合架构规范与业务目标。
|
||||
@@ -1,7 +1,8 @@
|
||||
---
|
||||
title: Hello World
|
||||
date: 2026-01-12 12:00:00
|
||||
|
||||
cover: https://r.kevisual.cn/img/20260119002721561_1768753641561.webp
|
||||
tag: '传说之旅'
|
||||
---
|
||||
|
||||
# Hello World
|
||||
|
||||
@@ -37,6 +37,9 @@ nav:
|
||||
link: https://image.anheyu.com/
|
||||
icon: https://image.anheyu.com/favicon.ico
|
||||
|
||||
# umami analytics
|
||||
umami_analytics: ffd1b3f8-8f0b-4137-b4ee-cb9500994870
|
||||
|
||||
# mourn (哀悼日,指定日期网站简单变灰,不包括滚动条)
|
||||
# 注意: 仅网站首页变灰,其他页面正常显示
|
||||
mourn:
|
||||
|
||||
@@ -29,3 +29,6 @@ if theme.microsoft_clarity
|
||||
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i;
|
||||
y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
|
||||
})(window, document, "clarity", "script", "!{theme.microsoft_clarity}");
|
||||
|
||||
if theme.umami_analytics
|
||||
script(defer src='https://umami.xiongxiao.me/script.js' data-website-id=theme.umami_analytics)
|
||||
@@ -12,7 +12,7 @@ if !theme.disable_top_img && page.top_img !== false
|
||||
if top_img !== false
|
||||
- var imgSource = top_img && top_img.indexOf('/') !== -1 ? url_for(top_img) : top_img
|
||||
- var bg_img = top_img ? imgSource : ''
|
||||
- var home_index_img_bg = home_index_img ? home_index_img : ''
|
||||
- var home_index_img_bg = home_index_img ? home_index_img : bg_img? `background: url(${bg_img}) center / cover no-repeat` : 'background: linear-gradient(to right, #3164ae, rgba(49, 100, 174, 0.8), rgba(49, 100, 174, 0.6));'
|
||||
- var site_title = page.title || page.tag || page.category || config.title
|
||||
- var isHomeClass = is_home() ? 'full_page' : 'not-home-page'
|
||||
- is_post() ? isHomeClass = 'post-bg' : isHomeClass
|
||||
|
||||
10
deploy.sh
Normal file
10
deploy.sh
Normal file
@@ -0,0 +1,10 @@
|
||||
docker build -t ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest .
|
||||
|
||||
docker push ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest
|
||||
|
||||
echo "${KUBECONFIG_DATA}" | base64 -d > ~/.kube/config
|
||||
|
||||
kubectl config use-context dev-context
|
||||
|
||||
|
||||
kubectl rollout restart deployment/blog -n default
|
||||
12
package.json
12
package.json
@@ -5,10 +5,18 @@
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"build": "cd blog && pnpm i && pnpm build",
|
||||
"test": "docker run -it --rm -p 8080:80 docker.cnb.cool/abearxiong/blog:latest"
|
||||
"dev": "cd blog && pnpm dev",
|
||||
"test": "docker run -it --rm -p 8080: 80 docker.cnb.cool/abearxiong/blog:latest"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "ISC",
|
||||
"packageManager": "pnpm@10.28.0"
|
||||
"packageManager": "pnpm@10.28.0",
|
||||
"dependencies": {
|
||||
"@kevisual/cnb": "^0.0.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/bun": "^1.3.5",
|
||||
"@types/node": "^25.0.6"
|
||||
}
|
||||
}
|
||||
2568
pnpm-lock.yaml
generated
Normal file
2568
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
2
pnpm-workspace.yaml
Normal file
2
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
packages:
|
||||
- blog
|
||||
15
skill/deploy/SKILL.md
Normal file
15
skill/deploy/SKILL.md
Normal file
@@ -0,0 +1,15 @@
|
||||
---
|
||||
name: deploy-blog
|
||||
description: 部署博客步骤
|
||||
---
|
||||
|
||||
# 部署博客步骤
|
||||
|
||||
```sh
|
||||
docker build -t ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest .
|
||||
docker push ${CNB_DOCKER_REGISTRY}/${CNB_REPO_SLUG_LOWERCASE}:latest
|
||||
|
||||
echo "${KUBECONFIG_DATA}" | base64 -d > ~/.kube/config
|
||||
kubectl config use-context dev-context
|
||||
kubectl rollout restart deployment/blog -n default
|
||||
```
|
||||
48
src/index.ts
Normal file
48
src/index.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { CNB } from "@kevisual/cnb";
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
|
||||
const _posts = path.join(process.cwd(), 'blog', 'source', '_posts')
|
||||
|
||||
export const cnb = new CNB({
|
||||
token: process.env.CNB_TOKEN!,
|
||||
cookie: process.env.CNB_COOKIE!
|
||||
});
|
||||
|
||||
const issuesList = await cnb.issue.getList('abearxiong/blog', {
|
||||
page: 1,
|
||||
state: 'closed',
|
||||
page_size: 1000
|
||||
})
|
||||
// TODO: 获取对应的 property的属性的内容,如果有cover和link和tags进行合并
|
||||
|
||||
for (const issue of issuesList.data) {
|
||||
const res = await cnb.issue.getItem('abearxiong/blog', issue.number)
|
||||
console.log(res)
|
||||
if (res.code === 200) {
|
||||
const data = res.data
|
||||
const title = data.title;
|
||||
// @ts-ignore
|
||||
const content = data.body;
|
||||
// @ts-ignore
|
||||
const created_at = data.created_at;
|
||||
const updated_at = data.updated_at
|
||||
const labels = data.labels || [];
|
||||
|
||||
const filename = `${issue.number}.md`
|
||||
const filepath = path.join(_posts, filename)
|
||||
|
||||
const article = `---
|
||||
title: ${title}
|
||||
date: ${new Date(created_at)}
|
||||
updated: ${new Date(updated_at)}
|
||||
tags: [${labels.map((l: any) => l.name).join(',')}]
|
||||
---
|
||||
|
||||
${content}
|
||||
`
|
||||
|
||||
fs.writeFileSync(filepath, article, 'utf-8')
|
||||
console.log(`已写入: ${issue.number}`)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user