├── src
├── auth
│ ├── index.js
│ └── authConfig.js
├── views
│ ├── mainContent
│ │ ├── personal
│ │ │ ├── index.scss
│ │ │ ├── index.js
│ │ │ └── percentageEcharts.js
│ │ ├── storeManage
│ │ │ ├── list
│ │ │ │ ├── listNew
│ │ │ │ │ └── index.scss
│ │ │ │ ├── index.scss
│ │ │ │ ├── listDetailInfo
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── data.js
│ │ │ │ └── data.js
│ │ │ ├── index.js
│ │ │ └── echarts
│ │ │ │ ├── newStoreEcharts.js
│ │ │ │ └── storeRankEcharts.js
│ │ ├── userManage
│ │ │ ├── list
│ │ │ │ ├── listNew
│ │ │ │ │ └── index.scss
│ │ │ │ ├── index.scss
│ │ │ │ ├── data.js
│ │ │ │ └── listDetailInfo
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── data.js
│ │ │ ├── adminList
│ │ │ │ ├── listNew
│ │ │ │ │ ├── index.scss
│ │ │ │ │ ├── data.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── index.scss
│ │ │ │ ├── data.js
│ │ │ │ └── listDetailInfo
│ │ │ │ │ ├── data.js
│ │ │ │ │ └── index.js
│ │ │ ├── grade
│ │ │ │ └── index.js
│ │ │ ├── index.js
│ │ │ ├── member
│ │ │ │ └── index.js
│ │ │ └── echarts
│ │ │ │ └── index.js
│ │ ├── goodsManage
│ │ │ ├── goodsList
│ │ │ │ ├── listNew
│ │ │ │ │ ├── index.scss
│ │ │ │ │ ├── data.js
│ │ │ │ │ └── index.js
│ │ │ │ ├── index.scss
│ │ │ │ ├── listDetailInfo
│ │ │ │ │ ├── index.js
│ │ │ │ │ └── data.js
│ │ │ │ └── data.js
│ │ │ └── index.js
│ │ ├── home
│ │ │ ├── baseMap
│ │ │ │ ├── index.scss
│ │ │ │ ├── markerContent
│ │ │ │ │ ├── index.js
│ │ │ │ │ ├── markerContent.scss
│ │ │ │ │ └── markerContent.js
│ │ │ │ └── index.js
│ │ │ ├── index.scss
│ │ │ ├── data.js
│ │ │ └── index.js
│ │ ├── authManage
│ │ │ ├── index.js
│ │ │ └── roleList
│ │ │ │ ├── index.scss
│ │ │ │ └── data.js
│ │ ├── historyRecord
│ │ │ ├── index.js
│ │ │ ├── deleteUserList
│ │ │ │ ├── index.scss
│ │ │ │ └── data.js
│ │ │ └── deleteAdminUserList
│ │ │ │ ├── index.scss
│ │ │ │ └── data.js
│ │ ├── index.scss
│ │ └── index.js
│ ├── App.scss
│ ├── header
│ │ ├── data.js
│ │ └── index.scss
│ ├── login
│ │ ├── index.scss
│ │ └── index.js
│ ├── App.js
│ └── leftNav
│ │ └── index.scss
├── components
│ ├── CEcharts
│ │ ├── index.scss
│ │ └── index.js
│ ├── CBreadcrumb
│ │ ├── index.scss
│ │ └── index.js
│ ├── CPage
│ │ ├── index.scss
│ │ └── index.js
│ ├── CDetailInfo
│ │ ├── detailInfoTitle.js
│ │ ├── index.js
│ │ ├── index.scss
│ │ └── detailInfoItem.js
│ ├── CBaseComponent
│ │ └── index.js
│ ├── CAvatar
│ │ ├── index.scss
│ │ └── index.js
│ ├── CPageNew
│ │ └── index.scss
│ ├── CSwiper
│ │ ├── index.scss
│ │ └── index.js
│ ├── CForm
│ │ ├── CCheckbox.js
│ │ ├── CSwitch.js
│ │ ├── CRadio.js
│ │ ├── index.scss
│ │ ├── CSelect.js
│ │ ├── CDatePicker.js
│ │ ├── validate.js
│ │ └── CInput.js
│ ├── CScroll
│ │ └── index.jsx
│ ├── CButton
│ │ ├── index.js
│ │ └── index.scss
│ └── CTable
│ │ ├── index.scss
│ │ ├── filterHead.js
│ │ └── tableFilter.js
├── assets
│ ├── images
│ │ ├── login-bg.jpg
│ │ ├── map-marker.png
│ │ └── projectShot
│ │ │ ├── home.jpg
│ │ │ ├── login.jpg
│ │ │ ├── theme1.jpg
│ │ │ ├── goodsManage1.jpg
│ │ │ ├── roleManage1.jpg
│ │ │ ├── storeManage1.jpg
│ │ │ ├── storeManage2.jpg
│ │ │ ├── userManage1.png
│ │ │ ├── userManage2.jpg
│ │ │ ├── userManage3.jpg
│ │ │ ├── userManage4.png
│ │ │ ├── userManage5.jpg
│ │ │ └── historyRecord1.jpg
│ └── css
│ │ ├── antdReset.scss
│ │ ├── common.scss
│ │ └── var.scss
├── routers
│ ├── homeRouter.js
│ ├── personalRouter.js
│ ├── authManageRouter.js
│ ├── historyRecordRouter.js
│ ├── goodsManageRouter.js
│ ├── storeManageRouter.js
│ ├── userManageRouter.js
│ └── index.js
├── servers
│ ├── homeApi.js
│ ├── authManageApi.js
│ ├── goodsManageApi.js
│ ├── historyRecordApi.js
│ ├── storeManageApi.js
│ ├── userManageApi.js
│ ├── commonApi.js
│ └── index.js
├── redux
│ ├── index.js
│ └── common
│ │ ├── action-type.js
│ │ ├── action.js
│ │ └── reducer.js
├── config
│ └── index.js
├── mock
│ ├── authManage
│ │ ├── index.js
│ │ └── roleList.js
│ ├── statistics
│ │ ├── index.js
│ │ ├── userApiList.js
│ │ └── storeApiList.js
│ ├── commonSchema.js
│ ├── index.js
│ ├── createMockData.js
│ ├── goodsManage
│ │ ├── index.js
│ │ └── schema.js
│ ├── storeManage
│ │ ├── index.js
│ │ └── schema.js
│ ├── login
│ │ └── index.js
│ ├── common
│ │ └── index.js
│ └── userManage
│ │ ├── index.js
│ │ └── schema.js
├── index.js
└── logo.svg
├── public
├── favicon.ico
├── manifest.json
└── index.html
├── config
├── jest
│ ├── cssTransform.js
│ └── fileTransform.js
├── utils.js
├── pnpTs.js
├── modules.js
├── paths.js
└── env.js
├── .gitignore
├── scripts
└── test.js
└── README.md
/src/auth/index.js:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/views/mainContent/personal/index.scss:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/components/CEcharts/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .c-echarts{
3 | height: 100%;
4 | }
5 |
--------------------------------------------------------------------------------
/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chengllNice/react-store-admin/HEAD/public/favicon.ico
--------------------------------------------------------------------------------
/src/views/mainContent/storeManage/list/listNew/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .store-manage-list-new{
3 | height: 100%;
4 | }
5 |
--------------------------------------------------------------------------------
/src/views/mainContent/userManage/list/listNew/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .user-manage-list-new{
3 | height: 100%;
4 | }
5 |
--------------------------------------------------------------------------------
/src/views/mainContent/goodsManage/goodsList/listNew/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .store-manage-list-new{
3 | height: 100%;
4 | }
5 |
--------------------------------------------------------------------------------
/src/views/mainContent/userManage/adminList/listNew/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .user-manage-list-new{
3 | height: 100%;
4 | }
5 |
--------------------------------------------------------------------------------
/src/assets/images/login-bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chengllNice/react-store-admin/HEAD/src/assets/images/login-bg.jpg
--------------------------------------------------------------------------------
/src/components/CBreadcrumb/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .c-breadcrumb{
3 | width: 100%;
4 | justify-content: space-between;
5 | }
6 |
--------------------------------------------------------------------------------
/src/assets/images/map-marker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chengllNice/react-store-admin/HEAD/src/assets/images/map-marker.png
--------------------------------------------------------------------------------
/src/auth/authConfig.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | export const userRoleList = [];
4 |
5 | // 权限配置
6 | export const authConfig = [
7 |
8 | ];
9 |
--------------------------------------------------------------------------------
/src/assets/images/projectShot/home.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chengllNice/react-store-admin/HEAD/src/assets/images/projectShot/home.jpg
--------------------------------------------------------------------------------
/src/assets/images/projectShot/login.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chengllNice/react-store-admin/HEAD/src/assets/images/projectShot/login.jpg
--------------------------------------------------------------------------------
/src/assets/images/projectShot/theme1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chengllNice/react-store-admin/HEAD/src/assets/images/projectShot/theme1.jpg
--------------------------------------------------------------------------------
/src/assets/images/projectShot/goodsManage1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chengllNice/react-store-admin/HEAD/src/assets/images/projectShot/goodsManage1.jpg
--------------------------------------------------------------------------------
/src/assets/images/projectShot/roleManage1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chengllNice/react-store-admin/HEAD/src/assets/images/projectShot/roleManage1.jpg
--------------------------------------------------------------------------------
/src/assets/images/projectShot/storeManage1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chengllNice/react-store-admin/HEAD/src/assets/images/projectShot/storeManage1.jpg
--------------------------------------------------------------------------------
/src/assets/images/projectShot/storeManage2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chengllNice/react-store-admin/HEAD/src/assets/images/projectShot/storeManage2.jpg
--------------------------------------------------------------------------------
/src/assets/images/projectShot/userManage1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chengllNice/react-store-admin/HEAD/src/assets/images/projectShot/userManage1.png
--------------------------------------------------------------------------------
/src/assets/images/projectShot/userManage2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chengllNice/react-store-admin/HEAD/src/assets/images/projectShot/userManage2.jpg
--------------------------------------------------------------------------------
/src/assets/images/projectShot/userManage3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chengllNice/react-store-admin/HEAD/src/assets/images/projectShot/userManage3.jpg
--------------------------------------------------------------------------------
/src/assets/images/projectShot/userManage4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chengllNice/react-store-admin/HEAD/src/assets/images/projectShot/userManage4.png
--------------------------------------------------------------------------------
/src/assets/images/projectShot/userManage5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chengllNice/react-store-admin/HEAD/src/assets/images/projectShot/userManage5.jpg
--------------------------------------------------------------------------------
/src/views/mainContent/home/baseMap/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .base-map{
3 | width: 100%;
4 | height: 400px;
5 | }
6 |
7 | .marker-content{
8 |
9 | }
10 |
--------------------------------------------------------------------------------
/src/assets/images/projectShot/historyRecord1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chengllNice/react-store-admin/HEAD/src/assets/images/projectShot/historyRecord1.jpg
--------------------------------------------------------------------------------
/src/routers/homeRouter.js:
--------------------------------------------------------------------------------
1 |
2 | import Home from '@/views/mainContent/home'
3 |
4 | export default {
5 | path: '/home',
6 | component: Home,
7 | exact: true
8 | }
9 |
--------------------------------------------------------------------------------
/src/servers/homeApi.js:
--------------------------------------------------------------------------------
1 | import {ajax_get} from "./index";
2 |
3 | // 获取所有商铺列表
4 | export const getStoreAllList = (data) => ajax_get('/fe/storeManage/storeAllList/get/', data);
5 |
--------------------------------------------------------------------------------
/src/routers/personalRouter.js:
--------------------------------------------------------------------------------
1 |
2 | import personal from '@/views/mainContent/personal'
3 |
4 | export default {
5 | path: '/personal',
6 | component: personal,
7 | exact: true,
8 | }
9 |
--------------------------------------------------------------------------------
/src/assets/css/antdReset.scss:
--------------------------------------------------------------------------------
1 |
2 | .ant-message-notice-content{
3 | padding: 4px 10px!important;
4 | border-radius: 2px!important;
5 | font-size: 13px;
6 | }
7 | .ant-message .anticon{
8 | font-size: 14px!important;
9 | }
10 |
--------------------------------------------------------------------------------
/src/views/mainContent/authManage/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | export default class AuthManage extends Component{
4 | render(){
5 |
6 | return (
7 |
{this.props.children}
8 | )
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/views/mainContent/goodsManage/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | export default class GoodsManage extends Component{
4 | render(){
5 |
6 | return (
7 | {this.props.children}
8 | )
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/views/mainContent/historyRecord/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | export default class HistoryRecord extends Component{
4 | render(){
5 | return (
6 | {this.props.children}
7 | )
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/views/mainContent/storeManage/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | export default class StoreManage extends Component{
4 | render(){
5 |
6 | return (
7 | {this.props.children}
8 | )
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/views/mainContent/userManage/grade/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | export default class UserManageGrade extends Component{
4 | render(){
5 | return (
6 | UserManageGrade
7 | )
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/views/mainContent/userManage/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | export default class UserManage extends Component{
4 | render(){
5 |
6 | return (
7 | {this.props.children}
8 | )
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/views/mainContent/userManage/member/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 |
3 | export default class UserManageMember extends Component{
4 | render(){
5 | return (
6 | UserManageMember
7 | )
8 | }
9 | }
10 |
--------------------------------------------------------------------------------
/src/views/mainContent/home/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .home{
3 | .home-filter{
4 | justify-content: flex-end;
5 | margin-bottom: 20px;
6 | .search-input{
7 | width: 200px;
8 | }
9 | }
10 | .home-base-map{
11 | border: 1px solid #eeeeee;
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/src/components/CPage/index.scss:
--------------------------------------------------------------------------------
1 | @import "@/assets/css/var.scss";
2 | .c-page{
3 | margin: 10px 0;
4 | .ant-pagination-item-active{
5 | background-color: $main-base-primary-color;
6 | border-radius: 2px;
7 | a{
8 | color: $text-color-white!important;
9 | }
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/redux/index.js:
--------------------------------------------------------------------------------
1 | import {createStore, combineReducers, applyMiddleware} from 'redux';
2 |
3 | import Common from './common/reducer'
4 |
5 | import thunk from 'redux-thunk';
6 |
7 | const store = createStore(
8 | combineReducers({Common}),
9 | applyMiddleware(thunk)
10 | );
11 |
12 | export default store;
13 |
--------------------------------------------------------------------------------
/src/views/App.scss:
--------------------------------------------------------------------------------
1 | @import "@/assets/css/var.scss";
2 | .app{
3 | background-color: $main-background-color;
4 | height: 100%;
5 | .app-content{
6 | height: calc(100% - 45px);
7 | align-items: start;
8 | .app-mainContent{
9 | flex: 1;
10 | height: 100%;
11 | overflow: auto;
12 | }
13 | }
14 | }
15 |
--------------------------------------------------------------------------------
/src/views/header/data.js:
--------------------------------------------------------------------------------
1 |
2 | export const menuList = [
3 | {
4 | id: 'personal',
5 | path: '/personal',
6 | name: '个人信息',
7 | },
8 | {
9 | id: 'changeAccount',
10 | path: '/changeAccount',
11 | name: '切换账号',
12 | },
13 | {
14 | id: 'loginOut',
15 | path: '/loginOut',
16 | name: '退出',
17 | }
18 | ];
19 |
--------------------------------------------------------------------------------
/src/config/index.js:
--------------------------------------------------------------------------------
1 |
2 | module.exports = {
3 | name: 'X-Admin',//项目名称
4 | leftNavdefaultOpenAll: false,//是否默认展开所有侧导航自导航 true展开 false不展开(会展开当前路由所在的一级菜单)
5 | CollapseModel: true,//侧导航切换的模式 true为手风琴模式 默认false
6 | collapsedDefaultOpen: false,//默认是否展开侧导航 true展开 false收起
7 |
8 | mock: true,//是否使用mock数据, 如果是生产环境此项配置不生效(暂无真实接口支持,只能用mock数据接口)
9 | };
10 |
--------------------------------------------------------------------------------
/src/views/mainContent/userManage/echarts/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import CBaseComponent from '@/components/CBaseComponent'
3 |
4 | @CBaseComponent
5 | class UserManageEcharts extends Component{
6 | render(){
7 | return (
8 | UserManageEcharts
9 | )
10 | }
11 | }
12 |
13 | export default UserManageEcharts
14 |
--------------------------------------------------------------------------------
/src/servers/authManageApi.js:
--------------------------------------------------------------------------------
1 | import { ajax_post} from "./index";
2 |
3 | // 删除角色
4 | export const delRoleList = (data) => ajax_post('/fe/authManage/roleList/delete/', data);
5 | // 新增角色
6 | export const insertRoleList = (data) => ajax_post('/fe/authManage/roleList/insert/', data);
7 | // 编辑角色
8 | export const editRoleList = (data) => ajax_post('/fe/authManage/roleList/edit/', data);
9 |
--------------------------------------------------------------------------------
/public/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "short_name": "React App",
3 | "name": "Create React App Sample",
4 | "icons": [
5 | {
6 | "src": "favicon.ico",
7 | "sizes": "64x64 32x32 24x24 16x16",
8 | "type": "image/x-icon"
9 | }
10 | ],
11 | "start_url": ".",
12 | "display": "standalone",
13 | "theme_color": "#000000",
14 | "background_color": "#ffffff"
15 | }
16 |
--------------------------------------------------------------------------------
/config/jest/cssTransform.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // This is a custom Jest transformer turning style imports into empty objects.
4 | // http://facebook.github.io/jest/docs/en/webpack.html
5 |
6 | module.exports = {
7 | process() {
8 | return 'module.exports = {};';
9 | },
10 | getCacheKey() {
11 | // The output is always the same.
12 | return 'cssTransform';
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/src/views/mainContent/storeManage/list/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .user-manage-list{
3 | .filter-wrap{
4 | justify-content: space-between;
5 | .filter-left{
6 | justify-content: start;
7 | &>*{
8 | margin-right: 5px;
9 | }
10 | }
11 | .filter-right{
12 | justify-content: end;
13 | &>*{
14 | margin-left: 5px;
15 | }
16 | }
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/views/mainContent/userManage/list/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .user-manage-list{
3 | .filter-wrap{
4 | justify-content: space-between;
5 | .filter-left{
6 | justify-content: start;
7 | &>*{
8 | margin-right: 5px;
9 | }
10 | }
11 | .filter-right{
12 | justify-content: end;
13 | &>*{
14 | margin-left: 5px;
15 | }
16 | }
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/redux/common/action-type.js:
--------------------------------------------------------------------------------
1 |
2 | // 登录用户信息
3 | export const USERINFO = 'USERINFO';
4 | // 左侧导航切换
5 | export const COLLAPSEDTOGGLE = 'COLLAPSEDTOGGLE';
6 | // 设置面包屑导航数据
7 | export const SETBREADCRUMB = 'SETBREADCRUMB';
8 | // 面包屑导航右侧reload的标志
9 | export const RELOAD = 'RELOAD';
10 | // 浏览器信息(宽度、高度等)
11 | export const WINDOWINFO = 'WINDOWINFO';
12 | // 切换主题
13 | export const CURRENTTHEME = 'CURRENTTHEME';
14 |
--------------------------------------------------------------------------------
/src/views/mainContent/authManage/roleList/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .auth-manage-list{
3 | .filter-wrap{
4 | justify-content: space-between;
5 | .filter-left{
6 | justify-content: start;
7 | &>*{
8 | margin-right: 5px;
9 | }
10 | }
11 | .filter-right{
12 | justify-content: end;
13 | &>*{
14 | margin-left: 5px;
15 | }
16 | }
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/views/mainContent/goodsManage/goodsList/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .user-manage-list{
3 | .filter-wrap{
4 | justify-content: space-between;
5 | .filter-left{
6 | justify-content: start;
7 | &>*{
8 | margin-right: 5px;
9 | }
10 | }
11 | .filter-right{
12 | justify-content: end;
13 | &>*{
14 | margin-left: 5px;
15 | }
16 | }
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/views/mainContent/userManage/adminList/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .user-manage-list{
3 | .filter-wrap{
4 | justify-content: space-between;
5 | .filter-left{
6 | justify-content: start;
7 | &>*{
8 | margin-right: 5px;
9 | }
10 | }
11 | .filter-right{
12 | justify-content: end;
13 | &>*{
14 | margin-left: 5px;
15 | }
16 | }
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/routers/authManageRouter.js:
--------------------------------------------------------------------------------
1 |
2 | import authManage from '@/views/mainContent/authManage'
3 |
4 | import authManageRole from '@/views/mainContent/authManage/roleList'
5 |
6 | export default {
7 | path: '/authManage',
8 | component: authManage,
9 | exact: true,
10 | children: [
11 | {
12 | path: '/authManage/role',
13 | component: authManageRole,
14 | exact: true,
15 | },
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/src/views/mainContent/historyRecord/deleteUserList/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .history-record-delete-user-list{
3 | .filter-wrap{
4 | justify-content: space-between;
5 | .filter-left{
6 | justify-content: start;
7 | &>*{
8 | margin-right: 5px;
9 | }
10 | }
11 | .filter-right{
12 | justify-content: end;
13 | &>*{
14 | margin-left: 5px;
15 | }
16 | }
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/src/views/mainContent/historyRecord/deleteAdminUserList/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .history-record-delete-user-list{
3 | .filter-wrap{
4 | justify-content: space-between;
5 | .filter-left{
6 | justify-content: start;
7 | &>*{
8 | margin-right: 5px;
9 | }
10 | }
11 | .filter-right{
12 | justify-content: end;
13 | &>*{
14 | margin-left: 5px;
15 | }
16 | }
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | /node_modules
5 | /.idea
6 | .idea
7 | /.pnp
8 | .pnp.js
9 |
10 | # testing
11 | /coverage
12 |
13 | # production
14 | /build
15 |
16 | # misc
17 | .DS_Store
18 | .env.local
19 | .env.development.local
20 | .env.test.local
21 | .env.production.local
22 |
23 | npm-debug.log*
24 | yarn-debug.log*
25 | yarn-error.log*
26 |
--------------------------------------------------------------------------------
/src/mock/authManage/index.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs';
2 | import { formatURL} from '../index'
3 |
4 | // 权限管理角色
5 | import {
6 | deleteAuthManageRole,
7 | insertAuthManageRole,
8 | editStoreManage,} from "./roleList";
9 |
10 | // 删除角色
11 | Mock.mock(formatURL('/authManage/roleList/delete'), 'post', deleteAuthManageRole);
12 | // 新建角色
13 | Mock.mock(formatURL('/authManage/roleList/insert'), 'post', insertAuthManageRole);
14 | // 编辑角色
15 | Mock.mock(formatURL('/authManage/roleList/edit'), 'post', editStoreManage);
16 |
17 |
--------------------------------------------------------------------------------
/config/utils.js:
--------------------------------------------------------------------------------
1 | var childProcess = require('child_process');
2 |
3 | const exec = (command) => {
4 | return new Promise(function(resolve, reject) {
5 | let cmd = childProcess.exec(command, {maxBuffer: 50000 * 1024}, function(err, stdout) {
6 | if (err) {
7 | reject(err);
8 | } else {
9 | resolve(stdout);
10 | }
11 | });
12 | cmd.stdout.pipe(process.stdout);
13 | cmd.stderr.pipe(process.stderr);
14 | })
15 | };
16 |
17 | module.exports = {
18 | exec
19 | };
--------------------------------------------------------------------------------
/src/mock/statistics/index.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs';
2 | import { formatURL} from '../index'
3 |
4 | import {
5 | getStatisticsStoreByCategory,
6 | getStatisticsNewStore,
7 | getStatisticsStoreRank} from "./storeApiList";
8 |
9 | /*店铺按分类统计数量*/
10 | Mock.mock(formatURL('/statistics/store/category/get'), 'get', getStatisticsStoreByCategory);
11 | /*新增店铺数量统计*/
12 | Mock.mock(formatURL('/statistics/store/new/get'), 'get', getStatisticsNewStore);
13 | /*店铺排行榜(信誉、售后、星级)*/
14 | Mock.mock(formatURL('/statistics/store/rank/get'), 'get', getStatisticsStoreRank);
15 |
16 |
--------------------------------------------------------------------------------
/src/views/mainContent/home/baseMap/markerContent/index.js:
--------------------------------------------------------------------------------
1 |
2 | import React from 'react'
3 | import ReactDOM from 'react-dom'
4 | import MarkerContent from './markerContent'
5 | let componentInfoContent = null;
6 | let getRef = (self) => {
7 | componentInfoContent = self.refs.markerContent;
8 | };
9 |
10 | export const markerContentInit = (data, map, el) => {
11 | ReactDOM.render(, document.createElement('div'));
12 | return new Promise((resolve, reject) => {
13 | resolve(componentInfoContent);
14 | })
15 | };
16 |
--------------------------------------------------------------------------------
/src/components/CDetailInfo/detailInfoTitle.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react'
2 | import './index.scss'
3 |
4 | class CDetailInfoTitle extends Component{
5 | render(){
6 | return (
7 |
8 |
9 |
10 | {this.props.title}
11 |
12 |
{this.props.children}
13 |
14 | )
15 | }
16 | }
17 |
18 |
19 | export default CDetailInfoTitle
20 |
--------------------------------------------------------------------------------
/src/servers/goodsManageApi.js:
--------------------------------------------------------------------------------
1 | import {ajax_get, ajax_post} from "./index";
2 |
3 | // 获取商品列表
4 | export const getGoodsList = (data) => ajax_get('/fe/goodsManage/goodsList/get/', data);
5 | // 删除商品
6 | export const delGoodsList = (data) => ajax_post('/fe/goodsManage/goodsList/delete/', data);
7 | // 新增商品
8 | export const insertGoodsList = (data) => ajax_post('/fe/goodsManage/goodsList/insert/', data);
9 | // 编辑商品
10 | export const editGoodsList = (data) => ajax_post('/fe/goodsManage/goodsList/edit/', data);
11 | // 获取商品详情
12 | export const detailGoodsList = (data) => ajax_get('/fe/goodsManage/goodsList/detail/', data);
13 |
--------------------------------------------------------------------------------
/src/views/mainContent/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .main-content{
3 | height: 100%;
4 | overflow: auto;
5 | .main-content-scroll{
6 | height: 100%;
7 | position: relative;
8 | //min-width: 1000px;
9 | }
10 | .main-breadcrumb{
11 | background-color: #ffffff;
12 | height: 40px;
13 | justify-content: start;
14 | padding: 0 10px;
15 | span{
16 | font-size: 12px;
17 | }
18 | }
19 | .main-content-body{
20 | padding: 10px;
21 | //height: calc(100% - 40px);
22 | .main-content-body-card{
23 | .ant-card-body{
24 | padding: 15px;
25 | }
26 | }
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/components/CBaseComponent/index.js:
--------------------------------------------------------------------------------
1 |
2 | function InjectUnount(target) {
3 | if(!target) return
4 | // 改装componentWillUnmount,销毁的时候记录一下
5 | let next = target.prototype.componentWillUnmount;
6 | target.prototype.componentWillUnmount = function() {
7 | if (next) next.call(this, ...arguments);
8 | this.unmount = true;
9 | };
10 | // 对setState的改装,setState查看目前是否已经销毁
11 | let setState = target.prototype.setState;
12 | target.prototype.setState = function() {
13 | if (this.unmount) return;
14 | setState.call(this, ...arguments);
15 | };
16 | return target
17 | }
18 |
19 | export default InjectUnount;
20 |
--------------------------------------------------------------------------------
/src/mock/commonSchema.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs'
2 | import * as commonData from './commonData'
3 |
4 | let length = commonData.data.adminRoleList.length;
5 |
6 | /*角色列表数据*/
7 | const adminRoleList = {
8 | [`list|${length}`]:[
9 | {
10 | 'id|+1': 1,
11 | 'uid': function () {
12 | return commonData.data.adminRoleList[this.id-1]['uid']
13 | },//真实用户姓名
14 | 'name': function () {
15 | return commonData.data.adminRoleList[this.id-1]['name']
16 | },//登录密码
17 | 'createTime': '@datetime',//创建时间
18 | }
19 | ]
20 | };
21 |
22 | export default {
23 | adminRoleList: Mock.mock(adminRoleList).list,
24 | }
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/src/mock/index.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs';
2 |
3 | export const mockConfig = {
4 | baseURL: 'mock/fe',
5 | baseMock: {
6 | status: 200,
7 | code: '',
8 | errmsg: '',
9 | data: {},
10 | }
11 | };
12 |
13 | export const formatURL = (url) => {
14 | return new RegExp(`${mockConfig.baseURL}${url}`);
15 | };
16 |
17 | // import './userManage/index'
18 | require('./common/index');
19 | require('./login/index');
20 | require('./userManage/index');
21 | require('./storeManage/index');
22 | require('./authManage/index');
23 | require('./goodsManage/index');
24 | require('./statistics/index');
25 |
26 |
27 | Mock.setup({
28 | timeout: '200-600'
29 | });
30 |
31 |
--------------------------------------------------------------------------------
/src/mock/createMockData.js:
--------------------------------------------------------------------------------
1 |
2 | import userManage from "./userManage/schema";
3 | import storeManage from "./storeManage/schema";
4 | import goodsManage from "./goodsManage/schema";
5 |
6 | // 商户列表数据
7 | export const userListBusniess = userManage.userListBusniess;
8 | // 商户列表数据(已删除数据列表)
9 | // export const userListBusniessDelete = userManage.userListBusniessDelete;
10 | // 管理员数据
11 | export const userListAdmin = userManage.userListAdmin;
12 | // 管理员数据(已删除数据列表)
13 | // export const userListAdminDelete = userManage.userListAdminDelete;
14 | // 店铺列表数据
15 | export const storeManageStoreList = storeManage.storeList;
16 | // 商品列表数据
17 | export const goodsManageList = goodsManage.goodsList;
18 |
--------------------------------------------------------------------------------
/src/components/CAvatar/index.scss:
--------------------------------------------------------------------------------
1 |
2 |
3 | .c-avatar{
4 | justify-content: start;
5 | align-items: start;
6 | padding-bottom: 20px;
7 | border-bottom: 1px solid #eeeeee;
8 | .c-avatar-img{
9 | width: 80px;
10 | height: 80px;
11 | flex: none;
12 | border: 1px solid #eeeeee;
13 | border-radius: 2px;
14 | padding: 5px;
15 | margin-right: 10px;
16 | }
17 | .c-avatar-info{
18 | padding: 5px 0;
19 | p{
20 | margin: 0;
21 | }
22 | .c-avatar-title{
23 | font-weight: bold;
24 | }
25 | .c-avatar-rate{
26 | font-size: 14px;
27 | }
28 | .c-avatar-description{
29 | color: #888888;
30 | font-size: 12px;
31 | }
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/src/mock/goodsManage/index.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs';
2 | import { formatURL} from '../index'
3 |
4 | import {
5 | deleteGoodsManage,
6 | getGoodsManageList,
7 | insertGoodsManage,
8 | editGoodsManage,
9 | detailGoodsManage} from "./apiList";
10 |
11 | /*获取商品数据*/
12 | Mock.mock(formatURL('/goodsManage/goodsList/get'), 'get', getGoodsManageList);
13 | Mock.mock(formatURL('/goodsManage/goodsList/delete'), 'post', deleteGoodsManage);
14 | Mock.mock(formatURL('/goodsManage/goodsList/insert'), 'post', insertGoodsManage);
15 | Mock.mock(formatURL('/goodsManage/goodsList/edit'), 'post', editGoodsManage);
16 | // 获取商品详情
17 | Mock.mock(formatURL('/goodsManage/goodsList/detail'), 'get', detailGoodsManage);
18 |
19 |
--------------------------------------------------------------------------------
/src/routers/historyRecordRouter.js:
--------------------------------------------------------------------------------
1 |
2 | import historyRecord from '@/views/mainContent/historyRecord'
3 |
4 | import historyRecordDeleteUserList from '@/views/mainContent/historyRecord/deleteUserList'
5 | import historyRecordDeleteAdminUserList from '@/views/mainContent/historyRecord/deleteAdminUserList'
6 |
7 | export default {
8 | path: '/historyRecord',
9 | component: historyRecord,
10 | exact: true,
11 | children: [
12 | {
13 | path: '/historyRecord/deleteUser',
14 | component: historyRecordDeleteUserList,
15 | exact: true,
16 | },
17 | {
18 | path: '/historyRecord/deleteAdminUser',
19 | component: historyRecordDeleteAdminUserList,
20 | exact: true,
21 | },
22 | ]
23 | }
24 |
--------------------------------------------------------------------------------
/config/pnpTs.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const { resolveModuleName } = require('ts-pnp');
4 |
5 | exports.resolveModuleName = (
6 | typescript,
7 | moduleName,
8 | containingFile,
9 | compilerOptions,
10 | resolutionHost
11 | ) => {
12 | return resolveModuleName(
13 | moduleName,
14 | containingFile,
15 | compilerOptions,
16 | resolutionHost,
17 | typescript.resolveModuleName
18 | );
19 | };
20 |
21 | exports.resolveTypeReferenceDirective = (
22 | typescript,
23 | moduleName,
24 | containingFile,
25 | compilerOptions,
26 | resolutionHost
27 | ) => {
28 | return resolveModuleName(
29 | moduleName,
30 | containingFile,
31 | compilerOptions,
32 | resolutionHost,
33 | typescript.resolveTypeReferenceDirective
34 | );
35 | };
36 |
--------------------------------------------------------------------------------
/src/assets/css/common.scss:
--------------------------------------------------------------------------------
1 | @import "./var.scss";
2 | @import "./antdReset.scss";
3 | body{
4 | font-size: 12px;
5 | font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
6 | }
7 | body,html{
8 | width: 100%;
9 | height: 100%;
10 | }
11 | #root{
12 | width: 100%;
13 | height: 100%;
14 | }
15 |
16 | .flex{
17 | display: flex;
18 | flex-direction: row;
19 | align-items: center;
20 | justify-content: center;
21 | }
22 |
23 | .ellipsis{
24 | overflow: hidden;
25 | text-overflow: ellipsis;
26 | white-space: nowrap;
27 | }
28 |
29 | .text-color-white{
30 | color: $text-color-white;
31 | }
32 |
33 | /*table操作列的样式*/
34 | .operate{
35 | &>*{
36 | margin-right: 5px;
37 | &:nth-last-of-type(1){
38 | margin-right: 0;
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/components/CBreadcrumb/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component} from 'react';
2 | import PropTypes from 'prop-types'
3 | import { Breadcrumb} from 'antd'
4 | import './index.scss'
5 |
6 | class CBreadcrumb extends Component {
7 |
8 |
9 | render(){
10 | return (
11 |
12 |
13 | {
14 | this.props.data.map((item, index)=>{
15 | return {item.name}
16 | })
17 | }
18 |
19 | {this.props.children}
20 |
21 |
22 | )
23 | }
24 | }
25 |
26 | CBreadcrumb.propTypes = {
27 | data: PropTypes.array.isRequired,
28 | children: PropTypes.element
29 | };
30 |
31 | export default CBreadcrumb
32 |
--------------------------------------------------------------------------------
/src/servers/historyRecordApi.js:
--------------------------------------------------------------------------------
1 |
2 | import {ajax_get, ajax_post} from "./index";
3 |
4 | // 获取已删除的商家用户列表
5 | export const getDeleteUserList = (data) => ajax_get('/fe/historyRecord/deleteUserList/get/', data);
6 | // 恢复已删除用户
7 | export const postResetDeleteUser = (data) => ajax_post('/fe/historyRecord/deleteUserList/reset/', data);
8 | // 永久删除用户
9 | export const postPermanentDeleteUser = (data) => ajax_post('/fe/historyRecord/deleteUserList/delete/', data);
10 |
11 | // 获取已删除的系统用户列表
12 | export const getDeleteAdminUserList = (data) => ajax_get('/fe/historyRecord/deleteAdminUserList/get/', data);
13 | // 恢复已删除系统用户
14 | export const postResetDeleteAdminUser = (data) => ajax_post('/fe/historyRecord/deleteAdminUserList/reset/', data);
15 | // 永久删除系统用户
16 | export const postPermanentDeleteAdminUser = (data) => ajax_post('/fe/historyRecord/deleteAdminUserList/delete/', data);
17 |
18 |
--------------------------------------------------------------------------------
/src/mock/storeManage/index.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs';
2 | import { formatURL} from '../index'
3 |
4 | import {
5 | getStoreAllList,
6 | deleteStoreManage,
7 | getStoreManageList,
8 | insertStoreManage,
9 | editStoreManage,
10 | detailStoreManage} from "./apiList";
11 |
12 | /*获取店铺列表数据*/
13 | Mock.mock(formatURL('/storeManage/storeList/get'), 'get', getStoreManageList);
14 | /*获取所有店铺列表数据*/
15 | Mock.mock(formatURL('/storeManage/storeAllList/get'), 'get', getStoreAllList);
16 | // 删除商铺
17 | Mock.mock(formatURL('/storeManage/storeList/delete'), 'post', deleteStoreManage);
18 | // 新建店铺
19 | Mock.mock(formatURL('/storeManage/storeList/insert'), 'post', insertStoreManage);
20 | // 编辑店铺
21 | Mock.mock(formatURL('/storeManage/storeList/edit'), 'post', editStoreManage);
22 | // 获取用户详情
23 | Mock.mock(formatURL('/storeManage/storeList/detail'), 'get', detailStoreManage);
24 |
25 |
--------------------------------------------------------------------------------
/src/views/mainContent/home/baseMap/markerContent/markerContent.scss:
--------------------------------------------------------------------------------
1 |
2 | .marker-content{
3 | background-color: #ffffff;
4 | border: 1px solid #eeeeee;
5 | border-radius: 2px;
6 | overflow: hidden;
7 | min-width: 200px;
8 | .marker-content-title{
9 | padding: 5px 10px;
10 | border-bottom: 1px solid #eeeeee;
11 | font-size: 12px;
12 | justify-content: space-between;
13 | span{
14 | padding-right: 20px;
15 | }
16 | i{
17 | cursor: pointer;
18 | font-size: 14px;
19 | }
20 | }
21 | .marker-content-body{
22 | padding: 10px;
23 | .content-item{
24 | justify-content: start;
25 | padding: 2px 0;
26 | font-size: 12px;
27 | .label{
28 | margin-right: 5px;
29 | }
30 | }
31 | }
32 |
33 | .marker-content-footer{
34 | border-top: 1px solid #eeeeee;
35 | text-align: right;
36 | padding: 5px 10px;
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/components/CAvatar/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component} from 'react';
2 | import PropTypes from 'prop-types'
3 | import { Rate} from 'antd'
4 | import './index.scss'
5 |
6 | class CAvatar extends Component {
7 | render(){
8 | return (
9 |
10 |

11 |
12 |
{this.props.title}
13 | {this.props.type === 'rate' &&
}
14 |
{this.props.description}
15 |
16 |
17 | )
18 | }
19 | }
20 |
21 | CAvatar.defaultProps = {
22 | type: 'user'
23 | };
24 |
25 | CAvatar.propTypes = {
26 | type: PropTypes.string,
27 | rate: PropTypes.number,
28 | };
29 |
30 | export default CAvatar
31 |
--------------------------------------------------------------------------------
/src/redux/common/action.js:
--------------------------------------------------------------------------------
1 |
2 | import * as Common from './action-type'
3 |
4 | // 修改left-nav状态
5 | export const collapsedToggle = (value)=>{
6 | return {
7 | type: Common.COLLAPSEDTOGGLE,
8 | value
9 | }
10 | };
11 |
12 | // 修改left-nav状态
13 | export const setBreadcrumb = (value)=>{
14 | return {
15 | type: Common.SETBREADCRUMB,
16 | value
17 | }
18 | };
19 |
20 | // 修改reload状态
21 | export const setReload = (value)=>{
22 | return {
23 | type: Common.RELOAD,
24 | value
25 | }
26 | };
27 |
28 | // 修改windowInfo
29 | export const setWindowInfo = (value)=>{
30 | return {
31 | type: Common.WINDOWINFO,
32 | value
33 | }
34 | };
35 |
36 | // 修改登录用户信息
37 | export const setUserInfo = (value)=>{
38 | return {
39 | type: Common.USERINFO,
40 | value
41 | }
42 | };
43 |
44 | // 切换主题
45 | export const setCurrentTheme = (value)=>{
46 | return {
47 | type: Common.CURRENTTHEME,
48 | value
49 | }
50 | };
51 |
--------------------------------------------------------------------------------
/src/servers/storeManageApi.js:
--------------------------------------------------------------------------------
1 | import {ajax_get, ajax_post} from "./index";
2 |
3 | // 获取商铺列表
4 | export const getStoreList = (data) => ajax_get('/fe/storeManage/storeList/get/', data);
5 | // 删除商铺
6 | export const delStoreList = (data) => ajax_post('/fe/storeManage/storeList/delete/', data);
7 | // 新增商铺
8 | export const insertStoreList = (data) => ajax_post('/fe/storeManage/storeList/insert/', data);
9 | // 编辑商铺
10 | export const editStoreList = (data) => ajax_post('/fe/storeManage/storeList/edit/', data);
11 | // 获取商铺详情
12 | export const detailStoreList = (data) => ajax_get('/fe/storeManage/storeList/detail/', data);
13 | // 根据店铺分类统计店铺数量
14 | export const statisticsStoreByCategory = (data) => ajax_get('/fe/statistics/store/category/get', data);
15 | // 统计新增店铺数量
16 | export const statisticsNewStore = (data) => ajax_get('/fe/statistics/store/new/get', data);
17 | // 店铺排行榜(信誉、售后、星级)
18 | export const statisticsStoreRank = (data) => ajax_get('/fe/statistics/store/rank/get', data);
19 |
20 |
--------------------------------------------------------------------------------
/src/components/CPageNew/index.scss:
--------------------------------------------------------------------------------
1 |
2 | @import "@/assets/css/var.scss";
3 |
4 | .c-page-new{
5 | //max-width: 600px;
6 | //min-width: 600px;
7 | .c-page-new-item{
8 | .c-page-new-item-title{
9 | justify-content: start;
10 | font-weight: bold;
11 | font-size: 13px;
12 | height: 40px;
13 | line-height: 40px;
14 | margin-bottom: 20px;
15 | .title-before-icon{
16 | display: inline-block;
17 | width: 4px;
18 | height: 15px;
19 | background: $main-base-primary-color;
20 | border-radius: 2px;
21 | margin-right: 5px;
22 | }
23 | }
24 | .c-page-form{
25 | justify-content: space-between;
26 | .c-page-form-item{
27 | flex: 1;
28 | }
29 | }
30 | }
31 | .c-page-footer-button{
32 | background-color: #ffffff;
33 | padding: 15px 30px;
34 | border-top: 1px solid #eaeaea;
35 | margin-top: 60px;
36 | &>*{
37 | margin-right: 10px;
38 | }
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/components/CSwiper/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .c-swiper{
3 | width: 100%;
4 | .c-swiper-container{
5 | width: 100%;
6 | .swiper-wrapper{
7 | .swiper-slide{
8 | background-color: #ffffff;
9 | img{
10 | width: 100%;
11 | height: 100%;
12 | }
13 | }
14 | }
15 |
16 | .swiper-button-prev{
17 | background-image: none;
18 | i{
19 | font-size: 66px;
20 | position: absolute;
21 | top: -13px;
22 | left: 0;
23 | color: #888888;
24 | }
25 | &:hover{
26 | i{
27 | color: #999999;
28 | }
29 | }
30 | }
31 | .swiper-button-next{
32 | background-image: none;
33 | i{
34 | font-size: 66px;
35 | position: absolute;
36 | top: -12px;
37 | right: 0;
38 | color: #888888;
39 | }
40 | &:hover{
41 | i{
42 | color: #999999;
43 | }
44 | }
45 | }
46 |
47 | .swiper-pagination{
48 |
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/views/mainContent/personal/index.js:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * 个人中心
4 | * */
5 |
6 | import React, {Component} from 'react';
7 | import CBaseComponent from '@/components/CBaseComponent'
8 | import {connect} from 'react-redux'
9 | import { bindActionCreators} from 'redux'
10 | import { setBreadcrumb} from "@/redux/common/action";
11 | // import PercentageEcharts from './percentageEcharts'
12 | import './index.scss'
13 |
14 | @CBaseComponent
15 | class Personal extends Component{
16 |
17 | componentWillMount(){
18 |
19 | }
20 |
21 | componentDidMount(){
22 | this.props.setBreadcrumb([{name: '个人中心'}]);
23 | }
24 |
25 | render(){
26 | return (
27 | 个人中心
28 |
29 | )
30 | }
31 | }
32 |
33 | const mapStateToProps = (state) => {
34 | return {
35 |
36 | }
37 | };
38 |
39 | const mapDispatchToProps = (dispatch) => {
40 | return {
41 | setBreadcrumb: bindActionCreators(setBreadcrumb, dispatch)
42 | }
43 | };
44 |
45 | export default connect(mapStateToProps, mapDispatchToProps)(Personal);
46 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | // import App from './views/App';
4 | import '@/assets/css/common.scss'
5 | import * as serviceWorker from './serviceWorker';
6 | import Route from '@/routers/index'
7 | import Store from '@/redux/index'
8 | import { Provider } from 'react-redux'
9 | import { AppContainer} from 'react-hot-loader'
10 | import '@/mock'
11 |
12 |
13 |
14 | const render = (Component) => {
15 | ReactDOM.render(
16 |
17 |
18 |
19 |
20 | ,
21 | document.getElementById('root'));
22 | };
23 |
24 | render(Route);
25 |
26 | if (module.hot) {
27 | module.hot.accept('./routers/', () => {
28 | render(Route);
29 | })
30 | }
31 |
32 |
33 |
34 | // If you want your app to work offline and load faster, you can change
35 | // unregister() to register() below. Note this comes with some pitfalls.
36 | // Learn more about service workers: https://bit.ly/CRA-PWA
37 | serviceWorker.unregister();
38 |
--------------------------------------------------------------------------------
/src/components/CForm/CCheckbox.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react'
2 | // import PropTypes from 'prop-types'
3 | import { Checkbox} from 'antd'
4 | import './index.scss'
5 |
6 | class CCheckbox extends Component{
7 |
8 | constructor(props) {
9 | super(props);
10 | this.changeHandler = this.changeHandler.bind(this);
11 | }
12 |
13 |
14 | state = {
15 | value: false
16 | }
17 |
18 | componentWillReceiveProps(nextProps) {
19 | this.setState({
20 | value: nextProps.value
21 | });
22 | }
23 |
24 | changeHandler(e){
25 | let value = e.target.checked;
26 | this.setState({
27 | value: value
28 | });
29 | this.props.onChange && this.props.onChange(value);
30 | }
31 |
32 | componentWillMount(){
33 | let value = this.props.value || false;
34 | this.setState({
35 | value: value
36 | })
37 | }
38 |
39 | render(){
40 | const {onChange, ...props} = this.props;
41 | return (
42 | this.changeHandler(e)}>{this.props.children}
43 | )
44 | }
45 | }
46 |
47 | export default CCheckbox
48 |
--------------------------------------------------------------------------------
/src/components/CForm/CSwitch.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react'
2 | // import PropTypes from 'prop-types'
3 | import { Switch} from 'antd'
4 | import './index.scss'
5 |
6 | class CSwitch extends Component{
7 |
8 | constructor(props) {
9 | super(props);
10 | this.changeHandler = this.changeHandler.bind(this);
11 | }
12 |
13 |
14 | state = {
15 | value: false
16 | }
17 |
18 | componentWillReceiveProps(nextProps) {
19 | this.setState({
20 | value: nextProps.value
21 | });
22 | }
23 |
24 | changeHandler(checked){
25 | let value = checked;
26 | this.setState({
27 | value: value
28 | });
29 | this.props.onChange && this.props.onChange(value);
30 | }
31 |
32 | componentWillMount(){
33 | let value = this.props.value || false;
34 | this.setState({
35 | value: value
36 | })
37 | }
38 |
39 | render(){
40 | const {onChange, value, ...props} = this.props;
41 | return (
42 | this.changeHandler(checked)} />
43 | )
44 | }
45 | }
46 |
47 | CSwitch.defaultProps = {
48 | size: 'small'
49 | }
50 |
51 | export default CSwitch
52 |
--------------------------------------------------------------------------------
/src/views/mainContent/userManage/adminList/data.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | export const tableData = {
4 | tHead: [
5 | {
6 | key: 'id',
7 | title: 'id',
8 | dataIndex: 'id',
9 | },
10 | {
11 | key: 'name',
12 | dataIndex: 'name',
13 | title: '姓名',
14 | },
15 | {
16 | key: 'password',
17 | dataIndex: 'password',
18 | title: '密码',
19 | },
20 | {
21 | key: 'email',
22 | dataIndex: 'email',
23 | title: '邮箱',
24 | },
25 | {
26 | key: 'phone',
27 | dataIndex: 'phone',
28 | title: '联系电话',
29 | },
30 | {
31 | key: 'userRole',
32 | dataIndex: 'userRole.name',
33 | title: '角色',
34 | filterMultiple: false,
35 | filters: []
36 | },
37 | {
38 | key: 'createTime',
39 | dataIndex: 'createTime',
40 | title: '创建时间',
41 | filterMultiple: true,
42 | filterDate: 'range',
43 | },
44 | {
45 | key: 'operate',
46 | dataIndex: 'operate',
47 | title: '操作',
48 | fixed: 'right',
49 | width: 100,
50 | slot: 'operate',
51 | },
52 | ],
53 | tBody: [],
54 | tPage: {
55 | total: 0,
56 | page: 1,
57 | pageSize: 10
58 | }
59 | };
60 |
--------------------------------------------------------------------------------
/src/components/CForm/CRadio.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react'
2 | // import PropTypes from 'prop-types'
3 | import { Radio} from 'antd'
4 | import './index.scss'
5 |
6 | class CRadio extends Component{
7 |
8 | constructor(props) {
9 | super(props);
10 | this.changeHandler = this.changeHandler.bind(this);
11 | }
12 |
13 |
14 | state = {
15 | value: ''
16 | }
17 |
18 | componentWillReceiveProps(nextProps) {
19 | this.setState({
20 | value: nextProps.value
21 | });
22 | }
23 |
24 | changeHandler(e){
25 | let value = e.target.value;
26 | this.setState({
27 | value: value
28 | });
29 | this.props.onChange && this.props.onChange(value);
30 | }
31 |
32 | componentWillMount(){
33 | let value = this.props.value || '';
34 | this.setState({
35 | value: value
36 | })
37 | }
38 |
39 | render(){
40 | return (
41 | this.changeHandler(e)} value={this.state.value}>
42 | {
43 | this.props.options.map((item=>{
44 | return {item.name}
45 | }))
46 | }
47 |
48 | )
49 | }
50 | }
51 |
52 | export default CRadio
53 |
--------------------------------------------------------------------------------
/src/components/CScroll/index.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component} from 'react';
2 | // import PropTypes from 'prop-types';
3 | import { Scrollbars } from 'react-custom-scrollbars';
4 |
5 | export default class CScroll extends Component{
6 | constructor(props){
7 | super(props);
8 | this.handleScroll = this.handleScroll.bind(this);
9 | }
10 | static propTypes = {
11 |
12 | };
13 | renderThumb({ style, ...props }) {//设置滚动条的样式
14 | // 暂时不设置滚动条样式
15 | const thumbStyle = {
16 | width: '4px',
17 | backgroundColor: '#000000',
18 | opacity: '0.2',
19 | borderRadius: '4px',
20 | right: '0px',
21 | };
22 | return (
23 |
26 | );
27 | }
28 | handleScroll(e){
29 | this.props.onScroll && this.props.onScroll(e);
30 | }
31 | render(){
32 | return(
33 |
42 | {this.props.children}
43 |
44 | )
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/mock/login/index.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs'
2 | import { formatURL} from '../index'
3 | import { mockConfig} from '../index'
4 | import { filterByObj} from "../commonUtils";
5 | import { userListBusniess, userListAdmin} from '../createMockData'
6 | let userList = [...userListBusniess, ...userListAdmin];
7 |
8 | Mock.mock(formatURL('/user/login'), 'post', (opts) => {
9 | // 获取参数
10 | let name = JSON.parse(opts.body).name;
11 | let password = JSON.parse(opts.body).password;
12 | let result = filterByObj(userList, {name,password}, 'and', 'eq');
13 | if(!result || !result.length){
14 | // 支持手机号登录
15 | result = filterByObj(userList, {phone: name,password}, 'and', 'eq');
16 | console.log(result,'====---result==--')
17 | }
18 | console.log(result,'result==--')
19 | let errmsg = '';
20 | let code = 10000;
21 | let status = 400;
22 | let data = {};
23 | if(!result || !result.length){
24 | errmsg = '登录失败';
25 | code = 10001;
26 | }else if(result[0].isDelete){
27 | errmsg = '该用户已被删除,请联系管理员';
28 | code = 10002;
29 | }else if(!result[0].isActive){
30 | errmsg = '该用户已被停用,请联系管理员';
31 | code = 10002;
32 | }else{
33 | data = result[0];
34 | status = 200;
35 | }
36 | return {...mockConfig.baseMock, ...{errmsg, code, data, status}}
37 | });
38 |
--------------------------------------------------------------------------------
/src/routers/goodsManageRouter.js:
--------------------------------------------------------------------------------
1 |
2 | import goodsManage from '@/views/mainContent/goodsManage'
3 |
4 | import goodsManageList from '@/views/mainContent/goodsManage/goodsList'
5 | import goodsManageListNew from '@/views/mainContent/goodsManage/goodsList/listNew'
6 | import goodsManageListDetail from '@/views/mainContent/goodsManage/goodsList/listDetailInfo'
7 |
8 |
9 | export default {
10 | path: '/goodsManage',
11 | component: goodsManage,
12 | exact: true,
13 | children: [
14 | // {
15 | // path: '/storeManage/echarts',
16 | // component: storeManageEcharts,
17 | // exact: true,
18 | // },
19 | {
20 | path: '/goodsManage/list',
21 | component: goodsManageList,
22 | exact: true,
23 | },
24 | {
25 | path: '/goodsManage/list/new',
26 | component: goodsManageListNew,
27 | exact: true,
28 | },
29 | {
30 | path: '/goodsManage/list/detail',
31 | component: goodsManageListDetail,
32 | exact: true,
33 | },
34 | // {
35 | // path: '/storeManage/grade',
36 | // component: storeManageGrade,
37 | // exact: true,
38 | // },
39 | // {
40 | // path: '/storeManage/member',
41 | // component: storeManageMemer,
42 | // exact: true,
43 | // }
44 | ]
45 | }
46 |
--------------------------------------------------------------------------------
/src/servers/userManageApi.js:
--------------------------------------------------------------------------------
1 | import {ajax_get, ajax_post} from "./index";
2 |
3 | // 获取商家用户列表
4 | export const getUserList = (data) => ajax_get('/fe/userManage/userList/get/', data);
5 | // 删除商家用户
6 | export const delUserList = (data) => ajax_post('/fe/userManage/userList/delete/', data);
7 | // 新增商家用户
8 | export const insertUserList = (data) => ajax_post('/fe/userManage/userList/insert/', data);
9 | // 编辑商家用户
10 | export const editUserList = (data) => ajax_post('/fe/userManage/userList/edit/', data);
11 | // 获取商家用户详情
12 | export const detailUserList = (data) => ajax_get('/fe/userManage/userList/detail/', data);
13 | // 激活停用
14 | export const editActiveUserList = (data) => ajax_post('/fe/userManage/userList/active/', data);
15 |
16 |
17 | // 获取管理员用户列表
18 | export const getUserAdminList = (data) => ajax_get('/fe/userManage/adminList/get/', data);
19 | // 删除管理员用户
20 | export const delUserAdminList = (data) => ajax_post('/fe/userManage/adminList/delete/', data);
21 | // 新增管理员用户
22 | export const insertUserAdminList = (data) => ajax_post('/fe/userManage/adminList/insert/', data);
23 | // 编辑管理员用户
24 | export const editUserAdminList = (data) => ajax_post('/fe/userManage/adminList/edit/', data);
25 | // 获取管理员用户详情
26 | export const detailUserAdminList = (data) => ajax_get('/fe/userManage/adminList/detail/', data);
27 |
--------------------------------------------------------------------------------
/src/servers/commonApi.js:
--------------------------------------------------------------------------------
1 | import Axios from 'axios'
2 | import {ajax_get, ajax_post} from "./index";
3 |
4 | // 登录
5 | export const postLogin = (data) => ajax_post('/fe/user/login/', data);
6 |
7 | // 获取商家用户角色列表
8 | export const getUserBussinesRoleList = (data) => ajax_get('/fe/common/userBussinesRoleList/get/', data);
9 | // 获取管理员角色列表
10 | export const getUserAdminRoleList = (data) => ajax_get('/fe/common/userAdminRoleList/get/', data);
11 | // 获取商店类型列表
12 | export const getStoreCategoryList = (data) => ajax_get('/fe/common/storeCategoryList/get/', data);
13 | // 获取商家用户列表id name
14 | export const getUserBusniessList = (data) => ajax_get('/fe/common/userListBusniess/get/', data);
15 |
16 |
17 |
18 |
19 | // 高德地图关键字搜索
20 | export const getAMapKeywordsSearch = (data) => {
21 | let url = 'https://restapi.amap.com/v3/place/text';
22 | data.key = 'ba979a0bcd8b467f8a33479f832077c3';//高德地图web服务的key
23 | data.offset = data.offset || 20;
24 | data.page = data.page || 1;
25 | data.extensions = 'all';
26 | data.types = data.types || 190400;
27 | data.keywords = data.keywords || '';
28 |
29 | return Axios.get(url, {
30 | params: data,
31 | }).then(response => {
32 | return Promise.resolve(response && response.data)
33 | }).catch(error=>{
34 | return Promise.reject(error)
35 | })
36 | };
37 |
38 |
--------------------------------------------------------------------------------
/src/mock/goodsManage/schema.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs'
2 | import * as commonData from '../commonData'
3 | import storeManage from '../storeManage/schema'
4 | const Random = Mock.Random;
5 |
6 | /*商品列表数据*/
7 | const goodsList = {
8 | 'list|30-100':[
9 | {
10 | 'id|+1': 1,//商品id
11 | 'storeInfo|1': storeManage.storeList,//店铺id
12 | 'category': 1,//所属分类
13 | 'name': '@cword',//名称
14 | 'description': '@ctitle',//描述
15 | 'price|10-100': 1,//价格
16 | 'originPrice': function () {
17 | return this.price - Random.integer(0, 8)
18 | },//原来的价格
19 | 'stockNum|100-1000': 0,//数量库存
20 | 'tradingTotalNum|1000-100000': 0,//总交易数量
21 | 'tradingMonthNum|100-500': 0,//月交易数量
22 | 'tradingDayNum|0-100': 0,//日交易数量
23 | 'imgs': commonData.data.images.goodsImg,//图片列表id
24 | 'avatarImg': function () {
25 | return this.imgs[0]
26 | },//展示图片
27 | 'commitIds': [],//评价id列表
28 | 'commitGoodRate|0-100': 0,//好评率
29 | 'specification': 1,//规格参数对应的id
30 | 'packList': 0,//包装清单
31 | 'couponIds': [],//优惠券列表id
32 | 'status': '@boolean',//上架(true)下架(false)
33 | 'createTime': '@datetime',//创建时间
34 | }
35 | ]
36 | };
37 |
38 |
39 | export default {
40 | goodsList: Mock.mock(goodsList).list
41 | }
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/src/views/mainContent/historyRecord/deleteAdminUserList/data.js:
--------------------------------------------------------------------------------
1 |
2 | export const tableData = {
3 | tHead: [
4 | {
5 | key: 'id',
6 | title: 'id',
7 | dataIndex: 'id',
8 | },
9 | {
10 | key: 'name',
11 | dataIndex: 'name',
12 | title: '姓名',
13 | },
14 | {
15 | key: 'deleteReason',
16 | dataIndex: 'deleteReason',
17 | title: '删除原因',
18 | width: 100,
19 | },
20 | {
21 | key: 'email',
22 | dataIndex: 'email',
23 | title: '邮箱',
24 | },
25 | {
26 | key: 'phone',
27 | dataIndex: 'phone',
28 | title: '联系电话',
29 | },
30 | {
31 | key: 'userRole',
32 | dataIndex: 'userRole.name',
33 | title: '角色',
34 | filterMultiple: false,
35 | filters: []
36 | },
37 | {
38 | key: 'createTime',
39 | dataIndex: 'createTime',
40 | title: '创建时间',
41 | filterMultiple: true,
42 | filterDate: 'range',
43 | },
44 | {
45 | key: 'deleteTime',
46 | dataIndex: 'deleteTime',
47 | title: '删除时间',
48 | },
49 | {
50 | key: 'operate',
51 | dataIndex: 'operate',
52 | title: '操作',
53 | fixed: 'right',
54 | width: 100,
55 | slot: 'operate',
56 | },
57 | ],
58 | tBody: [],
59 | tPage: {
60 | total: 0,
61 | page: 1,
62 | pageSize: 10
63 | }
64 | };
65 |
--------------------------------------------------------------------------------
/src/redux/common/reducer.js:
--------------------------------------------------------------------------------
1 | import * as Common from './action-type'
2 | import config from '@/config'
3 |
4 | let defaultState = {
5 | currentTheme: 'default',//当前主题
6 | collapsed: config.collapsedDefaultOpen || true,//左侧导航状态
7 | breadcrumbData: [],//面包屑导航数据
8 | reload: false,
9 | userInfo: null,//登录用户信息
10 | windowInfo: {
11 | screenHeight: window.innerHeight || document.body.clientHeight || document.documentElement.clientHeight,//浏览器高度
12 | screenWidth: window.innerWidth || document.body.clientWidth || document.documentElement.clientWidth,//浏览器宽度
13 | mainContentHeight: '',//主内容区域高度
14 | mainContentWidth: '',//主内容区域宽度
15 | }
16 | };
17 |
18 | let CommonReducer = (state = defaultState, action) => {
19 | switch (action.type) {
20 | case Common.COLLAPSEDTOGGLE:
21 | return {...state, ...{collapsed: action.value}};
22 | case Common.SETBREADCRUMB:
23 | return {...state, ...{breadcrumbData: action.value}};
24 | case Common.RELOAD:
25 | return {...state, ...{reload: action.value}};
26 | case Common.WINDOWINFO:
27 | return {...state, ...{windowInfo: action.value}};
28 | case Common.USERINFO:
29 | return {...state, ...{userInfo: action.value}};
30 | case Common.CURRENTTHEME:
31 | return {...state, ...{currentTheme: action.value}};
32 | default:
33 | return state;
34 | }
35 | };
36 |
37 | export default CommonReducer;
38 |
--------------------------------------------------------------------------------
/config/jest/fileTransform.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 | const camelcase = require('camelcase');
5 |
6 | // This is a custom Jest transformer turning file imports into filenames.
7 | // http://facebook.github.io/jest/docs/en/webpack.html
8 |
9 | module.exports = {
10 | process(src, filename) {
11 | const assetFilename = JSON.stringify(path.basename(filename));
12 |
13 | if (filename.match(/\.svg$/)) {
14 | // Based on how SVGR generates a component name:
15 | // https://github.com/smooth-code/svgr/blob/01b194cf967347d43d4cbe6b434404731b87cf27/packages/core/src/state.js#L6
16 | const pascalCaseFileName = camelcase(path.parse(filename).name, {
17 | pascalCase: true,
18 | });
19 | const componentName = `Svg${pascalCaseFileName}`;
20 | return `const React = require('react');
21 | module.exports = {
22 | __esModule: true,
23 | default: ${assetFilename},
24 | ReactComponent: React.forwardRef(function ${componentName}(props, ref) {
25 | return {
26 | $$typeof: Symbol.for('react.element'),
27 | type: 'svg',
28 | ref: ref,
29 | key: null,
30 | props: Object.assign({}, props, {
31 | children: ${assetFilename}
32 | })
33 | };
34 | }),
35 | };`;
36 | }
37 |
38 | return `module.exports = ${assetFilename};`;
39 | },
40 | };
41 |
--------------------------------------------------------------------------------
/src/views/mainContent/userManage/adminList/listDetailInfo/data.js:
--------------------------------------------------------------------------------
1 |
2 | export const detailInfoData = [
3 | {
4 | id: 'baseInfo',
5 | title: '基本信息',
6 | data: [
7 | {
8 | id: 'id',
9 | name: '用户ID',
10 | value: '',
11 | type: 'input',
12 | jpath: 'id',
13 | },
14 | {
15 | id: 'name',
16 | name: '姓名',
17 | value: '',
18 | type: 'input',
19 | jpath: 'name',
20 | },
21 | {
22 | id: 'password',
23 | name: '密码',
24 | value: '',
25 | type: 'input',
26 | jpath: 'password',
27 | },
28 | {
29 | id: 'phone',
30 | name: '手机号',
31 | value: '',
32 | type: 'input',
33 | jpath: 'phone',
34 | },
35 | {
36 | id: 'sex',
37 | name: '性别',
38 | value: '',
39 | type: 'input',
40 | jpath: 'sex.name',
41 | },
42 | {
43 | id: 'userRole',
44 | name: '用户角色',
45 | value: '',
46 | type: 'input',
47 | jpath: 'userRole.name',
48 | },
49 | {
50 | id: 'email',
51 | name: '邮箱',
52 | value: '',
53 | type: 'input',
54 | jpath: 'email',
55 | },
56 | {
57 | id: 'createTime',
58 | name: '创建时间',
59 | value: '',
60 | type: 'input',
61 | jpath: 'createTime',
62 | },
63 | ]
64 | }
65 | ];
66 |
--------------------------------------------------------------------------------
/src/mock/common/index.js:
--------------------------------------------------------------------------------
1 |
2 | import Mock from 'mockjs';
3 | import { formatURL, mockConfig} from '../index'
4 | import * as commonData from '../commonData'
5 | import commonSchema from '../commonSchema'
6 | import { userListBusniess} from "../createMockData";
7 | import { urlFormat} from "@/utils";
8 | import { filterByObj} from '../commonUtils'
9 |
10 | /*获取用户管理员角色数据*/
11 | Mock.mock(formatURL('/common/userAdminRoleList/get'), 'get', {...mockConfig.baseMock, data: {list: commonSchema.adminRoleList}});
12 |
13 | /*获取用户商家角色数据*/
14 | Mock.mock(formatURL('/common/userBussinesRoleList/get'), 'get', {...mockConfig.baseMock, data: {list: commonData.data.userRole}});
15 |
16 | /*获取商店类型数据*/
17 | Mock.mock(formatURL('/common/storeCategoryList/get'), 'get', {...mockConfig.baseMock, data: {list: commonData.data.storeCategory}});
18 |
19 | /*获取商家用户列表id name数据*/
20 | Mock.mock(formatURL('/common/userListBusniess/get'), 'get', function (opts) {
21 | let search = decodeURI(urlFormat(opts.url, 'search'));
22 | let id = urlFormat(opts.url, 'id');
23 | let data = [];
24 | let result = userListBusniess;
25 | if(search && search !== 'undefined'){
26 | result = filterByObj(result, {'name':search}, 'or');
27 | }
28 | if(id){
29 | result = filterByObj(result, {'id':id}, 'or', 'eq');
30 | }
31 | result.forEach(item=>{
32 | data.push({
33 | id: item.id,
34 | name: item.name
35 | })
36 | });
37 | return {...mockConfig.baseMock, data: {list: data}}
38 | });
39 |
40 |
--------------------------------------------------------------------------------
/src/routers/storeManageRouter.js:
--------------------------------------------------------------------------------
1 |
2 | import storeManage from '@/views/mainContent/storeManage'
3 | import storeManageEcharts from '@/views/mainContent/storeManage/echarts'
4 | // import storeManageGrade from '@/views/mainContent/storeManage/grade'
5 |
6 | import storeManageList from '@/views/mainContent/storeManage/list'
7 | import storeManageListNew from '@/views/mainContent/storeManage/list/listNew'
8 | import storeManageListDetail from '@/views/mainContent/storeManage/list/listDetailInfo'
9 |
10 | // import storeManageMemer from '@/views/mainContent/storeManage/member'
11 |
12 | export default {
13 | path: '/storeManage',
14 | component: storeManage,
15 | exact: true,
16 | children: [
17 | {
18 | path: '/storeManage/echarts',
19 | component: storeManageEcharts,
20 | exact: true,
21 | },
22 | {
23 | path: '/storeManage/list',
24 | component: storeManageList,
25 | exact: true,
26 | },
27 | {
28 | path: '/storeManage/list/new',
29 | component: storeManageListNew,
30 | exact: true,
31 | },
32 | {
33 | path: '/storeManage/list/detail',
34 | component: storeManageListDetail,
35 | exact: true,
36 | },
37 | // {
38 | // path: '/storeManage/grade',
39 | // component: storeManageGrade,
40 | // exact: true,
41 | // },
42 | // {
43 | // path: '/storeManage/member',
44 | // component: storeManageMemer,
45 | // exact: true,
46 | // }
47 | ]
48 | }
49 |
--------------------------------------------------------------------------------
/scripts/test.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | // Do this as the first thing so that any code reading it knows the right env.
4 | process.env.BABEL_ENV = 'test';
5 | process.env.NODE_ENV = 'test';
6 | process.env.PUBLIC_URL = '';
7 |
8 | // Makes the script crash on unhandled rejections instead of silently
9 | // ignoring them. In the future, promise rejections that are not handled will
10 | // terminate the Node.js process with a non-zero exit code.
11 | process.on('unhandledRejection', err => {
12 | throw err;
13 | });
14 |
15 | // Ensure environment variables are read.
16 | require('../config/env');
17 |
18 |
19 | const jest = require('jest');
20 | const execSync = require('child_process').execSync;
21 | let argv = process.argv.slice(2);
22 |
23 | function isInGitRepository() {
24 | try {
25 | execSync('git rev-parse --is-inside-work-tree', { stdio: 'ignore' });
26 | return true;
27 | } catch (e) {
28 | return false;
29 | }
30 | }
31 |
32 | function isInMercurialRepository() {
33 | try {
34 | execSync('hg --cwd . root', { stdio: 'ignore' });
35 | return true;
36 | } catch (e) {
37 | return false;
38 | }
39 | }
40 |
41 | // Watch unless on CI or explicitly running all tests
42 | if (
43 | !process.env.CI &&
44 | argv.indexOf('--watchAll') === -1
45 | ) {
46 | // https://github.com/facebook/create-react-app/issues/5210
47 | const hasSourceControl = isInGitRepository() || isInMercurialRepository();
48 | argv.push(hasSourceControl ? '--watch' : '--watchAll');
49 | }
50 |
51 |
52 | jest.run(argv);
53 |
--------------------------------------------------------------------------------
/src/components/CForm/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .c-input, .c-input-number, .c-select, .ant-select, .ant-select-selection, .c-date-picker{
3 | width: 100%;
4 | border-radius: 2px!important;
5 | font-size: 12px!important;
6 | &.ant-input, .ant-input{
7 | border-radius: 2px!important;
8 | font-size: 12px!important;
9 | }
10 | }
11 |
12 | .ant-input-number.c-input-number{
13 | width: 100%;
14 | }
15 |
16 | .ant-input-search{
17 | .ant-input{
18 | border-radius: 2px;
19 | }
20 | }
21 |
22 | .no-show-number-step{
23 | .ant-input-number-handler-wrap{
24 | display: none;
25 | }
26 | }
27 |
28 | .c-select {
29 | min-width: 150px;
30 | }
31 | .ant-select-dropdown{
32 | font-size: 13px;
33 | .ant-select-dropdown-menu{
34 | font-size: 13px;
35 | }
36 | }
37 |
38 | .c-upload{
39 | .ant-upload-text{
40 | font-size: 12px;
41 | }
42 | }
43 |
44 |
45 | .c-form{
46 | .ant-form label{
47 | font-size: 13px;
48 | }
49 | .c-form-content{
50 | justify-content: start;
51 | .c-form-label{
52 | width: 120px;
53 | text-align: right;
54 | margin-right: 10px;
55 | font-size: 12px;
56 | .required-icon{
57 | color: red;
58 | }
59 | }
60 | .c-form-content-form{
61 | flex: 1;
62 | }
63 | }
64 | .c-form-error-info{
65 | height: 15px;
66 | color: red;
67 | padding-left: 130px;
68 | font-size: 12px;
69 | }
70 | .c-form-none-label{
71 | padding-left: 0;
72 | }
73 | .c-form-item{
74 | margin-bottom: 0;
75 | }
76 | }
77 |
78 |
79 |
80 |
--------------------------------------------------------------------------------
/src/mock/storeManage/schema.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs'
2 | import * as commonData from '../commonData'
3 | import userList from '../userManage/schema'
4 | import {randomDate} from "@/utils";
5 | import {randomLongLat} from "../commonUtils";
6 |
7 | // const Random = Mock.Random;
8 |
9 | /*店铺列表数据*/
10 | const storeList = {
11 | 'list|30-150': [
12 | {
13 | 'id|+1': 1,//店铺id
14 | 'user|1': userList.userListBusniess,//商家id
15 | 'storeName': '@ctitle',//店铺名称
16 | 'description': '@cparagraph',//店铺描述
17 | 'address': '@COUNTY(true)',//店铺地址
18 | 'category|1': commonData.data.storeCategory,//店铺所属分类
19 | 'organizationCode': /[A-Z0-9]{8}-[A-Z0-9]$|[A-Z0-9]{8}-[A-Z0-9]-[0-9]{2}$/,//组织机构代码
20 | 'businessLicenseImg|1': commonData.data.images.businessLicenseImg,//营业执照
21 | 'storeAge|0-500': 0,//店铺年限(按天计)
22 | 'focusNum|100-10000000': 0,//被关注数量(粉丝)
23 | 'avatarImg|1': commonData.data.images.avatar,//店铺头像
24 | 'grade': 1,//店铺等级
25 | 'creditGrade|1': commonData.data.creditGrade,//店铺信誉等级
26 | 'serviceScore|0-9.0-1': 0,//店铺售后评分
27 | 'rate|0-9.0-1': 0,//店铺星级
28 | 'latlong': function () {
29 | return randomLongLat([87.9345703125,118.5644531250], [21.8614987344,42.0329743324]);
30 | },//经纬度
31 | 'createTime': function () {
32 | return randomDate('2017-01-01', new Date())
33 | },//创建时间
34 | // 'createTime': '@datetime',//创建时间
35 | }
36 | ]
37 | };
38 |
39 |
40 | export default {
41 | storeList: Mock.mock(storeList).list
42 | }
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/src/components/CButton/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component} from 'react';
2 | import PropTypes from 'prop-types'
3 | import { Button, Icon} from 'antd'
4 | import './index.scss'
5 |
6 | class CButton extends Component {
7 | constructor(props) {
8 | super(props);
9 | this.clickHandler = this.clickHandler.bind(this);
10 | }
11 |
12 | clickHandler(e){
13 | e.preventDefault();
14 | this.props.onClick && this.props.onClick();
15 | }
16 |
17 | render(){
18 | const {icon, type, size, disabled, className, authId, ...props} = this.props;
19 | const iconRender = icon.includes('fa') ? : ;
20 | return (
21 |
22 |
31 |
32 | )
33 | }
34 | }
35 |
36 | CButton.defaultProps = {
37 | type: 'default',
38 | size: 'default',
39 | icon: '',
40 | disabled: false,
41 | loading: false,
42 | };
43 |
44 | CButton.propTypes = {
45 | type: PropTypes.string,
46 | icon: PropTypes.string,
47 | shape: PropTypes.string,
48 | disabled: PropTypes.bool,
49 | loading: PropTypes.bool,
50 | onClick: PropTypes.func,
51 | authId: PropTypes.string,//权限id
52 | };
53 |
54 | export default CButton
55 |
--------------------------------------------------------------------------------
/src/components/CEcharts/index.js:
--------------------------------------------------------------------------------
1 |
2 | import React, {Component} from 'react'
3 | import { connect} from 'react-redux'
4 | import Echarts from 'echarts'
5 | import './index.scss'
6 |
7 | class CEcharts extends Component{
8 |
9 | constructor(props) {
10 | super(props);
11 | this.initEcharts = this.initEcharts.bind(this);
12 | this.initOptions = this.initOptions.bind(this);
13 | this.resizeHandler = this.resizeHandler.bind(this);
14 | }
15 |
16 | state = {
17 | echarts: null,
18 | options: null
19 | }
20 |
21 | initEcharts(){
22 | let echarts = Echarts.init(this.refs.CEcharts);
23 | this.setState({
24 | echarts: echarts
25 | }, () => this.initOptions(this.props.options));
26 | }
27 |
28 | initOptions(options){
29 | if(this.state.echarts && options){
30 | this.state.echarts.setOption(options)
31 | }
32 | }
33 |
34 | resizeHandler(){
35 | this.state.echarts && this.state.echarts.resize();
36 | }
37 |
38 | componentWillReceiveProps(nextProps) {
39 | this.initOptions(nextProps.options);
40 | this.resizeHandler();
41 | }
42 |
43 |
44 | componentWillMount(){
45 |
46 | }
47 |
48 | componentDidMount(){
49 | this.initEcharts();
50 | }
51 |
52 | render(){
53 | const { height} = this.props;
54 | let style = {};
55 | if(height) style = {height: height};
56 | return (
57 |
58 | )
59 | }
60 | }
61 |
62 |
63 | const mapStateToProps = (state) => {
64 | return {
65 | windowInfo: state.Common.windowInfo,
66 | }
67 | };
68 |
69 | export default connect(mapStateToProps)(CEcharts);
70 |
--------------------------------------------------------------------------------
/src/components/CTable/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .c-table{
3 | .ant-table{
4 | border-radius: 2px;
5 | }
6 | .ant-table-body{
7 | margin: 0!important;
8 | }
9 | .c-table-column{
10 | white-space: nowrap;
11 | overflow: hidden;
12 | font-size: 13px;
13 | }
14 | table thead, .ant-table .ant-table-head{
15 | th{
16 | background-color: #fafafa!important;
17 | font-weight: bold;
18 | color: rgba(0,0,0,0.7);
19 | font-size: 13px;
20 | }
21 | }
22 | }
23 |
24 | //表格头部展示的筛选项样式
25 | .filter-head{
26 | justify-content: start;
27 | margin: 10px 0;
28 | align-items: baseline;
29 | flex-wrap: wrap;
30 | .filter-label{
31 | justify-content: start;
32 | width: 80px;
33 | i{
34 | font-size: 13px;
35 | }
36 | span{
37 | margin-left: 5px;
38 | font-size: 13px;
39 | }
40 | }
41 | .filter-content{
42 | justify-content: start;
43 | flex-wrap: wrap;
44 | flex: 1;
45 | .filter-head-item{
46 | margin: 5px 0;
47 | margin-right: 20px;
48 | .label{
49 | font-size: 12px;
50 | font-weight: bold;
51 | }
52 | .filter-tag{
53 | margin-left: 5px;
54 | }
55 | }
56 | }
57 | }
58 |
59 | //表格下拉的筛选项样式
60 | .table-filter-dropdown-list{
61 | font-size: 12px;
62 | border-radius: 2px;
63 | .table-filter-item{
64 | cursor: pointer;
65 | span{
66 | font-size: 12px;
67 | }
68 | &:hover{
69 | background-color: rgba(30, 159, 255, 0.2);
70 | }
71 | }
72 |
73 | .table-filter-dropdown-footer{
74 | width: 100%;
75 | justify-content: flex-end;
76 | &>*{
77 | margin-left: 3px;
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/src/views/mainContent/authManage/roleList/data.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | export const tableData = {
4 | tHead: [
5 | {
6 | key: 'id',
7 | title: 'id',
8 | dataIndex: 'id',
9 | },
10 | {
11 | key: 'uid',
12 | title: 'uid',
13 | dataIndex: 'uid',
14 | },
15 | {
16 | key: 'name',
17 | dataIndex: 'name',
18 | title: '角色',
19 | },
20 | {
21 | key: 'createTime',
22 | dataIndex: 'createTime',
23 | title: '创建时间',
24 | },
25 | {
26 | key: 'operate',
27 | dataIndex: 'operate',
28 | title: '操作',
29 | width: 100,
30 | slot: 'operate',
31 | },
32 | ],
33 | tBody: [],
34 | tPage: {
35 | total: 0,
36 | page: 1,
37 | pageSize: 10
38 | }
39 | };
40 |
41 |
42 | export const authManageRoleListNewData = [
43 | {
44 | id: 'baseInfo',
45 | title: '',
46 | data: [
47 | {
48 | id: 'uid',
49 | name: 'uid',
50 | placeholder: '请输入uid',
51 | type: 'input',
52 | checkType: 'required',
53 | newDisabled: false,
54 | editDisabled: false,
55 | newShow: true,
56 | editShow: true,
57 | value: '',
58 | options: [],
59 | expand: {},
60 | jpath: 'uid'
61 | },
62 | {
63 | id: 'name',
64 | name: '角色名',
65 | placeholder: '请输入角色名',
66 | type: 'input',
67 | checkType: 'required',
68 | newDisabled: false,
69 | editDisabled: false,
70 | newShow: true,
71 | editShow: true,
72 | value: '',
73 | options: [],
74 | expand: {},
75 | jpath: 'name'
76 | },
77 | ]
78 | }
79 | ];
80 |
--------------------------------------------------------------------------------
/src/views/header/index.scss:
--------------------------------------------------------------------------------
1 | @import "@/assets/css/var.scss";
2 | @import "@/assets/css/themeFn.scss";
3 |
4 | .header{
5 | height: $header-height;
6 | background: $header-background;
7 | @include themify(){
8 | background: themed('header-background-color');
9 | }
10 | .logo{
11 | width: 200px;
12 | font-size: 18px;
13 | padding: 0 20px;
14 | }
15 | .info{
16 | padding-right: 20px;
17 | flex: 1;
18 | justify-content: space-between;
19 | .collapsed{
20 | background-color: rgba(255,255,255,0.1);
21 | padding: 8px;
22 | border-radius: 2px;
23 | cursor: pointer;
24 | &:hover{
25 | background-color: rgba(255,255,255,0.3);
26 | }
27 | i{
28 | font-size: 16px;
29 | }
30 | }
31 |
32 | .info-right{
33 | justify-content: flex-end;
34 | .theme-config{
35 | margin-right: 20px;
36 | .theme-config-name{
37 | font-size: 12px;
38 | margin-right: 10px;
39 | }
40 | .themeItem{
41 | .themeItemColor{
42 | width: 20px;
43 | height: 20px;
44 | border-radius: 2px;
45 | margin: 0 5px;
46 | }
47 | }
48 | }
49 |
50 | .user-info{
51 | color: $text-color-white;
52 | .user-name{
53 | margin-right: 8px;
54 | }
55 | .user-avatar{
56 | width: 30px;
57 | height: 30px;
58 | border-radius: 50%;
59 | margin-right: 5px;
60 | }
61 | }
62 |
63 | .ant-dropdown-trigger{
64 | display: inline-block;
65 | height: $header-height;
66 | line-height: $header-height;
67 | }
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/views/mainContent/userManage/adminList/listDetailInfo/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import CDetailInfo from '@/components/CDetailInfo'
3 | import CAvatar from '@/components/CAvatar'
4 | import CBaseComponent from '@/components/CBaseComponent'
5 | import { detailInfoData} from "./data";
6 | import { detailUserAdminList} from "@/servers/userManageApi";
7 | import { urlFormat, setPageNewValue} from "@/utils";
8 |
9 | @CBaseComponent
10 | class UserManageAdminListDetailInfo extends Component{
11 |
12 | constructor(props) {
13 | super(props);
14 | this.getUserDetailData = this.getUserDetailData.bind(this);
15 | }
16 |
17 |
18 | state = {
19 | data: detailInfoData,
20 | avatar: {
21 | img: '',
22 | title: '',
23 | description: ''
24 | }
25 | };
26 |
27 | getUserDetailData(){
28 | let id = urlFormat(this.props.history.location.search).query.id;
29 | detailUserAdminList({id}).then(res=>{
30 | let userInfo = res.data.userInfo;
31 | let data = setPageNewValue(detailInfoData, userInfo);
32 | this.setState({
33 | data: data,
34 | avatar: {
35 | img: userInfo.avatar && userInfo.avatar.url,
36 | title: userInfo.name,
37 | description: ''
38 | }
39 | })
40 | }).catch(err=>{
41 |
42 | })
43 | }
44 |
45 | componentDidMount(){
46 | this.getUserDetailData();
47 | }
48 |
49 | render(){
50 | return (
51 | <>
52 |
53 |
54 | >
55 |
56 | )
57 | }
58 | }
59 |
60 | export default UserManageAdminListDetailInfo
61 |
--------------------------------------------------------------------------------
/src/mock/authManage/roleList.js:
--------------------------------------------------------------------------------
1 |
2 | import { mockConfig} from '../index'
3 | // import _ from 'lodash'
4 | import commonSchema from '../commonSchema'
5 | import { filterByObj, deleteDataByKeys} from "../commonUtils";
6 | import { formatDate} from "@/utils";
7 |
8 | /*系统角色列表*/
9 | let adminRoleListData = commonSchema.adminRoleList.reverse();
10 |
11 | /*获取角色列表在commmonApi中*/
12 |
13 | /*删除角色*/
14 | export const deleteAuthManageRole = (opts) => {
15 | // 获取参数
16 | let id = JSON.parse(opts.body).id;
17 |
18 | let delArray = deleteDataByKeys(adminRoleListData, 'id', id);
19 |
20 | let errmsg = '';
21 | if(delArray.length !== id.length){
22 | errmsg = '删除失败';
23 | mockConfig.baseMock.code = 10001;
24 | }
25 |
26 | return {...mockConfig.baseMock, errmsg}
27 | };
28 |
29 | /*添加角色*/
30 | export const insertAuthManageRole = (opts) => {
31 | // 获取参数
32 | let roleInfo = JSON.parse(opts.body);
33 | let popRoleInfo = adminRoleListData[0];//第一项
34 | let id = Number(popRoleInfo.id) + 1;//取第一项的id+1为新项id
35 | roleInfo.id = id;
36 | roleInfo.createTime = formatDate();
37 | adminRoleListData.unshift(roleInfo);
38 |
39 | return {...mockConfig.baseMock, ...{data: {id}}}
40 | };
41 |
42 | /*编辑角色*/
43 | export const editStoreManage = (opts) => {
44 | // 获取参数
45 | let editRoleInfo = JSON.parse(opts.body);
46 | let {id, ...editPropsRoleInfo} = editRoleInfo;//获取角色id及其他信息
47 | let roleInfo = filterByObj(adminRoleListData, {id: id}, 'or', 'eq')[0];
48 | let newRoleInfo = Object.assign({}, roleInfo, editPropsRoleInfo);
49 |
50 | let index = adminRoleListData.findIndex(item=>{
51 | return item.id.toString() === id.toString()
52 | });
53 |
54 | adminRoleListData.splice(index, 1, newRoleInfo);
55 |
56 | return {...mockConfig.baseMock}
57 | };
58 |
--------------------------------------------------------------------------------
/src/views/mainContent/goodsManage/goodsList/listDetailInfo/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import CDetailInfo from '@/components/CDetailInfo'
3 | import CBaseComponent from '@/components/CBaseComponent'
4 | import CAvatar from '@/components/CAvatar'
5 | import {detailInfoData} from "./data";
6 | import {detailGoodsList} from "@/servers/goodsManageApi";
7 | import {urlFormat, setPageNewValue} from "@/utils";
8 |
9 | @CBaseComponent
10 | class StoreManageListDetailInfo extends Component {
11 |
12 | constructor(props) {
13 | super(props);
14 | this.getStoreDetailData = this.getStoreDetailData.bind(this);
15 | }
16 |
17 |
18 | state = {
19 | data: detailInfoData,
20 | avatar: {
21 | img: '',
22 | title: '',
23 | description: '',
24 | }
25 | };
26 |
27 | getStoreDetailData() {
28 | let id = urlFormat(this.props.history.location.search).query.id;
29 | detailGoodsList({id}).then(res => {
30 | let goodsInfo = res.data.goodsInfo;
31 | let data = setPageNewValue(detailInfoData, goodsInfo);
32 | this.setState({
33 | data: data,
34 | avatar: {
35 | img: goodsInfo.avatarImg && goodsInfo.avatarImg.url,
36 | title: goodsInfo.name,
37 | description: goodsInfo.description,
38 | }
39 | })
40 | }).catch(err => {
41 |
42 | })
43 | }
44 |
45 | render() {
46 | return (
47 | <>
48 |
50 |
51 | >
52 | )
53 | }
54 |
55 | componentDidMount() {
56 | this.getStoreDetailData();
57 | }
58 | }
59 |
60 | export default StoreManageListDetailInfo
61 |
--------------------------------------------------------------------------------
/src/components/CDetailInfo/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react'
2 | import PropTypes from 'prop-types'
3 | import _ from 'lodash'
4 | import CDetailInfoTitle from './detailInfoTitle'
5 | import CDetailInfoItem from './detailInfoItem'
6 | import './index.scss'
7 |
8 | class CDetailInfo extends Component{
9 |
10 | componentWillMount(){
11 |
12 | }
13 |
14 | render(){
15 | console.log(this.props.children,'this.props.children')
16 | return (
17 |
18 | {
19 | this.props.data && !!this.props.data.length && this.props.data.map((baseItem, baseIndex) => {
20 | return
21 | {
22 | baseItem.title &&
23 | }
24 | {
25 | !!baseItem.data.length && !baseItem.slot &&
26 | }
27 | {/*如果children是数组则循环判断用到的是哪一个children*/}
28 | {
29 | !!baseItem.data.length && baseItem.slot && _.isArray(this.props.children) && this.props.children.map((slotItem, slotIndex) => {
30 | return slotItem.props.slot === baseItem.slot && slotItem
31 | })
32 | }
33 | {/*如果children是对象并且children的props.slot为data中定义的slot则展示*/}
34 | {
35 | baseItem.slot && !_.isArray(this.props.children) && this.props.children.props.slot === baseItem.slot && this.props.children
36 | }
37 |
38 | })
39 | }
40 |
41 | )
42 | }
43 | }
44 |
45 | CDetailInfo.defaultProps = {
46 | data: []
47 | };
48 |
49 | CDetailInfo.propTypes = {
50 | data: PropTypes.array,
51 | };
52 |
53 | export default CDetailInfo
54 |
--------------------------------------------------------------------------------
/src/views/mainContent/goodsManage/goodsList/data.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | export const tableData = {
4 | tHead: [
5 | {
6 | key: 'id',
7 | title: 'id',
8 | dataIndex: 'id',
9 | },
10 | {
11 | key: 'name',
12 | dataIndex: 'name',
13 | title: '商品名称',
14 | },
15 | {
16 | key: 'storeInfo',
17 | dataIndex: 'storeInfo.storeName',
18 | title: '所属店铺',
19 | },
20 | {
21 | key: 'category',
22 | dataIndex: 'category',
23 | title: '所属分类',
24 | },
25 | {
26 | key: 'price',
27 | dataIndex: 'price',
28 | title: '价格(元)',
29 | },
30 | {
31 | key: 'stockNum',
32 | dataIndex: 'stockNum',
33 | title: '库存(件)',
34 | },
35 | {
36 | key: 'tradingTotalNum',
37 | dataIndex: 'tradingTotalNum',
38 | title: '总交易数量(件)',
39 | },
40 | {
41 | key: 'tradingMonthNum',
42 | dataIndex: 'tradingMonthNum',
43 | title: '月交易数量(件)',
44 | },
45 | {
46 | key: 'tradingDayNum',
47 | dataIndex: 'tradingDayNum',
48 | title: '日交易数量(件)',
49 | },
50 | {
51 | key: 'commitGoodRate',
52 | dataIndex: 'commitGoodRate',
53 | title: '好评率(%)',
54 | },
55 | {
56 | key: 'createTime',
57 | dataIndex: 'createTime',
58 | title: '创建时间',
59 | filterMultiple: true,
60 | filterDate: 'range',
61 | },
62 | {
63 | key: 'status',
64 | dataIndex: 'status',
65 | title: '上下架',
66 | fixed: 'right',
67 | slot: 'status',
68 | },
69 | {
70 | key: 'operate',
71 | dataIndex: 'operate',
72 | title: '操作',
73 | fixed: 'right',
74 | width: 100,
75 | slot: 'operate',
76 | },
77 | ],
78 | tBody: [],
79 | tPage: {
80 | total: 0,
81 | page: 1,
82 | pageSize: 10
83 | }
84 | };
85 |
--------------------------------------------------------------------------------
/src/views/login/index.scss:
--------------------------------------------------------------------------------
1 |
2 | .login{
3 | height: 100%;
4 | min-height: 500px;
5 | background: url("../../assets/images/login-bg.jpg") no-repeat;
6 | background-size: cover;
7 | display: flex;
8 | flex-direction: column;
9 | .login-header{
10 | justify-content: space-between;
11 | padding: 20px 50px;
12 | .login-header-logo{
13 | color: #ffffff;
14 | font-size: 26px;
15 | }
16 | .login-header-href{
17 | a:hover{
18 | color: #dddddd;
19 | }
20 | }
21 | a{
22 | color: #ffffff;
23 | }
24 | }
25 | .login-content{
26 | padding: 20px 50px;
27 | justify-content: flex-end;
28 | flex: 1;
29 | .login-form{
30 | width: 400px;
31 | overflow: hidden;
32 | transform: translateY(-30%);
33 | border-radius: 2px;
34 | .login-form-title{
35 | width: 100%;
36 | padding: 20px;
37 | justify-content: space-between;
38 | color: #ffffff;
39 | background: rgba(0,0,0,0.4);
40 | color: rgba(255,255,255,0.8);
41 | i{
42 | font-size: 24px;
43 | color: rgba(255,255,255,0.3);
44 | }
45 | }
46 | .login-form-content{
47 | width: 100%;
48 | padding: 20px;
49 | background: rgba(0,0,0,0.3);
50 | &>*{
51 | margin: 10px 0;
52 | }
53 | input{
54 | background-color: rgba(255, 255, 255, 0.2);
55 | border: none;
56 | color: rgba(255,255,255,0.8);
57 | &::-webkit-input-placeholder{
58 | color: rgba(255,255,255,0.8);
59 | }
60 | }
61 | .ant-input-suffix{
62 | i{
63 | color: #cccccc;
64 | }
65 | }
66 | }
67 |
68 | .login-button{
69 | width: 100%;
70 | font-size: 12px;
71 | }
72 | }
73 | }
74 | }
75 |
--------------------------------------------------------------------------------
/src/views/mainContent/storeManage/list/listDetailInfo/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import CDetailInfo from '@/components/CDetailInfo'
3 | import CBaseComponent from '@/components/CBaseComponent'
4 | import CAvatar from '@/components/CAvatar'
5 | import {detailInfoData} from "./data";
6 | import {detailStoreList} from "@/servers/storeManageApi";
7 | import {urlFormat, setPageNewValue} from "@/utils";
8 |
9 | @CBaseComponent
10 | class StoreManageListDetailInfo extends Component {
11 | constructor(props) {
12 | super(props);
13 | this.getStoreDetailData = this.getStoreDetailData.bind(this);
14 | }
15 |
16 |
17 | state = {
18 | data: detailInfoData,
19 | avatar: {
20 | img: '',
21 | title: '',
22 | description: '',
23 | rate: 0
24 | }
25 | };
26 |
27 | getStoreDetailData() {
28 | let id = urlFormat(this.props.history.location.search).query.id;
29 | detailStoreList({id}).then(res => {
30 | let userInfo = res.data.userInfo;
31 | let data = setPageNewValue(detailInfoData, userInfo);
32 | this.setState({
33 | data: data,
34 | avatar: {
35 | img: userInfo.avatarImg && userInfo.avatarImg.url,
36 | title: userInfo.storeName,
37 | description: userInfo.description,
38 | rate: userInfo.rate
39 | }
40 | })
41 | }).catch(err => {
42 |
43 | })
44 | }
45 |
46 | render() {
47 | return (
48 | <>
49 |
51 |
52 | >
53 | )
54 | }
55 |
56 | componentDidMount() {
57 | this.getStoreDetailData();
58 | }
59 | }
60 |
61 | export default StoreManageListDetailInfo
62 |
--------------------------------------------------------------------------------
/src/views/mainContent/storeManage/list/data.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | export const tableData = {
4 | tHead: [
5 | {
6 | key: 'id',
7 | title: 'id',
8 | dataIndex: 'id',
9 | },
10 | {
11 | key: 'storeName',
12 | dataIndex: 'storeName',
13 | title: '店铺名称',
14 | /*filterMultiple: true,
15 | filters: [
16 | {
17 | value: '1',
18 | text: '用户类型1'
19 | },
20 | {
21 | value: '2',
22 | text: '用户类型2'
23 | },
24 | {
25 | value: '3',
26 | text: '用户类型3'
27 | }
28 | ]*/
29 | },
30 | {
31 | key: 'storeAge',
32 | dataIndex: 'storeAge',
33 | title: '店铺年限(天)',
34 | },
35 | {
36 | key: 'name',
37 | dataIndex: 'user.name',
38 | title: '所属用户',
39 | },
40 | {
41 | key: 'role',
42 | dataIndex: 'user.userRole.name',
43 | title: '用户角色',
44 | },
45 | {
46 | key: 'address',
47 | dataIndex: 'address',
48 | title: '地址',
49 | },
50 | {
51 | key: 'category',
52 | dataIndex: 'category.name',
53 | title: '店铺分类',
54 | filterMultiple: false,
55 | },
56 | {
57 | key: 'focusNum',
58 | dataIndex: 'focusNum',
59 | title: '关注量',
60 | },
61 | {
62 | key: 'creditGrade',
63 | dataIndex: 'creditGrade.name',
64 | title: '信誉等级',
65 | },
66 | {
67 | key: 'createTime',
68 | dataIndex: 'createTime',
69 | title: '创建时间',
70 | filterMultiple: true,
71 | filterDate: 'range',
72 | },
73 | {
74 | key: 'operate',
75 | dataIndex: 'operate',
76 | title: '操作',
77 | fixed: 'right',
78 | width: 100,
79 | slot: 'operate',
80 | },
81 | ],
82 | tBody: [],
83 | tPage: {
84 | total: 0,
85 | page: 1,
86 | pageSize: 10
87 | }
88 | };
89 |
--------------------------------------------------------------------------------
/src/views/mainContent/historyRecord/deleteUserList/data.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | export const tableData = {
4 | tHead: [
5 | {
6 | key: 'id',
7 | title: 'id',
8 | dataIndex: 'id',
9 | },
10 | {
11 | key: 'name',
12 | dataIndex: 'name',
13 | title: '姓名',
14 | /*filterMultiple: true,
15 | filters: [
16 | {
17 | value: '1',
18 | text: '用户类型1'
19 | },
20 | {
21 | value: '2',
22 | text: '用户类型2'
23 | },
24 | {
25 | value: '3',
26 | text: '用户类型3'
27 | }
28 | ]*/
29 | },
30 | {
31 | key: 'deleteReason',
32 | dataIndex: 'deleteReason',
33 | title: '删除原因',
34 | width: 100,
35 | },
36 | {
37 | key: 'email',
38 | dataIndex: 'email',
39 | title: '邮箱',
40 | },
41 | {
42 | key: 'address',
43 | dataIndex: 'address',
44 | title: '住址',
45 | },
46 | {
47 | key: 'phone',
48 | dataIndex: 'phone',
49 | title: '联系电话',
50 | },
51 | {
52 | key: 'IDCard',
53 | dataIndex: 'IDCard',
54 | title: '身份证号码',
55 | },
56 | {
57 | key: 'userRole',
58 | dataIndex: 'userRole.name',
59 | title: '角色',
60 | filterMultiple: false,
61 | filters: []
62 | },
63 | {
64 | key: 'createTime',
65 | dataIndex: 'createTime',
66 | title: '创建时间',
67 | filterMultiple: true,
68 | filterDate: 'range',
69 | },
70 | {
71 | key: 'deleteTime',
72 | dataIndex: 'deleteTime',
73 | title: '删除时间',
74 | },
75 | {
76 | key: 'operate',
77 | dataIndex: 'operate',
78 | title: '操作',
79 | fixed: 'right',
80 | width: 100,
81 | slot: 'operate',
82 | },
83 | ],
84 | tBody: [],
85 | tPage: {
86 | total: 0,
87 | page: 1,
88 | pageSize: 10
89 | }
90 | };
91 |
--------------------------------------------------------------------------------
/src/views/mainContent/userManage/list/data.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | export const tableData = {
4 | tHead: [
5 | {
6 | key: 'id',
7 | title: 'id',
8 | dataIndex: 'id',
9 | },
10 | {
11 | key: 'name',
12 | dataIndex: 'name',
13 | title: '姓名',
14 | /*filterMultiple: true,
15 | filters: [
16 | {
17 | value: '1',
18 | text: '用户类型1'
19 | },
20 | {
21 | value: '2',
22 | text: '用户类型2'
23 | },
24 | {
25 | value: '3',
26 | text: '用户类型3'
27 | }
28 | ]*/
29 | },
30 | {
31 | key: 'password',
32 | dataIndex: 'password',
33 | title: '密码',
34 | },
35 | {
36 | key: 'email',
37 | dataIndex: 'email',
38 | title: '邮箱',
39 | },
40 | {
41 | key: 'address',
42 | dataIndex: 'address',
43 | title: '住址',
44 | },
45 | {
46 | key: 'phone',
47 | dataIndex: 'phone',
48 | title: '联系电话',
49 | },
50 | {
51 | key: 'IDCard',
52 | dataIndex: 'IDCard',
53 | title: '身份证号码',
54 | },
55 | {
56 | key: 'userRole',
57 | dataIndex: 'userRole.name',
58 | title: '角色',
59 | filterMultiple: false,
60 | filters: []
61 | },
62 | {
63 | key: 'createTime',
64 | dataIndex: 'createTime',
65 | title: '创建时间',
66 | filterMultiple: true,
67 | filterDate: 'range',
68 | },
69 | {
70 | key: 'isActive',
71 | dataIndex: 'isActive',
72 | title: '激活停用',
73 | fixed: 'right',
74 | slot: 'isActive',
75 | },
76 | {
77 | key: 'operate',
78 | dataIndex: 'operate',
79 | title: '操作',
80 | fixed: 'right',
81 | width: 100,
82 | slot: 'operate',
83 | },
84 | ],
85 | tBody: [],
86 | tPage: {
87 | total: 0,
88 | page: 1,
89 | pageSize: 10
90 | }
91 | };
92 |
--------------------------------------------------------------------------------
/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
22 |
23 | React App
24 |
25 |
26 |
27 |
28 |
29 |
39 |
40 |
41 |
--------------------------------------------------------------------------------
/src/views/mainContent/storeManage/list/listDetailInfo/data.js:
--------------------------------------------------------------------------------
1 |
2 | export const detailInfoData = [
3 | {
4 | id: 'baseInfo',
5 | title: '基本信息',
6 | data: [
7 | {
8 | id: 'id',
9 | name: '店铺ID',
10 | value: '',
11 | type: 'input',
12 | jpath: 'id',
13 | },
14 | {
15 | id: 'storeName',
16 | name: '店铺名称',
17 | value: '',
18 | type: 'input',
19 | jpath: 'storeName',
20 | },
21 | {
22 | id: 'storeAge',
23 | name: '店铺年限(天)',
24 | value: '',
25 | type: 'input',
26 | jpath: 'storeAge',
27 | },
28 | {
29 | id: 'user',
30 | name: '所属商家',
31 | value: '',
32 | type: 'input',
33 | jpath: 'user.name',
34 | },
35 | {
36 | id: 'organizationCode',
37 | name: '组织机构代码',
38 | value: '',
39 | type: 'input',
40 | jpath: 'organizationCode',
41 | },
42 | {
43 | id: 'address',
44 | name: '店铺地址',
45 | value: '',
46 | type: 'input',
47 | jpath: 'address',
48 | },
49 | {
50 | id: 'category',
51 | name: '店铺分类',
52 | value: '',
53 | type: 'input',
54 | jpath: 'category.name',
55 | },
56 | {
57 | id: 'focusNum',
58 | name: '关注量',
59 | value: '',
60 | type: 'input',
61 | jpath: 'focusNum',
62 | },
63 | {
64 | id: 'creditGrade',
65 | name: '荣誉等级',
66 | value: '',
67 | type: 'input',
68 | jpath: 'creditGrade.name',
69 | },
70 | {
71 | id: 'createTime',
72 | name: '创建时间',
73 | value: '',
74 | type: 'input',
75 | jpath: 'createTime',
76 | },
77 | {
78 | id: 'businessLicenseImg',
79 | name: '营业执照',
80 | value: [],
81 | type: 'img',
82 | jpath: 'businessLicenseImg',
83 | },
84 | ]
85 | }
86 | ];
87 |
--------------------------------------------------------------------------------
/src/components/CDetailInfo/index.scss:
--------------------------------------------------------------------------------
1 | @import "@/assets/css/var.scss";
2 |
3 | .c-detail-info{
4 | .c-detail-info-base-item{
5 | margin-bottom: 20px;
6 | }
7 | }
8 |
9 |
10 | .c-detail-info-title{
11 | justify-content: space-between;
12 | .c-detail-info-title-left{
13 | justify-content: start;
14 | font-weight: bold;
15 | font-size: 13px;
16 | height: 40px;
17 | line-height: 40px;
18 | margin-bottom: 10px;
19 | .title-before-icon{
20 | display: inline-block;
21 | width: 4px;
22 | height: 15px;
23 | background: $main-base-primary-color;
24 | border-radius: 2px;
25 | margin-right: 5px;
26 | }
27 | }
28 | .c-detail-info-title-right{
29 |
30 | }
31 | }
32 |
33 |
34 | //c-detail-info-item
35 | .c-detail-info-item{
36 | justify-content: space-between;
37 | align-items: start;
38 | padding: 10px 20px;
39 | .info-col{
40 | width: 47%;
41 | .info-row{
42 | justify-content: start;
43 | .info-row-label{
44 | border: 1px solid #ebedf0;
45 | border-bottom: none;
46 | border-right: none;
47 | width: 100px;
48 | height: 35px;
49 | line-height: 35px;
50 | padding: 0 8px;
51 | font-size: 13px;
52 | font-weight: bold;
53 | }
54 | .info-row-content{
55 | border: 1px solid #ebedf0;
56 | border-bottom: none;
57 | width: calc(100% - 100px);
58 | height: 35px;
59 | line-height: 35px;
60 | padding: 0 8px;
61 | font-size: 13px;
62 | .none-value{
63 | color: #999999;
64 | }
65 | }
66 | &:nth-last-of-type(1){
67 | .info-row-label, .info-row-content{
68 | border-bottom: 1px solid #ebedf0;
69 | }
70 | }
71 | .img-look{
72 | color: $main-base-primary-color;
73 | cursor: pointer;
74 | }
75 | }
76 | }
77 | .info-col-one{
78 |
79 | }
80 | .info-col-two{
81 |
82 | }
83 | .info-col-null{
84 | width: 6%;
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/src/components/CForm/CSelect.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react'
2 | import PropTypes from 'prop-types'
3 | import { Select, TreeSelect} from 'antd'
4 | import './index.scss'
5 | const { Option} = Select
6 |
7 | class CSelect extends Component{
8 |
9 | state = {
10 | value: undefined
11 | };
12 |
13 | changeHandler(value){
14 | this.setState({
15 | value: value
16 | });
17 | this.props.onChange && this.props.onChange(value);
18 | }
19 |
20 | searchHandler(value){
21 | this.props.onSearch && this.props.onSearch(value);
22 | }
23 |
24 | componentWillReceiveProps(nextProps) {
25 | let defaultValue = !nextProps.value ? undefined : nextProps.value;
26 | this.setState({
27 | value: defaultValue
28 | })
29 | }
30 |
31 | componentWillMount(){
32 | let defaultValue = !this.props.value ? undefined : this.props.value;
33 | this.setState({
34 | value: this.props.value || defaultValue
35 | })
36 | }
37 |
38 | render(){
39 | const {type, options, style, onSearch, onChange, ...props} = this.props;
40 | const SelectDom = type === 'treeSelect' ? TreeSelect : Select;
41 | return (
42 | this.searchHandler(value)}
47 | onChange={(value) => this.changeHandler(value)}>
48 | {
49 | type === 'select' && options.map((item, index)=>{
50 | return
51 | })
52 | }
53 |
54 | )
55 | }
56 | }
57 |
58 | CSelect.defaultProps = {
59 | type: 'select',
60 | options: [],
61 | style: {},
62 | };
63 |
64 | CSelect.propTypes = {
65 | type: PropTypes.string,
66 | options: PropTypes.array,
67 | onChange: PropTypes.func,
68 | onSearch: PropTypes.func,
69 | style: PropTypes.object,
70 | };
71 |
72 | export default CSelect
73 |
--------------------------------------------------------------------------------
/src/components/CForm/CDatePicker.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react'
2 | import PropTypes from 'prop-types'
3 | import _ from 'lodash'
4 | import { DatePicker} from 'antd'
5 | import moment from 'moment'
6 | import locale from 'antd/lib/date-picker/locale/zh_CN'
7 | import './index.scss'
8 |
9 | class CDatePicker extends Component{
10 |
11 | constructor(props) {
12 | super(props);
13 | this.changeHandler = this.changeHandler.bind(this);
14 | this.valueFormat = this.valueFormat.bind(this);
15 | }
16 |
17 |
18 | state = {
19 | value: null,
20 | dateType: {
21 | 'mouth': 'MonthPicker',
22 | 'range': 'RangePicker',
23 | 'week': 'WeekPicker '
24 | },
25 | dateFormat: 'YYYY-MM-DD HH:mm:ss'
26 | };
27 |
28 | componentWillReceiveProps(nextProps) {
29 | if(nextProps.hasOwnProperty('value')){
30 | this.valueFormat(nextProps.value);
31 | }
32 | }
33 |
34 | valueFormat(value){
35 | if(_.isString(value)){
36 | value = value ? moment(value, this.state.dateFormat) : null;
37 | }
38 | if(_.isArray(value)){
39 | value = value.length ? [moment(value[0], this.state.dateFormat),moment(value[1], this.state.dateFormat)] : null;
40 | }
41 | this.setState({
42 | value: value
43 | })
44 | }
45 |
46 | changeHandler(date, dateString){
47 | this.valueFormat(dateString);
48 | this.props.onChange && this.props.onChange(dateString);
49 | }
50 |
51 | componentWillMount(){
52 | this.valueFormat(this.props.value);
53 | }
54 |
55 | render(){
56 | const {type, value, onChange, className, ...props} = this.props;
57 | const DatePickerDom = this.state.dateType[type] ? DatePicker[this.state.dateType[type]] : DatePicker;
58 | return (
59 | this.changeHandler(date, dateString)}/>
60 | )
61 | }
62 | }
63 |
64 | CDatePicker.propTypes = {
65 | onChange: PropTypes.func,
66 | };
67 |
68 | export default CDatePicker
69 |
--------------------------------------------------------------------------------
/src/routers/userManageRouter.js:
--------------------------------------------------------------------------------
1 |
2 | import userManage from '@/views/mainContent/userManage'
3 | import userManageEcharts from '@/views/mainContent/userManage/echarts'
4 | import userManageGrade from '@/views/mainContent/userManage/grade'
5 |
6 | import userManageList from '@/views/mainContent/userManage/list'
7 | import userManageListNew from '@/views/mainContent/userManage/list/listNew'
8 | import userManageListDetail from '@/views/mainContent/userManage/list/listDetailInfo'
9 |
10 | import userManageAdminList from '@/views/mainContent/userManage/adminList'
11 | import userManageAdminListNew from '@/views/mainContent/userManage/adminList/listNew'
12 | import userManageAdminListDetail from '@/views/mainContent/userManage/adminList/listDetailInfo'
13 |
14 | import userManageMemer from '@/views/mainContent/userManage/member'
15 |
16 | export default {
17 | path: '/userManage',
18 | component: userManage,
19 | exact: true,
20 | children: [
21 | {
22 | path: '/userManage/echarts',
23 | component: userManageEcharts,
24 | exact: true,
25 | },
26 | {
27 | path: '/userManage/list',
28 | component: userManageList,
29 | exact: true,
30 | },
31 | {
32 | path: '/userManage/list/new',
33 | component: userManageListNew,
34 | exact: true,
35 | },
36 | {
37 | path: '/userManage/list/detail',
38 | component: userManageListDetail,
39 | exact: true,
40 | },
41 | {
42 | path: '/userManage/admin',
43 | component: userManageAdminList,
44 | exact: true,
45 | },
46 | {
47 | path: '/userManage/admin/new',
48 | component: userManageAdminListNew,
49 | exact: true,
50 | },
51 | {
52 | path: '/userManage/admin/detail',
53 | component: userManageAdminListDetail,
54 | exact: true,
55 | },
56 | {
57 | path: '/userManage/grade',
58 | component: userManageGrade,
59 | exact: true,
60 | },
61 | {
62 | path: '/userManage/member',
63 | component: userManageMemer,
64 | exact: true,
65 | }
66 | ]
67 | }
68 |
--------------------------------------------------------------------------------
/src/views/mainContent/personal/percentageEcharts.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import CEcharts from '@/components/CEcharts'
3 | import InfoTitle from '@/components/CDetailInfo/detailInfoTitle'
4 | import CBaseComponent from '@/components/CBaseComponent'
5 | // import Echarts from 'echarts'
6 | // import _ from 'lodash'
7 |
8 | @CBaseComponent
9 | class PercentageEcharts extends Component{
10 | constructor(props) {
11 | super(props);
12 | this.initOptions = this.initOptions.bind(this);
13 | }
14 |
15 | state = {
16 | options: {
17 | backgroundColor: '#1b2735',
18 | title: {
19 | text: 'CPU使用率',
20 | textStyle: {
21 | fontWeight: 'normal',
22 | fontSize: 25,
23 | color: 'rgb(97, 142, 205)'
24 | }
25 | },
26 | series: [{
27 | type: 'liquidFill',
28 | radius: '80%',
29 | data: [0.3, 0.3, 0.3, 0.3, 0.3],
30 | backgroundStyle: {
31 | borderWidth: 5,
32 | borderColor: 'rgb(255,0,255,0.9)',
33 | color: 'rgb(255,0,255,0.01)'
34 | },
35 | label: {
36 | normal: {
37 | formatter: (0.3 * 100).toFixed(2) + '%',
38 | textStyle: {
39 | fontSize: 50
40 | }
41 | }
42 | }
43 | }]
44 | }
45 | }
46 |
47 | initOptions(data){
48 | // if(data) {
49 | // let options = _.cloneDeep(this.state.options);
50 | // options.series[0].data = data;
51 | // this.setState({
52 | // options: options
53 | // })
54 | // }
55 | }
56 |
57 | componentWillReceiveProps(nextProps){
58 | // this.initOptions(nextProps.data)
59 | }
60 |
61 | componentDidMount(){
62 | // this.initOptions(this.props.data);
63 | }
64 |
65 | render(){
66 | return (
67 |
68 |
69 | {this.props.children}
70 |
71 |
72 |
73 | )
74 | }
75 | }
76 |
77 | export default PercentageEcharts
78 |
--------------------------------------------------------------------------------
/src/routers/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import { HashRouter, Route, Switch} from 'react-router-dom';
3 |
4 | import App from "@/views/App";
5 | import Login from "@/views/login";
6 | import MainContent from "@/views/mainContent";
7 |
8 |
9 | import homeRouter from './homeRouter'
10 | import userManageRouter from './userManageRouter'
11 | import storeManageRouter from './storeManageRouter'
12 | import authManageRouter from './authManageRouter'
13 | import goodsManageRouter from './goodsManageRouter'
14 | import historyRecordRouter from './historyRecordRouter'
15 | import personalRouter from './personalRouter'
16 |
17 | const routers = [
18 | homeRouter,
19 | userManageRouter,
20 | storeManageRouter,
21 | authManageRouter,
22 | goodsManageRouter,
23 | historyRecordRouter,
24 | personalRouter
25 | ];
26 |
27 | const renderRoutes = (routers) => {
28 | return routers.map((item, index)=>{
29 | if(item.children){
30 | let Com = item.component;
31 | return (
32 |
33 | {renderRoutes(item.children)}
34 |
35 | )
36 | }else{
37 | return (
38 |
39 | )
40 | }
41 | })
42 | };
43 | /*{item.children && renderRoutes(item.children)})*/
44 |
45 |
46 | export default class RouteConfig extends Component{
47 | render(){
48 | return (
49 |
50 |
51 |
52 | {/**/}
53 | {/* */}
54 | {/* */}
55 | {/* {renderRoutes(routers)}*/}
56 | {/* */}
57 | {/* */}
58 | {/*}>*/}
59 | {/**/}
60 |
61 |
62 | {renderRoutes(routers)}
63 |
64 |
65 |
66 |
67 | )
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/views/mainContent/userManage/list/listDetailInfo/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import CDetailInfo from '@/components/CDetailInfo'
3 | import CAvatar from '@/components/CAvatar'
4 | import CTable from '@/components/CTable'
5 | import CBaseComponent from '@/components/CBaseComponent'
6 | import { detailInfoData, detailTableData} from "./data";
7 | import { detailUserList} from "@/servers/userManageApi";
8 | import { urlFormat, setPageNewValue} from "@/utils";
9 |
10 | @CBaseComponent
11 | class UserManageListDetailInfo extends Component{
12 | constructor(props) {
13 | super(props);
14 | this.getUserDetailData = this.getUserDetailData.bind(this);
15 | }
16 |
17 |
18 | state = {
19 | data: detailInfoData,
20 | columns: detailTableData.tHead,
21 | dataSource: detailTableData.tBody,
22 | avatar: {
23 | img: '',
24 | title: '',
25 | description: ''
26 | }
27 | };
28 |
29 | getUserDetailData(){
30 | let id = urlFormat(this.props.history.location.search).query.id;
31 | detailUserList({id}).then(res=>{
32 | let userInfo = res.data.userInfo;
33 | userInfo.latlong = userInfo.latlong.join(',');//经纬度分割成字符串
34 | let storeList = res.data.storeList;
35 | let data = setPageNewValue(this.state.data, userInfo);
36 | this.setState({
37 | data: data,
38 | dataSource: storeList,
39 | avatar: {
40 | img: userInfo.avatar && userInfo.avatar.url,
41 | title: userInfo.name,
42 | description: ''
43 | }
44 | })
45 | }).catch(err=>{
46 |
47 | })
48 | }
49 |
50 | componentDidMount(){
51 | this.getUserDetailData();
52 | }
53 |
54 | render(){
55 | return (
56 | <>
57 |
58 |
59 |
60 |
61 |
62 |
63 | >
64 | )
65 | }
66 | }
67 |
68 | export default UserManageListDetailInfo
69 |
--------------------------------------------------------------------------------
/src/components/CSwiper/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import PropTypes from 'prop-types'
3 | // import Swiper from 'swiper'
4 | import Swiper from 'swiper/dist/js/swiper.js'
5 | import 'swiper/dist/css/swiper.min.css'
6 | import './index.scss'
7 |
8 | class CSwiper extends Component{
9 |
10 | constructor(props) {
11 | super(props);
12 | this.initSwiper = this.initSwiper.bind(this);
13 | }
14 |
15 |
16 | state = {
17 | swiper: null,
18 | options: {
19 | autoplay: {
20 | disableOnInteraction: false,
21 | },
22 | loop: true, //循环
23 | navigation: {
24 | nextEl: '.swiper-button-next',
25 | prevEl: '.swiper-button-prev',
26 | },
27 | pagination: {
28 | el: '.swiper-pagination',
29 | clickable :true,
30 | },
31 | }
32 | };
33 |
34 | initSwiper(){
35 | let swiper = new Swiper('.c-swiper-container',this.state.options);
36 | this.setState({
37 | swiper: swiper
38 | })
39 | }
40 |
41 | componentWillMount(){
42 | this.setState({
43 | options: {...this.state.options, ...this.props.options}
44 | })
45 | }
46 |
47 | componentDidMount(){
48 | this.initSwiper();
49 | }
50 |
51 | render(){
52 | return (
53 |
54 |
55 |
56 | {
57 | this.props.data.map((swiperItem, swiperIndex) => {
58 | return
59 |

60 |
61 | })
62 | }
63 |
64 |
65 | {/*前后切换按钮*/}
66 |
67 |
68 |
69 | {/*分页器*/}
70 |
71 |
72 |
73 | )
74 | }
75 | }
76 |
77 | CSwiper.defaultProps = {
78 | data: []
79 | };
80 |
81 | CSwiper.propTypes = {
82 | data: PropTypes.array,
83 | options: PropTypes.object,
84 | };
85 |
86 | export default CSwiper
87 |
--------------------------------------------------------------------------------
/src/components/CPage/index.js:
--------------------------------------------------------------------------------
1 |
2 | import React, {Component} from 'react'
3 | import { Pagination } from 'antd';
4 | import PropTypes from 'prop-types'
5 |
6 | import './index.scss'
7 |
8 | class CPage extends Component{
9 |
10 | state = {
11 | page: 1,
12 | pageSize: 10,
13 | total: 0
14 | }
15 |
16 | componentWillReceiveProps(nextProps) {
17 | this.setState({
18 | page: nextProps.page || 1,
19 | pageSize: nextProps.pageSize || 10,
20 | total: nextProps.total || 0
21 | });
22 | }
23 |
24 | onShowSizeChange(current, pageSize){
25 | this.setState({
26 | page: current,
27 | pageSize: pageSize
28 | });
29 | let data = {
30 | type: 'pageSize',
31 | data: {
32 | page: current,
33 | pageSize: pageSize
34 | }
35 | };
36 | this.props.onPageChange && this.props.onPageChange(data);
37 | }
38 |
39 | onChange(page, pageSize){
40 | this.setState({
41 | page: page,
42 | pageSize: pageSize
43 | });
44 | let data = {
45 | type: 'page',
46 | data: {
47 | page: page,
48 | pageSize: pageSize
49 | }
50 | };
51 | this.props.onPageChange && this.props.onPageChange(data);
52 | }
53 |
54 | componentWillMount(){
55 | this.setState({
56 | page: this.props.page || 1,
57 | pageSize: this.props.pageSize || 10,
58 | total: this.props.total || 0
59 | });
60 | }
61 |
62 | render(){
63 | const {page, ...props} = this.props;
64 | return (
65 | this.onChange(page, pageSize)}
71 | onShowSizeChange={(current, pageSize) => this.onShowSizeChange(current, pageSize)}/>
72 | )
73 | }
74 | }
75 |
76 | CPage.defaultProps = {
77 | total: 0,
78 | page: 1,
79 | pageSize: 10,
80 | showSizeChanger: true,
81 | showQuickJumper: true,
82 | size: 'small',
83 | showTotal: total => `共 ${total} 条`,
84 | }
85 |
86 | CPage.propTypes = {
87 | total: PropTypes.number,
88 | page: PropTypes.number,
89 | pageSize: PropTypes.number,
90 | }
91 |
92 |
93 | export default CPage
94 |
--------------------------------------------------------------------------------
/src/mock/userManage/index.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs';
2 | import { formatURL} from '../index'
3 |
4 | // 商家用户
5 | import {
6 | deleteUserManage,
7 | getUserManageList,
8 | insertUserManage,
9 | detailUserManage,
10 | editUserManage,
11 | editActiveUser,
12 | getUserManageDeleteList,
13 | resetDeleteUser,
14 | deletePermanentUser} from "./userList";
15 |
16 | // 管理员用户
17 | import {
18 | deleteUserManageAdmin,
19 | getUserManageAdminList,
20 | insertUserManageAdmin,
21 | detailUserManageAdmin,
22 | editUserManageAdmin,
23 | getUserManageDeleteAdminList,
24 | resetDeleteAdminUser,
25 | deletePermanentAdminUser} from "./adminList";
26 |
27 | /*获取商家用户数据*/
28 | Mock.mock(formatURL('/userManage/userList/get'), 'get', getUserManageList);
29 | // 删除商家用户
30 | Mock.mock(formatURL('/userManage/userList/delete'), 'post', deleteUserManage);
31 | // 新建商家用户
32 | Mock.mock(formatURL('/userManage/userList/insert'), 'post', insertUserManage);
33 | // 编辑商家用户
34 | Mock.mock(formatURL('/userManage/userList/edit'), 'post', editUserManage);
35 | // 获取用户详情
36 | Mock.mock(formatURL('/userManage/userList/detail'), 'get', detailUserManage);
37 | // 激活停用
38 | Mock.mock(formatURL('/userManage/userList/active'), 'post', editActiveUser);
39 | /*获取已删除的商家用户数据*/
40 | Mock.mock(formatURL('/historyRecord/deleteUserList/get'), 'get', getUserManageDeleteList);
41 | // 恢复已删除用户
42 | Mock.mock(formatURL('/historyRecord/deleteUserList/reset'), 'post', resetDeleteUser);
43 | // 永久删除用户
44 | Mock.mock(formatURL('/historyRecord/deleteUserList/delete'), 'post', deletePermanentUser);
45 |
46 |
47 | /*获取管理员用户数据*/
48 | Mock.mock(formatURL('/userManage/adminList/get'), 'get', getUserManageAdminList);
49 | // 删除管理员用户
50 | Mock.mock(formatURL('/userManage/adminList/delete'), 'post', deleteUserManageAdmin);
51 | // 新建管理员用户
52 | Mock.mock(formatURL('/userManage/adminList/insert'), 'post', insertUserManageAdmin);
53 | // 编辑管理员用户
54 | Mock.mock(formatURL('/userManage/adminList/edit'), 'post', editUserManageAdmin);
55 | // 获取管理员用户详情
56 | Mock.mock(formatURL('/userManage/adminList/detail'), 'get', detailUserManageAdmin);
57 | /*获取已删除的系统用户数据*/
58 | Mock.mock(formatURL('/historyRecord/deleteAdminUserList/get'), 'get', getUserManageDeleteAdminList);
59 | // 恢复已删除系统用户
60 | Mock.mock(formatURL('/historyRecord/deleteAdminUserList/reset'), 'post', resetDeleteAdminUser);
61 | // 永久删除系统用户
62 | Mock.mock(formatURL('/historyRecord/deleteAdminUserList/delete'), 'post', deletePermanentAdminUser);
63 |
--------------------------------------------------------------------------------
/src/views/mainContent/goodsManage/goodsList/listDetailInfo/data.js:
--------------------------------------------------------------------------------
1 |
2 | export const detailInfoData = [
3 | {
4 | id: 'baseInfo',
5 | title: '基本信息',
6 | data: [
7 | {
8 | id: 'id',
9 | name: '商品ID',
10 | value: '',
11 | type: 'input',
12 | jpath: 'id',
13 | },
14 | {
15 | id: 'name',
16 | name: '商品名称',
17 | value: '',
18 | type: 'input',
19 | jpath: 'name',
20 | },
21 | {
22 | id: 'storeInfo',
23 | name: '所属店铺',
24 | value: '',
25 | type: 'input',
26 | jpath: 'storeInfo.storeName',
27 | },
28 | {
29 | id: 'description',
30 | name: '商品描述',
31 | value: '',
32 | type: 'input',
33 | jpath: 'description',
34 | },
35 | {
36 | id: 'category',
37 | name: '所属分类',
38 | value: '',
39 | type: 'input',
40 | jpath: 'category',
41 | },
42 | {
43 | id: 'price',
44 | name: '价格',
45 | value: '',
46 | type: 'input',
47 | jpath: 'price',
48 | },
49 | {
50 | id: 'stockNum',
51 | name: '库存',
52 | value: '',
53 | type: 'input',
54 | jpath: 'stockNum',
55 | },
56 | {
57 | id: 'tradingTotalNum',
58 | name: '总交易数量',
59 | value: '',
60 | type: 'input',
61 | jpath: 'tradingTotalNum',
62 | },
63 | {
64 | id: 'tradingMonthNum',
65 | name: '月交易数量',
66 | value: '',
67 | type: 'input',
68 | jpath: 'tradingMonthNum',
69 | },
70 | {
71 | id: 'tradingDayNum',
72 | name: '日交易数量',
73 | value: '',
74 | type: 'input',
75 | jpath: 'tradingDayNum',
76 | },
77 | {
78 | id: 'commitGoodRate',
79 | name: '好评率',
80 | value: '',
81 | type: 'input',
82 | jpath: 'commitGoodRate',
83 | },
84 | {
85 | id: 'createTime',
86 | name: '创建时间',
87 | value: '',
88 | type: 'input',
89 | jpath: 'createTime',
90 | },
91 | {
92 | id: 'imgs',
93 | name: '商品图片',
94 | value: [],
95 | type: 'img',
96 | jpath: 'imgs',
97 | },
98 | ]
99 | }
100 | ];
101 |
--------------------------------------------------------------------------------
/src/views/mainContent/home/data.js:
--------------------------------------------------------------------------------
1 | import React from 'react'
2 | import CButton from "../../../components/CButton";
3 |
4 | export const tableData = {
5 | tHead: [
6 | {
7 | key: 'key',
8 | title: 'key',
9 | dataIndex: 'key',
10 | },
11 | {
12 | key: 'name',
13 | dataIndex: 'name',
14 | title: 'name',
15 | filterMultiple: false,
16 | filters: [
17 | {
18 | value: '1',
19 | text: '用户类型1'
20 | },
21 | {
22 | value: '2',
23 | text: '用户类型2'
24 | },
25 | {
26 | value: '3',
27 | text: '用户类型3'
28 | }
29 | ]
30 | },
31 | {
32 | key: 'address',
33 | dataIndex: 'address',
34 | title: 'address',
35 | filterMultiple: true,
36 | filters: [
37 | {
38 | value: '1',
39 | text: '用户类型1'
40 | },
41 | {
42 | value: '2',
43 | text: '用户类型2'
44 | },
45 | {
46 | value: '3',
47 | text: '用户类型3'
48 | }
49 | ]
50 | },
51 | {
52 | key: 'phone',
53 | dataIndex: 'phone',
54 | title: 'phone',
55 | filterMultiple: true,
56 | filters: [
57 | {
58 | value: '1',
59 | text: '用户类型1'
60 | },
61 | {
62 | value: '2',
63 | text: '用户类型2'
64 | },
65 | {
66 | value: '3',
67 | text: '用户类型3'
68 | }
69 | ]
70 | },
71 | {
72 | key: 'IDCard',
73 | dataIndex: 'IDCard',
74 | title: 'IDCard',
75 | filterMultiple: true,
76 | filters: [
77 | {
78 | value: '1',
79 | text: '用户类型1'
80 | },
81 | {
82 | value: '2',
83 | text: '用户类型2'
84 | },
85 | {
86 | value: '3',
87 | text: '用户类型3'
88 | }
89 | ]
90 | },
91 | {
92 | key: 'operate',
93 | dataIndex: 'operate',
94 | title: '操作',
95 | width: 60,
96 | render: () => 查看,
97 | }
98 | ],
99 | tBody: [
100 | {
101 | key: '1',
102 | name: '111',
103 | age: '222',
104 | grade: '333',
105 | checked: true
106 | }
107 | ],
108 | tPage: {
109 | total: 0,
110 | page: 1,
111 | pageSize: 10
112 | }
113 | };
114 |
--------------------------------------------------------------------------------
/src/logo.svg:
--------------------------------------------------------------------------------
1 |
8 |
--------------------------------------------------------------------------------
/src/components/CForm/validate.js:
--------------------------------------------------------------------------------
1 |
2 | const validateStatus = {
3 | error: 'error',
4 | success: 'success',
5 | warning: 'warning',
6 | validating: 'validating',
7 | };
8 |
9 | const baseInfo = {
10 | required: '必填项',
11 | email: '邮箱格式不正确',
12 | card: '身份证号码格式不正确',
13 | phone: '手机号码格式不正确',
14 | maxLength: '最大长度',
15 | minLength: '最小长度',
16 | };
17 |
18 | const baseReg = {
19 | email: /^([A-Za-z0-9_\-.])+@[a-zA-Z0-9_-]+(\.[a-zA-Z0-9_-]{2,8})+$/,
20 | card: /^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|[xX])$/,
21 | phone: /^((13|14|15|16|17|18|19)[0-9]{1}\d{8})$/,
22 | };
23 |
24 | const baseData = {
25 | validate: true,
26 | info: '',
27 | validateStatus: ''
28 | };
29 |
30 | /*必填项*/
31 | const required = (value) => {
32 | if(!value || (value instanceof Array && !value.length)){
33 | return { ...baseData, validateStatus: validateStatus.error, validate: false, info: baseInfo.required}
34 | }
35 | return { ...baseData, validateStatus: '', validate: true, info: ''};
36 | };
37 |
38 | /*邮箱验证*/
39 | const email = (value) => {
40 | if(!baseReg.email.test(value)){
41 | return { ...baseData, validateStatus: validateStatus.error, validate: false, info: baseInfo.email}
42 | }
43 | return { ...baseData, validateStatus: '', validate: true, info: ''};
44 | };
45 |
46 | /*身份证号验证*/
47 | const card = (value) => {
48 | if(!baseReg.card.test(value)){
49 | return { ...baseData, validateStatus: validateStatus.error, validate: false, info: baseInfo.card}
50 | }
51 | return { ...baseData, validateStatus: '', validate: true, info: ''};
52 | };
53 |
54 | /*手机号码验证*/
55 | const phone = (value) => {
56 | if(!baseReg.phone.test(value)){
57 | return { ...baseData, validateStatus: validateStatus.error, validate: false, info: baseInfo.phone}
58 | }
59 | return { ...baseData, validateStatus: '', validate: true, info: ''};
60 | };
61 |
62 | /*字符最大长度验证*/
63 | const maxLength = (value, checkArg) => {
64 | if(value.length > Number(checkArg)){
65 | return { ...baseData, validateStatus: validateStatus.error, validate: false, info: `${baseInfo.maxLength}${checkArg}`}
66 | }
67 | return { ...baseData, validateStatus: '', validate: true, info: ''};
68 | };
69 |
70 | /*字符最小长度验证*/
71 | const minLength = (value, checkArg) => {
72 | if(value.length < Number(checkArg)){
73 | return { ...baseData, validateStatus: validateStatus.error, validate: false, info: `${baseInfo.minLength}${checkArg}`}
74 | }
75 | return { ...baseData, validateStatus: '', validate: true, info: ''};
76 | };
77 |
78 | export default {
79 | required,
80 | email,
81 | card,
82 | phone,
83 | maxLength,
84 | minLength,
85 | };
86 |
--------------------------------------------------------------------------------
/src/assets/css/var.scss:
--------------------------------------------------------------------------------
1 |
2 | @import "./themeFn.scss";
3 |
4 |
5 |
6 | /*BACKGDROUND*/
7 | $main-background-color: #f1f1f1;
8 | $main-base-color: rgba(0, 150, 136, 1);
9 | $main-base-primary-color: rgba(30, 159, 255, 1);
10 |
11 | /*TEXT COLOR*/
12 | $text-color-base: #666666;
13 | $text-color-white: #ffffff;
14 | $text-color-label: #333333;
15 |
16 | /*BUTTON COLOR*/
17 | $button-primary-background-color: rgba(30, 159, 255, 1);
18 | $button-primary-hover-background-color: rgba(30, 159, 255, 0.8);
19 | $button-danger-background-color: rgba(255, 87, 34, 1);
20 | $button-danger-hover-background-color: rgba(255, 87, 34, 0.8);
21 | $button-c-success-background-color: rgba(0, 150, 136, 1);
22 | $button-c-success-hover-background-color: rgba(0, 150, 136, 0.8);
23 | $button-warning-background-color: rgba(255, 128, 82, 1);
24 | $button-warning-hover-background-color: rgba(255, 128, 82, 0.8);
25 | $button-success-background-color: rgba(103, 194, 58, 1);
26 | $button-success-hover-background-color: rgba(103, 194, 58, 0.8);
27 | $button-default-background-color: rgba(255, 255, 255, 1);
28 | $button-default-hover-background-color: rgba(255, 255, 255, 1);
29 | $button-disabled-background-color: rgba(245, 245, 245, 1);
30 | $button-primary-text-color: $text-color-white;
31 | $button-danger-text-color: $text-color-white;
32 | $button-warning-text-color: $text-color-white;
33 | $button-success-text-color: $text-color-white;
34 | $button-c-success-text-color: $text-color-white;
35 | $button-default-text-color: $text-color-base;
36 | $button-disabled-text-color: $text-color-base;
37 | $button-hover-text-color: rgba(30, 159, 255, 1);
38 | $button-border-radius: 2px;
39 | $button-primary-border-color: rgba(30, 159, 255, 1);
40 | $button-danger-border-color: rgba(255, 87, 34, 1);
41 | $button-success-border-color: rgba(103, 194, 58, 1);
42 | $button-c-success-border-color: rgba(0, 150, 136, 1);
43 | $button-warning-border-color: rgba(255, 128, 82, 1);
44 | $button-default-border-color: #d9d9d9;
45 | $button-border-hover-color: rgba(30, 159, 255, 1);
46 | $button-size-small: 28px;
47 | $button-size-default: 30px;
48 | $button-size-larger: 32px;
49 | $button-size-small-font-size: 12px;
50 | $button-size-default-font-size: 12px;
51 | $button-size-larger-font-size: 13px;
52 |
53 |
54 | /*HEAD STYLE*/
55 | $header-background: $default-theme-header-background-color;
56 | $header-height: 45px;
57 |
58 | /*LEFTNAV STYLE*/
59 | $left-nav-background-color: $default-theme-left-nav-background-color;
60 | $left-nav-children-background-color: $default-theme-left-nav-children-background-color;
61 | $left-nav-active-background-color: $default-theme-left-nav-active-background-color;
62 | $left-nav-active-border-color: $default-theme-left-nav-active-border-color;
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/config/modules.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const fs = require('fs');
4 | const path = require('path');
5 | const paths = require('./paths');
6 | const chalk = require('react-dev-utils/chalk');
7 |
8 | /**
9 | * Get the baseUrl of a compilerOptions object.
10 | *
11 | * @param {Object} options
12 | */
13 | function getAdditionalModulePaths(options = {}) {
14 | const baseUrl = options.baseUrl;
15 |
16 | // We need to explicitly check for null and undefined (and not a falsy value) because
17 | // TypeScript treats an empty string as `.`.
18 | if (baseUrl == null) {
19 | // If there's no baseUrl set we respect NODE_PATH
20 | // Note that NODE_PATH is deprecated and will be removed
21 | // in the next major release of create-react-app.
22 |
23 | const nodePath = process.env.NODE_PATH || '';
24 | return nodePath.split(path.delimiter).filter(Boolean);
25 | }
26 |
27 | const baseUrlResolved = path.resolve(paths.appPath, baseUrl);
28 |
29 | // We don't need to do anything if `baseUrl` is set to `node_modules`. This is
30 | // the default behavior.
31 | if (path.relative(paths.appNodeModules, baseUrlResolved) === '') {
32 | return null;
33 | }
34 |
35 | // Allow the user set the `baseUrl` to `appSrc`.
36 | if (path.relative(paths.appSrc, baseUrlResolved) === '') {
37 | return [paths.appSrc];
38 | }
39 |
40 | // Otherwise, throw an error.
41 | throw new Error(
42 | chalk.red.bold(
43 | "Your project's `baseUrl` can only be set to `src` or `node_modules`." +
44 | ' Create React App does not support other values at this time.'
45 | )
46 | );
47 | }
48 |
49 | function getModules() {
50 | // Check if TypeScript is setup
51 | const hasTsConfig = fs.existsSync(paths.appTsConfig);
52 | const hasJsConfig = fs.existsSync(paths.appJsConfig);
53 |
54 | if (hasTsConfig && hasJsConfig) {
55 | throw new Error(
56 | 'You have both a tsconfig.json and a jsconfig.json. If you are using TypeScript please remove your jsconfig.json file.'
57 | );
58 | }
59 |
60 | let config;
61 |
62 | // If there's a tsconfig.json we assume it's a
63 | // TypeScript project and set up the config
64 | // based on tsconfig.json
65 | if (hasTsConfig) {
66 | config = require(paths.appTsConfig);
67 | // Otherwise we'll check if there is jsconfig.json
68 | // for non TS projects.
69 | } else if (hasJsConfig) {
70 | config = require(paths.appJsConfig);
71 | }
72 |
73 | config = config || {};
74 | const options = config.compilerOptions || {};
75 |
76 | const additionalModulePaths = getAdditionalModulePaths(options);
77 |
78 | return {
79 | additionalModulePaths: additionalModulePaths,
80 | hasTsConfig,
81 | };
82 | }
83 |
84 | module.exports = getModules();
85 |
--------------------------------------------------------------------------------
/src/servers/index.js:
--------------------------------------------------------------------------------
1 | import Axios from 'axios'
2 | import config from '@/config'
3 |
4 | const axios = Axios.create();
5 | const CancelToken = Axios.CancelToken;
6 | const baseURL = config.mock ? '/mock' : '/api';
7 | let cancel_list = [];
8 |
9 | // axios默认配置
10 | axios.defaults.baseURL = baseURL;
11 | axios.defaults.timeout = 180000; //3min
12 |
13 | // axios.defaults.headers.common['Authorization'] = AUTH_TOKEN;
14 | // axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';
15 |
16 |
17 |
18 | // 请求拦截器
19 | axios.interceptors.request.use(function (config) {
20 | // 在发送请求之前做些什么
21 | // 删除get参数中为空的参数
22 | if(config.params){
23 | Object.keys(config.params).forEach(key=>{
24 | if(typeof config.params[key] == 'number' && !config.params[key].toString()){
25 | delete config.params[key]
26 | }else if(typeof config.params[key] == 'string' && !config.params[key]){
27 | delete config.params[key]
28 | }
29 | })
30 | }
31 | return config;
32 | }, function (error) {
33 | // 对请求错误做些什么
34 | return Promise.reject(error);
35 | });
36 |
37 |
38 | // 响应拦截器
39 | axios.interceptors.response.use(function (response) {
40 | // 对响应数据做点什么
41 | if (response.status === 200) {
42 | return Promise.resolve(response.data);
43 | } else {
44 | return Promise.reject(response.data);
45 | }
46 | // return response;
47 | }, function (error) {
48 |
49 | // 对响应错误做点什么
50 | // console.log(error.response,'error')
51 | // console.log(error.response.data);
52 | // console.log(error.response.status);
53 | // console.log(error.response.headers);
54 |
55 | return Promise.reject(error && error.response && error.response.data);
56 | });
57 |
58 |
59 |
60 |
61 | // 该方法会取消所有正在进行的请求
62 | export const ajax_abort_all = () => {
63 | cancel_list.forEach(item=>{
64 | item();
65 | });
66 | cancel_list = [];
67 | };
68 |
69 | export const ajax_all = (method, url, params, data) => {
70 | return axios({
71 | method,
72 | url,
73 | params,
74 | data,
75 | cancelToken: new CancelToken(function (cancel) {
76 | cancel_list.push(cancel);
77 | })
78 | }).then(response=>{
79 | return Promise.resolve(response)
80 | }).catch(error=>{
81 | return Promise.reject(error)
82 | });
83 | };
84 |
85 |
86 | export const ajax_get = (url, params) => {
87 | return ajax_all('get', url, params);
88 | };
89 |
90 | export const ajax_post = (url, data) => {
91 | return ajax_all('post', url, {}, data);
92 | };
93 |
94 | export const ajax_put = (url, data) => {
95 | return ajax_all('put', url, {}, data);
96 | };
97 |
98 | export const ajax_delete = (url, data) => {
99 | return ajax_all('delete', url, {}, data);
100 | };
101 |
102 |
--------------------------------------------------------------------------------
/src/mock/userManage/schema.js:
--------------------------------------------------------------------------------
1 | import Mock from 'mockjs'
2 | import * as commonData from '../commonData'
3 | import commonSchema from '../commonSchema'
4 | import {randomLongLat} from "../commonUtils";
5 |
6 | // const Random = Mock.Random;
7 |
8 | /*商家用户列表数据*/
9 | const busniessList = {
10 | 'list|30-100':[
11 | {
12 | 'id|+1': 1,
13 | 'name': '@CNAME',//真实用户姓名
14 | 'password': '123456',//登录密码
15 | 'sex|1': commonData.data.sex,//性别
16 | 'IDCard': /^\d{6}(18|19|20)?\d{2}(0[1-9]|1[012])(0[1-9]|[12]\d|3[01])\d{3}(\d|[xX])$/,//身份证号
17 | 'IDCardPicture|1': commonData.data.images.IDCardPicture,//身份证照片正反面
18 | 'userRole|1': commonData.data.userRole,//用户角色
19 | 'phone': /^1[3456789]\d{9}$/,//手机号
20 | 'avatar|1': commonData.data.images.avatar,//头像
21 | 'email': '@EMAIL',//邮箱
22 | 'address': '@COUNTY(true)',//住址
23 | 'latlong': function () {
24 | return randomLongLat([87.9345703125,118.5644531250], [21.8614987344,42.0329743324]);
25 | },//经纬度
26 | 'storeNum|0-10': 0,//店铺数量
27 | 'isDelete': '@boolean',//是否是删除的用户
28 | 'isActive': '@boolean',//激活停用
29 | 'deleteReason': '已到期',//删除原因
30 | 'createTime': '@datetime',//创建时间
31 | 'deleteTime': '@datetime',//删除时间
32 | }
33 | ]
34 | };
35 |
36 | /*管理员用户列表数据*/
37 | const adminList = {
38 | 'list|30-100':[
39 | {
40 | 'id|+1': 1,
41 | 'name': '@CNAME',//真实用户姓名
42 | 'password': '123456',//登录密码
43 | 'sex|1': commonData.data.sex,//性别
44 | 'userRole|1': commonSchema.adminRoleList,//用户角色
45 | 'phone': /^1[3456789]\d{9}$/,//手机号
46 | 'avatar|1': commonData.data.images.avatar,//头像
47 | 'email': '@EMAIL',//邮箱
48 | 'isDelete': '@boolean',//是否是删除的用户
49 | 'isActive': '@boolean',//激活停用
50 | 'deleteReason': '已离职',//删除原因
51 | 'createTime': '@datetime',//创建时间
52 | 'deleteTime': '@datetime',//删除时间
53 | }
54 | ]
55 | };
56 |
57 | let userListBusniessAll = Mock.mock(busniessList);
58 | let userListAdminAll = Mock.mock(adminList);
59 | // let userListBusniess = userListBusniessAll.list.filter(item=>{
60 | // return !item.isDelete
61 | // });
62 | // let userListAdmin = userListAdminAll.list.filter(item=>{
63 | // return !item.isDelete
64 | // });
65 | // let userListBusniessDelete = userListBusniessAll.list.filter(item=>{
66 | // return item.isDelete
67 | // });
68 | // let userListAdminDelete = userListAdminAll.list.filter(item=>{
69 | // return item.isDelete
70 | // });
71 |
72 | export default {
73 | userListBusniess: userListBusniessAll.list.concat([commonData.data.userList[1]]),
74 | userListAdmin: userListAdminAll.list.concat([commonData.data.userList[0]]),
75 | // userListBusniessDelete: userListBusniessDelete,
76 | // userListAdminDelete: userListAdminDelete,
77 | }
78 |
79 |
80 |
81 |
--------------------------------------------------------------------------------
/src/components/CTable/filterHead.js:
--------------------------------------------------------------------------------
1 | /*
2 | * 过滤项展示组件
3 | * */
4 |
5 | import React, {Component} from 'react';
6 | import PropTypes from 'prop-types'
7 | import _ from 'lodash'
8 | import { Tag } from 'antd';
9 |
10 | class FilterHead extends Component{
11 |
12 |
13 | tagClose(data, tag){
14 | this.props.onTagClose && this.props.onTagClose(data, tag);
15 | }
16 |
17 | flag(data){
18 | if(_.isArray(data.data)){
19 | return !!data.data.length
20 | }else if(_.isObject(data.data)){
21 | return _.isArray(data.data.dateString) ? !!data.data.dateString.length : !!data.data.dateString
22 | }
23 | return false
24 | }
25 |
26 | componentWillReceiveProps(nextProps) {
27 |
28 | }
29 |
30 | render(){
31 | return (
32 |
33 | {
34 | !!this.props.data.length && (
35 | <>
36 |
37 |
38 | 筛选项
39 |
40 |
41 | {
42 | this.props.data.map((item, index)=>{
43 | return
44 | {
45 | this.flag(item) &&
46 |
{item.title}
47 |
48 | {
49 | item.type === 'filter' && item.data.map((tag, tag_index)=>{
50 | return this.tagClose(item, tag)} key={tag.value}>{tag.text}
51 | })
52 | }
53 | {
54 | item.type === 'date' && _.isString(item.data.dateString) && this.tagClose(item, item.data.dateString)}>{item.data.dateString}
55 | }
56 | {
57 | item.type === 'date' && _.isArray(item.data.dateString) && this.tagClose(item, item.data.dateString)}>{item.data.dateString[0]}-{item.data.dateString[1]}
58 | }
59 |
60 |
61 | }
62 |
63 | })
64 | }
65 |
66 | >
67 | )
68 | }
69 |
70 | )
71 | }
72 | }
73 |
74 | FilterHead.propTypes = {
75 | data: PropTypes.array,
76 | onTagClose: PropTypes.func,
77 | };
78 |
79 | export default FilterHead
80 |
--------------------------------------------------------------------------------
/src/views/mainContent/home/index.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import { connect} from 'react-redux'
3 | import CInput from '@/components/CForm/CInput'
4 | import CBaseComponent from '@/components/CBaseComponent'
5 | import InfoTitle from '@/components/CDetailInfo/detailInfoTitle'
6 | import BaseMap from './baseMap'
7 | import './index.scss'
8 |
9 | import { getStoreAllList} from "@/servers/homeApi";
10 |
11 | @CBaseComponent
12 | class Home extends Component{
13 | constructor(props) {
14 | super(props);
15 | this.getStoreListAllData = this.getStoreListAllData.bind(this);
16 | this.searchHandler = this.searchHandler.bind(this);
17 | }
18 |
19 |
20 | state = {
21 | data: null,
22 | searchData: {
23 | value: '',//搜索框筛选
24 | placeholder: '请输入店铺名称'
25 | },
26 | loading: false,
27 | mapHeight: '300px',//地图高度
28 | };
29 |
30 | // 获取用户列表数据
31 | getStoreListAllData(){
32 | let getData = {
33 | search: this.state.searchData.value,
34 | };
35 | this.setState({
36 | loading: true
37 | });
38 | getStoreAllList(getData).then(res=>{
39 | let data = res.data.list;
40 | this.setState({
41 | data: data,
42 | loading: false
43 | });
44 | })
45 | }
46 |
47 | // 名称筛选
48 | searchHandler(value){
49 | this.setState({
50 | searchData: {...this.state.searchData, value: value}
51 | }, () => this.getStoreListAllData())
52 | }
53 |
54 | // 计算地图高度
55 | computedMapHeight(){
56 | let screenHeight = this.props.windowInfo && this.props.windowInfo.screenHeight;
57 | let mapHeight = screenHeight - 200;
58 | this.setState({
59 | mapHeight: mapHeight + 'px'
60 | })
61 | }
62 |
63 |
64 |
65 | componentWillReceiveProps(nextProps){
66 | this.computedMapHeight();
67 | }
68 |
69 | componentWillMount(){
70 |
71 | }
72 |
73 |
74 | componentDidMount(){
75 | this.getStoreListAllData();
76 | this.computedMapHeight();
77 | }
78 |
79 | render(){
80 | return (
81 |
82 |
83 |
84 |
88 |
89 |
90 |
91 |
92 | )
93 | }
94 | }
95 |
96 | const mapStateToProps = (state) => {
97 | return {
98 | windowInfo: state.Common.windowInfo,
99 | }
100 | };
101 |
102 | export default connect(mapStateToProps)(Home);
103 |
--------------------------------------------------------------------------------
/src/components/CForm/CInput.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react'
2 | import PropTypes from 'prop-types'
3 | import { Input, InputNumber} from 'antd'
4 | import './index.scss'
5 |
6 | class CInput extends Component{
7 |
8 | constructor(props) {
9 | super(props);
10 | this.changeHandler = this.changeHandler.bind(this);
11 | }
12 |
13 | componentWillReceiveProps(nextProps) {
14 | this.setState({
15 | value: nextProps.value
16 | })
17 | }
18 |
19 | state = {
20 | inputTypeOver: {
21 | 'password':'Password',
22 | 'search':'Search',
23 | 'textarea':'TextArea',
24 | },
25 | value: ''
26 | }
27 |
28 | changeHandler(e){
29 | let value = this.props.type === 'number' ? e : e.target.value;
30 | this.setState({
31 | value: value
32 | });
33 | this.props.onChange && this.props.onChange(value);
34 | }
35 |
36 | enterHandler(e){
37 | let value = e.target.value;
38 | this.props.onEnter && this.props.onEnter(value);
39 | }
40 |
41 | searchHandler(value){
42 | this.props.onEnter && this.props.onEnter(value);
43 | }
44 |
45 | componentWillMount(){
46 | let defaultValue = this.props.type === 'number' ? undefined : '';
47 | this.setState({
48 | value: this.props.value || defaultValue
49 | })
50 | }
51 |
52 | render(){
53 | const {type, showNumberStep, className, onChange, onEnter, value, ...props} = this.props;
54 |
55 | const InputDom = this.state.inputTypeOver[type] ? Input[this.state.inputTypeOver[type]] : (type === 'input' && Input);
56 | const onSearch = (value) => this.searchHandler(value);
57 | let propsObj = {};
58 | if(type === 'search'){
59 | propsObj = {
60 | onSearch
61 | }
62 | }
63 | return (
64 | <>
65 | {!!InputDom && this.changeHandler(e)}
70 | onPressEnter={(e) => this.enterHandler(e)}/>}
71 | {type === 'number'
72 | && this.changeHandler(value)}
75 | className={`c-input-number ${className} ${!showNumberStep ? 'no-show-number-step' : ''}`}/>}
76 | >
77 | )
78 | }
79 | }
80 |
81 | CInput.defaultProps = {
82 | type: 'input',
83 | showNumberStep: false,//是否显示number类型的step
84 | value: ''
85 | };
86 |
87 | CInput.propTypes = {
88 | type: PropTypes.string,
89 | showNumberStep: PropTypes.bool,
90 | value: PropTypes.oneOfType([
91 | PropTypes.string,
92 | PropTypes.number
93 | ])
94 | };
95 |
96 | export default CInput
97 |
--------------------------------------------------------------------------------
/src/views/mainContent/storeManage/echarts/newStoreEcharts.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import CEcharts from '@/components/CEcharts'
3 | import InfoTitle from '@/components/CDetailInfo/detailInfoTitle'
4 | import Echarts from 'echarts'
5 | import _ from 'lodash'
6 |
7 | export default class NewStoreEcharts extends Component{
8 | constructor(props) {
9 | super(props);
10 | this.initOptions = this.initOptions.bind(this);
11 | }
12 |
13 |
14 | state = {
15 | options: {
16 | title: '',
17 | grid: {
18 | left: '5%',
19 | top: '10%',
20 | bottom: '2%',
21 | right: '2%',
22 | containLabel: true,
23 | },
24 | tooltip: {
25 | show: true,
26 | trigger: 'axis',
27 | },
28 | xAxis: {
29 | type: 'time',
30 | axisLabel: {
31 | textStyle: {
32 | color: '#666'
33 | }
34 | },
35 | axisTick: {
36 | show: false
37 | },
38 | },
39 | yAxis: {
40 | type: 'value',
41 | name: '数量(个)',
42 | max: 'dataMax',
43 | axisTick: {
44 | show: false
45 | },
46 | axisLabel: {
47 | textStyle: {
48 | color: '#666'
49 | }
50 | },
51 | splitLine: {
52 | lineStyle: {
53 | color: '#eee'
54 | }
55 | }
56 | },
57 | series: [
58 | {
59 | name: '新增店铺数量统计',
60 | type: 'line',
61 | showSymbol: false,
62 | hoverAnimation: false,
63 | itemStyle: {
64 | normal: {
65 | color: new Echarts.graphic.LinearGradient(
66 | 0, 0, 0, 1,
67 | [
68 | {offset: 0, color: '#83bff6'},
69 | {offset: 0.5, color: '#188df0'},
70 | {offset: 1, color: '#188df0'}
71 | ]
72 | )
73 | }
74 | },
75 | data: []
76 | }
77 | ]
78 | }
79 | }
80 |
81 | initOptions(data){
82 | if(data) {
83 | let options = _.cloneDeep(this.state.options);
84 | options.series[0].data = data;
85 | this.setState({
86 | options: options
87 | })
88 | }
89 | }
90 |
91 | componentWillReceiveProps(nextProps){
92 | this.initOptions(nextProps.data)
93 | }
94 |
95 | componentDidMount(){
96 | this.initOptions(this.props.data);
97 | }
98 |
99 | render(){
100 | return (
101 |
102 |
103 | {this.props.children}
104 |
105 |
106 |
107 | )
108 | }
109 | }
110 |
--------------------------------------------------------------------------------
/src/views/mainContent/userManage/adminList/listNew/data.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | export const userManageListNewData = [
4 | {
5 | id: 'baseInfo',
6 | title: '基本信息',
7 | data: [
8 | {
9 | id: 'name',
10 | name: '姓名',
11 | placeholder: '请输入姓名',
12 | type: 'input',
13 | checkType: 'required',
14 | newDisabled: false,
15 | editDisabled: false,
16 | newShow: true,
17 | editShow: true,
18 | value: '',
19 | options: [],
20 | expand: {},
21 | jpath: 'name'
22 | },
23 | {
24 | id: 'password',
25 | name: '密码',
26 | placeholder: '请输入用户密码',
27 | type: 'input',
28 | checkType: 'required',
29 | newDisabled: false,
30 | editDisabled: false,
31 | newShow: true,
32 | editShow: true,
33 | value: '',
34 | options: [],
35 | expand: {},
36 | jpath: 'password'
37 | },
38 | {
39 | id: 'sex',
40 | name: '性别',
41 | placeholder: '',
42 | type: 'radio',
43 | checkType: 'required',
44 | newDisabled: false,
45 | editDisabled: false,
46 | newShow: true,
47 | editShow: true,
48 | value: '1',
49 | options: [
50 | {
51 | value: '1',
52 | name: '男'
53 | },
54 | {
55 | value: '0',
56 | name: '女'
57 | }
58 | ],
59 | expand: {},
60 | jpath: 'sex.id'
61 | },
62 | {
63 | id: 'userRole',
64 | name: '用户角色',
65 | placeholder: '请选择用户角色',
66 | type: 'select',
67 | checkType: 'required',
68 | newDisabled: false,
69 | editDisabled: false,
70 | newShow: true,
71 | editShow: true,
72 | value: '',
73 | options: [],
74 | expand: {},
75 | jpath: 'userRole.id'
76 | },
77 | {
78 | id: 'phone',
79 | name: '手机号码',
80 | placeholder: '请输入手机号码',
81 | type: 'number',
82 | checkType: 'required|phone',
83 | newDisabled: false,
84 | editDisabled: false,
85 | newShow: true,
86 | editShow: true,
87 | value: '',
88 | options: [],
89 | expand: {},
90 | jpath: 'phone'
91 | },
92 | {
93 | id: 'email',
94 | name: '邮箱',
95 | placeholder: '请输入邮箱',
96 | type: 'input',
97 | checkType: 'required|email',
98 | newDisabled: false,
99 | editDisabled: false,
100 | newShow: true,
101 | editShow: true,
102 | value: '',
103 | options: [],
104 | expand: {},
105 | jpath: 'email'
106 | },
107 | ]
108 | }
109 | ];
110 |
--------------------------------------------------------------------------------
/src/views/mainContent/userManage/list/listDetailInfo/data.js:
--------------------------------------------------------------------------------
1 |
2 | export const detailInfoData = [
3 | {
4 | id: 'baseInfo',
5 | title: '基本信息',
6 | data: [
7 | {
8 | id: 'id',
9 | name: '用户ID',
10 | value: '',
11 | type: 'input',
12 | jpath: 'id',
13 | },
14 | {
15 | id: 'name',
16 | name: '姓名',
17 | value: '',
18 | type: 'input',
19 | jpath: 'name',
20 | },
21 | {
22 | id: 'password',
23 | name: '密码',
24 | value: '',
25 | type: 'input',
26 | jpath: 'password',
27 | },
28 | {
29 | id: 'phone',
30 | name: '手机号',
31 | value: '',
32 | type: 'input',
33 | jpath: 'phone',
34 | },
35 | {
36 | id: 'IDCard',
37 | name: '身份证号',
38 | value: '',
39 | type: 'input',
40 | jpath: 'IDCard',
41 | },
42 | {
43 | id: 'sex',
44 | name: '性别',
45 | value: '',
46 | type: 'input',
47 | jpath: 'sex.name',
48 | },
49 | {
50 | id: 'userRole',
51 | name: '用户角色',
52 | value: '',
53 | type: 'input',
54 | jpath: 'userRole.name',
55 | },
56 | {
57 | id: 'email',
58 | name: '邮箱',
59 | value: '',
60 | type: 'input',
61 | jpath: 'email',
62 | },
63 | {
64 | id: 'address',
65 | name: '地址',
66 | value: '',
67 | type: 'input',
68 | jpath: 'address',
69 | },
70 | {
71 | id: 'latlong',
72 | name: '经纬度',
73 | value: '',
74 | type: 'input',
75 | jpath: 'latlong',
76 | },
77 | {
78 | id: 'storeNum',
79 | name: '店铺数量',
80 | value: '',
81 | type: 'input',
82 | jpath: 'storeNum',
83 | },
84 | {
85 | id: 'createTime',
86 | name: '创建时间',
87 | value: '',
88 | type: 'input',
89 | jpath: 'createTime',
90 | },
91 | {
92 | id: 'IDCardPictrue',
93 | name: '身份证号照片',
94 | value: [],
95 | type: 'img',
96 | jpath: 'IDCardPicture',
97 | }
98 | ]
99 | },
100 | {
101 | id: 'storeInfo',
102 | title: '店铺信息',
103 | slot: 'storeInfo',
104 | data: []
105 | }
106 | ];
107 |
108 |
109 | export const detailTableData = {
110 | tHead: [
111 | {
112 | key: 'id',
113 | title: '店铺ID',
114 | dataIndex: 'id',
115 | },
116 | {
117 | key: 'storeName',
118 | dataIndex: 'storeName',
119 | title: '店铺名称',
120 | }
121 | ],
122 | tBody: [],
123 | tPage: {
124 | total: 0,
125 | page: 1,
126 | pageSize: 10
127 | }
128 | };
129 |
--------------------------------------------------------------------------------
/src/views/App.js:
--------------------------------------------------------------------------------
1 | import React, {Component} from 'react';
2 | import { withRouter} from 'react-router-dom'
3 | // import { ajax_abort_all} from "@/servers";
4 | import { setUserInfo} from "../redux/common/action";
5 | import { connect} from 'react-redux'
6 | import { bindActionCreators} from 'redux'
7 | import { compose} from 'redux'
8 | import './App.scss'
9 | import Header from './header'
10 | import LeftNav from './leftNav'
11 | import { getStorage, setStorage} from "@/utils";
12 | import { LocaleProvider, ConfigProvider} from 'antd'
13 | import zhCN from 'antd/es/locale-provider/zh_CN';
14 | import moment from 'moment'
15 | import 'moment/locale/zh-cn';
16 | moment.locale('zh-cn');
17 |
18 |
19 |
20 |
21 | class App extends Component{
22 |
23 | state = {
24 | theme: null,//主题
25 | };
26 |
27 | // 在全局监听数据变化
28 | watchRouterChange(){
29 | this.props.history.listen((location)=>{
30 | this.userIsLogin(location);
31 | console.log('watchRouterChange');
32 | // ajax_abort_all();//路由变化时取消axios请求
33 | })
34 | }
35 |
36 | userIsLogin(location){
37 | // 判断用户是否登录,如果没有登录直接跳到login页面
38 | let userInfo = getStorage('userInfo');
39 | if(!userInfo && location.pathname !== '/login'){
40 | this.props.history.push({
41 | pathname: '/login'
42 | });
43 | }
44 | this.props.setUserInfo(userInfo);
45 | }
46 |
47 | // // 切换主题文件
48 | setThemeFile(currentTheme){
49 | if(!getStorage('theme')){
50 | setStorage('theme', currentTheme);
51 | }
52 | this.setState({
53 | theme: getStorage('theme')
54 | });
55 | }
56 |
57 | componentWillReceiveProps(nextProps){
58 | this.setThemeFile(nextProps.currentTheme);
59 | }
60 |
61 | componentDidMount(){
62 | console.log('====33')
63 | this.watchRouterChange();
64 | this.userIsLogin(this.props.history.location);
65 | this.setThemeFile(this.props.currentTheme);
66 | }
67 |
68 | render(){
69 | return (
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 | {this.props.children}
79 |
80 |
81 |
82 |
83 | )
84 | }
85 | }
86 |
87 |
88 | const mapStateToProps = (state) => {
89 | return {
90 | userInfo: state.Common.userInfo,
91 | currentTheme: state.Common.currentTheme
92 | }
93 | };
94 |
95 | const mapDispatchToProps = (dispatch) => {
96 | return {
97 | setUserInfo: bindActionCreators(setUserInfo, dispatch),
98 | }
99 | };
100 |
101 | export default compose(withRouter, connect(mapStateToProps, mapDispatchToProps))(App);
102 |
--------------------------------------------------------------------------------
/src/mock/statistics/userApiList.js:
--------------------------------------------------------------------------------
1 |
2 | import { urlFormat, formatDate} from "@/utils";
3 | import { mockConfig} from '../index'
4 | // import _ from 'lodash'
5 | import { storeManageStoreList} from "../createMockData";
6 | // import * as commonData from '../commonData'
7 |
8 | /*统计店铺根据店铺分类*/
9 | export const getStatisticsStoreByCategory = (opts) => {
10 | let data = {
11 | list: []
12 | };
13 | let obj = {};
14 | storeManageStoreList.forEach(item=>{
15 | if(!obj[item.category.id]){
16 | obj[item.category.id] = {
17 | name: item.category.name,
18 | num: 1,
19 | }
20 | }else{
21 | obj[item.category.id]['num']++
22 | }
23 | });
24 | Object.keys(obj).forEach(key=>{
25 | data.list.push({
26 | id: key,
27 | name: obj[key].name,
28 | num: obj[key].num
29 | })
30 | });
31 | return {...mockConfig.baseMock, data: data}
32 | };
33 |
34 | /*新增店铺数量统计*/
35 | export const getStatisticsNewStore = (opts) => {
36 | let startTime = urlFormat(opts.url, 'startTime');
37 | let endTime = urlFormat(opts.url, 'endTime');
38 | let data = {
39 | list: []
40 | };
41 | let obj = {};
42 | storeManageStoreList.forEach(item=>{
43 | let createTime = formatDate(item.createTime, 'YYYY-MM-DD');
44 | if(startTime && endTime){
45 | if(createTime >= startTime && createTime <= endTime){
46 | if(!obj[createTime]){
47 | obj[createTime] = 1;
48 | }else{
49 | obj[createTime]++
50 | }
51 | }
52 | }else{
53 | if(!obj[createTime]){
54 | obj[createTime] = 1;
55 | }else{
56 | obj[createTime]++
57 | }
58 | }
59 | });
60 | let arr = [];
61 | Object.keys(obj).forEach(key=>{
62 | arr.push({
63 | dateTime: key,
64 | num: obj[key]
65 | })
66 | });
67 | data.list = arr.sort(function (a, b) {
68 | return new Date(a.dateTime) - new Date(b.dateTime)
69 | });
70 | return {...mockConfig.baseMock, data: data}
71 | };
72 |
73 | /*店铺排行榜(信誉、售后、星级)*/
74 | export const getStatisticsStoreRank = (opts) => {
75 | let data = {};
76 | // 信誉排行(由小到大)
77 | storeManageStoreList.sort((a, b)=>{
78 | return a.creditGrade.id - b.creditGrade.id
79 | });
80 | // 返回信誉前十的店铺
81 | let creditGradeTop10 = storeManageStoreList.slice(0,10);
82 | // 售后排行(由大到小)
83 | storeManageStoreList.sort((a, b)=>{
84 | return b.serviceScore - a.serviceScore
85 | });
86 | // 返回售后前十的店铺
87 | let serviceScoreTop10 = storeManageStoreList.slice(0,10);
88 | // 星级排行(由大到小)
89 | storeManageStoreList.sort((a, b)=>{
90 | return b.rate - a.rate
91 | });
92 | // 返回星级前十的店铺
93 | let rateTop10 = storeManageStoreList.slice(0,10);
94 |
95 | data = {
96 | creditGradeTop10,
97 | serviceScoreTop10,
98 | rateTop10
99 | };
100 | return {...mockConfig.baseMock, data: data}
101 | };
102 |
--------------------------------------------------------------------------------
/src/mock/statistics/storeApiList.js:
--------------------------------------------------------------------------------
1 |
2 | import { urlFormat, formatDate} from "@/utils";
3 | import { mockConfig} from '../index'
4 | // import _ from 'lodash'
5 | import { storeManageStoreList} from "../createMockData";
6 | // import * as commonData from '../commonData'
7 |
8 | /*统计店铺根据店铺分类*/
9 | export const getStatisticsStoreByCategory = (opts) => {
10 | let data = {
11 | list: []
12 | };
13 | let obj = {};
14 | storeManageStoreList.forEach(item=>{
15 | if(!obj[item.category.id]){
16 | obj[item.category.id] = {
17 | name: item.category.name,
18 | num: 1,
19 | }
20 | }else{
21 | obj[item.category.id]['num']++
22 | }
23 | });
24 | Object.keys(obj).forEach(key=>{
25 | data.list.push({
26 | id: key,
27 | name: obj[key].name,
28 | num: obj[key].num
29 | })
30 | });
31 | return {...mockConfig.baseMock, data: data}
32 | };
33 |
34 | /*新增店铺数量统计*/
35 | export const getStatisticsNewStore = (opts) => {
36 | let startTime = urlFormat(opts.url, 'startTime');
37 | let endTime = urlFormat(opts.url, 'endTime');
38 | let data = {
39 | list: []
40 | };
41 | let obj = {};
42 | storeManageStoreList.forEach(item=>{
43 | let createTime = formatDate(item.createTime, 'YYYY-MM-DD');
44 | if(startTime && endTime){
45 | if(createTime >= startTime && createTime <= endTime){
46 | if(!obj[createTime]){
47 | obj[createTime] = 1;
48 | }else{
49 | obj[createTime]++
50 | }
51 | }
52 | }else{
53 | if(!obj[createTime]){
54 | obj[createTime] = 1;
55 | }else{
56 | obj[createTime]++
57 | }
58 | }
59 | });
60 | let arr = [];
61 | Object.keys(obj).forEach(key=>{
62 | arr.push({
63 | dateTime: key,
64 | num: obj[key]
65 | })
66 | });
67 | data.list = arr.sort(function (a, b) {
68 | return new Date(a.dateTime) - new Date(b.dateTime)
69 | });
70 | return {...mockConfig.baseMock, data: data}
71 | };
72 |
73 | /*店铺排行榜(信誉、售后、星级)*/
74 | export const getStatisticsStoreRank = (opts) => {
75 | let data = {};
76 | // 信誉排行(由小到大)
77 | storeManageStoreList.sort((a, b)=>{
78 | return a.creditGrade.id - b.creditGrade.id
79 | });
80 | // 返回信誉前十的店铺
81 | let creditGradeTop10 = storeManageStoreList.slice(0,10);
82 | // 售后排行(由大到小)
83 | storeManageStoreList.sort((a, b)=>{
84 | return b.serviceScore - a.serviceScore
85 | });
86 | // 返回售后前十的店铺
87 | let serviceScoreTop10 = storeManageStoreList.slice(0,10);
88 | // 星级排行(由大到小)
89 | storeManageStoreList.sort((a, b)=>{
90 | return b.rate - a.rate
91 | });
92 | // 返回星级前十的店铺
93 | let rateTop10 = storeManageStoreList.slice(0,10);
94 |
95 | data = {
96 | creditGradeTop10,
97 | serviceScoreTop10,
98 | rateTop10
99 | };
100 | return {...mockConfig.baseMock, data: data}
101 | };
102 |
--------------------------------------------------------------------------------
/src/views/mainContent/goodsManage/goodsList/listNew/data.js:
--------------------------------------------------------------------------------
1 |
2 |
3 | export const goodsManageListNewData = [
4 | {
5 | id: 'baseInfo',
6 | title: '基本信息',
7 | data: [
8 | {
9 | id: 'name',
10 | name: '商品名称',
11 | placeholder: '请输入商品名称',
12 | type: 'input',
13 | checkType: 'required|maxLength:30',
14 | newDisabled: false,
15 | editDisabled: false,
16 | newShow: true,
17 | editShow: true,
18 | value: '',
19 | options: [],
20 | expand: {},
21 | jpath: 'name'
22 | },
23 | {
24 | id: 'storeInfo',
25 | name: '所属商铺',
26 | placeholder: '请选择所属商铺',
27 | type: 'select',
28 | checkType: 'required',
29 | newDisabled: false,
30 | editDisabled: false,
31 | newShow: true,
32 | editShow: true,
33 | value: '',
34 | options: [],
35 | expand: {
36 | showSearch: true,//可以搜索
37 | filterOption: false,//不触发options过滤,做手动远程过滤
38 | defaultActiveFirstOption: false,//默认不选中options第一个,防止不选中失去焦点时的闪现问题
39 | },
40 | jpath: 'storeInfo.id'
41 | },
42 | {
43 | id: 'price',
44 | name: '商品价格',
45 | placeholder: '请输入商品价格',
46 | type: 'number',
47 | checkType: 'required',
48 | newDisabled: false,
49 | editDisabled: false,
50 | newShow: true,
51 | editShow: true,
52 | value: '',
53 | options: [],
54 | expand: {},
55 | jpath: 'price'
56 | },
57 | {
58 | id: 'description',
59 | name: '商品描述',
60 | placeholder: '请输入商品描述',
61 | type: 'textarea',
62 | checkType: 'required',
63 | newDisabled: false,
64 | editDisabled: false,
65 | newShow: true,
66 | editShow: true,
67 | value: '',
68 | options: [],
69 | expand: {
70 | autoSize: {minRows: 3, maxRows: 6}
71 | },
72 | jpath: 'description'
73 | },
74 | {
75 | id: 'stockNum',
76 | name: '库存量',
77 | placeholder: '请输入库存量',
78 | type: 'number',
79 | checkType: 'required',
80 | newDisabled: false,
81 | editDisabled: false,
82 | newShow: true,
83 | editShow: true,
84 | value: '',
85 | options: [],
86 | expand: {},
87 | jpath: 'stockNum'
88 | },
89 | {
90 | id: 'imgs',
91 | name: '商品图片',
92 | placeholder: '',
93 | type: 'img',
94 | checkType: 'required',
95 | newDisabled: false,
96 | editDisabled: false,
97 | newShow: true,
98 | editShow: true,
99 | value: [],
100 | options: [],
101 | expand: {
102 | limit: 5
103 | },
104 | jpath: 'imgs'
105 | }
106 | ]
107 | }
108 | ];
109 |
--------------------------------------------------------------------------------
/src/views/mainContent/index.js:
--------------------------------------------------------------------------------
1 | import React, { Component} from 'react'
2 | import { connect} from 'react-redux'
3 | import { bindActionCreators} from 'redux'
4 | import { Card} from 'antd'
5 | import CBreadcrumb from '@/components/CBreadcrumb'
6 | import CButton from '@/components/CButton'
7 | import CScroll from '@/components/CScroll'
8 | import { setReload, setWindowInfo} from "@/redux/common/action";
9 | import './index.scss'
10 |
11 | class MainContent extends Component{
12 |
13 | constructor(props) {
14 | super(props);
15 | this.reload = this.reload.bind(this);
16 | this.listenWindowInfo = this.listenWindowInfo.bind(this);
17 | }
18 |
19 |
20 | // static getDerivedStateFromProps(){
21 | //
22 | // }
23 |
24 | reload(){
25 | this.props.setReload(true);
26 | }
27 |
28 | // 监听window高宽变化
29 | listenWindowInfo(){
30 | let self = this;
31 | window.addEventListener('resize', function (e) {
32 | let height = window.innerHeight || document.body.clientHeight || document.documentElement.clientHeight;
33 | let width = window.innerWidth || document.body.clientWidth || document.documentElement.clientWidth;
34 | let mainContentHeight = document.getElementById('mainContent').offsetHeight;
35 | let mainContentWidth = document.getElementById('mainContent').offsetWidth;
36 | let value = {
37 | ...self.props.windowInfo,
38 | screenHeight: height,
39 | screenWidth: width,
40 | mainContentHeight,
41 | mainContentWidth};
42 | self.props.setWindowInfo && self.props.setWindowInfo(value);
43 | })
44 | }
45 |
46 | componentWillMount(){
47 |
48 | }
49 |
50 | componentDidMount(){
51 | this.listenWindowInfo();
52 | }
53 |
54 | componentDidUpdate(){
55 |
56 | }
57 |
58 | render(){
59 | return (
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 | {this.props.children}
71 |
72 |
73 |
74 |
75 |
76 | )
77 | }
78 | }
79 |
80 | const mapStateToProps = (state) => {
81 | return {
82 | breadcrumbData: state.Common.breadcrumbData,
83 | windowInfo: state.Common.windowInfo,
84 | reload: state.Common.reload,
85 | }
86 | };
87 |
88 | const mapDispatchToProps = (dispatch) => {
89 | return {
90 | setReload: bindActionCreators(setReload, dispatch),
91 | setWindowInfo: bindActionCreators(setWindowInfo, dispatch),
92 | }
93 | };
94 |
95 | export default connect(mapStateToProps, mapDispatchToProps)(MainContent);
96 |
--------------------------------------------------------------------------------
/config/paths.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | const path = require('path');
4 | const fs = require('fs');
5 | const url = require('url');
6 |
7 | // Make sure any symlinks in the project folder are resolved:
8 | // https://github.com/facebook/create-react-app/issues/637
9 | const appDirectory = fs.realpathSync(process.cwd());
10 | const resolveApp = relativePath => path.resolve(appDirectory, relativePath);
11 |
12 | const envPublicUrl = process.env.PUBLIC_URL;
13 |
14 | function ensureSlash(inputPath, needsSlash) {
15 | const hasSlash = inputPath.endsWith('/');
16 | if (hasSlash && !needsSlash) {
17 | return inputPath.substr(0, inputPath.length - 1);
18 | } else if (!hasSlash && needsSlash) {
19 | return `${inputPath}/`;
20 | } else {
21 | return inputPath;
22 | }
23 | }
24 |
25 | const getPublicUrl = appPackageJson =>
26 | envPublicUrl || require(appPackageJson).homepage;
27 |
28 | // We use `PUBLIC_URL` environment variable or "homepage" field to infer
29 | // "public path" at which the app is served.
30 | // Webpack needs to know it to put the right