update 菜单搜索
This commit is contained in:
@@ -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()}>
|
||||
|
||||
144
web-react/src/views/main/_layout/header/search.jsx
Normal file
144
web-react/src/views/main/_layout/header/search.jsx
Normal 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>
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
Reference in New Issue
Block a user