feat: 插件使用fes-design

This commit is contained in:
wanchun 2021-12-27 14:25:22 +08:00
parent abb28212df
commit 6782f5eedc
15 changed files with 396 additions and 503 deletions

View File

@ -31,8 +31,9 @@
},
"peerDependencies": {
"@ant-design/icons-vue": "^6.0.0",
"@fesjs/fes": "^2.0.0",
"ant-design-vue": "^2.2.0",
"@fesjs/fes": "^2.0.0",
"@fesjs/fes-design": "^0.1.2",
"vue": "^3.0.5"
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 33 KiB

After

Width:  |  Height:  |  Size: 50 KiB

View File

@ -1,4 +1,4 @@
import { unref, computed } from 'vue';
import { computed, ref } from 'vue';
// eslint-disable-next-line
import { useAccess } from '../../plugin-access/core';
@ -9,32 +9,26 @@ if (!useAccess) {
}
export const hasAccessByMenuItem = (item) => {
let res;
if (item.path && (!item.children || item.children.length === 0)) {
res = useAccess(item.path);
} else if (item.children && item.children.length > 0) {
res = computed(() => item.children.some((child) => {
const hasChild = item.children && item.children.length;
if (item.path && !hasChild) {
return useAccess(item.path);
}
if (hasChild) {
return computed(() => item.children.some((child) => {
const rst = hasAccessByMenuItem(child);
return rst && rst.value;
}));
}
return res;
return ref(true);
};
const _addAccessTag = (arr) => {
if (Array.isArray(arr)) {
arr.forEach((item) => {
item.access = hasAccessByMenuItem(item);
if (item.children && item.children.length > 0) {
_addAccessTag(item.children);
}
});
export const transform = menus => menus.map((menu) => {
const hasAccess = hasAccessByMenuItem(menu);
if (!hasAccess.value) {
return false;
}
};
export const transform = (menus) => {
const originData = unref(menus);
_addAccessTag(originData);
return originData;
};
if (menu.children) {
menu.children = transform(menu.children);
}
return menu;
}).filter(Boolean);

View File

@ -1,7 +1,5 @@
import { unref, computed } from 'vue';
import { plugin } from '@@/core/coreExports';
export const transTitle = (name) => {
const sharedLocale = plugin.getShared('locale');
if (sharedLocale) {
@ -12,22 +10,14 @@ export const transTitle = (name) => {
};
const _transform = (arr) => {
if (Array.isArray(arr)) {
arr.forEach((item) => {
if (item.title) {
item._title = item.title;
item.title = computed(() => transTitle(item._title));
}
if (item.children && item.children.length > 0) {
_transform(item.children);
}
});
export const transform = menus => menus.map((menu) => {
const copy = {
...menu,
_label: menu.label,
label: transTitle(menu.label)
};
if (menu.children) {
copy.children = transform(menu.children);
}
};
export const transform = (menus) => {
const originData = unref(menus);
_transform(originData);
return originData;
};
return copy;
});

View File

@ -1,7 +1,7 @@
<template>
<a-result status="403" title="403" sub-title="对不起您没有权限访问此页面">
<template #extra>
<a-button type="primary" @click="click">上一页</a-button>
<f-button type="primary" @click="click">上一页</f-button>
</template>
</a-result>
</template>
@ -14,13 +14,12 @@
import { useRouter } from '@@/core/coreExports';
import Result from 'ant-design-vue/lib/result';
import 'ant-design-vue/lib/result/style/css';
import Button from 'ant-design-vue/lib/button';
import 'ant-design-vue/lib/button/style/css';
import { FButton } from '@fesjs/fes-design';
export default {
components: {
[Result.name]: Result,
[Button.name]: Button
FButton
},
setup() {
const router = useRouter();

View File

@ -1,7 +1,7 @@
<template>
<a-result status="404" title="404" sub-title="对不起您访问的页面不存在">
<template #extra>
<a-button type="primary" @click="click">上一页</a-button>
<f-button type="primary" @click="click">上一页</f-button>
</template>
</a-result>
</template>
@ -14,13 +14,12 @@
import { useRouter } from '@@/core/coreExports';
import Result from 'ant-design-vue/lib/result';
import 'ant-design-vue/lib/result/style/css';
import Button from 'ant-design-vue/lib/button';
import 'ant-design-vue/lib/button/style/css';
import { FButton } from '@fesjs/fes-design';
export default {
components: {
[Result.name]: Result,
[Button.name]: Button
FButton
},
setup() {
const router = useRouter();

View File

@ -1,68 +1,126 @@
<template>
<a-layout
v-if="routeLayout"
:class="[
collapsed ? 'main-layout-collapsed' : '',
`main-layout-navigation-${navigation}`,
`main-layout-theme-${siderTheme}`
]"
class="main-layout"
>
<template v-if="navigation !== 'top' && routeLayout.side">
<div v-if="fixedSideBar" :style="siderFixedStuffStyle" class="layout-sider-fixed-stuff"></div>
<a-layout-sider
<f-layout v-if="routeLayout" class="main-layout">
<template v-if="navigation === 'side'">
<f-aside
v-if="routeLayout.side"
v-model:collapsed="collapsed"
:width="sideWidth"
:class="[
'layout-sider',
fixedSideBar ? 'layout-sider-fixed' : ''
]"
:theme="siderTheme"
:fixed="fixedSideBar"
class="layout-aside"
collapsible
:inverted="theme === 'dark'"
>
<div v-if="navigation !== 'mixin' && routeLayout.logo" class="layout-logo">
<div v-if="routeLayout.logo" class="layout-logo">
<img :src="logo" class="logo-img" />
<h1 class="logo-name">{{title}}</h1>
<div class="logo-name">{{title}}</div>
</div>
<Menu :menus="menus" :theme="siderTheme" />
</a-layout-sider>
</template>
<a-layout class="child-layout">
<a-layout-header v-if="currentFixedHeader && routeLayout.top" class="layout-header">
</a-layout-header>
<a-layout-header
v-if="routeLayout.top"
:style="headerFixedStyle"
:class="[currentFixedHeader ? 'layout-header-fixed' : '']"
class="layout-header"
>
<div v-if="navigation === 'mixin' && routeLayout.logo" class="layout-logo">
<img :src="logo" class="logo-img" />
<h1 class="logo-name">{{title}}</h1>
</div>
<template v-if="navigation === 'top'">
<div v-if="routeLayout.logo" class="layout-logo">
<img :src="logo" class="logo-img" />
<h1 class="logo-name">{{title}}</h1>
<Menu
class="layout-menu"
:menus="menus"
:collapsed="collapsed"
mode="vertical"
:inverted="theme === 'dark'"
/>
</f-aside>
<f-layout>
<f-header
v-if="routeLayout.top"
class="layout-header"
:fixed="currentFixedHeader"
>
<div class="layout-header-custom">
<slot name="customHeader"></slot>
</div>
<Menu :menus="menus" :theme="theme" class="layout-menu" mode="horizontal" />
</template>
<template v-if="locale">
<slot name="locale"></slot>
</template>
</f-header>
<f-main class="layout-main">
<MultiTabProvider v-if="multiTabs" />
<router-view v-else></router-view>
</f-main>
<f-footer v-if="footer" class="layout-footer">
{{footer}}
</f-footer>
</f-layout>
</template>
<template v-if="navigation === 'top'">
<f-header
v-if="routeLayout.top"
class="layout-header"
:inverted="theme === 'dark'"
:fixed="currentFixedHeader"
>
<div v-if="routeLayout.logo" class="layout-logo">
<img :src="logo" class="logo-img" />
<div class="logo-name">{{title}}</div>
</div>
<Menu
class="layout-menu"
:menus="menus"
mode="horizontal"
:inverted="theme === 'dark'"
/>
<div class="layout-header-custom">
<slot name="customHeader"></slot>
</div>
<template v-if="locale">
<slot name="locale"></slot>
</template>
</a-layout-header>
<a-layout-content class="layout-content">
</f-header>
<f-main class="layout-main">
<MultiTabProvider v-if="multiTabs" />
<router-view v-else></router-view>
</a-layout-content>
<a-layout-footer v-if="footer" class="layout-footer">
</f-main>
<f-footer v-if="footer" class="layout-footer">
{{footer}}
</a-layout-footer>
</a-layout>
</a-layout>
</f-footer>
</template>
<template v-if="navigation === 'mixin'">
<f-header
v-if="routeLayout.top"
class="layout-header"
:fixed="currentFixedHeader"
>
<div v-if="routeLayout.logo" class="layout-logo">
<img :src="logo" class="logo-img" />
<div class="logo-name">{{title}}</div>
</div>
<div class="layout-header-custom">
<slot name="customHeader"></slot>
</div>
<template v-if="locale">
<slot name="locale"></slot>
</template>
</f-header>
<f-layout>
<f-aside
v-if="routeLayout.side"
v-model:collapsed="collapsed"
:fixed="fixedSideBar"
collapsible
:inverted="theme === 'dark'"
class="layout-aside"
>
<Menu
class="layout-menu"
:menus="menus"
:collapsed="collapsed"
mode="vertical"
:inverted="theme === 'dark'"
/>
</f-aside>
<f-layout>
<f-main class="layout-main">
<MultiTabProvider v-if="multiTabs" />
<router-view v-else></router-view>
</f-main>
<f-footer v-if="footer" class="layout-footer">
{{footer}}
</f-footer>
</f-layout>
</f-layout>
</template>
</f-layout>
<div v-else class="content-wrapper">
<router-view></router-view>
</div>
@ -71,19 +129,20 @@
<script>
import { ref, computed } from 'vue';
import { useRoute, plugin, ApplyPluginsType } from '@@/core/coreExports';
import Layout from 'ant-design-vue/lib/layout';
import 'ant-design-vue/lib/layout/style/css';
import {
FLayout, FAside, FMain, FFooter, FHeader
} from '@fesjs/fes-design';
import Menu from './Menu';
import MultiTabProvider from './MultiTabProvider';
import defaultLogo from '../assets/logo.png';
export default {
components: {
[Layout.name]: Layout,
[Layout.Sider.name]: Layout.Sider,
[Layout.Content.name]: Layout.Content,
[Layout.Header.name]: Layout.Header,
[Layout.Footer.name]: Layout.Footer,
FLayout,
FAside,
FMain,
FFooter,
FHeader,
Menu,
MultiTabProvider
},
@ -153,7 +212,9 @@ export default {
} else if (typeof metaLayoutConfig === 'object') {
config = { ...runtimeConfig, ...metaLayoutConfig };
} else {
console.error('[plugin-layout]: meta layout must be object or boolean');
console.error(
'[plugin-layout]: meta layout must be object or boolean'
);
}
// query layout false
const routeQueryLayoutConfig = route.query.layout && JSON.parse(route.query.layout);
@ -162,159 +223,94 @@ export default {
} else if (typeof routeQueryLayoutConfig === 'object') {
config = { ...config, ...routeQueryLayoutConfig };
} else if (routeQueryLayoutConfig !== undefined) {
console.error('[plugin-layout]: query layout must be object or boolean');
console.error(
'[plugin-layout]: query layout must be object or boolean'
);
}
return config;
});
const siderTheme = computed(() => {
if (props.navigation === 'mixin') {
return 'light';
}
return props.theme;
});
const currentFixedHeader = computed(() => props.fixedHeader || props.navigation === 'mixin');
const siderFixedStuffStyle = computed(() => {
if (collapsed.value) {
const currentFixedHeader = computed(
() => props.fixedHeader || props.navigation === 'mixin'
);
const asideFixedStyle = computed(() => {
if (
routeLayout.value.top
&& props.navigation === 'mixin'
&& props.fixedSideBar
) {
return {
width: '80px'
top: '54px'
};
}
return {
width: `${props.sideWidth}px`
};
});
const headerFixedStyle = computed(() => {
if (!currentFixedHeader.value) {
return {};
}
if (props.navigation === 'side') {
return {
left: `${props.sideWidth}px`,
width: `calc(100% - ${props.sideWidth}px)`
};
}
return {
left: 0,
width: '100%'
};
return {};
});
// const sideTheme = computed(() => {
// if (props.navigation === 'mixin') {
// return 'light';
// }
// return props.theme;
// });
// const headerFixedStyle = computed(() => {
// if (!currentFixedHeader.value) {
// return {};
// }
// if (props.navigation === 'side') {
// return {
// left: `${props.sideWidth}px`,
// width: `calc(100% - ${props.sideWidth}px)`
// };
// }
// return {
// left: 0,
// width: '100%'
// };
// });
return {
siderTheme,
currentFixedHeader,
route,
routeLayout,
collapsed,
siderFixedStuffStyle,
headerFixedStyle
currentFixedHeader,
asideFixedStyle
// sideTheme,
// currentFixedHeader,
// siderFixedStuffStyle,
// headerFixedStyle
};
}
};
</script>
<style lang="less">
.main-layout.main-layout-navigation-mixin{
.layout-sider{
.ant-layout-sider-trigger {
border-top: 1px solid #f0f0f0;
}
}
}
</style>
<style lang="less" scoped>
.main-layout {
min-height: 100vh;
&.main-layout-collapsed {
.layout-sider {
.layout-logo {
justify-content: center;
.logo-name {
display: none;
}
.layout-header {
display: flex;
.layout-logo {
display: flex;
justify-content: flex-start;
align-items: center;
min-width: 165px;
height: 100%;
overflow: hidden;
transition: all 0.3s;
.logo-img {
height: 32px;
width: auto;
}
}
}
&.main-layout-navigation-top {
.layout-header {
padding-left: 24px;
color: hsla(0,0%,100%,.65);
background: #001529;
.layout-menu {
line-height: 48px;
}
.layout-logo {
display: flex;
justify-content: flex-start;
align-items: center;
min-width: 165px;
height: 100%;
.logo-name {
overflow: hidden;
transition: all .3s;
.logo-img {
height: 32px;
width: auto;
}
.logo-name {
overflow: hidden;
margin: 0 0 0 12px;
color: #fff;
font-weight: 600;
font-size: 18px;
line-height: 32px;
}
margin: 0 0 0 12px;
font-weight: 600;
font-size: 18px;
line-height: 32px;
}
}
}
&.main-layout-navigation-mixin {
.layout-sider {
padding: 48px 0 0;
box-shadow: 2px 0 8px 0 rgba(29,35,41,.05);
}
.layout-header {
padding-left: 24px;
color: hsla(0,0%,100%,.65);
background: #001529;
.layout-menu {
line-height: 48px;
}
.layout-logo {
display: flex;
justify-content: flex-start;
align-items: center;
min-width: 165px;
height: 100%;
overflow: hidden;
transition: all .3s;
.logo-img {
height: 32px;
width: auto;
}
.logo-name {
overflow: hidden;
margin: 0 0 0 12px;
color: #fff;
font-weight: 600;
font-size: 18px;
line-height: 32px;
}
}
.layout-header-custom {
flex: 1;
}
}
.layout-sider-fixed-stuff {
overflow: hidden;
transition: width 0.2s;
flex-shrink: 0;
}
.child-layout {
position: relative;
}
.layout-sider {
&.layout-sider-fixed {
position: fixed;
left: 0;
top: 0;
bottom: 0;
width: 200px;
}
.fes-layout-aside {
.layout-logo {
height: 32px;
margin: 16px;
@ -328,55 +324,29 @@ export default {
.logo-name {
overflow: hidden;
margin: 0 0 0 12px;
color: #fff;
font-weight: 600;
font-size: 18px;
line-height: 32px;
}
}
}
.layout-header {
position: relative;
z-index: 1;
display: flex;
align-items: center;
height: 48px;
line-height: 48px;
background: #fff;
box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08);
padding: 0;
.layout-header-custom {
flex: 1;
.layout-menu {
margin-top: 24px;
}
&.layout-header-fixed {
position: fixed;
top: 0;
right: 0;
z-index: 10;
&.is-collapsed {
.layout-logo {
justify-content: center;
.logo-name {
display: none;
}
}
}
}
.layout-content,
.content-wrapper {
position: relative;
}
.layout-footer {
text-align: center;
}
&.main-layout-theme-light{
.logo-name{
color: rgba(0, 0, 0, 0.65) !important;
}
&.main-layout-navigation-mixin{
.logo-name{
color: #fff !important;
}
}
&.main-layout-navigation-top{
.layout-header {
background: #fff;
color: rgba(0, 0, 0, 0.85);
}
}
}
}
.content-wrapper {
position: relative;
}
</style>

View File

@ -1,67 +1,24 @@
<template>
<a-menu
:selectedKeys="selectedKeys"
:theme="theme"
mode="inline"
@click="onMenuClick"
>
<template v-for="(item, index) in fixedMenus" :key="index">
<template v-if="item.access">
<a-sub-menu v-if="item.children" :key="index" :title="item.title">
<template v-if="item.icon" #icon>
<MenuIcon :icon="item.icon" />
</template>
<template
v-for="(item1, index1) in item.children"
>
<template v-if="item1.access">
<a-sub-menu
v-if="item1.children"
:key="`${index}-${index1}`"
:title="item1.title"
>
<template
v-for="(item2) in item1.children"
>
<a-menu-item
v-if="item2.access"
:key="item2.path"
:title="item2.title"
>
{{item2.title}}
</a-menu-item>
</template>
</a-sub-menu>
<a-menu-item v-else :key="item1.path" :title="item1.title">
{{item1.title}}
</a-menu-item>
</template>
</template>
</a-sub-menu>
<a-menu-item v-else :key="item.path" :title="item.title">
<MenuIcon v-if="item.icon" :icon="item.icon" />
<span>{{item.title}}</span>
</a-menu-item>
</template>
</template>
</a-menu>
<f-menu
:modelValue="route.path"
:inverted="inverted"
:mode="mode"
:options="fixedMenus"
@select="onMenuClick"
></f-menu>
</template>
<script>
import { toRefs, computed } from 'vue';
import { computed, h } from 'vue';
import { FMenu } from '@fesjs/fes-design';
import { useRoute, useRouter } from '@@/core/coreExports';
import Menu from 'ant-design-vue/lib/menu';
import 'ant-design-vue/lib/menu/style/css';
import MenuIcon from './MenuIcon';
import { transform as transformByAccess } from '../helpers/pluginAccess';
import { transform as transformByLocale } from '../helpers/pluginLocale';
export default {
components: {
[Menu.name]: Menu,
[Menu.SubMenu.name]: Menu.SubMenu,
[Menu.Item.name]: Menu.Item,
MenuIcon
FMenu
},
props: {
menus: {
@ -70,18 +27,37 @@ export default {
return [];
}
},
theme: {
mode: {
type: String,
default: 'dark'
default: 'vertical'
},
inverted: {
type: Boolean,
default: false
}
},
setup(props) {
const { menus } = toRefs(props);
const route = useRoute();
const router = useRouter();
const fixedMenus = transformByLocale(transformByAccess(menus));
const transform = menus => menus.map((menu) => {
const copy = {
...menu,
label: menu.title,
value: menu.path
};
if (menu.icon) {
copy.icon = () => h(MenuIcon, {
icon: menu.icon
});
}
if (menu.children) {
copy.children = transform(menu.children);
}
return copy;
});
const fixedMenus = computed(() => transformByLocale(transformByAccess(transform(props.menus))));
const onMenuClick = (e) => {
const path = e.key;
const path = e.value;
if (/^https?:\/\//.test(path)) {
window.open(path, '_blank');
} else if (/^\//.test(path)) {
@ -92,15 +68,11 @@ export default {
);
}
};
const selectedKeys = computed(() => [route.path]);
return {
selectedKeys,
route,
fixedMenus,
onMenuClick
};
}
};
</script>
<style lang="less">
</style>

View File

@ -1,5 +1,4 @@
<script>
import { ref, onBeforeMount } from 'vue';
// eslint-disable-next-line import/extensions
import Icons from '../icons';
@ -33,8 +32,10 @@ export default {
}
if (AText.value) {
return (
<span className={'fes-layout-icon anticon'} innerHTML={AText.value}>
</span>
<span
className={'fes-layout-icon anticon'}
innerHTML={AText.value}
></span>
);
}
return null;
@ -43,7 +44,7 @@ export default {
};
</script>
<style>
.fes-layout-icon{
.fes-layout-icon {
display: inline-block;
color: inherit;
font-style: normal;
@ -56,6 +57,7 @@ export default {
min-width: 14px;
margin-right: 10px;
font-size: 14px;
transition: font-size 0.15s cubic-bezier(0.215, 0.61, 0.355, 1), margin 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
transition: font-size 0.15s cubic-bezier(0.215, 0.61, 0.355, 1),
margin 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
}
</style>

View File

@ -33,7 +33,7 @@
"peerDependencies": {
"@ant-design/icons-vue": "^6.0.0",
"@fesjs/fes": "^2.0.0",
"ant-design-vue": "^2.2.0",
"@fesjs/fes-design": "^0.1.2",
"vue": "^3.0.5"
}
}

View File

@ -1,41 +1,42 @@
<template>
<a-dropdown>
<div class="lang-icon"><GlobalOutlined /></div>
<template #overlay>
<a-menu :selectedKeys="selectedKeys" @click="handleClick">
<a-menu-item
<FTooltip v-model="isOpened">
<div class="lang-icon">
<GlobalOutlined />
</div>
<template #content>
<FScrollbar height="274" class="lang-container">
<div
v-for="item in configs"
:key="item.lang"
class="lang-item"
:class="[
'lang-option',
item.lang === locale && 'is-selected'
]"
@click="handleSelect(item)"
>
<span class="lang-item-icon">{{item.icon}}</span>
<span class="lang-item-label">{{item.label}}</span>
</a-menu-item>
</a-menu>
<span>{{item.icon}}</span>
<span>{{item.label}}</span>
</div>
</FScrollbar>
</template>
</a-dropdown>
</FTooltip>
</template>
<script>
import Dropdown from 'ant-design-vue/lib/dropdown';
import Menu from 'ant-design-vue/lib/menu';
import 'ant-design-vue/lib/dropdown/style/css';
import 'ant-design-vue/lib/menu/style/css';
import { FTooltip, FScrollbar } from '@fesjs/fes-design';
import { GlobalOutlined } from '@ant-design/icons-vue';
import { useI18n } from 'vue-i18n';
import { computed } from 'vue';
import { computed, ref } from 'vue';
import langUConfigMap from '../langUConfigMap';
export default {
components: {
[Dropdown.name]: Dropdown,
[Menu.name]: Menu,
[Menu.Item.name]: Menu.Item,
FTooltip,
FScrollbar,
GlobalOutlined
},
setup() {
const { messages, locale } = useI18n();
const selectedKeys = computed(() => [locale.value]);
const configs = computed(() => {
const arr = [];
Object.keys(messages.value)
@ -45,30 +46,46 @@ export default {
});
return arr;
});
const handleClick = ({ key }) => {
locale.value = key;
window.localStorage.setItem('fes_locale', key);
const isOpened = ref(false);
const handleSelect = ({ lang }) => {
locale.value = lang;
isOpened.value = false;
window.localStorage.setItem('fes_locale', lang);
};
return {
handleClick,
selectedKeys,
configs
handleSelect,
locale,
configs,
isOpened
};
}
};
</script>
<style lang="less">
<style lang="less" scoped>
.lang-icon {
margin: 0 8px;
padding: 0 4px;
cursor: pointer;
}
.lang-item {
display: flex;
align-items: center;
.lang-item-label {
margin-left: 8px;
.lang-container {
width: 180px;
.lang-option {
display: flex;
align-items: center;
justify-content: space-between;
height: 32px;
padding: 0 8px;
color: #0f1222;
line-height: 32px;
background: #ffffff;
cursor: pointer;
transition: all 0.2s cubic-bezier(0.9, 0, 0.3, 0.7);
&:hover,
&.is-selected {
color: #5384ff;
background: #f5f8ff;
}
}
}
</style>

View File

@ -34,8 +34,8 @@ export default {
title: "Fes.js",
footer: "Created by MumbleFe",
multiTabs: true,
navigation: "mixin",
theme: 'light',
navigation: "side",
theme: 'dark',
menus: [
{
name: "index",
@ -55,7 +55,7 @@ export default {
],
},
{
// name: "setting",
name: "setting",
title: "setting",
children: [
{

View File

@ -59,6 +59,7 @@
"@fesjs/plugin-sass": "^2.0.0",
"@fesjs/plugin-monaco-editor": "^2.0.0-beta.0",
"@fesjs/plugin-windicss": "^2.0.0",
"@fesjs/fes-design": "^0.1.2",
"ant-design-vue": "^2.2.0",
"vue": "^3.0.5",
"vuex": "^4.0.0"

View File

@ -1,16 +1,6 @@
<template>
<div :class="$style.red">
<a-input placeholder="请输入。。。" />
<a-button type="primary">Primary</a-button>
<div class="m-2">国际化 {{t("test")}}</div>
fes & 拉夫德鲁 <br />
<access :id="accessId"> accessOnepicess1 <input /> </access>
<div v-access="accessId"> accessOnepicess2 <input /> </div>
<input />
<h4>数据字典</h4>
<div v-for="item in enumsGet('status')" :key="item.key">{{item.value}}{{item.key}}</div>
<div v-for="item in roles" :key="item.key">{{item.name}}{{item.disabled}}</div>
<div>{{enumsGet('roles', '2', { dir: 'eName' })}}</div>
<div>
home
</div>
</template>
<config>
@ -20,124 +10,15 @@
}
</config>
<script>
import { ref, onMounted } from 'vue';
import {
useAccess, useRouter, useI18n, locale, enums, request
} from '@fesjs/fes';
import { Button, Input } from 'ant-design-vue';
export default {
components: {
[Button.name]: Button,
[Input.name]: Input
},
setup() {
const fes = ref('fes upgrade to vue3');
const accessOnepicess = useAccess('/onepiece1');
const localI18n = useI18n();
const router = useRouter();
const accessId = ref('/onepiece1');
enums.push('roles', [
{
id: '1',
cName: '系统管理员',
eName: 'System',
perm: ['1', '2', '3']
},
{
id: '2',
cName: '业务管理员',
eName: 'Business',
perm: ['1', '2']
},
{
id: '3',
cName: '普通用户',
eName: 'User',
perm: ['1']
}
], { keyName: 'id' });
const roles = enums.get('roles', {
extend: [
{
key: 'name',
dir: 'cName'
},
{
key: 'disabled',
transfer: item => item.value.perm.some(i => i >= 2)
}
]
});
console.log('enums roles=>', roles);
console.log('enums roles[1]=>', enums.get('roles', '1'));
console.log('enums status[0]=> ', enums.get('status', 0));
console.log('enums status concat', enums.concat('status', [['3', '普通的']], { extend: [{ key: 'name', dir: 'value' }] }));
console.log('enums status get extend=>', enums.get('status', {
extend: [
{
key: 'name',
dir: 'value'
},
{
key: 'disabled',
transfer: item => item.key === '0'
}
]
}));
onMounted(() => {
console.log(router);
setTimeout(() => {
locale.setLocale({ locale: 'en-US' });
locale.addLocale({ locale: 'ja-JP', messages: { test: 'テスト' } });
console.log(locale.getAllLocales());
}, 2000);
setTimeout(() => {
accessId.value = '11';
}, 4000);
console.log('测试 mock!!');
request('/v2/file').then((data) => {
console.log(data);
}).catch((err) => {
console.log(err);
});
request('/v2/movie/in_theaters_mock', { a: 1 }, 'get').then((data) => {
console.log(data);
}).catch((err) => {
console.log(err);
});
console.log('测试 proxy!!');
request('/v2/movie/in_theaters_proxy', { a: 1 }, {
method: 'get',
headers: { Accept: '*/*' }
}).then((resp) => {
console.log(resp);
}).catch((err) => {
console.log(err);
});
});
return {
accessId,
fes,
accessOnepicess,
t: localI18n.t,
enumsGet: enums.get,
roles
};
},
mounted() {
console.log('$style:', this.$style);
}
};
</script>
<style module>
.red {
color: red;
}
.bold {
font-weight: bold;
}
</style>

View File

@ -1142,6 +1142,13 @@
dependencies:
regenerator-runtime "^0.13.4"
"@babel/runtime@^7.16.3":
version "7.16.5"
resolved "https://registry.npmmirror.com/@babel/runtime/download/@babel/runtime-7.16.5.tgz#7f3e34bf8bdbbadf03fbb7b1ea0d929569c9487a"
integrity sha512-TXWihFIS3Pyv5hzR7j6ihmeLkZfrXGxAr5UfSl8CHf+6q/wpiYDkUau0czckpYG8QmnCIuPpdLtuA9VmuGGyMA==
dependencies:
regenerator-runtime "^0.13.4"
"@babel/template@^7.0.0", "@babel/template@^7.14.5", "@babel/template@^7.3.3":
version "7.14.5"
resolved "http://10.107.103.115:8001/@babel/template/download/@babel/template-7.14.5.tgz#a9bc9d8b33354ff6e55a9c60d1109200a68974f4"
@ -1393,6 +1400,21 @@
minimatch "^3.0.4"
strip-json-comments "^3.1.1"
"@fesjs/fes-design@^0.1.2":
version "0.1.2"
resolved "https://registry.npmmirror.com/@fesjs/fes-design/download/@fesjs/fes-design-0.1.2.tgz#be1751561f10585bbb95de72e8863072112f640a"
integrity sha512-JIUd2uIC0O2E2JCUCm1pxT4ZSQg0z1+rFmtN0zS7OO0usZDKN0T/LSnivDc3K7QSAGMTeOYTgQCb6bLqf8jAfQ==
dependencies:
"@babel/runtime" "^7.16.3"
"@juggle/resize-observer" "^3.3.1"
"@popperjs/core" "^2.4.0"
"@vue/shared" "^3.2.19"
"@vueuse/core" "^6.7.5"
async-validator "^4.0.1"
lodash-es "^4.17.21"
normalize-wheel "^1.0.1"
stickybits "^3.7.9"
"@hapi/hoek@^9.0.0":
version "9.2.0"
resolved "http://10.107.103.115:8001/@hapi/hoek/download/@hapi/hoek-9.2.0.tgz#f3933a44e365864f4dad5db94158106d511e8131"
@ -1665,6 +1687,11 @@
"@types/yargs" "^16.0.0"
chalk "^4.0.0"
"@juggle/resize-observer@^3.3.1":
version "3.3.1"
resolved "https://registry.npmmirror.com/@juggle/resize-observer/download/@juggle/resize-observer-3.3.1.tgz#b50a781709c81e10701004214340f25475a171a0"
integrity sha1-tQp4FwnIHhBwEAQhQ0DyVHWhcaA=
"@lerna/add@4.0.0":
version "4.0.0"
resolved "http://10.107.103.115:8001/@lerna/add/download/@lerna/add-4.0.0.tgz#c36f57d132502a57b9e7058d1548b7a565ef183f"
@ -2526,6 +2553,11 @@
resolved "http://10.107.103.115:8001/@polka/url/download/@polka/url-1.0.0-next.17.tgz#25fdbdfd282c2f86ddf3fcefbd98be99cd2627e2"
integrity sha1-Jf29/SgsL4bd8/zvvZi+mc0mJ+I=
"@popperjs/core@^2.4.0":
version "2.11.0"
resolved "https://registry.npmmirror.com/@popperjs/core/download/@popperjs/core-2.11.0.tgz#6734f8ebc106a0860dff7f92bf90df193f0935d7"
integrity sha512-zrsUxjLOKAzdewIDRWy9nsV1GQsKBCWaGwsZQlCgr6/q+vjyZhFgqedLfFBuI9anTPEUT4APq9Mu0SZBTzIcGQ==
"@rollup/plugin-babel@^5.2.0":
version "5.3.0"
resolved "http://10.107.103.115:8001/@rollup/plugin-babel/download/@rollup/plugin-babel-5.3.0.tgz#9cb1c5146ddd6a4968ad96f209c50c62f92f9879"
@ -3070,6 +3102,11 @@
resolved "http://10.107.103.115:8001/@vue/shared/download/@vue/shared-3.2.2.tgz#6104185ebd57af5a14ac51c1f491b2205fc24054"
integrity sha1-YQQYXr1Xr1oUrFHB9JGyIF/CQFQ=
"@vue/shared@^3.2.19":
version "3.2.26"
resolved "https://registry.npmmirror.com/@vue/shared/download/@vue/shared-3.2.26.tgz#7acd1621783571b9a82eca1f041b4a0a983481d9"
integrity sha512-vPV6Cq+NIWbH5pZu+V+2QHE9y1qfuTq49uNWw4f7FDEeZaDU2H2cx5jcUZOAKW7qTrUS4k6qZPbMy1x4N96nbA==
"@vuepress/bundler-webpack@2.0.0-beta.24":
version "2.0.0-beta.24"
resolved "http://10.107.103.115:8001/@vuepress/bundler-webpack/download/@vuepress/bundler-webpack-2.0.0-beta.24.tgz#61fd0860568d68ddd9111edb5cc82dfecd3c12d4"
@ -3342,6 +3379,14 @@
"@vueuse/shared" "6.0.0-beta.3"
vue-demi "*"
"@vueuse/core@^6.7.5":
version "6.9.2"
resolved "https://registry.npmmirror.com/@vueuse/core/download/@vueuse/core-6.9.2.tgz#76b16d01f33cf367dd1a2d7f2e31d106443ceb8a"
integrity sha512-FRwl4ccSFuHZBHLGgS9TMv/+Dd6XFaL4o9nph2qtgQIV+z29RBFokw08XjHfykiENRzB01MjYHJ7iRUnsIFQXg==
dependencies:
"@vueuse/shared" "6.9.2"
vue-demi "*"
"@vueuse/shared@6.0.0-beta.3":
version "6.0.0-beta.3"
resolved "http://10.107.103.115:8001/@vueuse/shared/download/@vueuse/shared-6.0.0-beta.3.tgz#2e52a1e573983d3b806054948b0eca01ced7c504"
@ -3349,6 +3394,13 @@
dependencies:
vue-demi "*"
"@vueuse/shared@6.9.2":
version "6.9.2"
resolved "https://registry.npmmirror.com/@vueuse/shared/download/@vueuse/shared-6.9.2.tgz#97e4369fa7262ebc96fe1d6e210268f30b037005"
integrity sha512-lAiMh6XROs0kSKVd0Yb/6GKoQMxC1fYrFDi6opvQWISPtcqRNluRrQxLUZ3WTI78ovtoKRLktjhkFAtydcfFDg==
dependencies:
vue-demi "*"
"@webank/eslint-config-webank@0.3.1":
version "0.3.1"
resolved "https://registry.npmjs.org/@webank/eslint-config-webank/-/eslint-config-webank-0.3.1.tgz#71e803808ff239eb66ed04954edab144617467dd"
@ -3949,6 +4001,11 @@ async-validator@^3.3.0:
resolved "http://10.107.103.115:8001/async-validator/download/async-validator-3.5.2.tgz#68e866a96824e8b2694ff7a831c1a25c44d5e500"
integrity sha1-aOhmqWgk6LJpT/eoMcGiXETV5QA=
async-validator@^4.0.1:
version "4.0.7"
resolved "https://registry.npmmirror.com/async-validator/download/async-validator-4.0.7.tgz?cache=0&sync_timestamp=1634529502627&other_urls=https%3A%2F%2Fregistry.npmmirror.com%2Fasync-validator%2Fdownload%2Fasync-validator-4.0.7.tgz#034a0fd2103a6b2ebf010da75183bec299247afe"
integrity sha1-A0oP0hA6ay6/AQ2nUYO+wpkkev4=
async@^2.6.2:
version "2.6.3"
resolved "http://10.107.103.115:8001/async/download/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
@ -8911,7 +8968,7 @@ locate-path@^6.0.0:
dependencies:
p-locate "^5.0.0"
lodash-es@^4.17.15:
lodash-es@^4.17.15, lodash-es@^4.17.21:
version "4.17.21"
resolved "http://10.107.103.115:8001/lodash-es/download/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee"
integrity sha1-Q+YmxG5lkbd1C+srUBFzkMYJ4+4=
@ -9787,6 +9844,11 @@ normalize-url@^6.0.1, normalize-url@^6.1.0:
resolved "http://10.107.103.115:8001/normalize-url/download/normalize-url-6.1.0.tgz#40d0885b535deffe3f3147bec877d05fe4c5668a"
integrity sha1-QNCIW1Nd7/4/MUe+yHfQX+TFZoo=
normalize-wheel@^1.0.1:
version "1.0.1"
resolved "https://registry.npmmirror.com/normalize-wheel/download/normalize-wheel-1.0.1.tgz#aec886affdb045070d856447df62ecf86146ec45"
integrity sha1-rsiGr/2wRQcNhWRH32Ls+GFG7EU=
npm-bundled@^1.1.1:
version "1.1.2"
resolved "http://10.107.103.115:8001/npm-bundled/download/npm-bundled-1.1.2.tgz#944c78789bd739035b70baa2ca5cc32b8d860bc1"
@ -12269,6 +12331,11 @@ std-env@^2.2.1:
dependencies:
ci-info "^3.0.0"
stickybits@^3.7.9:
version "3.7.9"
resolved "https://registry.npmmirror.com/stickybits/download/stickybits-3.7.9.tgz#0e469ffb960e1e661bd308ba4da370dc439902bf"
integrity sha1-Dkaf+5YOHmYb0wi6TaNw3EOZAr8=
strict-uri-encode@^2.0.0:
version "2.0.0"
resolved "http://10.107.103.115:8001/strict-uri-encode/download/strict-uri-encode-2.0.0.tgz#b9c7330c7042862f6b142dc274bbcc5866ce3546"