update 菜单搜索

This commit is contained in:
2021-06-17 14:11:44 +08:00
parent cad86cf7a5
commit 67a58cf7c4
8 changed files with 189 additions and 8 deletions

View File

@@ -3,6 +3,7 @@ import { Layout, Badge } from 'antd'
import { AntIcon, Container } from 'components'
import Logo from '../logo'
import User from './user'
import Search from './search'
import store from 'store'
const { getState, subscribe, dispatch } = store
@@ -41,7 +42,7 @@ export default class index extends Component {
<AntIcon type="menu" />
</span>
<Logo />
{/* search */}
<Search />
</div>
<div className="header-actions">
<span className="header-action" onClick={() => window.realodContentWindow()}>

View File

@@ -0,0 +1,144 @@
import React, { Component } from 'react'
import { AutoComplete, Input } from 'antd'
import { AntIcon } from 'components'
import store from 'store'
import { concat } from 'lodash'
const { getState, subscribe } = store
const unZip = (menus) => {
const result = []
menus.forEach(item => {
if (item.children) {
result.push({
parent: item.meta.title,
children: item.children
})
} else {
result.push({
parent: item.meta.title,
children: [item]
})
}
})
return result
}
export default class search extends Component {
state = {
options: [],
searchValue: ''
}
nav = getState('nav').nav
autoComplete = React.createRef()
constructor(props) {
super(props)
this.unsubscribe = subscribe('nav', state => {
this.getOptions(state.nav)
})
}
componentDidMount() {
this.getOptions(this.nav)
}
componentWillUnmount() {
this.unsubscribe()
}
onSearch(searchValue, option) {
searchValue = searchValue.toLowerCase()
return (option.value && option.value.toLowerCase().indexOf(searchValue) > -1)
|| (option.component && option.component.toLowerCase().indexOf(searchValue) > -1)
}
onSelect(value, option) {
const { id, meta, component } = option.menu
// 选中时清空输入框内容,并失去焦点
this.setState({ searchValue: '' })
this.autoComplete.current.blur()
window.openContentWindow({
key: id,
title: meta.title,
icon: meta.icon,
path: component,
})
}
getOptions(nav) {
const menus = unZip(concat.apply(this, nav.map(p => p.menu)))
const options = menus.map(item => {
if (item.parent) {
return {
label: this.renderTitle(item.parent),
options: item.children.map(menu => {
return this.renderItem(menu.meta.title, menu)
})
}
} else {
return {
options: item.children.map(menu => {
return this.renderItem(menu.meta.title, menu)
})
}
}
})
this.setState({ options })
}
renderTitle(title) {
return <span>
{title}
</span>
}
renderItem(title, menu) {
return {
value: title,
component: menu.component,
menu,
label: (
<>
{title}
<div className="text-normal">{menu.component}</div>
</>
),
}
}
render() {
const { options, searchValue } = this.state
return (
<AutoComplete
ref={this.autoComplete}
value={searchValue}
options={options}
dropdownMatchSelectWidth={false}
dropdownStyle={{ width: '300px' }}
dropdownClassName="certain-category-search-dropdown"
optionLabelProp="value"
filterOption={(searchValue, option) => this.onSearch(searchValue, option)}
onSelect={(value, option) => this.onSelect(value, option)}
onChange={(value) => this.setState({ searchValue: value })}
>
<Input
allowClear
placeholder="请输入检索关键字"
suffix={<AntIcon type="search" />}
/>
</AutoComplete>
)
}
}

View File

@@ -78,7 +78,7 @@ export default class index extends Component {
<div className="swiper-container" id="layout--swiper-container">
<div className="swiper-wrapper">
<div className="swiper-slide">
<Menu parent={this} menuStyle={{ height: '100%', borderRight: 0 }} nav={this.props.nav} />
<Menu parent={this} menuStyle={{ height: '100%', borderRight: 0 }} />
</div>
</div>
<div className="swiper-scrollbar" id="layout--swiper-scrollbar"></div>

View File

@@ -1,9 +1,28 @@
import React, { Component } from 'react'
import { Menu } from 'antd'
import AntIcon from 'components/ant-icon'
import store from 'store'
const { getState, subscribe } = store
export default class index extends Component {
state = {
...getState('nav')
}
constructor(props) {
super(props)
this.unsubscribe = subscribe('nav', state => {
this.setState(state)
})
}
componentWillUnmount() {
this.unsubscribe()
}
renderMenu = (menu) => {
return menu.map((p) => {
return p.children ? this.renderSubMenu(p) : this.renderMenuItem(p)
@@ -56,7 +75,7 @@ export default class index extends Component {
return (
<>
{
this.props.nav.map((item, i) => {
this.state.nav.map((item, i) => {
return (
<section key={i}>
<div className="yo-sider-nav--app">{item.app.name}</div>

View File

@@ -36,8 +36,7 @@ const setNav = async (nav) => {
})
})
const menus = await api
.$queue(getNav.map((p) => api.sysMenuChangeAwait({ application: p.app.code })))
const menus = await Promise.all(getNav.map(p => api.sysMenuChange({ application: p.app.code })))
menus.forEach((menu, i) => {
getNav[i].menu = serializeMenu(menu.data)
})
@@ -52,7 +51,6 @@ export default class index extends Component {
state = {
loading: true,
nav: [],
panes: [],
actived: '',
test: 0
@@ -73,7 +71,12 @@ export default class index extends Component {
user: data
})
this.setState({ loading: false, nav }, () => {
dispatch({
type: 'SET_ANV',
nav
})
this.setState({ loading: false }, () => {
this.onOpenContentWindow({
title: '工作台',
path: '/home',
@@ -233,7 +236,7 @@ export default class index extends Component {
<Layout>
<Header />
<Layout className="yo-nav-theme--light">
<Sider nav={this.state.nav} />
<Sider />
<Content parent={this} panes={this.state.panes} actived={this.state.actived} />
</Layout>
</Layout>