vue3-element-admin实现同一个菜单多标签
原框架代码: 赵志江/huzhushan-vue3-element-admin
目录
TagsBar实现
实现同一个菜单多标签
device/detail/:id,不同参数时页面缓存删不掉的问题
TagsBar实现
在src/layout/components/下新建目录Tagsbar,新建index.vue
<template><div class="tags-container" :class="{ hide: !isTagsbarShow }"><el-scrollbarref="scrollContainer":vertical="false"class="scroll-container"@wheel.prevent="onScroll"><router-linkv-for="(tag, i) in tagList":key="tag.fullPath":to="tag":ref="el => setItemRef(i, el)"customv-slot="{ navigate, isExactActive }"><divclass="tags-item":class="isExactActive? 'active' : ''"@click="navigate"@click.middle="closeTag(tag)"@contextmenu.prevent="openMenu(tag, $event)"><span class="title">{{ $t(tag.title) }}</span><el-iconv-if="!isAffix(tag)"class="el-icon-close"@click.prevent.stop="closeTag(tag)"><Close /></el-icon></div></router-link></el-scrollbar></div><ulv-show="visible":style="{ left: left + 'px', top: top + 'px' }"class="contextmenu"><!-- <li @click="refreshSelectedTag(selectedTag)">{{ $t('tags.refresh') }}</li> --><li v-if="!isAffix(selectedTag)" @click="closeTag(selectedTag)">{{ $t('tags.close') }}</li><li @click="closeOtherTags">{{ $t('tags.other') }}</li><li @click="closeLeftTags">{{ $t('tags.left') }}</li><li @click="closeRightTags">{{ $t('tags.right') }}</li><li @click="closeAllTags">{{ $t('tags.all') }}</li></ul>
</template><script>
import { defineComponent, computed, getCurrentInstance } from 'vue'
import { useTags } from './hooks/useTags'
import { useContextMenu } from './hooks/useContextMenu'
import { useLayoutsettings } from '@/pinia/modules/layoutSettings'export default defineComponent({name: 'Tagsbar',mounted() {},setup() {const instance = getCurrentInstance()instance.appContext.config.globalProperties.$tagsbar = thisconst defaultSettings = useLayoutsettings()const isTagsbarShow = computed(() => defaultSettings.tagsbar.isShow)const tags = useTags()const contextMenu = useContextMenu(tags.tagList)const onScroll = e => {tags.handleScroll(e)contextMenu.closeMenu.value()}return {isTagsbarShow,onScroll,...tags,...contextMenu}},
})
</script><style lang="scss" scoped>
.tags-container {height: 32px;width: 100%;background: #fff;border-bottom: 1px solid #e0e4ef;&.hide {display: none;}.scroll-container {white-space: nowrap;overflow: hidden;::v-deep(.el-scrollbar__bar) {bottom: 0px;}}.tags-item {display: inline-block;height: 32px;line-height: 32px;box-sizing: border-box;border-left: 1px solid #e6e6e6;border-right: 1px solid #e6e6e6;color: #5c5c5c;background: #fff;padding: 0 8px;font-size: 12px;margin-left: -1px;vertical-align: bottom;cursor: pointer;&:first-of-type {margin-left: 15px;}&:last-of-type {margin-right: 15px;}&.active {color: #303133;background: #f5f5f5;}.title {display: inline-block;vertical-align: top;max-width: 200px;overflow: hidden;white-space: nowrap;text-overflow: ellipsis;}.el-icon-close {color: #5c5c5c;margin-left: 8px;width: 16px;height: 16px;vertical-align: -2px;border-radius: 50%;text-align: center;transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);transform-origin: 100% 50%;&:before {transform: scale(0.8);display: inline-block;vertical-align: -2px;}&:hover {background-color: #333;color: #fff;}}}
}
.contextmenu {margin: 0;background: #fff;z-index: 3000;position: fixed;list-style-type: none;padding: 5px 0;border-radius: 4px;font-size: 12px;font-weight: 400;color: #333;box-shadow: 2px 2px 3px 0 rgba(0, 0, 0, 0.3);white-space: nowrap;li {margin: 0;padding: 8px 16px;cursor: pointer;&:hover {background: #eee;}}
}
</style>
新建hooks目录,新建useTags.js
import { storeToRefs } from 'pinia'
import { useTags as useTagsbar } from '@/pinia/modules/tags'
import { useScrollbar } from './useScrollbar'
import { watch, computed, ref, nextTick, onBeforeMount } from 'vue'
import { useRouter } from 'vue-router'export const isAffix = tag => {return !!tag.meta && !!tag.meta.affix
}export const useTags = () => {const tagStore = useTagsbar()const { tagList } = storeToRefs(tagStore)const { addTag, delTag, saveActivePosition, updateTagList } = tagStoreconst router = useRouter()const route = router.currentRouteconst routes = computed(() => router.getRoutes())const tagsItem = ref([])const setItemRef = (i, el) => {tagsItem.value[i] = el}const scrollbar = useScrollbar(tagsItem)watch(() => tagList.value.length,() => {tagsItem.value = []})const filterAffixTags = routes => {return routes.filter(route => isAffix(route))}const initTags = () => {const affixTags = filterAffixTags(routes.value)for (const tag of affixTags) {if (tag.name) {addTag(tag)}}// 不在路由中的所有标签,需要删除const noUseTags = tagList.value.filter(tag =>routes.value.every(route => route.name !== tag.name))noUseTags.forEach(tag => {delTag(tag)})}const addTagList = () => {const tag = route.valueif (!!tag.name && tag.matched[0].components.default.name === 'layout') {addTag(tag)}}const saveTagPosition = tag => {const index = tagList.value.findIndex(item => item.fullPath === tag.fullPath)saveActivePosition(Math.max(0, index))}const moveToCurrentTag = () => {nextTick(() => {for (const tag of tagsItem.value) {if (!!tag && tag.to.path === route.value.path) {scrollbar.moveToTarget(tag)if (tag.to.fullPath !== route.value.fullPath) {updateTagList(route.value)}break}}})}onBeforeMount(() => {initTags()addTagList()moveToCurrentTag()})watch(route, (newRoute, oldRoute) => {saveTagPosition(oldRoute) // 保存标签的位置addTagList()moveToCurrentTag()})return {tagList,setItemRef,isAffix,...scrollbar,}
}
useScrollbar.js
import { ref } from 'vue'export const useScrollbar = tagsItem => {const scrollContainer = ref(null)const scrollLeft = ref(0)const doScroll = val => {scrollLeft.value = valscrollContainer.value.setScrollLeft(scrollLeft.value)}const handleScroll = e => {const $wrap = scrollContainer.value.wrapRefif ($wrap.offsetWidth + scrollLeft.value > $wrap.children[0].scrollWidth) {doScroll($wrap.children[0].scrollWidth - $wrap.offsetWidth)return} else if (scrollLeft.value < 0) {doScroll(0)return}const eventDelta = e.wheelDelta || -e.deltaYdoScroll(scrollLeft.value - eventDelta / 4)}const moveToTarget = currentTag => {const $wrap = scrollContainer.value.wrapRefconst tagList = tagsItem.valuelet firstTag = nulllet lastTag = nullif (tagList.length > 0) {firstTag = tagList[0]lastTag = tagList[tagList.length - 1]}if (firstTag === currentTag) {doScroll(0)} else if (lastTag === currentTag) {doScroll($wrap.children[0].scrollWidth - $wrap.offsetWidth)} else {const el = currentTag.$el.nextElementSiblingel.offsetLeft + el.offsetWidth > $wrap.offsetWidth? doScroll(el.offsetLeft - el.offsetWidth): doScroll(0)}}return {scrollContainer,handleScroll,moveToTarget,}
}
useContextMenu.js
import { useTags } from '@/pinia/modules/tags'
import { onMounted, onBeforeUnmount, reactive, toRefs, nextTick } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { isAffix } from './useTags'export const useContextMenu = tagList => {const router = useRouter()const route = useRoute()const tagsStore = useTags()const state = reactive({visible: false,top: 0,left: 0,selectedTag: {},openMenu(tag, e) {state.visible = truestate.left = e.clientXstate.top = e.clientYstate.selectedTag = tag},closeMenu() {state.visible = false},refreshSelectedTag(tag) {tagsStore.deCacheList(tag)const { fullPath } = tagnextTick(() => {router.replace({path: '/redirect' + fullPath,})})},closeTag(tag) {if (isAffix(tag)) returnconst closedTagIndex = tagList.value.findIndex(item => {return item.path === tag.path})console.log(closedTagIndex)tagsStore.delTag(tag)if (isActive(tag)) {toLastTag(closedTagIndex - 1)}},closeOtherTags() {tagsStore.delOtherTags(state.selectedTag)router.push(state.selectedTag)},closeLeftTags() {state.closeSomeTags('left')},closeRightTags() {state.closeSomeTags('right')},closeSomeTags(direction) {const index = tagList.value.findIndex(item => item.fullPath === state.selectedTag.fullPath)if ((direction === 'left' && index <= 0) ||(direction === 'right' && index >= tagList.value.length - 1)) {return}const needToClose =direction === 'left'? tagList.value.slice(0, index): tagList.value.slice(index + 1)tagsStore.delSomeTags(needToClose)router.push(state.selectedTag)},closeAllTags() {tagsStore.delAllTags()router.push('/')},})const isActive = tag => {return tag.fullPath === route.fullPath}const toLastTag = lastTagIndex => {const lastTag = tagList.value[lastTagIndex]if (lastTag) {router.push(lastTag.fullPath)} else {router.push('/')}}onMounted(() => {document.addEventListener('click', state.closeMenu)})onBeforeUnmount(() => {document.removeEventListener('click', state.closeMenu)})return toRefs(state)
}
在src/pinia/modules下新建tags.js
import { defineStore } from 'pinia'
import { getItem, setItem, removeItem } from '@/utils/storage' //getItem和setItem是封装的操作localStorage的方法
const TAGLIST = 'VEA-TAGLIST'export const useTags = defineStore('tags', {state: () => ({tagList: getItem(TAGLIST) || [],cacheList: [],activePosition: -1,}),actions: {saveActivePosition(index) {this.activePosition = index},addTag({ path, fullPath, name, meta, params, query }) {if (this.tagList.some(v => v.path === path)) return false// 添加tagListconst target = Object.assign({},{ path, fullPath, name, meta, params, query },{title: meta.title || '未命名',fullPath: fullPath || path,})if (this.activePosition === -1) {if (name === 'home') {this.tagList.unshift(target)} else {this.tagList.push(target)}} else {this.tagList.splice(this.activePosition + 1, 0, target)}// 保存到localStoragesetItem(TAGLIST, this.tagList)// 添加cacheListif (this.cacheList.includes(name)) returnif (!meta.noCache) {this.cacheList.push(name)}},deTagList(tag) {// 删除tagListthis.tagList = this.tagList.filter(v => v.path !== tag.path)// 保存到localStoragesetItem(TAGLIST, this.tagList)},deCacheList(tag) {// 删除cacheListthis.cacheList = this.cacheList.filter(v => v !== tag.name)},delTag(tag) {// 删除tagListthis.deTagList(tag)// 删除cacheListthis.deCacheList(tag)},delOtherTags(tag) {this.tagList = this.tagList.filter(v => !!v.meta.affix || v.path === tag.path)// 保存到localStoragesetItem(TAGLIST, this.tagList)this.cacheList = this.cacheList.filter(v => v === tag.name)},delSomeTags(tags) {this.tagList = this.tagList.filter(v => !!v.meta.affix || tags.every(tag => tag.path !== v.path))// 保存到localStoragesetItem(TAGLIST, this.tagList)this.cacheList = this.cacheList.filter(v =>tags.every(tag => tag.name !== v))},delAllTags() {this.tagList = this.tagList.filter(v => !!v.meta.affix)// 保存到localStorageremoveItem(TAGLIST)this.cacheList = []},updateTagList(tag) {const index = this.tagList.findIndex(v => v.path === tag.path)if (index > -1) {this.tagList[index] = Object.assign({}, this.tagList[index], tag)// 保存到localStoragesetItem(TAGLIST, this.tagList)}},clearAllTags() {this.cacheList = []this.tagList = []// 保存到localStorageremoveItem(TAGLIST)},},
})
src/layout/components/Content下新建index.vue,keep-alive组件会根据Component的name来跟include进行匹配,来缓存页面,同样的页面重新进入时不会触发onMounted,只会触发onActivated。
<template><router-view v-slot="{ Component }"><keep-alive :include="cacheList.join(',')"><component :is="Component" :key="key" /></keep-alive></router-view>
</template>
<script>
import { storeToRefs } from 'pinia'
import { computed, defineComponent } from 'vue'
import { useRoute } from 'vue-router'
import { useTags } from '@/pinia/modules/tags'export default defineComponent({setup() {const route = useRoute()const { cacheList } = storeToRefs(useTags())const key = computed(() => route.fullPath)return {cacheList,key,}},
})
</script>
实现同一个菜单多标签
框架通过vue-router来实现页面跳转和菜单展示,下面介绍对一个菜单,如果实现参数不同,显示多个tag。
按如下定义menu
{path: 'detail/:id',name: 'device_detail',component: () => import('@/views/device/detail.vue'),meta: { title: '设备详情', icon: 'el-icon-s-platform' },hidden: true,}
device/detail.vue中动态修改Component的name:
onMounted(() => {ctx.deviceId = parseInt(ctx.$route.params.id)ctx.$options.name = 'device_detail' + ctx.deviceId
})
onActivated(() => {ctx.$options.name = 'device_detail' + ctx.deviceId
})
修改src/pinia/modules/tags.js,修改地方:tag.name 改为 this.getFinalName(tag),即根据参数不同name也不同,name放入cacheList,用于唯一标识一个Component。
import { defineStore } from 'pinia'
import { getItem, setItem, removeItem } from '@/utils/storage' //getItem和setItem是封装的操作localStorage的方法
const TAGLIST = 'VEA-TAGLIST'export const useTags = defineStore('tags', {state: () => ({tagList: getItem(TAGLIST) || [],cacheList: [],activePosition: -1,}),actions: {saveActivePosition(index) {this.activePosition = index},addTag({ path, fullPath, name, meta, params, query }) {if (this.tagList.some(v => v.path === path)) return falsevar title = meta.titleif (name == 'device_detail') {title = title + ' ' + query.name}// 添加tagListconst target = Object.assign({},{ path, fullPath, name, meta, params, query },{title: title || '未命名',fullPath: fullPath || path,})if (this.activePosition === -1) {if (name === 'home') {this.tagList.unshift(target)} else {this.tagList.push(target)}} else {this.tagList.splice(this.activePosition + 1, 0, target)}// 保存到localStoragesetItem(TAGLIST, this.tagList)// 添加cacheListconst finalName = this.getFinalName(target)if (this.cacheList.includes(finalName)) returnif (!meta.noCache) {this.cacheList.push(finalName)}},getFinalName(tag) {if (tag.name == 'device_detail') {return tag.name + tag.params.id}return tag.name},deTagList(tag) {// 删除tagListthis.tagList = this.tagList.filter(v => v.path !== tag.path)// 保存到localStoragesetItem(TAGLIST, this.tagList)},deCacheList(tag) {const name = this.getFinalName(tag)// 删除cacheListthis.cacheList = this.cacheList.filter(v => v !== name)},delTag(tag) {// 删除tagListthis.deTagList(tag)// 删除cacheListthis.deCacheList(tag)},delOtherTags(tag) {this.tagList = this.tagList.filter(v => !!v.meta.affix || v.path === tag.path)// 保存到localStoragesetItem(TAGLIST, this.tagList)const name = this.getFinalName(tag)this.cacheList = this.cacheList.filter(v => v === name)},delSomeTags(tags) {this.tagList = this.tagList.filter(v => !!v.meta.affix || tags.every(tag => tag.path !== v.path))// 保存到localStoragesetItem(TAGLIST, this.tagList)this.cacheList = this.cacheList.filter(v =>tags.every(tag => tag.name !== v))},delAllTags() {this.tagList = this.tagList.filter(v => !!v.meta.affix)// 保存到localStorageremoveItem(TAGLIST)this.cacheList = []},updateTagList(tag) {const index = this.tagList.findIndex(v => v.path === tag.path)if (index > -1) {this.tagList[index] = Object.assign({}, this.tagList[index], tag)// 保存到localStoragesetItem(TAGLIST, this.tagList)}},clearAllTags() {this.cacheList = []this.tagList = []// 保存到localStorageremoveItem(TAGLIST)},},
})
device/detail/:id,不同参数时页面缓存删不掉的问题
现象如下:进入/device/detail/1,再打开/device/detail/2,点击其他标签,删掉/device/detail/2标签,再打开/device/detail/2,此时发现只触发了onActivated方法,没有触发onMounted方法,页面没有重新渲染,keepalive这里的缓存机制不清楚,但是可以知道框架误以为/device/detail/2还在缓存中,直接把缓存中的页面拿过来显示了。
解决方法
对于这种动态菜单的情况,Compnent的key属性增加自增的标识,每次打开标识加1。
修改src/pinia/modules/tags.js,增加detailIndex,在addTag时增加detailIndex的修改
import { defineStore } from 'pinia'
import { getItem, setItem, removeItem } from '@/utils/storage' //getItem和setItem是封装的操作localStorage的方法
const TAGLIST = 'VEA-TAGLIST'export const useTags = defineStore('tags', {state: () => ({tagList: getItem(TAGLIST) || [],cacheList: [],activePosition: -1,detailIndex: {}}),actions: {saveActivePosition(index) {this.activePosition = index},addTag({ path, fullPath, name, meta, params, query }) {if (this.tagList.some(v => v.path === path)) return falsevar title = meta.titleif (name == 'device_detail') {title = title + ' ' + query.name}// 添加tagListconst target = Object.assign({},{ path, fullPath, name, meta, params, query },{title: title || '未命名',fullPath: fullPath || path,})if (this.activePosition === -1) {if (name === 'home') {this.tagList.unshift(target)} else {this.tagList.push(target)}} else {this.tagList.splice(this.activePosition + 1, 0, target)}// 保存到localStoragesetItem(TAGLIST, this.tagList)// 添加cacheListconst finalName = this.getFinalName(target)if (this.cacheList.includes(finalName)) returnif (!meta.noCache) {if (finalName.startsWith('device_detail')) {if (!this.detailIndex[target.path]) {this.detailIndex[target.path] = 1} else {this.detailIndex[target.path]++}} else {this.detailIndex[target.path] = ''}this.cacheList.push(finalName)}},
修改src/layout/components/Content/index.vue中的key未route.path + detailIndex.value[route.path]
<template><router-view v-slot="{ Component }"><keep-alive :include="cacheList.join(',')"><component :is="Component" :key="key" /></keep-alive></router-view>
</template>
<script>
import { storeToRefs } from 'pinia'
import { computed, defineComponent } from 'vue'
import { useRoute } from 'vue-router'
import { useTags } from '@/pinia/modules/tags'export default defineComponent({setup() {const route = useRoute()const { cacheList, detailIndex } = storeToRefs(useTags())const key = computed(() => route.path + detailIndex[route.path])return {cacheList,key,}},
})
</script>
相关文章:

vue3-element-admin实现同一个菜单多标签
原框架代码: 赵志江/huzhushan-vue3-element-admin 目录 TagsBar实现 实现同一个菜单多标签 device/detail/:id,不同参数时页面缓存删不掉的问题 TagsBar实现 在src/layout/components/下新建目录Tagsbar,新建index.vue <template><div c…...

第三十六节 Java 网络编程
网络编程是指编写运行在多个设备(计算机)的程序,这些设备都通过网络连接起来。 java.net包中J2SE的API包含有类和接口,它们提供低层次的通信细节。你可以直接使用这些类和接口,来专注于解决问题,而不用关注…...

DRF的认证、权限、限流、序列化、反序列化
DRF的认证、权限、限流、序列化、反序列化 一、认证1、直接用,用户授权2、认证组件源码 二、权限1. 直接使用,用户权限2.权限组件源码 三、序列化1. 序列化1.1 自定义Serailizer类序列化1.2 在视图APIView中使用1.3 自定义ModelSerializer类序列化1.4 不…...

解决:Cannot read properties of undefined (reading ‘validate‘)问题
问题:Element UI使用表单校验功能控制台出现Cannot read properties of undefined (reading validate)报错 解决:在 <el-form :model"form" :rules"rules">添加 ref"form",form为自定义的表单名称 <…...

关于IP地址发展历程的详细探讨
IP地址的发展历程是一段不断演进、适应网络技术发展的历史。自互联网诞生以来,IP地址作为网络设备的唯一标识,扮演了至关重要的角色。以下是对IP地址发展历程的详细探讨。 在互联网的初期,主机数量相对较少,IP地址主要用于区分不…...

【LeetCode热题100】【二叉树】将有序数组转换为二叉搜索树
题目链接:108. 将有序数组转换为二叉搜索树 - 力扣(LeetCode) 取中间的数作为根节点,左边的数递归转换,右边的数递归转换 class Solution { public:TreeNode *sortedArrayToBST(vector<int> &nums) {retur…...

文心一言和GPT-4全面比较
自大型语言模型出现以来,人工智能在自然语言处理方面取得了显著进步。文心一言和GPT-4是当前最先进的两款语言模型,在业内广受关注。两者都具有强大的能力,但各有特点和优势。本文将从多个方面对这两个模型进行全面比较,以帮助读者…...
Mac的终端配置
Mac的终端配置 参考教程包管理工具 - Homebrew出现的问题用虚拟环境解决方案:直接将解释器的路径放过去错误方法:用find查找到虚拟环境安装的路径,其链接的是brew安装的python路径 编辑器没有报错,但是运行过程中仍然找不到pandas…...

制作一个RISC-V的操作系统十-Trap和Exception(流 mtvec mepc mcause mtval mstatus trap完整流程)
文章目录 流mtvecmepcmcausemtvalmstatustrap 初始化trap的top half(硬件完成)trap的bottom half(软件完成)从trap返回代码实现 流 控制流:程序控制的执行流 trap分为中断和异常 mtvec base:存储trap入…...

【爬虫开发】爬虫从0到1全知识md笔记第4篇:Selenium课程概要,selenium的介绍【附代码文档】
爬虫开发从0到1全知识教程完整教程(附代码资料)主要内容讲述:爬虫课程概要,爬虫基础爬虫概述,,http协议复习。requests模块,requests模块1. requests模块介绍,2. response响应对象,3. requests模块发送请求,4. request…...

对一个时间序列中的每个元素按照指定精度向上取整
【小白从小学Python、C、Java】 【计算机等考500强证书考研】 【Python-数据分析】 对一个时间序列中的每个元素 按照指定精度向上取整 例如:对小时处理, 则9:01处理为10:00 Series.dt.ceil() 选择题 以下代码的输出结果中正确的是? import pandas as…...

51单片机+TN901非接触式红外测温设计论文与源码PCB等资料
1、摘要 温度测量技术应用十分广泛,而且在现代设备故障检测领域中也是一项非常重要的技术。但在某些应用领域中,要求测量温度用的传感器不能与被测物体相接触,这就需要一种非接触的测温方式来满足上述测温需求。本论文正是应上述实际需求而设…...

AI创业项目:AI旅游规划定制师
在当前的旅游市场中,个性化旅游规划成为越来越多旅行者的需求。然而,现行的定制旅行服务主要依赖于人工定制师,这一模式面临着信息不透明、价格弹性大等挑战。定制师在客户与服务供应商之间掌握着信息差,依靠这一优势获得收益&…...

win 安装 Stable Diffusion
注:本人使用的是 RTX2060 - 6G版 特别提醒:安装一定要 CUDA 和 PyTorch 版本能配套用,不然会有生成保存问题(我是这样的),装完用 python -m xformers.info 这个看对应的版本 建议:有些命令安装在venv 虚拟机中做&…...

STM32F407+FreeRTOS+LWIP UDP组播
开发环境介绍: MCU:STM32F407ZET6 网卡:LAN8720A LWIP版本:V1.1.0 FreeRTOS 版本:V10.2.1 LAN8720A硬件原理图: 硬件连接说明: MII_RX_CLK/RMII_REF_CLK ------>PA1 …...

(源码+部署+讲解)基于Spring Boot + Vue的车位租赁系统设计与实现
前言 💗博主介绍:✌专注于Java、小程序技术领域和毕业项目实战✌💗 👇🏻 精彩专栏 推荐订阅👇🏻 2024年Java精品实战案例《100套》 🍅文末获取源码联系🍅 🌟…...

Lecture 2~4 About Filter
文章目录 空间域上的滤波器- 线性滤波器盒状滤波器Box Filter锐化Sharpening相关运算 vs. 卷积运算 Correlation vs. Convolution - 非线性滤波器高斯滤波器Gaussian filter - 实际问题- 纹理texture 频域上的滤波器 滤波的应用- 模板匹配- 图像金字塔 空间域上的滤波器 图像…...

【LINUX】Linux 命令大全:系统管理与网络操作指南
开始之前 Linux命令行,也称为终端,是Linux最强大的特性之一。通过命令行,用户可以执行几乎所有的任务,比如文件操作、程序安装、系统监控和网络配置等。了解这些基本命令,将帮助你更好地掌握Linux系统。 文件和目录操…...

Day50 动态规划 part11
Day50 动态规划 part11 123.买卖股票的最佳时机III 我的思路: 这道题考虑了交易次数 j(最大次数为2),以及某天 i 应该买or卖股票(两种状态) 用三维数组表示 dp[i][j][0] – 第i天结束时,交易j…...

Docker 搭建私有镜像仓库
一、镜像仓库简介 Docker的镜像仓库是一个用于存储和管理Docker镜像的中央位置。镜像仓库的主要作用是提供一个集中的地方,让用户可以上传、下载、删除和共享Docker镜像。镜像仓库又可以分为公共镜像仓库和私有仓库镜像仓库: 公共镜像仓库 Docker Hub 是…...

Nginx反向代理与Tomcat实现ssm项目前后端分离部署
Nginx nginx是一款http和支持反向代理的web服务器,以其优越的性能被广泛使用。以下是百度百科的介绍。 Nginx (engine x) 是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务。Nginx是由伊戈尔赛索耶夫为俄罗斯访问量第二的Rambler.…...

element UI 日期选择器 当前年份之前不可选
<el-date-pickertype"year"format"YYYY"value-format"YYYY"v-model"declareYear"placeholder"请选择年份":disabled-date"disabledDateFun"/>function disabledDateFun(time) {if (time.getFullYear() <…...

windows wireshark抓包rtmp推流出现TCP Retransmission
解决办法:tcp.port1935 && !(tcp.analysis.retransmission)...

C++之std::initializer_list详解
相关文章系列: C/C中{}的用法总结(全)_c {}-CSDN博客 目录 1.引言 2.容器的初始化 3.函数中使用std::initializer_list 4.自定义类型中使用std::initializer_list 5.迭代std::initializer_list 6. 在模板中使用std::initializer_list 7.std::initializer_lis…...

4月9日学习记录
[GXYCTF 2019]禁止套娃 涉及知识点:git泄露,无参数RCE 打开环境,源码什么的都没有,扫描后台看看 扫描发现存在git泄露 用githack下载查看得到一串源码 <?php include "flag.php"; echo "flag在哪里呢&#…...

解析快手滑块验证码的逆向工程
快手滑块验证码是一种常见的反机器人验证方式,通过模拟用户拖动滑块来验证用户身份。本文将介绍如何逆向工程快手滑块验证码的加密算法和轨迹生成方式,并提供详细的代码实现。 1. 加密算法解析 首先,我们需要了解滑块验证码生成时所用的加密…...

mysql运维知识总结
1. 日志 1.1 错误日志 错误日志是 MySQL 中最重要的日志之一,它记录了当 mysqld 启动和停止时,以及服务器在运行过 程中发生任何严重错误时的相关信息。当数据库出现任何故障导致无法正常使用时,建议首先查看此日志。 该日志是默认开启的&…...

【目标检测】-入门知识
1、回归与分类问题 回归问题是指给定输入变量(特征)和一个连续的输出变量(标签),建立一个函数来预测输出变量的值。换句话说,回归问题的目标是预测一个连续的输出值,例如预测房价、股票价格、销售额等。回归问题通常使用回归分析技术,例如线性回归、多项式回归、决策树…...

翻译笔实现文字识别功能的原理
翻译笔作为一种便携式设备,近年来在语言学习、旅游、商务交流等领域中逐渐受到人们的青睐。其核心功能之一便是文字识别,即将纸质或电子文档中的文字快速、准确地转化为机器可读的文本格式。那么,翻译笔是如何实现这一神奇功能的呢࿱…...

文件批量重命名,繁体中文秒变简体中文,轻松实现高效翻译
在数字化时代,我们的工作、学习和生活都离不开电脑文件。随着时间的推移,文件数量不断增加,管理起来变得越来越困难。你是否曾经为如何高效、有序地管理文件而烦恼?现在,有一款强大的文件批量重命名工具,它…...