AI书签管理工具开发全记录(六):前端管理基础框框搭建 Vue3+Element Plus

article/2025/7/6 15:08:22

文章目录

  • AI书签管理工具开发全记录(五):前端管理基础框框搭建(Vue3+Element Plus)
    • 前言 📝
    • 1. 前端技术选型 🛠️
    • 2. 项目创建与初始化 🚀
      • 2.1 创建项目
      • 2.2 配置路径别名
      • 2.3 配置代码格式化
    • 3. 核心库集成 💻
      • 3.1 安装 Element Plus
      • 3.2 集成 Pinia 状态管理
      • 3.3 集成 Vue Router
      • 3.4 集成 Axios
    • 4. 全局样式与布局 🎨
      • 4.1 全局样式配置
      • 4.2 实现基础布局
    • 5.修改入口文件 📝
      • 5.1 修改网站图标和标题
      • 5.2 修改`App.vue`
      • 5.3 修改`main.js`
    • 6. 项目结构与运行 🏗️
      • 6.1 项目结构
      • 6.2 启动项目
    • 总结 📚

AI书签管理工具开发全记录(五):前端管理基础框框搭建(Vue3+Element Plus)

前言 📝

在上一篇博客中,我们基于 Gin 框架搭建了后端 API 服务,实现了书签和分类的 CRUD 功能。现在,我们将使用 Vue3 和 Element Plus 搭建一个现代化的前端管理界面,为用户提供直观易用的操作体验。

1. 前端技术选型 🛠️

在众多前端框架中,我们选择了以下技术栈:

  • Vue3:渐进式 JavaScript 框架,提供响应式和组件化开发
  • Element Plus:基于 Vue3 的桌面端组件库
  • Pinia:轻量级状态管理库
  • Vue Router:官方路由管理库
  • Axios:HTTP 请求库
  • Vite:下一代前端构建工具
# 安装 Vue CLI
npm install -g @vue/cli# 查看版本
vue --version
# @vue/cli 5.0.8

2. 项目创建与初始化 🚀

2.1 创建项目

使用 Vite 创建 Vue3 项目:

npx create-vite@latest web --template vue --yes
cd web
npm install

启动前端应用

npm run dev

启动成功后,访问http://localhost:5173
image.png
此时,vue项目已经正常工作了

2.2 配置路径别名

修改 vite.config.js,添加路径别名:

import { defineConfig } from "vite"
import vue from "@vitejs/plugin-vue"
import path from "path"export default defineConfig({plugins: [vue()],resolve: {alias: {"/@": path.resolve(__dirname, "./src/")}}
})

2.3 配置代码格式化

安装 Prettier:

npm install --save-dev prettier

创建 .prettierrc 文件:

{"semi": false,"singleQuote": true,"trailingComma": "none"
}

在 VSCode 中配置保存时自动格式化。

3. 核心库集成 💻

3.1 安装 Element Plus

npm install element-plus
npm install -D unplugin-vue-components unplugin-auto-import

配置 vite.config.js

import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { ElementPlusResolver } from 'unplugin-vue-components/resolvers'export default defineConfig({plugins: [vue(),AutoImport({resolvers: [ElementPlusResolver()],}),Components({resolvers: [ElementPlusResolver()],}),],
})

3.2 集成 Pinia 状态管理

安装 Pinia:

npm install pinia

main.js 中配置:

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import App from './App.vue'const app = createApp(App)
app.use(createPinia())
app.mount('#app')

创建示例 store (src/stores/counter.js):

import { defineStore } from 'pinia'export const useCounterStore = defineStore('counter', {state: () => ({ count: 0 }),actions: {increment() {this.count++}}
})

3.3 集成 Vue Router

安装 Vue Router:

npm install vue-router@4

创建categorybookmark占位页面
创建src/views/category/index.vue

<template><div><h1>category</h1></div>
</template><script setup></script><style scoped></style>

创建src/views/bookmark/index.vue

<template><div><h1>bookmark</h1></div>
</template><script setup></script><style scoped></style>

创建路由配置 (src/router/index.js):

import { createRouter, createWebHistory } from 'vue-router'const routes = [{path: '/bookmarks',name: 'Bookmarks',component: () => import('/@/views/bookmark/index.vue')},{path: '/categories',name: 'Categories',component: () => import('/@/views/category/index.vue')}
]const router = createRouter({history: createWebHistory(),routes
})export default router

3.4 集成 Axios

安装 Axios:

npm install axios

创建请求工具 (src/utils/request.js):

import axios from 'axios'// 创建 axios 实例
const service = axios.create({baseURL: import.meta.env.VITE_API_BASE_URL,timeout: 10000
})export default service

4. 全局样式与布局 🎨

4.1 全局样式配置

创建全局样式文件src/styles.css

* {margin: 0;padding: 0;box-sizing: border-box;}html, body, #app {height: 100%;margin: 0;overflow: hidden; /* 禁止整个页面滚动 */}

创建全局样式文件 src/styles/variables.scss存放一些额外的样式,可以存放变量

:root {--primary-color: #409EFF;--success-color: #67C23A;--warning-color: #E6A23C;--danger-color: #F56C6C;--info-color: #909399;--sidebar-width: 200px;--header-height: 60px;
}#app {display: flex;flex-direction: column;background-color: #f5f7fa;
}

安装sass-embedded

npm install -D sass-embedded

在 `vite.config.js` 中配置全局 SCSS 变量:```javascript
export default defineConfig({css: {preprocessorOptions: {scss: {additionalData: `@import "/@/styles/variables.scss";`}}}
})

4.2 实现基础布局

创建布局组件 (src/layout/index.vue):

<template><el-container class="layout-container"><!-- 侧边栏 --><el-aside :width="sidebarWidth" class="sidebar"><div class="logo">AI书签管理</div><el-menu:default-active="activeMenu"routerbackground-color="#304156"text-color="#bfcbd9"active-text-color="#409EFF":collapse="isCollapse"class="sidebar-menu"><el-menu-item index="/bookmarks"><el-icon><icon-menu /></el-icon><span>书签管理</span></el-menu-item><el-menu-item index="/categories"><el-icon><setting /></el-icon><span>分类管理</span></el-menu-item></el-menu></el-aside><!-- 主内容区 --><el-containerclass="main-container":style="{ 'margin-left': sidebarWidth }"><!-- 顶部导航 --><el-header class="header"><div class="header-left"><el-icon @click="toggleSidebar"><expand v-if="isCollapse" /><fold v-else /></el-icon><el-breadcrumb separator="/"><el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item><el-breadcrumb-item v-if="route.meta?.title">{{route.meta.title}}</el-breadcrumb-item></el-breadcrumb></div></el-header><!-- 内容区域 --><el-main class="main-content"><router-view v-slot="{ Component }"><transition name="fade" mode="out-in"><component :is="Component" /></transition></router-view></el-main></el-container></el-container>
</template><script setup>
import { ref, computed } from 'vue'
import { useRoute } from 'vue-router'
import {Menu as IconMenu,Setting,Expand,Fold
} from '@element-plus/icons-vue'const route = useRoute()
const isCollapse = ref(false)
const sidebarWidth = computed(() => (isCollapse.value ? '64px' : '200px'))
const activeMenu = computed(() => route?.path || '/')const toggleSidebar = () => {isCollapse.value = !isCollapse.value
}
</script><style scoped>
.layout-container {min-height: 100vh;display: flex;
}.sidebar {background-color: #304156;height: 100vh;position: fixed;left: 0;top: 0;z-index: 1000;transition: width 0.3s;display: flex;flex-direction: column;overflow: hidden;
}.logo {height: 60px;line-height: 60px;text-align: center;color: #fff;font-size: 18px;font-weight: bold;background-color: #2b2f3a;flex-shrink: 0;
}.sidebar-menu {flex: 1;overflow-y: auto;overflow-x: hidden;border-right: none;
}.main-container {width: 100%;min-height: 100vh;display: flex;flex-direction: column;transition: margin-left 0.3s;
}.header {display: flex;align-items: center;justify-content: space-between;background-color: #fff;box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);height: 60px;flex-shrink: 0;z-index: 999;position: sticky;top: 0;padding: 0 20px;
}.header-left {display: flex;align-items: center;gap: 16px;
}.header-left .el-icon {font-size: 20px;cursor: pointer;
}.main-content {padding: 20px;background-color: #f5f7fa;flex: 1;overflow-y: auto;height: calc(100vh - 60px);
}/* 过渡动画 */
.fade-enter-active,
.fade-leave-active {transition: opacity 0.3s ease;
}.fade-enter-from,
.fade-leave-to {opacity: 0;
}
</style>

5.修改入口文件 📝

5.1 修改网站图标和标题

favicon.ico图标放到public目录下,修改图标和标题

<!doctype html>
<html lang="en"><head><meta charset="UTF-8" /><link rel="icon" type="image/x-icon" href="/favicon.ico" /><meta name="viewport" content="width=device-width, initial-scale=1.0" /><title>AiBookmark</title></head><body><div id="app"></div><script type="module" src="/src/main.js"></script></body>
</html>

5.2 修改App.vue

<script setup>
import MainLayout from '/@/layout/index.vue'
</script><template><MainLayout><router-view /></MainLayout>
</template><style scoped></style>

5.3 修改main.js

import { createApp } from 'vue'
import { createPinia } from 'pinia'
import './style.css'
import router from './router'
import App from './App.vue'const app = createApp(App)
app.use(router)
app.use(createPinia())
app.mount('#app')

6. 项目结构与运行 🏗️

6.1 项目结构

web/
├── public/
├── src/
│   ├── api/             # API 接口
│   ├── assets/          # 静态资源
│   ├── components/      # 通用组件
│   ├── layout/          # 布局组件
│   ├── router/          # 路由配置
│   ├── stores/          # Pinia 状态管理
│   ├── styles/          # 全局样式
│   ├── utils/           # 工具函数
│   ├── views/           # 页面组件
│   │   ├── bookmark/    # 书签管理
│   │   ├── category/    # 分类管理
│   ├── App.vue
│   └── main.js
├── .env.development     # 开发环境变量
├── .prettierrc         # 代码格式化配置
├── index.html
├── package.json
└── vite.config.js

6.2 启动项目

重新启动前端项目

# 启动前端
npm run dev

访问 http://localhost:5173 查看效果:

AI书签管理系统界面

总结 📚

本文详细介绍了如何基于 Vue3 和 Element Plus 搭建前端管理界面。我们实现了:

  • 现代化的后台管理布局
  • 响应式侧边栏和顶部导航
  • 路由配置

在下一篇文章中,我们将实现页面编写和接口对接。



http://www.hkcw.cn/article/mrJouhOXeu.shtml

相关文章

Paraformer语音模型:一种语音模型加速方法

随着智能语音技术的普及&#xff0c;语音识别&#xff08;ASR&#xff09;、语音合成&#xff08;TTS&#xff09;、声纹识别等应用场景对模型推理效率提出了极高要求&#xff0c;本文介绍将Paraformer语音模型从预训练模型导出为ONNX格式&#xff0c;并使用ONNX Runtime进行推…

Spring,SpringMVC,SpringBoot

1.Spring最核心包括aop和ioc概念 AOP 能够将将哪些于业务无关的&#xff0c;并且大量重复的业务逻辑进行封装起来&#xff0c;便于减少重复代码&#xff0c;降低模块之间的耦合度&#xff0c;给未来的系统更好的可用性和可维护性。 Spring中AOP是采用动态代理&#xff0c;JDK代…

浏览器的渲染原理

浏览器的渲染原理 掘金 整个过程 网络 网络线程: 收到html,css,js 文件资源. 产生一个渲染任务,并将其传递给渲染主线程的消息队列. 渲染 在事件循环机制下, 渲染主线程取出消息队列中的渲染任务,开启渲染流程. 整个过程 渲染主线程 完成 绘制之前的所有工作合成线程和…

【30万像素实时调控!石墨烯“魔镜”突破毫米波极限】

12厘米见方的超表面&#xff0c;藏着30万个比头发丝还细的像素单元&#xff0c;正在无声地操控着无形的太赫兹波束。曼彻斯特大学的科学家们将石墨烯的非凡电学特性与现代显示技术巧妙融合&#xff0c;创造出世界上最大规模的可编程智能超表面。想象一下&#xff0c;只需轻轻点…

线性调频波形测距测速信号处理——全代码+注释

clear all close all clc %% 参数设置 fs600e6;%采样率 fc10.45e9;% 波形发射载频 t10e-6;%脉宽 f050e6;%波形中频频率 B10e6;%带宽 uB/(2*t);%调频斜率 Tv100e-6;% 脉冲重复周期 Num64;% 测速脉冲数 lamdfs/B;% 抽取带宽 Nsround(fs*t); NTvround(fs*Tv); tt0:1/fs:t-1/fs; ff…

Spine工具入门教程2之导入

1、导入定义 从原画转化为Spine的环节。 &#xff08;1&#xff09;选择路径&#xff0c;拖动图片导入方式 缺点&#xff1a;定位不准 【使用批量导出的方式】 在PS工具中&#xff0c;选择所有图层后右键选择导出。 在Spine工具中&#xff0c;选择路径导入图片。 然后再拖…

吴恩达MCP课程(1):chat_bot

原课程代码是用Anthropic写的&#xff0c;下面代码是用OpenAI改写的&#xff0c;模型则用阿里巴巴的模型做测试 .env 文件为&#xff1a; OPENAI_API_KEYsk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx OPENAI_API_BASEhttps://dashscope.aliyuncs.com/compatible-mode…

Z-AnyLabeling1.0.1

1.前段时间写了第一个版本的Z-AnyLabeling&#xff0c;使用起来只能标注一个文件夹里面的图片&#xff0c;不能标注多个文件夹数据 2.现在更新一个版本可以标注多个文件夹数据&#xff0c;同时可以保存成一个工程文件。 3.软件开发环境:Pycharm&#xff0c;Pyside6 4.软件界面 …

告别充电焦虑:移动充电桩如何优化传统充电模式?

新能源汽车的普及&#xff0c;充电难、充电慢的问题日益凸显。传统固定充电桩受限于场地和电网&#xff0c;难以满足用户灵活、高效的充电需求。而移动充电桩的出现&#xff0c;正逐步改变这一局面。它以其灵活部署、智能调度和高效补能的优势&#xff0c;为缓解充电焦虑提供了…

github访问慢

解决github外玩访问慢 &#xff0c;点击解决方案

榕壹云医疗服务系统:基于ThinkPHP+MySQL+UniApp的多门店医疗预约小程序解决方案

在数字化浪潮下,传统医疗服务行业正面临效率提升与客户体验优化的双重挑战。针对口腔、美容、诊所、中医馆、专科医院及康复护理等需要预约或诊断服务的行业,我们开发了一款基于ThinkPHP+MySQL+UniApp的多门店服务预约小程序——榕壹云医疗服务系统。该系统通过模块化设计与开…

RPA如何支持跨平台和跨浏览器的自动化

RPA&#xff0c;即机器人流程自动化&#xff08;Robotic Process Automation&#xff09;&#xff0c;正日益成为企业实现业务流程高效自动化的关键技术。在复杂的数字化环境中&#xff0c;跨平台和跨浏览器的自动化需求极为迫切&#xff0c;RPA 通过多种技术手段和策略来满足这…

SpringBoot简单体验(TODO)

1 Helloworld 打开&#xff1a;https://start.spring.io/ 选择maven配置。增加SpringWeb的依赖。 Generate之后解压&#xff0c;代码大致如下&#xff1a; hpDESKTOP-430500P:~/springboot2/demo$ tree ├── HELP.md ├── mvnw ├── mvnw.cmd ├── pom.xml └── s…

事件驱动架构入门

主要参考资料&#xff1a; 软件架构-事件驱动架构: https://blog.csdn.net/liuxinghao/article/details/113923639 目录 简介事件队列事件日志事件收集器响应队列读事件 vs. 写事件 简介 事件驱动架构是一种系统或组件之间通过发送事件和响应事件彼此交互的架构风格。当某个事…

2024全国青少年信息素养大赛python复赛真题——计算握手次数

2024全国青少年信息素养大赛python复赛真题——计算握手次数 题目可点下面去处&#xff0c;支持在线编程&#xff0c;在线测评&#xff5e; 计算握手次数&#xff08;2024全国青少年信息素养大赛复赛真题&#xff09;_python_少儿编程题库学习中心-嗨信奥 题库收集了历届各白名…

[春秋云镜] CVE-2023-23752 writeup

首先奉上大佬的wp表示尊敬&#xff1a;&#xff08;很详细&#xff09;[ 漏洞复现篇 ] Joomla未授权访问Rest API漏洞(CVE-2023-23752)_joomla未授权访问漏洞(cve-2023-23752)-CSDN博客 知识点 Joomla版本为4.0.0 到 4.2.7 存在未授权访问漏洞 Joomla是一套全球知名的内容管理…

Trae Builder编程助手-基于Builder完成算法生成+api接口实现全流程

Trae插件下载链接 ​ 总结 使用过Builder后&#xff0c;我的感觉就是&#xff0c;可以通过嘴写代码&#xff01;&#xff01;雄起吧&#xff0c;我们程序员的口语交际能力。同时重点要先把自己的编码环境设置好&#xff0c;否则很麻烦 参考 安装过程单击Trae插件下载链接&…

python笔面试题汇总

1. 如何利用SciKit包训练一个简单的线性回归模型 利用linear_model.LinearRegression()函数 # Create linear regression object regr linear_model.LinearRegression() # Train the model using the training sets regr.fit(data_X_train, data_y_train) 2. 例举几个常用的…

pandas数据分析

数据读取 import pandas as pd df pd.read_csv(D:\my_app\python\python project\data\sample_data.csv) print(df)数据保存 import pandas as pd# 创建示例数据 data {Name: [Alice, Bob, Charlie, David, Eve],Age: [25, 30, 35, 28, 22],City: [Beijing, Shanghai, Guan…

力扣每日一题——找到离给定两个节点最近的节点

目录 题目链接&#xff1a;2359. 找到离给定两个节点最近的节点 - 力扣&#xff08;LeetCode&#xff09; 题目描述 解法一&#xff1a;双指针路径交汇法​ 基本思路 关键步骤 为什么这样可行呢我请问了&#xff1f; 举个例子 特殊情况 Java写法&#xff1a; C写法&a…