├── src ├── pages │ ├── Asset │ │ ├── index.js │ │ ├── Asset.jsx │ │ └── components │ │ │ └── AssetTab │ │ │ ├── index.js │ │ │ ├── TableFilter.jsx │ │ │ └── AssetTable.jsx │ ├── Goods │ │ ├── index.js │ │ ├── Goods.jsx │ │ └── components │ │ │ ├── Filter │ │ │ └── index.js │ │ │ └── Table │ │ │ └── index.js │ ├── Reserve │ │ ├── index.js │ │ ├── Reserve.jsx │ │ └── components │ │ │ ├── Filter │ │ │ └── index.js │ │ │ └── Table │ │ │ └── index.js │ ├── AddGoods │ │ ├── index.js │ │ ├── AddGoods.jsx │ │ └── components │ │ │ └── GoodsForm │ │ │ └── index.js │ ├── AddReserve │ │ ├── index.js │ │ ├── AddReserve.jsx │ │ └── components │ │ │ └── ReserveForm │ │ │ └── index.js │ ├── Dashboard │ │ ├── index.js │ │ ├── Dashboard.jsx │ │ ├── components │ │ │ ├── ReserveChart │ │ │ │ └── index.js │ │ │ ├── PaymentChart │ │ │ │ └── index.js │ │ │ ├── SalesChart │ │ │ │ ├── ColumnChart.jsx │ │ │ │ └── index.js │ │ │ ├── DoughnutChart │ │ │ │ └── index.jsx │ │ │ ├── RevenueChart │ │ │ │ ├── DonutChart.jsx │ │ │ │ └── index.js │ │ │ └── QuickNav │ │ │ │ └── index.js │ │ └── data.js │ ├── Membership │ │ ├── index.js │ │ ├── Membership.jsx │ │ └── components │ │ │ ├── FilterTag │ │ │ ├── index.module.scss │ │ │ └── index.js │ │ │ ├── FilterForm │ │ │ └── index.js │ │ │ └── Table │ │ │ └── index.js │ ├── OrderList │ │ ├── index.js │ │ └── OrderList.jsx │ ├── UserLogin │ │ ├── index.js │ │ └── UserLogin.jsx │ └── UserRegister │ │ ├── index.js │ │ └── UserRegister.jsx ├── layouts │ ├── BasicLayout │ │ ├── components │ │ │ ├── Aside │ │ │ │ ├── index.js │ │ │ │ ├── images │ │ │ │ │ └── avatar.png │ │ │ │ ├── Aside.scss │ │ │ │ └── Aside.jsx │ │ │ ├── Logo │ │ │ │ ├── index.js │ │ │ │ ├── images │ │ │ │ │ └── logo.png │ │ │ │ ├── index.module.scss │ │ │ │ └── Logo.jsx │ │ │ ├── Footer │ │ │ │ ├── index.js │ │ │ │ ├── Footer.scss │ │ │ │ └── Footer.jsx │ │ │ └── Header │ │ │ │ ├── images │ │ │ │ └── avatar.png │ │ │ │ ├── index.scss │ │ │ │ └── index.js │ │ ├── index.scss │ │ ├── MainRoutes.jsx │ │ └── index.js │ └── UserLayout │ │ ├── components │ │ ├── Header │ │ │ ├── index.scss │ │ │ └── index.js │ │ ├── Intro │ │ │ └── index.js │ │ └── Footer │ │ │ └── index.js │ │ └── index.js ├── components │ ├── CustomForm │ │ ├── index.jsx │ │ └── CustomForm.jsx │ ├── CustomTable │ │ ├── index.js │ │ ├── SearchFilter.jsx │ │ └── CustomTable.jsx │ ├── PageHead │ │ └── index.js │ ├── NotFound │ │ ├── index.scss │ │ └── index.js │ └── Overview │ │ └── index.js ├── index.js ├── router.jsx ├── menuConfig.js └── routerConfig.js ├── public ├── favicon.png └── index.html ├── .eslintignore ├── .editorconfig ├── .gitignore ├── README.md ├── .eslintrc ├── package.json └── LICENSE /src/pages/Asset/index.js: -------------------------------------------------------------------------------- 1 | import Asset from './Asset'; 2 | 3 | export default Asset; 4 | -------------------------------------------------------------------------------- /src/pages/Goods/index.js: -------------------------------------------------------------------------------- 1 | import Goods from './Goods'; 2 | 3 | export default Goods; 4 | -------------------------------------------------------------------------------- /public/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Saseke/poseidon-admin/HEAD/public/favicon.png -------------------------------------------------------------------------------- /src/pages/Reserve/index.js: -------------------------------------------------------------------------------- 1 | import Reserve from './Reserve'; 2 | 3 | export default Reserve; 4 | -------------------------------------------------------------------------------- /src/pages/AddGoods/index.js: -------------------------------------------------------------------------------- 1 | import AddGoods from './AddGoods'; 2 | 3 | export default AddGoods; 4 | -------------------------------------------------------------------------------- /src/pages/AddReserve/index.js: -------------------------------------------------------------------------------- 1 | import AddReserve from './AddReserve'; 2 | 3 | export default AddReserve; 4 | -------------------------------------------------------------------------------- /src/pages/Dashboard/index.js: -------------------------------------------------------------------------------- 1 | import Dashboard from './Dashboard'; 2 | 3 | export default Dashboard; 4 | -------------------------------------------------------------------------------- /src/pages/Membership/index.js: -------------------------------------------------------------------------------- 1 | import Membership from './Membership'; 2 | 3 | export default Membership; 4 | -------------------------------------------------------------------------------- /src/pages/OrderList/index.js: -------------------------------------------------------------------------------- 1 | import OrderList from './OrderList'; 2 | 3 | export default OrderList; 4 | -------------------------------------------------------------------------------- /src/pages/UserLogin/index.js: -------------------------------------------------------------------------------- 1 | import UserLogin from './UserLogin'; 2 | 3 | export default UserLogin; 4 | -------------------------------------------------------------------------------- /src/layouts/BasicLayout/components/Aside/index.js: -------------------------------------------------------------------------------- 1 | import Aside from './Aside'; 2 | 3 | export default Aside; 4 | -------------------------------------------------------------------------------- /src/layouts/BasicLayout/components/Logo/index.js: -------------------------------------------------------------------------------- 1 | import Logo from './Logo'; 2 | 3 | export default Logo; 4 | -------------------------------------------------------------------------------- /src/components/CustomForm/index.jsx: -------------------------------------------------------------------------------- 1 | import CustomForm from './CustomForm'; 2 | 3 | export default CustomForm; 4 | -------------------------------------------------------------------------------- /src/components/CustomTable/index.js: -------------------------------------------------------------------------------- 1 | import CustomTable from './CustomTable'; 2 | 3 | export default CustomTable; 4 | -------------------------------------------------------------------------------- /src/layouts/BasicLayout/components/Footer/index.js: -------------------------------------------------------------------------------- 1 | import Footer from './Footer'; 2 | 3 | export default Footer; 4 | -------------------------------------------------------------------------------- /src/pages/UserRegister/index.js: -------------------------------------------------------------------------------- 1 | import UserRegister from './UserRegister'; 2 | 3 | export default UserRegister; 4 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | # 忽略目录 2 | build/ 3 | tests/ 4 | demo/ 5 | 6 | # node 覆盖率文件 7 | coverage/ 8 | 9 | # 忽略文件 10 | **/*-min.js 11 | **/*.min.js 12 | -------------------------------------------------------------------------------- /src/layouts/BasicLayout/components/Logo/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Saseke/poseidon-admin/HEAD/src/layouts/BasicLayout/components/Logo/images/logo.png -------------------------------------------------------------------------------- /src/layouts/BasicLayout/components/Aside/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Saseke/poseidon-admin/HEAD/src/layouts/BasicLayout/components/Aside/images/avatar.png -------------------------------------------------------------------------------- /src/layouts/BasicLayout/components/Header/images/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Saseke/poseidon-admin/HEAD/src/layouts/BasicLayout/components/Header/images/avatar.png -------------------------------------------------------------------------------- /src/layouts/BasicLayout/index.scss: -------------------------------------------------------------------------------- 1 | .ice-design-layout { 2 | min-width: 1200px; 3 | 4 | .ice-layout-main { 5 | padding: 0; 6 | background: #f5f5f5; 7 | .main-container { 8 | padding: 20px; 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false 13 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/ignore-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | 6 | # production 7 | /build 8 | /dist 9 | 10 | # misc 11 | .idea/ 12 | .happypack 13 | .DS_Store 14 | 15 | npm-debug.log* 16 | yarn-debug.log* 17 | yarn-error.log* 18 | -------------------------------------------------------------------------------- /src/pages/AddGoods/AddGoods.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import GoodsForm from './components/GoodsForm'; 3 | 4 | export default class AddGoods extends Component { 5 | render() { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/pages/AddReserve/AddReserve.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import ReserveForm from './components/ReserveForm'; 3 | 4 | export default class AddReserve extends Component { 5 | render() { 6 | return ( 7 |
8 | 9 |
10 | ); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 商家管理系统 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /src/pages/Membership/Membership.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Table from './components/Table'; 3 | import PageHead from '../../components/PageHead'; 4 | 5 | export default class Membership extends Component { 6 | render() { 7 | return ( 8 |
9 | 10 | 11 | 12 | ); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import ReactDOM from 'react-dom'; 2 | // 载入默认全局样式 normalize 、.clearfix 和一些 mixin 方法等 3 | import '@alifd/next/reset.scss'; 4 | import router from './router'; 5 | 6 | const ICE_CONTAINER = document.getElementById('ice-container'); 7 | 8 | if (!ICE_CONTAINER) { 9 | throw new Error('当前页面不存在
节点.'); 10 | } 11 | 12 | ReactDOM.render(router, ICE_CONTAINER); 13 | -------------------------------------------------------------------------------- /src/layouts/BasicLayout/components/Footer/Footer.scss: -------------------------------------------------------------------------------- 1 | .ice-design-layout-footer-body { 2 | width: 100%; 3 | margin: 20px auto; 4 | padding: 0 20px; 5 | display: flex; 6 | justify-content: space-between; 7 | align-items: center; 8 | .copyright { 9 | color: #666; 10 | line-height: 1.5; 11 | font-size: 12px; 12 | text-align: left; 13 | } 14 | .copyright-link { 15 | color: #666; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/layouts/BasicLayout/components/Logo/index.module.scss: -------------------------------------------------------------------------------- 1 | .container { 2 | display: flex; 3 | align-items: center; 4 | margin-right: 20px; 5 | } 6 | .logoText { 7 | color: $color-brand1-6 !important; 8 | display: block; 9 | overflow: hidden; 10 | max-width: 180px; 11 | font-size: 30px; 12 | white-space: nowrap; 13 | margin-left: 10px; 14 | font-weight: bold; 15 | text-overflow: ellipsis; 16 | text-decoration: none; 17 | } 18 | -------------------------------------------------------------------------------- /src/layouts/BasicLayout/components/Aside/Aside.scss: -------------------------------------------------------------------------------- 1 | .aside-custom-menu { 2 | width: 240px; 3 | .user-info { 4 | display: flex; 5 | align-items: center; 6 | background: #fff; 7 | justify-content: center; 8 | padding: 20px 0; 9 | .user-avatar { 10 | margin-right: 12px; 11 | border-radius: 4px; 12 | } 13 | 14 | .user-department { 15 | font-size: 12px; 16 | } 17 | } 18 | .ice-menu-item-text { 19 | padding-left: 1em; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/layouts/BasicLayout/components/Logo/Logo.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | import styles from './index.module.scss'; 4 | 5 | export default class Logo extends Component { 6 | render() { 7 | return ( 8 |
9 | 10 | {this.props.text || 'LOGO'} 11 | 12 |
13 | ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /src/layouts/UserLayout/components/Header/index.scss: -------------------------------------------------------------------------------- 1 | .nav-menu { 2 | .arrow-up-icon, 3 | .arrow-down-icon { 4 | position: absolute; 5 | right: 15px; 6 | top: 0; 7 | z-index: 1; 8 | transition: 0.3s ease; 9 | } 10 | .sub-navs, 11 | .arrow-up-icon { 12 | display: none; 13 | } 14 | &:hover { 15 | background: #272b2f; 16 | .sub-navs, 17 | .arrow-up-icon { 18 | display: block; 19 | } 20 | .arrow-down-icon { 21 | display: none; 22 | } 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/pages/Membership/components/FilterTag/index.module.scss: -------------------------------------------------------------------------------- 1 | .filterItem { 2 | height: 28px; 3 | display: flex; 4 | align-items: center; 5 | margin-bottom: 20px; 6 | } 7 | .filterLabel { 8 | width: 80px; 9 | font-size: 14px; 10 | } 11 | .filterText { 12 | cursor: pointer; 13 | font-size: 12px; 14 | margin-right: 15px; 15 | } 16 | .activeText { 17 | composes: filterText; 18 | color: #fff; 19 | padding: 5px 15px; 20 | min-height: 60px; 21 | background: $color-brand1-6; 22 | border-radius: 20px; 23 | } 24 | -------------------------------------------------------------------------------- /src/layouts/BasicLayout/components/Header/index.scss: -------------------------------------------------------------------------------- 1 | .header-container { 2 | width: 100%; 3 | height: 62px; 4 | padding: 0 20px; 5 | display: flex; 6 | align-items: center; 7 | justify-content: flex-end; 8 | background: $color-brand1-6; 9 | box-shadow: 0 1px 4px rgba(0, 21, 41, 0.08); 10 | 11 | .header-navbar { 12 | display: flex; 13 | flex-direction: row; 14 | .next-menu { 15 | .next-menu-item { 16 | i { 17 | padding-right: 1em; 18 | } 19 | } 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ice-commodity-management-admin 2 | 3 | ## 使用 4 | 5 | - 启动调试服务: `npm start` 6 | - 构建 dist: `npm run build` 7 | 8 | ## 目录结构 9 | 10 | - react-router @4.x 默认采用 hashHistory 的单页应用 11 | - 入口文件: `src/index.js` 12 | - 导航配置: `src/menuConfig.js` 13 | - 路由配置: `src/routerConfig.js` 14 | - 路由入口: `src/router.jsx` 15 | - 布局文件: `src/layouts` 16 | - 通用组件: `src/components` 17 | - 页面文件: `src/pages` 18 | 19 | ## 主题配置 20 | 21 | - 默认主题:@icedesign/theme 22 | - 可选主题:@alifd/theme-1 23 | 24 | ## 效果图 25 | 26 | ![screenshot](https://img.alicdn.com/tfs/TB1cmQaCZbpK1RjSZFyXXX_qFXa-2872-1580.png) 27 | -------------------------------------------------------------------------------- /src/router.jsx: -------------------------------------------------------------------------------- 1 | /** 2 | * 定义应用路由 3 | */ 4 | import { HashRouter, Switch, Route } from 'react-router-dom'; 5 | import React from 'react'; 6 | import UserLayout from './layouts/UserLayout'; 7 | import BasicLayout from './layouts/BasicLayout'; 8 | 9 | // 按照 Layout 分组路由 10 | // UserLayout 对应的路由:/user/xxx 11 | // BasicLayout 对应的路由:/xxx 12 | const router = () => { 13 | return ( 14 | 15 | 16 | 17 | 18 | 19 | 20 | ); 21 | }; 22 | 23 | export default router(); 24 | -------------------------------------------------------------------------------- /src/pages/Goods/Goods.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { withRouter } from 'react-router-dom'; 3 | import Table from './components/Table'; 4 | import PageHead from '../../components/PageHead'; 5 | 6 | @withRouter 7 | export default class Goods extends Component { 8 | handleClick = () => { 9 | this.props.history.push('add/goods'); 10 | }; 11 | 12 | render() { 13 | return ( 14 |
15 | 20 |
21 | 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/pages/Reserve/Reserve.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { withRouter } from 'react-router-dom'; 3 | import Table from './components/Table'; 4 | import PageHead from '../../components/PageHead'; 5 | 6 | @withRouter 7 | export default class Reserve extends Component { 8 | handleClick = () => { 9 | this.props.history.push('add/reserve'); 10 | }; 11 | 12 | render() { 13 | return ( 14 |
15 | 20 |
21 | 22 | ); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/pages/Asset/Asset.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Overview from '../../components/Overview'; 3 | import PageHead from '../../components/PageHead'; 4 | import AssetTab from './components/AssetTab'; 5 | 6 | const MOCK_DATA = [ 7 | { 8 | title: '可用余额(元)', 9 | value: '0.00', 10 | }, 11 | { 12 | title: '待结算(元)', 13 | value: '0.00', 14 | }, 15 | { 16 | title: '储值资金(元)', 17 | value: '0.00', 18 | }, 19 | ]; 20 | 21 | export default class Asset extends Component { 22 | render() { 23 | return ( 24 |
25 | 26 | 27 | 28 |
29 | ); 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/layouts/UserLayout/components/Header/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | import './index.scss'; 4 | 5 | export default () => { 6 | return ( 7 |
8 | 9 | LOGO 10 | 11 |
12 | ); 13 | }; 14 | 15 | const styles = { 16 | container: { 17 | height: '60px', 18 | borderBottom: '1px solid rgba(255, 255, 255, 0.3)', 19 | display: 'flex', 20 | justifyContent: 'space-between', 21 | }, 22 | logoLink: { 23 | display: 'flex', 24 | alignItems: 'center', 25 | fontSize: '24px', 26 | fontWeight: 'bold', 27 | paddingLeft: '20px', 28 | color: '#fff', 29 | }, 30 | }; 31 | -------------------------------------------------------------------------------- /src/pages/Dashboard/Dashboard.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Overview from '../../components/Overview'; 3 | import QuickNav from './components/QuickNav'; 4 | import SalesChart from './components/SalesChart'; 5 | import RevenueChart from './components/RevenueChart'; 6 | import ReserveChart from './components/ReserveChart'; 7 | import PaymentChart from './components/PaymentChart'; 8 | import data from './data'; 9 | 10 | export default class Dashboard extends Component { 11 | render() { 12 | return ( 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | ); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/layouts/BasicLayout/MainRoutes.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Switch, Route, Redirect } from 'react-router-dom'; 3 | import NotFound from '../../components/NotFound'; 4 | import routerData from '../../routerConfig'; 5 | 6 | class MainRoutes extends Component { 7 | /** 8 | * 渲染路由组件 9 | */ 10 | renderNormalRoute = (item, index) => { 11 | return item.component ? ( 12 | 18 | ) : null; 19 | }; 20 | 21 | render() { 22 | return ( 23 | 24 | {/* 渲染路由表 */} 25 | {routerData.map(this.renderNormalRoute)} 26 | 27 | {/* 根路由默认重定向到 /dashboard */} 28 | 29 | 30 | {/* 未匹配到的路由重定向到 NotFound */} 31 | 32 | 33 | ); 34 | } 35 | } 36 | 37 | export default MainRoutes; 38 | -------------------------------------------------------------------------------- /src/layouts/BasicLayout/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import Layout from '@icedesign/layout'; 3 | import Header from './components/Header'; 4 | import Aside from './components/Aside'; 5 | import Footer from './components/Footer'; 6 | import MainRoutes from './MainRoutes'; 7 | import './index.scss'; 8 | 9 | export default class BasicLayout extends Component { 10 | render() { 11 | return ( 12 | 17 | 18 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | ); 45 | } 46 | } 47 | 48 | export default ReserveChart; 49 | -------------------------------------------------------------------------------- /src/layouts/UserLayout/components/Footer/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export default () => { 4 | return ( 5 |
6 |
7 | 8 | 帮助 9 | 10 | 11 | 隐私 12 | 13 | 14 | 条款 15 | 16 |
17 |
阿里巴巴集团 © 2018 版权所有
18 |
19 | ); 20 | }; 21 | 22 | const styles = { 23 | footer: { 24 | display: 'flex', 25 | flexDirection: 'column', 26 | alignItems: 'center', 27 | justifyContent: 'center', 28 | position: 'fixed', 29 | left: '0', 30 | right: '0', 31 | bottom: '20px', 32 | }, 33 | links: { 34 | marginBottom: '8px', 35 | }, 36 | link: { 37 | fontSize: '13px', 38 | marginRight: '40px', 39 | color: '#fff', 40 | }, 41 | copyright: { 42 | fontSize: '13px', 43 | color: '#fff', 44 | lineHeight: 1.5, 45 | textAlign: 'right', 46 | }, 47 | }; 48 | -------------------------------------------------------------------------------- /src/layouts/BasicLayout/components/Footer/Footer.jsx: -------------------------------------------------------------------------------- 1 | import React, { PureComponent } from 'react'; 2 | import Layout from '@icedesign/layout'; 3 | import cx from 'classnames'; 4 | import Logo from '../Logo'; 5 | 6 | import './Footer.scss'; 7 | 8 | export default class Footer extends PureComponent { 9 | render() { 10 | const { className, style } = this.props; 11 | return ( 12 | 20 |
21 |
22 | 23 |
24 |
25 | © 2018 Theme designed by{' '} 26 | 32 | ICE 33 | 34 |
35 |
36 |
37 | ); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/pages/Dashboard/components/PaymentChart/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Grid } from '@alifd/next'; 3 | import IceContainer from '@icedesign/container'; 4 | import DoughnutChart from '../DoughnutChart'; 5 | 6 | const { Row, Col } = Grid; 7 | 8 | const MOCK_DARA = { 9 | payment: [ 10 | { 11 | item: '现金', 12 | count: 20, 13 | }, 14 | { 15 | item: '微信', 16 | count: 10, 17 | }, 18 | { 19 | item: '支付宝', 20 | count: 70, 21 | }, 22 | ], 23 | income: [ 24 | { 25 | item: '现金', 26 | count: 60, 27 | }, 28 | { 29 | item: '微信', 30 | count: 30, 31 | }, 32 | { 33 | item: '支付宝', 34 | count: 10, 35 | }, 36 | ], 37 | }; 38 | 39 | class ReserveChart extends React.Component { 40 | render() { 41 | return ( 42 | 43 | 44 |
45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | ); 53 | } 54 | } 55 | 56 | export default ReserveChart; 57 | -------------------------------------------------------------------------------- /src/menuConfig.js: -------------------------------------------------------------------------------- 1 | // 菜单配置 2 | // headerMenuConfig:头部导航配置 3 | // asideMenuConfig:侧边导航配置 4 | 5 | const headerMenuConfig = [ 6 | { 7 | name: '反馈', 8 | path: 'https://github.com/alibaba/ice', 9 | external: true, 10 | newWindow: true, 11 | icon: 'message', 12 | }, 13 | { 14 | name: '帮助', 15 | path: 'https://alibaba.github.io/ice', 16 | external: true, 17 | newWindow: true, 18 | icon: 'bangzhu', 19 | }, 20 | { 21 | name: '退出', 22 | path: '/user/login', 23 | icon: 'yonghu', 24 | }, 25 | ]; 26 | 27 | const asideMenuConfig = [ 28 | { 29 | name: '工作台', 30 | path: '/dashboard', 31 | icon: 'home2', 32 | }, 33 | { 34 | name: '资产管理', 35 | path: '/asset', 36 | icon: 'cascades', 37 | }, 38 | { 39 | name: '商品管理', 40 | path: '/goods', 41 | icon: 'shopcar', 42 | }, 43 | { 44 | name: '添加商品', 45 | path: '/add/goods', 46 | icon: 'publish', 47 | }, 48 | { 49 | name: '预约管理', 50 | path: '/reserve', 51 | icon: 'clock', 52 | }, 53 | { 54 | name: '添加预约', 55 | path: '/add/reserve', 56 | icon: 'edit2', 57 | }, 58 | { 59 | name: '订单管理', 60 | path: '/order', 61 | icon: 'shopcar', 62 | }, 63 | { 64 | name: '会员管理', 65 | path: '/membership', 66 | icon: 'menu', 67 | }, 68 | ]; 69 | 70 | export { headerMenuConfig, asideMenuConfig }; 71 | -------------------------------------------------------------------------------- /src/pages/Dashboard/components/SalesChart/ColumnChart.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Chart, Geom } from 'bizcharts'; 3 | 4 | export default class ColumnChart extends Component { 5 | render() { 6 | const { color } = this.props; 7 | const data = [ 8 | { month: '1', sales: 38 }, 9 | { month: '2', sales: 52 }, 10 | { month: '3', sales: 61 }, 11 | { month: '4', sales: 80 }, 12 | { month: '5', sales: 65 }, 13 | { month: '6', sales: 60 }, 14 | { month: '7', sales: 60 }, 15 | { month: '8', sales: 58 }, 16 | { month: '9', sales: 48 }, 17 | { month: '10', sales: 50 }, 18 | { month: '11', sales: 40 }, 19 | { month: '12', sales: 40 }, 20 | ]; 21 | const cols = { 22 | sales: { tickInterval: 20 }, 23 | }; 24 | return ( 25 | 32 | 38 | 45 | 46 | ); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/routerConfig.js: -------------------------------------------------------------------------------- 1 | // 以下文件格式为描述路由的协议格式 2 | // 你可以调整 routerConfig 里的内容 3 | // 变量名 routerConfig 为 iceworks 检测关键字,请不要修改名称 4 | 5 | import UserLogin from './pages/UserLogin'; 6 | import UserRegister from './pages/UserRegister'; 7 | import Dashboard from './pages/Dashboard'; 8 | import Reserve from './pages/Reserve'; 9 | import Asset from './pages/Asset'; 10 | import OrderList from './pages/OrderList'; 11 | import Goods from './pages/Goods'; 12 | import Membership from './pages/Membership'; 13 | import AddReserve from './pages/AddReserve'; 14 | import AddGoods from './pages/AddGoods'; 15 | 16 | const routerConfig = [ 17 | { 18 | path: '/user/login', 19 | component: UserLogin, 20 | }, 21 | { 22 | path: '/user/register', 23 | component: UserRegister, 24 | }, 25 | { 26 | path: '/dashboard', 27 | component: Dashboard, 28 | }, 29 | { 30 | path: '/reserve', 31 | component: Reserve, 32 | }, 33 | { 34 | path: '/asset', 35 | component: Asset, 36 | }, 37 | { 38 | path: '/goods', 39 | component: Goods, 40 | }, 41 | { 42 | path: '/order', 43 | component: OrderList, 44 | }, 45 | { 46 | path: '/membership', 47 | component: Membership, 48 | }, 49 | { 50 | path: '/add/reserve', 51 | component: AddReserve, 52 | }, 53 | { 54 | path: '/add/goods', 55 | component: AddGoods, 56 | }, 57 | ]; 58 | 59 | export default routerConfig; 60 | -------------------------------------------------------------------------------- /src/components/NotFound/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | import IceContainer from '@icedesign/container'; 4 | import './index.scss'; 5 | 6 | export default class NotFound extends Component { 7 | static displayName = 'NotFound'; 8 | 9 | render() { 10 | return ( 11 |
12 | 13 |
14 | 页面不存在 20 |
21 |

22 | 抱歉,你访问的页面不存在 23 |

24 |

25 | 您要找的页面没有找到,请返回 26 | 首页 27 | 继续浏览 28 |

29 |
30 |
31 |
32 |
33 | ); 34 | } 35 | } 36 | 37 | const styles = { 38 | exceptionContent: { 39 | display: 'flex', 40 | justifyContent: 'center', 41 | alignItems: 'center', 42 | }, 43 | title: { 44 | color: '#333', 45 | }, 46 | description: { 47 | color: '#666', 48 | }, 49 | }; 50 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "babel-eslint", 4 | "extends": "eslint-config-airbnb", 5 | "parserOptions": { 6 | "ecmaVersion": 6, 7 | "ecmaFeatures": { 8 | "jsx": true, 9 | "experimentalObjectRestSpread": true 10 | } 11 | }, 12 | "env": { 13 | "browser": true, 14 | "mocha": true 15 | }, 16 | "plugins": ["react", "babel"], 17 | "rules": { 18 | "react/prefer-stateless-function": 0, 19 | "no-console": 0, 20 | "jsx-a11y/label-has-for": 0, 21 | "jsx-a11y/no-static-element-interactions": 0, 22 | "jsx-a11y/anchor-has-content": 0, 23 | "jsx-a11y/click-events-have-key-events": 0, 24 | "jsx-a11y/anchor-is-valid": 0, 25 | "react/no-array-index-key": 0, 26 | "func-names": 0, 27 | "arrow-body-style": 0, 28 | "no-use-before-define": 0, 29 | "react/sort-comp": 0, 30 | "react/prop-types": 0, 31 | "react/jsx-first-prop-new-line": 0, 32 | "react/jsx-filename-extension": [ 33 | 1, 34 | { 35 | "extensions": [".js", ".jsx"] 36 | } 37 | ], 38 | "import/extensions": 0, 39 | "import/no-unresolved": 0, 40 | "import/no-extraneous-dependencies": 0, 41 | "prefer-destructuring": 0, 42 | "no-param-reassign": 0, 43 | "no-return-assign": 0, 44 | "max-len": 0, 45 | "consistent-return": 0, 46 | "no-redeclare": 0, 47 | "react/require-extension": 0, 48 | "react/no-danger": 0, 49 | "comma-dangle": ["error", "always-multiline"], 50 | "function-paren-newline": 0, 51 | "object-curly-newline": 0, 52 | "no-restricted-globals": 0, 53 | "react/jsx-no-bind": 0, 54 | "no-mixed-operators": 0, 55 | "global-require": 0 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /src/components/Overview/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import IceContainer from '@icedesign/container'; 3 | import { Grid, Icon, Balloon } from '@alifd/next'; 4 | 5 | const { Row, Col } = Grid; 6 | 7 | export default class Overview extends Component { 8 | renderHelp = () => { 9 | return ( 10 | } 12 | align="t" 13 | alignEdge 14 | closable={false} 15 | > 16 | 相关说明 17 | 18 | ); 19 | }; 20 | 21 | render() { 22 | const { data = [], title = '', col = 4 } = this.props; 23 | return ( 24 | 25 | 26 | {data.map((item, index) => { 27 | const hasBorder = (index + 1) % col !== 0 ? styles.border : {}; 28 | return ( 29 |
34 |
35 | {item.title} {this.renderHelp()} 36 |
37 |
{item.value}
38 | 39 | ); 40 | })} 41 | 42 | 43 | ); 44 | } 45 | } 46 | 47 | const styles = { 48 | item: { 49 | display: 'flex', 50 | flexDirection: 'column', 51 | justifyContent: 'center', 52 | alignItems: 'center', 53 | margin: '20px 0', 54 | }, 55 | border: { 56 | borderRight: '1px solid #F0F0F0', 57 | }, 58 | title: { 59 | fontSize: '12px', 60 | marginBottom: '10px', 61 | }, 62 | value: { 63 | fontSize: '22px', 64 | color: '#333', 65 | }, 66 | }; 67 | -------------------------------------------------------------------------------- /src/layouts/UserLayout/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Switch, Route, Redirect } from 'react-router-dom'; 3 | import { Grid } from '@alifd/next'; 4 | import Footer from './components/Footer'; 5 | import Intro from './components/Intro'; 6 | import routerData from '../../routerConfig'; 7 | 8 | const { Row, Col } = Grid; 9 | 10 | export default class UserLayout extends Component { 11 | render() { 12 | return ( 13 |
14 | 15 |
16 | 17 | 18 | 19 |
20 | 21 | {routerData.map((item, index) => { 22 | return item.component ? ( 23 | 29 | ) : null; 30 | })} 31 | 32 | 33 | 34 |
35 | 36 | 37 |
38 | 39 | ); 40 | } 41 | } 42 | 43 | const styles = { 44 | container: { 45 | position: 'relative', 46 | width: '100wh', 47 | minWidth: '1200px', 48 | height: '100vh', 49 | backgroundImage: 50 | 'url(https://img.alicdn.com/tfs/TB1OpAhC7zoK1RjSZFlXXai4VXa-1350-900.jpg)', 51 | backgroundSize: 'cover', 52 | display: 'flex', 53 | flexDirection: 'column', 54 | }, 55 | row: { 56 | display: 'flex', 57 | alignItems: 'center', 58 | justifyContent: 'center', 59 | flex: '1', 60 | }, 61 | form: { 62 | display: 'flex', 63 | alignItems: 'center', 64 | justifyContent: 'center', 65 | }, 66 | }; 67 | -------------------------------------------------------------------------------- /src/pages/Dashboard/data.js: -------------------------------------------------------------------------------- 1 | const MOCK_DATA = { 2 | data0: [ 3 | { 4 | title: '营业收入', 5 | value: '123,459', 6 | }, 7 | { 8 | title: '充值收入', 9 | value: '3,954', 10 | }, 11 | { 12 | title: '现金支付', 13 | value: '509,432', 14 | }, 15 | { 16 | title: '网上支付', 17 | value: '249,234', 18 | }, 19 | { 20 | title: '实体下单', 21 | value: '12,323', 22 | }, 23 | { 24 | title: '网上下单', 25 | value: '452,234', 26 | }, 27 | { 28 | title: '新增用户', 29 | value: '2,334', 30 | }, 31 | { 32 | title: '新增会员', 33 | value: '1,234', 34 | }, 35 | ], 36 | data1: [ 37 | { 38 | title: '品项收入', 39 | value: '594,128', 40 | }, 41 | { 42 | title: '充值收入', 43 | value: '35,042', 44 | }, 45 | { 46 | title: '售卡收入', 47 | value: '3,904', 48 | }, 49 | { 50 | title: '耗卡金额', 51 | value: '2,309', 52 | }, 53 | ], 54 | data2: [ 55 | { 56 | title: '新增会员数', 57 | value: '2,323', 58 | }, 59 | { 60 | title: '发卡张数', 61 | value: '4,065', 62 | }, 63 | { 64 | title: '消费客户数', 65 | value: '3,409', 66 | }, 67 | { 68 | title: '消费客单价', 69 | value: '213', 70 | }, 71 | ], 72 | data3: [ 73 | { 74 | title: '积分发放', 75 | value: '5,3409', 76 | }, 77 | { 78 | title: '积分消耗', 79 | value: '23,232', 80 | }, 81 | ], 82 | data4: [ 83 | { 84 | title: '持卡会员总人数', 85 | value: '32,312', 86 | }, 87 | { 88 | title: '售卡总张数', 89 | value: '45,324', 90 | }, 91 | { 92 | title: '超时预约单数', 93 | value: '567', 94 | }, 95 | { 96 | title: '取消预约单数', 97 | value: '856', 98 | }, 99 | ], 100 | }; 101 | 102 | export default MOCK_DATA; 103 | -------------------------------------------------------------------------------- /src/pages/Reserve/components/Filter/index.js: -------------------------------------------------------------------------------- 1 | /* eslint react/no-string-refs:0 */ 2 | import React, { Component } from 'react'; 3 | import { DatePicker, Button } from '@alifd/next'; 4 | import { 5 | FormBinderWrapper as IceFormBinderWrapper, 6 | FormBinder as IceFormBinder, 7 | FormError as IceFormError, 8 | } from '@icedesign/form-binder'; 9 | 10 | const { RangePicker } = DatePicker; 11 | 12 | export default class Filter extends Component { 13 | state = { 14 | value: {}, 15 | }; 16 | 17 | formChange = (value) => { 18 | this.props.onChange(value); 19 | }; 20 | 21 | buttonChange = () => { 22 | this.props.onChange(); 23 | }; 24 | 25 | render() { 26 | return ( 27 | 32 |
33 |
34 | 到店时间: 35 | 36 | 37 | 38 |
39 | 40 |
41 |
42 |
43 | {['今天', '明天', '本周'].map((item, index) => { 44 | return ( 45 | 53 | ); 54 | })} 55 |
56 |
57 |
58 | ); 59 | } 60 | } 61 | 62 | const styles = { 63 | formContent: { 64 | display: 'flex', 65 | }, 66 | formItem: { 67 | display: 'flex', 68 | alignItems: 'center', 69 | margin: '10px 0', 70 | }, 71 | formLabel: { 72 | minWidth: '80px', 73 | }, 74 | }; 75 | -------------------------------------------------------------------------------- /src/pages/Membership/components/FilterTag/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import styles from './index.module.scss'; 3 | 4 | const MOCK_DATA = [ 5 | { 6 | selected: '全部', 7 | label: '消费频次', 8 | value: ['全部', '1月未消费', '2月未消费', '3月未消费', '4月未消费'], 9 | }, 10 | { 11 | selected: '全部', 12 | label: '消费次数', 13 | value: ['全部', '1次以内', '2次以内', '3次以内', '4次以上'], 14 | }, 15 | { 16 | selected: '全部', 17 | label: '会员等级', 18 | value: ['全部', '普通会员', '白银会员', '黄金会员', 'VIP 会员'], 19 | }, 20 | { 21 | selected: '全部', 22 | label: '会员来源', 23 | value: ['全部', '线上顾客', '线下顾客', '广告引流', '未知来源'], 24 | }, 25 | ]; 26 | 27 | export default class FilterTag extends Component { 28 | state = { 29 | data: MOCK_DATA, 30 | }; 31 | 32 | handleClick = (value, index) => { 33 | const { data } = this.state; 34 | data[index].selected = value; 35 | this.setState( 36 | { 37 | data, 38 | }, 39 | () => { 40 | this.props.onChange(); 41 | } 42 | ); 43 | }; 44 | 45 | render() { 46 | const { data } = this.state; 47 | return ( 48 |
49 | {data.map((item, index) => { 50 | const lastItem = index === data.length - 1; 51 | const lastItemStyle = lastItem ? { marginBottom: 10 } : null; 52 | return ( 53 |
54 |
{item.label}:
55 |
56 | {item.value.map((text, idx) => { 57 | const activeStyle = 58 | item.selected === text ? styles.activeText : styles.filterText; 59 | return ( 60 | this.handleClick(text, index)} 62 | className={activeStyle} 63 | key={idx} 64 | > 65 | {text} 66 | 67 | ); 68 | })} 69 |
70 |
71 | ); 72 | })} 73 |
74 | ); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /src/pages/Dashboard/components/DoughnutChart/index.jsx: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import { Chart, Geom, Axis, Tooltip, Coord, Legend, Guide } from 'bizcharts'; 3 | import DataSet from '@antv/data-set'; 4 | 5 | class Donut extends React.Component { 6 | render() { 7 | const { text = '预约付款金额', data = [] } = this.props; 8 | const { DataView } = DataSet; 9 | const { Html } = Guide; 10 | const dv = new DataView(); 11 | dv.source(data).transform({ 12 | type: 'percent', 13 | field: 'count', 14 | dimension: 'item', 15 | as: 'percent', 16 | }); 17 | const cols = { 18 | percent: { 19 | formatter: (val) => { 20 | val = `${val * 100}%`; 21 | return val; 22 | }, 23 | }, 24 | }; 25 | return ( 26 | 27 | 28 | 29 | { 34 | return val; 35 | }} 36 | /> 37 | 41 | 42 | ${text}
0.00`} 45 | alignX="middle" 46 | alignY="middle" 47 | /> 48 |
49 | { 56 | percent = `${percent * 100}%`; 57 | return { 58 | name: item, 59 | value: percent, 60 | }; 61 | }, 62 | ]} 63 | style={{ 64 | lineWidth: 1, 65 | stroke: '#fff', 66 | }} 67 | /> 68 |
69 | ); 70 | } 71 | } 72 | 73 | export default Donut; 74 | -------------------------------------------------------------------------------- /src/pages/Dashboard/components/RevenueChart/DonutChart.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Chart, Geom, Axis, Tooltip, Coord, Legend, Guide } from 'bizcharts'; 3 | import DataSet from '@antv/data-set'; 4 | 5 | export default class DonutChart extends Component { 6 | render() { 7 | const { DataView } = DataSet; 8 | const { Html } = Guide; 9 | 10 | // MOCK 数据,实际业务按需进行替换 11 | const data = [ 12 | { 13 | item: '实体收入', 14 | count: 40, 15 | }, 16 | { 17 | item: '网店收入', 18 | count: 21, 19 | }, 20 | ]; 21 | const dv = new DataView(); 22 | dv.source(data).transform({ 23 | type: 'percent', 24 | field: 'count', 25 | dimension: 'item', 26 | as: 'percent', 27 | }); 28 | const cols = { 29 | percent: { 30 | formatter: (val) => { 31 | val = `${val * 100}%`; 32 | return val; 33 | }, 34 | }, 35 | }; 36 | return ( 37 | 38 | 39 | 40 | 41 | 45 | 46 | 52 | 53 | { 60 | percent = `${percent * 100}%`; 61 | return { 62 | name: item, 63 | value: percent, 64 | }; 65 | }, 66 | ]} 67 | style={{ 68 | lineWidth: 1, 69 | stroke: '#fff', 70 | }} 71 | /> 72 | 73 | ); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/layouts/BasicLayout/components/Aside/Aside.jsx: -------------------------------------------------------------------------------- 1 | /* eslint no-undef:0, no-unused-expressions:0, array-callback-return:0 */ 2 | import React, { Component } from 'react'; 3 | import { Nav } from '@alifd/next'; 4 | import { withRouter, Link } from 'react-router-dom'; 5 | import FoundationSymbol from '@icedesign/foundation-symbol'; 6 | import IceImg from '@icedesign/img'; 7 | import Logo from '../Logo'; 8 | import { asideMenuConfig } from '../../../../menuConfig'; 9 | 10 | import './Aside.scss'; 11 | 12 | @withRouter 13 | export default class BasicLayout extends Component { 14 | render() { 15 | const { location } = this.props; 16 | const { pathname } = location; 17 | 18 | return ( 19 |
20 | 30 |
31 | 37 |
38 | 39 | 淘小宝 40 | 41 |
42 | 技术部 43 |
44 |
45 | 46 | 66 |
67 | ); 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/pages/Dashboard/components/QuickNav/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Link } from 'react-router-dom'; 3 | import IceContainer from '@icedesign/container'; 4 | import { Grid, Icon } from '@alifd/next'; 5 | 6 | const { Row, Col } = Grid; 7 | 8 | const MOCK_DATA = [ 9 | { 10 | title: '资产管理', 11 | icon: 'cart', 12 | color: '#5e83fb', 13 | to: '/asset', 14 | }, 15 | { 16 | title: '商品管理', 17 | icon: 'cart', 18 | color: '#f7da47', 19 | to: '/goods', 20 | }, 21 | { 22 | title: '预约管理', 23 | icon: 'cart', 24 | color: '#ee706d', 25 | to: '/reserve', 26 | }, 27 | { 28 | title: '订单管理', 29 | icon: 'cart', 30 | color: '#58ca9a', 31 | to: '/order', 32 | }, 33 | { 34 | title: '会员管理', 35 | icon: 'cart', 36 | color: '#58ca9a', 37 | to: '/membership', 38 | }, 39 | { 40 | title: '添加商品', 41 | icon: 'cart', 42 | color: '#447eff', 43 | to: '/add/goods', 44 | }, 45 | ]; 46 | 47 | export default class QuickNav extends Component { 48 | render() { 49 | return ( 50 | 51 | 52 | {MOCK_DATA.map((item, index) => { 53 | return ( 54 |
55 | 56 | 59 | 60 |
{item.title}
61 |
62 | 63 | 64 | ); 65 | })} 66 | 67 | 68 | ); 69 | } 70 | } 71 | 72 | const styles = { 73 | card: { 74 | display: 'flex', 75 | alignItems: 'center', 76 | justifyContent: 'center', 77 | }, 78 | link: { 79 | display: 'block', 80 | textDecoration: 'none', 81 | }, 82 | item: { 83 | display: 'flex', 84 | alignItems: 'center', 85 | justifyContent: 'center', 86 | }, 87 | icon: { 88 | marginRight: '5px', 89 | color: '#fff', 90 | }, 91 | title: { 92 | color: '#fff', 93 | fontSize: '14px', 94 | fontWeight: '450', 95 | }, 96 | }; 97 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@icedesign/commodity-management-scaffold", 3 | "version": "1.0.0", 4 | "description": "该模板适用于商家类管理后台,布局方式采用左侧固定,右侧自适应方式,适合大量数据展示和界面操作", 5 | "author": "ice-admin@alibaba-inc.com", 6 | "files": [ 7 | "src/", 8 | "build/", 9 | "public/", 10 | "tests/", 11 | "_gitignore", 12 | ".editorconfig", 13 | ".eslintignore", 14 | ".eslintrc" 15 | ], 16 | "dependencies": { 17 | "@alifd/next": "^1.x", 18 | "@antv/data-set": "^0.9.5", 19 | "@icedesign/container": "^1.x", 20 | "@icedesign/form-binder": "^1.x", 21 | "@icedesign/foundation-symbol": "^1.x", 22 | "@icedesign/img": "^1.x", 23 | "@icedesign/layout": "^1.x", 24 | "@icedesign/theme": "^1.x", 25 | "bizcharts": "^3.2.2", 26 | "enquire-js": "^0.1.2", 27 | "moment": "^2.23.0", 28 | "prop-types": "^15.5.8", 29 | "react": "^16.2.0", 30 | "react-dom": "^16.4.1", 31 | "react-router-dom": "^4.2.2" 32 | }, 33 | "publishConfig": { 34 | "registry": "http://registry.npmjs.com", 35 | "access": "public" 36 | }, 37 | "devDependencies": { 38 | "babel-eslint": "^8.0.3", 39 | "eslint": "^4.13.1", 40 | "eslint-config-airbnb": "^16.1.0", 41 | "eslint-plugin-babel": "^4.1.1", 42 | "eslint-plugin-import": "^2.8.0", 43 | "eslint-plugin-jsx-a11y": "^6.0.3", 44 | "eslint-plugin-react": "^7.5.1", 45 | "ice-scripts": "^1.6.0-next.3" 46 | }, 47 | "scripts": { 48 | "start": "ice dev", 49 | "build": "ice build", 50 | "lint": "eslint . --ext '.js,.jsx' --fix" 51 | }, 52 | "buildConfig": { 53 | "theme": "@icedesign/theme", 54 | "entry": "src/index.js", 55 | "localization": false, 56 | "output": { 57 | "publicPath": "./" 58 | } 59 | }, 60 | "scaffoldConfig": { 61 | "builder": "ice-scripts", 62 | "name": "ice-commodity-management-admin", 63 | "title": "商家管理系统", 64 | "categories": [ 65 | "行业领域" 66 | ], 67 | "screenshot": "https://img.alicdn.com/tfs/TB1cmQaCZbpK1RjSZFyXXX_qFXa-2872-1580.png", 68 | "screenshots": [ 69 | "https://img.alicdn.com/tfs/TB1NtNrDxjaK1RjSZKzXXXVwXXa-2872-1582.png", 70 | "https://img.alicdn.com/tfs/TB1jt7ZDgDqK1RjSZSyXXaxEVXa-2860-1580.png", 71 | "https://img.alicdn.com/tfs/TB1oUpsDyLaK1RjSZFxXXamPFXa-2872-1580.png" 72 | ] 73 | }, 74 | "engines": { 75 | "node": ">=8.0.0" 76 | }, 77 | "title": "poseidon-admin" 78 | } 79 | -------------------------------------------------------------------------------- /src/components/CustomTable/SearchFilter.jsx: -------------------------------------------------------------------------------- 1 | /* eslint react/no-string-refs:0,react/forbid-prop-types:0 */ 2 | import React, { Component } from 'react'; 3 | import PropTypes from 'prop-types'; 4 | import { Icon, Button } from '@alifd/next'; 5 | import CustomForm from '../CustomForm'; 6 | 7 | export default class SearchFilter extends Component { 8 | static displayName = 'SearchFilter'; 9 | 10 | static propTypes = { 11 | formConfig: PropTypes.array.isRequired, 12 | value: PropTypes.object.isRequired, 13 | onChange: PropTypes.func, 14 | onSubmit: PropTypes.func, 15 | onReset: PropTypes.func, 16 | }; 17 | 18 | static defaultProps = { 19 | onChange: () => {}, 20 | onSubmit: () => {}, 21 | onReset: () => {}, 22 | }; 23 | 24 | state = { 25 | showAdvancedFields: false, 26 | }; 27 | 28 | /** 29 | * 提交回调函数 30 | */ 31 | handleSubmit = (errors, value) => { 32 | if (errors) { 33 | console.log({ errors }); 34 | return; 35 | } 36 | 37 | this.props.onSubmit(value); 38 | }; 39 | 40 | /** 41 | * 高级搜索 42 | */ 43 | handleAdvancedSearch = () => { 44 | const { showAdvancedFields } = this.state; 45 | this.setState({ 46 | showAdvancedFields: !showAdvancedFields, 47 | }); 48 | }; 49 | 50 | /** 51 | * 渲染按钮 52 | */ 53 | renderExtraContent = () => { 54 | return ( 55 | 66 | ); 67 | }; 68 | 69 | render() { 70 | const { formConfig, value, onChange, onReset, hasAdvance } = this.props; 71 | const { showAdvancedFields } = this.state; 72 | 73 | const config = showAdvancedFields 74 | ? formConfig 75 | : formConfig.filter(item => !item.advanced); 76 | 77 | return ( 78 | 87 | ); 88 | } 89 | } 90 | 91 | const styles = { 92 | extraContent: { 93 | position: 'absolute', 94 | right: '0', 95 | bottom: '0', 96 | }, 97 | }; 98 | -------------------------------------------------------------------------------- /src/pages/Membership/components/FilterForm/index.js: -------------------------------------------------------------------------------- 1 | /* eslint react/no-string-refs:0 */ 2 | import React, { Component } from 'react'; 3 | import { Grid, DatePicker, Select } from '@alifd/next'; 4 | import { 5 | FormBinderWrapper as IceFormBinderWrapper, 6 | FormBinder as IceFormBinder, 7 | FormError as IceFormError, 8 | } from '@icedesign/form-binder'; 9 | 10 | const { Row, Col } = Grid; 11 | 12 | export default class Filter extends Component { 13 | state = { 14 | value: {}, 15 | }; 16 | 17 | formChange = (value) => { 18 | this.props.onChange(value); 19 | }; 20 | 21 | render() { 22 | return ( 23 | 28 | 29 | 30 |
31 | 注册时间: 32 | 33 | 34 | 35 |
36 | 37 |
38 |
39 | 40 | 41 |
42 | 生日时间: 43 | 44 | 45 | 46 |
47 | 48 |
49 |
50 | 51 | 52 |
53 | 归属门店: 54 | 55 | 60 | 61 |
62 | 63 |
64 |
65 | 66 | 67 | 68 | ); 69 | } 70 | } 71 | 72 | const styles = { 73 | formItem: { 74 | display: 'flex', 75 | alignItems: 'center', 76 | margin: '10px 0', 77 | }, 78 | formLabel: { 79 | minWidth: '80px', 80 | }, 81 | }; 82 | -------------------------------------------------------------------------------- /src/pages/Dashboard/components/SalesChart/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Grid, Icon } from '@alifd/next'; 3 | import ColumnChart from './ColumnChart'; 4 | 5 | const { Row, Col } = Grid; 6 | const mockData = [ 7 | { 8 | title: '年度销售数', 9 | amount: '1,293', 10 | percent: '15%', 11 | increase: true, 12 | color: '#fff', 13 | borderColor: '#4FD4A4', 14 | background: '#1BC98E', 15 | }, 16 | { 17 | title: '年度订单数', 18 | amount: '758', 19 | percent: '1.3%', 20 | increase: false, 21 | color: '#fff', 22 | borderColor: '#EB6C7A', 23 | background: '#E64758', 24 | }, 25 | { 26 | title: '年度会员数', 27 | amount: '3,659', 28 | percent: '20%', 29 | increase: true, 30 | color: '#fff', 31 | borderColor: '#B29FFF', 32 | background: '#9F85FF', 33 | }, 34 | { 35 | title: '年度总收入', 36 | amount: '298,234', 37 | percent: '12%', 38 | increase: false, 39 | color: '#fff', 40 | borderColor: '#E9E063', 41 | background: '#E5D936', 42 | }, 43 | ]; 44 | 45 | export default class SalesChart extends Component { 46 | render() { 47 | return ( 48 | 49 | {mockData.map((item, index) => { 50 | return ( 51 | 52 |
53 |
54 |

{item.title}

55 |
56 |

{item.amount}

57 |
58 | {item.percent}{' '} 59 | 64 |
65 |
66 |
67 | 68 |
69 | 70 | ); 71 | })} 72 | 73 | ); 74 | } 75 | } 76 | 77 | const styles = { 78 | content: { 79 | color: '#fff', 80 | borderRadius: '3px', 81 | }, 82 | summary: { 83 | padding: '20px', 84 | }, 85 | title: { 86 | margin: '0 0 10px 0', 87 | }, 88 | data: { 89 | display: 'flex', 90 | margin: '10px 0', 91 | }, 92 | amount: { 93 | margin: '0 15px 0 0', 94 | fontSize: '28px', 95 | }, 96 | percent: { 97 | display: 'flex', 98 | alignItems: 'flex-end', 99 | marginBottom: '4px', 100 | fontSize: '12px', 101 | }, 102 | arrowIcon: { 103 | marginLeft: '8px', 104 | }, 105 | }; 106 | -------------------------------------------------------------------------------- /src/pages/Goods/components/Filter/index.js: -------------------------------------------------------------------------------- 1 | /* eslint react/no-string-refs:0 */ 2 | import React, { Component } from 'react'; 3 | import { Grid, Input, Select } from '@alifd/next'; 4 | import { 5 | FormBinderWrapper as IceFormBinderWrapper, 6 | FormBinder as IceFormBinder, 7 | FormError as IceFormError, 8 | } from '@icedesign/form-binder'; 9 | 10 | const { Row, Col } = Grid; 11 | 12 | export default class Filter extends Component { 13 | state = { 14 | value: {}, 15 | }; 16 | 17 | formChange = (value) => { 18 | this.props.onChange(value); 19 | }; 20 | 21 | render() { 22 | return ( 23 | 28 | 29 | 30 |
31 | 商品名称: 32 | 33 | 34 | 35 |
36 | 37 |
38 |
39 | 40 | 41 |
42 | 商品分类: 43 | 44 | 49 | 50 |
51 | 52 |
53 |
54 | 55 | 56 |
57 | 归属门店: 58 | 59 | 64 | 65 |
66 | 67 |
68 |
69 | 70 | 71 | 72 | ); 73 | } 74 | } 75 | 76 | const styles = { 77 | formItem: { 78 | display: 'flex', 79 | alignItems: 'center', 80 | margin: '10px 0', 81 | }, 82 | formLabel: { 83 | minWidth: '80px', 84 | }, 85 | }; 86 | -------------------------------------------------------------------------------- /src/pages/Asset/components/AssetTab/TableFilter.jsx: -------------------------------------------------------------------------------- 1 | /* eslint react/no-string-refs:0 */ 2 | import React, { Component } from 'react'; 3 | import { Grid, DatePicker, Select } from '@alifd/next'; 4 | import { 5 | FormBinderWrapper as IceFormBinderWrapper, 6 | FormBinder as IceFormBinder, 7 | FormError as IceFormError, 8 | } from '@icedesign/form-binder'; 9 | 10 | const { Row, Col } = Grid; 11 | 12 | export default class Filter extends Component { 13 | state = { 14 | value: {}, 15 | }; 16 | 17 | formChange = (value) => { 18 | this.props.onChange(value); 19 | }; 20 | 21 | render() { 22 | return ( 23 | 28 | 29 | 30 |
31 | 时间筛选: 32 | 33 | 34 | 35 |
36 | 37 |
38 |
39 | 40 | 41 |
42 | 时间区间: 43 | 44 | 49 | 50 |
51 | 52 |
53 |
54 | 55 | 56 |
57 | 状态: 58 | 59 | 64 | 65 |
66 | 67 |
68 |
69 | 70 | 71 | 72 | ); 73 | } 74 | } 75 | 76 | const styles = { 77 | formItem: { 78 | display: 'flex', 79 | alignItems: 'center', 80 | margin: '10px 0', 81 | }, 82 | formLabel: { 83 | minWidth: '70px', 84 | }, 85 | }; 86 | -------------------------------------------------------------------------------- /src/pages/Asset/components/AssetTab/AssetTable.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Table, Pagination } from '@alifd/next'; 3 | import IceContainer from '@icedesign/container'; 4 | import TableFilter from './TableFilter'; 5 | 6 | // Random Numbers 7 | const random = (min, max) => { 8 | return Math.floor(Math.random() * (max - min + 1) + min); 9 | }; 10 | 11 | // MOCK 数据,实际业务按需进行替换 12 | const getData = (length = 10) => { 13 | return Array.from({ length }).map(() => { 14 | return { 15 | applyTime: `2018-12-1${random(1, 9)}`, 16 | transactionId: random(10000000, 100000000), 17 | amount: random(1000, 10000), 18 | endTime: `2019-06-1${random(1, 9)}`, 19 | applicant: ['淘小宝', '淘二宝'][random(0, 1)], 20 | state: ['已完成', '申请中'][random(0, 1)], 21 | }; 22 | }); 23 | }; 24 | 25 | export default class MembersshipTable extends Component { 26 | state = { 27 | current: 1, 28 | isLoading: false, 29 | data: [], 30 | }; 31 | 32 | componentDidMount() { 33 | this.fetchData(); 34 | } 35 | 36 | mockApi = (len) => { 37 | return new Promise((resolve) => { 38 | setTimeout(() => { 39 | resolve(getData(len)); 40 | }, 600); 41 | }); 42 | }; 43 | 44 | fetchData = (len) => { 45 | this.setState( 46 | { 47 | isLoading: true, 48 | }, 49 | () => { 50 | this.mockApi(len).then((data) => { 51 | this.setState({ 52 | data, 53 | isLoading: false, 54 | }); 55 | }); 56 | } 57 | ); 58 | }; 59 | 60 | handlePaginationChange = (current) => { 61 | this.setState( 62 | { 63 | current, 64 | }, 65 | () => { 66 | this.fetchData(); 67 | } 68 | ); 69 | }; 70 | 71 | handleFilterChange = () => { 72 | this.fetchData(5); 73 | }; 74 | 75 | renderOper = () => { 76 | return ( 77 |
78 | 详情 79 | 80 | 申请权限 81 |
82 | ); 83 | }; 84 | 85 | render() { 86 | const { isLoading, data, current } = this.state; 87 | 88 | return ( 89 |
90 | 91 | 92 |
93 | 94 | 95 | 96 | 97 | 98 | 99 |
100 | 105 | 106 |
107 | ); 108 | } 109 | } 110 | 111 | const styles = { 112 | pagination: { 113 | marginTop: '20px', 114 | textAlign: 'right', 115 | }, 116 | }; 117 | -------------------------------------------------------------------------------- /src/pages/AddReserve/components/ReserveForm/index.js: -------------------------------------------------------------------------------- 1 | /* eslint react/no-string-refs:0 */ 2 | import React, { Component } from 'react'; 3 | import IceContainer from '@icedesign/container'; 4 | import { Input, Button, Message } from '@alifd/next'; 5 | import { 6 | FormBinderWrapper as IceFormBinderWrapper, 7 | FormBinder as IceFormBinder, 8 | FormError as IceFormError, 9 | } from '@icedesign/form-binder'; 10 | import PageHead from '../../../../components/PageHead'; 11 | 12 | export default class ReserveForm extends Component { 13 | state = { 14 | value: {}, 15 | }; 16 | 17 | formChange = (value) => { 18 | console.log('value', value); 19 | }; 20 | 21 | validateAllFormField = () => { 22 | this.refs.form.validateAll((errors, values) => { 23 | if (errors) { 24 | return; 25 | } 26 | console.log({ values }); 27 | Message.success('提交成功'); 28 | }); 29 | }; 30 | 31 | render() { 32 | return ( 33 |
34 | 35 | 36 | 41 |
42 |
客户姓名:
43 | 44 | 45 | 46 |
47 | 48 |
49 |
50 |
51 |
预约服务:
52 | 53 | 54 | 55 |
56 | 57 |
58 |
59 |
60 |
联系方式:
61 | 62 | 63 | 64 |
65 | 66 |
67 |
68 |
69 |
预约备注:
70 | 71 | 72 | 73 |
74 | 81 |
82 |
83 |
84 | ); 85 | } 86 | } 87 | 88 | const styles = { 89 | formItem: { 90 | marginBottom: '30px', 91 | display: 'flex', 92 | alignItems: 'center', 93 | }, 94 | formLabel: { 95 | fontWeight: '450', 96 | width: '80px', 97 | }, 98 | formError: { 99 | marginTop: '10px', 100 | }, 101 | button: { 102 | marginLeft: '100px', 103 | }, 104 | }; 105 | -------------------------------------------------------------------------------- /src/components/CustomTable/CustomTable.jsx: -------------------------------------------------------------------------------- 1 | /* eslint no-prototype-builtins:0, react/forbid-prop-types:0 */ 2 | import React, { Component } from 'react'; 3 | import cloneDeep from 'lodash.clonedeep'; 4 | import PropTypes from 'prop-types'; 5 | import { Table, Pagination } from '@alifd/next'; 6 | import SearchFilter from './SearchFilter'; 7 | 8 | export default class CustomTable extends Component { 9 | static displayName = 'CustomTable'; 10 | 11 | static propTypes = { 12 | enableFilter: PropTypes.bool, 13 | searchQueryHistory: PropTypes.object, 14 | dataSource: PropTypes.array, 15 | }; 16 | 17 | static defaultProps = { 18 | enableFilter: true, 19 | searchQueryHistory: null, 20 | dataSource: [], 21 | }; 22 | 23 | constructor(props) { 24 | super(props); 25 | this.state = { 26 | loading: true, 27 | searchQuery: cloneDeep(this.props.searchQueryHistory), 28 | pageIndex: 1, 29 | dataSource: [], 30 | }; 31 | } 32 | 33 | componentDidMount() { 34 | this.fetchDataSource(); 35 | } 36 | 37 | componentWillReceiveProps(nextProps) { 38 | if (nextProps.hasOwnProperty('searchQueryHistory')) { 39 | this.setState( 40 | { 41 | searchQuery: Object.assign( 42 | cloneDeep(this.props.searchQueryHistory), 43 | nextProps.searchQueryHistory 44 | ), 45 | pageIndex: 1, 46 | }, 47 | this.fetchDataSource 48 | ); 49 | } 50 | } 51 | 52 | fetchDataSource = () => { 53 | this.setState({ 54 | loading: true, 55 | }); 56 | 57 | // 根据当前的 searchQuery/pageIndex 获取列表数据,使用 setTimeout 模拟异步请求 58 | 59 | setTimeout(() => { 60 | this.setState({ 61 | loading: false, 62 | dataSource: this.props.dataSource, 63 | }); 64 | }, 1 * 1000); 65 | }; 66 | 67 | onSearchChange = (searchQuery) => { 68 | this.setState({ 69 | searchQuery, 70 | }); 71 | }; 72 | 73 | onSearchSubmit = (searchQuery) => { 74 | this.setState( 75 | { 76 | searchQuery, 77 | pageIndex: 1, 78 | }, 79 | this.fetchDataSource 80 | ); 81 | }; 82 | 83 | onSearchReset = () => { 84 | this.setState({ 85 | searchQuery: cloneDeep(this.props.searchQueryHistory), 86 | }); 87 | }; 88 | 89 | onPaginationChange = (pageIndex) => { 90 | this.setState( 91 | { 92 | pageIndex, 93 | }, 94 | this.fetchDataSource 95 | ); 96 | }; 97 | 98 | render() { 99 | const { enableFilter, columns, formConfig, hasAdvance } = this.props; 100 | const { searchQuery, dataSource, loading, pageIndex } = this.state; 101 | 102 | return ( 103 |
104 | {enableFilter && ( 105 | 113 | )} 114 | 115 | {columns.map((item) => { 116 | return ( 117 | 126 | ); 127 | })} 128 |
129 | 134 |
135 | ); 136 | } 137 | } 138 | 139 | const styles = { 140 | pagination: { 141 | margin: '20px 0', 142 | textAlign: 'center', 143 | }, 144 | }; 145 | -------------------------------------------------------------------------------- /src/pages/Goods/components/Table/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Table, Pagination, Button, Dialog } from '@alifd/next'; 3 | import IceContainer from '@icedesign/container'; 4 | import Filter from '../Filter'; 5 | 6 | // Random Numbers 7 | const random = (min, max) => { 8 | return Math.floor(Math.random() * (max - min + 1) + min); 9 | }; 10 | 11 | // MOCK 数据,实际业务按需进行替换 12 | const getData = (length = 10) => { 13 | return Array.from({ length }).map(() => { 14 | return { 15 | name: ['蓝牙音箱', '天猫精灵', '智能机器人'][random(0, 2)], 16 | cate: ['数码', '智能'][random(0, 1)], 17 | tag: ['新品', '预售'][random(0, 1)], 18 | store: ['余杭盒马店', '滨江盒马店', '西湖盒马店'][random(0, 2)], 19 | sales: random(1000, 2000), 20 | service: ['可预约', '可体验'][random(0, 1)], 21 | }; 22 | }); 23 | }; 24 | 25 | export default class GoodsTable extends Component { 26 | state = { 27 | current: 1, 28 | isLoading: false, 29 | data: [], 30 | }; 31 | 32 | componentDidMount() { 33 | this.fetchData(); 34 | } 35 | 36 | mockApi = (len) => { 37 | return new Promise((resolve) => { 38 | setTimeout(() => { 39 | resolve(getData(len)); 40 | }, 600); 41 | }); 42 | }; 43 | 44 | fetchData = (len) => { 45 | this.setState( 46 | { 47 | isLoading: true, 48 | }, 49 | () => { 50 | this.mockApi(len).then((data) => { 51 | this.setState({ 52 | data, 53 | isLoading: false, 54 | }); 55 | }); 56 | } 57 | ); 58 | }; 59 | 60 | handlePaginationChange = (current) => { 61 | this.setState( 62 | { 63 | current, 64 | }, 65 | () => { 66 | this.fetchData(); 67 | } 68 | ); 69 | }; 70 | 71 | handleFilterChange = () => { 72 | this.fetchData(5); 73 | }; 74 | 75 | handleDelete = () => { 76 | Dialog.confirm({ 77 | title: '提示', 78 | content: '确认删除吗', 79 | onOk: () => { 80 | this.fetchData(10); 81 | }, 82 | }); 83 | }; 84 | 85 | handleDetail = () => { 86 | Dialog.confirm({ 87 | title: '提示', 88 | content: '暂不支持查看详情', 89 | }); 90 | }; 91 | 92 | renderOper = () => { 93 | return ( 94 |
95 | 102 | 105 |
106 | ); 107 | }; 108 | 109 | render() { 110 | const { isLoading, data, current } = this.state; 111 | 112 | return ( 113 |
114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 131 |
132 | 137 |
138 |
139 | ); 140 | } 141 | } 142 | 143 | const styles = { 144 | pagination: { 145 | marginTop: '20px', 146 | textAlign: 'right', 147 | }, 148 | }; 149 | -------------------------------------------------------------------------------- /src/pages/Reserve/components/Table/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Table, Pagination, Button, Dialog } from '@alifd/next'; 3 | import IceContainer from '@icedesign/container'; 4 | import Filter from '../Filter'; 5 | 6 | // Random Numbers 7 | const random = (min, max) => { 8 | return Math.floor(Math.random() * (max - min + 1) + min); 9 | }; 10 | 11 | // MOCK 数据,实际业务按需进行替换 12 | const getData = (length = 10) => { 13 | return Array.from({ length }).map(() => { 14 | return { 15 | name: ['淘小宝', '淘二宝'][random(0, 1)], 16 | service: ['项目A', '项目B', '项目C'][random(0, 2)], 17 | receiver: ['淘小宝', '淘二宝'][random(0, 1)], 18 | arrivalTime: `2019-01-1${random(1, 9)}`, 19 | reserveTime: `2018-12-1${random(1, 9)}`, 20 | address: ['余杭盒马店', '滨江盒马店', '西湖盒马店'][random(0, 2)], 21 | note: '- -', 22 | }; 23 | }); 24 | }; 25 | 26 | export default class ReserveTable extends Component { 27 | state = { 28 | current: 1, 29 | isLoading: false, 30 | data: [], 31 | }; 32 | 33 | componentDidMount() { 34 | this.fetchData(); 35 | } 36 | 37 | mockApi = (len) => { 38 | return new Promise((resolve) => { 39 | setTimeout(() => { 40 | resolve(getData(len)); 41 | }, 600); 42 | }); 43 | }; 44 | 45 | fetchData = (len) => { 46 | this.setState( 47 | { 48 | isLoading: true, 49 | }, 50 | () => { 51 | this.mockApi(len).then((data) => { 52 | this.setState({ 53 | data, 54 | isLoading: false, 55 | }); 56 | }); 57 | } 58 | ); 59 | }; 60 | 61 | handlePaginationChange = (current) => { 62 | this.setState( 63 | { 64 | current, 65 | }, 66 | () => { 67 | this.fetchData(); 68 | } 69 | ); 70 | }; 71 | 72 | handleFilterChange = () => { 73 | this.fetchData(5); 74 | }; 75 | 76 | handleDelete = () => { 77 | Dialog.confirm({ 78 | title: '提示', 79 | content: '确认删除吗', 80 | onOk: () => { 81 | this.fetchData(10); 82 | }, 83 | }); 84 | }; 85 | 86 | handleDetail = () => { 87 | Dialog.confirm({ 88 | title: '提示', 89 | content: '暂不支持查看详情', 90 | }); 91 | }; 92 | 93 | renderOper = () => { 94 | return ( 95 |
96 | 103 | 106 |
107 | ); 108 | }; 109 | 110 | render() { 111 | const { isLoading, data, current } = this.state; 112 | 113 | return ( 114 |
115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 133 |
134 | 139 |
140 |
141 | ); 142 | } 143 | } 144 | 145 | const styles = { 146 | pagination: { 147 | marginTop: '20px', 148 | textAlign: 'right', 149 | }, 150 | }; 151 | -------------------------------------------------------------------------------- /src/pages/Dashboard/components/RevenueChart/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import IceContainer from '@icedesign/container'; 3 | import { Grid, Balloon, Icon } from '@alifd/next'; 4 | import DonutChart from './DonutChart'; 5 | 6 | const { Row, Col } = Grid; 7 | 8 | export default class RevenueChart extends Component { 9 | render() { 10 | return ( 11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 |
19 |
20 | 21 |
实体店收入
22 | } 24 | align="t" 25 | closable={false} 26 | alignEdge 27 | triggerType="hover" 28 | style={{ width: 300 }} 29 | > 30 | 实体店收入的相关简介 31 | 32 |
33 |
34 | 567.89 35 | 万元 36 |
37 |
38 | 环比 39 | 66.99% 40 |
41 |
42 |
43 |
44 | 45 |
网上零售收入
46 | } 48 | align="t" 49 | closable={false} 50 | alignEdge 51 | triggerType="hover" 52 | style={{ width: 300 }} 53 | > 54 | 网上零售收入的相关简介 55 | 56 |
57 |
58 | 123,45 59 | 万元 60 |
61 |
62 | 环比 63 | 18.88% 64 |
65 |
66 |
67 | 68 |
69 |
70 | ); 71 | } 72 | } 73 | 74 | const styles = { 75 | profile: { 76 | margin: '68px 0', 77 | display: 'flex', 78 | }, 79 | head: { 80 | display: 'flex', 81 | alignItems: 'center', 82 | }, 83 | circle: { 84 | width: '10px', 85 | height: '10px', 86 | marginRight: '10px', 87 | display: 'inline-block', 88 | borderRadius: '5px', 89 | }, 90 | purple: { 91 | background: '#908ce1', 92 | }, 93 | green: { 94 | background: '#26c9ad', 95 | }, 96 | cell: { 97 | width: '50%', 98 | padding: '0 10px', 99 | }, 100 | cellTitle: { 101 | color: '#666', 102 | lineHeight: '14px', 103 | fontSize: '14px', 104 | marginRight: '5px', 105 | }, 106 | body: { 107 | display: 'flex', 108 | alignItems: 'baseline', 109 | marginTop: '20px', 110 | }, 111 | costValue: { 112 | fontSize: '32px', 113 | fontWeight: '500', 114 | lineHeight: '30px', 115 | height: '30px', 116 | color: '#333', 117 | }, 118 | costUnit: { 119 | marginLeft: '2px', 120 | fontSize: '12px', 121 | color: '#333', 122 | }, 123 | footer: { 124 | display: 'flex', 125 | marginTop: '10px', 126 | fontSize: '12px', 127 | color: '#999', 128 | }, 129 | footerText: { 130 | marginRight: '60px', 131 | }, 132 | }; 133 | -------------------------------------------------------------------------------- /src/layouts/BasicLayout/components/Header/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Link, withRouter } from 'react-router-dom'; 3 | import { Nav } from '@alifd/next'; 4 | import FoundationSymbol from '@icedesign/foundation-symbol'; 5 | import { headerMenuConfig } from '../../../../menuConfig'; 6 | import './index.scss'; 7 | 8 | @withRouter 9 | export default class Header extends Component { 10 | render() { 11 | const { location = {} } = this.props; 12 | const { pathname } = location; 13 | return ( 14 |
15 |
16 | 102 |
103 |
104 | ); 105 | } 106 | } 107 | -------------------------------------------------------------------------------- /src/pages/Membership/components/Table/index.js: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Table, Pagination, Button, Dialog } from '@alifd/next'; 3 | import IceContainer from '@icedesign/container'; 4 | import FilterTag from '../FilterTag'; 5 | import FilterForm from '../FilterForm'; 6 | 7 | // Random Numbers 8 | const random = (min, max) => { 9 | return Math.floor(Math.random() * (max - min + 1) + min); 10 | }; 11 | 12 | // MOCK 数据,实际业务按需进行替换 13 | const getData = (length = 10) => { 14 | return Array.from({ length }).map(() => { 15 | return { 16 | name: ['淘小宝', '淘二宝'][random(0, 1)], 17 | level: ['普通会员', '白银会员', '黄金会员', 'VIP 会员'][random(0, 3)], 18 | balance: random(10000, 100000), 19 | accumulative: random(50000, 100000), 20 | regdate: `2018-12-1${random(1, 9)}`, 21 | birthday: `1992-10-1${random(1, 9)}`, 22 | store: ['余杭盒马店', '滨江盒马店', '西湖盒马店'][random(0, 2)], 23 | }; 24 | }); 25 | }; 26 | 27 | export default class GoodsTable extends Component { 28 | state = { 29 | current: 1, 30 | isLoading: false, 31 | data: [], 32 | }; 33 | 34 | componentDidMount() { 35 | this.fetchData(); 36 | } 37 | 38 | mockApi = (len) => { 39 | return new Promise((resolve) => { 40 | setTimeout(() => { 41 | resolve(getData(len)); 42 | }, 600); 43 | }); 44 | }; 45 | 46 | fetchData = (len) => { 47 | this.setState( 48 | { 49 | isLoading: true, 50 | }, 51 | () => { 52 | this.mockApi(len).then((data) => { 53 | this.setState({ 54 | data, 55 | isLoading: false, 56 | }); 57 | }); 58 | } 59 | ); 60 | }; 61 | 62 | handlePaginationChange = (current) => { 63 | this.setState( 64 | { 65 | current, 66 | }, 67 | () => { 68 | this.fetchData(); 69 | } 70 | ); 71 | }; 72 | 73 | handleFilterChange = () => { 74 | this.fetchData(5); 75 | }; 76 | 77 | handleDelete = () => { 78 | Dialog.confirm({ 79 | title: '提示', 80 | content: '确认删除吗', 81 | onOk: () => { 82 | this.fetchData(10); 83 | }, 84 | }); 85 | }; 86 | 87 | handleDetail = () => { 88 | Dialog.confirm({ 89 | title: '提示', 90 | content: '暂不支持查看详情', 91 | }); 92 | }; 93 | 94 | renderOper = () => { 95 | return ( 96 |
97 | 104 | 107 |
108 | ); 109 | }; 110 | 111 | render() { 112 | const { isLoading, data, current } = this.state; 113 | 114 | return ( 115 |
116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 135 |
136 | 141 |
142 |
143 | ); 144 | } 145 | } 146 | 147 | const styles = { 148 | pagination: { 149 | marginTop: '20px', 150 | textAlign: 'right', 151 | }, 152 | }; 153 | -------------------------------------------------------------------------------- /src/pages/UserLogin/UserLogin.jsx: -------------------------------------------------------------------------------- 1 | /* eslint react/no-string-refs:0 */ 2 | import React, { Component } from 'react'; 3 | import { withRouter, Link } from 'react-router-dom'; 4 | import { Input, Button, Checkbox, Message } from '@alifd/next'; 5 | import { 6 | FormBinderWrapper as IceFormBinderWrapper, 7 | FormBinder as IceFormBinder, 8 | FormError as IceFormError, 9 | } from '@icedesign/form-binder'; 10 | import IceIcon from '@icedesign/foundation-symbol'; 11 | 12 | @withRouter 13 | class UserLogin extends Component { 14 | static displayName = 'UserLogin'; 15 | 16 | static propTypes = {}; 17 | 18 | static defaultProps = {}; 19 | 20 | constructor(props) { 21 | super(props); 22 | this.state = { 23 | value: { 24 | username: '', 25 | password: '', 26 | checkbox: false, 27 | }, 28 | }; 29 | } 30 | 31 | formChange = (value) => { 32 | this.setState({ 33 | value, 34 | }); 35 | }; 36 | 37 | handleSubmit = (e) => { 38 | e.preventDefault(); 39 | this.refs.form.validateAll((errors, values) => { 40 | if (errors) { 41 | console.log('errors', errors); 42 | return; 43 | } 44 | console.log(values); 45 | Message.success('登录成功'); 46 | this.props.history.push('/'); 47 | }); 48 | }; 49 | 50 | render() { 51 | return ( 52 |
53 |

登 录

54 | 59 |
60 |
61 | 62 | 63 | 69 | 70 | 71 |
72 | 73 |
74 | 75 | 76 | 82 | 83 | 84 |
85 | 86 |
87 | 88 | 记住账号 89 | 90 |
91 | 92 |
93 | 101 | 102 | 立即注册 103 | 104 |
105 |
106 |
107 |
108 | ); 109 | } 110 | } 111 | 112 | const styles = { 113 | container: { 114 | width: '400px', 115 | padding: '40px', 116 | background: '#fff', 117 | borderRadius: '6px', 118 | }, 119 | title: { 120 | margin: '0 0 40px', 121 | color: 'rgba(0, 0, 0, 0.8)', 122 | fontSize: '28px', 123 | fontWeight: '500', 124 | textAlign: 'center', 125 | }, 126 | formItem: { 127 | position: 'relative', 128 | marginBottom: '20px', 129 | }, 130 | inputIcon: { 131 | position: 'absolute', 132 | left: '12px', 133 | top: '12px', 134 | color: '#666', 135 | }, 136 | inputCol: { 137 | width: '100%', 138 | paddingLeft: '20px', 139 | }, 140 | submitBtn: { 141 | width: '100%', 142 | }, 143 | tips: { 144 | marginTop: '20px', 145 | display: 'block', 146 | textAlign: 'center', 147 | }, 148 | }; 149 | 150 | export default UserLogin; 151 | -------------------------------------------------------------------------------- /src/components/CustomForm/CustomForm.jsx: -------------------------------------------------------------------------------- 1 | /* eslint react/no-string-refs:0, array-callback-return:0, react/forbid-prop-types:0 */ 2 | import React, { Component } from 'react'; 3 | import PropTypes from 'prop-types'; 4 | import { Checkbox, Input, Button, Grid, Select, DatePicker } from '@alifd/next'; 5 | import { 6 | FormBinderWrapper as IceFormBinderWrapper, 7 | FormBinder as IceFormBinder, 8 | FormError as IceFormError, 9 | } from '@icedesign/form-binder'; 10 | 11 | const { Row, Col } = Grid; 12 | const { RangePicker } = DatePicker; 13 | 14 | class CustomForm extends Component { 15 | static displayName = 'CustomForm'; 16 | 17 | static propTypes = { 18 | value: PropTypes.object.isRequired, 19 | config: PropTypes.array.isRequired, 20 | handleSubmit: PropTypes.func, 21 | formChange: PropTypes.func, 22 | handleReset: PropTypes.func, 23 | extraContent: PropTypes.element, 24 | }; 25 | 26 | static defaultProps = { 27 | extraContent: null, 28 | handleReset: () => {}, 29 | handleSubmit: () => {}, 30 | formChange: () => {}, 31 | }; 32 | 33 | formChange = (value) => { 34 | this.props.formChange(value); 35 | }; 36 | 37 | handleSubmit = (e) => { 38 | e.preventDefault(); 39 | this.refs.form.validateAll((errors, values) => { 40 | this.props.handleSubmit(errors, values); 41 | }); 42 | }; 43 | 44 | renderInput = (item) => { 45 | return ( 46 | 47 |
48 | {item.label}: 49 | 50 | 51 | 52 |
53 | 54 |
55 |
56 | 57 | ); 58 | }; 59 | 60 | renderCheckbox = (item) => { 61 | return ( 62 | 63 |
64 | 65 | {item.label} 66 | 67 |
68 | 69 | ); 70 | }; 71 | 72 | renderDatePicker = (item) => { 73 | return ( 74 | 75 |
76 | {item.label}: 77 | 78 | 79 | 80 |
81 | 82 | ); 83 | }; 84 | 85 | renderSelect = (item) => { 86 | return ( 87 | 88 |
89 | {item.label}: 90 | 91 | 60 | 61 |
62 | 63 |
64 |
65 |
66 |
条形码:
67 | 68 | 72 | 73 |
74 |
75 |
库存量:
76 | 77 | 78 | 79 |
80 |
81 |
商品标签:
82 | 83 | 93 | 94 |
95 |
96 |
商品价格:
97 | 98 | 102 | 103 |
104 | 105 |
106 |
107 |
108 |
预售时间:
109 | 110 | 111 | 112 |
113 |
114 |
预约条件:
115 | 116 | 128 | 129 |
130 |
131 |
体验展示:
132 | 133 | 145 | 146 |
147 | 150 | 151 | 152 | 153 | ); 154 | } 155 | } 156 | 157 | const styles = { 158 | formItem: { 159 | marginBottom: '30px', 160 | display: 'flex', 161 | alignItems: 'center', 162 | }, 163 | formLabel: { 164 | fontWeight: '450', 165 | width: '80px', 166 | }, 167 | formError: { 168 | marginTop: '10px', 169 | }, 170 | button: { 171 | marginLeft: '100px', 172 | }, 173 | }; 174 | -------------------------------------------------------------------------------- /src/pages/UserRegister/UserRegister.jsx: -------------------------------------------------------------------------------- 1 | /* eslint react/no-string-refs:0 */ 2 | import React, { Component } from 'react'; 3 | import { withRouter, Link } from 'react-router-dom'; 4 | import { Input, Button, Message } from '@alifd/next'; 5 | import { 6 | FormBinderWrapper as IceFormBinderWrapper, 7 | FormBinder as IceFormBinder, 8 | FormError as IceFormError, 9 | } from '@icedesign/form-binder'; 10 | import IceIcon from '@icedesign/foundation-symbol'; 11 | 12 | @withRouter 13 | class UserRegister extends Component { 14 | static displayName = 'UserRegister'; 15 | 16 | static propTypes = {}; 17 | 18 | static defaultProps = {}; 19 | 20 | constructor(props) { 21 | super(props); 22 | this.state = { 23 | value: { 24 | name: '', 25 | email: '', 26 | passwd: '', 27 | rePasswd: '', 28 | }, 29 | }; 30 | } 31 | 32 | checkPasswd = (rule, values, callback) => { 33 | if (!values) { 34 | callback('请输入正确的密码'); 35 | } else if (values.length < 8) { 36 | callback('密码必须大于8位'); 37 | } else if (values.length > 16) { 38 | callback('密码必须小于16位'); 39 | } else { 40 | callback(); 41 | } 42 | }; 43 | 44 | checkPasswd2 = (rule, values, callback, stateValues) => { 45 | if (!values) { 46 | callback('请输入正确的密码'); 47 | } else if (values && values !== stateValues.passwd) { 48 | callback('两次输入密码不一致'); 49 | } else { 50 | callback(); 51 | } 52 | }; 53 | 54 | formChange = (value) => { 55 | this.setState({ 56 | value, 57 | }); 58 | }; 59 | 60 | handleSubmit = () => { 61 | this.refs.form.validateAll((errors, values) => { 62 | if (errors) { 63 | console.log('errors', errors); 64 | return; 65 | } 66 | console.log(values); 67 | Message.success('注册成功'); 68 | this.props.history.push('/user/login'); 69 | }); 70 | }; 71 | 72 | render() { 73 | return ( 74 |
75 |

注 册

76 | 81 |
82 |
83 | 84 | 85 | 90 | 91 | 92 |
93 | 94 |
95 | 96 | 102 | 108 | 109 | 110 |
111 | 112 |
113 | 114 | 119 | 125 | 126 | 127 |
128 | 129 |
130 | 131 | 135 | this.checkPasswd2(rule, values, callback, this.state.value) 136 | } 137 | > 138 | 144 | 145 | 146 |
147 | 148 |
149 | 157 | 158 | 使用已有账户登录 159 | 160 |
161 |
162 |
163 |
164 | ); 165 | } 166 | } 167 | 168 | const styles = { 169 | container: { 170 | width: '400px', 171 | padding: '40px', 172 | background: '#fff', 173 | borderRadius: '6px', 174 | }, 175 | title: { 176 | margin: '0 0 40px', 177 | color: 'rgba(0, 0, 0, 0.8)', 178 | fontSize: '28px', 179 | fontWeight: '500', 180 | textAlign: 'center', 181 | }, 182 | formItem: { 183 | position: 'relative', 184 | marginBottom: '20px', 185 | }, 186 | inputIcon: { 187 | position: 'absolute', 188 | left: '12px', 189 | top: '12px', 190 | color: '#666', 191 | }, 192 | inputCol: { 193 | width: '100%', 194 | paddingLeft: '20px', 195 | }, 196 | submitBtn: { 197 | width: '100%', 198 | }, 199 | tips: { 200 | marginTop: '20px', 201 | display: 'block', 202 | textAlign: 'center', 203 | }, 204 | }; 205 | 206 | export default UserRegister; 207 | -------------------------------------------------------------------------------- /src/pages/OrderList/OrderList.jsx: -------------------------------------------------------------------------------- 1 | import React, { Component } from 'react'; 2 | import { Dialog, Button } from '@alifd/next'; 3 | import IceContainer from '@icedesign/container'; 4 | import CustomTable from '../../components/CustomTable'; 5 | import PageHead from '../../components/PageHead'; 6 | 7 | const defaultSearchQuery = { 8 | id: '', 9 | goodId: '', 10 | applyCode: '', 11 | name: '', 12 | state: '', 13 | orderType: '', 14 | createTime: [], 15 | refundTime: [], 16 | orderTime: [], 17 | payment: '', 18 | transport: '', 19 | checkbox: 'false', 20 | }; 21 | 22 | const formConfig = [ 23 | { 24 | label: '订单编号', 25 | component: 'Input', 26 | componentProps: { 27 | placeholder: '请输入订单编号', 28 | }, 29 | formBinderProps: { 30 | name: 'id', 31 | required: false, 32 | message: '请输入正确的订单编号', 33 | }, 34 | }, 35 | { 36 | label: '商品编号', 37 | component: 'Input', 38 | componentProps: { 39 | placeholder: '请输入商品编号', 40 | }, 41 | formBinderProps: { 42 | name: 'goodId', 43 | required: false, 44 | message: '请输入正确的商品编号', 45 | }, 46 | }, 47 | { 48 | label: '申请单号', 49 | component: 'Input', 50 | componentProps: { 51 | placeholder: '请输入申请单号', 52 | }, 53 | formBinderProps: { 54 | name: 'applyCode', 55 | }, 56 | }, 57 | { 58 | label: '订单名称', 59 | component: 'Input', 60 | componentProps: { 61 | placeholder: '请输入订单名称', 62 | }, 63 | formBinderProps: { 64 | name: 'name', 65 | }, 66 | }, 67 | { 68 | label: '订单状态', 69 | component: 'Select', 70 | componentProps: { 71 | placeholder: '请选择', 72 | dataSource: [ 73 | { label: '已发货', value: 'option1' }, 74 | { label: '代发货', value: 'option2' }, 75 | ], 76 | }, 77 | formBinderProps: { 78 | name: 'state', 79 | }, 80 | }, 81 | { 82 | label: '订单类型', 83 | component: 'Select', 84 | componentProps: { 85 | placeholder: '请选择', 86 | dataSource: [ 87 | { label: '普通订单', value: 'option1' }, 88 | { label: '代付订单', value: 'option2' }, 89 | ], 90 | }, 91 | formBinderProps: { 92 | name: 'orderType', 93 | }, 94 | }, 95 | { 96 | label: '创建时间', 97 | component: 'RangePicker', 98 | advanced: true, 99 | componentProps: { 100 | placeholder: '请选择日期', 101 | }, 102 | formBinderProps: { 103 | name: 'createTime', 104 | }, 105 | }, 106 | { 107 | label: '下单时间', 108 | component: 'RangePicker', 109 | advanced: true, 110 | componentProps: { 111 | placeholder: '请选择日期', 112 | }, 113 | formBinderProps: { 114 | name: 'orderTime', 115 | }, 116 | }, 117 | { 118 | label: '退款时间', 119 | component: 'RangePicker', 120 | advanced: true, 121 | componentProps: { 122 | placeholder: '请选择日期', 123 | }, 124 | formBinderProps: { 125 | name: 'refundTime', 126 | }, 127 | }, 128 | { 129 | label: '付款方式', 130 | component: 'Select', 131 | advanced: true, 132 | componentProps: { 133 | placeholder: '请选择', 134 | dataSource: [ 135 | { value: '1', label: '支付宝付款' }, 136 | { value: '2', label: '银行卡付款' }, 137 | { value: '3', label: '微信付款' }, 138 | { value: '4', label: '找人代付' }, 139 | ], 140 | }, 141 | formBinderProps: { 142 | name: 'payment', 143 | }, 144 | }, 145 | { 146 | label: '物流方式', 147 | component: 'Select', 148 | advanced: true, 149 | componentProps: { 150 | placeholder: '请选择', 151 | dataSource: [ 152 | { label: '快递发货', value: '1' }, 153 | { label: '上门自提', value: '2' }, 154 | { label: '同城配送', value: '3' }, 155 | ], 156 | }, 157 | formBinderProps: { 158 | name: 'transport', 159 | }, 160 | }, 161 | { 162 | label: '查询我处理过的订单', 163 | component: 'Checkbox', 164 | advanced: true, 165 | componentProps: {}, 166 | formBinderProps: { 167 | name: 'checkbox', 168 | }, 169 | }, 170 | ]; 171 | 172 | const random = (min, max) => { 173 | return Math.floor(Math.random() * (max - min + 1) + min); 174 | }; 175 | 176 | const mockData = Array.from({ length: 10 }).map(() => { 177 | return { 178 | id: random(1, 100), 179 | goodId: random(200, 1000), 180 | name: ['淘公仔', '天猫精灵', '蓝牙音响'][random(1, 2)], 181 | payment: 182 | ['支付宝付款', '银行卡付款', '微信付款'][random(1, 2)] || '支付宝付款', 183 | orderType: ['普通订单', '代付订单'][random(0, 1)], 184 | createTime: '2018-12-12', 185 | state: '派送中', 186 | transport: ['快递发货', '上门自提', '同城配送'][random(0, 2)], 187 | }; 188 | }); 189 | 190 | export default class OrderList extends Component { 191 | renderState = (value) => { 192 | return ( 193 |
194 | {value} 195 |
196 | ); 197 | }; 198 | 199 | handleDelete = () => { 200 | Dialog.confirm({ 201 | title: '提示', 202 | content: '确认删除吗', 203 | }); 204 | }; 205 | 206 | handleDetail = () => { 207 | Dialog.confirm({ 208 | title: '提示', 209 | content: '只有管理员才能查看具体的订单信息', 210 | }); 211 | }; 212 | 213 | renderOper = () => { 214 | return ( 215 |
216 | 219 | 220 | 223 |
224 | ); 225 | }; 226 | 227 | getTableColumns = () => { 228 | return [ 229 | { 230 | title: '订单编号', 231 | dataIndex: 'id', 232 | key: 'id', 233 | lock: true, 234 | }, 235 | { 236 | title: '商品编号', 237 | dataIndex: 'goodId', 238 | key: 'goodId', 239 | lock: true, 240 | }, 241 | { 242 | title: '订单名称', 243 | dataIndex: 'name', 244 | key: 'name', 245 | }, 246 | { 247 | title: '付款方式', 248 | dataIndex: 'payment', 249 | key: 'payment', 250 | }, 251 | { 252 | title: '订单类型', 253 | dataIndex: 'orderType', 254 | key: 'orderType', 255 | }, 256 | { 257 | title: '创建时间', 258 | dataIndex: 'createTime', 259 | key: 'createTime', 260 | }, 261 | { 262 | title: '物流方式', 263 | dataIndex: 'transport', 264 | key: 'transport', 265 | }, 266 | { 267 | title: '订单状态', 268 | dataIndex: 'state', 269 | key: 'state', 270 | cell: this.renderState, 271 | }, 272 | { 273 | title: '操作', 274 | dataIndex: 'detail', 275 | key: 'detail', 276 | cell: this.renderOper, 277 | }, 278 | ]; 279 | }; 280 | 281 | render() { 282 | return ( 283 |
284 | 285 | 286 | 293 | 294 |
295 | ); 296 | } 297 | } 298 | 299 | const styles = { 300 | stateText: { 301 | display: 'inline-block', 302 | padding: '5px 10px', 303 | color: '#5e83fb', 304 | background: '#fff', 305 | border: '1px solid #5e83fb', 306 | borderRadius: '4px', 307 | }, 308 | separator: { 309 | margin: '0 8px', 310 | display: 'inline-block', 311 | height: '12px', 312 | verticalAlign: 'middle', 313 | background: '#e8e8e8', 314 | }, 315 | }; 316 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------