feat: 新增模块首页、国际化适配与菜单重载功能

1. 为菜单数据新增remark字段并设置默认值
2. 全量替换硬编码文本为国际化多语言支持
3. 新增生产配置模块首页组件与路由
4. 新增菜单重载action,支持语言切换后重载菜单
5. 补充简体中文、英文、日文、繁体中文语言包
This commit is contained in:
sheng
2026-05-28 15:47:19 +08:00
parent 05bfa95bfe
commit 3149ffb932
22 changed files with 1132 additions and 72 deletions

View File

@@ -1,5 +1,5 @@
<template>
<el-tooltip effect="dark" :content="active ? '退出全屏' : '全屏'" placement="bottom">
<el-tooltip effect="dark" :content="active ? $t('page.layout.fullscreen.exit') : $t('page.layout.fullscreen.enter')" placement="bottom">
<el-button class="d2-mr btn-text can-hover" type="text" @click="toggle">
<d2-icon v-if="active" name="compress"/>
<d2-icon v-else name="arrows-alt" style="font-size: 16px"/>

View File

@@ -19,10 +19,8 @@ export default {
}),
tooltipContent () {
return this.logLength === 0
? '没有日志或异常'
: `${this.logLength} 条日志${this.logLengthError > 0
? ` | 包含 ${this.logLengthError} 个异常`
: ''}`
? this.$t('page.layout.log.no_log')
: this.$t('page.layout.log.tooltip', { count: this.logLength, error: this.logLengthError })
}
},
methods: {

View File

@@ -4,7 +4,7 @@
<d2-icon name="font" style="font-size: 16px;"/>
</el-button>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="item in options" :key="item.value" :command="item.value">
<el-dropdown-item v-for="item in sizeOptions" :key="item.value" :command="item.value">
<d2-icon :name="iconName(item.value)" class="d2-mr-5"/>{{item.label}}
</el-dropdown-item>
</el-dropdown-menu>
@@ -12,37 +12,32 @@
</template>
<script>
import { mapState, mapMutations, mapActions } from 'vuex'
import { mapState, mapActions } from 'vuex'
export default {
name: 'd2-header-size',
data () {
return {
options: [
{ label: '默认', value: 'default' },
{ label: '中', value: 'medium' },
{ label: '小', value: 'small' },
{ label: '最小', value: 'mini' }
]
}
},
computed: {
...mapState('d2admin/size', [
'value'
])
]),
sizeOptions () {
return [
{ label: this.$t('page.layout.size.default'), value: 'default' },
{ label: this.$t('page.layout.size.medium'), value: 'medium' },
{ label: this.$t('page.layout.size.small'), value: 'small' },
{ label: this.$t('page.layout.size.mini'), value: 'mini' }
]
}
},
methods: {
...mapMutations({
pageKeepAliveClean: 'd2admin/page/keepAliveClean'
}),
...mapActions({
sizeSet: 'd2admin/size/set'
}),
handleChange (value) {
this.sizeSet(value)
this.$notify({
title: '提示',
title: this.$t('page.layout.size.notification_title'),
dangerouslyUseHTMLString: true,
message: '已更新页面内 <b>组件</b> 的 <b>默认尺寸</b><br/>例如按钮大小,<b>非字号</b>',
message: this.$t('page.layout.size.notification_message'),
type: 'success'
})
},

View File

@@ -1,13 +1,13 @@
<template>
<el-table :data="list" v-bind="table">
<el-table-column prop="title" align="center" width="160"/>
<el-table-column label="预览" width="120">
<el-table-column :label="$t('page.layout.theme.preview')" width="120">
<div slot-scope="scope" class="theme-preview" :style="{ backgroundImage: `url(${$baseUrl}${scope.row.preview})` }"/>
</el-table-column>
<el-table-column prop="address" align="center">
<template slot-scope="scope">
<el-button v-if="activeName === scope.row.name" type="success" icon="el-icon-check" round>已激活</el-button>
<el-button v-else round @click="handleSelectTheme(scope.row.name)">使用</el-button>
<el-button v-if="activeName === scope.row.name" type="success" icon="el-icon-check" round>{{ $t('page.layout.theme.active') }}</el-button>
<el-button v-else round @click="handleSelectTheme(scope.row.name)">{{ $t('page.common.use') }}</el-button>
</template>
</el-table-column>
</el-table>

View File

@@ -2,7 +2,7 @@
<div>
<el-tooltip
effect="dark"
content="主题"
:content="$t('page.layout.theme.title')"
placement="bottom">
<el-button
class="d2-ml-0 d2-mr btn-text can-hover"
@@ -14,7 +14,7 @@
</el-button>
</el-tooltip>
<el-dialog
title="主题"
:title="$t('page.layout.theme.title')"
width="600px"
:visible.sync="dialogVisible"
:append-to-body="true">

View File

@@ -1,10 +1,10 @@
<template>
<el-dropdown size="small" class="d2-mr">
<span class="btn-text">{{info.name ? `你好 ${info.name}` : '未登录'}}</span>
<span class="btn-text">{{info.name ? $t('page.layout.user.greeting', { name: info.name }) : $t('page.layout.user.not_logged_in')}}</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item @click.native="logOff">
<d2-icon name="power-off" class="d2-mr-5"/>
注销
{{ $t('page.layout.user.logout') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>

View File

@@ -12,7 +12,7 @@ export function elMenuItem (h, menu) {
key={ menu.path }
index={ menu.path }>
{ icon }
<span slot="title">{ menu.title || '未命名菜单' }</span>
<span slot="title">{ menu.title ? this.$t(menu.title) : this.$t('page.layout.menu.unnamed_menu') }</span>
</el-menu-item>
}
@@ -30,7 +30,7 @@ export function elSubmenu (h, menu) {
key={ menu.path }
index={ menu.path }>
{ icon }
<span slot="title">{ menu.title || '未命名菜单' }</span>
<span slot="title">{ menu.title ? this.$t(menu.title) : this.$t('page.layout.menu.unnamed_menu') }</span>
{ menu.children.map(child => createMenu.call(this, h, child)) }
</el-submenu>
}

View File

@@ -23,7 +23,7 @@ export default {
this.aside.length === 0 && !this.asideCollapse
? <div class="d2-layout-header-aside-menu-empty" flex="dir:top main:center cross:center">
<d2-icon name="inbox"/>
<span>没有侧栏菜单</span>
<span>{ this.$t('page.layout.menu.no_sidebar') }</span>
</div>
: null
}

View File

@@ -5,7 +5,7 @@ export default {
methods: {
handleMenuSelect (index, indexPath) {
if (/^d2-menu-empty-\d+$/.test(index) || index === undefined) {
this.$message.warning('临时菜单')
this.$message.warning(this.$t('page.layout.menu.temp_menu'))
} else if (/^https:\/\/|http:\/\//.test(index)) {
util.open(index)
} else {

View File

@@ -7,7 +7,7 @@
ref="input"
v-model="searchText"
suffix-icon="el-icon-search"
placeholder="搜索页面"
:placeholder="$t('page.layout.search.placeholder')"
:fetch-suggestions="querySearch"
:trigger-on-focus="false"
:clearable="true"
@@ -15,13 +15,7 @@
@select="handleSelect">
<d2-panel-search-item slot-scope="{ item }" :item="item"/>
</el-autocomplete>
<div class="panel-search__tip">
您可以使用快捷键
<span class="panel-search__key">{{hotkey.open}}</span>
唤醒搜索面板
<span class="panel-search__key">{{hotkey.close}}</span>
关闭
</div>
<div class="panel-search__tip" v-html="$t('page.layout.search.tip', { open: hotkey.open, close: hotkey.close })"></div>
</div>
<div v-if="resultsList.length > 0" class="panel-search__results-group" flex-box="1">
<el-card shadow="never">

View File

@@ -20,7 +20,7 @@
<el-tab-pane
v-for="page in opened"
:key="page.fullPath"
:label="page.meta.title || '未命名'"
:label="page.meta.title || $t('page.layout.tabs.unnamed')"
:name="page.fullPath"
:closable="isTabClosable(page)"/>
</el-tabs>
@@ -36,19 +36,19 @@
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="left">
<d2-icon name="arrow-left" class="d2-mr-10"/>
关闭左侧
{{ $t('page.layout.tabs.close_left') }}
</el-dropdown-item>
<el-dropdown-item command="right">
<d2-icon name="arrow-right" class="d2-mr-10"/>
关闭右侧
{{ $t('page.layout.tabs.close_right') }}
</el-dropdown-item>
<el-dropdown-item command="other">
<d2-icon name="times" class="d2-mr-10"/>
关闭其它
{{ $t('page.layout.tabs.close_other') }}
</el-dropdown-item>
<el-dropdown-item command="all">
<d2-icon name="times-circle" class="d2-mr-10"/>
全部关闭
{{ $t('page.layout.tabs.close_all') }}
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
@@ -70,16 +70,6 @@ export default {
contextmenuFlag: false,
contentmenuX: 0,
contentmenuY: 0,
contextmenuListIndex: [
{ icon: 'times-circle', title: '关闭全部', value: 'all' }
],
contextmenuList: [
{ icon: 'refresh', title: '刷新', value: 'refresh' },
{ icon: 'arrow-left', title: '关闭左侧', value: 'left' },
{ icon: 'arrow-right', title: '关闭右侧', value: 'right' },
{ icon: 'times', title: '关闭其它', value: 'other' },
{ icon: 'times-circle', title: '关闭全部', value: 'all' }
],
tagName: '/index'
}
},
@@ -87,7 +77,21 @@ export default {
...mapState('d2admin/page', [
'opened',
'current'
])
]),
contextmenuListIndex () {
return [
{ icon: 'times-circle', title: this.$t('page.layout.tabs.close_all'), value: 'all' }
]
},
contextmenuList () {
return [
{ icon: 'refresh', title: this.$t('page.layout.tabs.refresh'), value: 'refresh' },
{ icon: 'arrow-left', title: this.$t('page.layout.tabs.close_left'), value: 'left' },
{ icon: 'arrow-right', title: this.$t('page.layout.tabs.close_right'), value: 'right' },
{ icon: 'times', title: this.$t('page.layout.tabs.close_other'), value: 'other' },
{ icon: 'times-circle', title: this.$t('page.layout.tabs.close_all'), value: 'all' }
]
}
},
methods: {
...mapActions('d2admin/page', [
@@ -148,7 +152,7 @@ export default {
case 'right': this.closeRight(params); break
case 'other': this.closeOther(params); break
case 'all': this.closeAll(); break
default: this.$message.error('无效的操作'); break
default: this.$message.error(this.$t('page.layout.tabs.invalid_operation')); break
}
},
/**