mirror of
https://github.com/ZiuChen/ClipboardManager.git
synced 2025-06-07 22:04:06 +08:00
commit
b69829d80a
@ -106,6 +106,16 @@ class DB {
|
|||||||
})
|
})
|
||||||
this.updateDataBaseLocal()
|
this.updateDataBaseLocal()
|
||||||
}
|
}
|
||||||
|
removeItemViaId(id) {
|
||||||
|
for (const item of this.dataBase.data) {
|
||||||
|
if (item.id === id) {
|
||||||
|
this.dataBase.data.splice(this.dataBase.data.indexOf(item), 1)
|
||||||
|
this.updateDataBaseLocal()
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const pbpaste = async () => {
|
const pbpaste = async () => {
|
||||||
@ -171,12 +181,15 @@ const paste = () => {
|
|||||||
else utools.simulateKeyboardTap('v', 'ctrl')
|
else utools.simulateKeyboardTap('v', 'ctrl')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const db = new DB(DBPath)
|
||||||
|
db.init()
|
||||||
|
|
||||||
|
const remove = (item) => db.removeItemViaId(item.id)
|
||||||
|
|
||||||
const focus = () => document.querySelector('.clip-search input')?.focus()
|
const focus = () => document.querySelector('.clip-search input')?.focus()
|
||||||
const toTop = () => (document.scrollingElement.scrollTop = 0)
|
const toTop = () => (document.scrollingElement.scrollTop = 0)
|
||||||
const resetNav = () => document.querySelectorAll('.clip-switch-item')[0]?.click()
|
const resetNav = () => document.querySelectorAll('.clip-switch-item')[0]?.click()
|
||||||
|
|
||||||
const db = new DB(DBPath)
|
|
||||||
db.init()
|
|
||||||
watchClipboard(db, (item) => {
|
watchClipboard(db, (item) => {
|
||||||
// 此函数不断执行
|
// 此函数不断执行
|
||||||
if (!item) return
|
if (!item) return
|
||||||
@ -204,6 +217,7 @@ utools.onPluginEnter(() => {
|
|||||||
window.db = db
|
window.db = db
|
||||||
window.copy = copy
|
window.copy = copy
|
||||||
window.paste = paste
|
window.paste = paste
|
||||||
|
window.remove = remove
|
||||||
window.openFile = utools.shellOpenPath
|
window.openFile = utools.shellOpenPath
|
||||||
window.getIcon = utools.getFileIcon
|
window.getIcon = utools.getFileIcon
|
||||||
window.focus = focus
|
window.focus = focus
|
||||||
|
@ -47,7 +47,21 @@
|
|||||||
</template>
|
</template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="clip-count">{{ index + 1 }}</div>
|
<div class="clip-operate" v-show="activeIndex === index">
|
||||||
|
<template v-for="{ id, title } of operation">
|
||||||
|
<div
|
||||||
|
v-if="id !== 'collect' || (id === 'collect' && item.collect !== true)"
|
||||||
|
:class="id"
|
||||||
|
:title="title"
|
||||||
|
@click.stop="handleOperateClick({ id, item })"
|
||||||
|
>
|
||||||
|
{{ title.slice(0, 1) }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
<div class="clip-count" v-show="activeIndex !== index">
|
||||||
|
{{ index + 1 }}
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -66,7 +80,7 @@ const props = defineProps({
|
|||||||
required: true
|
required: true
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const emit = defineEmits(['onDataChange'])
|
const emit = defineEmits(['onDataChange', 'onDataRemove'])
|
||||||
const handleItemClick = (ev, item) => {
|
const handleItemClick = (ev, item) => {
|
||||||
const { button } = ev
|
const { button } = ev
|
||||||
if (button === 0) {
|
if (button === 0) {
|
||||||
@ -81,6 +95,26 @@ const handleItemClick = (ev, item) => {
|
|||||||
const handleDataClick = (item) => emit('onDataChange', item)
|
const handleDataClick = (item) => emit('onDataChange', item)
|
||||||
const activeIndex = ref(0)
|
const activeIndex = ref(0)
|
||||||
const handleMouseOver = (index) => (activeIndex.value = index)
|
const handleMouseOver = (index) => (activeIndex.value = index)
|
||||||
|
const operation = [
|
||||||
|
{ id: 'copy', title: '复制' },
|
||||||
|
{ id: 'collect', title: '收藏' },
|
||||||
|
{ id: 'remove', title: '删除' }
|
||||||
|
]
|
||||||
|
const handleOperateClick = ({ id, item }) => {
|
||||||
|
switch (id) {
|
||||||
|
case 'copy':
|
||||||
|
window.copy(item)
|
||||||
|
break
|
||||||
|
case 'collect':
|
||||||
|
item.collect = true // important
|
||||||
|
window.db.updateDataBaseLocal(db)
|
||||||
|
break
|
||||||
|
case 'remove':
|
||||||
|
window.remove(item)
|
||||||
|
emit('onDataRemove')
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
// 父组件中改变了引用类型的地址 故要用 getter返回
|
// 父组件中改变了引用类型的地址 故要用 getter返回
|
||||||
watch(
|
watch(
|
||||||
() => props.showList,
|
() => props.showList,
|
||||||
|
@ -21,7 +21,8 @@ const tabs = ref([
|
|||||||
{ name: '📚 全部', type: 'all' },
|
{ name: '📚 全部', type: 'all' },
|
||||||
{ name: '📋 文字', type: 'text' },
|
{ name: '📋 文字', type: 'text' },
|
||||||
{ name: '⛺ 图片', type: 'image' },
|
{ name: '⛺ 图片', type: 'image' },
|
||||||
{ name: '📂 文件', type: 'file' }
|
{ name: '📂 文件', type: 'file' },
|
||||||
|
{ name: '⭐ 收藏', type: 'collect' }
|
||||||
])
|
])
|
||||||
const activeTab = ref('all')
|
const activeTab = ref('all')
|
||||||
const emit = defineEmits(['onNavClick'])
|
const emit = defineEmits(['onNavClick'])
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
position: fixed;
|
position: fixed;
|
||||||
top: 0;
|
top: 0;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 60%;
|
width: 70%;
|
||||||
color: @text-color;
|
color: @text-color;
|
||||||
background: @bg-color;
|
background: @bg-color;
|
||||||
padding: 0px 20px 0px 20px;
|
padding: 0px 20px 0px 20px;
|
||||||
|
@ -40,6 +40,11 @@
|
|||||||
padding: 5px 7px 5px 7px;
|
padding: 5px 7px 5px 7px;
|
||||||
&.clip-data-status {
|
&.clip-data-status {
|
||||||
color: @primary-color;
|
color: @primary-color;
|
||||||
|
&:hover {
|
||||||
|
color: @bg-color;
|
||||||
|
background-color: @primary-color;
|
||||||
|
transition: all 0.15s;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -70,5 +75,29 @@
|
|||||||
color: @text-color-lighter;
|
color: @text-color-lighter;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
|
.clip-operate {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
min-width: 100px;
|
||||||
|
padding: 10px;
|
||||||
|
& * {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
font-size: 13px;
|
||||||
|
color: @primary-color;
|
||||||
|
background: @text-bg-color;
|
||||||
|
margin: 0px 2px;
|
||||||
|
border-radius: 5px;
|
||||||
|
width: 30px;
|
||||||
|
height: 30px;
|
||||||
|
&:hover {
|
||||||
|
color: @bg-color;
|
||||||
|
background: @primary-color;
|
||||||
|
transition: all 0.15s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
.clip-search {
|
.clip-search {
|
||||||
width: 40%;
|
min-width: 300px;
|
||||||
margin-right: 30px;
|
|
||||||
input {
|
input {
|
||||||
width: 100%;
|
width: 90%;
|
||||||
/* normalize */
|
/* normalize */
|
||||||
background: none;
|
background: none;
|
||||||
outline: none;
|
outline: none;
|
||||||
@ -20,7 +19,7 @@
|
|||||||
}
|
}
|
||||||
.clip-search-suffix {
|
.clip-search-suffix {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
position: absolute;
|
position: fixed;
|
||||||
right: 20px;
|
right: 20px;
|
||||||
top: 18px;
|
top: 18px;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
@ -28,7 +27,7 @@
|
|||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
background-color: @nav-bg-color;
|
background-color: @nav-bg-color;
|
||||||
border-radius: 20px;
|
border-radius: 5px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: @nav-hover-bg-color;
|
background-color: @nav-hover-bg-color;
|
||||||
|
@ -19,9 +19,10 @@
|
|||||||
justify-content: left;
|
justify-content: left;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
margin-left: 5px;
|
||||||
.clip-switch-item {
|
.clip-switch-item {
|
||||||
padding: 10px 15px 10px 15px;
|
padding: 10px 15px 10px 15px;
|
||||||
margin: 10px 5px 10px 10px;
|
margin: 10px 5px 10px 5px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
|
@ -13,7 +13,12 @@
|
|||||||
</ClipSwitch>
|
</ClipSwitch>
|
||||||
<div class="clip-break"></div>
|
<div class="clip-break"></div>
|
||||||
<div class="clip-empty-status" v-if="showList.length === 0">📪 无记录</div>
|
<div class="clip-empty-status" v-if="showList.length === 0">📪 无记录</div>
|
||||||
<ClipItemList :showList="showList" :fullData="fullData" @onDataChange="toggleFullData">
|
<ClipItemList
|
||||||
|
:showList="showList"
|
||||||
|
:fullData="fullData"
|
||||||
|
@onDataChange="toggleFullData"
|
||||||
|
@onDataRemove="handleDataRemove"
|
||||||
|
>
|
||||||
</ClipItemList>
|
</ClipItemList>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@ -34,7 +39,9 @@ const showList = ref([]) // 展示的数据
|
|||||||
const updateShowList = (type) => {
|
const updateShowList = (type) => {
|
||||||
// 更新显示列表
|
// 更新显示列表
|
||||||
showList.value = list.value
|
showList.value = list.value
|
||||||
.filter((item) => (type === 'all' ? item : item.type === type)) // 是 all则返回所有 否则按照 type返回
|
.filter((item) =>
|
||||||
|
type === 'collect' ? item.collect === true : type === 'all' ? item : item.type === type
|
||||||
|
) // 是 collect则返回所有收藏 否则按照 type返回
|
||||||
.filter((item) => (filterText.value ? item.type !== 'image' : item)) // 有过滤词 排除掉图片 DataURL
|
.filter((item) => (filterText.value ? item.type !== 'image' : item)) // 有过滤词 排除掉图片 DataURL
|
||||||
.filter(
|
.filter(
|
||||||
(item) =>
|
(item) =>
|
||||||
@ -67,6 +74,14 @@ const toggleFullData = (item) => {
|
|||||||
fullDataShow.value = !fullDataShow.value
|
fullDataShow.value = !fullDataShow.value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const ClipSwitchRef = ref()
|
||||||
|
|
||||||
|
const handleDataRemove = () => {
|
||||||
|
// 此函数须在挂载后执行
|
||||||
|
list.value = window.db.dataBase.data
|
||||||
|
updateShowList(ClipSwitchRef.value.activeTab)
|
||||||
|
}
|
||||||
|
|
||||||
const restoreDataBase = () => {
|
const restoreDataBase = () => {
|
||||||
// 情况数据库
|
// 情况数据库
|
||||||
const flag = window.confirm('确定要清空剪贴板记录吗?')
|
const flag = window.confirm('确定要清空剪贴板记录吗?')
|
||||||
@ -76,11 +91,11 @@ const restoreDataBase = () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const ClipSwitchRef = ref()
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
// 获取挂载的导航组件 Ref
|
// 获取挂载的导航组件 Ref
|
||||||
const activeTab = computed(() => ClipSwitchRef.value.activeTab)
|
const activeTab = computed(() => ClipSwitchRef.value.activeTab)
|
||||||
const toggleNav = ClipSwitchRef.value.toggleNav
|
const toggleNav = ClipSwitchRef.value.toggleNav
|
||||||
|
const tabs = ClipSwitchRef.value.tabs
|
||||||
|
|
||||||
// 初始化数据
|
// 初始化数据
|
||||||
list.value = window.db.dataBase.data
|
list.value = window.db.dataBase.data
|
||||||
@ -129,9 +144,9 @@ onMounted(() => {
|
|||||||
(ctrlKey && (key === 'F' || key === 'f')) || (ctrlKey && (key === 'L' || key === 'l'))
|
(ctrlKey && (key === 'F' || key === 'f')) || (ctrlKey && (key === 'L' || key === 'l'))
|
||||||
const isExit = key === 'Escape'
|
const isExit = key === 'Escape'
|
||||||
if (isTab) {
|
if (isTab) {
|
||||||
const list = ['all', 'text', 'image', 'file']
|
const tabTypes = tabs.map((item) => item.type)
|
||||||
const index = list.indexOf(activeTab.value)
|
const index = tabTypes.indexOf(activeTab.value)
|
||||||
const target = index === list.length - 1 ? list[0] : list[index + 1]
|
const target = index === tabTypes.length - 1 ? tabTypes[0] : tabTypes[index + 1]
|
||||||
toggleNav(target)
|
toggleNav(target)
|
||||||
updateShowList(activeTab.value)
|
updateShowList(activeTab.value)
|
||||||
} else if (isSearch) {
|
} else if (isSearch) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user