Write the Code. Change the World.

9月 10
精选文章

该后台使用 vite + ts + pnpm + vue3 + element-plus + tailwindcss 等技术栈构成。没有添加任意可视化图标等插件。以最小功能,最基础功能展现。用户可以额外添加可使用的插件逻辑。

该后台后端使用 php8.2 + laravel 10 + mysql

该后台后端 go 语言版本开发中。将使用 gframe2.5.2

源码: https://github.com/vini123/simpleAdmin

在线体验: https://www.zeipan.com/admin

权限以及密码一键复位: https://v3test.yuepaibao.com/admin/api/reset

测试账号以及密码: zhoulin@xiangrong.pro、 111111 (如果发现登录不了,可一键复位谢谢)

阅读全文 >>

9月 04

https://github.com/vbenjs/vite-plugin-svg-icons/

创建一个空的 vue 项目

pnpm create vue

┌  Vue.js - The Progressive JavaScript Framework
◇  请输入项目名称:
│  vueSvg
│
◇  请输入包名称:
│  vuesvg
│
◇  请选择要包含的功能: (↑/↓ 切换,空格选择,a 全选,回车确认)
│  TypeScript, ESLint(错误预防), Prettier(代码格式化)
│
◇  选择要包含的试验特性: (↑/↓ 切换,空格选择,a 全选,回车确认)
│  none
│

正在初始化项目 C:\Users\Windows\Desktop\study\vue\primevue\vueSvg...
│
└  项目初始化完成,可执行以下命令:

   cd vueSvg
   pnpm install
   pnpm format
   pnpm dev

| 可选:使用以下命令在项目目录中初始化 Git:

   git init && git add -A && git commit -m "initial commit"

空的 vue 项目创建好后,开始安装 vite-plugin-svg-icons

阅读全文 >>

8月 27

服务器突然拉不下 github 代码,报下边错误,ping github 也 ping 不通。

git pull

ssh: connect to host github.com port 22: Connection timed out
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.

这个是 github 22 端口号访问不了。既保留了 SSH 协议的便利(如使用 SSH 密钥认证),又绕开了被封锁的 22 端口。GitHub 允许通过 443 端口进行 SSH 连接。

1. 编辑 ssh 配置文件。

vim ~/.ssh/config

在文件中添加以下内容:

Host github.com
  Hostname ssh.github.com
  Port 443
  User git
  IdentityFile ~/.ssh/id_rsa  # 这里指向你的私钥文件,如果默认是 id_rsa 通常不用改

保存退出,然后测试 ssh 连接是否畅通。

ssh -T git@github.com

# 输出以下信息
Hi 17vision! You've successfully authenticated, but GitHub does not provide shell access.

# 然后拉代码
git pull

阅读全文 >>

8月 11

项目体积比较大,或使用的插件体积比较大,小程序分包就很有必要。

https://developers.weixin.qq.com/miniprogram/dev/framework/subpackages/basic.html

配置方法

假设支持分包的小程序目录结构如下:

├── app.js
├── app.json
├── app.wxss
├── packageA
│   └── pages
│       ├── cat
│       └── dog
├── packageB
│   └── pages
│       ├── apple
│       └── banana
├── pages
│   ├── index
│   └── logs
└── utils

开发者通过在 app.json subPackages 字段声明项目分包结构:

{
  "pages":[
    "pages/index",
    "pages/logs"
  ],
  "subPackages": [
    {
      "root": "packageA",
      "pages": [
        "pages/cat",
        "pages/dog"
      ],
      "entry": "index.js"
    }, {
      "root": "packageB",
      "name": "pack2",
      "pages": [
        "pages/apple",
        "pages/banana"
      ]
    }
  ]
}

当然,分包文件也可以在根的 pages 目录下,记得定义好 root 就好。root 下的所有页面都是属于分包的。 还有,插件的配置。如果想插件也在分包内使用,必须也配置进去,否则插件会打包在主包里。
如:

{
    ……,
    "subPackages": [
        {
            "root": "packageA",
            "pages": [
                "pages/cat",
                "pages/dog"
            ],
            "plugins": {
                "kivicube": {
                    "version": "2.16.19",
                    "provider": "wx3bbab3920eabccb2"
                }
            }
        }
    ]
}

阅读全文 >>

7月 29

以下是一个基于 Nuxt 4 架构面向复杂企业级后台系统的完整项目目录结构示例,结合了官方推荐、社区实践与真实项目经验,具备高度可扩展性和清晰的职责划分:

my-nuxt4-project/
├── app/                          # 所有客户端代码集中目录(Nuxt 4 新结构)
│   ├── assets/                   # 需构建的静态资源(scss、字体、图片等)
│   │   ├── css/
│   │   │   └── main.scss
│   │   └── fonts/
│   ├── components/               # 自动导入的 Vue 组件
│   │   ├── ui/                   # 基础 UI 组件(按钮、表单、弹窗)
│   │   ├── layout/               # 布局相关组件(Sidebar、Header、Footer)
│   │   └── charts/               # 图表组件(ECharts、D3)
│   ├── composables/              # 自动导入的 Composition API 逻辑
│   │   ├── useAuth.ts            # 权限处理
│   │   ├── useApi.ts             # 统一 API 调用封装
│   │   └── useTable.ts           # 列表页通用逻辑
│   ├── layouts/                  # 页面级布局
│   │   ├── default.vue           # 默认布局(含侧边栏、顶部栏)
│   │   ├── auth.vue              # 登录/注册页布局
│   │   └── blank.vue             # 空白布局(弹窗、预览页)
│   ├── middleware/               # 路由中间件
│   │   ├── auth.global.ts        # 全局鉴权
│   │   ├── role.ts               # 路由级角色控制
│   │   └── log.ts                # 路由访问日志
│   ├── pages/                    # 文件系统路由
│   │   ├── index.vue             # 首页(重定向到 /dashboard)
│   │   ├── login.vue
│   │   ├── dashboard.vue
│   │   ├── system/
│   │   │   ├── user.vue
│   │   │   ├── role.vue
│   │   │   └── dept.vue
│   │   └── […slug].vue           # 404 或其他通配路由
│   ├── plugins/                  # 客户端插件
│   │   ├── vuetify.client.ts     # UI 框架初始化
│   │   ├── dayjs.client.ts       # 日期库
│   │   └── pinia.ts              # 状态管理
│   ├── stores/                   # Pinia 全局状态
│   │   ├── auth.ts
│   │   ├── app.ts                # 全局设置、主题
│   │   └── menu.ts               # 动态菜单
│   ├── utils/                    # 通用工具函数
│   │   ├── request.ts            # axios 二次封装
│   │   ├── validate.ts           # 表单校验规则
│   │   └── constants.ts          # 常量枚举
│   ├── app.vue                   # 应用根组件(全局入口)
│   ├── app.config.ts             # 运行时配置(主题、i18n)
│   └── error.vue                 # 错误页(500/404)

├── shared/                       # 前后端共享代码(类型、DTO、工具)
│   ├── types/
│   │   ├── api.d.ts
│   │   └── user.d.ts
│   └── utils/
│       └── date.ts

├── server/                       # 服务端代码(Nitro)
│   ├── api/                      # RESTful API
│   │   ├── auth/
│   │   │   ├── login.post.ts
│   │   │   └── logout.post.ts
│   │   ├── system/
│   │   │   ├── user.get.ts
│   │   │   └── user.post.ts
│   ├── middleware/               # 服务端中间件(日志、鉴权)
│   │   └── logger.ts
│   ├── plugins/                  # 服务端插件(数据库连接)
│   │   └── db.ts
│   ├── utils/                    # 服务端工具(加密、权限)
│   │   └── jwt.ts
│   └── routes/                   # 非 /api 前缀的自定义路由
│       └── healthz.ts            # /healthz

├── public/                       # 纯静态资源(favicon、robots.txt)
│   ├── favicon.ico
│   └── images/
│       └── logo.png

├── modules/                      # 本地开发的 Nuxt 模块
│   └── nuxt-module-i18n/

├── layers/                       # 多应用共享层(微前端、主题系统)
│   └── admin-layer/

├── tests/                        # 单元 & e2e 测试
│   ├── unit/
│   └── e2e/

├── .env                          # 环境变量
├── .env.example
├── .gitignore
├── nuxt.config.ts                # 主配置文件
├── package.json
├── tsconfig.json                 # 一个 tsconfig 即可(Nuxt 4 特性)
└── README.md

✅ 目录亮点说明

目录/文件 作用与最佳实践
app/ Nuxt 4 强制的新结构,所有客户端代码集中,IDE 感知更清晰,监听更快
shared/ 前后端共享类型、DTO、工具,避免重复定义
server/ 基于 Nitro 的服务端逻辑,支持热更新、无服务器部署
modules/ 本地私有模块,便于拆分业务、发布内部包
layers/ 多应用/主题继承,适合微前端或 SaaS 白标系统

✅ 迁移建议

  • 旧项目想升级?
    运行 npx nuxt upgrade --dedupe 即可平滑升级;目录结构不强制迁移,旧结构也能跑 。
  • 新项目建议直接采用上述结构,提前享受更快的 HMR、类型推断和 IDE 体验 。

如需进一步模板,可直接使用官方 nuxt-ui-pro/dashboard 作为起点,再按此结构扩展。

阅读全文 >>

7月 29

nuxt 的一些搞法。

  • 路由别名。比如你想访问 www.xxx.com 默认对应代码的 ./app/pages/index.vue./app.vue 文件。如果想对应 ./app/pages/home/index.vue,路由别名就很有用处了。

只需要在 ./app/pages/home/index.vue 中使用路由别名就好。如:

<template>
    <h2>home</h2>
</template>

<script setup lang="ts">
definePageMeta({
  alias: '/'
})
</script>

这种方法,访问地址依然是 www.xxx.com。 初了使用路由别名,还可以使用中间件和redirect 的方式来实现。其实,这两种方式都是 redirect 。但是这个时候地址变成了 www.xxx.com/home 。方法如下。

方法一: ./app/pages/index.vue 依然存在,通过 definePageMeta 来做跳转。

// pages/index.vue
<script setup lang="ts">
definePageMeta({
  redirect: '/home'
})
</script>

方法二: 新建中间件 ./app/middleware/redirectRoot.ts 文件。加入以下代码

export default defineNuxtRouteMiddleware(() => {
  if (useRoute().path === '/') {
    return navigateTo('/home')
  }
})

然后在 nuxt.config.ts 中加入以下代码

export default defineNuxtConfig({
  …,
  nitro: {
    routeRules: {
      '/': { redirect: '/home' }
    }
  }
})

看个人喜好,个人还是喜欢用路由别名,然后是中间件。确实有强迫症,不喜欢多一个 ./app/index.vue 文件。

阅读全文 >>

7月 25

以整个视口为单位,使用滑轮滚动或导航触发来达到展示效果的网站是一种需求。一种是自己手写 js + css 来达到这种效果。还有一种使用 fullpage.js 来达到这个效果。当然,使用 swiperjs 来实现这效果也是妥妥的赞,还很丝滑。

https://github.com/alvarotrigo/fullPage.js

https://swiperjs.com/get-started

主要是 fullpage.js 是需要花钱购买服务,而 swiperjs 是开源使用的。并且 swiperjs 不仅仅可以做这种视口滚动效果。

所以,这里选择使用 swiperjs 来完成目标。

DEMO 展示效果如下图所示(gif 使用 https://www.mnggiflab.com/ 录制和压缩):

基础环境

初始化一个 vue 项目。

pnpm create vue

cd swiperFullpage

pnpm install 

pnpm format

pnpm dev

创建选项如下图所示。

然后,创建一个版本管理。

git init

git add .

git commit -m 'initialize'

先去掉 components 里的页面和默认样式。只留 App.vue 文件

rm -rf ./src/components
rm -rf ./src/assets

然后,修改 App.vue 文件。

<template>
  <h2>Home</h2>
</template>

删除 main.ts 中的样式引入。运行起来看看。没问题,添加 git 版本控制。

git add . && git commit -m '删除默认页面和样式'

使用

先安装 swiper

pnpm add swiper

开始在 App.vue 中编写相关的代码

<template>
  <swiper
    direction="vertical"
    :modules="[FreeMode, Mousewheel]"
    :space-between="0"
    :slides-per-view="'auto'"
    :allow-touch-move="false"
    :pagination="{ clickable: true }"
    :mousewheel="{ forceToAxis: true, sensitivity: 10, releaseOnEdges: true }"
    style="height: 100vh"
    class="swiper-pointer-events"
    @swiper="onSwiper"
    @slideChange="onSlideChange"
    ref="swiperRef"
  >
    <swiper-slide class="slide" style="background: #444">
      <div class="slide-content">
        <h2>点绛唇·屏却相思</h2>
        <p>屏却相思,近来知道都无益</p>
        <p>不成抛掷,梦里终相觅</p>
        <p>醒后楼台,与梦俱明灭</p>
        <p>西窗白,纷纷凉月,一院丁香雪</p>
      </div>
    </swiper-slide>

    <swiper-slide class="slide" style="background: #333">
      <div class="slide-content">
        <h2>《望江南》</h2>
        <p>多少恨,昨夜梦魂中</p>
        <p>还似旧时游上苑</p>
        <p>车如流水马如龙</p>
        <p>花月正春风</p>
      </div>
    </swiper-slide>

    <swiper-slide class="slide" style="background: #222">
      <div class="slide-content">
        <h2>《蟾宫曲·春情》</h2>
        <p>平生不会相思</p>
        <p>才会相思,便害相思</p>
        <p>身似浮萍,心如飞絮,气若游丝,</p>
        <p>空一缕余香在此</p>
      </div>
    </swiper-slide>

    <swiper-slide class="slide slide-footer" style="height: 240px; background: #111">
      <p>© 2025 Vini123.Com All rights reserved.</p>
    </swiper-slide>
  </swiper>
</template>

<script setup lang="ts">
import { ref } from 'vue'
import { Swiper, SwiperSlide } from 'swiper/vue'
import { FreeMode, Mousewheel } from 'swiper/modules'
import 'swiper/css'

const swiperRef = ref()
const activeIndex = ref(0)

const onSwiper = (swiper: any) => {
  swiperRef.value = swiper
  activeIndex.value = swiper.activeIndex
}
const onSlideChange = () => {
  if (swiperRef.value) {
    activeIndex.value = swiperRef.value.activeIndex
  }
}
</script>

<style>
html,
body {
  margin: 0;
  padding: 0;
}
</style>

<style scoped>
.slide {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100vh;
}

.slide-footer {
  color: #fff;
  align-items: flex-end;
  padding-bottom: 20px;
}

.slide-content {
  color: #fff;
  text-align: center;
  background: rgba(0, 0, 0, 0.4);
  padding: 30px 100px;
  border-radius: 24px;
}
</style>

这里要注意一点。并不是所有的页面都是整个视口的高度。比如底部的信息。这个时候需要设置 slides-per-view:autoFreeMode。其他的根据实际情况操作。这里页面高度是整个视口的高度 100vh,有的时候,swiper 是某个页面的一部分,高度自然不一样。

运行起来看看,提交版本控制。

git add .
git commit -m '安装 swiper,编写 demo'

阅读全文 >>

7月 24

dify 使用 docker 部署是最方便的。只是拉取镜像的时候经常会失败。

配置 docker 镜像可方便拉取。

{
    "registry-mirrors": [
        "https://docker.1panel.live",
        "https://docker.nju.edu.cn",
        "https://docker.m.daocloud.io",
        "https://dockerproxy.com",
        "https://hub-mirror.c.163.com",
        "https://docker.mirrors.ustc.edu.cn",
        "https://registry.docker-cn.com",
        "https://registry.cn-hangzhou.aliyuncs.com"
    ]
}

阅读全文 >>