实现一个简单的后台架子(侧边栏菜单渲染,折叠,黑白主题,组件主题色,全屏,路由快捷栏)
目录
侧边栏菜单渲染
侧边栏折叠
黑白主题
全屏切换
切换组件主题色
tab快捷栏
代码
侧边栏菜单渲染
结合ElementPlus组件库进行实现
新建的Vue3项目,引入了格式化样式normalize.css和ElementPlus,并进行了全局引入

并进行了全局引入

设置高度为100%

粘贴ElementPlus的布局容器代码,到HomeView.vue文件中,并进行简单修改

<template><div class="contioner"><el-container class="layout-container-demo" style="height: 100%"><!-- 侧边栏 START --><el-aside width="200px"><el-scrollbar><el-menu router><!-- 一级菜单 --><el-menu-item index="1-4-1">一级菜单</el-menu-item><!-- 子级菜单 --><el-sub-menu index="1"><template #title><el-icon><message /></el-icon>子级菜单</template><el-menu-item index="1-4-1">孙子菜单1</el-menu-item><el-sub-menu index="1-4"><template #title>孙子菜单2</template><el-menu-item index="1-4-1">重孙菜单</el-menu-item></el-sub-menu></el-sub-menu></el-menu></el-scrollbar></el-aside><!-- 侧边栏 END --><!-- 内容区 START --><el-container><el-header style="text-align: right; font-size: 12px"><div class="toolbar"><el-dropdown><el-icon style="margin-right: 8px; margin-top: 1px"><setting /></el-icon><template #dropdown><el-dropdown-menu><el-dropdown-item>View</el-dropdown-item><el-dropdown-item>Add</el-dropdown-item><el-dropdown-item>Delete</el-dropdown-item></el-dropdown-menu></template></el-dropdown><span>Tom</span></div></el-header><el-main><el-scrollbar><!-- 路由出口,可以展示子级菜单内容 --><router-view></router-view></el-scrollbar></el-main></el-container><!-- 内容区 END --></el-container></div>
</template><script setup lang="ts">
import { Message, Setting } from '@element-plus/icons-vue'
</script><style scoped>
.contioner {width: 100%;height: 100%;
}.layout-container-demo .el-header {position: relative;background-color: var(--el-color-primary-light-7);color: var(--el-text-color-primary);
}
.layout-container-demo .el-aside {color: var(--el-text-color-primary);background: var(--el-color-primary-light-8);
}
.layout-container-demo .el-menu {border-right: none;
}
.layout-container-demo .el-main {padding: 0;
}
.layout-container-demo .toolbar {display: inline-flex;align-items: center;justify-content: center;height: 100%;right: 20px;
}
</style>
效果图如下,一个简单的后台架子就出来了

然后开始路由新增
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: '/',name: 'home',component: HomeView,children: [{path: '/test1',name: 'test1',component: () => import('@/views/ParentPage.vue'),},{path: '/test2',name: 'test2',children: [{path: '/test3',name: 'test3',component: () => import('@/views/SonPage.vue'),},{path: '/test4',name: 'test4',children: [{path: '/test5',name: 'test5',component: () => import('@/views/SonPage.vue'),},],},],},],},{path: '/login',name: 'login',component: () => import('../views/AboutView.vue'),},],
})export default router
在views下新增ParentPage.vue和SonPage.vue文件
路由定义好了,就可以在HomeView.vue文件中引入路由数据了
<script setup lang="ts">
import { Message, Setting } from '@element-plus/icons-vue'
import { computed } from 'vue'
import { useRouter } from 'vue-router'const router = useRouter()// 路由数据
const routes = computed(() => {return router.getRoutes().filter(p => p.path === '/')[0].children
})
</script>
多级菜单渲染,需要用到递归组件,所以我们把侧边栏菜单展示进行封装,views下新建MenuTree.vue
<template><div><template v-for="i in routes" :key="i.path"><!-- 一级菜单 --><el-menu-item :index="i.path" v-if="!i.children">{{ i.path }}</el-menu-item><!-- 子级菜单 --><el-sub-menu :index="i.path" v-else><template #title><el-icon><message /></el-icon>{{ i.path }}</template><!-- 使用递归组件,传递嵌套路由数据 --><MenuTree :routes="i.children"></MenuTree></el-sub-menu></template></div>
</template><script setup lang="ts">
import { Message } from '@element-plus/icons-vue'
import type { RouteRecordRaw } from 'vue-router'defineProps({routes: {type: Array<RouteRecordRaw>,default: () => [],},
})
</script>
最后在HomeView.vue中引入此组件
<!-- 侧边栏 START --><el-aside width="200px"><el-scrollbar><el-menu router><MenuTree :routes="routes"></MenuTree></el-menu></el-scrollbar></el-aside><!-- 侧边栏 END -->
此时就完成了侧边栏菜单的渲染

侧边栏折叠
然后再加一个侧边栏折叠的功能

添加一个按钮到头部,修改HomeView.vue
结构处修改:<el-header><el-button type="primary" size="small">折叠/展开</el-button><div class="toolbar"><el-dropdown><el-icon style="margin-right: 8px; margin-top: 1px"><setting /></el-icon><template #dropdown><el-dropdown-menu><el-dropdown-item>View</el-dropdown-item><el-dropdown-item>Add</el-dropdown-item><el-dropdown-item>Delete</el-dropdown-item></el-dropdown-menu></template></el-dropdown><span>Tom</span></div></el-header>样式处修改:
.layout-container-demo .el-header {position: relative;background-color: var(--el-color-primary-light-7);color: var(--el-text-color-primary);display: flex;justify-content: space-between;align-items: center;
}
页面效果

然后修改侧边栏代码 修改HomeView.vue
结构处修改<!-- 侧边栏 START --><!-- width="collapse" 可以让侧边栏宽度正好合适!!! --><el-aside width="collapse"><el-scrollbar><el-menu router class="el-menu-vertical-demo" :collapse="isCollapse"><MenuTree :routes="routes"></MenuTree></el-menu></el-scrollbar></el-aside><!-- 侧边栏 END -->逻辑处新增:
// 折叠状态
const isCollapse = ref(false)
// 折叠/展开
const collapseChange = () => {isCollapse.value = !isCollapse.value
}样式处新增:
/* 侧边栏宽度 */
.el-menu-vertical-demo:not(.el-menu--collapse) {width: 200px;
}
MenuTree.vue修改
<template><template v-for="i in routes" :key="i.path"><!-- 一级菜单 --><el-menu-item :index="i.path" v-if="!i.children">{{ i.path }}</el-menu-item><!-- 子级菜单 --><el-sub-menu :index="i.path" v-else><template #title><el-icon><message /></el-icon><!-- 标题一定要用标签包裹,不然折叠的时候会显示一部分字!!! --><span>{{ i.path }}</span></template><!-- 使用递归组件,传递嵌套路由数据 --><MenuTree :routes="i.children"></MenuTree></el-sub-menu></template>
</template>
看下效果:
- 折叠

- 展开

黑白主题
然后再加个黑白主题吧(ElementPlus本身就有此功能)暗黑模式 | Element Plus
首先在main.ts中引入暗色主题
import 'element-plus/theme-chalk/dark/css-vars.css'
然后在HomeView.vue中新增切换按钮并添加逻辑处理
结构处修改: <el-header><el-button type="primary" size="small" @click="collapseChange">折叠/展开</el-button><div class="toolbar"><el-switchinline-promptv-model="theme"active-text="暗黑"inactive-text="白亮"@change="toggle"/><el-dropdown><el-icon style="margin-right: 8px; margin-top: 1px"><setting /></el-icon><template #dropdown><el-dropdown-menu><el-dropdown-item>View</el-dropdown-item><el-dropdown-item>Add</el-dropdown-item><el-dropdown-item>Delete</el-dropdown-item></el-dropdown-menu></template></el-dropdown><span>Tom</span></div></el-header>逻辑处修改:
// 引入切换主题的hook
import { useDark, useToggle } from '@vueuse/core'// 主题状态
const theme = ref(localStorage.getItem('theme') === 'dark' ? true : false)// 切换主题
const isDark = useDark({// 存储到localStorage中的Key 根据自己的需求更改storageKey: 'theme',// 暗黑class名字valueDark: 'dark',// 高亮class名字valueLight: 'light',
})
const toggle = useToggle(isDark)
但是这个只实现了在组件库的主题切换,我们自己写的代码也要实现主题切换,可以在assets文件夹下新建theme文件夹,再新建theme.scss文件
// 主题
$themes: (// 白亮: 设置一些字体颜色,背景色什么的light:(background: #fff,color: #000,textColor: #000,),// 暗黑dark:(background: #121212,color: #fff,textColor: #fff,)
);// 当前主题
$curTheme: light;// 混合
// @mixin useTheme() {
// html[data-theme='light'] & {
// background-color: #fff;
// color: #000;
// }
// html[data-theme='dark'] & {
// background-color: #121212;
// color: #fff;
// }
// }// 混合优化(遍历上面的主题)
@mixin useTheme() {@each $key, $value in $themes {$curTheme: $key !global; // 当前的主题html[data-theme='#{$key}'] & {// & 表示传入什么选择器就是什么选择器@content; // 类似于插槽,样式可以进行传入}}
}// 生成对应主题的变量
@function getVar($key) {$themeMap: map-get($themes, $curTheme);@return map-get($themeMap, $key);
}
全局引入此scss文件
import { fileURLToPath, URL } from 'node:url'import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'// https://vite.dev/config/
export default defineConfig({plugins: [vue(), vueJsx()],resolve: {alias: {'@': fileURLToPath(new URL('./src', import.meta.url)),},},// 配置全局scss文件css: {preprocessorOptions: {// 引入全局的scss文件scss: {additionalData: `@import "./src/assets/theme/theme.scss";`,},},},
})
找个测试页面测试即可
<template><div><h2>父级页面</h2><div class="box"></div><div class="mb-4"><el-button>Default</el-button><el-button type="primary">Primary</el-button><el-button type="success">Success</el-button><el-button type="info">Info</el-button><el-button type="warning">Warning</el-button><el-button type="danger">Danger</el-button></div></div>
</template><script setup lang="ts"></script><style scoped>
.box {width: 100%;height: 200px;/* 使用主题变量 */background-color: getVar('background');
}
</style>
全屏切换
再做一个切换全屏的效果
安装一个screenfull插件
npm i screenfull
然后修改HomeView.vue的代码
结构处修改:
<el-header><el-button type="primary" size="small" @click="collapseChange">折叠/展开</el-button><div class="toolbar"><el-switchinline-promptv-model="theme"active-text="暗黑"inactive-text="白亮"@change="toggle"/><el-button type="primary" size="small" @click="screenfullChange">全屏/非全屏</el-button><el-dropdown><el-icon style="margin-right: 8px; margin-top: 1px"><setting /></el-icon><template #dropdown><el-dropdown-menu><el-dropdown-item>View</el-dropdown-item><el-dropdown-item>Add</el-dropdown-item><el-dropdown-item>Delete</el-dropdown-item></el-dropdown-menu></template></el-dropdown><span>Tom</span></div></el-header>逻辑处修改:
import screenfull from 'screenfull'
import { ElMessage } from 'element-plus'// 全屏/非全屏
const screenfullChange = () => {if (!screenfull.isEnabled) {return ElMessage({ message: '你的浏览器不支持全屏', type: 'warning' })}screenfull.toggle()
}
切换组件主题色
如果不喜欢ElementPlus的组件配色,也可以自己进行修改: 主题 | Element Plus
新建styles文件夹,然后再新建element文件夹,然后再新建index.scss文件,粘贴以下代码
// styles/element/index.scss
/* 只需要重写你需要的即可 */
@forward 'element-plus/theme-chalk/src/common/var.scss' with ($colors: ('primary': ('base': green,),),
);// 如果只是按需导入,则可以忽略以下内容。
// 如果你想导入所有样式:
@use "element-plus/theme-chalk/src/index.scss" as *;
然后再修改main.ts,更换引入的scss文件
import ElementPlus from 'element-plus'// import 'element-plus/dist/index.css' // 更换完下面的scss文件,因为下面的scss文件中已经引入了所有样式
import './styles/element/index.scss'
此时就已经修改成功了,组件主题色都变成了我们设置的颜色

但是如果想通过按钮修改主题色呢?比如下面的效果

我们应该这么做
新增一个处理设置组件主题颜色的函数:在utils文件夹下新增theme.ts
// import { useCssVar } from '@vueuse/core'type RGB = {r: numberg: numberb: number
}const rgbWhite = {r: 255,g: 255,b: 255,
}
const rgbBlack = {r: 0,g: 0,b: 0,
}function componentToHex(c: number): string {const hex = Math.round(c).toString(16)return hex.length === 1 ? '0' + hex : hex
}function rgbToHex(rgb: RGB): string {return `#${componentToHex(rgb.r)}${componentToHex(rgb.g)}${componentToHex(rgb.b)}`
}function mix(color: RGB, mixColor: RGB, weight: number): RGB {return {r: color.r * (1 - weight) + mixColor.r * weight,g: color.g * (1 - weight) + mixColor.g * weight,b: color.b * (1 - weight) + mixColor.b * weight,}
}/*** hex 转换为 rgb* @param hex 例如 #FF0000*/
function hexToRGB(hex: string): RGB {if (!/^[0-9A-Fa-f]{3}$|[0-9A-Fa-f]{6}$/.test(hex)) {throw new Error('请传入合法的16进制颜色值,eg: #FF0000')}// 移除可能存在的 # 符号hex = hex.replace('#', '')// 确保十六进制代码是有效的// 返回 RGB 对象return {r: parseInt(hex.slice(0, 2), 16),g: parseInt(hex.slice(2, 4), 16),b: parseInt(hex.slice(4, 6), 16),}
}/*** 修改 element-plus的颜色主题*/
function updateElementPlusTheme(type: string, baseColor: string): void {// 针对 element-plus 进行修改const colorArray: Record<string, string>[] = [{ className: `--el-color-${type}`, color: rgbToHex(mix(hexToRGB(baseColor), rgbBlack, 0)) },{className: `--el-color-${type}-dark-2`,color: rgbToHex(mix(hexToRGB(baseColor), rgbBlack, 0.2)),},{className: `--el-color-${type}-light-3`,color: rgbToHex(mix(hexToRGB(baseColor), rgbWhite, 0.3)),},{className: `--el-color-${type}-light-5`,color: rgbToHex(mix(hexToRGB(baseColor), rgbWhite, 0.5)),},{className: `--el-color-${type}-light-7`,color: rgbToHex(mix(hexToRGB(baseColor), rgbWhite, 0.7)),},{className: `--el-color-${type}-light-8`,color: rgbToHex(mix(hexToRGB(baseColor), rgbWhite, 0.78)),},{className: `--el-color-${type}-light-9`,color: rgbToHex(mix(hexToRGB(baseColor), rgbWhite, 0.85)),},]// document.documentElement 是全局变量时// const el = document.documentElementcolorArray.forEach((item) => {// 下面两种方式都可以// 方法1: 需要把顶部的导入解开// const color = useCssVar(item.className, document.documentElement)// color.value = item.color// 方法2:document.documentElement.style.setProperty(item.className, item.color)// 方法3: 把上面的el解开// 获取 css 变量// getComputedStyle(el).getPropertyValue(item.className)// 设置 css 变量// el.style.setProperty(item.className, item.color)})
}export { type RGB, hexToRGB, rgbToHex, updateElementPlusTheme }
修改HomeView.vue:
结构处修改:<!-- 颜色选择器 --><el-color-pickerv-model="color":predefine="predefineColors"@change="setThemeColor"color-format="hex":show-alpha="false"/>逻辑处修改:
import { updateElementPlusTheme } from '@/utils/theme'// 颜色
const color = ref(localStorage.getItem('theme-color') || '#409EFF')
// 组件预定义颜色
const predefineColors = ref(['#ff4500','#ff8c00','#ffd700','#90ee90','#00ced1','#1e90ff','#c71585','rgba(255, 69, 0, 0.68)','rgb(255, 120, 0)','hsv(51, 100, 98)','hsva(120, 40, 94, 0.5)','hsl(181, 100%, 37%)','hsla(209, 100%, 56%, 0.73)','#c7158577',
])/*** 设置主题颜色* @param type 类型* @param color 颜色*/
const setThemeColor = (color: string, type = 'primary') => {// 存入本地主题颜色的值if (localStorage.getItem('theme-color') !== color) {localStorage.setItem('theme-color', color)}// 更新 Element Plus 主题updateElementPlusTheme(type, color)
}
看下效果

但是刷新后还是会丢失,所以我们在App.vue中重新设置下组件的主题颜,刷新后也不会丢失
import { onMounted } from 'vue'
import { updateElementPlusTheme } from './utils/theme'onMounted(() => {updateElementPlusTheme('primary',localStorage.getItem('theme-color') || '#409EFF',)
})
tab快捷栏
设置快捷栏需要用到pinia持久化,所以我们要先下载一个持久化插件
npm i pinia-plugin-persistedstate
然后修改counter.ts

import { ref } from 'vue'
import { defineStore, createPinia } from 'pinia'
import piniaPluginPersistedstate from 'pinia-plugin-persistedstate'
import router from '@/router'
import { ElMessage } from 'element-plus'// 创建仓库
const pinia = createPinia()// 使用插件进行持久化存储
pinia.use(piniaPluginPersistedstate)interface IHistoryList {path: stringname: string
}export const useCounterStore = defineStore('counter',() => {const historyList = ref<IHistoryList[]>([])// 设置菜单历史记录列表的方法const setHistoryList = ({ path, name }: IHistoryList) => {// 没有就添加if (historyList.value.findIndex(i => i.path === path) === -1) {historyList.value.push({ path, name })}}// 清除某个菜单历史记录列表的方法const clearHistory = (path: string) => {// 如果只剩下一个路由,则弹窗提示,不操作if (historyList.value.length === 1) {return ElMessage.warning('只剩下一个路由了,无法删除')}// 跳转到后一个路由const index = historyList.value.findIndex(i => i.path === path)// 如果是最后一个路由则跳转到前一个路由if (index === historyList.value.length - 1) {router.push(historyList.value[index - 1].path)} else {router.push(historyList.value[index + 1].path)}// 删除该路由historyList.value = historyList.value.filter(i => i.path !== path)}return { historyList, setHistoryList, clearHistory }},{// 设置持久化persist: {key: 'settingInfo',storage: sessionStorage,},},
)
然后还需要修改一下路由配置,也就是router文件夹下的index.ts。设置了首页重定向,然后新增了一个全局路由前置守卫(监听路由跳转,好往路由历史数组里添加路由信息)
import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'
import { useCounterStore } from '@/stores/counter'const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: '/',name: 'home',component: HomeView,// 首页进来重定向到test1redirect: '/test1',children: [{path: '/test1',name: 'test1',component: () => import('@/views/ParentPage.vue'),},{path: '/test2',name: 'test2',children: [{path: '/test3',name: 'test3',component: () => import('@/views/SonPage.vue'),},{path: '/test4',name: 'test4',children: [{path: '/test5',name: 'test5',component: () => import('@/views/SonPage.vue'),},],},],},],},{path: '/login',name: 'login',component: () => import('../views/AboutView.vue'),},],
})// 全局前置路由守卫
router.beforeEach(to => {const path = to.pathconst name = to.name as stringuseCounterStore().setHistoryList({ path, name })return true
})export default router
最后修改HomeView.vue文件
结构处修改:<el-header><div class="header"><el-button type="primary" size="small" @click="collapseChange">折叠/展开</el-button><div class="toolbar"><el-switch inline-prompt v-model="theme" active-text="暗黑" inactive-text="白亮" @change="toggle" /><el-button type="primary" size="small" @click="screenfullChange">全屏/非全屏</el-button><!-- 颜色选择器 --><el-color-picker v-model="color" :predefine="predefineColors" @change="setThemeColor" color-format="hex":show-alpha="false" /><el-dropdown><el-icon style="margin-right: 8px; margin-top: 1px"><setting /></el-icon><template #dropdown><el-dropdown-menu><el-dropdown-item>View</el-dropdown-item><el-dropdown-item>Add</el-dropdown-item><el-dropdown-item>Delete</el-dropdown-item></el-dropdown-menu></template></el-dropdown><span>Tom</span></div></div><el-tag v-for="tag in store.historyList" :key="tag.name" closable @click="toPath(tag.path)"@close="delHistory(tag.path)" class="ml-2">{{ tag.name }}</el-tag></el-header>逻辑处修改:
import { useCounterStore } from '@/stores/counter'const store = useCounterStore()// 删除历史记录
const delHistory = (path: string) => {store.clearHistory(path)
}
// 跳转路由
const toPath = (path: string) => {router.push(path)
}样式处修改:
.layout-container-demo .el-header {position: relative;background-color: var(--el-color-primary-light-7);color: var(--el-text-color-primary);
}.header {display: flex;justify-content: space-between;align-items: center;
}
.ml-2 {margin-left: 8px;
}
效果:

至于想实现下面的效果

可以使用ElementPlus的Dropdown组件,做出修改即可,本质就是操作pinia中存储的路由历史数组

代码
通过网盘分享的文件:test.zip
链接: https://pan.baidu.com/s/1mmGT_xjW52s9dKUVJNZE2Q?pwd=atm8 提取码: atm8
写的很糙,关注实现即可。有空闲时间了,还会加上中英文切换
相关文章:
实现一个简单的后台架子(侧边栏菜单渲染,折叠,黑白主题,组件主题色,全屏,路由快捷栏)
目录 侧边栏菜单渲染 侧边栏折叠 黑白主题 全屏切换 切换组件主题色 tab快捷栏 代码 侧边栏菜单渲染 结合ElementPlus组件库进行实现 新建的Vue3项目,引入了格式化样式normalize.css和ElementPlus,并进行了全局引入 并进行了全局引入 设置高度为100% 粘贴ElementPlus的…...
vue3-canvas实现在图片上框选标记(放大,缩小,移动,删除)
双图版本(模板对比) 业务描述:模板与图片对比,只操作模板框选的位置进行色差对比,传框选坐标位置给后端,返回对比结果显示 draw.js文件: 新增了 createUuid,和求取两个数组差集的方…...
unity3d—demo(2d人物左右移动发射子弹)
目录 人物代码示例: 子弹代码示例: 总结上面代码: 注意点: 人物代码示例: using System.Collections; using System.Collections.Generic; using UnityEngine;public class PlayerTiao : MonoBehaviour {public f…...
【ETCD】【源码阅读】 深入解析 raftNode.start`函数:Raft 核心启动逻辑剖析
raftNode.start方法 是 etcd 中 Raft 模块的核心启动点,其职责是管理 Raft 状态机的状态变迁、日志处理及集群通信等逻辑。通过对源码的逐行分析,我们将全面揭示其运行机制,探讨其设计背后的分布式系统理念。 函数核心结构 raftNode.start 方…...
Robust Depth Enhancement via Polarization Prompt Fusion Tuning
paper:论文地址 code:github项目地址 今天给大家分享一篇2024CVPR上的文章,文章是用偏振做提示学习,做深度估计的。模型架构图如下 这篇博客不是讲这篇论文的内容,感兴趣的自己去看paper,主要是分享环境&…...
NEFTune,SFT训练阶段给Embedding加噪音
仿照CV里,数据增强的思路(给图像做旋转、反转、改变亮度等);NLP里,SFT训练数据较少时,也可往embedding上加噪音,来增加训练数据的丰富程度。进而提升最终训练效果。 前提假设:Embed…...
uniapp -- 实现页面滚动触底加载数据
效果 首选,是在pages.json配置开启下拉刷新 {"path": "pages/my/document/officialDocument","style": {"navigationStyle":</...
L22.【LeetCode笔记】相交链表(新版)
目录 1.题目 代码模板 2.分析 编辑 算法误区 正确方法1 但不能通过所有的测试用例 修改后 提交结果 正确方法2 节省代码的技巧 1.题目 https://leetcode.cn/problems/3u1WK4/description/ 给定两个单链表的头节点 headA 和 headB ,请找出并返回两个单…...
智能时代网络空间认知安全新观察
文章目录 前言一、历史上的四次认知革命二、人工智能革命掀起认知安全新浪潮三、人工智能技术塑造认知安全新范式四、人工智能治理应对认知安全新思考 前言 12月5日,在2024第三届北外滩网络安全论坛上以“智能时代网络空间认知安全新观察”为主题作主旨演讲&#x…...
游戏如何应对模拟器作弊
模拟器是指能在PC端模拟出安卓手机系统的软件,市面上比较常见的安卓模拟器有:雷电模拟器、MuMu模拟器、夜神模拟器等。 市面上常见的模拟器 模拟器既可以节省手机内存空间,避免长时间玩游戏手机发烫发热的尴尬,也可以用键盘鼠标对…...
c++ 判断一个 IP 地址(可能是 IPv6 或 IPv4)是否属于特定范围
在 C 中,判断一个 IP 地址(可能是 IPv6 或 IPv4)是否属于特定范围时,需要考虑两种不同的地址格式和它们的范围比较。IPv6 和 IPv4 地址结构完全不同,因此需要分别处理这两种地址类型。 实现思路: 识别 IP…...
计算机视觉——相机标定(Camera Calibration)
文章目录 1. 简介2. 原理3. 相机模型3.1 四大坐标系3.2 坐标系间的转换关系3.2.1 世界坐标系到相机坐标系3.2.2 相机坐标系到图像坐标系3.2.3 像素坐标系转换为图像坐标系3.2.4 世界坐标转换为像素坐标 3.3 畸变3.3.1 畸变类型3.3.1.1 径向畸变(Radial Distortion&a…...
【qt环境配置】windows下的qt与vs工具集安装\版本对应关系
vs工具集安装通过vs的在线安装器勾选工具集即可 工具包下载路径:https://www.microsoft.com/zh-cn/download/details.aspx?id40784 配置工具集在qt中可以自动扫描到 《正确在 Windows 上配置 MSVC(2019) 作为 Qt 编译器》https://b3logfile.com/pdf/article/15922…...
GitHub使用
太久不用GitHub发现自己又有些不会了,突发奇想为何不把每次看到的有指导意义的博客收录一下以便下次查阅呢 如何上传文件夹到GitHub上(配图详解)?_github上傳資料夾-CSDN博客 github上如何删除自己的仓库_github删除仓库-CSDN博…...
元宇宙时代的社交平台:Facebook的愿景与实践
随着科技的不断进步,元宇宙(Metaverse)这一概念逐渐走进了人们的视野。作为全球最大的社交平台之一,Facebook(现Meta)在这场元宇宙革命中扮演着重要角色。Meta不仅在不断扩展其社交平台的边界,还…...
vue2中各种钩子函数的总结以及使用场景
在 Vue 2 中,生命周期钩子函数是 Vue 实例在不同阶段自动调用的函数。这些钩子允许开发者在组件的创建、更新和销毁的特定时刻插入自定义逻辑。以下是 Vue 2 中的各种生命周期钩子函数的总结及其使用场景。 生命周期钩子函数总结 1、beforeCreate 调用时机&#…...
软件架构:从传统单体到现代微服务的技术演变
1.引言 在软件开发中,架构设计不仅仅是程序员的技术任务,它更是一个项目成功的关键。无论是小型应用还是大型分布式系统,软件架构都直接影响着系统的可维护性、可扩展性、性能和稳定性。理解软件架构的必要性,能够帮助开发人员做…...
git新建远程分支后,无法切换
git remote # 列出所有远程主机 git remote update origin --prune # 更新远程主机origin 整理分支 git branch -r # 列出远程分支 git branch -vv # 查看本地分支和远程分支对应关系 git checkout -b gpf origin/gpf # 新建本地分支gpf与远程gpf分支相关…...
【SpringBoot】31 Session + Redis 实战
Gitee https://gitee.com/Lin_DH/system 介绍 【SpringBoot】30 Cookie、Session、Token https://blog.csdn.net/weixin_44088274/article/details/144241595 背景 Spring Session 是 Spring 的一个子项目,它提供了一种管理用户会话信息的方法,无论…...
在Windows环境下的rknn-toolkit环境搭建
首先安装好conda,我是用的是anaconda,miniconda也可以。 下载rknn_toolkit的轮子。可以直接在瑞芯微的git仓库中下载,地址为:github.com/rockchip-linux/rknn-toolkit/releases。我这里下载的是1.7.5版本的。选择rknn-toolkit-v1.…...
深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...
Leetcode 3577. Count the Number of Computer Unlocking Permutations
Leetcode 3577. Count the Number of Computer Unlocking Permutations 1. 解题思路2. 代码实现 题目链接:3577. Count the Number of Computer Unlocking Permutations 1. 解题思路 这一题其实就是一个脑筋急转弯,要想要能够将所有的电脑解锁&#x…...
linux 错误码总结
1,错误码的概念与作用 在Linux系统中,错误码是系统调用或库函数在执行失败时返回的特定数值,用于指示具体的错误类型。这些错误码通过全局变量errno来存储和传递,errno由操作系统维护,保存最近一次发生的错误信息。值得注意的是,errno的值在每次系统调用或函数调用失败时…...
SpringBoot+uniapp 的 Champion 俱乐部微信小程序设计与实现,论文初版实现
摘要 本论文旨在设计并实现基于 SpringBoot 和 uniapp 的 Champion 俱乐部微信小程序,以满足俱乐部线上活动推广、会员管理、社交互动等需求。通过 SpringBoot 搭建后端服务,提供稳定高效的数据处理与业务逻辑支持;利用 uniapp 实现跨平台前…...
Python ROS2【机器人中间件框架】 简介
销量过万TEEIS德国护膝夏天用薄款 优惠券冠生园 百花蜂蜜428g 挤压瓶纯蜂蜜巨奇严选 鞋子除臭剂360ml 多芬身体磨砂膏280g健70%-75%酒精消毒棉片湿巾1418cm 80片/袋3袋大包清洁食品用消毒 优惠券AIMORNY52朵红玫瑰永生香皂花同城配送非鲜花七夕情人节生日礼物送女友 热卖妙洁棉…...
保姆级教程:在无网络无显卡的Windows电脑的vscode本地部署deepseek
文章目录 1 前言2 部署流程2.1 准备工作2.2 Ollama2.2.1 使用有网络的电脑下载Ollama2.2.2 安装Ollama(有网络的电脑)2.2.3 安装Ollama(无网络的电脑)2.2.4 安装验证2.2.5 修改大模型安装位置2.2.6 下载Deepseek模型 2.3 将deepse…...
云原生安全实战:API网关Kong的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关(API Gateway) API网关是微服务架构中的核心组件,负责统一管理所有API的流量入口。它像一座…...
HTML前端开发:JavaScript 获取元素方法详解
作为前端开发者,高效获取 DOM 元素是必备技能。以下是 JS 中核心的获取元素方法,分为两大系列: 一、getElementBy... 系列 传统方法,直接通过 DOM 接口访问,返回动态集合(元素变化会实时更新)。…...
前端工具库lodash与lodash-es区别详解
lodash 和 lodash-es 是同一工具库的两个不同版本,核心功能完全一致,主要区别在于模块化格式和优化方式,适合不同的开发环境。以下是详细对比: 1. 模块化格式 lodash 使用 CommonJS 模块格式(require/module.exports&a…...
Android屏幕刷新率与FPS(Frames Per Second) 120hz
Android屏幕刷新率与FPS(Frames Per Second) 120hz 屏幕刷新率是屏幕每秒钟刷新显示内容的次数,单位是赫兹(Hz)。 60Hz 屏幕:每秒刷新 60 次,每次刷新间隔约 16.67ms 90Hz 屏幕:每秒刷新 90 次,…...
