diff --git a/src/cpns/ClipItemList.vue b/src/cpns/ClipItemList.vue index 37fc496..383e55d 100644 --- a/src/cpns/ClipItemList.vue +++ b/src/cpns/ClipItemList.vue @@ -7,7 +7,11 @@ @click.left="handleItemClick($event, item)" @click.right="handleItemClick($event, item)" @mouseover="handleMouseOver(index)" - :class="{ active: index === activeIndex, select: selectItemList.indexOf(item) !== -1 }" + :class="{ + active: !isMultiple && index === activeIndex, + 'multi-active': isMultiple && index === activeIndex, + select: selectItemList.indexOf(item) !== -1 + }" >
@@ -70,6 +74,10 @@ const props = defineProps({ isMultiple: { type: Boolean, required: true + }, + currentActiveTab: { + type: String, + required: true } }) const emit = defineEmits(['onDataChange', 'onDataRemove', 'onSelectItemAdd']) @@ -81,6 +89,7 @@ const isOverSizedContent = (item) => { return JSON.parse(item.data).length >= 6 } } +const isShiftDown = ref(false) const selectItemList = ref([]) const emptySelectItemList = () => (selectItemList.value = []) defineExpose({ @@ -97,13 +106,59 @@ watch( ) const handleItemClick = (ev, item) => { if (props.isMultiple === true) { - const index = selectItemList.value.indexOf(item) - console.log(index) - if (index !== -1) { - selectItemList.value.splice(index, 1) // 已经存在 点击移除 + const i = selectItemList.value.indexOf(item) // 在已选中列表中的位置 + const index = props.showList.indexOf(item) // 在全部列表中的位置 + if (selectItemList.value.length !== 0 && isShiftDown.value) { + // 列表不为空 且 Shift按下 多选 + // 找到selectList的最高位与最低位 + // 如果index大于最高位/小于最低位 则将二者之间的全部历史都选中 + // 区分不同标签 + console.log(props.currentActiveTab) + const tmpArray = selectItemList.value + .filter((item) => + props.currentActiveTab === 'all' ? true : item.type === props.currentActiveTab + ) + .sort((a, b) => selectItemList.value.indexOf(a) - selectItemList.value.indexOf(b)) + const h = props.showList.indexOf(tmpArray[0]) // 已选中的index最高位 实际上index是最小的 + const l = props.showList.indexOf(tmpArray[tmpArray.length - 1]) // 已选中的最低位 实际上index是最大的 + console.log(props.showList) + if (index < h) { + // 更高: index从0开始计算 + // selectItemList.value = [] + for (let i = index; i <= h; i++) { + selectItemList.value.push(props.showList[i]) + } + // 数组去重 + selectItemList.value = selectItemList.value.filter(function (item, index) { + return selectItemList.value.indexOf(item) === index + }) + } else if (index > l) { + // 更低 + // selectItemList.value = [] + for (let i = h; i <= index; i++) { + selectItemList.value.push(props.showList[i]) + } + // 数组去重 + selectItemList.value = selectItemList.value.filter(function (item, index) { + return selectItemList.value.indexOf(item) === index + }) + } else if (index <= l && index >= h) { + // 单选操作 与下面代码相同 + if (i !== -1) { + selectItemList.value.splice(i, 1) // 已经存在 点击移除 + } else { + selectItemList.value.push(item) // 添加到已选列表中 + } + } } else { - selectItemList.value.push(item) // 添加到已选列表中 + // Shift未按下 单选 + if (i !== -1) { + selectItemList.value.splice(i, 1) // 已经存在 点击移除 + } else { + selectItemList.value.push(item) // 添加到已选列表中 + } } + emit('onSelectItemAdd') } else { const { button } = ev @@ -165,6 +220,7 @@ onMounted(() => { const isEnter = key === 'Enter' const isCopy = (ctrlKey || metaKey) && (key === 'C' || key === 'c') const isNumber = parseInt(key) <= 9 && parseInt(key) >= 0 + const isShift = key === 'Shift' if (isArrowUp) { if (activeIndex.value > 0) { activeIndex.value-- @@ -196,6 +252,19 @@ onMounted(() => { } else if ((ctrlKey || metaKey || altKey) && isNumber) { window.copy(props.showList[parseInt(key) - 1]) window.paste() + } else if (isShift) { + if (props.isMultiple) { + isShiftDown.value = true + } + } + }) + document.addEventListener('keyup', (e) => { + const { key } = e + const isShift = key === 'Shift' + if (isShift) { + if (props.isMultiple) { + isShiftDown.value = false + } } }) }) diff --git a/src/style/cpns/clip-item-list.less b/src/style/cpns/clip-item-list.less index 6a27ee2..1475a38 100644 --- a/src/style/cpns/clip-item-list.less +++ b/src/style/cpns/clip-item-list.less @@ -1,5 +1,6 @@ .clip-item-list { background: @bg-color; + user-select: none; .clip-item { display: flex; justify-content: space-between; @@ -16,6 +17,12 @@ background-color: @text-bg-color-lighter; transition: all 0.15s; } + &.multi-active { + border-style: hidden hidden hidden solid; + border-width: 1px 0px 0px 6px; + border-color: @bg-color @bg-color @bg-color @primary-color; + transition: all 0.15s; + } &.select { background-color: @text-bg-color-lighter; } diff --git a/src/views/Main.vue b/src/views/Main.vue index 23bfdb8..7ba70bb 100644 --- a/src/views/Main.vue +++ b/src/views/Main.vue @@ -44,7 +44,7 @@ :showList="showList" :fullData="fullData" :isMultiple="isMultiple" - @onSelectItemAdd="handleSelectItemAdd" + :currentActiveTab="outSideActiveTab" @onDataChange="toggleFullData" @onDataRemove="handleDataRemove" > @@ -76,11 +76,6 @@ const handleSearchBtnClick = () => { const ClipItemListRef = ref(null) const selectCount = ref(0) - -const handleSelectItemAdd = () => { - // 每次添加选择的 item都将 count更新 - selectCount.value = ClipItemListRef.value.selectItemList.length -} const handleMultiCopyBtnClick = (isPaste) => { const itemList = ClipItemListRef.value.selectItemList // 如果包含了图片/文件 则转为文件合并 否则仅合并文本 @@ -194,12 +189,19 @@ const handleDataRemove = () => { updateShowList(ClipSwitchRef.value.activeTab) } +const outSideActiveTab = ref('all') + onMounted(() => { // 获取挂载的导航组件 Ref const activeTab = computed(() => ClipSwitchRef.value.activeTab) const toggleNav = ClipSwitchRef.value.toggleNav const tabs = ClipSwitchRef.value.tabs + watch(activeTab, (val) => (outSideActiveTab.value = val)) + + // 已选择的条数 + selectCount.value = computed(() => ClipItemListRef.value?.selectItemList?.length) + // 初始化数据 list.value = window.db.dataBase.data showList.value = list.value.slice(0, GAP) // 最初展示 10条 @@ -250,6 +252,7 @@ onMounted(() => { const isExit = key === 'Escape' const isArrow = key === 'ArrowDown' || key === 'ArrowUp' const isEnter = key === 'Enter' + const isShift = key === 'Shift' if (isTab) { const tabTypes = tabs.map((item) => item.type) const index = tabTypes.indexOf(activeTab.value) @@ -274,6 +277,9 @@ onMounted(() => { } else if (ctrlKey || metaKey || isArrow || isEnter) { // 仅有 Ctrl时 什么也不执行 (utools模拟执行粘贴时触发) e.preventDefault() + } else if (isShift) { + // Shift: 多选操作 + // e.preventDefault() } else { window.focus() // 其他键盘事件 直接聚焦搜索框 }