feat: 添加自定义终端背景html功能
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
<script setup lang="ts">
|
||||
import { ref } from 'vue';
|
||||
import { ref, onMounted, onUnmounted, nextTick, reactive } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import type { TerminalTheme } from '../types/terminal-theme.types';
|
||||
import StyleCustomizerUiTab from './style-customizer/StyleCustomizerUiTab.vue';
|
||||
@@ -42,15 +42,102 @@ const handleResetUiTheme = async () => {
|
||||
|
||||
|
||||
const modalRootRef = ref<HTMLDivElement | null>(null);
|
||||
const headerRef = ref<HTMLElement | null>(null);
|
||||
const dialogContentRef = ref<HTMLDivElement | null>(null);
|
||||
|
||||
const draggableState = reactive({
|
||||
isDragging: false,
|
||||
startX: 0,
|
||||
startY: 0,
|
||||
initialLeft: 0,
|
||||
initialTop: 0,
|
||||
});
|
||||
|
||||
onMounted(() => {
|
||||
const headerElement = headerRef.value;
|
||||
const dialogEl = dialogContentRef.value;
|
||||
const rootEl = modalRootRef.value;
|
||||
|
||||
if (!headerElement || !dialogEl || !rootEl) {
|
||||
// console.warn("Draggable elements not found for StyleCustomizer modal."); // 用于调试的可选日志
|
||||
return;
|
||||
}
|
||||
|
||||
nextTick(() => {
|
||||
//确保对话框已渲染且其尺寸可用
|
||||
if (dialogEl && rootEl) {
|
||||
dialogEl.style.position = 'absolute'; // 使对话框在rootEl内绝对定位
|
||||
const rootWidth = rootEl.clientWidth;
|
||||
const rootHeight = rootEl.clientHeight;
|
||||
const dialogWidth = dialogEl.offsetWidth;
|
||||
const dialogHeight = dialogEl.offsetHeight;
|
||||
|
||||
// 使对话框居中
|
||||
dialogEl.style.left = `${Math.max(0, (rootWidth - dialogWidth) / 2)}px`;
|
||||
dialogEl.style.top = `${Math.max(0, (rootHeight - dialogHeight) / 2)}px`;
|
||||
}
|
||||
});
|
||||
|
||||
const onMouseDown = (event: MouseEvent) => {
|
||||
if (!dialogEl) return;
|
||||
event.preventDefault(); // 防止文本选择等默认行为
|
||||
|
||||
draggableState.isDragging = true;
|
||||
draggableState.startX = event.clientX;
|
||||
draggableState.startY = event.clientY;
|
||||
draggableState.initialLeft = dialogEl.offsetLeft;
|
||||
draggableState.initialTop = dialogEl.offsetTop;
|
||||
|
||||
document.addEventListener('mousemove', onMouseMove);
|
||||
document.addEventListener('mouseup', onMouseUp);
|
||||
};
|
||||
|
||||
const onMouseMove = (event: MouseEvent) => {
|
||||
if (!draggableState.isDragging || !dialogEl || !rootEl) return;
|
||||
|
||||
const dx = event.clientX - draggableState.startX;
|
||||
const dy = event.clientY - draggableState.startY;
|
||||
|
||||
let newLeft = draggableState.initialLeft + dx;
|
||||
let newTop = draggableState.initialTop + dy;
|
||||
|
||||
// 边界检查,使对话框保持在 modalRootRef (视口) 内
|
||||
newLeft = Math.max(0, Math.min(newLeft, rootEl.clientWidth - dialogEl.offsetWidth));
|
||||
newTop = Math.max(0, Math.min(newTop, rootEl.clientHeight - dialogEl.offsetHeight));
|
||||
|
||||
dialogEl.style.left = `${newLeft}px`;
|
||||
dialogEl.style.top = `${newTop}px`;
|
||||
};
|
||||
|
||||
const onMouseUp = () => {
|
||||
if (!draggableState.isDragging) return;
|
||||
draggableState.isDragging = false;
|
||||
document.removeEventListener('mousemove', onMouseMove);
|
||||
document.removeEventListener('mouseup', onMouseUp);
|
||||
};
|
||||
|
||||
headerElement.addEventListener('mousedown', onMouseDown);
|
||||
headerElement.style.cursor = 'move'; // 设置页眉鼠标样式为可拖动
|
||||
|
||||
onUnmounted(() => {
|
||||
if (headerElement) {
|
||||
headerElement.removeEventListener('mousedown', onMouseDown);
|
||||
headerElement.style.cursor = ''; // 重置鼠标样式
|
||||
}
|
||||
// 清理全局监听器
|
||||
document.removeEventListener('mousemove', onMouseMove);
|
||||
document.removeEventListener('mouseup', onMouseUp);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
|
||||
|
||||
<template>
|
||||
<div ref="modalRootRef" class="fixed inset-0 bg-black/60 flex justify-center items-center z-[1000] p-2 md:p-4" @click.self="closeCustomizer">
|
||||
<div class="bg-background text-foreground rounded-lg shadow-lg w-full h-full md:w-[90%] md:max-w-[800px] md:h-[85vh] md:max-h-[700px] flex flex-col overflow-hidden">
|
||||
<header class="flex justify-between items-center px-4 py-3 border-b border-border bg-header flex-shrink-0">
|
||||
<div ref="modalRootRef" class="fixed inset-0 z-[1000]" @click.self="closeCustomizer">
|
||||
<div ref="dialogContentRef" class="bg-background text-foreground rounded-lg shadow-lg w-full h-full md:w-[90%] md:max-w-[800px] md:h-[85vh] md:max-h-[700px] flex flex-col overflow-hidden">
|
||||
<header ref="headerRef" class="flex justify-between items-center px-4 py-3 border-b border-border bg-header flex-shrink-0">
|
||||
<h2 class="m-0 text-lg md:text-xl text-foreground">{{ t('styleCustomizer.title') }}</h2>
|
||||
<button @click="closeCustomizer" class="bg-transparent border-none text-2xl md:text-3xl leading-none cursor-pointer text-text-secondary px-2 py-1 rounded hover:text-foreground hover:bg-black/10">×</button>
|
||||
</header>
|
||||
|
||||
Reference in New Issue
Block a user