🐛 终端无法粘贴.

This commit is contained in:
lijiahangmax
2024-03-23 23:31:21 +08:00
parent a3d4420754
commit 1125ef8a5a
5 changed files with 2714 additions and 1034 deletions

View File

@@ -1,7 +1,7 @@
{
"name": "orion-ops-pro-ui",
"description": "Orion Ops Pro for Vue",
"version": "1.0.2",
"version": "1.0.3",
"private": true,
"author": "Jiahang Li",
"license": "Apache 2.0",

File diff suppressed because it is too large Load Diff

View File

@@ -1,189 +1,189 @@
<script lang="tsx">
import type { RouteMeta, RouteRecordRaw } from 'vue-router';
import { useRoute, useRouter } from 'vue-router';
import { compile, computed, defineComponent, h, ref } from 'vue';
import { useAppStore } from '@/store';
import { listenerRouteChange } from '@/utils/route-listener';
import { openWindow, regexUrl } from '@/utils';
import { openNewRoute } from '@/router';
import useMenuTree from './use-menu-tree';
<!--<script lang="tsx">-->
<!-- import type { RouteMeta, RouteRecordRaw } from 'vue-router';-->
<!-- import { useRoute, useRouter } from 'vue-router';-->
<!-- import { compile, computed, defineComponent, h, ref } from 'vue';-->
<!-- import { useAppStore } from '@/store';-->
<!-- import { listenerRouteChange } from '@/utils/route-listener';-->
<!-- import { openWindow, regexUrl } from '@/utils';-->
<!-- import { openNewRoute } from '@/router';-->
<!-- import useMenuTree from './use-menu-tree';-->
export default defineComponent({
name: 'menuTree',
emit: ['collapse'],
setup() {
const appStore = useAppStore();
const router = useRouter();
const route = useRoute();
const { menuTree } = useMenuTree();
const collapsed = computed({
get() {
if (appStore.device === 'desktop') return appStore.menuCollapse;
return false;
},
set(value: boolean) {
appStore.updateSettings({ menuCollapse: value });
},
});
<!-- export default defineComponent({-->
<!-- name: 'menuTree',-->
<!-- emit: ['collapse'],-->
<!-- setup() {-->
<!-- const appStore = useAppStore();-->
<!-- const router = useRouter();-->
<!-- const route = useRoute();-->
<!-- const { menuTree } = useMenuTree();-->
<!-- const collapsed = computed({-->
<!-- get() {-->
<!-- if (appStore.device === 'desktop') return appStore.menuCollapse;-->
<!-- return false;-->
<!-- },-->
<!-- set(value: boolean) {-->
<!-- appStore.updateSettings({ menuCollapse: value });-->
<!-- },-->
<!-- });-->
const topMenu = computed(() => appStore.topMenu);
const openKeys = ref<string[]>([]);
const selectedKey = ref<string[]>([]);
<!-- const topMenu = computed(() => appStore.topMenu);-->
<!-- const openKeys = ref<string[]>([]);-->
<!-- const selectedKey = ref<string[]>([]);-->
// 跳转路由
const goto = (e: any, item: RouteRecordRaw) => {
// 打开外链
if (regexUrl.test(item.path)) {
openWindow(item.path);
return;
}
const { hideInMenu, activeMenu, newWindow } = item.meta as RouteMeta;
// 新页面打开
if (newWindow || e.ctrlKey) {
openNewRoute({
name: item.name,
});
return;
}
// 设置 selectedKey
if (route.name === item.name && !hideInMenu && !activeMenu) {
selectedKey.value = [item.name as string];
return;
}
// 触发跳转
router.push({
name: item.name,
});
};
<!-- // 跳转路由-->
<!-- const goto = (e: any, item: RouteRecordRaw) => {-->
<!-- // 打开外链-->
<!-- if (regexUrl.test(item.path)) {-->
<!-- openWindow(item.path);-->
<!-- return;-->
<!-- }-->
<!-- const { hideInMenu, activeMenu, newWindow } = item.meta as RouteMeta;-->
<!-- // 新页面打开-->
<!-- if (newWindow || e.ctrlKey) {-->
<!-- openNewRoute({-->
<!-- name: item.name,-->
<!-- });-->
<!-- return;-->
<!-- }-->
<!-- // 设置 selectedKey-->
<!-- if (route.name === item.name && !hideInMenu && !activeMenu) {-->
<!-- selectedKey.value = [item.name as string];-->
<!-- return;-->
<!-- }-->
<!-- // 触发跳转-->
<!-- router.push({-->
<!-- name: item.name,-->
<!-- });-->
<!-- };-->
const findMenuOpenKeys = (target: string) => {
const result: string[] = [];
let isFind = false;
const backtrack = (item: RouteRecordRaw, keys: string[]) => {
if (item.name === target) {
isFind = true;
result.push(...keys);
return;
}
if (item.children?.length) {
item.children.forEach((el) => {
backtrack(el, [...keys, el.name as string]);
});
}
};
menuTree.value.forEach((el: RouteRecordRaw) => {
if (isFind) return;
backtrack(el, [el.name as string]);
});
return result;
};
<!-- const findMenuOpenKeys = (target: string) => {-->
<!-- const result: string[] = [];-->
<!-- let isFind = false;-->
<!-- const backtrack = (item: RouteRecordRaw, keys: string[]) => {-->
<!-- if (item.name === target) {-->
<!-- isFind = true;-->
<!-- result.push(...keys);-->
<!-- return;-->
<!-- }-->
<!-- if (item.children?.length) {-->
<!-- item.children.forEach((el) => {-->
<!-- backtrack(el, [...keys, el.name as string]);-->
<!-- });-->
<!-- }-->
<!-- };-->
<!-- menuTree.value.forEach((el: RouteRecordRaw) => {-->
<!-- if (isFind) return;-->
<!-- backtrack(el, [el.name as string]);-->
<!-- });-->
<!-- return result;-->
<!-- };-->
// 监听路由 设置打开的 key
listenerRouteChange((newRoute) => {
const { activeMenu, hideInMenu } = newRoute.meta;
if (!hideInMenu || activeMenu) {
const menuOpenKeys = findMenuOpenKeys(
(activeMenu || newRoute.name) as string
);
<!-- // 监听路由 设置打开的 key-->
<!-- listenerRouteChange((newRoute) => {-->
<!-- const { activeMenu, hideInMenu } = newRoute.meta;-->
<!-- if (!hideInMenu || activeMenu) {-->
<!-- const menuOpenKeys = findMenuOpenKeys(-->
<!-- (activeMenu || newRoute.name) as string-->
<!-- );-->
const keySet = new Set([...menuOpenKeys, ...openKeys.value]);
openKeys.value = [...keySet];
<!-- const keySet = new Set([...menuOpenKeys, ...openKeys.value]);-->
<!-- openKeys.value = [...keySet];-->
selectedKey.value = [
activeMenu || menuOpenKeys[menuOpenKeys.length - 1],
];
}
}, true);
<!-- selectedKey.value = [-->
<!-- activeMenu || menuOpenKeys[menuOpenKeys.length - 1],-->
<!-- ];-->
<!-- }-->
<!-- }, true);-->
// 展开菜单
const setCollapse = (val: boolean) => {
if (appStore.device === 'desktop')
appStore.updateSettings({ menuCollapse: val });
};
<!-- // 展开菜单-->
<!-- const setCollapse = (val: boolean) => {-->
<!-- if (appStore.device === 'desktop')-->
<!-- appStore.updateSettings({ menuCollapse: val });-->
<!-- };-->
// 渲染菜单
const renderSubMenu = () => {
function travel(_route: RouteRecordRaw[], nodes = []) {
if (_route) {
_route.forEach((element) => {
// This is demo, modify nodes as needed
const icon = element?.meta?.icon
? () => h(compile(`<${element?.meta?.icon}/>`))
: null;
const node =
element?.children && element?.children.length !== 0 ? (
<a-sub-menu
key={element?.name}
v-slots={{
icon,
// 去除国际化 title: () => h(compile(t(element?.meta?.locale || ''))),
title: () => h(compile(element?.meta?.locale || '')),
}}
>
{travel(element?.children)}
</a-sub-menu>
) : (
<a-menu-item
key={element?.name}
v-slots={{ icon }}
onClick={($event: any) => goto($event, element)}
>
{element?.meta?.locale || ''}
</a-menu-item>
);
nodes.push(node as never);
});
}
return nodes;
}
<!-- // 渲染菜单-->
<!-- const renderSubMenu = () => {-->
<!-- function travel(_route: RouteRecordRaw[], nodes = []) {-->
<!-- if (_route) {-->
<!-- _route.forEach((element) => {-->
<!-- // This is demo, modify nodes as needed-->
<!-- const icon = element?.meta?.icon-->
<!-- ? () => h(compile(`<${element?.meta?.icon}/>`))-->
<!-- : null;-->
<!-- const node =-->
<!-- element?.children && element?.children.length !== 0 ? (-->
<!-- <a-sub-menu-->
<!-- key={element?.name}-->
<!-- v-slots={{-->
<!-- icon,-->
<!-- // 去除国际化 title: () => h(compile(t(element?.meta?.locale || ''))),-->
<!-- title: () => h(compile(element?.meta?.locale || '')),-->
<!-- }}-->
<!-- >-->
<!-- {travel(element?.children)}-->
<!-- </a-sub-menu>-->
<!-- ) : (-->
<!-- <a-menu-item-->
<!-- key={element?.name}-->
<!-- v-slots={{ icon }}-->
<!-- onClick={($event: any) => goto($event, element)}-->
<!-- >-->
<!-- {element?.meta?.locale || ''}-->
<!-- </a-menu-item>-->
<!-- );-->
<!-- nodes.push(node as never);-->
<!-- });-->
<!-- }-->
<!-- return nodes;-->
<!-- }-->
return travel(menuTree.value);
};
<!-- return travel(menuTree.value);-->
<!-- };-->
return () => (
<a-menu
mode={topMenu.value ? 'horizontal' : 'vertical'}
v-model:collapsed={collapsed.value}
v-model:open-keys={openKeys.value}
show-collapse-button={appStore.device !== 'mobile'}
auto-open={false}
selected-keys={selectedKey.value}
auto-open-selected={true}
level-indent={34}
style="height: 100%; width:100%;"
onCollapse={setCollapse}
>
{renderSubMenu()}
</a-menu>
);
},
});
</script>
<!-- return () => (-->
<!-- <a-menu-->
<!-- mode={topMenu.value ? 'horizontal' : 'vertical'}-->
<!-- v-model:collapsed={collapsed.value}-->
<!-- v-model:open-keys={openKeys.value}-->
<!-- show-collapse-button={appStore.device !== 'mobile'}-->
<!-- auto-open={false}-->
<!-- selected-keys={selectedKey.value}-->
<!-- auto-open-selected={true}-->
<!-- level-indent={34}-->
<!-- style="height: 100%; width:100%;"-->
<!-- onCollapse={setCollapse}-->
<!-- >-->
<!-- {renderSubMenu()}-->
<!-- </a-menu>-->
<!-- );-->
<!-- },-->
<!-- });-->
<!--</script>-->
<style lang="less" scoped>
:deep(.arco-menu-inner) {
.arco-menu-inline-header {
display: flex;
align-items: center;
}
<!--<style lang="less" scoped>-->
<!-- :deep(.arco-menu-inner) {-->
<!-- .arco-menu-inline-header {-->
<!-- display: flex;-->
<!-- align-items: center;-->
<!-- }-->
.arco-icon {
&:not(.arco-icon-down) {
font-size: 18px;
}
}
<!-- .arco-icon {-->
<!-- &:not(.arco-icon-down) {-->
<!-- font-size: 18px;-->
<!-- }-->
<!-- }-->
.arco-menu-icon {
margin-right: 10px !important;
}
<!-- .arco-menu-icon {-->
<!-- margin-right: 10px !important;-->
<!-- }-->
.arco-menu-indent-list {
width: 28px;
display: inline-block;
}
<!-- .arco-menu-indent-list {-->
<!-- width: 28px;-->
<!-- display: inline-block;-->
<!-- }-->
.arco-menu-title {
user-select: none;
}
}
</style>
<!-- .arco-menu-title {-->
<!-- user-select: none;-->
<!-- }-->
<!-- }-->
<!--</style>-->

View File

@@ -1,15 +1,12 @@
import { useClipboard } from '@vueuse/core';
import { Message } from '@arco-design/web-vue';
const { copy: c } = useClipboard();
// 复制
export const copy = async (value: string | undefined, tips: string | boolean = `${value} 已复制`) => {
try {
if (!value) {
return;
}
await c(value);
await copyToClipboard(value);
if (tips) {
Message.success(tips as string);
}
@@ -20,7 +17,49 @@ export const copy = async (value: string | undefined, tips: string | boolean = `
// 获取剪切板内容
export const readText = () => {
return navigator.clipboard.readText();
if (navigator.clipboard) {
return navigator.clipboard.readText();
} else {
return new Promise<string>((resolve, reject) => {
const textarea = document.createElement('textarea');
textarea.style.position = 'absolute';
textarea.style.left = '-9999px';
document.body.appendChild(textarea);
textarea.select();
try {
const success = document.execCommand('paste');
if (!success) {
Message.error('当前浏览器无法读取剪切板内容');
}
resolve(textarea.value);
} catch (error) {
reject(error);
} finally {
document.body.removeChild(textarea);
}
});
}
};
// 复制到剪切板
export const copyToClipboard = async (value: string) => {
if (navigator.clipboard) {
await navigator.clipboard.writeText(value);
} else {
const textarea = document.createElement('textarea');
textarea.textContent = value;
textarea.style.position = 'absolute';
textarea.style.left = '-9999px';
document.body.appendChild(textarea);
textarea.select();
try {
document.execCommand('copy');
} catch (error) {
throw error;
} finally {
document.body.removeChild(textarea);
}
}
};
export default function useCopy() {

View File

@@ -16,17 +16,18 @@ const preventKeys: Array<ShortcutKey> = [
altKey: false,
shiftKey: true,
code: 'KeyC'
}, {
ctrlKey: true,
altKey: false,
shiftKey: true,
code: 'KeyV'
}, {
ctrlKey: false,
altKey: false,
shiftKey: true,
code: 'Insert'
},
}
// , {
// ctrlKey: true,
// altKey: false,
// shiftKey: true,
// code: 'KeyV'
// }, {
// ctrlKey: false,
// altKey: false,
// shiftKey: true,
// code: 'Insert'
// },
];
const { copy: copyValue, readText } = useCopy();