├── 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 |
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 | 
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 |
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 |
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 |
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 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | );
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/layouts/UserLayout/components/Intro/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | const LoginIntro = () => {
4 | return (
5 |
6 |
7 |
商家管理系统
8 |
多数据可视化展示的商家管理系统
9 |
一起解构数字世界,碰撞科技创新思想
10 |
11 |
12 | );
13 | };
14 |
15 | const styles = {
16 | container: {
17 | display: 'flex',
18 | flexDirection: 'column',
19 | alignItems: 'center',
20 | justifyContent: 'center',
21 | position: 'relative',
22 | },
23 | content: {
24 | width: '400px',
25 | color: '#fff',
26 | },
27 | title: {
28 | marginBottom: '20px',
29 | fontWeight: '700',
30 | fontSize: '48px',
31 | lineHeight: '1.5',
32 | },
33 | description: {
34 | margin: '0',
35 | fontSize: '16px',
36 | color: '#fff',
37 | letterSpacing: '0.45px',
38 | lineHeight: '40px',
39 | },
40 | };
41 |
42 | export default LoginIntro;
43 |
--------------------------------------------------------------------------------
/src/pages/Asset/components/AssetTab/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import { Tab } from '@alifd/next';
3 | import IceContainer from '@icedesign/container';
4 | import AssetTable from './AssetTable';
5 |
6 | const detachedContentStyle = {
7 | borderLeft: 0,
8 | borderRight: 0,
9 | borderBottom: 0,
10 | };
11 |
12 | export default class Asset extends Component {
13 | render() {
14 | const panes = [
15 | {
16 | tab: '提现',
17 | key: 0,
18 | content: ,
19 | },
20 | {
21 | tab: '退款',
22 | key: 1,
23 | content: ,
24 | },
25 | ];
26 |
27 | return (
28 |
29 |
30 | {panes.map((pane) => {
31 | return (
32 |
33 | {pane.content}
34 |
35 | );
36 | })}
37 |
38 |
39 | );
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/components/PageHead/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import PropTypes from 'prop-types';
3 | import { Button } from '@alifd/next';
4 |
5 | const PageHead = ({ title, style, ...props }) => {
6 | return (
7 |
8 |
{title}
9 | {props.buttonText ? (
10 |
11 | {props.buttonText}
12 |
13 | ) : null}
14 |
15 | );
16 | };
17 |
18 | const styles = {
19 | container: {
20 | margin: '0 10px 20px',
21 | display: 'flex',
22 | alignItems: 'center',
23 | justifyContent: 'space-between',
24 | },
25 | title: {
26 | margin: '0',
27 | padding: '0',
28 | fonSize: '16px',
29 | color: 'rgba(0, 0, 0, 0.85)',
30 | fontWeight: '500',
31 | },
32 | };
33 |
34 | PageHead.propTypes = {
35 | title: PropTypes.string.isRequired,
36 | buttonText: PropTypes.string,
37 | };
38 |
39 | PageHead.defaultProps = {
40 | buttonText: '',
41 | };
42 |
43 | export default PageHead;
44 |
--------------------------------------------------------------------------------
/src/components/NotFound/index.scss:
--------------------------------------------------------------------------------
1 | @media screen and (max-width: 720px) {
2 | .exception-content {
3 | min-height: 200px;
4 | .imgException {
5 | max-width: 100px;
6 | margin-right: 10px;
7 | }
8 | .title {
9 | font-size: 14px;
10 | margin: 10px 0;
11 | }
12 | .description {
13 | font-size: 12px;
14 | }
15 | }
16 | }
17 |
18 | @media screen and (min-width: 721px) and (max-width: 1199px) {
19 | .exception-content {
20 | min-height: 300px;
21 | .imgException {
22 | max-width: 180px;
23 | margin-right: 30px;
24 | }
25 | .title {
26 | font-size: 20px;
27 | margin: 10px 0;
28 | }
29 | .description {
30 | font-size: 14px;
31 | }
32 | }
33 | }
34 |
35 | @media screen and (min-width: 1200px) {
36 | .exception-content {
37 | min-height: 500px;
38 | .imgException {
39 | max-width: 260px;
40 | margin-right: 50px;
41 | }
42 | .title {
43 | font-size: 24px;
44 | margin: 20px 0;
45 | }
46 | .description {
47 | font-size: 16px;
48 | }
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/pages/Dashboard/components/ReserveChart/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 | income: [
10 | {
11 | item: '网店预付金额',
12 | count: 30,
13 | },
14 | {
15 | item: '实体店预付金额',
16 | count: 70,
17 | },
18 | ],
19 | order: [
20 | {
21 | item: '网店预约',
22 | count: 80,
23 | },
24 | {
25 | item: '实体店预约',
26 | count: 20,
27 | },
28 | ],
29 | };
30 |
31 | class ReserveChart extends React.Component {
32 | render() {
33 | return (
34 |
35 |
36 |
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 |
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 |
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 |
51 | {item}
52 |
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 |
51 | {Array.isArray(asideMenuConfig) &&
52 | asideMenuConfig.length > 0 &&
53 | asideMenuConfig.map((nav) => {
54 | return (
55 |
56 |
57 | {nav.icon ? (
58 |
59 | ) : null}
60 | {nav.name}
61 |
62 |
63 | );
64 | })}
65 |
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 |
60 | 高级搜索{' '}
61 |
65 |
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 |
56 | 余杭盒马店
57 | 滨江盒马店
58 | 西湖盒马店
59 |
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 |
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 | }
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 |
45 | 近3个月
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 | }
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 |
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 |
79 | 提 交
80 |
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 |
100 | 详情
101 |
102 |
103 | 删除
104 |
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 |
101 | 详情
102 |
103 |
104 | 删除
105 |
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 |
23 | {headerMenuConfig &&
24 | headerMenuConfig.length > 0 &&
25 | headerMenuConfig.map((nav, index) => {
26 | if (nav.children && nav.children.length > 0) {
27 | return (
28 |
33 | {nav.icon ? (
34 |
35 | ) : null}
36 | {nav.name}
37 |
38 | }
39 | >
40 | {nav.children.map((item) => {
41 | const linkProps = {};
42 | if (item.external) {
43 | if (item.newWindow) {
44 | linkProps.target = '_blank';
45 | }
46 |
47 | linkProps.href = item.path;
48 | return (
49 |
50 |
51 | {item.name}
52 |
53 |
54 | );
55 | }
56 | linkProps.to = item.path;
57 | return (
58 |
59 |
60 | {item.name}
61 |
62 |
63 | );
64 | })}
65 |
66 | );
67 | }
68 | const linkProps = {};
69 | if (nav.external) {
70 | if (nav.newWindow) {
71 | linkProps.target = '_blank';
72 | }
73 | linkProps.href = nav.path;
74 | return (
75 |
76 |
77 |
78 | {nav.icon ? (
79 |
80 | ) : null}
81 | {nav.name}
82 |
83 |
84 |
85 | );
86 | }
87 | linkProps.to = nav.path;
88 | return (
89 |
90 |
91 |
92 | {nav.icon ? (
93 |
94 | ) : null}
95 | {nav.name}
96 |
97 |
98 |
99 | );
100 | })}
101 |
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 |
102 | 详情
103 |
104 |
105 | 删除
106 |
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 |
99 | 登 录
100 |
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 |
92 |
93 |
94 |
95 | );
96 | };
97 |
98 | renderFromItem = (config) => {
99 | return config.map((item) => {
100 | if (item.component === 'Input') {
101 | return this.renderInput(item);
102 | } else if (item.component === 'Checkbox') {
103 | return this.renderCheckbox(item);
104 | } else if (item.component === 'Select') {
105 | return this.renderSelect(item);
106 | } else if (item.component === 'RangePicker') {
107 | return this.renderDatePicker(item);
108 | }
109 | });
110 | };
111 |
112 | render() {
113 | const { value, config, extraContent, hasAdvance, handleReset } = this.props;
114 |
115 | return (
116 |
117 |
122 |
123 |
124 | {this.renderFromItem(config)}
125 |
126 |
127 |
132 | 搜 索
133 |
134 |
135 | 重 置
136 |
137 |
138 | {hasAdvance ? extraContent : null}
139 |
140 |
141 |
142 | );
143 | }
144 | }
145 |
146 | const styles = {
147 | formContainer: {
148 | position: 'relative',
149 | background: '#fff',
150 | },
151 | formItem: {
152 | display: 'flex',
153 | alignItems: 'center',
154 | margin: '10px 0',
155 | },
156 | formLabel: {
157 | minWidth: '70px',
158 | },
159 | buttons: {
160 | margin: '10px 0 20px',
161 | textAlign: 'center',
162 | },
163 | };
164 |
165 | export default CustomForm;
166 |
--------------------------------------------------------------------------------
/src/pages/AddGoods/components/GoodsForm/index.js:
--------------------------------------------------------------------------------
1 | /* eslint react/no-string-refs:0 */
2 | import React, { Component } from 'react';
3 | import IceContainer from '@icedesign/container';
4 | import {
5 | Input,
6 | Button,
7 | Message,
8 | NumberPicker,
9 | DatePicker,
10 | Radio,
11 | Select,
12 | } from '@alifd/next';
13 | import {
14 | FormBinderWrapper as IceFormBinderWrapper,
15 | FormBinder as IceFormBinder,
16 | FormError as IceFormError,
17 | } from '@icedesign/form-binder';
18 | import PageHead from '../../../../components/PageHead';
19 |
20 | const { Option } = Select;
21 | const { Group: RadioGroup } = Radio;
22 | const { RangePicker } = DatePicker;
23 |
24 | export default class GoodsForm extends Component {
25 | state = {
26 | value: {},
27 | };
28 |
29 | formChange = (value) => {
30 | console.log('value', value);
31 | };
32 |
33 | validateAllFormField = () => {
34 | this.refs.form.validateAll((errors, values) => {
35 | if (errors) {
36 | return;
37 | }
38 | console.log({ values });
39 | Message.success('提交成功');
40 | });
41 | };
42 |
43 | render() {
44 | return (
45 |
46 |
47 |
48 |
53 |
54 |
商品名称:
55 |
56 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
条形码:
67 |
68 |
72 |
73 |
74 |
75 |
库存量:
76 |
77 |
78 |
79 |
80 |
81 |
商品标签:
82 |
83 |
88 | 新品
89 | 数码
90 | 智能
91 | 生活
92 |
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 |
148 | 提 交
149 |
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 |
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 |
217 | 查看
218 |
219 |
220 |
221 | 删除
222 |
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 |
--------------------------------------------------------------------------------