Sfoglia il codice sorgente

编辑项目-项目类型

魏熙美 5 anni fa
parent
commit
40dcec1536

+ 45
- 21
config/config.js Vedi File

@@ -124,7 +124,8 @@ export default {
124 124
                 },
125 125
                 {
126 126
                   path: '/building/list/add',
127
-                  name: '', // 项目添加
127
+                  name: '项目添加', // 项目添加
128
+                  hideInMenu: true,
128 129
                   component: './building/list/add/index',
129 130
                 },
130 131
                 {
@@ -134,7 +135,8 @@ export default {
134 135
                 },
135 136
                 {
136 137
                   path: '/building/type/edi',
137
-                  name: '',
138
+                  name: '项目类型编辑',
139
+                  hideInMenu: true,
138 140
                   component: './building/type/edi',
139 141
                 },
140 142
               ],
@@ -151,7 +153,8 @@ export default {
151 153
                 },
152 154
                 {
153 155
                   path: '/customer/customerlist/customerDetail',
154
-                  name: '',
156
+                  name: '客户编辑',
157
+                  hideInMenu: true,
155 158
                   component: './customer/customerlist/customerDetail',
156 159
                 },
157 160
                 {
@@ -171,7 +174,8 @@ export default {
171 174
                 },
172 175
                 {
173 176
                   path: '/customer/recommendCustomer/audit',
174
-                  name: '', //审核
177
+                  name: '客户审核', 
178
+                  hideInMenu: true,
175 179
                   component: './customer/recommendCustomer/audit',
176 180
                 },
177 181
                 {
@@ -198,7 +202,8 @@ export default {
198 202
                 },
199 203
                 {
200 204
                   path: '/integralMall/editGoods',
201
-                  name: '',
205
+                  name: '商品编辑',
206
+                  hideInMenu: true,
202 207
                   component: './integralMall/editGoods',
203 208
                 },
204 209
                 {
@@ -213,7 +218,8 @@ export default {
213 218
                 },
214 219
                 {
215 220
                   path: '/integralMall/verifyList',
216
-                  name: '',
221
+                  name: '商品核销列表',
222
+                  hideInMenu: true,
217 223
                   component: './integralMall/verifyList',
218 224
                 },
219 225
               ],
@@ -230,12 +236,14 @@ export default {
230 236
                 },
231 237
                 {
232 238
                   path: '/channel/addChannel',
233
-                  name: '',
239
+                  name: '添加渠道',
240
+                  hideInMenu: true,
234 241
                   component: './channel/addChannel',
235 242
                 },
236 243
                 {
237 244
                   path: '/channel/editChannel',
238
-                  name: '',
245
+                  name: '编辑渠道',
246
+                  hideInMenu: true,
239 247
                   component: './channel/editChannel',
240 248
                 },
241 249
                 {
@@ -245,12 +253,14 @@ export default {
245 253
                 },
246 254
                 {
247 255
                   path: '/channel/recommendClients',
248
-                  name: '',
256
+                  name: '渠道推荐',
257
+                  hideInMenu: true,
249 258
                   component: './channel/recommendClients',
250 259
                 },
251 260
                 {
252 261
                   path: '/channel/InviteClients',
253
-                  name: '',
262
+                  name: '邀请客户',
263
+                  hideInMenu: true,
254 264
                   component: './channel/InviteClients',
255 265
                 },
256 266
               ],
@@ -267,7 +277,8 @@ export default {
267 277
                 },
268 278
                 {
269 279
                   path: '/news/type/editNews',
270
-                  name: '',
280
+                  name: '编辑资讯类型',
281
+                  hideInMenu: true,
271 282
                   component: './news/type/editNews',
272 283
                 },
273 284
                 {
@@ -277,7 +288,8 @@ export default {
277 288
                 },
278 289
                 {
279 290
                   path: '/news/list/editNewsList',
280
-                  name: '',
291
+                  name: '编辑资讯',
292
+                  hideInMenu: true,
281 293
                   component: './news/list/editNewsList',
282 294
                 },
283 295
               ],
@@ -294,12 +306,14 @@ export default {
294 306
                 },
295 307
                 {
296 308
                   path: '/activity/editActivity',
297
-                  name: '',
309
+                  name: '编辑活动',
310
+                  hideInMenu: true,
298 311
                   component: './activity/editActivity',
299 312
                 },
300 313
                 {
301 314
                   path: '/activity/SignList',
302
-                  name: '',
315
+                  name: '报名列表',
316
+                  hideInMenu: true,
303 317
                   component: './activity/SignList',
304 318
                 },
305 319
               ],
@@ -316,7 +330,8 @@ export default {
316 330
                 },
317 331
                 {
318 332
                   path: '/staff/editStaff',
319
-                  name: '',
333
+                  name: '编辑员工',
334
+                  hideInMenu: true,
320 335
                   component: './staff/list/editStaff',
321 336
                 },
322 337
 
@@ -327,10 +342,16 @@ export default {
327 342
                 },
328 343
                 {
329 344
                   path: '/staff/editRole',
330
-                  name: '',
345
+                  name: '编辑角色',
346
+                  hideInMenu: true,
331 347
                   component: './staff/list/editRole',
332 348
                 },
333
-
349
+                {
350
+                  path: '/staff/list/addRole',
351
+                  name: '添加角色',
352
+                  hideInMenu: true,
353
+                  component: './staff/list/addRole',
354
+                },  
334 355
               ],
335 356
             },
336 357
             {
@@ -345,7 +366,8 @@ export default {
345 366
                 },
346 367
                 {
347 368
                   path: '/carouselFigure/editCarousel',
348
-                  name: '',
369
+                  name: '轮播图编辑',
370
+                  hideInMenu: true,
349 371
                   component: './carouselFigure/editCarousel',
350 372
                 },
351 373
                 {
@@ -355,7 +377,8 @@ export default {
355 377
                 },
356 378
                 {
357 379
                   path: '/carouselFigure/editAdvertising',
358
-                  name: '',
380
+                  name: '开屏广告编辑',
381
+                  hideInMenu: true,
359 382
                   component: './carouselFigure/editAdvertising',
360 383
                 },
361 384
               ],
@@ -387,7 +410,8 @@ export default {
387 410
                 },
388 411
                 {
389 412
                   path: '/system/editPolicy',
390
-                  name: '',
413
+                  name: '购房政策编辑',
414
+                  hideInMenu: true,
391 415
                   component: './system/editPolicy',
392 416
                 },
393 417
               ],
@@ -455,7 +479,7 @@ export default {
455 479
 
456 480
   proxy: {
457 481
     '/api/': {
458
-      target: 'http://localhost:8080/',
482
+      target: 'http://192.168.0.11:8080/',
459 483
       changeOrigin: true,
460 484
       // pathRewrite: { '^/server': '' },
461 485
     },

+ 2
- 0
package.json Vedi File

@@ -45,6 +45,7 @@
45 45
     "@antv/data-set": "^0.10.2",
46 46
     "antd": "^3.20.0",
47 47
     "classnames": "^2.2.6",
48
+    "dayjs": "^1.8.16",
48 49
     "dva": "^2.4.1",
49 50
     "echarts": "^4.3.0",
50 51
     "lodash": "^4.17.11",
@@ -68,6 +69,7 @@
68 69
     "@ant-design/colors": "^3.1.0",
69 70
     "@ant-design/pro-cli": "^1.0.0",
70 71
     "@types/classnames": "^2.2.7",
72
+    "@types/echarts": "^4.1.14",
71 73
     "@types/express": "^4.17.0",
72 74
     "@types/history": "^4.7.2",
73 75
     "@types/jest": "^24.0.13",

+ 25
- 0
src/components/AuthButton/index.jsx Vedi File

@@ -0,0 +1,25 @@
1
+import React from 'react';
2
+
3
+let allBtns = [];
4
+let current = [];
5
+
6
+const AuthButton = ({ children, name, noRight }) => {
7
+  const btn = allBtns.filter(x => x.code === name)[0]
8
+
9
+  // 没维护的按钮, 或者不需要权限的按钮直接通过
10
+  if (!btn || !btn.roles || !btn.roles.length) {
11
+    return <>{children}</>
12
+  }
13
+
14
+  const hasRight = btn.roles.some(x => current.some(y => x === y))
15
+  return hasRight ? <>{children}</> : <>{noRight}</>
16
+}
17
+
18
+const setAllBtnAuth = x => allBtns = x;
19
+const setUserBtnAuth = x => current = x;
20
+
21
+export default AuthButton;
22
+export {
23
+  setAllBtnAuth,
24
+  setUserBtnAuth,
25
+};

+ 16
- 10
src/components/EchartsTest/EChart.jsx Vedi File

@@ -3,17 +3,20 @@ import React, { Component } from 'react';
3 3
 // 引入 ECharts 主模块
4 4
 import echarts from 'echarts/lib/echarts';
5 5
 // 引入柱状图
6
-import  'echarts/lib/chart/bar';
6
+import 'echarts/lib/chart/bar';
7
+import 'echarts/lib/chart/pie';
7 8
 // 引入提示框和标题组件
8 9
 import 'echarts/lib/component/tooltip';
10
+import 'echarts/lib/component/legend';
9 11
 import 'echarts/lib/component/title';
10 12
 
13
+
11 14
 class EchartsTest extends Component {
12
-    chartRef = undefined
15
+    chartRef = React.createRef();
13 16
     chart = undefined
14 17
     defaultChartOption = {}
15 18
 
16
-    componentDidMount() {
19
+    componentDidMount () {
17 20
         this.chart = echarts.init(this.chartRef.current)
18 21
 
19 22
         // 绘制图表
@@ -23,25 +26,28 @@ class EchartsTest extends Component {
23 26
         });
24 27
     }
25 28
 
26
-    componentDidUpdate(preProps) {
29
+    componentDidUpdate (preProps) {
27 30
         if (preProps.options != this.props.options) {
28
-            this.chart.setOption({
31
+            const options = {
29 32
                 ...this.defaultChartOption,
30 33
                 ...this.props.options || {},
31
-            });
34
+            }
35
+
36
+            console.log(options)
37
+
38
+            this.chart.setOption(options);
32 39
         }
33 40
     }
34 41
 
35
-    handleDom = ref => this.chartRef = ref
36
-
37
-    render() {
42
+    render () {
38 43
         const style = {
39 44
             width: '600px',
45
+            height: '400px',
40 46
             ...this.props.style || {}
41 47
         }
42 48
 
43 49
         return (
44
-            <div ref={this.handleDom} style={style}></div>
50
+            <div ref={this.chartRef} style={style}></div>
45 51
         );
46 52
     }
47 53
 }

+ 41
- 35
src/components/XForm/ImageListUpload.jsx Vedi File

@@ -3,71 +3,77 @@ import { Upload, Icon, Modal } from 'antd';
3 3
 import './style.less';
4 4
 import { uploaderProps } from '../../utils/upload';
5 5
 
6
-function getBase64(file) {
7
-  return new Promise((resolve, reject) => {
8
-    const reader = new FileReader();
9
-    reader.readAsDataURL(file);
10
-    reader.onload = () => resolve(reader.result);
11
-    reader.onerror = error => reject(error);
12
-  });
13
-}
14
-
15 6
 class ImageListUpload extends React.Component {
16 7
   state = {
17 8
     previewVisible: false,
18 9
     previewImage: '',
19
-    fileList: [],
10
+    loadding: false,
20 11
   };
21 12
 
13
+  getFileList = () => {
14
+    return (this.props.value || []).map((img, inx) => ({ uid: inx, url: img, status: 'done' }))
15
+  }
16
+
22 17
   handleCancel = () => this.setState({ previewVisible: false });
23 18
 
24 19
   handlePreview = async file => {
25
-    if (!file.url && !file.preview) {
26
-      file.preview = await getBase64(file.originFileObj);
27
-    }
28
-
29 20
     this.setState({
30
-      previewImage: file.url || file.preview,
21
+      previewImage: file.url ,
31 22
       previewVisible: true,
32 23
     });
33 24
   };
34 25
 
35
-  handleChange = ({ fileList }) => {
36
-    this.setState({ fileList })
37
-    console.log(fileList)
38
-    if (typeof this.props.onChange === 'function') {
39
-      // return item.response.url
40
-      const images = fileList.filter(item => item.status === 'done')
41
-      console.log(images)
42
-      this.props.onChange(images.map(item => item.response.url))
26
+  handleChange = (e) => {
27
+    if (e.file.status === "uploading") {
28
+      this.setState({ loading: true });
29
+      return;
43 30
     }
44
-  };
45 31
 
46
-  render() {
47
-    const { previewVisible, previewImage, fileList } = this.state;
32
+    if (e.file.state === 'removed') {
33
+      const fileList = (this.props.value || []).filter(x => x != e.file.url);
34
+      this.props.onChange(fileList);
35
+    }
36
+
37
+    // if (e.file.status === "done") {
38
+    //   this.setState({
39
+    //     loading: false,
40
+    //   })
41
+
42
+    //   if (e.file.response && e.file.response.url) {
43
+    //     if (typeof this.props.onChange === 'function') {
44
+    //       const fileList = this.getFileList()
45
+    //       this.props.onChange([...fileList || [], e.file.response.url]);
46
+    //     }
47
+    //   }
48
+    // }
49
+  };
48 50
 
49
-    const { value } = this.props
50
-    let images = []
51
-    if (value !== undefined && value !== null) {
52
-      // ?x-oss-process=style/thumbnail
53
-      images = value.map(item => ({ response: { url: item, thumbUrl: item, status: 'done' } }))
51
+  handleUploadSucess = (url) => {
52
+    this.setState({ loading: false });
53
+    if (typeof this.props.onChange === 'function') {
54
+      const fileList = this.props.value || [];
55
+      this.props.onChange([...fileList, url]);
54 56
     }
55
-    console.log('imageList: ', images)
57
+  }
58
+
59
+  render() {
60
+    const { previewVisible, previewImage } = this.state;
61
+    const fileList = this.getFileList();
56 62
 
57 63
     const uploadButton = (
58 64
       <div>
59
-        <Icon type="plus" />
60
-        <div className="ant-upload-text">Upload</div>
65
+        <Icon style={{ fontSize: '2em', color: '#aaa' }} type={this.state.loading ? "loading" : "plus"}  />
61 66
       </div>
62 67
     );
63 68
     return (
64 69
       <div className="clearfix">
65 70
         <Upload
66 71
           listType="picture-card"
67
-          fileList={fileList || images}
72
+          fileList={fileList}
68 73
           onPreview={this.handlePreview}
69 74
           onChange={this.handleChange}
70 75
           { ...uploaderProps }
76
+          onSuccess={this.handleUploadSucess}
71 77
         >
72 78
           {(fileList || images).length >= 8 ? null : uploadButton}
73 79
         </Upload>

+ 25
- 14
src/components/XForm/ImageUpload.jsx Vedi File

@@ -16,24 +16,35 @@ class ImageUpload extends React.Component {
16 16
       this.setState({ loading: true });
17 17
       return;
18 18
     }
19
+    
20
+    if (e.file.state === 'removed') {
21
+      this.props.onChange();
22
+    }
19 23
 
20
-    if (info.file.status === "done") {
21
-      this.setState({
22
-        loading: false,
23
-      })
24
+    // if (info.file.status === "done") {
25
+    //   this.setState({
26
+    //     loading: false,
27
+    //   })
24 28
 
25
-      if (info.file.response && info.file.response.url) {
26
-        this.setState({
27
-          imageUrl: info.file.response.thumbUrl,
28
-        });
29
+    //   if (info.file.response && info.file.response.url) {
30
+    //     this.setState({
31
+    //       imageUrl: info.file.response.thumbUrl,
32
+    //     });
29 33
 
30
-        if (typeof this.props.onChange === 'function') {
31
-          this.props.onChange(info.file.response.url);
32
-        }
33
-      }
34
-    }
34
+    //     if (typeof this.props.onChange === 'function') {
35
+    //       this.props.onChange(info.file.response.url);
36
+    //     }
37
+    //   }
38
+    // }
35 39
   };
36 40
 
41
+  handleUploadSucess = (url) => {
42
+    this.setState({ loading: false });
43
+    if (typeof this.props.onChange === 'function') {
44
+      this.props.onChange(url);
45
+    }
46
+  }
47
+
37 48
   render() {
38 49
     const uploadButton = (
39 50
       <div>
@@ -50,8 +61,8 @@ class ImageUpload extends React.Component {
50 61
         showUploadList={false}
51 62
         beforeUpload={this.props.beforeUpload}
52 63
         onChange={this.handleChange}
53
-
54 64
         {...uploaderProps}
65
+        onSuccess={this.handleUploadSucess}
55 66
       >
56 67
         {(this.state.imageUrl || value) ? (
57 68
           <img src={this.state.imageUrl || value} alt="avatar" style={{ width: "100%" }} />

+ 90
- 59
src/global.less Vedi File

@@ -23,6 +23,7 @@ body {
23 23
   text-rendering: optimizeLegibility;
24 24
   -webkit-font-smoothing: antialiased;
25 25
   -moz-osx-font-smoothing: grayscale;
26
+  font-size: 16px;
26 27
 }
27 28
 
28 29
 ul,
@@ -47,77 +48,107 @@ ol {
47 48
   }
48 49
 }
49 50
 
50
-.ant-pro-global-header{
51
+.ant-layout-header .ant-pro-global-header{
51 52
   background:#393C39;
52 53
 }
53
-.ant-pro-sider-menu-sider.light .ant-pro-sider-menu-logo{
54
+.ant-layout .ant-pro-sider-menu-sider.light .ant-pro-sider-menu-logo{
54 55
   background:#EF273A;
55 56
   box-shadow: none;
56 57
   border: none;
57
-}
58
-.ant-input-affix-wrapper .ant-input-prefix{
59
-  left:7px;
60
-}
61
-.ant-input-affix-wrapper .ant-input:not(:first-child) {
62
-  padding-left: 40px;
63
-}
64
-.ant-pro-global-header-trigger{
65
-  display: none;
66
-}
67
-.ant-pro-sider-menu-sider.light{
68
-  box-shadow: none;
69
-  .ant-pro-sider-menu-logo h1{
70
-    color: #fff;
58
+  a{
59
+    h1{
60
+      color: #fff;
61
+    }
71 62
   }
72 63
 }
73
-.ant-pro-page-header-wrap-page-header-warp{
74
-  background:rgba(240,240,240,1);
75
-}
76
-.ant-menu:not(.ant-menu-horizontal) .ant-menu-item-selected{
77
-  background:rgb(230, 227, 227);
78
-  border: none;
79
-}
80
-.ant-menu-inline .ant-menu-selected::after, .ant-menu-inline .ant-menu-item-selected::after{
81
-  opacity: 0;
64
+.antd-pro-layouts-user-layout-container{
65
+  .ant-input-affix-wrapper .ant-input-prefix{
66
+    left:7px;
67
+  }
68
+  .ant-input-affix-wrapper .ant-input:not(:first-child) {
69
+    padding-left: 40px;
70
+  }
82 71
 }
83
-.ant-menu-inline > .ant-menu-item{
84
-  height: 45px;
85
-  line-height: 45px;
72
+ 
73
+.ant-layout{
74
+  .ant-menu-vertical .ant-menu-item,
75
+.ant-menu-vertical-left .ant-menu-item,
76
+.ant-menu-vertical-right .ant-menu-item,
77
+.ant-menu-inline .ant-menu-item,
78
+.ant-menu-vertical .ant-menu-submenu-title,
79
+.ant-menu-vertical-left .ant-menu-submenu-title,
80
+.ant-menu-vertical-right .ant-menu-submenu-title,
81
+.ant-menu-inline .ant-menu-submenu-title,
82
+.ant-input ,.ant-btn{
86 83
   font-size: 16px;
87
-  margin: 0;
88
-}
89
-.ant-menu.ant-pro-sider-menu{
90
-  padding: 0!important;
91
-}
92
-
93
-.ant-breadcrumb + .ant-page-header-heading{
94
-  display: none;
95 84
 }
96
-.ant-page-header{
97
-  height: 50px;
98
-  padding:0 30px;
99
-  line-height: 50px;
85
+.ant-breadcrumb{
86
+  font-size: 16px;
87
+  .anticon {
88
+    font-size: 16px;
89
+  }
90
+} 
91
+  .ant-pro-global-header-trigger{
92
+    display: none;
93
+  }
94
+  .ant-pro-sider-menu-sider.light{
95
+    box-shadow: none;
96
+    .ant-pro-sider-menu-logo h1{
97
+      color: #fff;
98
+    }
99
+  }
100
+  .ant-pro-page-header-wrap-page-header-warp{
101
+    background:rgba(240,240,240,1);
102
+  }
103
+   .ant-menu:not(.ant-menu-horizontal)  .ant-menu-item-selected{
104
+    background:rgb(230, 227, 227)!important;
105
+    border: none!important;
106
+  }
107
+  .ant-menu-inline .ant-menu-selected::after, .ant-menu-inline .ant-menu-item-selected::after{
108
+    opacity: 0;
109
+  }
110
+  .ant-menu-inline > .ant-menu-item{
111
+    height: 45px;
112
+    line-height: 45px;
113
+    
114
+    margin: 0;
115
+    .ant-menu-submenu-title{
116
+      font-size: 16px!important;
117
+    }
118
+  }
119
+  .ant-menu.ant-pro-sider-menu{
120
+    padding: 0!important;
121
+  }
100 122
   
101
-  .ant-breadcrumb{
102
-    color: #333;
123
+  .ant-breadcrumb + .ant-page-header-heading{
124
+    display: none;
103 125
   }
104
-}
105
-.ant-pro-sider-menu-logo img{
106
-  height: 41px;
107
-}
108
-.ant-tabs.ant-tabs-card .ant-tabs-card-bar .ant-tabs-tab-active {
109
-  color: #FF7E48;
110
-}
111
-.ant-table{
112
-  line-height: 3;
113
-}
114
-.ant-modal-header{
115
-  border-bottom: none;
116
-  .ant-modal-title{
117
-    font-size: 24px;
126
+  .ant-page-header{
127
+    height: 50px;
128
+    padding:0 30px;
118 129
     line-height: 50px;
130
+    
131
+    .ant-breadcrumb{
132
+      color: #333;
133
+    }
134
+  }
135
+  .ant-pro-sider-menu-logo img{
136
+    height: 41px;
137
+  }
138
+  .ant-tabs.ant-tabs-card .ant-tabs-card-bar .ant-tabs-tab-active {
139
+    color: #FF7E48;
140
+  }
141
+  .ant-table{
142
+    line-height: 3;
143
+  }
144
+  .ant-modal-header{
145
+    border-bottom: none;
146
+    .ant-modal-title{
147
+      font-size: 24px;
148
+      line-height: 50px;
149
+    }
150
+  }
151
+  .ant-modal-footer{
152
+    border-top:none;
119 153
   }
120 154
 }
121
-.ant-modal-footer{
122
-  border-top:none;
123
-}

+ 32
- 23
src/layouts/BasicLayout.jsx Vedi File

@@ -6,24 +6,17 @@
6 6
 import ProLayout from '@ant-design/pro-layout';
7 7
 import React, { useEffect } from 'react';
8 8
 import Link from 'umi/link';
9
+import Redirect from 'umi/redirect';
9 10
 import { connect } from 'dva';
10 11
 import { formatMessage } from 'umi-plugin-react/locale';
11
-import Authorized from '@/utils/Authorized';
12
+// import Authorized from '@/utils/Authorized';
12 13
 import RightContent from '@/components/GlobalHeader/RightContent';
14
+import RenderAuthorize from '@/components/Authorized';
13 15
 import { isAntDesignPro } from '@/utils/utils';
14 16
 import logo from '../assets/logo.png';
15
-
16
-/**
17
- * use Authorized check all menu item
18
- */
19
-const menuDataRender = menuList =>
20
-  menuList.map(item => {
21
-    const localItem = { ...item, children: item.children ? menuDataRender(item.children) : [] };
22
-    return Authorized.check(item.authority, localItem, null);
23
-  });
17
+  
24 18
 const footerRender = () => {
25 19
   return (
26
-
27 20
     <div
28 21
       style={{
29 22
         padding: ' 44px 0',
@@ -32,22 +25,18 @@ const footerRender = () => {
32 25
         fontFamily: 'monospace',
33 26
         fontWeight: '200',
34 27
         color: 'rgba(102, 102, 102, 1)',
35
-    
36
-
37 28
       }}
38 29
     >
39 30
       copy Right @ 知与行
40 31
     </div>
41 32
   )
42 33
 }
34
+
43 35
 const BasicLayout = props => {
44 36
   const { dispatch, children, settings } = props;
45
-  /**
46
-   * constructor
47
-   */
48
-
37
+  
49 38
   useEffect(() => {
50
-    if (dispatch) {
39
+    if (dispatch && !props.user.currentUser.userId) {
51 40
       dispatch({
52 41
         type: 'user/fetchCurrent',
53 42
       });
@@ -56,9 +45,8 @@ const BasicLayout = props => {
56 45
       });
57 46
     }
58 47
   }, []);
59
-  /**
60
-   * init variables
61
-   */
48
+  
49
+  const Authorized = RenderAuthorize(props.user.currentUser.roles)
62 50
 
63 51
   const handleMenuCollapse = payload => {
64 52
     if (dispatch) {
@@ -69,6 +57,26 @@ const BasicLayout = props => {
69 57
     }
70 58
   };
71 59
 
60
+  const findAuthority = (path) => {
61
+    return ((props.user.menuList || []).filter(x => x.code === path)[0] || {}).roles
62
+  }
63
+  
64
+  /**
65
+   * use Authorized check all menu item
66
+   */
67
+  const menuDataRender = menuList =>
68
+    menuList.map(item => {
69
+      const localItem = { ...item, children: item.children ? menuDataRender(item.children) : [] };
70
+      const authority = findAuthority(item.path);
71
+      // return Authorized.check(item.authority, localItem, null);
72
+      return Authorized.check(authority, localItem, null);
73
+    });
74
+
75
+  const checkRights = (children) => {
76
+    const authority = findAuthority(props.location.pathname);
77
+    return Authorized.check(authority, children, <Redirect to="/exception/403" />);
78
+  }
79
+
72 80
   return (
73 81
     <ProLayout
74 82
       logo={logo}
@@ -106,12 +114,13 @@ const BasicLayout = props => {
106 114
       {...settings}
107 115
     // pageTitleRender={()=><></>}
108 116
     >
109
-      {children}
117
+      {checkRights(children)}
110 118
     </ProLayout>
111 119
   );
112 120
 };
113 121
 
114
-export default connect(({ global, settings }) => ({
122
+export default connect(({ global, settings, user }) => ({
115 123
   collapsed: global.collapsed,
116 124
   settings,
125
+  user
117 126
 }))(BasicLayout);

+ 11
- 4
src/models/login.js Vedi File

@@ -1,8 +1,13 @@
1 1
 import { routerRedux } from 'dva/router';
2 2
 import { stringify } from 'querystring';
3
-import { fakeAccountLogin, getFakeCaptcha } from '@/services/login';
3
+// import { fakeAccountLogin, getFakeCaptcha } from '@/services/login';
4 4
 import { setAuthority } from '@/utils/authority';
5 5
 import { getPageQuery } from '@/utils/utils';
6
+import { fetch, apis } from '@/utils/request';
7
+
8
+const signin = fetch(apis.user.signin);
9
+const signout = fetch(apis.user.signout);
10
+
6 11
 const Model = {
7 12
   namespace: 'login',
8 13
   state: {
@@ -10,7 +15,7 @@ const Model = {
10 15
   },
11 16
   effects: {
12 17
     *login({ payload }, { call, put }) {
13
-      const response = yield call(fakeAccountLogin, payload);
18
+      const response = yield call(signin, { data: payload });
14 19
       yield put({
15 20
         type: 'changeLoginStatus',
16 21
         payload: response,
@@ -42,9 +47,11 @@ const Model = {
42 47
       yield call(getFakeCaptcha, payload);
43 48
     },
44 49
 
45
-    *logout(_, { put }) {
50
+    *logout(_, { put, call }) {
46 51
       const { redirect } = getPageQuery(); // redirect
47 52
 
53
+      yield call(signout, { logout: true });
54
+
48 55
       if (window.location.pathname !== '/user/login' && !redirect) {
49 56
         yield put(
50 57
           routerRedux.replace({
@@ -59,7 +66,7 @@ const Model = {
59 66
   },
60 67
   reducers: {
61 68
     changeLoginStatus(state, { payload }) {
62
-      setAuthority((payload.user.roles || []).map(x => x.roleId));
69
+      // setAuthority((payload.user.roles || []).map(x => x.roleId));
63 70
       return { ...state, status: 'ok', type: payload.type };
64 71
     },
65 72
   },

+ 14
- 5
src/models/user.js Vedi File

@@ -1,11 +1,14 @@
1
-import request from '../utils/request';
2
-import apis from '../services/apis';
1
+import { fetch, apis } from '@/utils/request';
2
+import { setAllBtnAuth, setUserBtnAuth } from '@/components/AuthButton';
3
+
4
+const getCurrentUser = fetch(apis.user.current)
3 5
 
4 6
 const UserModel = {
5 7
   namespace: 'user',
6 8
   state: {
7 9
     currentUser: {},
8 10
     menuList: [],
11
+    buttonList: [],
9 12
   },
10 13
   effects: {
11 14
     // *fetch(_, { call, put }) {
@@ -17,7 +20,7 @@ const UserModel = {
17 20
     // },
18 21
 
19 22
     *fetchCurrent(_, { call, put }) {
20
-      const response = yield call(request, apis.user.current);
23
+      const response = yield call(getCurrentUser);
21 24
 
22 25
       yield put({
23 26
         type: 'saveCurrentUser',
@@ -26,8 +29,14 @@ const UserModel = {
26 29
     },
27 30
   },
28 31
   reducers: {
29
-    saveCurrentUser(state, { payload = {} }) {
30
-      return { ...state, currentUser: payload.taUser || {}, menuList: payload.menuList || [] };
32
+    saveCurrentUser(state, { payload }) {
33
+      const { taUser = {} , menuList = [], buttonList = [] } = payload || {}
34
+      const currentUser = { ...taUser, roles: (taUser.roles || []).map(x => x.roleId) }
35
+
36
+      setAllBtnAuth(buttonList)
37
+      setUserBtnAuth(currentUser.roles)
38
+
39
+      return { ...state, currentUser, menuList, buttonList };
31 40
     },
32 41
     changeNotifyCount(
33 42
       state = {

+ 1
- 1
src/pages/activity/ActivityList.jsx Vedi File

@@ -250,7 +250,7 @@ const handleSubmit = (e, props) => {
250 250
           </Button>
251 251
         </Form.Item>
252 252
       </Form>
253
-      <Button type="primary" className={styles.addBtn} onClick={toEditGoods()}>新增</Button>
253
+      <Button type="danger" className={styles.addBtn} onClick={toEditGoods()}>新增</Button>
254 254
       <Table dataSource={data.list} columns={columns} pagination={false}/>
255 255
       <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
256 256
         <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={changePageNum} />

+ 109
- 15
src/pages/activity/editActivity.jsx Vedi File

@@ -26,8 +26,7 @@ const { TextArea } = Input;
26 26
  * @returns
27 27
  */
28 28
 const Edit = (props) => {
29
-  const [tab, changeTab] = useState('poster')
30
-  // const [tab, changeTab] = useState('basic')
29
+  const [tab, changeTab] = useState('basic')
31 30
   const dynamicId = props.location.query.dynamicId
32 31
   const [dynamicData, setDynamicData] = useState({})
33 32
   if (dynamicId) {
@@ -149,6 +148,7 @@ const Edit = (props) => {
149 148
           method: 'PUT',
150 149
           data: submitValue,
151 150
         }).then((data) => {
151
+          message.info("保存成功")
152 152
           cancelPage()
153 153
         }).catch((err) => {
154 154
           message.info(err.msg || err.message)
@@ -159,6 +159,7 @@ const Edit = (props) => {
159 159
           method: 'POST',
160 160
           data: submitValue,
161 161
         }).then((data) => {
162
+          message.info("保存成功")
162 163
           cancelPage()
163 164
         }).catch((err) => {
164 165
           message.info(err.msg || err.message)
@@ -173,6 +174,57 @@ const Edit = (props) => {
173 174
     const [inputValue, changeInput] = useState('')
174 175
     const [textAreaValue, changeTextArea] = useState('')
175 176
     const [imgValue, changeImg] = useState('')
177
+    const [posterId, setPosterId] = useState('')
178
+
179
+    if(dynamicId){
180
+      useEffect(() => {
181
+        request({
182
+          url: '/api/admin/poster',
183
+          method: 'GET',
184
+          params: {targetId: dynamicId,targetType: 'activity'},
185
+        }).then((data) => {
186
+          console.log(data,"2222")
187
+          if(data.length > 0){
188
+            setPosterId(data[0].posterId)
189
+            changeImg(data[0].posterImg)
190
+            changeTextArea(data[0].posterDescription)
191
+            changeInput(data[0].posterTitle)
192
+          }
193
+        }).catch((err) => {
194
+          message.info(err.msg || err.message)
195
+        })
196
+      }, [])
197
+    }
198
+
199
+    const submitPoster  = () => {
200
+       if(dynamicId){
201
+        if(posterId){
202
+          request({
203
+            url: '/api/admin/poster/'+posterId,
204
+            method: 'PUT',
205
+            data: {targetId: dynamicId,targetType: 'activity',posterImg: imgValue,posterTitle: inputValue,posterDescription: textAreaValue},
206
+          }).then((data) => {
207
+            message.info("保存成功")
208
+          }).catch((err) => {
209
+            message.info(err.msg || err.message)
210
+          })
211
+         }else{
212
+          request({
213
+            url: '/api/admin/poster',
214
+            method: 'POST',
215
+            data: {targetId: dynamicId,targetType: 'activity',posterImg: imgValue,posterTitle: inputValue,posterDescription: textAreaValue},
216
+          }).then((data) => {
217
+            setPosterId(data.posterId)
218
+            message.info("保存成功")
219
+          }).catch((err) => {
220
+            message.info(err.msg || err.message)
221
+          })
222
+         }
223
+       }else{
224
+        message.warn("请先保存基本信息数据")
225
+       }
226
+    }
227
+
176 228
     return <div>
177 229
       <div style={{ display: 'flex' }}>
178 230
         <div style={{ width: '420px', height: '900px', display: 'inline-block', marginTop: '30px' }}>
@@ -210,20 +262,20 @@ const Edit = (props) => {
210 262
         <div >
211 263
           <div style={{ display: 'flex', width: '100%', margin: '60px 0' }}>
212 264
             <p style={{ minWidth: '200px', color: '#222', textAlign: 'right', margin: '0 30px 0 0' }}>海报图片</p>
213
-            <ImageUploader onChange={e => changeImg(e)} />
265
+            <ImageUploader value={imgValue} onChange={e => changeImg(e)} />
214 266
           </div>
215 267
           <div style={{ display: 'flex', alignItems: 'center', width: '100%', marginBottom: '60px' }}>
216 268
             <p style={{ minWidth: '200px', color: '#222', textAlign: 'right', margin: '0 30px 0 0' }}>海报标题</p>
217
-            <Input style={{ width: '20vw' }} placeholder="请输入海报标题" onChange={e => changeInput(e.target.value)} />
269
+            <Input style={{ width: '20vw' }} value={inputValue} placeholder="请输入海报标题" onChange={e => changeInput(e.target.value)} />
218 270
           </div>
219 271
           <div style={{ display: 'flex', margin: '10px 0 40px 0', width: '100%' }}>
220 272
             <p style={{ minWidth: '200px', color: '#222', textAlign: 'right', margin: '0 30px 0 0' }}>海报描述</p>
221
-            <TextArea rows={5} onChange={e => changeTextArea(e.target.value)} />
273
+            <TextArea rows={5} value={textAreaValue} onChange={e => changeTextArea(e.target.value)} />
222 274
           </div>
223 275
 
224 276
         </div>
225 277
       </div>
226
-      <Button type="primary" onClick={() => router.go(-1)} style={{ margin: '40px 40px 40px 30vw' }}> 确定</Button>
278
+      <Button type="primary" onClick={submitPoster} style={{ margin: '40px 40px 40px 30vw' }}> 确定</Button>
227 279
       <Button onClick={() => router.go(-1)}>取消</Button>
228 280
     </div>
229 281
 
@@ -234,13 +286,55 @@ const Edit = (props) => {
234 286
   const Share = (props) => {
235 287
     const [inputValue, changeInput] = useState('')
236 288
     const [imgValue, changeImg] = useState('')
237
-    // const changeInputValue = e => {
238
-    //   changeInput(e.target.value)
239
-    // }
240
-
241
-    // const handleSubmit = (values) => {
289
+    const [shareContentId, setShareContentId] = useState('')
290
+    
291
+    if(dynamicId){
292
+      useEffect(() => {
293
+        request({
294
+          url: '/api/admin/shareContent',
295
+          method: 'GET',
296
+          params: {targetId: dynamicId,targetType: 'activity'},
297
+        }).then((data) => {
298
+          console.log(data,"2222")
299
+          if(data.length > 0){
300
+            setShareContentId(data[0].shareContentId)
301
+            changeImg(data[0].shareContentImg)
302
+            changeInput(data[0].shareContentTitle)
303
+          }
304
+        }).catch((err) => {
305
+          message.info(err.msg || err.message)
306
+        })
307
+      }, [])
308
+    }
242 309
 
243
-    // }
310
+    const submitShare = () => {
311
+      if(dynamicId){
312
+        if(shareContentId){
313
+          request({
314
+            url: '/api/admin/shareContent/'+shareContentId,
315
+            method: 'PUT',
316
+            data: {targetId: dynamicId,shareContentType: 'activity',shareContentImg: imgValue,shareContentTitle: inputValue},
317
+          }).then((data) => {
318
+            message.info("保存成功")
319
+          }).catch((err) => {
320
+            message.info(err.msg || err.message)
321
+          })
322
+         }else{
323
+          request({
324
+            url: '/api/admin/shareContent',
325
+            method: 'POST',
326
+            data: {targetId: dynamicId,shareContentType: 'activity',shareContentImg: imgValue,shareContentTitle: inputValue},
327
+          }).then((data) => {
328
+            setShareContentId(data.shareContentId)
329
+            message.info("保存成功")
330
+          }).catch((err) => {
331
+            message.info(err.msg || err.message)
332
+          })
333
+         }
334
+       }else{
335
+        message.warn("请先保存基本信息数据")
336
+       }
337
+    }
244 338
 
245 339
     return <div style={{ padding: '20px' }}>
246 340
       <div style={{ display: 'flex', margin: '10px 0 40px 0', width: '100%' }}>
@@ -253,13 +347,13 @@ const Edit = (props) => {
253 347
       </div>
254 348
       <div style={{ display: 'flex', alignItems: 'center', width: '100%' }}>
255 349
         <p style={{ minWidth: '200px', color: '#222', textAlign: 'right', margin: '0 30px 0 0' }}>海报标题</p>
256
-        <Input placeholder="请输入海报标题" onChange={e => changeInput(e.target.value)} />
350
+        <Input placeholder="请输入海报标题" value={inputValue} onChange={e => changeInput(e.target.value)} />
257 351
       </div>
258 352
       <div style={{ display: 'flex', width: '100%', marginTop: '40px' }}>
259 353
         <p style={{ minWidth: '200px', color: '#222', textAlign: 'right', margin: '0 30px 0 0' }}>分享图片</p>
260
-        <ImageUploader onChange={e => changeImg(e)} />
354
+        <ImageUploader value={imgValue} onChange={e => changeImg(e)} />
261 355
       </div>
262
-      <Button type="primary" htmlType="submit" style={{ margin: '40px 40px 40px 220px' }}> 确定</Button>
356
+      <Button type="primary" htmlType="submit" onClick={submitShare} style={{ margin: '40px 40px 40px 220px' }}> 确定</Button>
263 357
       <Button onClick={() => router.go(-1)}>取消</Button>
264 358
     </div>
265 359
   }

+ 59
- 55
src/pages/building/list/index.jsx Vedi File

@@ -5,6 +5,7 @@ import request from '../../../utils/request';
5 5
 import apis from '../../../services/apis';
6 6
 import Styles from './style.less';
7 7
 import { router } from 'umi';
8
+import AuthButton from '@/components/AuthButton';
8 9
 
9 10
 
10 11
 const { Option } = Select;
@@ -100,56 +101,56 @@ function CartBody(props) {
100 101
   }
101 102
 
102 103
   return (
103
-          <Card
104
-            hoverable
105
-            style={{ minWidth: '400px', borderRadius: '12px', margin: '10px', boxShadow: '0px 0px 16px 2px rgba(0,0,0,0.12)' }}
106
-            cover={<img alt="example" src={ data.poster } style={{ borderRadius: '12px 12px 0 0', width: '100%', height: '14vw' }}></img>}
107
-            bodyStyle={{ padding: '10px 20px' }}
108
-          >
109
-            <p className={Styles.cardText}>
110
-              <span className={Styles.title}>楼盘编号</span>
111
-              <span >:{ data.code }</span>
112
-              <span className={Styles.ediText} onClick={() => toEdi(data)}>
113
-                编辑
104
+    <Card
105
+      hoverable
106
+      style={{ minWidth: '400px', borderRadius: '12px', margin: '10px', boxShadow: '0px 0px 16px 2px rgba(0,0,0,0.12)' }}
107
+      cover={<img alt="example" src={data.poster} style={{ borderRadius: '12px 12px 0 0', width: '100%', height: '14vw' }}></img>}
108
+      bodyStyle={{ padding: '10px 20px' }}
109
+    >
110
+      <p className={Styles.cardText}>
111
+        <span className={Styles.title}>楼盘编号</span>
112
+        <span >:{data.code}</span>
113
+        <span className={Styles.ediText} onClick={() => toEdi(data)}>
114
+          编辑
114 115
                 <Icon type="form" style={{ color: '#C0C4CC', marginLeft: '10px' }} />
115
-              </span>
116
-            </p>
117
-            <p className={Styles.cardText}>
118
-              <span className={Styles.title}>楼盘名称</span>
119
-              <span >:{ data.name }</span>
120
-            </p>
121
-            <p className={Styles.cardItem}>
122
-              <span className={Styles.title}>均价</span>
123
-              <span >
124
-                :约<span style={{ color: '#FF0707', fontSize: '20px' }}> { data.price } </span>元/m
125 116
         </span>
126
-            </p>
127
-            <p className={Styles.cardItem}>
128
-              <span className={Styles.title}>项目地址</span>
129
-              <span className={ Styles.address }>:{ data.address }</span>
130
-            </p>
131
-            <p className={Styles.cardItem}>
132
-              <span className={Styles.title}>发布状态</span>
133
-              <span >:{ data.status === 1 ? '已发布' : '未发布' }</span>
134
-            </p>
135
-            <p className={Styles.cardItem}>
136
-              <span className={Styles.title}>录入时间</span>
137
-              <span >:{ data.createDate }</span>
138
-            </p>
139
-            <p style={{ margin: '15px 0', position: 'relative', fontSize: '18px' }}>
140
-              <span style={{ color: '#1990FF' }} onClick={() => pulicAndUnPulic(data)}>
141
-                {/* 已发布的时候,需要显示取消发布的字样 */}
142
-                { data.status === 1 ? '取消发布' : '发布' }
143
-                <Icon type="close-circle" style={{ color: '#C0C4CC', marginLeft: '8px' }} />
144
-              </span>
145
-              <span style={{
146
-                color: '#FF4A4A', position: 'absolute', right: '0',
147
-              }} onClick={() => deleteBuilding(data)}>
148
-                删除
117
+      </p>
118
+      <p className={Styles.cardText}>
119
+        <span className={Styles.title}>楼盘名称</span>
120
+        <span >:{data.name}</span>
121
+      </p>
122
+      <p className={Styles.cardItem}>
123
+        <span className={Styles.title}>均价</span>
124
+        <span >
125
+          :约<span style={{ color: '#FF0707', fontSize: '20px' }}> {data.price} </span>元/m
126
+        </span>
127
+      </p>
128
+      <p className={Styles.cardItem}>
129
+        <span className={Styles.title}>项目地址</span>
130
+        <span className={Styles.address}>:{data.address}</span>
131
+      </p>
132
+      <p className={Styles.cardItem}>
133
+        <span className={Styles.title}>发布状态</span>
134
+        <span >:{data.status === 1 ? '已发布' : '未发布'}</span>
135
+      </p>
136
+      <p className={Styles.cardItem}>
137
+        <span className={Styles.title}>录入时间</span>
138
+        <span >:{data.createDate}</span>
139
+      </p>
140
+      <p style={{ margin: '15px 0', position: 'relative', fontSize: '18px' }}>
141
+        <span style={{ color: '#FF4A4A' }} onClick={() => pulicAndUnPulic(data)}>
142
+          {/* 已发布的时候,需要显示取消发布的字样 */}
143
+          {data.status === 1 ? '取消发布' : '发布'}
144
+          <Icon type={data.status === 1 ? 'close-circle' : 'form'} style={{ color: '#C0C4CC', marginLeft: '8px' }} />
145
+        </span>
146
+        <span style={{
147
+          color: '#FF4A4A', position: 'absolute', right: '0',
148
+        }} onClick={() => deleteBuilding(data)}>
149
+          删除
149 150
                 <Icon type="rest" style={{ color: '#C0C4CC', marginLeft: '8px' }} />
150
-              </span>
151
-            </p>
152
-          </Card>
151
+        </span>
152
+      </p>
153
+    </Card>
153 154
   )
154 155
 }
155 156
 
@@ -209,7 +210,7 @@ function body(props) {
209 210
   // 分页
210 211
   function onChange(pageNumber) {
211 212
     // eslint-disable-next-line react-hooks/rules-of-hooks
212
-      getList({ pageNum: pageNumber, pageSize: 9 })
213
+    getList({ pageNum: pageNumber, pageSize: 9 })
213 214
   }
214 215
 
215 216
   function getDate(value, dateString) {
@@ -285,18 +286,21 @@ function body(props) {
285 286
           </Button>
286 287
         </Form.Item>
287 288
       </Form>
288
-      <Button type="danger" className={Styles.addButton} onClick={() => toAdd()}>
289
-        新增楼盘
290
-      </Button>
289
+
290
+      <AuthButton name="building.add" noRight={null}>
291
+        <Button type="danger" className={Styles.addButton} onClick={() => toAdd()}>
292
+          新增楼盘
293
+        </Button>
294
+      </AuthButton>
291 295
 
292 296
       {/* 卡片内容,显示楼盘项目  */}
293 297
       <Row style={{ padding: ' 0 10px' }}>
294 298
         {
295 299
           dataSource.records.map((item, _) => (
296
-              <Col span={8}>
297
-                <CartBody data={item} key={item.buildingId} onSuccess={getList}/>
298
-              </Col>
299
-            ))
300
+            <Col span={8}>
301
+              <CartBody data={item} key={item.buildingId} onSuccess={getList} />
302
+            </Col>
303
+          ))
300 304
         }
301 305
       </Row>
302 306
       {/* 分页 */}

+ 2
- 2
src/pages/building/type/index.jsx Vedi File

@@ -96,8 +96,8 @@ function body() {
96 96
 
97 97
   return (
98 98
     <>
99
-      <Button type="primary" className={Styles.addButton} onClick={() => toEdi()}>新增类型</Button>
100
-      <Table dataSource={data.records} columns={columns} pagination={false}/>
99
+      <Button type="danger" onClick={() => toEdi()}>新增类型</Button>
100
+      <Table style={{marginTop:'30px'}} dataSource={data.records} columns={columns} pagination={false}/>
101 101
       {/* 分页 */}
102 102
       <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
103 103
         <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={onChange} />

+ 1
- 1
src/pages/carouselFigure/advertisingList.jsx Vedi File

@@ -217,7 +217,7 @@ const handleSubmit = (e, props) => {
217 217
           </Button>
218 218
         </Form.Item>
219 219
       </Form>
220
-      <Button type="primary" className={styles.addBtn} onClick={toEdit()}>新增</Button>
220
+      <Button type="danger" className={styles.addBtn} onClick={toEdit()}>新增</Button>
221 221
       <Table dataSource={data.records} columns={columns} pagination={false}/>
222 222
       <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
223 223
         <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={changePageNum} />

+ 1
- 1
src/pages/carouselFigure/carouselFigureList.jsx Vedi File

@@ -217,7 +217,7 @@ const handleSubmit = (e, props) => {
217 217
           </Button>
218 218
         </Form.Item>
219 219
       </Form>
220
-      <Button type="primary" className={styles.addBtn} onClick={toEditCarouse()}>新增</Button>
220
+      <Button type="danger" className={styles.addBtn} onClick={toEditCarouse()}>新增</Button>
221 221
       <Table dataSource={data.records} columns={columns} pagination={false}/>
222 222
       <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
223 223
         <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={changePageNum} />

+ 1
- 1
src/pages/channel/brokerList.jsx Vedi File

@@ -166,7 +166,7 @@ return (
166 166
       {/* <Button onClick={() => refurbishList() }>重置</Button> */}
167 167
     </div>
168 168
     </div>
169
-    <Table dataSource={data.list} columns={columns} pagination={{ pageSize: 10, total: data.total, onChange }} />
169
+    <Table style={{marginTop:'40px'}} dataSource={data.list} columns={columns} pagination={{ pageSize: 10, total: data.total, onChange }} />
170 170
   </>
171 171
 )
172 172
 }

+ 2
- 2
src/pages/customer/customerlist/index.jsx Vedi File

@@ -248,8 +248,8 @@ function body(props) {
248 248
           )}
249 249
         </Form.Item>
250 250
         <Form.Item>
251
-          <Button type="danger" htmlType="submit" >
252
-            搜索
251
+          <Button type="primary" htmlType="submit" >
252
+            查询
253 253
           </Button>
254 254
         </Form.Item>
255 255
       </Form>

+ 1
- 1
src/pages/customer/report/index.jsx Vedi File

@@ -159,7 +159,7 @@ function body(props) {
159 159
           </Button>
160 160
         </Form.Item>
161 161
       </Form>
162
-      <Table dataSource={dataSource.records} columns={columns} pagination={{ total: dataSource.total, onChange }} />
162
+      <Table style={{marginTop:'40px'}} dataSource={dataSource.records} columns={columns} pagination={{ total: dataSource.total, onChange }} />
163 163
     </>
164 164
   );
165 165
 }

+ 180
- 0
src/pages/indexEcharts/components/UserSource.jsx Vedi File

@@ -0,0 +1,180 @@
1
+import React, { Component, useState, useEffect } from 'react';
2
+
3
+import EChart from '../../../components/EchartsTest/EChart';
4
+import request from '../../../utils/request';
5
+import apis from '../../../services/apis';
6
+import dayjs from 'dayjs';
7
+import router from 'umi/router';
8
+import {Table, Select, Row, Col, Menu, Dropdown, Button, Icon, message } from 'antd';
9
+// import UserSource from './mmm';
10
+
11
+
12
+const UserSource = (props) => {
13
+
14
+  const [data, setData] = useState({ records: [] })
15
+  //柱图
16
+
17
+  useEffect(() => {
18
+    userResource()
19
+  }, [])
20
+
21
+  function userResource () {
22
+    request({
23
+      ...apis.indexEcharts.userResource,
24
+      params: { pageNum: 1, pageSize: 9999 }
25
+    }).then((data) => {
26
+      // console.log(data , '3333')
27
+      setData(data)
28
+    })
29
+  }
30
+
31
+  function toEdit () {
32
+    router.push({
33
+      pathname: '/indexEcharts/userSource',
34
+      // query: {
35
+      //   a: 'b',
36
+      // },
37
+    });
38
+  }
39
+
40
+  const dataset = data || {};
41
+  const source = dataset.columnar || [];
42
+
43
+  // const source = this.dataset.columnar || [];
44
+  const subtitle = '最近7天';
45
+  const baroptions = {
46
+    color: ['#286DD0', '#8565CE', '#6A96F8', '#F5749E', '#8B7FE2'],
47
+    xAxis: { type: 'category' },
48
+    legend: {
49
+      left: '20%',
50
+      data: ['所有用户', '注册用户'],
51
+    },
52
+
53
+    tooltip: {},
54
+
55
+    yAxis: {},
56
+    series: [
57
+      { type: 'bar', name: '所有用户', datasetIndex: 0 },
58
+      { type: 'bar', name: '注册用户' },
59
+    ],
60
+    dataset: {
61
+      id: 'bar',
62
+      dimensions: ['fromName', 'userCount', 'registered'],
63
+      source: source,
64
+    },
65
+
66
+  }
67
+  const { person_estate_agent = 0, person_null = 0, person_realty_consultant = 0 } = dataset.pie || {};
68
+  const pieoptions = {
69
+    // xAxis: {},
70
+    color: ['#286DD0', '#8565CE', '#6A96F8', '#F5749E', '#8B7FE2'],
71
+    legend: {
72
+      // left: '70%',
73
+      data: ['来源置业顾问', '来源全民经纪人', '自主进入'],
74
+    },
75
+    tooltip: {},
76
+    // yAxis: {},
77
+
78
+    series: [
79
+      {
80
+        type: 'pie',
81
+        // datasetIndex: 1,
82
+        center: ['50%', '50%'],
83
+        radius: [0, '50%'],
84
+      },
85
+    ],
86
+    dataset: {
87
+      id: 'pie',
88
+      source: [
89
+        { form: '来源置业顾问', value: person_realty_consultant },
90
+        { form: '来源全民经纪人', value: person_estate_agent },
91
+        { form: '自主进入', value: person_null },
92
+      ]
93
+    },
94
+
95
+
96
+
97
+
98
+
99
+  }
100
+  function handleSelectChange (e) {
101
+    // eslint-disable-next-line no-console
102
+    console.log(e)
103
+  }
104
+
105
+  //表格
106
+  const dataSource = [
107
+    {
108
+      name: '置业顾问',
109
+      status: '1',//显示停用
110
+    },
111
+    {
112
+      name: '置业经理',
113
+      status: '1',//停用
114
+    },
115
+  ];
116
+
117
+  const columns = [
118
+    // {
119
+    //   title: '商品图片',
120
+    //   dataIndex: 'img',
121
+    //   key: 'img',
122
+    //   align: 'center',
123
+  
124
+    //   render: (text, record) => <img src={record.img} className={channels.touxiang} />,
125
+    // },
126
+    {
127
+      title: '角色名称',
128
+      dataIndex: 'name',
129
+      key: 'name',
130
+      align: 'center',
131
+      render: text => <a>{text}</a>,
132
+    },
133
+  
134
+    {
135
+      title: '操作  ',
136
+      dataIndex: 'status',
137
+      key: 'status',
138
+      align: 'center',
139
+  
140
+      render: () => <>11</>
141
+       
142
+    },
143
+  ];
144
+
145
+  const style = {
146
+    width: '100%',
147
+    height: '400px',
148
+
149
+  }
150
+  const styles = {
151
+    width: '100%',
152
+    height: '400px',
153
+
154
+  }
155
+
156
+
157
+  return (
158
+    <>
159
+      <div>
160
+        <h3>用户来源 <small>{subtitle}</small></h3>
161
+        <Row>
162
+          <Col span={16}>
163
+            <EChart options={baroptions} style={style} /></Col>
164
+          <Col span={8}>
165
+            <EChart options={pieoptions} style={styles} /></Col>
166
+        </Row>
167
+      </div>
168
+      <Select style={{ width: '180px' }} placeholder="所有用户" onChange={handleSelectChange}>
169
+        <Option value={0}>所有用户</Option>
170
+        <Option value={1}>注册用户</Option>
171
+      </Select>
172
+
173
+
174
+      <Table dataSource={dataSource} columns={columns} />
175
+
176
+    </>
177
+  )
178
+}
179
+
180
+export default UserSource;

+ 27
- 0
src/pages/indexEcharts/index.jsx Vedi File

@@ -0,0 +1,27 @@
1
+
2
+import React, { useState, useEffect }  from 'react';
3
+import { Form, Input, Button, Icon, Select, message, Table, Divider, Row, Col, Tag, Pagination, Modal, DatePicker } from 'antd';
4
+
5
+// import styles from '../../style/GoodsList.less';
6
+import router from 'umi/router';
7
+
8
+import request from '../../utils/request'
9
+import apis from '../../services/apis';
10
+// import Styles from './style.less';/
11
+import UserSource from './components/UserSource.jsx';
12
+
13
+
14
+const header = (props) => {
15
+
16
+
17
+  return (
18
+
19
+    <>
20
+    {/* <div>2222</div> */}
21
+     <UserSource  ></UserSource>
22
+    </>
23
+  )
24
+}
25
+
26
+
27
+export default  header

+ 77
- 0
src/pages/indexEcharts/userSource.jsx Vedi File

@@ -0,0 +1,77 @@
1
+import dayjs from 'dayjs';
2
+import React from 'react';
3
+import {Radio, DatePicker,  Form, Input, Button, Icon, Select, message, Table, Divider, Tag, Pagination, Modal, Breadcrumb } from 'antd';
4
+
5
+import UserSource from './components/UserSource.jsx';
6
+// import XForm, { FieldTypes } from '../../components/XForm';
7
+import moment from 'moment';
8
+
9
+
10
+const header = props => {
11
+  const { RangePicker } = DatePicker;
12
+  function onChange(dates, dateStrings) {
13
+    console.log('From: ', dates[0], ', to: ', dates[1]);
14
+    console.log('From: ', dateStrings[0], ', to: ', dateStrings[1]);
15
+  }
16
+
17
+
18
+  const handleSubmit = (e, props) => {
19
+    e.preventDefault();
20
+    // props.form.validateFields((err, values) => {
21
+    //   if (!err) {
22
+    //     getList({ pageNum: 1, pageSize: 10, ...values })
23
+    //   }
24
+    // });
25
+  }
26
+
27
+
28
+  function getDataOf(days){      
29
+    // const endDate = new Date()
30
+    // const startDate = dayjs().subtract(days, 'day').toDate()
31
+
32
+    // this.$refs.chart.getData({ startDate, endDate })
33
+  }
34
+
35
+  function onChange(e) {
36
+    console.log(`radio checked:${e.target.value}`);
37
+  }
38
+
39
+  return (<>
40
+  {/* <el-button type="text" @click="() => getDataOf(7)">最近7天</el-button>
41
+      <el-button type="text" @click="() => getDataOf(30)">最近1月</el-button>
42
+      <el-date-picker
43
+        v-model="dateRange"
44
+        type="daterange"
45
+        start-placeholder="开始日期"
46
+        end-placeholder="结束日期"
47
+        style="margin-left: 16px">
48
+      </el-date-picker>
49
+      <el-button type="primary" icon="el-icon-search" style="margin-left: 32px" @click="search">查询</el-button>
50
+    </div>
51
+    <user-source ref="chart" mode="all"></user-source> */}
52
+  <Radio.Group onChange={onChange} defaultValue="a">
53
+        <Radio.Button value="a" onClick={getDataOf(7)}>最近7天</Radio.Button>
54
+        <Radio.Button value="b" onClick={getDataOf(30)}>最近1月</Radio.Button>
55
+      </Radio.Group>
56
+      <RangePicker
57
+      ranges={{
58
+        Today: [moment(), moment()],
59
+        'This Month': [moment().startOf('month'), moment().endOf('month')],
60
+      }}
61
+      showTime
62
+      format="YYYY/MM/DD HH:mm:ss"
63
+      // onChange={onChange}
64
+    />
65
+     <Button type="primary" htmlType="submit" >
66
+            查询
67
+          </Button>
68
+  <div>
69
+    
70
+
71
+    <UserSource ></UserSource>
72
+  </div>
73
+  </>
74
+  )
75
+}
76
+
77
+export default header

+ 1
- 1
src/pages/integralMall/GoodsList.jsx Vedi File

@@ -184,7 +184,7 @@ function header(props) {
184 184
           </Button>
185 185
         </Form.Item>
186 186
       </Form>
187
-      <Button type="primary" className={styles.addBtn} onClick={toEditGoods()}>新增</Button>
187
+      <Button type="danger" className={styles.addBtn} onClick={toEditGoods()}>新增</Button>
188 188
       <Table dataSource={data.records} columns={columns} pagination={false} />
189 189
       <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
190 190
         <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={changePageNum} />

+ 1
- 1
src/pages/integralMall/exchangeRecords.jsx Vedi File

@@ -190,7 +190,7 @@ function record(props) {
190 190
           </Form.Item>
191 191
         </div>
192 192
       </Form>
193
-      <Table dataSource={data.records} columns={columns} pagination={false} />
193
+      <Table style={{marginTop:'40px'}} dataSource={data.records} columns={columns} pagination={false} />
194 194
       <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '30px' }}>
195 195
         <Pagination showQuickJumper defaultCurrent={1} total={data.total} onChange={changePageNum} />
196 196
       </div>

+ 1
- 1
src/pages/news/list/NewsList.jsx Vedi File

@@ -178,7 +178,7 @@ function body(props) {
178 178
           </span> :
179 179
           <span style={{ position: 'absolute', left: '280px', bottom: '18px', fontSize: '18px', color: '#FF7E48' }} onClick={cancelRelease.bind(this, data.newsId, 0, data.buildingId, data.newsType.newsTypeId)}>
180 180
             发布
181
-              <Icon type="close-circle" style={{ color: '#C0C4CC', marginLeft: '8px' }} />
181
+              <Icon type="form" style={{ color: '#C0C4CC', marginLeft: '8px' }} />
182 182
           </span>
183 183
         }
184 184
 

+ 1
- 1
src/pages/staff/list/RoleList.jsx Vedi File

@@ -25,7 +25,7 @@ function confirm() {
25 25
 }
26 26
 function toEditRole() {
27 27
   router.push({
28
-    pathname: '/staff/editRole',
28
+    pathname: '/staff/list/addRole',
29 29
     query: {
30 30
       a: 'b',
31 31
     },

+ 1
- 1
src/pages/staff/list/StaffList.jsx Vedi File

@@ -146,7 +146,7 @@ function CartBody (props) {
146 146
             data.labels.map((item, index) => {
147 147
               const color = colors[item];
148 148
               console.log(color, '------');
149
-              return <Tag className={Styles.cardTag}  color = {color}>{item}</Tag>
149
+              return <Tag className={Styles.cardTag} color={color}>{item}</Tag>
150 150
             })
151 151
           }
152 152
         </span>

+ 162
- 0
src/pages/staff/list/addRole.jsx Vedi File

@@ -0,0 +1,162 @@
1
+import React, { useState, useEffect } from 'react';
2
+import { Checkbox, Input, Card } from 'antd';
3
+import { connect } from 'dva';
4
+import XForm, { FieldTypes } from '../../../components/XForm';
5
+import request from '../../../utils/request';
6
+import channels from './channelList.less';
7
+
8
+const { TextArea } = Input;
9
+
10
+
11
+/**
12
+ *
13
+ *
14
+ * @param {*} props
15
+ * @returns
16
+ */
17
+const Edit = props => {
18
+  console.log('props,props', props.user.currentUser)
19
+  const userMenus = props.user.currentUser.menus;
20
+  const userBtns = props.user.currentUser.buttons;
21
+
22
+
23
+  const [data, setData] = useState({ data: [] })
24
+ // 获取当前所有菜单
25
+  useEffect(() => {
26
+    localStorage.removeItem('value');
27
+    menuList({ pageNum: 1, pageSize: 100 })
28
+  }, [])
29
+
30
+  function menuList(params) {
31
+    request({
32
+      url: '/api/admin/menuList',
33
+      method: 'GET',
34
+      params: { ...params },
35
+  // eslint-disable-next-line no-shadow
36
+  }).then(data => {
37
+      console.log(data)
38
+      setData(data)
39
+  })
40
+  }
41
+
42
+  // function SuBmenu(params) {
43
+  //  return Array.from(userMenus).map(Item =>
44
+  //  <Checkbox value={ Item.menuId }> { Item.name }</Checkbox>)
45
+  // }
46
+  // const [tab, changeTab] = useState('basic')
47
+
48
+  const Permission = [
49
+    '项目管理',
50
+    '员工管理',
51
+    '客户管理',
52
+    '系统管理',
53
+    '渠道管理',
54
+    '轮播图管理',
55
+    '资讯管理',
56
+    '活动管理',
57
+    '积分商城',
58
+    '首页数据',
59
+  ]
60
+
61
+  const Poster = props => {
62
+    const dataSource = [
63
+      {
64
+        name: '员工管理',
65
+        per: [
66
+          '111111',
67
+          '22222',
68
+          '33333',
69
+        ],
70
+      },
71
+      {
72
+        name: '角色管理',
73
+        per: [
74
+          '444',
75
+          '555',
76
+          '666',
77
+        ],
78
+      },
79
+    ];
80
+
81
+
82
+    const gridStyle1 = {
83
+      width: '20%',
84
+      textAlign: 'left',
85
+    };
86
+    const gridStyle2 = {
87
+      width: '80%',
88
+      textAlign: 'left',
89
+      height: '69px',
90
+    };
91
+
92
+    return (
93
+    <>
94
+      <div style={{}}>
95
+        {userMenus.map(item => (
96
+          <Card title={<Checkbox>{item.name}</Checkbox>} bordered style={{ width: '100%' }}>
97
+              {
98
+                   userMenus.map(menu => (
99
+
100
+                    (item.menuId === menu.menuRoot && item.menuId !== menu.menuId) &&
101
+                    <>
102
+                      <Card.Grid style={gridStyle1} >
103
+                          <Checkbox>{menu.name}</Checkbox>
104
+                      </Card.Grid>
105
+                      <Card.Grid style={gridStyle2}>
106
+                        {userBtns.map(btn => (
107
+                          <>
108
+                            {
109
+                              btn.menuId === menu.menuId &&
110
+                              <Checkbox>{btn.name}</Checkbox>
111
+                            }
112
+                          </>
113
+                        ))}
114
+                      </Card.Grid>
115
+                   </>
116
+                   ))
117
+              }
118
+          </Card>
119
+        ))}
120
+      </div>
121
+    </>
122
+    )
123
+  }
124
+
125
+  const fields = [
126
+    {
127
+      label: '角色名称',
128
+      name: 'roleName',
129
+      type: FieldTypes.Text,
130
+      // placeholder: '名称',
131
+      value: ''
132
+    },
133
+    {
134
+      label: '简介',
135
+      name: 'roleIntroduction',
136
+      render: <TextArea className={channels.inpuitTxt} ></TextArea>,
137
+      value: ''
138
+
139
+    },
140
+
141
+    {
142
+      label: '菜单权限',
143
+      name: 'rolePermission',
144
+      render:
145
+        <>
146
+          <div>
147
+
148
+            <Poster />
149
+          </div>
150
+        </>,
151
+    },
152
+
153
+  ]
154
+
155
+  const handleSubmit = val => {
156
+    window.console.log('submit data --->', val)
157
+  }
158
+  return <XForm onSubmit={handleSubmit} fields={fields}></XForm>
159
+}
160
+
161
+
162
+export default connect(({ user }) => ({ user }))(Edit);

+ 8
- 8
src/pages/staff/list/editRole.jsx Vedi File

@@ -146,7 +146,7 @@ const Edit = (props) => {
146 146
       textAlign: 'left',
147 147
     };
148 148
 
149
-{/* <Checkbox>{Permission[index]}</Checkbox> */}
149
+    {/* <Checkbox>{Permission[index]}</Checkbox> */ }
150 150
     return <>
151 151
       <div style={{}}>
152 152
       {Array.from(data).map(Item =>
@@ -157,16 +157,16 @@ const Edit = (props) => {
157 157
             
158 158
               {dataSource.map((items, indexs) => (
159 159
               <>
160
-                <Card.Grid style={gridStyle1}><Checkbox>{items.name}</Checkbox></Card.Grid>
161
-                
160
+                <Card.Grid style={gridStyle1}><Checkbox value=''>{items.name}</Checkbox></Card.Grid>
161
+
162 162
                 <Card.Grid style={gridStyle2}>
163
-                {items.per.map((itemss,indexss) =>(
164
-                  <Checkbox>{items.per[indexss]}</Checkbox>
165
-                ))}
163
+                  {items.per.map((itemss, indexss) => (
164
+                    <Checkbox value=''>{items.per[indexss]}</Checkbox>
165
+                  ))}
166 166
                 </Card.Grid>
167
-                </>
167
+              </>
168 168
             ))}
169
-            
169
+
170 170
           </Card>
171 171
 
172 172
 

+ 0
- 1
src/pages/staff/list/style.less Vedi File

@@ -61,7 +61,6 @@
61 61
 }
62 62
 
63 63
 .cardTag {
64
-  width: 48px;
65 64
   height: 18px;
66 65
   font-size: 10px;
67 66
   // background: #fdce22;

+ 61
- 2
src/services/apis.js Vedi File

@@ -2,10 +2,14 @@ const prefix = '/api/admin'
2 2
 
3 3
 export default {
4 4
   image: {
5
-    upload: {
5
+    uploadForAnt: {
6 6
       url: `${prefix}/antd/image`,
7 7
       method: 'POST',
8
-    }
8
+    },
9
+    upload: {
10
+      url: `${prefix}/image`,
11
+      method: 'POST',
12
+    },
9 13
   },
10 14
   user: {
11 15
     current: {
@@ -16,6 +20,10 @@ export default {
16 20
       method: 'POST',
17 21
       url: `${prefix}/taUser/signin`,
18 22
     },
23
+    signout: {
24
+      method: 'POST',
25
+      url: `${prefix}/taUser/signout`,
26
+    },
19 27
   },
20 28
   building: {
21 29
     getList: {
@@ -145,4 +153,55 @@ export default {
145 153
       url: `${prefix}/customer/recommend/get/id`,
146 154
     },
147 155
   },
156
+  indexEcharts: {
157
+    userResource: {
158
+      method: 'GET',
159
+      url: `${prefix}/selectUserResource`
160
+    },
161
+
162
+  }
163
+  // indexEcharts:{
164
+  //   list:{
165
+  //     method:'get',
166
+  //     url: `${commPrefix}/indexStatistical`
167
+  //   },
168
+  //   userResource: {
169
+  //       method:'get',
170
+  //       url: `${commPrefix}/selectUserResource`
171
+  //   },
172
+  //   userConversion: {
173
+  //     method:'get',
174
+  //     url: `${commPrefix}/selectConversion`
175
+  //   },
176
+  //   userActive: {
177
+  //     method:'get',
178
+  //     url: `${commPrefix}/selectActiveUserCount`
179
+  //   },
180
+  //   newUser: {
181
+  //     method:'get',
182
+  //     url: `${commPrefix}/selectNewsUserCount`
183
+  //   },
184
+  //   userBehavior: {
185
+  //     summary: {
186
+  //       method:'get',
187
+  //       url: `${commPrefix}/selectUserBehavior`
188
+  //     },
189
+  //     profile: {
190
+  //       method:'get',
191
+  //       url: `${commPrefix}/selectEventAll`
192
+  //     },
193
+  //   },
194
+  //   intentionUsers: {
195
+  //     method:'get',
196
+  //     url: `${commPrefix}/selectIntentionUser`
197
+  //   },
198
+  //   userSex: {
199
+  //     method:'get',
200
+  //     url: `${commPrefix}/selectSexUser`
201
+  //   },
202
+  //   userCity: {
203
+  //     method:'get',
204
+  //     url: `${commPrefix}/selectCityUser`
205
+  //   },
206
+  // },
148 207
 }

+ 33
- 5
src/utils/upload.js Vedi File

@@ -1,11 +1,39 @@
1
-import apis from '../services/apis';
1
+import { fetch, apis } from './request';
2
+import mixStr from './mixStr';
3
+
4
+const getToken = () => mixStr(window.localStorage.getItem('test-foobar'))
5
+
6
+const uploadImage = fetch(apis.image.upload)
2 7
 
3 8
 const uploaderProps = {
4 9
   name: 'file',
5
-  action: apis.image.upload.url,
6
-  headers: {
7
-    Authorization: `Bearer ${window.localStorage.getItem('x-token')}`
8
-  }
10
+  // action: apis.image.uploadForAnt.url,
11
+  accept: '.png, .jpg, .jpeg, .gif',
12
+  // headers: {
13
+  //   Authorization: `Bearer ${getToken()}`
14
+  // },
15
+  customRequest({
16
+    action,
17
+    file,
18
+    headers,
19
+    onError,
20
+    onProgress,
21
+    onSuccess,
22
+    withCredentials,
23
+  }) {
24
+    const data = new FormData()
25
+    data.append('file', file)
26
+
27
+    uploadImage({ data }).then((img) => {
28
+      onSuccess(img, file);
29
+    }).catch(onError);
30
+
31
+    return {
32
+      abort() {
33
+        console.log('upload progress is aborted.');
34
+      },
35
+    };
36
+  },
9 37
 }
10 38
 
11 39
 export { uploaderProps }