新增前端vue

This commit is contained in:
2025-11-26 13:55:01 +08:00
parent ae391f1b94
commit ffd5a6ad66
781 changed files with 83348 additions and 0 deletions

View File

@@ -0,0 +1,9 @@
<template>
<div></div>
</template>
<script lang="ts">
import { defineComponent } from 'vue';
export default defineComponent({
name: 'FrameBlank',
});
</script>

View File

@@ -0,0 +1,138 @@
<!--
* Copyright (c) 2013-Now http://jeesite.com All rights reserved.
* No deletion without permission, or be held responsible to law.
* @author VbenThinkGem
-->
<template>
<div :class="prefixCls" :style="getWrapStyle">
<Spin :spinning="loading" size="large" :style="getWrapStyle">
<iframe
:src="frameSrc"
:class="`${prefixCls}__main ${props.frame?.name}`"
ref="frameRef"
@load="hideLoading"
></iframe>
</Spin>
</div>
</template>
<script lang="ts" setup>
import type { CSSProperties } from 'vue';
import type { AppRouteRecordRaw } from '@jeesite/core/router/types';
import { ref, unref, computed, watch } from 'vue';
import { Spin } from 'ant-design-vue';
import { useWindowSizeFn } from '@jeesite/core/hooks/event/useWindowSizeFn';
import { useDesign } from '@jeesite/core/hooks/web/useDesign';
import { useLayoutHeight } from '@jeesite/core/layouts/default/content/useContentViewHeight';
import { router } from '@jeesite/core/router';
const props = defineProps({
frame: { type: Object as PropType<AppRouteRecordRaw> },
query: { type: Object as PropType<Recordable> },
fullHeight: { type: Boolean, default: false },
});
const loading = ref(true);
const topRef = ref(50);
const heightRef = ref(window.innerHeight);
const frameRef = ref<HTMLFrameElement>();
const { headerHeightRef } = useLayoutHeight();
const { prefixCls } = useDesign('iframe-page');
useWindowSizeFn(calcHeight, 150, { immediate: true });
// const frameSrc = ref(props.frame?.meta?.frameSrc);
const frameSrc = ref<string>();
watch(
() => router.currentRoute.value.query,
() => {
// jee site iframe query
let src = props.frame?.meta?.frameSrc || '';
let search = window.location.search;
if (search && search != '') {
src += search;
}
const path = window.location.pathname.replace(/\/\//g, '/');
if (!frameSrc.value || (frameSrc.value != src && src.indexOf(path) != -1)) {
frameSrc.value = src;
}
},
{ immediate: true },
);
watch(
() => router.currentRoute.value.name,
() => {
// jee site iframe refresh
let params = router.currentRoute.value.params;
if (params && params.path == props.frame?.path) {
let src = props.frame?.meta?.frameSrc;
src += src?.indexOf('?') != -1 ? '&' : '?';
frameSrc.value = src + '__t' + new Date().getTime();
}
},
);
const padding = 13; // jee site default padding
const getWrapStyle = computed((): CSSProperties => {
return {
height: `${unref(heightRef) - padding}px`,
};
});
function calcHeight() {
const iframe = unref(frameRef);
if (!iframe) {
return;
}
if (props.fullHeight) {
const clientHeight = document.documentElement.clientHeight - 6;
iframe.style.height = `${clientHeight}px`;
return;
}
const top = headerHeightRef.value + padding;
topRef.value = top;
heightRef.value = window.innerHeight - top;
const clientHeight = document.documentElement.clientHeight - top;
iframe.style.height = `${clientHeight - padding}px`;
}
function hideLoading() {
loading.value = false;
calcHeight();
}
</script>
<style lang="less">
@prefix-cls: ~'jeesite-iframe-page';
.@{prefix-cls} {
.ant-spin-nested-loading {
position: relative;
height: 100%;
.ant-spin-container {
width: 100%;
height: 100%;
}
}
&__mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
&__main {
width: 100%;
height: 100%;
overflow: hidden;
background-color: @component-background;
border: 0;
box-sizing: border-box;
border-radius: 5px;
}
}
</style>

View File

@@ -0,0 +1,24 @@
<template>
<div v-if="showFrame">
<template v-for="frame in getFramePages" :key="frame.path">
<template v-if="frame.meta.frameSrc && showIframe(frame)">
<FramePage :frame="frame" :fullHeight="true" />
</template>
</template>
</div>
</template>
<script lang="ts">
import { computed, defineComponent, unref } from 'vue';
import FramePage from '@jeesite/core/layouts/iframe/FramePage.vue';
import { useFrameKeepAlive } from '@jeesite/core/layouts/iframe/useFrameKeepAlive';
export default defineComponent({
name: 'FrameSimple',
components: { FramePage },
setup() {
const { getFramePages, hasRenderFrame, showIframe } = useFrameKeepAlive();
const showFrame = computed(() => unref(getFramePages).length > 0);
return { getFramePages, hasRenderFrame, showIframe, showFrame };
},
});
</script>

View File

@@ -0,0 +1,25 @@
<template>
<div v-if="showFrame">
<template v-for="frame in getFramePages" :key="frame.path">
<FramePage v-if="frame.meta.frameSrc && hasRenderFrame(frame.name)" v-show="showIframe(frame)" :frame="frame" />
</template>
</div>
</template>
<script lang="ts">
import { defineComponent, unref, computed } from 'vue';
import FramePage from '@jeesite/core/layouts/iframe/FramePage.vue';
import { useFrameKeepAlive } from './useFrameKeepAlive';
export default defineComponent({
name: 'FrameLayout',
components: { FramePage },
setup() {
const { getFramePages, hasRenderFrame, showIframe } = useFrameKeepAlive();
const showFrame = computed(() => unref(getFramePages).length > 0);
return { getFramePages, hasRenderFrame, showIframe, showFrame };
},
});
</script>

View File

@@ -0,0 +1,105 @@
import type { AppRouteRecordRaw } from '@jeesite/core/router/types';
import { computed, toRaw, ref, unref } from 'vue';
import { useMultipleTabStore } from '@jeesite/core/store/modules/multipleTab';
import { uniqBy } from 'lodash-es';
import { useMultipleTabSetting } from '@jeesite/core/hooks/setting/useMultipleTabSetting';
import { useFullContent } from '@jeesite/core/hooks/web/useFullContent';
import { RouteRecordRaw, useRouter } from 'vue-router';
import { LAYOUT, IFRAME_BLANK } from '@jeesite/core/router/constant';
import { router } from '@jeesite/core/router';
const framePages = ref<AppRouteRecordRaw[]>();
const tempFramePages = ref<AppRouteRecordRaw[]>();
export function useFrameKeepAlive() {
const router = useRouter();
const { currentRoute } = router;
const { getShowMultipleTab } = useMultipleTabSetting();
const { getFullContent } = useFullContent();
const tabStore = useMultipleTabStore();
const getFramePages = computed(() => {
if (!unref(framePages.value)) {
framePages.value = getAllFramePages(toRaw(router.getRoutes()) as AppRouteRecordRaw[]);
}
return [...(framePages.value || []), ...(tempFramePages.value || [])];
});
const getOpenTabList = computed((): string[] => {
return tabStore.getTabList.reduce((prev: string[], next) => {
if (next.meta && Reflect.has(next.meta, 'frameSrc')) {
prev.push(next.name as string);
}
return prev;
}, []);
});
function getAllFramePages(routes: AppRouteRecordRaw[]): AppRouteRecordRaw[] {
let res: AppRouteRecordRaw[] = [];
for (const route of routes) {
const { meta: { frameSrc } = {}, children } = route;
if (frameSrc && !route.name.startsWith('JeeSite')) {
res.push(route);
}
if (children && children.length) {
res.push(...getAllFramePages(children));
}
}
res = uniqBy(res, 'name');
return (res || []) as AppRouteRecordRaw[];
}
function showIframe(item: AppRouteRecordRaw) {
return item.name === unref(currentRoute).name;
}
function hasRenderFrame(name: string) {
if (!unref(getShowMultipleTab) || unref(getFullContent)) {
return router.currentRoute.value.name === name;
}
return unref(getOpenTabList).includes(name);
}
return { hasRenderFrame, getFramePages, showIframe, getAllFramePages };
}
export function initFramePage() {
tempFramePages.value = JSON.parse(sessionStorage.getItem('temp-frame-pages') || '[]');
tempFramePages.value?.forEach((r) => addFramePage(r, false));
return addFramePage;
}
function addFramePage(route: AppRouteRecordRaw, store = true) {
if (store) {
let array = tempFramePages.value || [];
if (array.length > 10) {
array = array.slice(-10);
}
for (let i = array.length - 1; i >= 0; i--) {
if (array[i].name === route.name) {
array.splice(i, 1);
}
}
const currentRoute = router.currentRoute.value;
route.meta.currentActiveMenu = currentRoute.meta.currentActiveMenu || currentRoute.path;
array.push(route);
tempFramePages.value = array;
sessionStorage.setItem('temp-frame-pages', JSON.stringify(array));
}
router.addRoute({
component: LAYOUT,
meta: { single: true, affix: false },
name: `${route.name}Parent`,
children: [
{
component: IFRAME_BLANK,
...route,
},
],
} as unknown as RouteRecordRaw);
}