提交 2b11e564 作者: Hao

add

父级 2acb94ab
......@@ -21,6 +21,7 @@ declare module 'vue' {
ElMain: typeof import('element-plus/es')['ElMain']
EmotionComponent: typeof import('./src/components/EmotionComponent.vue')['default']
IndexComponent: typeof import('./src/components/IndexComponent.vue')['default']
LogingComponent: typeof import('./src/components/loging/logingComponent.vue')['default']
MenuComponent: typeof import('./src/components/Menu/MenuComponent.vue')['default']
RightClickMenu: typeof import('./src/components/RightClickMenu.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
......
import { h, render, reactive, ref, defineEmits } from "vue";
import RightClickMenu from "./RightClickMenu.vue";
// export function openRightClickMenu(e: MouseEvent) {
// const contextMenuVisible = ref(false);
// const contextMenuTop = ref(0);
// const contextMenuLeft = ref(0);
// const contextMenuIndex = ref(0);
// const scope = document.body;
// const containerEl: any = document.createElement("div");
// const vnode:any = h(RightClickMenu, {
// visible: contextMenuVisible.value,
// menuList: [
// "复制",
// "翻译",
// "设为客户名称",
// "设置国家/地区",
// "设为Email",
// "设为watchApp",
// ],
// active: contextMenuIndex.value,
// handleItemClick: (item: any, index: number) => {
// console.log(item);
// contextMenuIndex.value = index;
// },
// });
// render(vnode, containerEl);
// containerEl.style.position = "fixed";
// containerEl.style["z-index"] = "1000";
// scope?.appendChild(containerEl);
// const showContextMenu1 = (event: any, item: any) => {
// //阻止默认右键事件
// event.preventDefault();
// //菜单可见
// contextMenuVisible.value = true;
// //获取鼠标坐标
// contextMenuTop.value = event.clientY;
// contextMenuLeft.value = event.clientX;
// // 检测是否超出浏览器视口区域 一个菜单40px*6个
// const menuHeight = 300; // 右键菜单的高度
// const windowHeight = window.innerHeight;
// if (event.clientY + menuHeight > windowHeight) {
// // 如果右键菜单超出视口底部,调整位置为向上弹出
// contextMenuTop.value -= menuHeight;
// }
// containerEl.style.top = `${contextMenuTop.value}px`;
// containerEl.style.left = `${contextMenuLeft.value}px`;
// window.addEventListener("click", hideContextMenu2);
// };
// //隐藏右键菜单的函数,移除点击事件监听器,并将 contextMenuVisible 设置为 false
// const hideContextMenu2 = (e: any) => {
// console.log(vnode,'打印');
// const pop: any = document.querySelector("#select-box1");
// if (!e || (e?.target && !pop.contains(e?.target))) {
// contextMenuVisible.value = false;
// vnode.props.visible = false;
// console.log(contextMenuVisible.value, "关闭");
// window.removeEventListener("click", hideContextMenu2);
// }
// };
// return {
// showContextMenu1,
// hideContextMenu2,
// };
// }
export default function useMenu(e: MouseEvent) {
const contextMenuVisible = ref(true);
const contextMenuTop = ref(0);
const contextMenuLeft = ref(0);
const contextMenuIndex = ref(0);
const scope = document.body;
let containerEl = reactive<HTMLElement | any>(null);
let vnode = reactive<any>(null);
let props = reactive<any>({});
const setComponent = () => {
props = {
visible: contextMenuVisible.value,
menuList: [
"复制",
"翻译",
"设为客户名称",
"设置国家/地区",
"设为Email",
"设为watchApp",
],
active: contextMenuIndex.value,
"onUpdate:info": (info: any) => {
contextMenuIndex.value = info.index;
setComponent();
},
};
vnode = h(RightClickMenu, props);
render(vnode, scope);
};
const openRightClickMenu = (e: MouseEvent) => {
setComponent();
containerEl = document.getElementById("select-box1");
if (containerEl) containerEl.style.position = "fixed";
if (containerEl) containerEl.style["z-index"] = "1000";
};
const showContextMenu1 = (event: any, item: any) => {
//阻止默认右键事件
event.preventDefault();
//菜单可见
contextMenuVisible.value = true;
openRightClickMenu(e)
//获取鼠标坐标
contextMenuTop.value = event.clientY;
contextMenuLeft.value = event.clientX;
// 检测是否超出浏览器视口区域 一个菜单40px*6个
const menuHeight = 300; // 右键菜单的高度
const windowHeight = window.innerHeight;
if (event.clientY + menuHeight > windowHeight) {
// 如果右键菜单超出视口底部,调整位置为向上弹出
contextMenuTop.value -= menuHeight;
}
containerEl.style.top = `${contextMenuTop.value}px`;
containerEl.style.left = `${contextMenuLeft.value}px`;
window.addEventListener("click", hideContextMenu2);
};
//隐藏右键菜单的函数,移除点击事件监听器,并将 contextMenuVisible 设置为 false
const hideContextMenu2 = (e: any) => {
const pop: any = document.querySelector("#select-box1");
if (!e || (e?.target && !pop.contains(e?.target))) {
contextMenuVisible.value = false;
setComponent();
window.removeEventListener("click", hideContextMenu2);
}
};
return {
contextMenuVisible,
openRightClickMenu,
showContextMenu1,
hideContextMenu2,
};
}
<template>
<teleport to="body">
<div
id="select-box1"
v-if="visible"
:style="{ top: `${top}px`, left: `${left}px` }"
>
<ul
v-for="(item, index) in menuList"
:class="{ active: active == index }"
:key="index"
@click.stop="handleItemClick(item, index)"
>
<li>{{ item }}</li>
</ul>
</div>
</teleport>
</template>
<script setup lang="ts">
import { defineProps, onMounted, defineEmits } from 'vue'
defineProps(['top', 'left', 'visible', 'menuList', 'active'])
const emit = defineEmits(['update:info'])
const handleItemClick = (item: any, index: any) => {
emit('update:info', { item, index })
}
</script>
<style scoped lang="scss">
#select-box1 {
z-index: 1000;
display: flex;
width: 136px;
padding: var(--Spacing-md, 8px);
flex-direction: column;
align-items: flex-start;
gap: var(--Spacing-xs, 4px);
border-radius: var(--Radius-md, 8px);
background: var(--color-bg-Program-White, #fff);
box-shadow: 0 2px 12px 0 #08112914;
ul {
padding: 6px 8px;
height: 32px;
line-height: 32px;
}
.active {
display: flex;
padding: var(--Spacing-sm, 6px) var(--Spacing-md, 8px);
align-items: center;
gap: var(--Spacing-none, 0);
align-self: stretch;
color: #fff;
border-radius: 4px;
background: #010914;
font-size: 14px;
}
}
</style>
......@@ -28,11 +28,11 @@ export function openCountextMenus(e: Event) {
isShow = false;
}
}
// window.oncontextmenu = function (e: MouseEvent) {
// e.preventDefault();
// if (isShow) closeMenu();
// openMenu(e);
// };
// window.oncontextmenu = function (e: MouseEvent) {
// e.preventDefault();
// if (isShow) closeMenu();
// openMenu(e);
// };
return {
isShow,
openMenu,
......
<template>
<div class="loading">
<div></div>
<span v-if="$attrs.msg !== false">{{ $attrs.msg }}</span>
</div>
</template>
<script lang="ts">
export default {
}
</script>
<style>
@keyframes identifier {
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
.loading {
height: 100px;
width: 100%;
}
.loading div {
width: 50px;
height: 50px;
border-radius: 50%;
border: 2px solid green;
margin: 25px auto;
border-top: none;
border-left: none;
animation: identifier 1s infinite linear;
}
</style>
\ No newline at end of file
......@@ -12,6 +12,12 @@ const routes: Array<RouteRecordRaw> = [
component: () =>
import(/* webpackChunkName: "about" */ "../views/loginView.vue"),
},
{
path: "/loging",
name: "loging",
component: () =>
import(/* webpackChunkName: "about" */ "../views/logingView.vue"),
},
];
const router = createRouter({
......
......@@ -70,7 +70,7 @@
>
<div class="time">{{ message.time }}</div>
<div v-if="message.isSent" class="message-container">
<div class="bubble" @contextmenu="showContextMenu($event, item)">
<div class="bubble" @contextmenu="showContextMenu1($event, item)">
<div v-if="message?.msgType == 0" class="message">
<div class="content" v-html="message?.content"></div>
<div class="contentFy" v-html="message?.contentFy"></div>
......@@ -94,7 +94,7 @@
<div class="avatar">
<img :src="message?.userImg" class="avatar-image" />
</div>
<div class="bubble" @contextmenu="showContextMenu($event, item)">
<div class="bubble" @contextmenu="showContextMenu1($event, item)">
<div v-if="message?.msgType == 0" class="message">
<div class="content" v-html="message?.content"></div>
<div class="contentFy" v-html="message?.contentFy"></div>
......@@ -108,15 +108,6 @@
</div>
</div>
</div>
<RightClickMenu
:top="contextMenuTop"
:left="contextMenuLeft"
:active="contextMenuIndex"
:handleItemClick="handleContextMenuItemClick"
:visible="contextMenuVisible"
ref="targetElement"
:menuList="menuList"
/>
</el-main>
<el-footer class="el-footer">
<AutomaticPrompt
......@@ -262,57 +253,13 @@ import type { FormInstance } from 'element-plus'
import { initWebSocket } from '../utils/websocket'
import '@luohc92/vue3-image-viewer/dist/style.css'
import { getUserList, InquiryAdd, checkMesssages } from '../axios/model/user'
import { openCountextMenus } from '@/components/Menu/index'
import useMenu from '@/components/Menu/RightClickMenu'
import RightClickMenu from '@/components/RightClickMenu.vue'
let menuList = ref([
'复制',
'翻译',
'设为客户名称',
'设置国家/地区',
'设为Email',
'设为watchApp',
])
const targetElement = ref(null)
const contextMenuVisible = ref(false)
const contextMenuTop = ref(0)
const contextMenuLeft = ref(0)
const contextMenuIndex = ref(0)
let {showContextMenu1,hideContextMenu2} = useMenu()
// let { showContextMenu1, hideContextMenu2 } = openRightClickMenu()
//显示右键菜单的函数,在右键点击时调用。
//它阻止了默认的右键菜单并设置了菜单的位置,同时添加了一个点击事件监听器来在其他地方点击时隐藏菜单。
const showContextMenu = (event, item) => {
//阻止默认右键事件
event.preventDefault()
//菜单可见
contextMenuVisible.value = true
//获取鼠标坐标
contextMenuTop.value = event.clientY
contextMenuLeft.value = event.clientX
// 检测是否超出浏览器视口区域 一个菜单40px*6个
const menuHeight = 300 // 右键菜单的高度
const windowHeight = window.innerHeight
if (event.clientY + menuHeight > windowHeight) {
// 如果右键菜单超出视口底部,调整位置为向上弹出
contextMenuTop.value -= menuHeight
}
window.addEventListener('click', hideContextMenu)
}
//隐藏右键菜单的函数,移除点击事件监听器,并将 contextMenuVisible 设置为 false
const hideContextMenu = (e:any) => {
var pop: any = document.querySelector('#select-box')
if (!e || e?.target && !pop.contains(e?.target)) {
contextMenuVisible.value = false
window.removeEventListener('click', hideContextMenu)
}
}
//处理右键菜单项点击的函数,你可以在这里处理点击菜单项后的逻辑。
const handleContextMenuItemClick = (item: any, index: number) => {
console.log(`Clicked on ${(item, index)}`)
contextMenuIndex.value = index
hideContextMenu()
}
const ruleForm = ref({
count: 1,
})
......
<script setup lang="ts">
import { Directive, VNode, h, ref, render } from 'vue';
import Loading from '@/components/loging/logingComponent.vue';
const defaultOption: {msg?: string | false} = {
msg: '努力加载中'
}
interface Props {loading: boolean, msg?: string | false}
function formatOption (value: boolean | Props) {
const loading = typeof value === 'boolean'
? value
: value.loading
const option = typeof value !== 'boolean'
? Object.assign(defaultOption, value)
: {
loading,
...defaultOption
}
return { loading, option }
}
function renderLoading (el: HTMLElement, option: Props) {
const vnode = h(
Loading,
{ id: 'loading', ...option}
)
el.removeChild(el.children[0])
render(vnode, el)
}
function renderVNode (el: HTMLElement, vnode: VNode) {
el.querySelector('#loading')?.remove()
render(vnode, el)
}
const vLoading: Directive<HTMLElement, boolean | Props> = {
mounted(el, binding) {
const { loading, option } = formatOption(binding.value)
loading && renderLoading(el, option)
},
updated(el: HTMLElement, binding, vnode) {
const { loading, option } = formatOption(binding.value)
if (loading) {
renderLoading(el, option)
} else {
renderVNode(el, vnode)
}
},
}
const loading = ref(true)
setTimeout(() => loading.value = false, 2000)
</script>
<template>
<div style="width: 300px" v-loading="{ loading, msg: '一大波僵尸来袭' }">
<h1>加载成功</h1>
</div>
</template>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论