diff --git a/docs/.vitepress/config.mts b/docs/.vitepress/config.mts
index aff5304..aed810d 100644
--- a/docs/.vitepress/config.mts
+++ b/docs/.vitepress/config.mts
@@ -28,6 +28,14 @@ export default defineConfig({
{ text: 'Flutter', link: '/Flutter/' },
],
sidebar: {
+ '/Web-Front/': [
+ {
+ text: 'Web前端',
+ items: [
+ { text: 'Vue3-Common', link: '/Web-Front/Vue3-Common' },
+ ]
+ },
+ ],
'/Web-Backend/': [
{
text: 'Web后端',
diff --git a/docs/Web-Front/Vue3-Common.md b/docs/Web-Front/Vue3-Common.md
new file mode 100644
index 0000000..9f19941
--- /dev/null
+++ b/docs/Web-Front/Vue3-Common.md
@@ -0,0 +1,411 @@
+# 一、依赖管理
+ 本项目会传递安装的依赖有:
+| 包名称 | 版本 | 含义和用途说明 |
+|-------|------|---------------|
+| `@fortawesome/fontawesome-free` | ^6.7.2 | FontAwesome 图标库的免费版本 |
+| `@popperjs/core` | ^2.11.8 | 工具提示和弹出框定位引擎 |
+| `axios` | ^1.4.0 | 基于 Promise 的 HTTP 客户端 |
+| `compressorjs` | ^1.2.1 | 纯 JavaScript 图片压缩库 |
+| `crypto-js` | ^4.2.0 | JavaScript 加密算法库 |
+| `dayjs` | ^1.11.13 | 轻量级的日期处理库 |
+| `echarts` | ^5.5.1 | 百度开源的数据可视化图表库 |
+| `element-plus` | ^2.6.0 | 基于 Vue 3 的桌面端 UI 组件库 |
+| `js-cookie` | ^3.0.5 | JavaScript Cookie 操作库 |
+| `lunar-calendar` | ^0.1.4 | 农历日历转换库 |
+| `lunar-javascript` | ^1.6.13 | 农历日期处理的 JavaScript 库 |
+| `path-browserify` | ^1.0.1 | Node.js path 模块的浏览器版本兼容实现 |
+| `qs` | ^6.13.0 | URL 查询字符串解析和序列化库 |
+| `v-calendar` | ^3.1.2 | Vue.js 的日历和日期选择器组件 |
+
+>[!TIP]
+>如果使用pnpm安装,会传递peerDependencies部分。
+
+>[!WARNING]
+>建议将Vite、Typescript、@types等构建工具依赖放在devDependencies中。
+
+# 二、vite.config.ts配置
+## 2.1 生成Typescript类型文件
+ 安装vite-plugin-dts插件
+
+```cmd
+pnpm add vite-plugin-dts -D
+```
+
+```typescript
+import dts from 'vite-plugin-dts'
+
+// 打包输出文件夹
+const outDirPath = 'dist'
+// 需要打包的类型文件
+const TARGET_TYPE_FOLDERS = ['src/components', 'src/utils', 'src/types', 'src/vue3-common.ts']
+
+export default defineConfig({
+ plugins: [
+ // 生成类型文件
+ dts({
+ // 需要处理的文件
+ include: TARGET_TYPE_FOLDERS,
+ // 使用特定的 tsconfig 配置
+ tsconfigPath: path.resolve(__dirname, 'tsconfig.app.json'),
+ // 类型文件输出目录
+ outDir: path.resolve(__dirname, outDirPath)
+ })
+ ],
+})
+```
+
+ 打包后会在dist目录生成.d.ts文件,提供完整的Typescript类型支持。
+
+## 2.2 build打包配置
+```typescript
+import { defineConfig } from 'vite'
+import vue from '@vitejs/plugin-vue'
+import dts from 'vite-plugin-dts'
+import path from 'path'
+import fs from 'fs'
+import { ICommonObj } from './src/types'
+
+// 打包输出文件夹
+const outDirPath = 'dist'
+// 需要单个打包的文件夹(组件和工具类)
+const TARGET_LIB_FOLDERS = ['src/components', 'src/utils']
+// 需要排除的第三方依赖
+const EXTERNAL = ['vue', 'element-plus', 'echarts', 'axios', 'moment', 'crypto-js', 'spark-md5', 'path-browserify']
+
+/**
+ * 递归读取文件夹下的所有文件
+ * @param folderPath 文件夹
+ */
+const getFilesFromFolder = (folderPath: string) => {
+ const files: string[] = []
+
+ // 读取文件夹中的内容
+ fs.readdirSync(folderPath).forEach((item: string) => {
+ const fullPath = path.join(folderPath, item)
+ // 读取文件状态 如果是文件夹,递归读取
+ if (fs.statSync(fullPath).isDirectory()) {
+ files.push(...getFilesFromFolder(fullPath))
+ } else {
+ // 否则添加至文件列表
+ files.push(fullPath)
+ }
+ })
+
+ return files
+}
+
+// 动态生成入口文件
+const inputEntries = TARGET_LIB_FOLDERS.reduce((entries: ICommonObj, folder) => {
+ // 获取文件夹内的所有文件
+ const files = getFilesFromFolder(path.resolve(__dirname, folder))
+
+ files.forEach((filePath) => {
+ // 判断文件是否是 .vue 或 .ts 文件
+ if (filePath.endsWith('.vue') || filePath.endsWith('.ts')) {
+ // 获取相对路径并保持目录结构
+ const relativePath = path.relative('src', filePath)
+ const entryName = path.join('lib', relativePath.replace(/\.(vue|ts)$/, ''))
+
+ entries[entryName] = filePath // 为每个文件创建一个入口
+ }
+ })
+
+ return entries
+}, {})
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ build: {
+ // lib文件配置
+ lib: {
+ // 入口文件
+ entry: path.resolve(__dirname, 'src/vue3-common.ts'),
+ formats: ['es'],
+ name: 'vue3-common',
+ // 文件名
+ fileName: (format) => `vue3-common.${format}.js`
+ },
+ // 输出文件路径
+ outDir: outDirPath,
+ // 是否将css文件分割
+ cssCodeSplit: true,
+ // Rollup打包配置
+ rollupOptions: {
+ // 需要排除的依赖 通常为第三方库
+ external: EXTERNAL,
+ // 输入配置
+ input: {
+ // 入口文件
+ 'vue3-common': path.resolve(__dirname, 'src/vue3-common.ts'),
+ // 其余需要单独打包的文件
+ ...inputEntries
+ },
+ // 输出配置
+ output: {
+ dir: path.resolve(__dirname, outDirPath),
+ // 入口文件
+ entryFileNames: '[name].js',
+ // chunk文件
+ chunkFileNames: 'lib/[name].js',
+ // 资源文件
+ assetFileNames: 'styles/[name].[ext]'
+ }
+ },
+ // 是否压缩代码
+ minify: false
+ }
+})
+
+```
+
+ 打包后会在dist目录生成源码文件。
+
+# 三、package.json配置
+## 3.1 导出路径
+```json
+{
+ "exports": {
+ ".": {
+ "import": "./dist/vue3-common.js",
+ "require": "./dist/vue3-common.js",
+ "types": "./dist/vue3-common.d.ts"
+ },
+ "./components/SvgIcon.vue": {
+ "import": "./dist/lib/components/SvgIcon.js",
+ "types": "./dist/components/SvgIcon.vue.d.ts"
+ },
+ "./styles/SvgIcon.css": "./dist/styles/SvgIcon.css",
+ "./components/LoginForm.vue": {
+ "import": "./dist/lib/components/LoginForm.js",
+ "types": "./dist/components/LoginForm.vue.d.ts"
+ },
+ "./styles/LoginForm.css": "./dist/styles/LoginForm.css",
+ "./components/MenuItem.vue": {
+ "import": "./dist/lib/components/MenuItem.js",
+ "types": "./dist/components/MenuItem.vue.d.ts"
+ },
+ "./components/MenuList.vue": {
+ "import": "./dist/lib/components/MenuList.js",
+ "types": "./dist/components/MenuList.vue.d.ts"
+ },
+ "./components/Hamburger.vue": {
+ "import": "./dist/lib/components/Hamburger.js",
+ "types": "./dist/components/Hamburger.vue.d.ts"
+ },
+ "./styles/Hamburger.css": "./dist/styles/Hamburger.css",
+ "./components/MultiInput.vue": {
+ "import": "./dist/lib/components/MultiInput.js",
+ "types": "./dist/components/MultiInput.vue.d.ts"
+ },
+ "./styles/MultiInput.css": "./dist/styles/MultiInput.css",
+ "./types": {
+ "types": "./dist/types/index.d.ts"
+ },
+ "./utils/axiosUtil": {
+ "import": "./dist/lib/utils/axiosUtil.js",
+ "types": "./dist/types/utils/axiosUtil.d.ts"
+ },
+ "./utils/cryptoUtil": {
+ "import": "./dist/lib/utils/cryptoUtil.js",
+ "types": "./dist/types/utils/cryptoUtil.d.ts"
+ },
+ "./utils/dataUtil": {
+ "import": "./dist/lib/utils/dataUtil.js",
+ "types": "./dist/types/utils/dataUtil.d.ts"
+ },
+ }
+}
+```
+
+ 在项目中引入common包后,通过配置tsconfig.json即可实现按需引入功能`import { fun1 } from 'vue3-common/utils/index'`。
+```json
+{
+ "compilerOptions": {
+ "baseUrl": ".",
+ "paths": {
+ "vue3-common/*": ["node_modules/vue3-common/dist/*"]
+ }
+ }
+}
+```
+
+# 四、发布框架
+1. 发布到本地
+执行`npm pack`命令,会在项目文件夹下生成`.tgz`文件,其他项目通过文件路径形式引入:
+```json
+"vue3-common": "file:../vue3-common/vue3-common-1.0.0.tgz"
+```
+
+2. 发布到git
+将dist文件夹发布到git仓库,其他项目通过git形式引入:
+```json
+"vue3-common": "git+https://gitee.com/Cxx0822/vue3-common#master"
+```
+
+# 五、组件使用说明
+## 5.1 菜单组件
+1. 安装Vue Router
+```cmd
+pnpm install vue-router
+```
+
+2. 在src/views文件夹中新建vue文件,例如:
+```cmd
+views
+ viewA
+ index.vue
+ viewB
+ index.vue
+```
+
+3. 在src/views文件夹下新建meta.ts配置文件
+```typescript
+import type { IRouteMetaConfig } from 'vue3-common/types'
+
+export const metaList: IRouteMetaConfig = {
+ '/viewA': {
+ title: 'viewA',
+ icon: 'viewA',
+ order: 1,
+ redirect: '/viewA/index'
+ },
+ '/viewA/index': {
+ title: 'viewA-Index',
+ icon: ''
+ },
+ '/viewB': {
+ title: 'viewB',
+ icon: 'viewB',
+ order: 2,
+ redirect: '/viewB/index'
+ },
+ '/viewB/index': {
+ title: 'viewB-index',
+ icon: ''
+ }
+}
+```
+
+ order对应的显示顺序关系,icon对应的为src/icons/svg中的svg图标文件(参考下文图标组件)。
+
+4. 在src目录新建router文件夹,新建menu.ts文件
+```typescript
+import { getRoutersByModules, sortRoutesByOrder } from 'vue3-common/utils/routerUtil'
+import Layout from '@/layout/index.vue'
+import { metaList } from '@/views/meta'
+
+const modules = {
+ ...import.meta.glob('@/views/viewA/**/*.vue'),
+ ...import.meta.glob('@/views/viewB/**/*.vue'),
+}
+
+const menuRoutes = getRoutersByModules(modules, Layout, metaList)
+
+export default sortRoutesByOrder(menuRoutes)
+```
+
+ 导入刚才的views文件夹并生成路由菜单。
+
+5. 如果还有其他的常量路由,可以在src/router中新建constant.ts文件:
+```typescript
+import type { RouteRecordRaw } from 'vue-router'
+
+const constantRoutes: RouteRecordRaw[] = [
+ {
+ path: '/',
+ redirect: '/login'
+ },
+ // 主页
+ {
+ path: '/login',
+ component: () => import('@/views/login/index.vue'),
+ meta: { hidden: true }
+ }
+]
+
+export default constantRoutes
+```
+
+ 该部分即Vue Router中的路由定义。
+
+6. 在src/router中新建index.ts:
+```typescript
+import { createRouter, createWebHashHistory } from 'vue-router'
+import type { RouteRecordRaw } from 'vue-router'
+
+import { setupRouteGuard } from 'vue3-common/utils/permissionUtil'
+
+// 使用 import.meta.glob 自动导入所有 src/router 目录下的 .ts 文件
+const routeModules = import.meta.glob('./*.ts', { eager: true })
+
+// 将所有模块的默认导出(即路由配置)合并成一个路由数组
+const routes: RouteRecordRaw[] = Object.values(routeModules)
+ .map((module: any) => module.default) // 获取每个模块的默认导出
+ .flat() // 扁平化数组,确保所有路由项都在一个数组中
+
+const router = createRouter({
+ history: createWebHashHistory(),
+ scrollBehavior: () => ({ top: 0 }),
+ routes
+})
+
+// 设置路由守卫
+setupRouteGuard(router)
+
+export default router
+```
+
+ 遍历src/router文件夹下所有的路由文件,并添加路由守卫。
+
+7. 在main.ts中配置路由:
+```ts
+// 引入路由
+import router from './router'
+
+// 创建Vue3实例
+const app = createApp(App)
+
+// 使用路由
+app.use(router)
+```
+
+## 5.2 图标组件
+1. 安装vite-plugin-svg-icons依赖
+```cmd
+pnpm install vite-plugin-svg-icons -D
+```
+
+2. 配置vite.config.ts
+```typescript
+import { createSvgIconsPlugin } from 'vite-plugin-svg-icons'
+
+export default defineConfig({
+ plugins: [
+ vue(),
+ createSvgIconsPlugin({
+ // 指定 SVG图标 保存的文件夹路径
+ iconDirs: [path.resolve(process.cwd(), 'src/icons/svg')],
+ // 指定 使用svg图标的格式
+ symbolId: 'icon-[dir]-[name]'
+ })
+ ],
+})
+```
+
+3. 在main.ts中注册
+```typescript
+// 注册svg-icon
+import 'virtual:svg-icons-register'
+```
+
+4. 在src/icons/svg目录中添加svg图标
+5. 在组件中使用
+```vue
+
+
+
+
+
+```
\ No newline at end of file
diff --git a/docs/Web-Front/index.md b/docs/Web-Front/index.md
index dad279f..de19f51 100644
--- a/docs/Web-Front/index.md
+++ b/docs/Web-Front/index.md
@@ -4,3 +4,5 @@ title: Web前端
---
# 内容导航
+
+- [Vue3-Common](/Web-Front/Vue3-Common)
\ No newline at end of file