mirror of
https://gitee.com/WeBank/fes.js.git
synced 2024-12-01 19:27:47 +08:00
feat: plugin-layout的页签信息支持国际化
This commit is contained in:
parent
6d64a0997a
commit
0a78b72fdf
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@ -31,5 +31,8 @@
|
||||
"source": "./fixtures/output/**/*.*",
|
||||
"target": "./fixtures/input/<base>"
|
||||
}
|
||||
],
|
||||
"cSpell.words": [
|
||||
"unref"
|
||||
]
|
||||
}
|
||||
|
@ -30,6 +30,13 @@ export default (api) => {
|
||||
|
||||
const absRuntimeFilePath = join(namespace, 'runtime.js');
|
||||
|
||||
api.register({
|
||||
key: 'addExtraLocales',
|
||||
fn: () => [
|
||||
join(api.paths.absTmpPath, namespace, 'locales'),
|
||||
],
|
||||
});
|
||||
|
||||
api.onGenerateFiles(async () => {
|
||||
// .fes配置
|
||||
const userConfig = {
|
||||
|
@ -1,4 +1,4 @@
|
||||
const getMetaByName = (config, name) => {
|
||||
function getMetaByName(config, name) {
|
||||
let res = {};
|
||||
if (Array.isArray(config)) {
|
||||
for (let i = 0; i < config.length; i++) {
|
||||
@ -17,9 +17,9 @@ const getMetaByName = (config, name) => {
|
||||
}
|
||||
}
|
||||
return res;
|
||||
};
|
||||
}
|
||||
|
||||
const fillMenuByRoute = (menuConfig, routeConfig, dep = 0) => {
|
||||
function fillMenuByRoute(menuConfig, routeConfig, dep = 0) {
|
||||
dep += 1;
|
||||
if (dep > 3) {
|
||||
console.warn('[plugin-layout]: 菜单层级最好不要超出三层!');
|
||||
@ -44,6 +44,6 @@ const fillMenuByRoute = (menuConfig, routeConfig, dep = 0) => {
|
||||
});
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
}
|
||||
|
||||
export default fillMenuByRoute;
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { plugin } from '@@/core/coreExports';
|
||||
|
||||
export const transTitle = (name) => {
|
||||
export function transTitle(name) {
|
||||
if (!/^\$\S+$/.test(name)) {
|
||||
return name;
|
||||
}
|
||||
@ -10,10 +10,10 @@ export const transTitle = (name) => {
|
||||
return t(name.slice(1));
|
||||
}
|
||||
return name;
|
||||
};
|
||||
}
|
||||
|
||||
export const transform = (menus) =>
|
||||
menus.map((menu) => {
|
||||
export function transform(menus) {
|
||||
return menus.map((menu) => {
|
||||
const copy = {
|
||||
...menu,
|
||||
label: transTitle(menu.label),
|
||||
@ -23,3 +23,4 @@ export const transform = (menus) =>
|
||||
}
|
||||
return copy;
|
||||
});
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ const isStr = function (str) {
|
||||
return typeof str === 'string';
|
||||
};
|
||||
|
||||
export const isValid = (elm) => {
|
||||
export function isValid(elm) {
|
||||
if (elm.nodeType === 1) {
|
||||
if (elm.nodeName.toLowerCase() === 'script') {
|
||||
return false;
|
||||
@ -22,9 +22,9 @@ export const isValid = (elm) => {
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
export const validateContent = (svgContent) => {
|
||||
export function validateContent(svgContent) {
|
||||
const div = document.createElement('div');
|
||||
div.innerHTML = svgContent;
|
||||
|
||||
@ -46,4 +46,4 @@ export const validateContent = (svgContent) => {
|
||||
}
|
||||
}
|
||||
return '';
|
||||
};
|
||||
}
|
||||
|
@ -1,8 +1,9 @@
|
||||
export const flatNodes = (nodes = []) =>
|
||||
nodes.reduce((res, node) => {
|
||||
export function flatNodes(nodes = []) {
|
||||
return nodes.reduce((res, node) => {
|
||||
res.push(node);
|
||||
if (node.children) {
|
||||
res = res.concat(flatNodes(node.children));
|
||||
}
|
||||
return res;
|
||||
}, []);
|
||||
}
|
||||
|
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
pluginLayout: {
|
||||
closeOtherPage: 'Close Other Page',
|
||||
reloadPage: 'Reload Page',
|
||||
},
|
||||
};
|
@ -0,0 +1,6 @@
|
||||
export default {
|
||||
pluginLayout: {
|
||||
closeOtherPage: '关闭其他页签',
|
||||
reloadPage: '刷新当前页签',
|
||||
},
|
||||
};
|
@ -7,7 +7,7 @@
|
||||
type="card"
|
||||
class="layout-content-tabs"
|
||||
@close="handleCloseTab"
|
||||
@update:modelValue="switchPage"
|
||||
@update:model-value="switchPage"
|
||||
>
|
||||
<FTabPane v-for="page in pageList" :key="page.path" :value="page.path" :closable="pageList.length > 1">
|
||||
<template #tab>
|
||||
@ -30,7 +30,7 @@
|
||||
import { computed, ref, unref } from 'vue';
|
||||
import { FDropdown, FTabPane, FTabs } from '@fesjs/fes-design';
|
||||
import { MoreOutlined, ReloadOutlined } from '@fesjs/fes-design/icon';
|
||||
import { useRoute, useRouter } from '@@/core/coreExports';
|
||||
import { plugin, useRoute, useRouter } from '@@/core/coreExports';
|
||||
import { transTitle } from '../helpers/pluginLocale';
|
||||
import { deleteTitle, getTitle } from '../useTitle';
|
||||
import { useLayout } from '../useLayout';
|
||||
@ -71,26 +71,45 @@ export default {
|
||||
};
|
||||
|
||||
const pageList = ref([createPage(router.currentRoute.value)]);
|
||||
const actions = [
|
||||
{
|
||||
value: 'closeOtherPage',
|
||||
label: '关闭其他页签',
|
||||
},
|
||||
{
|
||||
value: 'reloadPage',
|
||||
label: '刷新当前页签',
|
||||
},
|
||||
];
|
||||
|
||||
const actions = computed(() => {
|
||||
const sharedLocale = plugin.getShared('locale');
|
||||
if (sharedLocale) {
|
||||
const { t } = sharedLocale.locale;
|
||||
return [
|
||||
{
|
||||
value: 'closeOtherPage',
|
||||
label: t('pluginLayout.closeOtherPage'),
|
||||
},
|
||||
{
|
||||
value: 'reloadPage',
|
||||
label: t('pluginLayout.reloadPage'),
|
||||
},
|
||||
];
|
||||
}
|
||||
return [
|
||||
{
|
||||
value: 'closeOtherPage',
|
||||
label: '关闭其他页签',
|
||||
},
|
||||
{
|
||||
value: 'reloadPage',
|
||||
label: '刷新当前页签',
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
const findPage = path => pageList.value.find(item => unref(item.path) === unref(path));
|
||||
|
||||
router.beforeEach((to) => {
|
||||
const page = findPage(to.path);
|
||||
if (!page)
|
||||
if (!page) {
|
||||
pageList.value = [...pageList.value, createPage(to)];
|
||||
}
|
||||
|
||||
else
|
||||
else {
|
||||
page.route = to;
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
@ -113,11 +132,13 @@ export default {
|
||||
const index = list.indexOf(selectedPage);
|
||||
if (route.path === selectedPage.path) {
|
||||
if (list.length > 1) {
|
||||
if (list.length - 1 === index)
|
||||
if (list.length - 1 === index) {
|
||||
await switchPage(list[index - 1].path);
|
||||
}
|
||||
|
||||
else
|
||||
else {
|
||||
await switchPage(list[index + 1].path);
|
||||
}
|
||||
}
|
||||
}
|
||||
list.splice(index, 1);
|
||||
@ -129,8 +150,9 @@ export default {
|
||||
|
||||
const reloadPage = (path) => {
|
||||
const selectedPage = findPage(path || unref(route.path));
|
||||
if (selectedPage)
|
||||
if (selectedPage) {
|
||||
selectedPage.key = getKey();
|
||||
}
|
||||
};
|
||||
const closeOtherPage = (path) => {
|
||||
const selectedPage = findPage(path || unref(route.path));
|
||||
@ -139,8 +161,9 @@ export default {
|
||||
};
|
||||
const getPageKey = (_route) => {
|
||||
const selectedPage = findPage(_route.path);
|
||||
if (selectedPage)
|
||||
if (selectedPage) {
|
||||
return selectedPage.key;
|
||||
}
|
||||
|
||||
return '';
|
||||
};
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { readFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { name } from '../package.json';
|
||||
|
||||
const namespace = 'plugin-locale';
|
||||
@ -32,10 +32,17 @@ export default (api) => {
|
||||
return join(api.paths.absSrcPath, api.config.singular ? 'locale' : 'locales');
|
||||
}
|
||||
|
||||
api.register({
|
||||
key: 'addExtraLocales',
|
||||
fn: () => [
|
||||
getLocaleFileBasePath(),
|
||||
],
|
||||
});
|
||||
|
||||
// 监听 locale 文件改变,重新生成文件
|
||||
api.addTmpGenerateWatcherPaths(getLocaleFileBasePath);
|
||||
|
||||
api.onGenerateFiles(() => {
|
||||
api.onGenerateFiles(async () => {
|
||||
// .fes配置
|
||||
const userConfig = {
|
||||
locale: 'zh-CN', // default locale
|
||||
@ -45,9 +52,13 @@ export default (api) => {
|
||||
...api.config.locale,
|
||||
};
|
||||
|
||||
const localeConfigFileBasePath = getLocaleFileBasePath();
|
||||
const additionalLocales = await api.applyPlugins({
|
||||
key: 'addExtraLocales',
|
||||
type: api.ApplyPluginsType.add,
|
||||
initialValue: [],
|
||||
});
|
||||
|
||||
const { files, locales } = getLocales(localeConfigFileBasePath);
|
||||
const { files, locales } = getLocales(additionalLocales);
|
||||
|
||||
const { baseNavigator, ...otherConfig } = userConfig;
|
||||
|
||||
@ -55,7 +66,7 @@ export default (api) => {
|
||||
path: join(namespace, 'locales.js'),
|
||||
content: Mustache.render(readFileSync(join(__dirname, 'runtime/locales.js.tpl'), 'utf-8'), {
|
||||
REPLACE_IMPORTS: files,
|
||||
REPLACE_LOCALES: locales.map((item) => ({
|
||||
REPLACE_LOCALES: locales.map(item => ({
|
||||
locale: item.locale,
|
||||
importNames: item.importNames.join(', '),
|
||||
})),
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { plugin } from '@@/core/coreExports';
|
||||
// eslint-disable-next-line import/extensions
|
||||
import { useI18n, locale, install } from './core';
|
||||
|
||||
import { install, locale, useI18n } from './core';
|
||||
import SelectLang from './views/SelectLang.vue';
|
||||
|
||||
// 共享出去
|
||||
|
@ -1,11 +1,11 @@
|
||||
<template>
|
||||
<FTooltip v-model="isOpened" popperClass="lang-popper" mode="popover">
|
||||
<FTooltip v-model="isOpened" popper-class="lang-popper" mode="popover">
|
||||
<div class="lang-icon">
|
||||
<LanguageOutlined />
|
||||
</div>
|
||||
<template #content>
|
||||
<FScrollbar height="274" class="lang-container">
|
||||
<div v-for="item in configs" :key="item.lang" :class="['lang-option', item.lang === locale && 'is-selected']" @click="handleSelect(item)">
|
||||
<div v-for="item in configs" :key="item.lang" class="lang-option" :class="[item.lang === locale && 'is-selected']" @click="handleSelect(item)">
|
||||
<span>{{ item.icon }}</span>
|
||||
<span>{{ item.label }}</span>
|
||||
</div>
|
||||
@ -15,12 +15,12 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { FTooltip, FScrollbar } from '@fesjs/fes-design';
|
||||
import { FScrollbar, FTooltip } from '@fesjs/fes-design';
|
||||
import { LanguageOutlined } from '@fesjs/fes-design/icon';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { computed, ref } from 'vue';
|
||||
import langUConfigMap from '../langUConfigMap';
|
||||
// eslint-disable-next-line import/extensions
|
||||
|
||||
import { locale as _locale } from '../core';
|
||||
|
||||
export default {
|
||||
@ -55,11 +55,13 @@ export default {
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.fes-tooltip.fes-tooltip-popover.lang-popper {
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.lang-icon {
|
||||
display: flex;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { join, basename } from 'path';
|
||||
import { basename, join } from 'node:path';
|
||||
import { glob, winPath } from '@fesjs/utils';
|
||||
|
||||
const ignore = /\.(d\.ts|\.test\.(js|ts))$/;
|
||||
@ -15,30 +15,32 @@ const getRouteName = function (path) {
|
||||
.replace(/\[...([a-zA-Z]*)\]/, 'FUZZYMATCH-$1');
|
||||
};
|
||||
|
||||
export function getLocales(cwd) {
|
||||
export function getLocales(cwdArray) {
|
||||
const map = {};
|
||||
const files = [];
|
||||
glob.sync('**/*.js', {
|
||||
cwd,
|
||||
})
|
||||
.filter((file) => !ignore.test(file))
|
||||
.forEach((fileName) => {
|
||||
const locale = basename(fileName, '.js');
|
||||
const importName = getRouteName(fileName).replace('.js', '');
|
||||
const result = {
|
||||
importName,
|
||||
// import语法的路径,必须处理win
|
||||
path: winPath(join(cwd, fileName)),
|
||||
};
|
||||
files.push(result);
|
||||
if (!map[locale]) {
|
||||
map[locale] = [];
|
||||
}
|
||||
map[locale].push(importName);
|
||||
});
|
||||
cwdArray.forEach((cwd) => {
|
||||
glob.sync('**/*.js', {
|
||||
cwd,
|
||||
})
|
||||
.filter(file => !ignore.test(file))
|
||||
.forEach((fileName) => {
|
||||
const locale = basename(fileName, '.js');
|
||||
const importName = getRouteName(fileName).replace('.js', '');
|
||||
const result = {
|
||||
importName,
|
||||
// import语法的路径,必须处理win
|
||||
path: winPath(join(cwd, fileName)),
|
||||
};
|
||||
files.push(result);
|
||||
if (!map[locale]) {
|
||||
map[locale] = [];
|
||||
}
|
||||
map[locale].push(importName);
|
||||
});
|
||||
});
|
||||
|
||||
return {
|
||||
locales: Object.keys(map).map((key) => ({ locale: key, importNames: map[key] })),
|
||||
locales: Object.keys(map).map(key => ({ locale: key, importNames: map[key] })),
|
||||
files,
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user