新闻详情

新闻详情

首页 / 资讯中心 / 详情

Vue3 + Element Plus 后台管理系统实战:架构、权限与避坑指南

发布时间:2026/9/29 1:23:49来源:尧图网络
Vue3 + Element Plus 后台管理系统实战:架构、权限与避坑指南
1. 项目缘起与整体设计思路1.1 为什么我最后选了 Vue3 Element Plus 这套组合后台管理系统这个品类说实话已经被做烂了但每年还是会有一批新项目要起。我前后带过四五个中后台项目从最早的 jQuery Bootstrap到后来的 Vue2 Element UI再到现在的 Vue3 Element Plus每次技术选型都会被问同一个问题图什么先说结论。Vue3 Element Plus 这套组合在当前时间点上是中小型中后台项目性价比最高的一条路。理由不是Vue3 性能好这种空话而是几个具体到能算账的点。第一个是组合式 API 对逻辑复用的改造。Vue2 时代我们用 mixin 抽公共逻辑一个页面引三四个 mixin变量从哪来的根本查不到改一个方法要全局搜。换成 Vue3 的setup加上自定义组合函数之后一个列表页的分页、搜索、加载状态、重置逻辑能打包成一个useTable哪个页面用了、传了什么参数一眼看得清楚。我实测过一个 30 多个页面的后台重构前后代码量从 8000 多行降到 6000 出头,而且新人接手时理解成本降得特别明显。第二个是Element Plus 的组件覆盖度。后台系统 90% 的界面就是表格、表单、弹窗、日期选择、上传这几样东西反复拼。Element Plus 把这几个核心组件做得足够厚el-table支持多级表头、固定列、树形数据、懒加载el-form的校验规则覆盖了从必填到自定义异步校验的全场景。这意味着你不需要为了一个复杂表单去引第三方库减少依赖就是减少维护成本。第三个是构建工具链的成熟。Vite 现在已经不是尝鲜阶段了冷启动一个中型项目两三秒,热更新基本是保存即生效。对比早期 Vue CLI 用 webpack 那种改一行等五秒的体验开发时的耐心消耗完全不是一个量级。当然也有取舍。Vue3 的响应式用 Proxy 实现对 IE 是完全不支持的如果你的甲方还在要求兼容 IE11那这套方案直接出局。另外 Element Plus 的默认样式偏朴素,想要那种设计感强的后台要么用它的 CSS 变量系统深度定制要么就干脆换 Naive UI 这类更现代感的库。我个人的判断标准是团队里有 2 年以上 Vue 经验的人、项目周期在 3 个月以内、不需要兼容老浏览器这三条同时满足闭眼选这套。1.2 一套后台系统到底要拆成哪几块很多新手一上来就写登录页写着写着发现路由守不住、权限没地方放、请求拦截器到处复制。根子在于没先把架构分层想清楚。我这套项目的分层是这样的基础设施层包括 Vite 配置、环境变量、路径别名、代理配置、代码规范工具。这层不写业务但决定了后面所有代码写得顺不顺。通用能力层封装 axios 实例、统一响应处理、token 存取、全局状态用 Pinia、路由实例。这层的目标是让业务层拿来就用不用关心底层细节。布局与框架层侧边栏、顶栏、标签页、内容区、面包屑。这层是可复用的外壳业务页面都挂在里面。业务页面层具体到每个模块的列表、详情、新增、编辑。我见过太多项目把 token 逻辑写在每个请求里、把权限判断写死在菜单组件里,后期加一个角色就要改十几个文件。分层不是为了好看,是为了改动时能被定位。你改权限规则就只动通用能力层那一个文件业务层完全不用碰。1.3 目录结构怎么排才不闹心下面是我用了几个项目之后固定下来的目录结构你可以直接抄src/ ├── api/ # 所有接口定义按模块拆分 │ ├── user.js │ └── role.js ├── assets/ # 静态资源会被构建处理 ├── components/ # 全局公共组件 │ └── SvgIcon/ ├── composables/ # 组合式函数逻辑复用核心 │ ├── useTable.js │ └── usePermission.js ├── layout/ # 布局外壳 │ ├── index.vue │ └── components/ ├── router/ # 路由与守卫 │ ├── index.js │ └── guard.js ├── stores/ # Pinia 状态 │ ├── user.js │ └── app.js ├── styles/ # 全局样式与变量 ├── utils/ # 纯函数工具 │ ├── request.js │ └── auth.js └── views/ # 业务页面与路由一一对应关键点是api和views的对应关系。我的习惯是路由路径、页面目录、接口文件三者同名比如路由是/system/user那页面在views/system/user/index.vue接口在api/system/user.js。这样别人问你用户管理在哪答案只有一个。命名一致性是团队协作里被严重低估的东西。关于composables这个目录我要单独强调一下。这是 Vue3 相对 Vue2 最大的结构性变化把可复用的响应式逻辑单独抽出来。它不是工具函数工具函数是纯输入输出而 composable 内部可以有ref、computed、生命周期钩子。理解这一点你才算真正用上了 Vue3。2. 环境搭建与工程化配置的关键细节2.1 从零初始化一个不埋雷的工程初始化这一步看着简单但很多坑是在这里埋下的。第一件事确认 Node 版本。Vite 5 要求 Node 18 以上Vite 6 要求 Node 18.18 以上。用node -v看一眼版本不对先升。Windows 上如果同时装了多个 Node建议用nvm-windows管理切换起来比手动改环境变量省事太多。创建项目直接用它官方的脚手架npm create vuelatest my-admin然后它会交互式问你要不要 TypeScript、要不要 Pinia、要不要 Router、要不要 ESLint 和 Prettier。我的建议是Pinia 和 Router 一定要选后面必然要用手动装还得配。TypeScript 看团队。如果团队 TS 经验足就上类型提示在大型项目里能省很多 debug 时间如果团队全是新手强上 TS 会变成any满天飞反而更乱。我个人的折中是新项目用 TS老项目迁移用 JS。ESLint Prettier 一定要选。多人协作没有统一规范代码 review 会变成格式争吵。创建完之后进目录装依赖然后跑起来看看能不能正常访问。2.2 Vite 配置里必须改的几处默认生成的vite.config.js是能跑但基本不能用于实战。我一般会改这几个地方每一处都有明确的理由。路径别名。默认导入组件要写../../../components/xxx层级一多眼睛都花。配个别名之后/components/xxx就搞定import { fileURLToPath, URL } from node:url export default defineConfig({ resolve: { alias: { : fileURLToPath(new URL(./src, import.meta.url)) } } })这里为什么要用fileURLToPath而不是直接用path.resolve(__dirname, src)因为在 ES Module 环境下__dirname是拿不到的用 URL 转换是更稳妥的写法也不会在某些打包场景下出错。开发服务器代理。本地开发时前端跑在 5173后端跑在 8080直接请求会撞跨域。代理配置是这样server: { port: 3000, proxy: { /api: { target: http://localhost:8080, changeOrigin: true, rewrite: (path) path.replace(/^\/api/, ) } } }changeOrigin: true的作用是修改请求头里的 Host让后端认为请求来自它自己的域名绕过同源检查。这个参数忘了加后端有时会拒绝请求而且报错信息很不直观。打包优化。默认打包所有依赖进一个大 chunk首屏加载会很难看。把体积大的库单独拆出来build: { rollupOptions: { output: { manualChunks: { element-plus: [element-plus], echarts: [echarts], vendor: [vue, vue-router, pinia] } } } }这么拆的好处是业务代码改动时vendor和element-plus这两个大 chunk 的 hash 不变用户浏览器缓存能命中只有业务 chunk 需要重新下载。一个真实项目里这个优化能把二次访问的加载时间从 2 秒多降到 400 毫秒左右。2.3 Element Plus 怎么引入才不拖慢首屏Element Plus 支持全量引入和按需引入两种方式。全量引入代码简单但会把整个库几百个组件都打进包里压缩后大概几百 KB首屏直接受影响。按需引入推荐用unplugin-vue-components和unplugin-auto-import这两个插件配置之后你在模板里用el-table插件自动识别并只引入用到的组件样式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: [ AutoImport({ resolvers: [ElementPlusResolver()] }), Components({ resolvers: [ElementPlusResolver()] }) ] })配置完要重启 dev server 才生效。有个坑要提醒自动引入的 API比如ElMessage如果插件没正确识别运行时会报ElMessage is not defined这时候检查一下插件版本和 Vite 版本是否匹配。另外ElMessage、ElMessageBox这类命令式调用的组件的样式有时需要手动在入口文件引入一次因为插件对它们样式的自动处理不完全。注意按需引入不是万能的它省的是没用到的组件你真正用到的组件该多大还是多大。如果项目用到了 Element Plus 里几乎全部组件这种情况很少全量引入反而更省事。关于热词里很多人问的 vue ui 框架对比 element plus简单说一句后台管理密集使用表格和表单的场景Element Plus 的文档和社区案例是最厚的遇到问题搜得到答案Naive UI 类型友好、主题定制强但生态相对薄Ant Design Vue 组件丰富风格偏企业级。没有绝对好坏看你团队熟悉哪个。3. 核心骨架路由、状态与请求层的落地3.1 路由设计静态路由和动态路由要分开后台系统的路由有两类。一类是登录页、404 页这种谁都能访问的叫静态路由直接写在router/index.js里。另一类是登录后根据用户权限动态生成的叫动态路由。分开写的原因很实际如果所有路由都写死那低权限用户虽然看不到某个菜单但手动输 URL 照样能进页面这是安全问题。动态路由的逻辑是登录拿到用户信息后从后端拿这个用户能访问的菜单列表前端根据列表过滤出路由再用router.addRoute动态添加。// router/index.js 静态部分 const constantRoutes [ { path: /login, component: () import(/views/login/index.vue) }, { path: /404, component: () import(/views/error/404.vue) } ] // 登录后动态添加 function addDynamicRoutes(menuList) { menuList.forEach(menu { if (menu.component) { router.addRoute(Layout, { path: menu.path, name: menu.name, component: import(/views/${menu.component}.vue), meta: { title: menu.title, icon: menu.icon } }) } }) }这里addRoute的第一个参数Layout是父路由的 name表示把这个路由挂到 Layout 下面。踩过的坑是如果你挂载的路由 name 和已有的重名Vue Router 会覆盖不报错导致有些页面莫名消失。所以动态路由的 name 一定要保证唯一我一般用路径转驼峰来生成。3.2 路由守卫判断顺序不能乱守卫是整个权限体系的闸门。逻辑顺序错了会出现死循环或者白屏router.beforeEach(async (to, from, next) { const userStore useUserStore() const token userStore.token if (!token) { // 没 token除了白名单都赶去登录 if (whiteList.includes(to.path)) { next() } else { next(/login?redirect${to.path}) } return } // 有 token 但没用户信息说明是刷新页面重新拉一次 if (!userStore.userInfo) { try { await userStore.getUserInfo() next({ ...to, replace: true }) } catch (e) { await userStore.logout() next(/login) } return } next() })关键点是那句next({ ...to, replace: true })。刷新页面时动态路由还没加上直接next()会走到 404。重新触发一次导航这次路由已经生成好了就能正确匹配。这个写法是官方推荐的但很多人第一次做都会卡在这。还有个细节whiteList白名单里必须包含/login否则未登录访问登录页会被重定向到登录页无限循环。3.3 Pinia 状态管理怎么切分Pinia 比 Vuex 舒服太多没有 mutation 那层了直接在 action 里改 state。但怎么切 store 是有讲究的切得太粗会变得像个全局变量垃圾场切得太细又会到处互相引用。我的切分原则是按领域切而不是按功能切。常见的有这几个usertoken、用户信息、权限列表app侧边栏折叠状态、设备类型、主题色tabs标签页列表、当前激活项如果需要多标签重点说user它是权限体系的核心export const useUserStore defineStore(user, { state: () ({ token: getToken() || , userInfo: null, roles: [], permissions: [] }), actions: { async login(loginForm) { const res await loginApi(loginForm) this.token res.data.token setToken(res.data.token) }, async getUserInfo() { const res await getUserInfoApi() this.userInfo res.data.user this.roles res.data.roles this.permissions res.data.permissions } } })为什么 token 要同时存在 state 和 localStoragestate 里是为了响应式localStorage 是为了刷新页面不丢。两者要同步登出的时候都要清掉。我见过只清了一个导致刷新后还是登录态的 bug排查半天。3.4 请求层封装一次写好受益全程axios 封装是最值得花心思的地方。封得好业务里写请求就一行封不好每个请求都要重复写 token、重复处理错误。先创建实例配好基础路径和超时。然后是请求拦截器主要做两件事带上 token、处理重复请求。带 token 是标配service.interceptors.request.use(config { const userStore useUserStore() if (userStore.token) { config.headers.Authorization Bearer ${userStore.token} } return config }, error Promise.reject(error))重复请求这块我要多讲两句。用户手快连点两次提交按钮就发出两个一样的请求可能造成重复下单、重复新增。做法是维护一个 pending 请求的 Map请求发出去前用method url 参数生成 key已存在就取消前一个。这个功能不是必须的但涉及资金、库存这种敏感操作时一定要加配合按钮的 loading 状态双保险。响应拦截器更关键它决定了业务层怎么写service.interceptors.response.use( response { const res response.data if (res.code ! 200) { ElMessage.error(res.message || 请求失败) if (res.code 401) { // token 过期清掉并跳登录 userStore.logout() router.push(/login) } return Promise.reject(new Error(res.message)) } return res }, error { // 网络层错误超时、断网等 ElMessage.error(error.message || 网络异常) return Promise.reject(error) } )注意区分两种错误业务错误HTTP 200 但 code 不是成功值比如用户名密码错和网络错误HTTP 4xx/5xx、超时。前者在第一个回调里处理后者在第二个。很多新手只写了第一个回调导致服务器 500 时页面一片安静用户完全不知道发生了什么。处理完这些业务层调用就干净了const res await getUserList(params)然后直接用res.data。这就是封装的价值。4. 实战落地从登录到增删改查全流程4.1 登录页要处理的几个非表面问题登录页看着就是个表单但有几个点是新手的重灾区。表单校验。用el-form的 rules密码这类字段加上长度和格式限制。写法就不展开重点提醒rules 里每个字段对应的trigger要选对输入框用blur选择器用change。trigger 写错了会出现填了还提示必填的情况。登录按钮防抖。前面说的重复请求防护是一层按钮自身的 loading 是另一层。在handleLogin开头把 loading 置 true请求结束后无论成功失败都置回 false用finally。记住密码。热门搜索里 vue3 登录页面 点线动态的背景 说明很多人想给登录页加视觉效果。用 canvas 画动态点线背景不算难但注意性能粒子数量控制在 60 到 100 个用requestAnimationFrame驱动离开页面时cancelAnimationFrame把循环停掉否则在登录页停留久了会一直占用 CPU。登录成功后的跳转有个坑如果 URL 里带了redirect参数要跳回那个地址而不是固定跳首页。否则用户从某个深层页面被踢到登录登录完回到首页还要自己找回去体验很差。4.2 列表页分页、搜索、加载的组合拳列表页是后台系统里重复率最高的东西值得抽成useTableimport { ref, reactive, onMounted } from vue export function useTable(apiFn, initParams {}) { const loading ref(false) const list ref([]) const total ref(0) const query reactive({ page: 1, pageSize: 10, ...initParams }) async function fetchData() { loading.value true try { const res await apiFn(query) list.value res.data.list total.value res.data.total } finally { loading.value false } } function handleSearch() { query.page 1 // 搜索时重置到第一页这个很重要 fetchData() } function handleReset() { Object.assign(query, { page: 1, pageSize: 10, ...initParams }) fetchData() } onMounted(fetchData) return { loading, list, total, query, fetchData, handleSearch, handleReset } }两个细节值得展开。第一handleSearch里把page重置为 1。如果不重置你在第 5 页按搜索搜出来结果只有 2 页就会显示空白。这个 bug 非常常见。第二loading用try/finally保证。如果写在成功回调里一旦请求报错 loading 永远是 true表格一直转圈。表格本身用el-table字段多的时候给关键列加fixedright固定操作列宽度用min-width而不是width让列能自适应。4.3 表单新增与编辑复用一套代码新增和编辑用同一个表单弹窗是惯例。区别在于编辑时要先回填数据。我的做法是用一个dialogType变量区分function handleAdd() { dialogType.value add formRef.value?.resetFields() // 先重置校验状态 Object.assign(form, getDefaultForm()) dialogVisible.value true } async function handleEdit(row) { dialogType.value edit dialogVisible.value true // 先打开弹窗再请求避免弹窗卡顿 const res await getDetailApi(row.id) Object.assign(form, res.data) }这里有个顺序讲究编辑时先打开弹窗再拉详情让用户立刻看到响应如果用await等数据回来才开弹窗网络慢时会有明显延迟感。还有resetFields这个坑。它的作用是重置表单校验状态和字段值但它只对在 el-form 上声明的 model 字段有效而且要在表单渲染完成后调用。如果你在弹窗还没渲染的时候调会报错或无效。所以我一般用formRef.value?.resetFields()加可选链且确认dialogVisible已经为 true。4.4 删除操作二次确认不能少删除是最危险的操作一定要二次确认async function handleDelete(row) { try { await ElMessageBox.confirm(确定删除「${row.name}」吗, 提示, { type: warning }) } catch { return // 用户点取消直接返回 } await deleteApi(row.id) ElMessage.success(删除成功) fetchData() }ElMessageBox.confirm在用户点取消时会reject所以要 catch 住不然后台会报未捕获的 Promise 错误。删除后要刷新列表但更友好的做法是判断当前页删完后是否为空如果空了就往前翻一页再刷新。这个细节能让用户少一次删完发现页面空白的困惑。批量操作要用el-table的selection-change事件收集选中项注意row-key必须设置且唯一否则选中状态在数据更新后会错乱。5. 常见问题排查与避坑实录5.1 开发环境类问题速查下面这张表是我和团队踩过的坑里最高频的一部分直接对照排查现象大概率原因处理方式启动报 Node 版本错误Node 低于 18升级 Node用 nvm 管理多版本组件自动引入失败插件未生效重启 dev server检查插件与 Vite 版本代理请求 404后端路径没配对检查 rewrite 规则是否正确去掉前缀修改样式不生效scoped 样式隔离用:deep()穿透子组件样式HMR 热更新失效文件大小写不一致检查 import 路径大小写与文件名完全一致特别说下Windows 上大小写问题。Windows 文件系统不区分大小写所以import Foo from ./foo.vue即使实际文件是Foo.vue也能跑。但一旦部署到 Linux 服务器构建直接失败。建议在 VS Code 里开启files.insensitive相关提示或者干脆养成严格大小写的习惯。还有热词里提到的 vue3 项目在 edge 浏览器中无法关闭最小化按钮这类问题一般是某些第三方库操作了浏览器原生 UI 导致的属于特定环境问题排查时先确认是不是引入了某个 UI 库或浏览器扩展所致。5.2 请求相关的典型问题token 过期后页面不停弹登录框。原因是响应拦截器里发现 401 直接跳登录但页面上可能有多个并发请求同时返回 401就会触发多次跳转。解决办法是加一个标志位第一个 401 的时候标记正在跳转后续 401 直接忽略let isRelogin false if (res.code 401 !isRelogin) { isRelogin true userStore.logout().finally(() { isRelogin false router.push(/login) }) }上传文件时 Content-Type 不对。用el-upload配合自定义请求时如果手动设了Content-Type: application/json文件就传不上去。正确做法是用FormData并让浏览器自动带上 multipart 的 boundary不要手动设 Content-Type。GET 请求传数组参数丢失。axios 默认对数组的序列化可能不符合后端预期。如果后端要ids1ids2需要配置paramsSerializer或者用URLSearchParams手动拼。5.3 权限控制的常见误区只藏了菜单没管路由。前面说过菜单隐藏不代表路由不可达。真正的权限控制要三层菜单不显示、路由不注册、按钮不渲染。按钮级权限可以用自定义指令// v-permission 指令 app.directive(permission, { mounted(el, binding) { const userStore useUserStore() if (!userStore.permissions.includes(binding.value)) { el.parentNode?.removeChild(el) } } })用的时候el-button v-permissionuser:delete删除/el-button。注意用的是removeChild而不是display: none因为隐藏的按钮理论上还能通过控制台触发点击删掉更彻底。当然真正的安全还是要后端再校验一次前端权限只是防误操作和提升体验绝对不能作为安全边界。动态路由刷新丢失。这是最经典的坑前面路由守卫那里已经给了方案核心就是刷新后重新拉一次菜单并生成路由且用next({ ...to, replace: true })重新触发导航。5.4 性能与体验优化心得表格大数据量卡顿。一页 100 条以上、列又多的表格会明显卡。第一选择是后端分页别一次拉几千条如果确实要展示大量行用el-table-v2虚拟滚动只渲染可视区域几千行也丝滑。图标全量引入导致包变大。Element Plus 的图标如果用import * as Icons全量注册会显著增加体积。建议按需引入或者用unplugin-icons自动处理。路由懒加载别忘了写。所有业务页面都用() import()动态导入Vite 会自动分包首屏只加载当前页面。如果全写成同步 import首屏会把所有页面都拉下来白屏时间翻倍。提醒性能优化一定要有数据支撑再动手。先跑一次构建看 chunk 体积用浏览器的 Performance 面板看真实瓶颈再决定优化哪块。凭感觉优化往往做了无用功。5.5 我从几个项目里攒下的实操建议最后分享几条不成体系但很值钱的经验。环境变量要区分清楚。.env.development和.env.production里的接口地址要区分开且变量名必须以VITE_开头 Vite 才会暴露给客户端。曾经有个项目把生产地址写进了开发配置打包后直接请求了生产库幸好及时发现。涉及敏感信息的东西绝对不要写在前端环境变量里因为打包后是明文可见的。提交前一定要跑一次 lint 和构建。本地开发时 Vite 不做类型检查和严格的 lint很多错误要到构建才暴露。装个husky加lint-staged提交时自动跑能拦住一大批低级错误。给团队写一份路由与接口的约定文档。不用长一页纸说清楚命名规范、目录对应关系、接口返回格式。这份文档能省下后面无数次口头解释尤其是团队有新人的时候。贵在一致不在最优。技术选型上纠结半天用哪个 UI 库、哪个状态管理对项目成败的影响远小于全项目风格是否统一。一套不那么完美但贯彻到底的规范胜过每个人各显神通。我带过的项目里出问题最多的从来不是技术选型选错而是同一件事有五种写法。关于后续扩展这套骨架往上加东西其实很顺需要可视化大屏就接 ECharts需要流程图就接 LogicFlow需要导出打印就接打印组件。因为基础层封得干净加新能力基本不动老代码。这也是为什么我一开始强调要把基础设施层和通用能力层做扎实前面多花的半天时间后面每个新功能都在还本付息。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

LT3045 LDO典型应用电路解析:PSRR与布局实战 2026/9/29 2:04:18

LT3045 LDO典型应用电路解析:PSRR与布局实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
一条用户消息的完整旅程:爪爪 PawWork sendMessage 工具循环源码解析 2026/9/29 2:04:18

一条用户消息的完整旅程:爪爪 PawWork sendMessage 工具循环源码解析

一条用户消息的完整旅程:爪爪 PawWork sendMessage 工具循环源码解析 【免费下载链接】BrowserKitten Paw Work - selection-first web agent for Chrome: select on the live page, describe the outcome, take away an editable office file. BYOK, sandboxed, no…

阅读更多 →
散户交易情绪全景深度分析:情绪周期、行为逻辑与市场影响量化拆解/反向预判、规避误区、把握拐点 2026/9/29 2:04:18

散户交易情绪全景深度分析:情绪周期、行为逻辑与市场影响量化拆解/反向预判、规避误区、把握拐点

A股市场最核心的交易特征之一,是散户交易情绪主导短期市场波动、机构资金定义中长期趋势。散户作为市场体量最大、交易最活跃的投资群体,其集体情绪的贪婪与恐惧、乐观与悲观,会直接催生短期涨跌、题材轮动、成交量异动乃至市场极致拐点。不同…

阅读更多 →
AI赋能硬件开发:从电机控制到芯片调试的实战经验 2026/9/29 2:04:18

AI赋能硬件开发:从电机控制到芯片调试的实战经验

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
边缘AI芯片选型:从场景反推芯片,避开算力与功耗误区 2026/9/29 2:04:18

边缘AI芯片选型:从场景反推芯片,避开算力与功耗误区

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
红外PPG心率检测系统设计与实操指南 2026/9/29 2:04:12

红外PPG心率检测系统设计与实操指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉