|
|
@@ -4,13 +4,24 @@
|
|
|
反馈
|
|
|
</span>
|
|
|
<br /> -->
|
|
|
- <span @click="dialogVisible2 = true">
|
|
|
- <el-icon>
|
|
|
- <ChatRound />
|
|
|
- </el-icon>
|
|
|
- <br />
|
|
|
- AI助手
|
|
|
- </span>
|
|
|
+ <div class="draggable-window"
|
|
|
+ v-draggable="{
|
|
|
+ updatePosition: handlePositionUpdate,
|
|
|
+ onClick: openxiaoKe
|
|
|
+ }"
|
|
|
+ :style="{ left: position.x + 'px', top: position.y + 'px' }"
|
|
|
+ @dragging="handleDragging">
|
|
|
+ <div class="window-header">
|
|
|
+ <span>
|
|
|
+ <el-icon>
|
|
|
+ <ChatRound />
|
|
|
+ </el-icon>
|
|
|
+ <br />
|
|
|
+ AI助手
|
|
|
+ </span>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
</div>
|
|
|
<el-dialog v-model="dialogVisible" :before-close="handleClose" width=500>
|
|
|
<template #header>
|
|
|
@@ -34,7 +45,7 @@
|
|
|
</div>
|
|
|
</template>
|
|
|
</el-dialog>
|
|
|
- <el-drawer v-model="dialogVisible2" width="100%" :direction="rtl" :size="Full_Screen ? ' 100%' : '30%'">
|
|
|
+ <el-drawer v-model="dialogVisible2" width="100%" direction="rtl" :size="Full_Screen ? ' 100%' : '30%'">
|
|
|
<template #header="{ close, titleId, titleClass }">
|
|
|
<div slot="title" style="display: flex; align-items: center;">
|
|
|
<img style="cursor: pointer;width: 24px;margin-left: 15px;" :src="!Full_Screen ? FullScreen : noFullScreen"
|
|
|
@@ -59,11 +70,102 @@ const dialogVisible = ref(false)
|
|
|
const textarea1 = ref("")
|
|
|
const dialogVisible2 = ref(false)
|
|
|
const Full_Screen = ref(false)
|
|
|
+const vDraggable = {
|
|
|
+ mounted(el, binding) {
|
|
|
+ let isDragging = false;
|
|
|
+ let offsetX = 0;
|
|
|
+ let offsetY = 0;
|
|
|
+ let startTime = '';
|
|
|
+
|
|
|
+ const onMouseDown = (event) => {
|
|
|
+
|
|
|
+ isDragging = true;
|
|
|
+ startTime = new Date().getTime();
|
|
|
+ offsetX = event.clientX - el.offsetLeft;
|
|
|
+ offsetY = event.clientY - el.offsetTop;
|
|
|
+
|
|
|
+ document.body.style.userSelect = "none";
|
|
|
+ document.addEventListener("mousemove", onMouseMove);
|
|
|
+ document.addEventListener("mouseup", onMouseUp);
|
|
|
+ };
|
|
|
+
|
|
|
+ const onMouseMove = (event) => {
|
|
|
+ let endTime = new Date().getTime();
|
|
|
+ if (isDragging && (endTime - startTime > 200)) {
|
|
|
+ el.style.left = `${event.clientX - offsetX}px`;
|
|
|
+ el.style.top = `${event.clientY - offsetY}px`;
|
|
|
+
|
|
|
+ // Vue 3 中需要通过 binding.value 传递回调函数
|
|
|
+ if (binding.value?.updatePosition) {
|
|
|
+ binding.value.updatePosition({
|
|
|
+ x: event.clientX - offsetX,
|
|
|
+ y: event.clientY - offsetY
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+ };
|
|
|
+
|
|
|
+ const onMouseUp = () => {
|
|
|
+ isDragging = false;
|
|
|
+ let endTime = new Date().getTime();
|
|
|
+
|
|
|
+ if (endTime - startTime < 200) {
|
|
|
+ // 通过 binding.value 调用回调
|
|
|
+ if (binding.value && binding.value.onClick) {
|
|
|
+ binding.value.onClick();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ document.body.style.userSelect = "";
|
|
|
+ document.removeEventListener("mousemove", onMouseMove);
|
|
|
+ document.removeEventListener("mouseup", onMouseUp);
|
|
|
+ };
|
|
|
+
|
|
|
+ // 确保元素有 window-header 类
|
|
|
+ const headerEl = el.querySelector(".window-header");
|
|
|
+ if (headerEl) {
|
|
|
+ headerEl.addEventListener("mousedown", onMouseDown);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 保存事件监听器引用以便卸载时清理
|
|
|
+ el._draggable = { onMouseDown, headerEl };
|
|
|
+ },
|
|
|
+
|
|
|
+ unmounted(el) {
|
|
|
+ // 清理事件监听器
|
|
|
+ if (el._draggable) {
|
|
|
+ const { onMouseDown, headerEl } = el._draggable;
|
|
|
+ if (headerEl) {
|
|
|
+ headerEl.removeEventListener("mousedown", onMouseDown);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+const position = ref({
|
|
|
+ x: window.innerWidth - 115, // 屏幕宽度减去元素宽度
|
|
|
+ y: window.innerHeight - 150, // 屏幕高度减去元素高度
|
|
|
+});
|
|
|
+
|
|
|
+const handlePositionUpdate = (newPos) => {
|
|
|
+ // 直接修改 reactive 对象的属性
|
|
|
+ position.value.x = newPos.x;
|
|
|
+ position.value.y = newPos.y;
|
|
|
+ console.log('位置更新:', position);
|
|
|
+};
|
|
|
+const openxiaoKe = () => {
|
|
|
+ console.log('点击事件触发');
|
|
|
+ dialogVisible2.value = true
|
|
|
+};
|
|
|
|
|
|
const goFeedback = () => {
|
|
|
// top.location.href = "https://bbs.cocorobo.cn/"
|
|
|
dialogVisible.value = true
|
|
|
}
|
|
|
+
|
|
|
+const handleClose = (done) => {
|
|
|
+ done()
|
|
|
+}
|
|
|
const CustomerService = () => {
|
|
|
top.location.href = "https://bbs.cocorobo.cn/"
|
|
|
}
|
|
|
@@ -102,4 +204,27 @@ const updateReduction = () => {
|
|
|
font-size: 14px;
|
|
|
}
|
|
|
}
|
|
|
+.draggable-window {
|
|
|
+ position: fixed;
|
|
|
+ background: #fff;
|
|
|
+ padding: 10px 0;
|
|
|
+ border-radius: 30px;
|
|
|
+ text-align: center;
|
|
|
+ box-shadow: 1px 2px 1px 2px #f1f1f1;
|
|
|
+ z-index: 100;
|
|
|
+}
|
|
|
+
|
|
|
+.window-header {
|
|
|
+ position: relative;
|
|
|
+ span {
|
|
|
+ display: inline-block;
|
|
|
+ padding: 10px 8px;
|
|
|
+ cursor: pointer;
|
|
|
+ font-size: 14px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.window-header:active {
|
|
|
+ cursor: grabbing;
|
|
|
+}
|
|
|
</style>
|