Compare commits

...

10 Commits

Author SHA1 Message Date
xiongxiao
e56590bce6 编辑文件 .cnb.yml 2026-01-20 00:34:58 +08:00
xiongxiao
6b20ed0511 feat: 添加部署博客的文档和脚本 2026-01-19 22:08:03 +08:00
xiongxiao
29a097d64f update 2026-01-19 22:02:04 +08:00
xiongxiao
39831dcec2 update add umami 2026-01-19 21:57:16 +08:00
xiongxiao
4788d3e0f9 update 2026-01-19 21:53:29 +08:00
xiongxiao
0993a14b24 update 2026-01-13 16:28:10 +08:00
xiongxiao
b9ef2e1205 编辑文件 .cnb.yml 2026-01-13 16:20:23 +08:00
xiongxiao
629912f264 编辑文件 .cnb.yml 2026-01-13 16:15:15 +08:00
xiongxiao
fdff9bb3ba update 2026-01-12 18:41:22 +08:00
xiongxiao
5bd87f532c udpate 2026-01-12 17:05:02 +08:00
21 changed files with 2862 additions and 11 deletions

View File

@@ -4,11 +4,11 @@ include:
.common: &common .common: &common
env: env:
TO_REPO: kevisual/cnb TO_REPO: kevisual/blog
TO_URL: git.xiongxiao.me TO_URL: git.xiongxiao.me
KUBECONFIG_CONTEXT: dev-cluster KUBE_CONTEXT: dev-context
KUBECONFIG_DEPLOYMENT: blog KUBE_DEPLOYMENT: blog
KUBECONFIG_NAMESPACE: default KUBE_NAMESPACE: default
imports: imports:
- https://cnb.cool/kevisual/env/-/blob/main/.env.development - https://cnb.cool/kevisual/env/-/blob/main/.env.development
services: services:

2
.gitignore vendored
View File

@@ -1 +1,3 @@
.pnpm-store .pnpm-store
node_modules

View File

@@ -5,6 +5,7 @@
"scripts": { "scripts": {
"build": "hexo generate", "build": "hexo generate",
"clean": "hexo clean", "clean": "hexo clean",
"dev": "hexo server",
"deploy": "hexo deploy", "deploy": "hexo deploy",
"server": "hexo server" "server": "hexo server"
}, },

25
blog/source/_posts/1.md Normal file
View 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
View 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
View 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可以打开新窗口
### traecn
打开remote使用trae打开新窗口
### codebuddycn
打开remote使用buddycn
### cursor
打开remote使用cursor
### 对应的位置
`C:\Users\${user}\AppData\Local\Programs`

14
blog/source/_posts/4.md Normal file
View 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
View 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
View 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
View 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
View 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 按照预期方向演进代码,确保输出符合架构规范与业务目标。

View File

@@ -1,7 +1,8 @@
--- ---
title: Hello World title: Hello World
date: 2026-01-12 12:00:00 date: 2026-01-12 12:00:00
cover: https://r.kevisual.cn/img/20260119002721561_1768753641561.webp
tag: '传说之旅'
--- ---
# Hello World # Hello World

View File

@@ -37,6 +37,9 @@ nav:
link: https://image.anheyu.com/ link: https://image.anheyu.com/
icon: https://image.anheyu.com/favicon.ico icon: https://image.anheyu.com/favicon.ico
# umami analytics
umami_analytics: ffd1b3f8-8f0b-4137-b4ee-cb9500994870
# mourn (哀悼日,指定日期网站简单变灰,不包括滚动条) # mourn (哀悼日,指定日期网站简单变灰,不包括滚动条)
# 注意: 仅网站首页变灰,其他页面正常显示 # 注意: 仅网站首页变灰,其他页面正常显示
mourn: mourn:

View File

@@ -29,3 +29,6 @@ if theme.microsoft_clarity
t=l.createElement(r);t.async=1;t.src="https://www.clarity.ms/tag/"+i; 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); y=l.getElementsByTagName(r)[0];y.parentNode.insertBefore(t,y);
})(window, document, "clarity", "script", "!{theme.microsoft_clarity}"); })(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)

View File

@@ -12,7 +12,7 @@ if !theme.disable_top_img && page.top_img !== false
if top_img !== false if top_img !== false
- var imgSource = top_img && top_img.indexOf('/') !== -1 ? url_for(top_img) : top_img - var imgSource = top_img && top_img.indexOf('/') !== -1 ? url_for(top_img) : top_img
- var bg_img = top_img ? imgSource : '' - 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 site_title = page.title || page.tag || page.category || config.title
- var isHomeClass = is_home() ? 'full_page' : 'not-home-page' - var isHomeClass = is_home() ? 'full_page' : 'not-home-page'
- is_post() ? isHomeClass = 'post-bg' : isHomeClass - is_post() ? isHomeClass = 'post-bg' : isHomeClass

10
deploy.sh Normal file
View 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

View File

@@ -5,10 +5,18 @@
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"build": "cd blog && pnpm i && pnpm build", "build": "cd blog && pnpm i && pnpm build",
"dev": "cd blog && pnpm dev",
"test": "docker run -it --rm -p 8080: 80 docker.cnb.cool/abearxiong/blog:latest" "test": "docker run -it --rm -p 8080: 80 docker.cnb.cool/abearxiong/blog:latest"
}, },
"keywords": [], "keywords": [],
"author": "", "author": "",
"license": "ISC", "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

File diff suppressed because it is too large Load Diff

2
pnpm-workspace.yaml Normal file
View File

@@ -0,0 +1,2 @@
packages:
- blog

15
skill/deploy/SKILL.md Normal file
View 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
View 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}`)
}
}