mirror of
https://github.com/Tencent/tdesign-vue-next-starter.git
synced 2024-12-23 14:40:12 +08:00
Merge branch 'develop' of github.com:Tencent/tdesign-vue-next-starter into main
This commit is contained in:
commit
5797d6926a
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "tdesign-vue-next-starter",
|
"name": "tdesign-vue-next-starter",
|
||||||
"version": "0.6.0",
|
"version": "0.6.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev:mock": "vite --open --mode mock",
|
"dev:mock": "vite --open --mode mock",
|
||||||
"dev": "vite --open --mode development",
|
"dev": "vite --open --mode development",
|
||||||
|
@ -24,11 +24,11 @@
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"nprogress": "^0.2.0",
|
"nprogress": "^0.2.0",
|
||||||
"pinia": "^2.0.11",
|
"pinia": "^2.0.11",
|
||||||
"pinia-plugin-persistedstate": "^2.1.1",
|
"pinia-plugin-persistedstate": "^3.0.1",
|
||||||
"qrcode.vue": "^3.2.2",
|
"qrcode.vue": "^3.2.2",
|
||||||
"qs": "^6.10.5",
|
"qs": "^6.10.5",
|
||||||
"tdesign-icons-vue-next": "^0.1.1",
|
"tdesign-icons-vue-next": "^0.1.1",
|
||||||
"tdesign-vue-next": "^0.24.9",
|
"tdesign-vue-next": "^0.26.2",
|
||||||
"tvision-color": "^1.3.1",
|
"tvision-color": "^1.3.1",
|
||||||
"vue": "^3.2.31",
|
"vue": "^3.2.31",
|
||||||
"vue-clipboard3": "^2.0.0",
|
"vue-clipboard3": "^2.0.0",
|
||||||
|
|
|
@ -55,7 +55,7 @@
|
||||||
</t-card>
|
</t-card>
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { PropType } from 'vue';
|
import type { PropType } from 'vue';
|
||||||
import {
|
import {
|
||||||
ShopIcon,
|
ShopIcon,
|
||||||
CalendarIcon,
|
CalendarIcon,
|
||||||
|
|
34
src/hooks/event/useWindowSizeFn.ts
Normal file
34
src/hooks/event/useWindowSizeFn.ts
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import debounce from 'lodash/debounce';
|
||||||
|
import { onUnmounted, onMounted } from 'vue';
|
||||||
|
|
||||||
|
interface WindowSizeOptions {
|
||||||
|
immediate?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Fn<T = any, R = T> {
|
||||||
|
(...arg: T[]): R;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useWindowSizeFn<T>(fn: Fn<T>, options?: WindowSizeOptions, wait = 150) {
|
||||||
|
const handleSize: () => void = debounce(fn, wait);
|
||||||
|
|
||||||
|
const start = () => {
|
||||||
|
if (options && options.immediate) {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
window.addEventListener('resize', handleSize);
|
||||||
|
};
|
||||||
|
|
||||||
|
const stop = () => {
|
||||||
|
window.removeEventListener('resize', handleSize);
|
||||||
|
};
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
start();
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
stop();
|
||||||
|
});
|
||||||
|
return [start, stop];
|
||||||
|
}
|
|
@ -6,11 +6,14 @@
|
||||||
</keep-alive>
|
</keep-alive>
|
||||||
</transition>
|
</transition>
|
||||||
</router-view>
|
</router-view>
|
||||||
|
<frame-page />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, ComputedRef } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
import type { ComputedRef } from 'vue';
|
||||||
import { useTabsRouterStore } from '@/store';
|
import { useTabsRouterStore } from '@/store';
|
||||||
|
import FramePage from '@/layouts/frame/index.vue';
|
||||||
|
|
||||||
// <suspense>标签属于实验性功能,请谨慎使用
|
// <suspense>标签属于实验性功能,请谨慎使用
|
||||||
// 如果存在需解决/page/1=> /page/2 刷新数据问题 请修改代码 使用activeRouteFullPath 作为key
|
// 如果存在需解决/page/1=> /page/2 刷新数据问题 请修改代码 使用activeRouteFullPath 作为key
|
||||||
|
|
10
src/layouts/components/FrameBlank.vue
Normal file
10
src/layouts/components/FrameBlank.vue
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
<template>
|
||||||
|
<div></div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent } from 'vue';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'FrameBlank',
|
||||||
|
});
|
||||||
|
</script>
|
99
src/layouts/components/FrameContent.vue
Normal file
99
src/layouts/components/FrameContent.vue
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
<template>
|
||||||
|
<div :class="prefixCls" :style="getWrapStyle">
|
||||||
|
<t-loading :loading="loading" size="large" :style="getWrapStyle">
|
||||||
|
<iframe ref="frameRef" :src="frameSrc" :class="`${prefixCls}__main`" @load="hideLoading"></iframe>
|
||||||
|
</t-loading>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts" setup>
|
||||||
|
import { CSSProperties, watch, ref, unref, computed } from 'vue';
|
||||||
|
import debounce from 'lodash/debounce';
|
||||||
|
import { useWindowSizeFn } from '@/hooks/event/useWindowSizeFn';
|
||||||
|
import { prefix } from '@/config/global';
|
||||||
|
import { useSettingStore } from '@/store';
|
||||||
|
|
||||||
|
defineProps({
|
||||||
|
frameSrc: String,
|
||||||
|
});
|
||||||
|
|
||||||
|
const loading = ref(true);
|
||||||
|
const heightRef = ref(window.innerHeight);
|
||||||
|
const frameRef = ref<HTMLFrameElement>();
|
||||||
|
const prefixCls = computed(() => [`${prefix}-iframe-page`]);
|
||||||
|
const settingStore = useSettingStore();
|
||||||
|
|
||||||
|
const getWrapStyle = computed((): CSSProperties => {
|
||||||
|
return {
|
||||||
|
height: `${unref(heightRef)}px`,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const computedStyle = getComputedStyle(document.documentElement);
|
||||||
|
const sizeXxxl = computedStyle.getPropertyValue('--td-comp-size-xxxl');
|
||||||
|
const paddingTBXxl = computedStyle.getPropertyValue('--td-comp-paddingTB-xxl');
|
||||||
|
|
||||||
|
function getOuterHeight(dom: Element) {
|
||||||
|
let height = dom.clientHeight;
|
||||||
|
const computedStyle = window.getComputedStyle(dom);
|
||||||
|
height += parseInt(computedStyle.marginTop, 10);
|
||||||
|
height += parseInt(computedStyle.marginBottom, 10);
|
||||||
|
height += parseInt(computedStyle.borderTopWidth, 10);
|
||||||
|
height += parseInt(computedStyle.borderBottomWidth, 10);
|
||||||
|
return height;
|
||||||
|
}
|
||||||
|
|
||||||
|
function calcHeight() {
|
||||||
|
const iframe = unref(frameRef);
|
||||||
|
if (!iframe) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let clientHeight = 0;
|
||||||
|
const { showFooter, isUseTabsRouter, showBreadcrumb } = settingStore;
|
||||||
|
const headerHeight = parseFloat(sizeXxxl);
|
||||||
|
const navDom = document.querySelector('.t-tabs__nav');
|
||||||
|
const navHeight = isUseTabsRouter ? getOuterHeight(navDom) : 0;
|
||||||
|
const breadcrumbDom = document.querySelector('.t-breadcrumb');
|
||||||
|
const breadcrumbHeight = showBreadcrumb ? getOuterHeight(breadcrumbDom) : 0;
|
||||||
|
const contentPadding = parseFloat(paddingTBXxl) * 2;
|
||||||
|
const footerDom = document.querySelector('.t-layout__footer');
|
||||||
|
const footerHeight = showFooter ? getOuterHeight(footerDom) : 0;
|
||||||
|
const top = headerHeight + navHeight + breadcrumbHeight + contentPadding + footerHeight + 2;
|
||||||
|
heightRef.value = window.innerHeight - top;
|
||||||
|
clientHeight = document.documentElement.clientHeight - top;
|
||||||
|
iframe.style.height = `${clientHeight}px`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hideLoading() {
|
||||||
|
loading.value = false;
|
||||||
|
calcHeight();
|
||||||
|
}
|
||||||
|
|
||||||
|
useWindowSizeFn(calcHeight, { immediate: true });
|
||||||
|
|
||||||
|
watch(
|
||||||
|
[() => settingStore.showFooter, () => settingStore.isUseTabsRouter, () => settingStore.showBreadcrumb],
|
||||||
|
debounce(calcHeight, 250),
|
||||||
|
);
|
||||||
|
</script>
|
||||||
|
<style lang="less" scoped>
|
||||||
|
@prefix-cls: ~'@{starter-prefix}-iframe-page';
|
||||||
|
|
||||||
|
.@{prefix-cls} {
|
||||||
|
&__mask {
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__main {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
background-color: #fff;
|
||||||
|
border: 0;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -64,13 +64,14 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { PropType, computed } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
import type { PropType } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { useSettingStore } from '@/store';
|
import { useSettingStore } from '@/store';
|
||||||
import { getActive } from '@/router';
|
import { getActive } from '@/router';
|
||||||
import { prefix } from '@/config/global';
|
import { prefix } from '@/config/global';
|
||||||
import LogoFull from '@/assets/assets-logo-full.svg?component';
|
import LogoFull from '@/assets/assets-logo-full.svg?component';
|
||||||
import { MenuRoute } from '@/types/interface';
|
import type { MenuRoute } from '@/types/interface';
|
||||||
|
|
||||||
import Notice from './Notice.vue';
|
import Notice from './Notice.vue';
|
||||||
import Search from './Search.vue';
|
import Search from './Search.vue';
|
||||||
|
@ -143,7 +144,10 @@ const handleNav = (url) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleLogout = () => {
|
const handleLogout = () => {
|
||||||
router.push(`/login?redirect=${router.currentRoute.value.fullPath}`);
|
router.push({
|
||||||
|
path: '/login',
|
||||||
|
query: { redirect: encodeURIComponent(router.currentRoute.value.fullPath) },
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const navToGitHub = () => {
|
const navToGitHub = () => {
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
:min-column-width="128"
|
:min-column-width="128"
|
||||||
:popup-props="{
|
:popup-props="{
|
||||||
overlayClassName: 'route-tabs-dropdown',
|
overlayClassName: 'route-tabs-dropdown',
|
||||||
onVisibleChange: (visible: boolean, ctx) => handleTabMenuClick(visible, ctx, routeItem.path),
|
onVisibleChange: (visible, ctx) => handleTabMenuClick(visible, ctx, routeItem.path),
|
||||||
visible: activeTabPath === routeItem.path,
|
visible: activeTabPath === routeItem.path,
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
|
@ -71,7 +71,7 @@ import { nextTick, ref, computed } from 'vue';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import { useSettingStore, useTabsRouterStore } from '@/store';
|
import { useSettingStore, useTabsRouterStore } from '@/store';
|
||||||
import { prefix } from '@/config/global';
|
import { prefix } from '@/config/global';
|
||||||
import { TRouterInfo } from '@/types/interface';
|
import type { TRouterInfo } from '@/types/interface';
|
||||||
|
|
||||||
import LContent from './Content.vue';
|
import LContent from './Content.vue';
|
||||||
import LBreadcrumb from './Breadcrumb.vue';
|
import LBreadcrumb from './Breadcrumb.vue';
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<div>
|
<div>
|
||||||
<template v-for="item in list" :key="item.path">
|
<template v-for="item in list" :key="item.path">
|
||||||
<template v-if="!item.children || !item.children.length || item.meta?.single">
|
<template v-if="!item.children || !item.children.length || item.meta?.single">
|
||||||
<t-menu-item v-if="getHref(item)" :href="getHref(item)?.[0]" :name="item.path" :value="getPath(item)">
|
<t-menu-item v-if="getHref(item)" :name="item.path" :value="getPath(item)" @click="openHref(getHref(item)[0])">
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<t-icon v-if="beIcon(item)" :name="item.icon" />
|
<t-icon v-if="beIcon(item)" :name="item.icon" />
|
||||||
<component :is="beRender(item).render" v-else-if="beRender(item).can" class="t-icon" />
|
<component :is="beRender(item).render" v-else-if="beRender(item).can" class="t-icon" />
|
||||||
|
@ -29,9 +29,10 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, PropType } from 'vue';
|
import { computed } from 'vue';
|
||||||
|
import type { PropType } from 'vue';
|
||||||
import isObject from 'lodash/isObject';
|
import isObject from 'lodash/isObject';
|
||||||
import { MenuRoute } from '@/types/interface';
|
import type { MenuRoute } from '@/types/interface';
|
||||||
import { getActive } from '@/router';
|
import { getActive } from '@/router';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
|
@ -47,7 +48,9 @@ const list = computed(() => {
|
||||||
return getMenuList(navData);
|
return getMenuList(navData);
|
||||||
});
|
});
|
||||||
|
|
||||||
const getMenuList = (list: MenuRoute[], basePath?: string): MenuRoute[] => {
|
type ListItemType = MenuRoute & { icon?: string };
|
||||||
|
|
||||||
|
const getMenuList = (list: MenuRoute[], basePath?: string): ListItemType[] => {
|
||||||
if (!list) {
|
if (!list) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
@ -71,7 +74,11 @@ const getMenuList = (list: MenuRoute[], basePath?: string): MenuRoute[] => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const getHref = (item: MenuRoute) => {
|
const getHref = (item: MenuRoute) => {
|
||||||
return item.path.match(/(http|https):\/\/([\w.]+\/?)\S*/);
|
const { frameSrc, frameBlank } = item.meta;
|
||||||
|
if (frameSrc && frameBlank) {
|
||||||
|
return frameSrc.match(/(http|https):\/\/([\w.]+\/?)\S*/);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
};
|
};
|
||||||
|
|
||||||
const getPath = (item) => {
|
const getPath = (item) => {
|
||||||
|
@ -97,6 +104,10 @@ const beRender = (item: MenuRoute) => {
|
||||||
render: null,
|
render: null,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const openHref = (url: string) => {
|
||||||
|
window.open(url);
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped></style>
|
<style lang="less" scoped></style>
|
||||||
|
|
|
@ -49,7 +49,7 @@
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { useNotificationStore } from '@/store';
|
import { useNotificationStore } from '@/store';
|
||||||
import { NotificationItem } from '@/types/interface';
|
import type { NotificationItem } from '@/types/interface';
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
const store = useNotificationStore();
|
const store = useNotificationStore();
|
||||||
|
|
|
@ -16,14 +16,15 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { computed, onMounted, PropType } from 'vue';
|
import { computed, onMounted } from 'vue';
|
||||||
|
import type { PropType } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import union from 'lodash/union';
|
import union from 'lodash/union';
|
||||||
|
|
||||||
import { useSettingStore } from '@/store';
|
import { useSettingStore } from '@/store';
|
||||||
import { prefix } from '@/config/global';
|
import { prefix } from '@/config/global';
|
||||||
import pgk from '../../../package.json';
|
import pgk from '../../../package.json';
|
||||||
import { MenuRoute } from '@/types/interface';
|
import type { MenuRoute } from '@/types/interface';
|
||||||
import { getActive, getRoutesExpanded } from '@/router';
|
import { getActive, getRoutesExpanded } from '@/router';
|
||||||
|
|
||||||
import AssetLogo from '@/assets/assets-t-logo.svg?component';
|
import AssetLogo from '@/assets/assets-t-logo.svg?component';
|
||||||
|
@ -54,7 +55,7 @@ const props = defineProps({
|
||||||
default: '64px',
|
default: '64px',
|
||||||
},
|
},
|
||||||
theme: {
|
theme: {
|
||||||
type: String as PropType<string>,
|
type: String as PropType<'light' | 'dark'>,
|
||||||
default: 'light',
|
default: 'light',
|
||||||
},
|
},
|
||||||
isCompact: {
|
isCompact: {
|
||||||
|
|
25
src/layouts/frame/index.vue
Normal file
25
src/layouts/frame/index.vue
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<template>
|
||||||
|
<div v-if="showFrame">
|
||||||
|
<template v-for="frame in getFramePages" :key="frame.path">
|
||||||
|
<frame-content v-if="hasRenderFrame(frame.name)" v-show="showIframe(frame)" :frame-src="frame.meta.frameSrc" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script lang="ts">
|
||||||
|
import { defineComponent, unref, computed } from 'vue';
|
||||||
|
import FrameContent from '../components/FrameContent.vue';
|
||||||
|
|
||||||
|
import { useFrameKeepAlive } from './useFrameKeepAlive';
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'FrameLayout',
|
||||||
|
components: { FrameContent },
|
||||||
|
setup() {
|
||||||
|
const { getFramePages, hasRenderFrame, showIframe } = useFrameKeepAlive();
|
||||||
|
|
||||||
|
const showFrame = computed(() => unref(getFramePages).length > 0);
|
||||||
|
|
||||||
|
return { getFramePages, hasRenderFrame, showIframe, showFrame };
|
||||||
|
},
|
||||||
|
});
|
||||||
|
</script>
|
53
src/layouts/frame/useFrameKeepAlive.ts
Normal file
53
src/layouts/frame/useFrameKeepAlive.ts
Normal file
|
@ -0,0 +1,53 @@
|
||||||
|
import { computed, toRaw, unref } from 'vue';
|
||||||
|
import uniqBy from 'lodash/uniqBy';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
import { useSettingStore, useTabsRouterStore } from '@/store';
|
||||||
|
import type { MenuRoute } from '@/types/interface';
|
||||||
|
|
||||||
|
export function useFrameKeepAlive() {
|
||||||
|
const router = useRouter();
|
||||||
|
const { currentRoute } = router;
|
||||||
|
const { isUseTabsRouter } = useSettingStore();
|
||||||
|
const tabStore = useTabsRouterStore();
|
||||||
|
const getFramePages = computed(() => {
|
||||||
|
const ret = getAllFramePages(toRaw(router.getRoutes()) as unknown as MenuRoute[]) || [];
|
||||||
|
return ret;
|
||||||
|
});
|
||||||
|
|
||||||
|
const getOpenTabList = computed((): string[] => {
|
||||||
|
return tabStore.tabRouters.reduce((prev: string[], next) => {
|
||||||
|
if (next.meta && Reflect.has(next.meta, 'frameSrc')) {
|
||||||
|
prev.push(next.name as string);
|
||||||
|
}
|
||||||
|
return prev;
|
||||||
|
}, []);
|
||||||
|
});
|
||||||
|
|
||||||
|
function getAllFramePages(routes: MenuRoute[]): MenuRoute[] {
|
||||||
|
let res: MenuRoute[] = [];
|
||||||
|
for (const route of routes) {
|
||||||
|
const { meta: { frameSrc, frameBlank } = {}, children } = route;
|
||||||
|
if (frameSrc && !frameBlank) {
|
||||||
|
res.push(route);
|
||||||
|
}
|
||||||
|
if (children && children.length) {
|
||||||
|
res.push(...getAllFramePages(children));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res = uniqBy(res, 'name');
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showIframe(item: MenuRoute) {
|
||||||
|
return item.name === unref(currentRoute).name;
|
||||||
|
}
|
||||||
|
|
||||||
|
function hasRenderFrame(name: string) {
|
||||||
|
if (!unref(isUseTabsRouter)) {
|
||||||
|
return router.currentRoute.value.name === name;
|
||||||
|
}
|
||||||
|
return unref(getOpenTabList).includes(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return { hasRenderFrame, getFramePages, showIframe, getAllFramePages };
|
||||||
|
}
|
|
@ -56,7 +56,7 @@ const appendNewRoute = () => {
|
||||||
meta: { title },
|
meta: { title },
|
||||||
name,
|
name,
|
||||||
} = route;
|
} = route;
|
||||||
tabsRouterStore.appendTabRouterList({ path, query, title: title as string, name, isAlive: true });
|
tabsRouterStore.appendTabRouterList({ path, query, title: title as string, name, isAlive: true, meta: route.meta });
|
||||||
};
|
};
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
|
|
|
@ -100,7 +100,8 @@
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, onMounted, watchEffect } from 'vue';
|
import { ref, computed, onMounted, watchEffect } from 'vue';
|
||||||
import { MessagePlugin, PopupVisibleChangeContext } from 'tdesign-vue-next';
|
import { MessagePlugin } from 'tdesign-vue-next';
|
||||||
|
import type { PopupVisibleChangeContext } from 'tdesign-vue-next';
|
||||||
import { Color } from 'tvision-color';
|
import { Color } from 'tvision-color';
|
||||||
import useClipboard from 'vue-clipboard3';
|
import useClipboard from 'vue-clipboard3';
|
||||||
|
|
||||||
|
|
|
@ -119,8 +119,8 @@ export const TABLE_COLUMNS_DATA = [
|
||||||
sorter: (a, b) => Date.parse(a.updateTime) - Date.parse(b.updateTime),
|
sorter: (a, b) => Date.parse(a.updateTime) - Date.parse(b.updateTime),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left' as const,
|
||||||
fixed: 'right',
|
fixed: 'right' as const,
|
||||||
width: 200,
|
width: 200,
|
||||||
className: 'test2',
|
className: 'test2',
|
||||||
colKey: 'op',
|
colKey: 'op',
|
||||||
|
|
|
@ -104,12 +104,12 @@ export const TABLE_COLUMNS = [
|
||||||
sorter: (a, b) => Date.parse(a.updateTime) - Date.parse(b.updateTime),
|
sorter: (a, b) => Date.parse(a.updateTime) - Date.parse(b.updateTime),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
align: 'left',
|
align: 'left' as const,
|
||||||
width: '200',
|
width: '200',
|
||||||
className: 'test2',
|
className: 'test2',
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
colKey: 'op',
|
colKey: 'op',
|
||||||
fixed: 'right',
|
fixed: 'right' as const,
|
||||||
title: '操作',
|
title: '操作',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
|
@ -60,7 +60,7 @@ export default {
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { storeToRefs } from 'pinia';
|
import { storeToRefs } from 'pinia';
|
||||||
import { NOTIFICATION_TYPES } from '@/constants';
|
import { NOTIFICATION_TYPES } from '@/constants';
|
||||||
import { NotificationItem } from '@/types/interface';
|
import type { NotificationItem } from '@/types/interface';
|
||||||
import EmptyIcon from '@/assets/assets-empty.svg?component';
|
import EmptyIcon from '@/assets/assets-empty.svg?component';
|
||||||
import { useNotificationStore } from '@/store';
|
import { useNotificationStore } from '@/store';
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
export const FORM_RULES = {
|
import { FormRule } from 'tdesign-vue-next';
|
||||||
|
|
||||||
|
export const FORM_RULES: Record<string, FormRule[]> = {
|
||||||
name: [{ required: true, message: '请输入合同名称', type: 'error' }],
|
name: [{ required: true, message: '请输入合同名称', type: 'error' }],
|
||||||
type: [{ required: true, message: '请选择合同类型', type: 'error' }],
|
type: [{ required: true, message: '请选择合同类型', type: 'error' }],
|
||||||
payment: [{ required: true, message: '请选择合同收付类型', type: 'error' }],
|
payment: [{ required: true, message: '请选择合同收付类型', type: 'error' }],
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
export const FORM_RULES = {
|
import { FormRule } from 'tdesign-vue-next';
|
||||||
|
|
||||||
|
export const FORM_RULES: Record<string, FormRule[]> = {
|
||||||
name: [{ required: true, message: '请选择合同名称', type: 'error' }],
|
name: [{ required: true, message: '请选择合同名称', type: 'error' }],
|
||||||
type: [{ required: true, message: '请选择发票类型', type: 'error' }],
|
type: [{ required: true, message: '请选择发票类型', type: 'error' }],
|
||||||
title: [{ required: true, message: '请输入发票抬头', type: 'error' }],
|
title: [{ required: true, message: '请输入发票抬头', type: 'error' }],
|
||||||
|
|
|
@ -149,7 +149,7 @@ export default {
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed } from 'vue';
|
import { ref, computed } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRouter } from 'vue-router';
|
||||||
import { ValidateResultContext } from 'tdesign-vue-next';
|
import { SubmitContext, Data } from 'tdesign-vue-next';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
FORM_RULES,
|
FORM_RULES,
|
||||||
|
@ -179,7 +179,7 @@ const amount = computed(() => {
|
||||||
return '--';
|
return '--';
|
||||||
});
|
});
|
||||||
|
|
||||||
const onSubmit = (result: ValidateResultContext<FormData>, val: number) => {
|
const onSubmit = (result: SubmitContext<Data>, val: number) => {
|
||||||
if (result.validateResult === true) {
|
if (result.validateResult === true) {
|
||||||
activeForm.value = val;
|
activeForm.value = val;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
export const COLUMNS = [
|
import { PrimaryTableCol, TableRowData } from 'tdesign-vue-next';
|
||||||
|
|
||||||
|
export const COLUMNS: PrimaryTableCol<TableRowData>[] = [
|
||||||
{ colKey: 'row-select', type: 'multiple', width: 64, fixed: 'left' },
|
{ colKey: 'row-select', type: 'multiple', width: 64, fixed: 'left' },
|
||||||
{
|
{
|
||||||
title: '合同名称',
|
title: '合同名称',
|
||||||
|
@ -7,7 +9,7 @@ export const COLUMNS = [
|
||||||
colKey: 'name',
|
colKey: 'name',
|
||||||
fixed: 'left',
|
fixed: 'left',
|
||||||
},
|
},
|
||||||
{ title: '合同状态', colKey: 'status', width: 200, cell: { col: 'status' } },
|
{ title: '合同状态', colKey: 'status', width: 200 },
|
||||||
{
|
{
|
||||||
title: '合同编号',
|
title: '合同编号',
|
||||||
width: 200,
|
width: 200,
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
:selected-row-keys="selectedRowKeys"
|
:selected-row-keys="selectedRowKeys"
|
||||||
:loading="dataLoading"
|
:loading="dataLoading"
|
||||||
:header-affixed-top="{ offsetTop, container: getContainer }"
|
:header-affixed-top="headerAffixedTop"
|
||||||
@page-change="rehandlePageChange"
|
@page-change="rehandlePageChange"
|
||||||
@change="rehandleChange"
|
@change="rehandleChange"
|
||||||
@select-change="rehandleSelectChange"
|
@select-change="rehandleSelectChange"
|
||||||
|
@ -177,13 +177,13 @@ const handleClickDelete = (row: { rowIndex: any }) => {
|
||||||
confirmVisible.value = true;
|
confirmVisible.value = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
const offsetTop = computed(() => {
|
const headerAffixedTop = computed(
|
||||||
return store.isUseTabsRouter ? 48 : 0;
|
() =>
|
||||||
});
|
({
|
||||||
|
offsetTop: store.isUseTabsRouter ? 48 : 0,
|
||||||
const getContainer = () => {
|
container: `.${prefix}-layout`,
|
||||||
return document.querySelector(`.${prefix}-layout`);
|
} as any),
|
||||||
};
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -36,7 +36,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, watch } from 'vue';
|
import { ref, watch } from 'vue';
|
||||||
import { MessagePlugin } from 'tdesign-vue-next';
|
import { MessagePlugin, FormRule, SubmitContext, Data } from 'tdesign-vue-next';
|
||||||
|
|
||||||
const INITIAL_DATA = {
|
const INITIAL_DATA = {
|
||||||
name: '',
|
name: '',
|
||||||
|
@ -70,12 +70,12 @@ const formVisible = ref(false);
|
||||||
const formData = ref(props.data);
|
const formData = ref(props.data);
|
||||||
const textareaValue = ref('');
|
const textareaValue = ref('');
|
||||||
|
|
||||||
const onSubmit = ({ result, firstError }) => {
|
const onSubmit = ({ validateResult, firstError }: SubmitContext<Data>) => {
|
||||||
if (!firstError) {
|
if (!firstError) {
|
||||||
MessagePlugin.success('提交成功');
|
MessagePlugin.success('提交成功');
|
||||||
formVisible.value = false;
|
formVisible.value = false;
|
||||||
} else {
|
} else {
|
||||||
console.log('Errors: ', result);
|
console.log('Errors: ', validateResult);
|
||||||
MessagePlugin.warning(firstError);
|
MessagePlugin.warning(firstError);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -107,7 +107,7 @@ watch(
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
const rules = {
|
const rules: Record<string, FormRule[]> = {
|
||||||
name: [{ required: true, message: '请输入产品名称', type: 'error' }],
|
name: [{ required: true, message: '请输入产品名称', type: 'error' }],
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
@ -73,7 +73,7 @@
|
||||||
:hover="hover"
|
:hover="hover"
|
||||||
:pagination="pagination"
|
:pagination="pagination"
|
||||||
:loading="dataLoading"
|
:loading="dataLoading"
|
||||||
:header-affixed-top="{ offsetTop, container: getContainer }"
|
:header-affixed-top="headerAffixedTop"
|
||||||
@page-change="rehandlePageChange"
|
@page-change="rehandlePageChange"
|
||||||
@change="rehandleChange"
|
@change="rehandleChange"
|
||||||
>
|
>
|
||||||
|
@ -114,7 +114,7 @@
|
||||||
</template>
|
</template>
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref, computed, onMounted } from 'vue';
|
import { ref, computed, onMounted } from 'vue';
|
||||||
import { MessagePlugin } from 'tdesign-vue-next';
|
import { MessagePlugin, PrimaryTableCol, TableRowData, PageInfo } from 'tdesign-vue-next';
|
||||||
import Trend from '@/components/trend/index.vue';
|
import Trend from '@/components/trend/index.vue';
|
||||||
import { getList } from '@/api/list';
|
import { getList } from '@/api/list';
|
||||||
import { useSettingStore } from '@/store';
|
import { useSettingStore } from '@/store';
|
||||||
|
@ -130,7 +130,7 @@ import {
|
||||||
|
|
||||||
const store = useSettingStore();
|
const store = useSettingStore();
|
||||||
|
|
||||||
const COLUMNS = [
|
const COLUMNS: PrimaryTableCol<TableRowData>[] = [
|
||||||
{
|
{
|
||||||
title: '合同名称',
|
title: '合同名称',
|
||||||
fixed: 'left',
|
fixed: 'left',
|
||||||
|
@ -139,7 +139,7 @@ const COLUMNS = [
|
||||||
align: 'left',
|
align: 'left',
|
||||||
colKey: 'name',
|
colKey: 'name',
|
||||||
},
|
},
|
||||||
{ title: '合同状态', colKey: 'status', width: 200, cell: { col: 'status' } },
|
{ title: '合同状态', colKey: 'status', width: 200 },
|
||||||
{
|
{
|
||||||
title: '合同编号',
|
title: '合同编号',
|
||||||
width: 200,
|
width: 200,
|
||||||
|
@ -182,7 +182,7 @@ const searchForm = {
|
||||||
|
|
||||||
const formData = ref({ ...searchForm });
|
const formData = ref({ ...searchForm });
|
||||||
const rowKey = 'index';
|
const rowKey = 'index';
|
||||||
const verticalAlign = 'top';
|
const verticalAlign = 'top' as const;
|
||||||
const hover = true;
|
const hover = true;
|
||||||
|
|
||||||
const pagination = ref({
|
const pagination = ref({
|
||||||
|
@ -251,8 +251,8 @@ const onReset = (val) => {
|
||||||
const onSubmit = (val) => {
|
const onSubmit = (val) => {
|
||||||
console.log(val);
|
console.log(val);
|
||||||
};
|
};
|
||||||
const rehandlePageChange = (curr, pageInfo) => {
|
const rehandlePageChange = (pageInfo: PageInfo, newDataSource: TableRowData[]) => {
|
||||||
console.log('分页变化', curr, pageInfo);
|
console.log('分页变化', pageInfo, newDataSource);
|
||||||
};
|
};
|
||||||
const rehandleChange = (changeParams, triggerAndData) => {
|
const rehandleChange = (changeParams, triggerAndData) => {
|
||||||
console.log('统一Change', changeParams, triggerAndData);
|
console.log('统一Change', changeParams, triggerAndData);
|
||||||
|
@ -261,13 +261,13 @@ const rehandleClickOp = ({ text, row }) => {
|
||||||
console.log(text, row);
|
console.log(text, row);
|
||||||
};
|
};
|
||||||
|
|
||||||
const offsetTop = computed(() => {
|
const headerAffixedTop = computed(
|
||||||
return store.isUseTabsRouter ? 48 : 0;
|
() =>
|
||||||
});
|
({
|
||||||
|
offsetTop: store.isUseTabsRouter ? 48 : 0,
|
||||||
const getContainer = () => {
|
container: `.${prefix}-layout`,
|
||||||
return document.querySelector(`.${prefix}-layout`);
|
} as any), // TO BE FIXED
|
||||||
};
|
);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="less" scoped>
|
<style lang="less" scoped>
|
||||||
|
|
|
@ -80,9 +80,10 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useRouter } from 'vue-router';
|
import { useRoute, useRouter } from 'vue-router';
|
||||||
import QrcodeVue from 'qrcode.vue';
|
import QrcodeVue from 'qrcode.vue';
|
||||||
import { FormInstanceFunctions, MessagePlugin } from 'tdesign-vue-next';
|
import { MessagePlugin } from 'tdesign-vue-next';
|
||||||
|
import type { FormInstanceFunctions, FormRule } from 'tdesign-vue-next';
|
||||||
import { useCounter } from '@/hooks';
|
import { useCounter } from '@/hooks';
|
||||||
import { useUserStore } from '@/store';
|
import { useUserStore } from '@/store';
|
||||||
|
|
||||||
|
@ -96,7 +97,7 @@ const INITIAL_DATA = {
|
||||||
checked: false,
|
checked: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const FORM_RULES = {
|
const FORM_RULES: Record<string, FormRule[]> = {
|
||||||
phone: [{ required: true, message: '手机号必填', type: 'error' }],
|
phone: [{ required: true, message: '手机号必填', type: 'error' }],
|
||||||
account: [{ required: true, message: '账号必填', type: 'error' }],
|
account: [{ required: true, message: '账号必填', type: 'error' }],
|
||||||
password: [{ required: true, message: '密码必填', type: 'error' }],
|
password: [{ required: true, message: '密码必填', type: 'error' }],
|
||||||
|
@ -116,6 +117,7 @@ const switchType = (val: string) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const router = useRouter();
|
const router = useRouter();
|
||||||
|
const route = useRoute();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 发送验证码
|
* 发送验证码
|
||||||
|
@ -134,9 +136,9 @@ const onSubmit = async ({ validateResult }) => {
|
||||||
await userStore.login(formData.value);
|
await userStore.login(formData.value);
|
||||||
|
|
||||||
MessagePlugin.success('登陆成功');
|
MessagePlugin.success('登陆成功');
|
||||||
router.push({
|
const redirect = route.query.redirect as string;
|
||||||
path: '/dashboard/base',
|
const redirectUrl = redirect ? decodeURIComponent(redirect) : '/dashboard';
|
||||||
});
|
router.push(redirectUrl);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
MessagePlugin.error(e.message);
|
MessagePlugin.error(e.message);
|
||||||
|
|
|
@ -72,7 +72,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { MessagePlugin } from 'tdesign-vue-next';
|
import { MessagePlugin, FormRule } from 'tdesign-vue-next';
|
||||||
import { useCounter } from '@/hooks';
|
import { useCounter } from '@/hooks';
|
||||||
|
|
||||||
const INITIAL_DATA = {
|
const INITIAL_DATA = {
|
||||||
|
@ -83,7 +83,7 @@ const INITIAL_DATA = {
|
||||||
checked: false,
|
checked: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
const FORM_RULES = {
|
const FORM_RULES: Record<string, FormRule[]> = {
|
||||||
phone: [{ required: true, message: '手机号必填', type: 'error' }],
|
phone: [{ required: true, message: '手机号必填', type: 'error' }],
|
||||||
email: [
|
email: [
|
||||||
{ required: true, message: '邮箱必填', type: 'error' },
|
{ required: true, message: '邮箱必填', type: 'error' },
|
||||||
|
|
|
@ -40,7 +40,10 @@ router.beforeEach(async (to, from, next) => {
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
MessagePlugin.error(error);
|
MessagePlugin.error(error);
|
||||||
next(`/login?redirect=${to.path}`);
|
next({
|
||||||
|
path: '/login',
|
||||||
|
query: { redirect: encodeURIComponent(to.fullPath) },
|
||||||
|
});
|
||||||
NProgress.done();
|
NProgress.done();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,7 +52,10 @@ router.beforeEach(async (to, from, next) => {
|
||||||
if (whiteListRouters.indexOf(to.path) !== -1) {
|
if (whiteListRouters.indexOf(to.path) !== -1) {
|
||||||
next();
|
next();
|
||||||
} else {
|
} else {
|
||||||
next(`/login?redirect=${to.path}`);
|
next({
|
||||||
|
path: '/login',
|
||||||
|
query: { redirect: encodeURIComponent(to.fullPath) },
|
||||||
|
});
|
||||||
}
|
}
|
||||||
NProgress.done();
|
NProgress.done();
|
||||||
}
|
}
|
||||||
|
|
47
src/router/modules/iframe.ts
Normal file
47
src/router/modules/iframe.ts
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import Layout from '@/layouts/index.vue';
|
||||||
|
|
||||||
|
const IFrame = () => import('@/layouts/components/FrameBlank.vue');
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
path: '/frame',
|
||||||
|
name: 'Frame',
|
||||||
|
component: Layout,
|
||||||
|
redirect: '/frame/doc',
|
||||||
|
meta: {
|
||||||
|
icon: 'internet',
|
||||||
|
title: '外部页面',
|
||||||
|
},
|
||||||
|
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
path: 'doc',
|
||||||
|
name: 'Doc',
|
||||||
|
component: IFrame,
|
||||||
|
meta: {
|
||||||
|
frameSrc: 'https://tdesign.tencent.com/starter/docs/vue-next/get-started',
|
||||||
|
title: '使用文档(内嵌)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'TDesign',
|
||||||
|
name: 'TDesign',
|
||||||
|
component: IFrame,
|
||||||
|
meta: {
|
||||||
|
frameSrc: 'https://tdesign.tencent.com/vue-next/getting-started',
|
||||||
|
title: 'TDesign 文档(内嵌)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'TDesign2',
|
||||||
|
name: 'TDesign2',
|
||||||
|
component: IFrame,
|
||||||
|
meta: {
|
||||||
|
frameSrc: 'https://tdesign.tencent.com/vue-next/getting-started',
|
||||||
|
frameBlank: true,
|
||||||
|
title: 'TDesign 文档(外链)',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
];
|
|
@ -1,5 +1,5 @@
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { NotificationItem } from '@/types/interface';
|
import type { NotificationItem } from '@/types/interface';
|
||||||
|
|
||||||
const msgData = [
|
const msgData = [
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,7 +19,7 @@ export const useSettingStore = defineStore('setting', {
|
||||||
showSidebar: (state) => state.layout !== 'top',
|
showSidebar: (state) => state.layout !== 'top',
|
||||||
showSidebarLogo: (state) => state.layout === 'side',
|
showSidebarLogo: (state) => state.layout === 'side',
|
||||||
showHeaderLogo: (state) => state.layout !== 'side',
|
showHeaderLogo: (state) => state.layout !== 'side',
|
||||||
displayMode: (state) => {
|
displayMode: (state): 'dark' | 'light' => {
|
||||||
if (state.mode === 'auto') {
|
if (state.mode === 'auto') {
|
||||||
const media = window.matchMedia('(prefers-color-scheme:dark)');
|
const media = window.matchMedia('(prefers-color-scheme:dark)');
|
||||||
if (media.matches) {
|
if (media.matches) {
|
||||||
|
@ -27,7 +27,7 @@ export const useSettingStore = defineStore('setting', {
|
||||||
}
|
}
|
||||||
return 'light';
|
return 'light';
|
||||||
}
|
}
|
||||||
return state.mode;
|
return state.mode as 'dark' | 'light';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { defineStore } from 'pinia';
|
import { defineStore } from 'pinia';
|
||||||
import { TRouterInfo, TTabRouterType } from '@/types/interface';
|
import type { TRouterInfo, TTabRouterType } from '@/types/interface';
|
||||||
import { store } from '@/store';
|
import { store } from '@/store';
|
||||||
|
|
||||||
const homeRoute: Array<TRouterInfo> = [
|
const homeRoute: Array<TRouterInfo> = [
|
||||||
|
|
|
@ -10,11 +10,18 @@
|
||||||
margin-left: var(--td-comp-margin-s);
|
margin-left: var(--td-comp-margin-s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.t-pagination-mini {
|
||||||
|
.t-button + .t-button {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.t-jumper {
|
.t-jumper {
|
||||||
.t-button + .t-button {
|
.t-button + .t-button {
|
||||||
margin-left: 0;
|
margin-left: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.@{starter-prefix}-link {
|
.@{starter-prefix}-link {
|
||||||
color: var(--td-brand-color);
|
color: var(--td-brand-color);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
@ -80,7 +87,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
&-layout {
|
&-layout {
|
||||||
height: calc(100vh - 64px);
|
height: calc(100vh - var(--td-comp-size-xxxl));
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
&-tabs-nav {
|
&-tabs-nav {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
|
|
2
src/types/interface.d.ts
vendored
2
src/types/interface.d.ts
vendored
|
@ -4,6 +4,7 @@ import STYLE_CONFIG from '@/config/style';
|
||||||
export interface MenuRoute {
|
export interface MenuRoute {
|
||||||
path: string;
|
path: string;
|
||||||
title?: string;
|
title?: string;
|
||||||
|
name?: string;
|
||||||
icon?:
|
icon?:
|
||||||
| string
|
| string
|
||||||
| {
|
| {
|
||||||
|
@ -42,6 +43,7 @@ export interface TRouterInfo {
|
||||||
name?: RouteRecordName;
|
name?: RouteRecordName;
|
||||||
isAlive?: boolean;
|
isAlive?: boolean;
|
||||||
isHome?: boolean;
|
isHome?: boolean;
|
||||||
|
meta?: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface TTabRouterType {
|
export interface TTabRouterType {
|
||||||
|
|
|
@ -17,7 +17,14 @@
|
||||||
"@/*": ["src/*"]
|
"@/*": ["src/*"]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"include": ["**/*.ts", "src/**/*.d.ts",
|
"include": [
|
||||||
"src/types/**/*.d.ts", "src/**/*.ts", "src/**/*.tsx", "src/**/*.vue"],
|
"**/*.ts",
|
||||||
|
"src/**/*.d.ts",
|
||||||
|
"src/types/**/*.d.ts",
|
||||||
|
"src/**/*.ts",
|
||||||
|
"src/**/*.tsx",
|
||||||
|
"src/**/*.vue",
|
||||||
|
"node_modules/tdesign-vue-next/global.d.ts"
|
||||||
|
],
|
||||||
"compileOnSave": false
|
"compileOnSave": false
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user