浏览代码

添加搜索

tuonina 5 年之前
父节点
当前提交
7a2adaa835

+ 7 - 1
src/App.js

@@ -6,6 +6,7 @@ import HeaderCustom from './components/HeaderCustom';
 import { Layout, notification, Icon } from 'antd';
 import { ThemePicker } from './components/widget';
 import { connectAlita } from 'redux-alita';
+import { browser, browserType } from './utils/BrowserUtils';
 
 const { Content, Footer } = Layout;
 
@@ -15,6 +16,11 @@ class App extends Component {
         title: '',
     };
 
+    constructor(props) {
+        super(props);
+        console.log('browser type=> ', browserType());
+    }
+
     componentWillMount() {
         const { setAlitaState } = this.props;
         const user = JSON.parse(localStorage.getItem('user'));
@@ -92,7 +98,7 @@ class App extends Component {
                         <HeaderCustom
                             toggle={this.toggle}
                             collapsed={this.state.collapsed}
-                            user={auth.data || {}}
+                            auth={auth.data || {}}
                         />
                         <Content style={{ margin: '0 16px', overflow: 'initial', flex: '1 1 0' }}>
                             <Routes auth={auth} {...this.props}/>

+ 15 - 1
src/api/qywx/index.js

@@ -1,6 +1,8 @@
 import qywx from '../../const/qywx';
 import { request } from '../../axios';
 
+const QYWXAPI="http://api.tonyandmoney.cn/fw";
+
 
 /**
  * 根据临时票据查询用户信息
@@ -8,8 +10,20 @@ import { request } from '../../axios';
  * @returns {Promise<unknown>}
  */
 export const qywxUserInfo = (params) => request({
-    url: 'http://100.100.1.35:11000/qywx/user',
+    url: `${QYWXAPI}/qywx/user`,
     method: 'get',
     params: { ...params, agentId: qywx.agentId },
 }).then(resp => resp.data);
 
+
+/**
+ * 简单的全局模糊查询
+ * @param params 参数信息
+ * @returns {Promise<AxiosResponse<any>>}
+ */
+export const qywxSearch=(params)=>request({
+    url:`${QYWXAPI}/wx/search`,
+    method:'get',
+    params:{...params,agentId: qywx.agentId}
+}).then(resp=>resp.data);
+

+ 44 - 17
src/components/HeaderCustom.jsx

@@ -5,21 +5,38 @@ import React, { Component } from 'react';
 import screenfull from 'screenfull';
 import avater from '../style/imgs/b1.jpg';
 import SiderCustom from './SiderCustom';
-import { Menu, Icon, Layout, Badge, Popover } from 'antd';
-import { gitOauthToken, gitOauthInfo } from '../axios';
+import { Badge, Icon, Layout, Menu, Popover } from 'antd';
+import { gitOauthInfo, gitOauthToken } from '../axios';
 import { queryString } from '../utils';
 import { withRouter } from 'react-router-dom';
 import { PwaInstaller } from './widget';
 import { connectAlita } from 'redux-alita';
+import * as PropTypes from 'prop-types';
+
 const { Header } = Layout;
 const SubMenu = Menu.SubMenu;
 const MenuItemGroup = Menu.ItemGroup;
 
 class HeaderCustom extends Component {
+
+    static propTypes = {
+        auth: PropTypes.object,
+    };
+    static defaultProps = {
+        auth: {
+            user: {
+                account: '',
+                username: '',
+                name: '',
+            },
+        },
+    };
+
     state = {
         user: '',
         visible: false,
     };
+
     componentDidMount() {
         const QueryString = queryString();
         const _user = JSON.parse(localStorage.getItem('user')) || '测试';
@@ -27,17 +44,18 @@ class HeaderCustom extends Component {
             gitOauthToken(QueryString.code).then(res => {
                 gitOauthInfo(res.access_token).then(info => {
                     this.setState({
-                        user: info
+                        user: info,
                     });
                     localStorage.setItem('user', JSON.stringify(info));
                 });
             });
         } else {
             this.setState({
-                user: _user
+                user: _user,
             });
         }
     };
+
     screenFull = () => {
         if (screenfull.enabled) {
             screenfull.request();
@@ -50,7 +68,7 @@ class HeaderCustom extends Component {
     };
     logout = () => {
         localStorage.removeItem('user');
-        this.props.history.push('/login')
+        this.props.history.push('/login');
     };
     popoverHide = () => {
         this.setState({
@@ -60,14 +78,22 @@ class HeaderCustom extends Component {
     handleVisibleChange = (visible) => {
         this.setState({ visible });
     };
+
     render() {
-        const { responsive = { data: {} }, path } = this.props;
+        const { responsive = { data: {} }, path ,auth={user:{}}} = this.props;
+
+        let user = auth.user;
+        if (!user) user={};
+        console.log('HeaderCustom=>', user);
+
         return (
-            <Header className="custom-theme header" >
+            <Header className="custom-theme header">
                 {
                     responsive.data.isMobile ? (
-                        <Popover content={<SiderCustom path={path} popoverHide={this.popoverHide} />} trigger="click" placement="bottomLeft" visible={this.state.visible} onVisibleChange={this.handleVisibleChange}>
-                            <Icon type="bars" className="header__trigger custom-trigger" />
+                        <Popover content={<SiderCustom path={path} popoverHide={this.popoverHide}/>} trigger="click"
+                                 placement="bottomLeft" visible={this.state.visible}
+                                 onVisibleChange={this.handleVisibleChange}>
+                            <Icon type="bars" className="header__trigger custom-trigger"/>
                         </Popover>
                     ) : (
                         <Icon
@@ -83,19 +109,20 @@ class HeaderCustom extends Component {
                     onClick={this.menuClick}
                 >
                     <Menu.Item key="pwa">
-                        <PwaInstaller />
+                        <PwaInstaller/>
                     </Menu.Item>
-                    <Menu.Item key="full" onClick={this.screenFull} >
-                        <Icon type="arrows-alt" onClick={this.screenFull} />
+                    <Menu.Item key="full" onClick={this.screenFull}>
+                        <Icon type="arrows-alt" onClick={this.screenFull}/>
                     </Menu.Item>
                     <Menu.Item key="1">
-                        <Badge count={25} overflowCount={10} style={{marginLeft: 10}}>
-                            <Icon type="notification" />
+                        <Badge count={25} overflowCount={10} style={{ marginLeft: 10 }}>
+                            <Icon type="notification"/>
                         </Badge>
                     </Menu.Item>
-                    <SubMenu title={<span className="avatar"><img src={avater} alt="头像" /><i className="on bottom b-white" /></span>}>
+                    <SubMenu title={<span className="avatar"><img src={avater} alt="头像"/><i
+                        className="on bottom b-white"/></span>}>
                         <MenuItemGroup title="用户中心">
-                            <Menu.Item key="setting:1">你好 - {this.props.user.userName}</Menu.Item>
+                            <Menu.Item key="setting:1">你好 - {user.username}</Menu.Item>
                             <Menu.Item key="setting:2">个人信息</Menu.Item>
                             <Menu.Item key="logout"><span onClick={this.logout}>退出登录</span></Menu.Item>
                         </MenuItemGroup>
@@ -106,7 +133,7 @@ class HeaderCustom extends Component {
                     </SubMenu>
                 </Menu>
             </Header>
-        )
+        );
     }
 }
 

+ 5 - 1
src/components/dashboard/Dashboard.jsx

@@ -7,6 +7,7 @@ import BreadcrumbCustom from '../BreadcrumbCustom';
 import EchartsViews from './EchartsViews';
 import EchartsProjects from './EchartsProjects';
 import b1 from '../../style/imgs/b1.jpg';
+import QywxSearch from '../../pages/qywx/QywxSearch';
 
 
 class Dashboard extends React.Component {
@@ -14,6 +15,9 @@ class Dashboard extends React.Component {
         return (
             <div className="gutter-example button-demo">
                 <BreadcrumbCustom />
+                <Row gutter={10}>
+                    <QywxSearch/>
+                </Row>
                 <Row gutter={10}>
                     <Col className="gutter-row" md={4}>
                         <div className="gutter-box">
@@ -171,4 +175,4 @@ class Dashboard extends React.Component {
     }
 }
 
-export default Dashboard;
+export default Dashboard;

+ 83 - 0
src/pages/qywx/QywxSearch.jsx

@@ -0,0 +1,83 @@
+/**
+ * @Classname QywxSearch
+ * @Description TODO
+ * @Date 2019/8/27 16:53
+ * @Created by Administrator
+ */
+
+import React from 'react';
+import * as PropTypes from 'prop-types';
+import { connectAlita } from 'redux-alita';
+import { Input,Tag } from 'antd';
+import './qywx.less'
+
+class QywxSearch extends React.Component {
+
+    static propTypes = {};
+
+    static defaultProps = {};
+
+    tagColors=['#f50','#2db7f5','#87d068','#108ee9'];
+
+    constructor(props) {
+        super(props);
+        this.state = {};
+    }
+
+    componentDidMount() {
+
+    }
+
+
+    getRandomTagColor(){
+        let i =  Math.round(Math.random()*(3));
+        return this.tagColors[i];
+    }
+
+    handleOnSearch(keywords, event) {
+        this.props.setAlitaState({ funcName: 'qywxSearch', stateName: 'searchResults', params: { keywords } })
+            .then(resp => {
+                console.log('handleOnSearch resp=>', resp);
+            })
+            .catch(e => {
+                console.log('error=>', e);
+            });
+    }
+
+
+    _renderSearchItem(item={message:'',data:[]}){
+        if (!item.data||item.data.length<1){
+            return  null;
+        }
+        return (<div key={item.message} className="qywx-results">
+            <h3 className="result-title">{item.message}</h3>
+            <div className="result-content">{item.data.map(result=>
+                <Tag key={result.title} color={this.getRandomTagColor()}>{result.title}</Tag>)}</div>
+        </div>)
+    }
+
+    render() {
+        let { data: results = [], isFetching } = this.props.searchResults || {};
+
+        console.log('qywx search data=> ', isFetching, results);
+
+        return (<div>
+            <div className="qywx-search">
+                <h3 className="search-title">搜索</h3>
+                <Input.Search
+                    placeholder="输入关键词查询,比如:值班"
+                    onSearch={this.handleOnSearch.bind(this)}/>
+            </div>
+            <div>
+                {results.map&&results.map(item=>this._renderSearchItem(item))}
+            </div>
+
+
+        </div>);
+    }
+
+
+}
+
+
+export default connectAlita(['searchResults'])(QywxSearch);

+ 35 - 0
src/pages/qywx/qywx.less

@@ -0,0 +1,35 @@
+
+.qywx-search {
+  display: flex;
+  flex-direction: row;
+  align-items: center;
+  padding-bottom: 10px;
+  border-bottom: solid 1px lightblue;
+  margin-top: 10px;
+
+  .search-title {
+    display: block;
+    min-width: 60px;
+    text-align: right;
+    height: 32px;
+    line-height: 32px;
+    padding: 0 10px;
+    margin: 0;
+  }
+}
+
+.qywx-results {
+  padding: 10px;
+  margin-bottom: 10px;
+  border-bottom: solid 1px lightblue;
+
+  .result-title {
+    font-size: 16px;
+  }
+
+  .result-content {
+    background: white;
+    padding: 10px;
+  }
+
+}

+ 13 - 3
src/routes/index.js

@@ -12,6 +12,7 @@ import { getStateUri, qyWxOauthUrl, qyWxQrCodeUri } from '../const';
 import { queryString } from '../utils';
 import * as PropTypes from 'prop-types';
 import { Modal, Skeleton } from 'antd';
+import { browserType, BrowType } from '../utils/BrowserUtils';
 
 let AllComponents = { ...Components, ...AllPages };
 export default class CRouter extends Component {
@@ -30,6 +31,7 @@ export default class CRouter extends Component {
 
             },
         };
+        this.browser = browserType();
         console.log('props=>', props);
     }
 
@@ -46,7 +48,7 @@ export default class CRouter extends Component {
 
     requireWxOauth = (component, permission, info) => {
         let params = queryString();
-        this.requestQywxUser(params,info)
+        this.requestQywxUser(params, info)
             .then(() => undefined);
         return null;
     };
@@ -63,7 +65,11 @@ export default class CRouter extends Component {
     };
 
 
-    async requestQywxUser(params,info) {
+    /**
+     * 判断如果是微信或者是企业微信或者是企业微信端,则默认用Oauth静默登录
+     * 如果是其它浏览器,特别是PC,则考虑用扫码登录
+     * */
+    async requestQywxUser(params, info) {
         this.setState({ isLoading: true });
         let { code, state, appid } = params;
         let path = getStateUri(state);
@@ -75,7 +81,11 @@ export default class CRouter extends Component {
                     _this.props.setAlitaState({ stateName: 'auth', data: { user: resp.data } });
                     _this.setState({ isLoading: false });
                 } else if (resp.code === 40029) {
-                    window.location.href = qyWxOauthUrl(info.key);
+                    if (_this.browser === BrowType.WX || _this.browser === BrowType.WXWORK) {
+                        window.location.href = qyWxOauthUrl(info.key);
+                    } else {
+                        window.location.href = qyWxQrCodeUri(info.key);
+                    }
                 } else {
                     Promise.reject({ message: resp.message });
                 }

+ 76 - 0
src/utils/BrowserUtils.js

@@ -0,0 +1,76 @@
+/**
+ * 浏览器类型
+ * @type {{versions: {iPhone: boolean, webApp: boolean, trident: boolean, gecko: boolean, android: boolean, mobile: boolean, iPad: boolean, ios: boolean, presto: boolean, webKit: boolean}, language: string}}
+ */
+export const browser = {
+    versions: function() {
+        let u = navigator.userAgent, app = navigator.appVersion;
+        return {         //移动终端浏览器版本信息
+            trident: u.indexOf('Trident') > -1, //IE内核
+            presto: u.indexOf('Presto') > -1, //opera内核
+            webKit: u.indexOf('AppleWebKit') > -1, //苹果、谷歌内核
+            gecko: u.indexOf('Gecko') > -1 && u.indexOf('KHTML') == -1, //火狐内核
+            mobile: !!u.match(/AppleWebKit.*Mobile.*/), //是否为移动终端
+            ios: !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/), //ios终端
+            android: u.indexOf('Android') > -1 || u.indexOf('Linux') > -1, //android终端或uc浏览器
+            iPhone: u.indexOf('iPhone') > -1, //是否为iPhone或者QQHD浏览器
+            iPad: u.indexOf('iPad') > -1, //是否iPad
+            webApp: u.indexOf('Safari') === -1, //是否web应该程序,没有头部与底部
+        };
+    }(),
+    language: (navigator.browserLanguage || navigator.language).toLowerCase(),
+};
+
+/**
+ * 浏览器类型
+ * @type {{QQ: string, WX: string, WEIBO: string, PC: string, WXWORK: string, UNKNOWN: string, ANDROID: string, IOS: string}}
+ */
+export const BrowType = {
+    ANDROID: 'android',
+    WXWORK: 'wxwork',
+    WX: 'wx',
+    WEIBO: 'WeiBo',
+    QQ: 'qq',
+    IOS: 'ios',
+    PC: 'pc',
+    UNKNOWN: 'UNKNOWN',
+};
+
+/**
+ * 获取当前的浏览器类型
+ * @returns {string}
+ */
+export function browserType() {
+    let ua = navigator.userAgent.toLowerCase();//获取判断用的对象
+    if (browser.versions.mobile) {//判断是否是移动设备打开。browser代码在下面
+        let result = ua.match(/MicroMessenger/i);
+        if (result && result.includes('micromessenger')) {
+            return BrowType.WX;
+        }
+        result = ua.match(/WeiBo/i);
+        if (result && result.includes('weibo')) {
+            //在新浪微博客户端打开
+            return BrowType.WEIBO;
+        }
+        result = ua.match(/QQ/i);
+        if (result && result.includes('qq')) {
+            //在QQ空间打开
+            return BrowType.QQ;
+        }
+        if (browser.versions.ios) {
+            //是否在IOS浏览器打开
+            return BrowType.IOS;
+        }
+        if (browser.versions.android) {
+            //是否在安卓浏览器打开
+            return BrowType.ANDROID;
+        }
+    } else {
+        let result = ua.match(/wxwork/i);
+        if (result && result.includes('wxwork')) {
+            return BrowType.WXWORK;
+        }
+        return BrowType.PC;
+        //否则就是PC浏览器打开
+    }
+}