DawnLauncher/src/pages/classification/components/Content.vue
2024-07-05 22:27:34 +08:00

1427 lines
45 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- 分类 -->
<div
id="classification-content"
class="pl-[8px] text-sm overflow-x-hidden"
:class="[
`${
store.setting.classification.layout === 'top' ? 'pr-[4px]' : 'pr-[8px]'
}`,
]"
:style="{
maxHeight: height + 'px',
height: store.setting.classification.layout === 'top' ? 'auto' : '100%',
width:
store.setting.classification.layout === 'left' ||
store.setting.classification.layout === 'right'
? store.setting.classification.mode === 'icon'
? '35px'
: store.setting.classification.width + 'px'
: 'auto',
}"
@wheel="wheel"
@contextmenu="contextmenu"
@dragover="dragover"
@drop="drop"
@mouseover="mouseover"
@mouseout="mouseout"
:key="'classification-content-' + count"
>
<ul
id="classification-list"
:class="[
`${
store.setting.classification.layout === 'top'
? 'flex flex-wrap gap-[4px] pb-1'
: ''
}`,
]"
>
<li
v-for="(classification, index) of store.classificationList"
:key="'classification-' + classification.id + '-' + index"
class="classification-parent"
@dragleave="clearMouseOverChangeClassificationSetTimeout"
>
<div
:id="'classification-' + classification.id"
class="classification-parent-content px-2 flex items-center relative h-[30px] rounded"
:class="[
`${
store.setting.classification.nameAlign === 'center' ||
store.setting.classification.mode === 'icon'
? 'justify-center'
: ''
}`,
`${store.setting.classification.mode === 'normal' ? 'px-2' : ''}`,
`${store.setting.classification.layout !== 'top' ? 'mb-1' : ''}`,
]"
:classification-id="classification.id"
:style="{
color:
isSelectedParent(classification.id) ||
(store.itemSorting &&
store.mouseoverClassificationId === classification.id)
? store.setting.appearance.theme.secondFontColor
: undefined,
backgroundColor:
isSelectedParent(classification.id) ||
(store.itemSorting &&
store.mouseoverClassificationId === classification.id)
? hexToRGBA(
store.setting.appearance.theme.secondBackgroundColor,
store.setting.appearance.transparency
)
: undefined,
}"
@click="switchParentClassification(classification.id, true)"
@dragleave="clearMouseOverChangeClassificationSetTimeout"
>
<span
class="overflow-hidden text-ellipsis whitespace-nowrap"
:style="{
filter: store.setting.appearance.fontShadow
? 'drop-shadow(1px 1px 1px ' +
store.setting.appearance.fontShadowColor +
')'
: undefined,
}"
>
{{ getClassificationName(classification) }}
</span>
<Icon
v-if="
classification.childList &&
classification.childList.length > 0 &&
!classificationChildShowHiddenMap.has(classification.id) &&
store.setting.classification.mode === 'normal'
"
class="cursor-pointer absolute right-[2px]"
:style="{
filter: store.setting.appearance.fontShadow
? 'drop-shadow(1px 1px 1px ' +
store.setting.appearance.fontShadowColor +
')'
: undefined,
}"
size="18"
@click="showHiddenChildClassification($event, classification.id)"
>
<ChevronRightRound></ChevronRightRound>
</Icon>
<Icon
v-if="
classification.childList &&
classification.childList.length > 0 &&
classificationChildShowHiddenMap.has(classification.id) &&
store.setting.classification.mode === 'normal'
"
class="cursor-pointer absolute right-[2px]"
:style="{
filter: store.setting.appearance.fontShadow
? 'drop-shadow(1px 1px 1px ' +
store.setting.appearance.fontShadowColor +
')'
: undefined,
}"
size="18"
@click="showHiddenChildClassification($event, classification.id)"
>
<KeyboardArrowDownRound></KeyboardArrowDownRound>
</Icon>
</div>
<div
v-show="
classification.childList &&
classification.childList.length > 0 &&
classificationChildShowHiddenMap.has(classification.id)
"
:class="[
`${
store.setting.classification.layout === 'top'
? '!fixed !z-[10000] !rounded-lg !origin-top-left !pt-1 !mt-1'
: ''
}`,
]"
:data-simplebar="store.setting.classification.layout === 'top'"
:style="{
backgroundColor:
store.setting.classification.layout === 'top'
? hexToRGBA(
store.setting.appearance.theme.mainBackgroundColor,
store.setting.appearance.transparency
)
: '',
width:
store.setting.classification.layout === 'top'
? classificationWidth + 'px'
: '',
maxHeight:
store.setting.classification.layout === 'top' ? '300px' : 'auto',
'box-shadow':
store.setting.classification.layout === 'top'
? '0 3px 6px -4px rgba(0, 0, 0, .12), 0 6px 16px 0 rgba(0, 0, 0, .08), 0 9px 28px 8px rgba(0, 0, 0, .05'
: '',
}"
>
<ul
class="classification-child-list h-full"
:classification-parent-id="classification.id"
>
<li
v-for="(
childClassification, childIndex
) of classification.childList"
:id="'classification-child-' + classification.id"
:key="
'classification-' +
classification.id +
'-' +
childClassification.id +
'-' +
childIndex
"
class="classification-child mb-1 px-2 flex items-center h-[30px]"
:class="[
`${
store.setting.classification.nameAlign === 'center' ||
store.setting.classification.mode === 'icon'
? 'justify-center'
: ''
}`,
`${
store.setting.classification.layout !== 'top' ? 'rounded' : ''
}`,
`${
store.setting.classification.mode === 'normal' ? 'px-2' : ''
}`,
]"
:style="{
color:
isSelectedChild(childClassification.id, classification.id) ||
(store.itemSorting &&
store.mouseoverClassificationId === childClassification.id)
? store.setting.appearance.theme.secondFontColor
: undefined,
backgroundColor:
isSelectedChild(childClassification.id, classification.id) ||
(store.itemSorting &&
store.mouseoverClassificationId === childClassification.id)
? hexToRGBA(
store.setting.appearance.theme.secondBackgroundColor,
store.setting.appearance.transparency
)
: undefined,
}"
:classification-parent-id="classification.id"
:classification-id="childClassification.id"
@click="
switchChildClassification(
classification.id,
childClassification.id
)
"
@dragleave="clearMouseOverChangeClassificationSetTimeout"
>
<span
class="overflow-hidden text-ellipsis whitespace-nowrap"
:style="{
filter: store.setting.appearance.fontShadow
? 'drop-shadow(1px 1px 1px ' +
store.setting.appearance.fontShadowColor +
')'
: undefined,
}"
>
{{ getClassificationName(childClassification) }}
</span>
</li>
<li
v-show="store.setting.classification.layout !== 'top'"
class="h-[1px] my-1 border-t-[1px]"
style="border-top-style: solid"
:style="{
borderColor: hexToRGBA(
store.setting.appearance.theme.borderColor,
store.setting.appearance.transparency
),
}"
></li>
</ul>
</div>
</li>
</ul>
</div>
</template>
<script setup lang="ts">
import {
ref,
Ref,
onMounted,
onUnmounted,
onBeforeMount,
nextTick,
onUpdated,
watch,
} from "vue";
import {
getClassElement,
setStyle,
removeStyle,
hexToRGBA,
} from "../../../utils/style";
import { Icon } from "@vicons/utils";
import { ChevronRightRound, KeyboardArrowDownRound } from "@vicons/material";
import {
getClassificationName,
hasChildClassification,
addClassification,
getClassificationById,
deleteClassification,
updateClassification,
updateClassificationOrder,
updateClassificationIcon,
convertClassificationList,
} from "../js/index";
import { Classification } from "../../../../types/classification";
import Sortable from "sortablejs";
import SimpleBar from "simplebar";
import "simplebar/dist/simplebar.css";
import { convert } from "../../../../commons/utils/common";
import {
getLocalSetting,
setLocalSetting,
deleteLocalSetting,
} from "../../../utils/localSetting";
import { findElement, unlistens } from "../../../utils/common";
import { deleteItemByClassificationId } from "../../item/js";
import { useMainStore } from "../../../store";
// pinia
const store = useMainStore();
// 暴露方法给父级组件
defineExpose({
switchClassificationById,
layoutTopHideOtherSubClassification,
});
// 计数器
let count = ref(0);
// 监听布局
watch(
() => store.setting.classification.layout,
() => {
// +1
count.value = count.value + 1;
classificationChildShowHiddenMap.value = new Map();
// 刷新DOM完毕执行
nextTick(() => {
// 滚动条
createSimpleBar();
// 设置分类宽度
setClassificationWidth();
// 创建父级分类拖拽对象;
createClassificationParentSortable();
// 创建子级分类拖拽对象
createClassificationChildSortable();
});
}
);
// 监听滚轮切换分类
watch(
() => store.classificationWheelEvent,
(newValue: WheelEvent | null) => {
if (newValue) {
wheelSwitchClassification(newValue);
}
}
);
// 锁定分类 解锁分类
let lockClassification =
getLocalSetting<boolean>("lockClassification") ?? false;
// 存储子级分类展开状态
let classificationChildShowHiddenMap: Ref<Map<number, boolean>> = ref(
new Map()
);
// 是否选中父级分类
function isSelectedParent(id: number): boolean {
return (
store.selectedClassificationParentId === id &&
!store.selectedClassificationChildId
);
}
// 是否选中子级分类
function isSelectedChild(id: number, parentId: number): boolean {
return (
store.selectedClassificationParentId === parentId &&
store.selectedClassificationChildId === id
);
}
/**
* 获取分类列表
*/
async function getClassificationList() {
// 获取列表
let classificationList = window.classification.list();
// 转换
store.classificationList = convertClassificationList(classificationList);
// default
let defaultFlag = true;
// 是否记住分类状态
if (store.setting.classification.rememberSelectionState) {
let strJson: string | null = getLocalSetting("classificationSelected");
if (strJson) {
let data = JSON.parse(strJson);
if (data.parentId) {
let classificationParent = getClassificationById(data.parentId);
if (classificationParent) {
defaultFlag = false;
store.selectedClassificationParentId = data.parentId;
if (data.childId) {
let classificationChild = getClassificationById(data.childId);
if (classificationChild) {
store.selectedClassificationChildId = data.childId;
}
}
if (store.setting.classification.layout !== "top") {
if (data.show) {
classificationChildShowHiddenMap.value.set(data.parentId, true);
}
let strJson: string | null = getLocalSetting(
"classificationChildShowHiddenMap"
);
if (strJson) {
let arr: Array<number> = JSON.parse(strJson);
for (const id of arr) {
classificationChildShowHiddenMap.value.set(id, true);
}
}
}
}
}
}
}
if (defaultFlag) {
// 默认选中
defaultSelected(null, null);
}
}
// 创建滚动条
function createSimpleBar() {
if (
store.setting.classification.layout === "left" ||
store.setting.classification.layout === "right"
) {
let element = document.getElementById("classification-content");
if (element) {
new SimpleBar(element);
}
}
}
// 默认选中
function defaultSelected(id: number | null, parentId: number | null) {
if (id) {
if (!parentId) {
store.selectedClassificationParentId = id;
store.selectedClassificationChildId = null;
} else {
store.selectedClassificationParentId = parentId;
store.selectedClassificationChildId = id;
classificationChildShowHiddenMap.value.set(
store.selectedClassificationParentId,
true
);
}
} else {
if (
!store.selectedClassificationParentId &&
store.classificationList.length > 0
) {
store.selectedClassificationParentId = store.classificationList[0].id;
store.selectedClassificationChildId = null;
}
}
// 记住分类状态
rememberClassification();
}
// 切换分类
let classificationTimer: any = null;
let classificationCounter: number = 0;
function switchParentClassification(id: number, counter: boolean) {
if (store.selectedClassificationParentId !== id) {
// 清除timeout
clearTimeout(classificationTimer);
classificationCounter = 0;
}
if (counter && hasChildClassification(id)) {
// +1
classificationCounter++;
// 等于2就是双击
if (classificationCounter === 2) {
// 清除timeout
clearTimeout(classificationTimer);
// 归0
classificationCounter = 0;
// 双击操作
if (classificationChildShowHiddenMap.value.has(id)) {
// 收起
classificationChildShowHiddenMap.value.delete(id);
} else {
// 展开
classificationChildShowHiddenMap.value.set(id, true);
}
} else {
// 间隔为500毫秒如果超过500毫秒就代表不是双击
classificationTimer = setTimeout(function () {
classificationCounter = 0;
}, 500);
}
}
store.selectedClassificationParentId = id;
store.selectedClassificationChildId = null;
store.itemBatchOperation = false;
// TOP布局
layoutTopHideOtherSubClassification(null, id);
// 记住分类状态
rememberClassification();
if (
store.setting.classification
.switchClassificationCollapseOtherSubClassification
) {
// 收起其他子分类
collapseSubClassification(store.selectedClassificationParentId);
}
}
// 切换子分类
function switchChildClassification(parentId: number, id: number) {
store.selectedClassificationParentId = parentId;
store.selectedClassificationChildId = id;
store.itemBatchOperation = false;
// TOP布局
layoutTopHideOtherSubClassification(null, parentId);
// 记住分类状态
rememberClassification();
if (
store.setting.classification
.switchClassificationCollapseOtherSubClassification
) {
// 收起其他子分类
collapseSubClassification(store.selectedClassificationParentId);
}
}
// 根据分类ID切换分类
function switchClassificationById(classificationId: number | null) {
if (classificationId) {
// 查询分类
let classification = getClassificationById(classificationId);
if (classification) {
if (classification.parentId) {
switchChildClassification(classification.parentId, classification.id);
} else {
switchParentClassification(classification.id, false);
}
}
}
}
// 鼠标悬停切换分类
let mouseHoverClassificationParentId: number | null = null;
let mouseHoverClassificationChildId: number | null = null;
let mouseHoverChangeClassificationSetTimeout: NodeJS.Timeout | null = null;
function mouseHoverChangeClassification(
classificationParentId: number,
classificationChildId: number | null,
timeout: number
) {
// 清空timeout
clearMouseOverChangeClassificationSetTimeout();
// 记录分类ID
mouseHoverClassificationParentId = classificationParentId;
mouseHoverClassificationChildId = classificationChildId;
// 设置timeout
mouseHoverChangeClassificationSetTimeout = setTimeout(() => {
// 切换分类
if (classificationChildId) {
switchChildClassification(classificationParentId, classificationChildId);
} else {
switchParentClassification(classificationParentId, false);
}
// 清空timeout
clearMouseOverChangeClassificationSetTimeout();
}, timeout);
}
// 清空timeout
function clearMouseOverChangeClassificationSetTimeout() {
if (mouseHoverChangeClassificationSetTimeout) {
mouseHoverClassificationParentId = null;
mouseHoverClassificationChildId = null;
clearTimeout(mouseHoverChangeClassificationSetTimeout);
mouseHoverChangeClassificationSetTimeout = null;
}
}
// 鼠标悬停展开子分类
let mouseHoverShowHiddenChildClassificationSetTimeout: NodeJS.Timeout | null =
null;
function mouseHovershowHiddenChildClassification(classificationId: number) {
// 清空timeout
clearMouseOverShowHiddenChildClassificationSetTimeout();
// 设置timeout
mouseHoverShowHiddenChildClassificationSetTimeout = setTimeout(() => {
// 展开子分类
if (
hasChildClassification(classificationId) &&
!classificationChildShowHiddenMap.value.has(classificationId)
) {
classificationChildShowHiddenMap.value.set(classificationId, true);
}
// 清空timeout
clearMouseOverShowHiddenChildClassificationSetTimeout();
}, 400);
}
// 清空timeout
function clearMouseOverShowHiddenChildClassificationSetTimeout() {
if (mouseHoverShowHiddenChildClassificationSetTimeout) {
clearTimeout(mouseHoverShowHiddenChildClassificationSetTimeout);
mouseHoverShowHiddenChildClassificationSetTimeout = null;
}
}
// 展开或收起子分类
function showHiddenChildClassification(e: any, id: number) {
if (classificationChildShowHiddenMap.value.has(id)) {
classificationChildShowHiddenMap.value.delete(id);
} else {
classificationChildShowHiddenMap.value.set(id, true);
}
// TOP布局
layoutTopHideOtherSubClassification(null, id);
if (
store.setting.classification
.switchClassificationCollapseOtherSubClassification
) {
// 收起其他子分类
collapseSubClassification(id);
}
if (e) {
e.stopPropagation();
}
}
// 滚轮切换分类
function wheelSwitchClassification(e: any) {
if (e) {
// 阻止默认事件
e.preventDefault();
}
// 分类
let element = document.getElementById("classification-content");
if (!element) {
return;
}
// 获取是上还是下 -1为上 1为下
const delta = Math.sign(e.deltaY);
// 判断当前分类是第几
let index = 0;
for (let i = 0; i < store.classificationList.length; i++) {
if (
store.classificationList[i].id === store.selectedClassificationParentId
) {
index = i;
}
}
let n = index;
// 切换分类
if (delta === 1) {
// 向下
if (index < store.classificationList.length - 1) {
n = index + 1;
}
} else {
// 向上
if (index > 0) {
n = index - 1;
}
}
if (n !== index) {
let classification = store.classificationList[n];
switchParentClassification(classification.id, false);
if (
store.setting.classification.layout === "left" ||
store.setting.classification.layout === "right"
) {
// 获取判断可以容纳多少个分类
let classificationNum = Math.trunc(element.clientHeight / 34);
// 获取滚动条实例
let simpleBar = SimpleBar.instances.get(element);
// 获取元素
let classificationElement = document.getElementById(
"classification-" + classification.id
);
if (!classificationElement) {
return;
}
// 分类坐标
let elTop = classificationElement.offsetTop;
// 向下
if (delta === 1 && n + 1 > classificationNum) {
let newTop = elTop + 34 - element.clientHeight;
if (newTop > simpleBar.getScrollElement().scrollTop) {
simpleBar.getScrollElement().scrollTop = newTop;
}
} else if (delta === -1) {
let down = Math.ceil(simpleBar.getScrollElement().scrollTop / 34);
let boundingClientRect = classificationElement.getBoundingClientRect();
if (n < down) {
simpleBar.getScrollElement().scrollTop =
simpleBar.getScrollElement().scrollTop -
(34 - boundingClientRect.y);
}
}
}
}
}
// 隐藏其他子分类
function layoutTopHideOtherSubClassification(e: any, id: number | null) {
// 如果是顶部布局,当点击除父级分类的地方的话,就收起子分类
if (store.setting.classification.layout === "top") {
// 寻找分类ID
let findClassificationId = (target: any) => {
if (target && target.classList) {
if (target.classList.contains("classification-parent-content")) {
let id = target.getAttribute("classification-id");
if (id) {
return parseInt(id);
}
}
}
return null;
};
// 分类ID
let classificationId: number | null = id;
if (!classificationId) {
// 先寻找当前元素,寻找不到的话就寻找父级元素
if (e.target) {
classificationId = findClassificationId(e.target);
if (!classificationId && e.target.parentElement) {
classificationId = findClassificationId(e.target.parentElement);
}
}
}
// 如果分类ID不为空的话就隐藏除当前分类的子分类列表
if (classificationId) {
for (const key of classificationChildShowHiddenMap.value.keys()) {
if (key !== classificationId) {
classificationChildShowHiddenMap.value.delete(key);
}
}
} else {
classificationChildShowHiddenMap.value = new Map();
}
}
}
// 收起子分类
function collapseSubClassification(id: number | null) {
for (let key of classificationChildShowHiddenMap.value.keys()) {
if (key !== id) {
classificationChildShowHiddenMap.value.delete(key);
}
}
}
// 记住分类状态
function rememberClassification() {
if (
store.setting.classification.rememberSelectionState &&
store.selectedClassificationParentId
) {
// 记录选择分类的状态
let data = {
parentId: store.selectedClassificationParentId,
childId: store.selectedClassificationChildId,
show:
store.setting.classification.layout === "top"
? false
: classificationChildShowHiddenMap.value.has(
store.selectedClassificationParentId
),
};
setLocalSetting("classificationSelected", JSON.stringify(data));
// 记录分类展开状态
if (
store.setting.classification.layout !== "top" &&
classificationChildShowHiddenMap.value.size > 0
) {
let arr = [];
for (const key of classificationChildShowHiddenMap.value.keys()) {
arr.push(key);
}
setLocalSetting("classificationChildShowHiddenMap", JSON.stringify(arr));
} else {
deleteLocalSetting("classificationChildShowHiddenMap");
}
}
}
// 父级分类拖拽对象
let classificationParentSortable: Sortable | null = null;
// 创建父级分类拖拽对象
function createClassificationParentSortable() {
// 如果存在先销毁
if (classificationParentSortable) {
classificationParentSortable.destroy();
}
// 创建
let element = document.getElementById("classification-list");
if (element) {
classificationParentSortable = Sortable.create(element, {
animation: 0,
forceFallback: true,
fallbackTolerance: 4,
disabled: lockClassification,
onStart() {
store.classificationSorting = true;
},
async onEnd({ newIndex, oldIndex }) {
if (
newIndex !== null &&
newIndex !== undefined &&
oldIndex !== null &&
oldIndex !== undefined
) {
// 当前分类
const currentClassification = store.classificationList[oldIndex];
// 目标分类
const targetClassification = store.classificationList[newIndex];
// 更新序号数据库
let res = window.classification.updateOrder(
currentClassification.id,
!targetClassification ? null : targetClassification.id,
null
);
if (res) {
// 更新序号
updateClassificationOrder(
currentClassification.id,
!targetClassification ? null : targetClassification.id,
null
);
}
store.classificationSorting = false;
// 刷新DOM完毕执行
nextTick(() => {
// 分类宽度
setClassificationWidth();
// 页面高度 - 34标题栏固定高度
height.value = document.documentElement.clientHeight - 34;
// 创建子级分类拖拽对象
createClassificationChildSortable();
});
}
},
});
}
}
// 子级分类拖拽对象
let classificationChildSortable: Array<Sortable> | null = null;
// 创建父级分类拖拽对象
function createClassificationChildSortable() {
// 如果存在先销毁
if (classificationChildSortable) {
for (const sortable of classificationChildSortable) {
if (sortable) {
sortable.destroy();
}
}
}
classificationChildSortable = [];
// 创建
let classificationChildElementList = document.getElementsByClassName(
"classification-child-list"
);
for (let i = 0; i < classificationChildElementList.length; i++) {
const element = classificationChildElementList[i];
classificationChildSortable.push(
Sortable.create(<HTMLElement>element, {
animation: 0,
forceFallback: true,
fallbackTolerance: 4,
disabled: lockClassification,
onStart() {
store.classificationSorting = true;
},
async onEnd({ newIndex, oldIndex }) {
// 先查询父级分类
let parentId: number = parseInt(
element.getAttribute("classification-parent-id")!
);
let parentClassification = getClassificationById(parentId);
if (
parentClassification &&
parentClassification.childList &&
parentClassification.childList.length > 0 &&
newIndex !== null &&
newIndex !== undefined &&
oldIndex !== null &&
oldIndex !== undefined
) {
// 当前分类
const currentClassification =
parentClassification.childList[oldIndex];
// 目标分类
const targetClassification =
parentClassification.childList[newIndex];
// 更新序号数据库
let res = window.classification.updateOrder(
currentClassification.id,
!targetClassification ? null : targetClassification.id,
parentId
);
if (res) {
// 更新序号
updateClassificationOrder(
currentClassification.id,
!targetClassification ? null : targetClassification.id,
parentId
);
}
}
store.classificationSorting = false;
// 刷新DOM完毕执行
nextTick(() => {
// 分类宽度
setClassificationWidth();
// 创建子级分类拖拽对象
createClassificationChildSortable();
});
},
})
);
}
}
// 页面高度
let height = ref(0);
// 初始化页面尺寸
resize();
// 监听页面大小
function resize() {
// 刷新DOM完毕执行
nextTick(() => {
// 分类宽度
setClassificationWidth();
// 页面高度 - 34标题栏固定高度
height.value = document.documentElement.clientHeight - 34;
});
}
// 监听滚轮
function wheel(e: any) {
if (!store.setting.classification.mouseWheel) {
return;
}
// 滚轮切换分类
wheelSwitchClassification(e);
}
// 监听鼠标右键
async function contextmenu(e: any) {
e.preventDefault();
e.stopPropagation();
let classification: Classification | null = null;
// 判断区域
if (getClassElement(e, "classification-parent-content")) {
// 获取分类ID
let element = getClassElement(e, "classification-parent-content");
let id = parseInt(element.getAttribute("classification-id"));
// 切换分类
switchParentClassification(id, false);
// 查询分类
classification = convert(getClassificationById(id));
} else if (getClassElement(e, "classification-child")) {
// 获取分类ID切换分类
let element = getClassElement(e, "classification-child");
let id = parseInt(element.getAttribute("classification-id"));
let parentId = parseInt(element.getAttribute("classification-parent-id"));
switchChildClassification(parentId, id);
// 查询分类
classification = convert(getClassificationById(id));
}
// 弹出菜单
window.classification.showRightMenu(classification, lockClassification);
}
// 设置分类宽度
let classificationWidth = ref(0);
function setClassificationWidth() {
// 获取分类区域
let classificationListElement = document.getElementById(
"classification-list"
);
if (classificationListElement) {
// 获取每个分类
let classificationParentListElement =
classificationListElement.getElementsByClassName("classification-parent");
// 分类位置为顶部时需要设置分类宽度
if (store.setting.classification.layout === "top") {
// 当前分类区域宽度
let width = window.innerWidth - 14;
// 最小宽度
let minWidth =
store.setting.classification.mode === "icon"
? 35
: store.setting.classification.width;
// 计算每个分类宽度
let num = Math.floor(width / (minWidth + 4));
// 设置分类宽度
if (classificationParentListElement.length >= num) {
for (let i = 0; i < classificationParentListElement.length; i++) {
let element = classificationParentListElement[i] as HTMLElement;
element.style.width = (width - num * 4) / num + "px";
classificationWidth.value = (width - num * 4) / num;
}
} else {
for (let i = 0; i < classificationParentListElement.length; i++) {
let element = classificationParentListElement[i] as HTMLElement;
element.style.width = minWidth + "px";
classificationWidth.value = minWidth;
}
}
} else {
// 设置分类宽度
for (let i = 0; i < classificationParentListElement.length; i++) {
let element = classificationParentListElement[i] as HTMLElement;
element.style.width = "100%";
}
}
}
}
// mouseover
function mouseover(e: any) {
// 鼠标经过添加分类样式
if (getClassElement(e, "classification-child")) {
let style: Map<string, string> = new Map();
style.set("color", store.setting.appearance.theme.secondFontColor);
style.set(
"background-color",
store.setting.appearance.theme.secondBackgroundColor
);
setStyle(e, "classification-child", style);
// 分类ID
let classificationElement = getClassElement(e, "classification-child");
let classificationId = parseInt(
classificationElement.getAttribute("classification-id")
);
// 父级分类ID
let classificationParentId = parseInt(
classificationElement.getAttribute("classification-parent-id")
);
// 如果是在项目拖拽中,跨分类移动项目
if (store.itemSorting) {
store.mouseoverClassificationId = classificationId;
}
if (
store.setting.classification.mouseHover &&
!store.itemSorting &&
!store.classificationSorting
) {
// 鼠标悬浮切换分类
mouseHoverChangeClassification(
classificationParentId,
classificationId,
store.setting.classification.mouseHoverMs
);
}
} else if (getClassElement(e, "classification-parent-content")) {
let style: Map<string, string> = new Map();
style.set("color", store.setting.appearance.theme.secondFontColor);
style.set(
"background-color",
store.setting.appearance.theme.secondBackgroundColor
);
setStyle(e, "classification-parent-content", style);
// 分类ID
let classificationElement = getClassElement(
e,
"classification-parent-content"
);
let classificationId = parseInt(
classificationElement.getAttribute("classification-id")
);
// 如果是在项目拖拽中,跨分类移动项目
if (store.itemSorting) {
store.mouseoverClassificationId = classificationId;
// 判断当前分类是否展开,如果没有展开的话需要展开
if (
hasChildClassification(classificationId) &&
!classificationChildShowHiddenMap.value.has(classificationId)
) {
mouseHovershowHiddenChildClassification(classificationId);
}
}
if (
store.setting.classification.mouseHover &&
!store.itemSorting &&
!store.classificationSorting
) {
// 鼠标悬浮切换分类
mouseHoverChangeClassification(
classificationId,
null,
store.setting.classification.mouseHoverMs
);
}
}
}
// mouseout
function mouseout(e: any) {
// 鼠标移走删除分类样式
if (getClassElement(e, "classification-child")) {
// 获取分类ID
let classificationChildElement = getClassElement(e, "classification-child");
let classificationId = parseInt(
classificationChildElement.getAttribute("classification-id")
);
let classificationParentId = parseInt(
classificationChildElement.getAttribute("classification-parent-id")
);
// 如果鼠标移走的是当前选中的分类则不删除样式
if (!isSelectedChild(classificationId, classificationParentId)) {
let style: Map<string, string | null> = new Map();
style.set("color", null);
style.set("background-color", null);
removeStyle(e, "classification-child", style);
}
} else if (getClassElement(e, "classification-parent-content")) {
// 获取分类ID
let classificationParentElement = getClassElement(
e,
"classification-parent-content"
);
let classificationId = parseInt(
classificationParentElement.getAttribute("classification-id")
);
// 如果鼠标移走的是当前选中的分类则不删除样式
if (!isSelectedParent(classificationId)) {
let style: Map<string, string | null> = new Map();
style.set("color", null);
style.set("background-color", null);
removeStyle(e, "classification-parent-content", style);
}
}
// 清空悬浮时分类ID
store.mouseoverClassificationId = null;
// 清空鼠标悬停切换分类timeout
clearMouseOverChangeClassificationSetTimeout();
// 清空鼠标悬停展开子分类timeout
clearMouseOverShowHiddenChildClassificationSetTimeout();
}
// dragover
function dragover(e: any) {
// 鼠标经过添加分类样式
if (findElement(e.target, "classification-child")) {
// 分类ID
let target = findElement(e.target, "classification-child");
let classificationId = parseInt(target.getAttribute("classification-id"));
// 父级分类ID
let classificationParentId = parseInt(
target.getAttribute("classification-parent-id")
);
if (
mouseHoverClassificationParentId !== classificationParentId ||
mouseHoverClassificationChildId !== classificationId
) {
// 鼠标悬浮切换分类
mouseHoverChangeClassification(
classificationParentId,
classificationId,
400
);
}
} else if (findElement(e.target, "classification-parent-content")) {
let target = findElement(e.target, "classification-parent-content");
// 分类ID
let classificationId = parseInt(target.getAttribute("classification-id"));
if (!mouseHoverClassificationParentId && !mouseHoverClassificationChildId) {
// 鼠标悬浮切换分类
mouseHoverChangeClassification(classificationId, null, 400);
}
}
e.preventDefault();
e.stopPropagation();
}
// drop
function drop(e: any) {
// 如果项目在拖拽排序中直接返回
if (store.itemSorting) {
return;
}
// 获取文件列表
let pathList = [];
for (const file of e.dataTransfer.files) {
pathList.push(file.path);
}
if (pathList.length > 0) {
// 根据文件夹创建分类
window.classification.addClassificationByDirectory(pathList);
}
}
// updated
onUpdated(() => {
// 刷新DOM完毕执行
nextTick(() => {
// 分类宽度
setClassificationWidth();
});
});
// beforeMount
onBeforeMount(async () => {
await getClassificationList();
// 刷新DOM完毕执行
nextTick(() => {
// 分类宽度
setClassificationWidth();
// 创建父级分类拖拽对象
createClassificationParentSortable();
// 创建子级分类拖拽对象
createClassificationChildSortable();
});
});
// 监听
let listens: Array<Function> = [];
// moutned
onMounted(() => {
// resize
window.addEventListener("resize", resize, true);
// 刷新DOM完毕执行
nextTick(() => {
// 分类宽度
setClassificationWidth();
// 滚动条
createSimpleBar();
// 创建父级分类拖拽对象
createClassificationParentSortable();
// 创建子级分类拖拽对象
createClassificationChildSortable();
});
// 监听新增分类
listens.push(
window.classification.onAdd((data) => {
// 分类
let classification: Classification = data;
// 添加分类
addClassification(classification);
// 默认选中
defaultSelected(classification.id, classification.parentId);
// 刷新DOM完毕执行
nextTick(() => {
// 分类宽度
setClassificationWidth();
// 创建父级分类拖拽对象
createClassificationParentSortable();
// 创建子级分类拖拽对象
createClassificationChildSortable();
});
})
);
// 监听更新分类
listens.push(
window.classification.onUpdate((data) => {
updateClassification(data);
// 刷新DOM完毕执行
nextTick(() => {
// 分类宽度
setClassificationWidth();
});
})
);
// 监听删除分类
listens.push(
window.classification.onDelete((data) => {
// 删除
deleteClassification(data);
// 清空选中ID
store.selectedClassificationParentId = null;
store.selectedClassificationChildId = null;
// 默认选中
defaultSelected(null, null);
// 刷新DOM完毕执行
nextTick(() => {
// 分类宽度
setClassificationWidth();
// 创建父级分类拖拽对象
createClassificationParentSortable();
// 创建子级分类拖拽对象
createClassificationChildSortable();
});
})
);
// 监听锁定/解锁分类
listens.push(
window.classification.onLock((data) => {
if (!lockClassification) {
setLocalSetting("lockClassification", "true");
lockClassification = true;
} else {
deleteLocalSetting("lockClassification");
lockClassification = false;
}
// 刷新DOM完毕执行
nextTick(() => {
// 创建父级分类拖拽对象
createClassificationParentSortable();
// 创建子级分类拖拽对象
createClassificationChildSortable();
});
})
);
// 更新分类图标
listens.push(
window.classification.onUpdateIcon((data) => {
updateClassificationIcon(data.id, data.icon);
})
);
// 收起子分类
listens.push(
window.classification.onCollapseSubClassification((data) => {
collapseSubClassification(null);
})
);
// 修改项目布局
listens.push(
window.classification.onUpdateItemLayout((data) => {
let dataList = data;
for (const data of dataList) {
let classification = getClassificationById(data.id);
if (classification) {
classification.data.itemLayout = data.layout;
}
}
})
);
// 修改项目排序
listens.push(
window.classification.onUpdateItemSort((data) => {
let dataList = data;
for (const data of dataList) {
let classification = getClassificationById(data.id);
if (classification) {
classification.data.itemSort = data.sort;
}
}
})
);
// 修改项目列数
listens.push(
window.classification.onUpdateItemColumnNumber((data) => {
let classification = getClassificationById(data.id);
if (classification) {
classification.data.itemColumnNumber = data.columnNumber;
}
})
);
// 修改项目图标
listens.push(
window.classification.onUpdateItemIconSize((data) => {
let dataList = data;
for (const data of dataList) {
let classification = getClassificationById(data.id);
if (classification) {
classification.data.itemIconSize = data.iconSize;
}
}
})
);
// 监听根据文件夹创建分类
listens.push(
window.classification.onAddClassificationByDirectory((data) => {
for (let i = 0; i < data.length; i++) {
// 分类
let classification: Classification = data[i].classification;
// 添加分类
addClassification(classification);
// 添加项目
window.item.drop(classification.id, data[i].fileList);
}
// 刷新DOM完毕执行
nextTick(() => {
// 分类宽度
setClassificationWidth();
// 创建父级分类拖拽对象
createClassificationParentSortable();
// 创建子级分类拖拽对象
createClassificationChildSortable();
});
})
);
// 修改项目显示
listens.push(
window.classification.onUpdateItemShowOnly((data) => {
let dataList = data;
for (const data of dataList) {
let classification = getClassificationById(data.id);
if (classification) {
classification.data.itemShowOnly = data.showOnly;
}
}
})
);
// 修改固定分类
listens.push(
window.classification.onUpdateFixed((data) => {
let id: number | null = data;
for (let classification of store.classificationList) {
classification.data.fixed = id === classification.id;
if (classification.childList) {
for (let childClassification of classification.childList) {
childClassification.data.fixed = id === childClassification.id;
}
}
}
})
);
// 将排序为打开次数的分类修改为默认排序
listens.push(
window.classification.onUpdateItemOpenNumberSortToDefualt((data) => {
for (const id of data) {
let classification = getClassificationById(id);
if (
classification &&
(classification.type === 0 || classification.type === 1)
) {
classification.data.itemSort = "default";
}
}
})
);
// 修改关联文件夹
listens.push(
window.classification.onUpdateAssociateFolder((data) => {
let classification = getClassificationById(data.id);
if (classification) {
classification.type = data.type;
classification.data.associateFolderPath = data.path;
classification.data.associateFolderHiddenItems = data.hiddenItems;
}
})
);
// 修改聚合分类
listens.push(
window.classification.onUpdateAggregate((data) => {
let classification = getClassificationById(data.id);
if (classification) {
classification.type = 2;
classification.data.itemSort = data.sort;
classification.data.aggregateItemCount = data.itemCount;
deleteItemByClassificationId(data.id);
}
})
);
// 修改排除搜索
listens.push(
window.classification.onUpdateExcludeSearch((data) => {
let classification = getClassificationById(data.id);
if (classification) {
classification.data.excludeSearch = data.value;
}
})
);
});
// unmounted
onUnmounted(() => {
// resize
window.removeEventListener("resize", resize, true);
// 删除监听
unlistens(listens);
});
</script>
../../../../types/classification