123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265 |
- <script>
- import events from './events'
- export default {
- name: 'MultiTab',
- data () {
- return {
- pagesRecordList: [], // 记录打开过的页面
- tabsList: [], // 已打开页签
- pages: [], // 已打开页面
- activeKey: '', // 当前页面
- newTabIndex: 0,
- maxTabNums: 10
- }
- },
- inject: ['reloadView'],
- created () {
- // bind event
- events.$on('open', val => {
- if (!val) {
- throw new Error(`multi-tab: open tab ${val} err`)
- }
- this.activeKey = val
- }).$on('close', val => {
- if (!val) {
- this.closeThat(this.activeKey)
- return
- }
- this.closeThat(val)
- }).$on('rename', ({ key, name }) => {
- // console.log('rename', key, name)
- try {
- const item = this.pages.find(item => item.path === key)
- item.meta.customTitle = name
- this.$forceUpdate()
- } catch (e) {
- }
- })
- if (this.pages.length <= this.maxTabNums) {
- this.pages.push(this.$route)
- this.tabsList.push(this.$route.name)
- this.pagesRecordList.push(this.$route.name)
- this.selectedLastPath()
- }
- },
- methods: {
- onEdit (targetKey, action) {
- this[action](targetKey)
- },
- onChange (targetKey) {
- const index = this.tabsList.indexOf(targetKey)
- if (index >= 0) {
- const row = this.pages[index]
- if (row && row.fullPath && row.fullPath.indexOf('/list') == -1) { // 非列表页,根据当前路由路径判断是子页还是列表页
- this.$store.state.app.isNewSubTab = true
- } else {
- this.$store.state.app.isNewSubTab = false
- }
- }
- },
- remove (targetKey) {
- this.pages = this.pages.filter(page => page.name !== targetKey)
- this.tabsList = this.tabsList.filter(name => name !== targetKey)
- // 判断当前标签是否关闭,若关闭则跳转到最后一个还存在的标签页
- if (!this.tabsList.includes(this.activeKey)) {
- this.selectedLastPath()
- }
- this.$store.state.app.closeTabPages.push(targetKey)
- },
- selectedLastPath () {
- this.activeKey = this.tabsList[this.tabsList.length - 1]
- },
- replaceTab (newtab, oldtab) {
- const index = this.pages.findIndex(item => item.name == oldtab.name)
- this.pages.splice(index, 1, newtab)
- this.tabsList.splice(index, 1, newtab.name)
- },
- // content menu
- refashThat (e) {
- this.reloadView()
- },
- closeThat (e) {
- // 判断是否为最后一个标签页,如果是最后一个,则无法被关闭
- if (this.tabsList.length > 1) {
- this.remove(e)
- } else {
- this.$message.info('这是最后一个标签了, 无法被关闭')
- }
- },
- closeLeft (e) {
- const currentIndex = this.tabsList.indexOf(e)
- if (currentIndex > 0) {
- this.tabsList.forEach((item, index) => {
- if (index < currentIndex) {
- this.remove(item)
- }
- })
- } else {
- this.$message.info('左侧没有标签')
- }
- },
- closeRight (e) {
- const currentIndex = this.tabsList.indexOf(e)
- if (currentIndex < (this.tabsList.length - 1)) {
- this.tabsList.forEach((item, index) => {
- if (index > currentIndex) {
- this.remove(item)
- }
- })
- } else {
- this.$message.info('右侧没有标签')
- }
- },
- closeAll (e) {
- const currentIndex = this.tabsList.indexOf(e)
- this.tabsList.forEach((item, index) => {
- if (index !== currentIndex) {
- this.remove(item)
- }
- })
- },
- closeMenuClick (key, route) {
- this[key](route)
- },
- renderTabPaneMenu (e) {
- // return (
- // <a-menu {...{ on: { click: ({ key, item, domEvent }) => { this.closeMenuClick(key, e) } } }}>
- // {this.activeKey == e ? (<a-menu-item key="refashThat">刷新页面</a-menu-item>) : ''}
- // <a-menu-item key="closeRight">关闭右侧</a-menu-item>
- // <a-menu-item key="closeLeft">关闭左侧</a-menu-item>
- // <a-menu-item key="closeAll">关闭全部</a-menu-item>
- // </a-menu>
- // )
- return (
- <a-menu {...{ on: { click: ({ key, item, domEvent }) => { this.closeMenuClick(key, e) } } }}>
- <a-menu-item key="closeRight">关闭右侧</a-menu-item>
- <a-menu-item key="closeLeft">关闭左侧</a-menu-item>
- <a-menu-item key="closeAll">关闭全部</a-menu-item>
- </a-menu>
- )
- },
- // render
- renderTabPane (title, keyPath) {
- const menu = this.renderTabPaneMenu(keyPath)
- return (
- <a-dropdown overlay={menu} trigger={['contextmenu']}>
- <span style={{ userSelect: 'none' }}>{ title }</span>
- </a-dropdown>
- )
- }
- },
- watch: {
- '$route': function (newVal, oldVal) {
- if (newVal.name == oldVal.name) { return }
- // console.log(newVal, oldVal, this.pages)
- // 解决页面地址相同参数不同时打开多个页签问题(例 详情页id或sn不同时)
- const index = this.tabsList.indexOf(newVal.name)
- // 是否时同一个父级菜单下的页面
- const mnlen = newVal.matched.length < 3
- const newMatched = newVal.matched[mnlen ? 1 : 2]
- // 是否已存在同级菜单
- const hasEqChild = this.pages.find(item => {
- const alen = item.matched.length < 3
- return item.matched[alen ? 1 : 2].name == newMatched.name
- })
- // console.log(hasEqChild, 'hasEqChild')
- const oldMenu = hasEqChild || oldVal
- const molen = oldMenu.matched.length < 3
- const oldMatched = oldMenu.matched[molen ? 1 : 2]
- const hasChildren = newMatched.name == oldMatched.name
- // 判断是否是新增,编辑,详情页
- const na = newVal.meta.title.indexOf('详情') >= 0
- const nb = newVal.meta.title.indexOf('新增') >= 0
- const nc = newVal.meta.title.indexOf('编辑') >= 0
- const nxt = newVal.meta.replaceTab
- const oa = oldMenu.meta.title.indexOf('详情') >= 0
- const ob = oldMenu.meta.title.indexOf('新增') >= 0
- const oc = oldMenu.meta.title.indexOf('编辑') >= 0
- const oxt = oldMenu.meta.replaceTab
- if (index < 0) { // 不存在
- // console.log(1, hasChildren, '不存在')
- if ((na || nb || nc || nxt || oa || ob || oc || oxt) && hasChildren) {
- // 替换当前页签
- this.replaceTab(newVal, oldMenu)
- // 从列表打开新增,编辑
- this.$store.state.app.isNewTab = na || nb || nc || nxt
- // 从编辑,新增返回列表,刷新列表
- this.$store.state.app.updateList = ob || oc || oxt
- this.activeKey = newVal.name
- } else {
- // 新打开的页签
- if (this.pages.length < this.maxTabNums) {
- this.tabsList.push(newVal.name)
- this.pages.push(newVal)
- this.pagesRecordList.push(newVal.name)
- this.$store.state.app.isNewTab = true
- this.$store.state.app.updateList = false
- this.activeKey = newVal.name
- } else {
- // this.$message.info('您当前打开窗口太多,请关闭一些,窗口不能超过' + this.maxTabNums + '个')
- const _this = this
- this.$store.state.app.closeTabPages.push(newVal.name)
- this.$warning({
- title: '提示',
- content: '您当前打开窗口太多,请关闭一些,窗口不能超过' + this.maxTabNums + '个',
- onOk () {}
- })
- _this.$router.go(-1)
- }
- }
- } else { // 已存在
- // console.log(1, nxt, '已存在')
- this.pages.splice(index, 1, newVal)
- this.tabsList.splice(index, 1, newVal.name)
- this.$store.state.app.isNewTab = !!nxt
- if (hasEqChild) {
- this.$store.state.app.updateList = hasEqChild.name == oldVal.name
- }
- this.activeKey = newVal.name
- }
- },
- activeKey: function (newPathKey) {
- const pages = this.pages.find(item => item.name == newPathKey)
- this.$router.push({ name: newPathKey, params: pages.params, query: pages.query })
- }
- },
- render () {
- const { onEdit, onChange, refashThat, $data: { pages, maxTabNums } } = this
- const tabPanel = pages.length > maxTabNums ? pages.slice(0, maxTabNums - 1) : pages
- const panes = tabPanel.map(page => {
- return (
- <a-tab-pane
- style={{ height: 0 }}
- key={page.name} closable={tabPanel.length > 1}
- >
- <span slot="tab">
- {this.renderTabPane(page.meta.customTitle || page.meta.title, page.name)}
- {this.activeKey == 'page.name' ? (<a-icon
- {...{ on: { click: refashThat } }}
- style={{ marginLeft: '8px', fontSize: '12px' }}
- type="reload" />) : ''}
- </span>
- </a-tab-pane>)
- })
- return (
- <div class="ant-pro-mu lti-tab">
- <div class="ant-pro-multi-tab-wrapper multi-tab-con">
- <a-tabs
- hideAdd
- type={'editable-card'}
- v-model={this.activeKey}
- tabBarStyle={{ background: '#FFF', margin: 0, paddingLeft: '16px', paddingTop: '1px' }}
- {...{ on: { edit: onEdit, 'change': onChange } }}>
- {panes}
- </a-tabs>
- </div>
- </div>
- )
- }
- }
- </script>
|