xy 7 rokov pred
rodič
commit
b3fe98eb2e

+ 4 - 3
config/webpack.config.js

@@ -301,7 +301,7 @@ module.exports = function(webpackEnv) {
               options: {
                 formatter: require.resolve('react-dev-utils/eslintFormatter'),
                 eslintPath: require.resolve('eslint'),
-                
+
               },
               loader: require.resolve('eslint-loader'),
             },
@@ -334,7 +334,7 @@ module.exports = function(webpackEnv) {
                 customize: require.resolve(
                   'babel-preset-react-app/webpack-overrides'
                 ),
-                
+
                 plugins: [
                   [
                     require.resolve('babel-plugin-named-asset-import'),
@@ -347,6 +347,7 @@ module.exports = function(webpackEnv) {
                       },
                     },
                   ],
+                  ["import", {libraryName: "antd", libraryDirectory: "es", style: "css"},  "ant"],
                   ["import", { libraryName: "antd-mobile", libraryDirectory: "lib", style: "css"}, "antd-mobile"]
                 ],
                 // This is a feature of `babel-loader` for webpack (not Babel itself).
@@ -375,7 +376,7 @@ module.exports = function(webpackEnv) {
                 ],
                 cacheDirectory: true,
                 cacheCompression: isEnvProduction,
-                
+
                 // If an error happens in a package, it's possible to be
                 // because it was compiled. Thus, we don't want the browser
                 // debugger to show the original code. Instead, the code

+ 2 - 0
package.json

@@ -5,6 +5,7 @@
   "dependencies": {
     "@babel/core": "7.1.6",
     "@svgr/webpack": "2.4.1",
+    "antd": "^3.11.6",
     "antd-mobile": "^2.2.6",
     "apollo-boost": "^0.1.23",
     "babel-core": "7.0.0-bridge.0",
@@ -38,6 +39,7 @@
     "jest-pnp-resolver": "1.0.1",
     "jest-resolve": "23.6.0",
     "mini-css-extract-plugin": "0.4.3",
+    "moment": "^2.23.0",
     "optimize-css-assets-webpack-plugin": "5.0.1",
     "pnp-webpack-plugin": "1.1.0",
     "postcss-flexbugs-fixes": "4.1.0",

+ 13 - 20
src/App.css

@@ -1,24 +1,17 @@
-.flex-container {
-  margin: 0 15px;
+#tab-bar.demo {
+  display: flex;
+  flex-direction: column;
 }
-.flex-container .inline {
-  width: 80px!important;
-  margin: 9px 9px 9px 0;
+#tab-bar .demoName {
+  height: 40px;
 }
-.flex-container .small {
-  height: 20px!important;
-  line-height: 20px!important;
+#tab-bar .demo-preview-item .am-tab-bar {
+  background-color: white;
 }
-.sub-title {
-  color: #888;
-  font-size: 14px;
-  padding: 30px 0 18px 0;
-}
-.placeholder {
-  background-color: #ebebef;
-  color: #bbb;
-  text-align: center;
-  height: 30px;
-  line-height: 30px;
-  width: 100%;
+
+.spin {
+  position: relative;
+  top: 50%;
+  left: 50%;
+  transform: translate(-50%,-50%);
 }

+ 68 - 87
src/App.js

@@ -1,93 +1,74 @@
-import React, { Component } from 'react';
-import { Flex, WhiteSpace } from 'antd-mobile';
+import React, {Component} from 'react';
+import {TabBar} from 'antd-mobile';
 import './App.css';
-
-const PlaceHolder = ({ className = '', ...restProps }) => (
-    <div className={`${className} placeholder`} {...restProps}>Block</div>
-);
-
-const FlexExample = () => (
-    <div className="flex-container">
-        <div className="sub-title">Basic</div>
-        <Flex>
-            <Flex.Item><PlaceHolder /></Flex.Item>
-            <Flex.Item><PlaceHolder /></Flex.Item>
-        </Flex>
-        <WhiteSpace size="lg" />
-        <Flex>
-            <Flex.Item><PlaceHolder /></Flex.Item>
-            <Flex.Item><PlaceHolder /></Flex.Item>
-            <Flex.Item><PlaceHolder /></Flex.Item>
-        </Flex>
-        <WhiteSpace size="lg" />
-        <Flex>
-            <Flex.Item><PlaceHolder /></Flex.Item>
-            <Flex.Item><PlaceHolder /></Flex.Item>
-            <Flex.Item><PlaceHolder /></Flex.Item>
-            <Flex.Item><PlaceHolder /></Flex.Item>
-        </Flex>
-        <WhiteSpace size="lg" />
-
-        <div className="sub-title">Wrap</div>
-        <Flex wrap="wrap">
-            <PlaceHolder className="inline" />
-            <PlaceHolder className="inline" />
-            <PlaceHolder className="inline" />
-            <PlaceHolder className="inline" />
-            <PlaceHolder className="inline" />
-            <PlaceHolder className="inline" />
-            <PlaceHolder className="inline" />
-        </Flex>
-        <WhiteSpace size="lg" />
-
-        <div className="sub-title">Align</div>
-        <Flex justify="center">
-            <PlaceHolder className="inline" />
-            <PlaceHolder className="inline" />
-            <PlaceHolder className="inline" />
-        </Flex>
-        <WhiteSpace />
-        <Flex justify="end">
-            <PlaceHolder className="inline" />
-            <PlaceHolder className="inline" />
-            <PlaceHolder className="inline" />
-        </Flex>
-        <WhiteSpace />
-        <Flex justify="between">
-            <PlaceHolder className="inline" />
-            <PlaceHolder className="inline" />
-            <PlaceHolder className="inline" />
-        </Flex>
-
-        <WhiteSpace />
-        <Flex align="start">
-            <PlaceHolder className="inline" />
-            <PlaceHolder className="inline small" />
-            <PlaceHolder className="inline" />
-        </Flex>
-        <WhiteSpace />
-        <Flex align="end">
-            <PlaceHolder className="inline" />
-            <PlaceHolder className="inline small" />
-            <PlaceHolder className="inline" />
-        </Flex>
-        <WhiteSpace />
-        <Flex align="baseline">
-            <PlaceHolder className="inline" />
-            <PlaceHolder className="inline small" />
-            <PlaceHolder className="inline" />
-        </Flex>
-    </div>
-);
+import My from './page/home/My';
+import Display from './page/display/Display';
 
 class App extends Component {
-  render() {
-    return (
-      <div className="App">
-          <FlexExample />
-      </div>
-    );
-  }
+    constructor(props) {
+        super(props);
+        this.state = {
+            selectedTab: 'appointment',
+            fullScreen: true,
+        };
+    }
+
+    render() {
+        return (
+            <div className="App">
+                <div style={{position: 'fixed', height: '100%', width: '100%', top: 0}}>
+                    <TabBar
+                        unselectedTintColor="#949494"
+                        tintColor="#33A3F4"
+                        barTintColor="white"
+                    >
+                        <TabBar.Item
+                            title="预约"
+                            key="appointment"
+                            icon={<div style={{
+                                width: '22px',
+                                height: '22px',
+                                background: 'url(https://zos.alipayobjects.com/rmsportal/sifuoDUQdAFKAVcFGROC.svg) center center /  21px 21px no-repeat'
+                            }}
+                            />
+                            }
+                            selectedIcon={<div style={{
+                                width: '22px',
+                                height: '22px',
+                                background: 'url(https://zos.alipayobjects.com/rmsportal/iSrlOTqrKddqbOmlvUfq.svg) center center /  21px 21px no-repeat'
+                            }}
+                            />
+                            }
+                            selected={this.state.selectedTab === 'appointment'}
+                            onPress={() => {
+                                this.setState({
+                                    selectedTab: 'appointment',
+                                });
+                            }}
+                            data-seed="logId"
+                        >
+                            <Display/>
+                        </TabBar.Item>
+                        <TabBar.Item
+                            icon={{uri: 'https://zos.alipayobjects.com/rmsportal/asJMfBrNqpMMlVpeInPQ.svg'}}
+                            selectedIcon={{uri: 'https://zos.alipayobjects.com/rmsportal/gjpzzcrPMkhfEqgbYvmN.svg'}}
+                            title="我的"
+                            key="my"
+                            selected={this.state.selectedTab === 'my'}
+                            onPress={() => {
+                                this.setState({
+                                    selectedTab: 'my',
+                                });
+                            }}
+                        >
+                            <My/>
+                        </TabBar.Item>
+                    </TabBar>
+                </div>
+            </div>
+        );
+    }
 }
 
 export default App;
+

+ 28 - 1
src/gql.js

@@ -16,6 +16,33 @@ const serverbyprops = `
     }
 `;
 
+const servicebyprops = `
+    query servicebyprops($server_id: ID) {
+      servicebyprops: service_by_props(server_id: $server_id) {
+        id
+        server_id {
+          id
+          name
+          description
+          img
+          createdAt
+          updatedAt
+        }
+        repertory_id {
+          id
+          count
+          createdAt
+          updatedAt
+        }
+        description
+        price
+        startTime
+        lastTime
+      }
+    }
+`;
+
 export {
-    serverbyprops
+    serverbyprops,
+    servicebyprops
 }

+ 80 - 0
src/page/component/CalendarPick.js

@@ -0,0 +1,80 @@
+import React, {Component} from 'react';
+import {Calendar} from 'antd-mobile';
+import './index.css';
+
+const extra = {
+    '2017/07/15': {info: 'Disable', disable: true},
+};
+
+const now = new Date();
+extra[+new Date(now.getFullYear(), now.getMonth(), now.getDate() + 5)] = {info: 'Disable', disable: true};
+extra[+new Date(now.getFullYear(), now.getMonth(), now.getDate() + 6)] = {info: 'Disable', disable: true};
+extra[+new Date(now.getFullYear(), now.getMonth(), now.getDate() + 7)] = {info: 'Disable', disable: true};
+extra[+new Date(now.getFullYear(), now.getMonth(), now.getDate() + 8)] = {info: 'Disable', disable: true};
+
+Object.keys(extra).forEach((key) => {
+    const info = extra[key];
+    const date = new Date(key);
+    if (!Number.isNaN(+date) && !extra[+date]) {
+        extra[+date] = info;
+    }
+});
+
+class CalendarPick extends Component {
+    originbodyScrollY = document.getElementsByTagName('body')[0].style.overflowY;
+
+    constructor(props) {
+        super(props);
+        this.state = {
+            show: props.show,
+        };
+    }
+
+
+    onSelectHasDisableDate = (dates) => {
+        console.warn('onSelectHasDisableDate', dates);
+    };
+
+    onConfirm = (startTime, endTime) => {
+        document.getElementsByTagName('body')[0].style.overflowY = this.originbodyScrollY;
+        this.setState({
+            show: false,
+            startTime,
+            endTime,
+        });
+    };
+
+    onCancel = () => {
+        document.getElementsByTagName('body')[0].style.overflowY = this.originbodyScrollY;
+        this.setState({
+            show: false,
+            startTime: undefined,
+            endTime: undefined,
+        });
+    };
+
+    getDateExtra = date => extra[+date];
+
+    render() {
+        return (
+            <div className={'picker'}>
+                <Calendar
+                    type={'one'}
+                    pickTime={true}
+                    visible={this.state.show}
+                    onCancel={this.onCancel}
+                    onConfirm={this.onConfirm}
+                    onSelectHasDisableDate={this.onSelectHasDisableDate}
+                    getDateExtra={this.getDateExtra}
+                    defaultDate={now}
+                    minDate={new Date(+now - 5184000000)}
+                    maxDate={new Date(+now + 31536000000)}
+                    style={{height: 200}}
+                />
+            </div>
+
+        );
+    }
+}
+
+export default CalendarPick;

+ 6 - 0
src/page/component/index.css

@@ -0,0 +1,6 @@
+.am-list-item .am-list-line .am-list-content {
+  display: flex;
+}
+.calendar-list .right {
+  float: right;
+}

+ 104 - 0
src/page/display/Display.js

@@ -0,0 +1,104 @@
+import React, {Component} from 'react';
+import {serverbyprops, servicebyprops} from "../../gql";
+import {Spin} from 'antd';
+import gql from "graphql-tag";
+import {Query} from "react-apollo";
+import Server from './Server';
+import Service from './Service';
+import './index.css'
+
+class Display extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            display: 'server',
+            serverID: ''
+        }
+    }
+
+    pageSwitchToService = (serverID) => {
+        return () => {
+            this.setState ({
+                serverID,
+                display: 'service'
+            })
+
+        }
+    };
+
+    pageSwitchToServer = () => {
+        this.setState ({
+            display: 'server',
+            serverID: ''
+        })
+    };
+
+
+    render() {
+        return (
+            <div>
+                {
+                    this.state.display === 'server' ?
+                        <Query query={gql(serverbyprops)} variables={{}}>
+                            {
+                                ({loading, error, data}) => {
+                                    if (loading) {
+                                        return <Spin className={'spin'}/>
+                                    }
+                                    if (error) {
+                                        return 'error!';
+                                    }
+
+                                    let servers = data.serverbyprops;
+                                    let tip = '';
+                                    if (servers.length === 0) {
+                                        servers = [];
+                                        tip = '还没有服务'
+                                    }
+
+                                    return (
+                                        <Server
+                                            servers={servers}
+                                            tip={tip}
+                                            pageSwitchToService={this.pageSwitchToService}
+                                        />
+                                    )
+                                }
+                            }
+                        </Query>
+                        :
+                        <Query query={gql(servicebyprops)} variables={{server_id: this.state.serverID}}>
+                            {
+                                ({loading, error, data}) => {
+                                    if (loading) {
+                                        return <Spin className={'spin'}/>
+                                    }
+                                    if (error) {
+                                        return 'error!';
+                                    }
+
+                                    let services = data.servicebyprops;
+                                    let tip = '';
+                                    if (services.length === 0) {
+                                        services = [];
+                                        tip = '本人休息'
+                                    }
+
+                                    return (
+                                        <Service
+                                            services={services}
+                                            tip={tip}
+                                            pageSwitchToServer={this.pageSwitchToServer}
+                                        />
+                                    )
+                                }
+                            }
+                        </Query>
+                }
+            </div>
+
+        );
+    }
+}
+
+export default Display;

+ 78 - 0
src/page/display/Server.js

@@ -0,0 +1,78 @@
+import React, {Component} from 'react';
+import {Card, WhiteSpace, Button, Carousel, WingBlank} from 'antd-mobile';
+
+class Server extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            data: ['AiyWuByWklrrUDlFignR', 'TekJlZRVCjLFexlOCuWn', 'IJOtIlfsYdTyaDTRVrLI'],
+            imgHeight: 176,
+        }
+    }
+
+    render() {
+        let {tip, servers} = this.props;
+        return (
+            <div>
+                <WingBlank>
+                    <Carousel
+                        autoplay={true}
+                        infinite
+                    >
+                        {this.state.data.map(val => (
+                            <a
+                                key={val}
+                                href="http://www.alipay.com"
+                                style={{display: 'inline-block', width: '100%', height: this.state.imgHeight}}
+                            >
+                                <img
+                                    src={`https://zos.alipayobjects.com/rmsportal/${val}.png`}
+                                    alt=""
+                                    style={{width: '100%', verticalAlign: 'top'}}
+                                    onLoad={() => {
+                                        window.dispatchEvent(new Event('resize'));
+                                        this.setState({imgHeight: 'auto'});
+                                    }}
+                                />
+                            </a>
+                        ))}
+                    </Carousel>
+                </WingBlank>
+
+
+                {
+                    tip ?
+                        <div>{tip}</div>
+                        :
+                        ''
+                }
+
+                {
+                    servers.map((server) => {
+                        return (
+                            <div key={server.id}>
+                                <WhiteSpace size="lg"/>
+                                <Card full>
+                                    <Card.Body>
+                                        <div className={'card'}>
+                                            <div className={'avatar'}
+                                                 style={{backgroundImage: `url(${server.img})`}}>1
+                                            </div>
+                                            <div>{server.name}</div>
+                                            <div>{server.description}</div>
+                                            <Button type='primary'
+                                                    onClick={this.props.pageSwitchToService(server.id)}>选我</Button>
+                                        </div>
+                                    </Card.Body>
+                                </Card>
+                            </div>
+                        )
+                    })
+                }
+
+            </div>
+        );
+    }
+}
+
+export default Server;

+ 74 - 0
src/page/display/Service.js

@@ -0,0 +1,74 @@
+import React, {Component} from 'react';
+import {NavBar, Icon, WhiteSpace, Card, Button} from 'antd-mobile';
+import CalendarPick from '../component/CalendarPick';
+import moment from 'moment';
+import 'moment/locale/zh-cn'
+moment.locale('zh-cn');
+
+class Service extends Component {
+    constructor(props) {
+        super(props);
+        this.state = {
+            pick: false
+        }
+    }
+
+    render() {
+        let {pageSwitchToServer, tip, services} = this.props;
+        return (
+            <div>
+                <NavBar
+                    mode="light"
+                    icon={<Icon type="left"/>}
+                    onLeftClick={pageSwitchToServer}
+                    rightContent={[
+                        <Icon key="1" type="search" onClick={() => {
+                            this.setState({pick: true})
+                        }}/>,
+                    ]}
+                >服务详情</NavBar>
+
+                {
+                    this.state.pick ?
+                        <CalendarPick show={true}/>
+                        :
+                        <div>
+
+                            {
+                                tip ?
+                                    <div>{tip}</div>
+                                    :
+                                    ''
+                            }
+
+                            {
+                                services.map(service => {
+                                    return (
+                                        <div key={service.id}>
+                                            <WhiteSpace size="lg"/>
+                                            <Card full>
+                                                <Card.Body>
+                                                    <div className={'card'}>
+                                                        <div>{service.description}</div>
+                                                        <div>价格: {service.price}</div>
+                                                        <div>开始时间: {moment(Number(service.startTime)).format("YYYY-MM-DD HH:mm:ss")}</div>
+                                                        <div>工作时间: {moment.duration(Number(service.lastTime), "milliseconds").humanize()}</div>
+                                                        <div>剩余名额: {service.repertory_id.count}</div>
+                                                        <Button type='primary' onClick={()=>{}}>预约</Button>
+                                                    </div>
+                                                </Card.Body>
+                                            </Card>
+                                        </div>
+                                    )
+                                })
+                            }
+                        </div>
+                }
+
+
+            </div>
+        );
+    }
+}
+
+export default Service;

+ 10 - 0
src/page/display/index.css

@@ -0,0 +1,10 @@
+.avatar {
+  width: 50px;
+  height: 50px;
+  background-repeat: no-repeat;
+  background-size:100% 100%
+}
+
+.spin {
+
+}

+ 13 - 0
src/page/home/Manage.js

@@ -0,0 +1,13 @@
+import React, { Component } from 'react';
+
+class Manage extends Component {
+    render() {
+        return (
+            <div>
+                manage
+            </div>
+        );
+    }
+}
+
+export default Manage;

+ 13 - 0
src/page/home/My.js

@@ -0,0 +1,13 @@
+import React, { Component } from 'react';
+
+class My extends Component {
+    render() {
+        return (
+            <div>
+                My
+            </div>
+        );
+    }
+}
+
+export default My;

+ 13 - 0
src/page/home/User.js

@@ -0,0 +1,13 @@
+import React, { Component } from 'react';
+
+class User extends Component {
+    render() {
+        return (
+            <div>
+                User
+            </div>
+        );
+    }
+}
+
+export default User;

+ 0 - 0
src/page/home/index.css