张延森 6 gadus atpakaļ
vecāks
revīzija
5b19f993de

+ 1
- 1
README.md Parādīt failu

@@ -1,4 +1,4 @@
1
-# 迎宾系统
1
+# 置业顾问&经纪人助手
2 2
 
3 3
 ## Project setup
4 4
 ```

+ 5
- 5
package.json Parādīt failu

@@ -18,15 +18,16 @@
18 18
     "vue": "^2.6.6",
19 19
     "vue-echarts": "^4.0.1",
20 20
     "vue-router": "^3.0.2",
21
-    "vuex": "^3.1.0"
21
+    "vuex": "^3.1.0",
22
+    "wangeditor": "^3.1.1"
22 23
   },
23 24
   "devDependencies": {
24 25
     "@vue/cli-plugin-babel": "^3.0.5",
25 26
     "@vue/cli-plugin-eslint": "^3.0.5",
26 27
     "@vue/cli-service": "^3.7.0",
27 28
     "babel-eslint": "^10.0.1",
28
-    "eslint": "^5.8.0",
29
-    "eslint-plugin-vue": "^5.0.0",
29
+    "eslint": "^5.16.0",
30
+    "eslint-plugin-vue": "^5.2.2",
30 31
     "node-sass": "^4.11.0",
31 32
     "sass-loader": "^7.1.0",
32 33
     "vue-template-compiler": "^2.5.21"
@@ -37,8 +38,7 @@
37 38
       "node": true
38 39
     },
39 40
     "extends": [
40
-      "plugin:vue/essential",
41
-      "eslint:recommended"
41
+      "plugin:vue/essential"
42 42
     ],
43 43
     "rules": {},
44 44
     "parserOptions": {

+ 66
- 0
src/config/api.js Parādīt failu

@@ -20,6 +20,10 @@ const apis = {
20 20
       url: `${commPrefix}/consultant`,
21 21
       method: 'get',
22 22
     },
23
+    detail: {
24
+      url: `${commPrefix}/consultant/:id`,
25
+      method: 'get',
26
+    },
23 27
     add: {
24 28
       url: `${commPrefix}/consultant`,
25 29
       method: 'post',
@@ -29,6 +33,68 @@ const apis = {
29 33
       method: 'put',
30 34
     },
31 35
   },
36
+  building: {
37
+    list: {
38
+      method: 'get',
39
+      url: `${commPrefix}/buildinglist`
40
+    },
41
+    add: {
42
+      method: 'post',
43
+      url: `${commPrefix}/building/add`
44
+    },
45
+    edit: {
46
+      method: 'put',
47
+      url: `${commPrefix}/building/update`
48
+    },
49
+    updateStatus: {
50
+      method: 'put',
51
+      url: `${commPrefix}/building/update/status`
52
+    },
53
+    detail: {
54
+      method: 'get',
55
+      url: `${commPrefix}/buildingSelectId/:id`
56
+    },
57
+    delete: {
58
+      method: 'delete',
59
+      url: `${commPrefix}/building/delete/:id`
60
+    }
61
+  },
62
+  dynamic: {
63
+    list: {
64
+      method: 'get',
65
+      url: `${commPrefix}/iBuildingDynamicList`
66
+    },
67
+    detail: {
68
+      method: 'get',
69
+      url: `${commPrefix}/iBuildingDynamicSelectId/:id`
70
+    },
71
+    add: {
72
+      method: 'post',
73
+      url: `${commPrefix}/buildingDynamic/add`
74
+    },
75
+    edit: {
76
+      method: 'put',
77
+      url: `${commPrefix}/buildingDynamic/update`
78
+    },
79
+    delete: {
80
+      method: 'delete',
81
+      url: `${commPrefix}/buildingDynamic/delete`
82
+    },
83
+    public: {
84
+      method: 'put',
85
+      url: `${commPrefix}/buildingDynamic/send/:id`
86
+    },
87
+    cancel: {
88
+      method: 'put',
89
+      url: `${commPrefix}/buildingDynamic/cancel/:id`
90
+    },
91
+  },
92
+  file: {
93
+    upload: {
94
+      method: 'post',
95
+      url: `${commPrefix}/image`
96
+    },
97
+  },
32 98
 }
33 99
 
34 100
 export default apis

+ 29
- 29
src/layout/default/index.vue Parādīt failu

@@ -3,7 +3,7 @@
3 3
     <el-aside class="siderbar" :style="{ width: '210px' }">
4 4
       <div class="logo"></div>
5 5
       <el-menu class="nav-menu" v-bind="menuParams">
6
-        <menu-item v-for="menu in menus" :key="menu.name" :menu="menu" :validate="isInMenuList" />
6
+        <menu-item v-for="menu in menus" :key="menu.name" :menu="menu" :validate="isInMenuList"/>
7 7
       </el-menu>
8 8
     </el-aside>
9 9
     <el-container>
@@ -19,65 +19,66 @@
19 19
         <router-view></router-view>
20 20
       </el-main>
21 21
       <el-footer class="noPadding">
22
-        <xm-footer company="荟房科技" />
22
+        <xm-footer company="荟房科技"/>
23 23
       </el-footer>
24 24
     </el-container>
25 25
   </el-container>
26 26
 </template>
27 27
 
28 28
 <script>
29
-import { pages, pageArray } from '@/views'
29
+import { pages, pageArray } from "@/views";
30 30
 
31 31
 export default {
32
-  name: 'default-layout',
32
+  name: "default-layout",
33 33
   components: {
34
-    xmFooter: () => import('@/components/XMFooter.vue'),
35
-    menuItem: () => import('./MenuItem.vue'),
36
-    user: () => import('./User.vue'),
34
+    xmFooter: () => import("@/components/XMFooter.vue"),
35
+    menuItem: () => import("./MenuItem.vue"),
36
+    user: () => import("./User.vue")
37 37
   },
38
-  data () {
38
+  data() {
39 39
     return {
40 40
       menus: pages,
41
-      menuArray: pageArray,
42
-    }
41
+      menuArray: pageArray
42
+    };
43 43
   },
44 44
   computed: {
45 45
     menuParams() {
46 46
       return {
47
-        backgroundColor: '#24292e',
48
-        textColor: '#eee',
49
-        activeTextColor: '#FFD04B',
50
-        defaultActive: this.$route.name,
51
-      }
47
+        backgroundColor: "#24292e",
48
+        textColor: "#eee",
49
+        activeTextColor: "#FFD04B",
50
+        defaultActive: this.$route.name
51
+      };
52 52
     },
53 53
     breads() {
54
-      const route = this.menuArray.filter(x => x.name === this.$route.name)[0] || {}
55
-      const p = (route.parents || []).map((rn) => {
54
+      const route =
55
+        this.menuArray.filter(x => x.name === this.$route.name)[0] || {};
56
+      const p = (route.parents || []).map(rn => {
56 57
         return this.menuArray.filter(x => x.name === rn.name)[0];
57
-      })
58
+      });
58 59
 
59
-      return p.concat(route)
60
+      return p.concat(route);
60 61
     }
61 62
   },
62 63
   methods: {
63 64
     isInMenuList(menu) {
64
-      return !!this.menuArray.filter(x => x.name === menu.name)[0]
65
+      return !!this.menuArray.filter(x => x.name === menu.name)[0];
65 66
     },
66 67
     resetPassword() {
67
-      window.console.log('------resetPassword------')
68
+      window.console.log("------resetPassword------");
68 69
     },
69 70
     logout() {
70
-      this.$store.dispatch('logout').then(() => {
71
+      this.$store.dispatch("logout").then(() => {
71 72
         this.$router.push({
72
-          name: 'login',
73
+          name: "login",
73 74
           query: {
74
-            from: this.$route.name,
75
+            from: this.$route.name
75 76
           }
76
-        })
77
-      })
77
+        });
78
+      });
78 79
     }
79 80
   }
80
-}
81
+};
81 82
 </script>
82 83
 
83 84
 <style lang="scss" scoped>
@@ -106,12 +107,11 @@ export default {
106 107
 }
107 108
 
108 109
 .logo {
109
-  
110 110
 }
111 111
 
112 112
 .siderbar {
113 113
   border-right: solid 1px #e6e6e6;
114
-  
114
+
115 115
   color: #eee;
116 116
   background-color: #24292e;
117 117
 

+ 3
- 0
src/store/index.js Parādīt failu

@@ -8,6 +8,9 @@ const store = new Vuex.Store({
8 8
   ...system,
9 9
   modules: {
10 10
     persons: require('./modules/persons').default,
11
+    dynamic: require('./modules/dynamic').default,
12
+    building: require('./modules/building').default,
13
+    img: require('./modules/img').default,
11 14
   }
12 15
 })
13 16
 

+ 103
- 0
src/store/modules/building.js Parādīt failu

@@ -0,0 +1,103 @@
1
+import request from '../../utils/request'
2
+import apis from '../../config/api'
3
+
4
+export default {
5
+  namespaced: true,
6
+  state: {
7
+    buildings: {},
8
+    detail: {}
9
+  },
10
+  mutations: {
11
+    updateList (state, payload) {
12
+      state.buildings = payload
13
+    },
14
+    updateDetail (state, payload) {
15
+      state.detail = payload
16
+    }
17
+  },
18
+  actions: {
19
+    setDetailNull ({ commit }) {
20
+      commit('updateDetail', {})
21
+    },
22
+    getBuildings ({ commit }, payload) {
23
+      return new Promise((resolve, reject) => {
24
+        request({
25
+          ...apis.building.list,
26
+          params: payload,
27
+        }).then((data) => {
28
+          commit('updateList', data)
29
+          resolve(data)
30
+        }).catch((err) => {
31
+          const message = err.message || err.msg
32
+          if (typeof message === 'string') {
33
+            reject(message)
34
+          }
35
+        })
36
+      })
37
+    },
38
+    getDetail ({ commit }, payload) {
39
+      return new Promise((resolve, reject) => {
40
+        request({
41
+          ...apis.building.detail,
42
+          urlData: payload,
43
+        }).then((data) => {
44
+          commit('updateDetail', data)
45
+          resolve(data)
46
+        }).catch((err) => {
47
+          const message = err.message || err.msg
48
+          if (typeof message === 'string') {
49
+            reject(message)
50
+          }
51
+        })
52
+      })
53
+    },
54
+    addBuilding (_, payload) {
55
+      const { onSuccess } = payload
56
+      request({
57
+        ...apis.building.add, 
58
+        data: payload.detail,
59
+      }).then((data) => {
60
+        onSuccess(data)
61
+      })
62
+    },
63
+    editBuilding (_, payload) {
64
+      const { onSuccess } = payload
65
+      request({
66
+        ...apis.building.edit, 
67
+        data: payload.detail,
68
+      }).then((data) => {
69
+        onSuccess(data)
70
+      })
71
+    },
72
+    delBuilding (_, payload) {
73
+      return new Promise((resolve, reject) => {
74
+        request({
75
+          ...apis.building.delete,
76
+          urlData: payload,
77
+        }).then((data) => {
78
+          resolve(data)
79
+        }).catch((err) => {
80
+          const message = err.message || err.msg
81
+          if (typeof message === 'string') {
82
+            reject(message)
83
+          }
84
+        })
85
+      })
86
+    },
87
+    updateBuildingStatus (_, payload) {
88
+      return new Promise((resolve, reject) => {
89
+        request({
90
+          ...apis.building.updateStatus,
91
+          data: payload,
92
+        }).then((data) => {
93
+          resolve(data)
94
+        }).catch((err) => {
95
+          const message = err.message || err.msg
96
+          if (typeof message === 'string') {
97
+            reject(message)
98
+          }
99
+        })
100
+      })
101
+    }
102
+  }
103
+}

+ 133
- 0
src/store/modules/dynamic.js Parādīt failu

@@ -0,0 +1,133 @@
1
+import request from '../../utils/request'
2
+import apis from '../../config/api'
3
+
4
+export default {
5
+  namespaced: true,
6
+  state: {
7
+    dynamics: {},
8
+    detail: {}
9
+  },
10
+  mutations: {
11
+    updateList (state, payload) {
12
+      state.dynamics = payload
13
+    },
14
+    updateDetail (state, payload) {
15
+      state.detail = payload
16
+    }
17
+  },
18
+  actions: {
19
+    setDetailNull ({ commit }) {
20
+      commit('updateDetail', {})
21
+    },
22
+    getDynamics ({ commit }, payload) {
23
+      return new Promise((resolve, reject) => {
24
+        request({
25
+          ...apis.dynamic.list,
26
+          params: payload,
27
+        }).then((data) => {
28
+          commit('updateList', data)
29
+          resolve(data)
30
+        }).catch((err) => {
31
+          const message = err.message || err.msg
32
+
33
+          if (typeof message === 'string') {
34
+            reject(message)
35
+          }
36
+        })
37
+      })
38
+    },
39
+    getDetail ({ commit }, payload) {
40
+      return new Promise((resolve, reject) => {
41
+        request({
42
+          ...apis.dynamic.detail,
43
+          params: payload,
44
+        }).then((data) => {
45
+          commit('updateDetail', data)
46
+          resolve(data)
47
+        }).catch((err) => {
48
+          const message = err.message || err.msg
49
+
50
+          if (typeof message === 'string') {
51
+            reject(message)
52
+          }
53
+        })
54
+      })
55
+    },
56
+    addDynamics (_, payload) {
57
+      return new Promise((resolve, reject) => {
58
+        request({
59
+          ...apis.dynamic.add, 
60
+          data: payload.detail,
61
+        }).then((data) => {
62
+          resolve(data)
63
+        }).catch((err) => {
64
+          const message = err.message || err.msg
65
+
66
+          if (typeof message === 'string') {
67
+            reject(message)
68
+          }
69
+        })
70
+      })
71
+    },
72
+    editDynamics (_, payload) {
73
+      return new Promise((resolve, reject) => {
74
+        request({
75
+          ...apis.dynamic.edit,
76
+          data: payload.detail,
77
+        }).then((data) => {
78
+          resolve(data)
79
+        }).catch((err) => {
80
+          const message = err.message || err.msg
81
+
82
+          if (typeof message === 'string') {
83
+            reject(message)
84
+          }
85
+        })
86
+      })
87
+    },
88
+    deleteDynamics (_, payload) {
89
+      return new Promise((resolve, reject) => {
90
+        request({
91
+          ...apis.dynamic.delete,
92
+          ...payload
93
+        }).then(() => {
94
+          resolve()
95
+        }).catch(() => {
96
+          reject()
97
+        })
98
+      })
99
+    },
100
+    publicDynamic (_, payload) {
101
+      return new Promise((resolve, reject) => {
102
+        request({
103
+          ...apis.dynamic.public,
104
+          urlData: payload,
105
+        }).then((data) => {
106
+          resolve(data)
107
+        }).catch((err) => {
108
+          const message = err.message || err.msg
109
+
110
+          if (typeof message === 'string') {
111
+            reject(message)
112
+          }
113
+        })
114
+      })
115
+    },
116
+    cancelDynamic (_, payload) {
117
+      return new Promise((resolve, reject) => {
118
+        request({
119
+          ...apis.dynamic.cancel,
120
+          urlData: payload,
121
+        }).then((data) => {
122
+          resolve(data)
123
+        }).catch((err) => {
124
+          const message = err.message || err.msg
125
+
126
+          if (typeof message === 'string') {
127
+            reject(message)
128
+          }
129
+        })
130
+      })
131
+    }
132
+  }
133
+}

+ 27
- 0
src/store/modules/img.js Parādīt failu

@@ -0,0 +1,27 @@
1
+
2
+import request from '../../utils/request'
3
+import apis from '../../config/api'
4
+
5
+export default {
6
+  namespaced: true,
7
+  state: {},
8
+  actions: {
9
+    uploadImg (_, payload) {
10
+      return new Promise((resolve, reject) => {
11
+        const fm = new FormData()
12
+        fm.append('file', payload)
13
+
14
+        request({
15
+          ...apis.file.upload,
16
+          data: fm,
17
+        }).then((data) => {
18
+          resolve(data)
19
+        }).catch(({ message }) => {
20
+          if (typeof message === 'string') {
21
+            reject(message)
22
+          }
23
+        })
24
+      })
25
+    },
26
+  }
27
+}

+ 23
- 1
src/store/modules/persons.js Parādīt failu

@@ -14,6 +14,28 @@ export default {
14 14
         ...apis.consultant.list,
15 15
         params: payload,
16 16
       })
17
-    }
17
+    },
18
+    getConsultant (context, payload) {
19
+      return request({
20
+        ...apis.consultant.detail,
21
+        urlData: payload,
22
+      })
23
+    },
24
+    editConsultant (context, payload) {
25
+      window.console.log(payload)
26
+
27
+      const config = payload.personId ?
28
+        {
29
+          ...apis.consultant.edit,
30
+          urlData: { id: payload.personId },
31
+          data: payload,
32
+        } :
33
+        {
34
+          ...apis.consultant.add,
35
+          data: payload,
36
+        }
37
+
38
+      return request(config)
39
+    },
18 40
   },
19 41
 }

+ 2
- 2
src/utils/request.js Parādīt failu

@@ -6,7 +6,7 @@ import axios from 'axios'
6 6
 function request(params = {}) {
7 7
   const { urlData, data: rawData, url: rawURL, headers = {}, ...config } = params;
8 8
   const url = replaceApiParams(rawURL, urlData)
9
-  const data = (rawData instanceof FormData) ? rawData : JSON.stringify(rawData)
9
+  // const data = (rawData instanceof FormData) ? rawData : JSON.stringify(rawData)
10 10
   const token = localStorage.getItem('x-token') || ''
11 11
   const contenType = (rawData instanceof FormData) ? 'multipart/form-data' : 'application/json'
12 12
   
@@ -14,7 +14,7 @@ function request(params = {}) {
14 14
     axios({
15 15
       ...config,
16 16
       url,
17
-      data,
17
+      data: rawData,
18 18
       headers: {
19 19
         'Content-Type': contenType,
20 20
         ...headers,

+ 10
- 4
src/views/Login.vue Parādīt failu

@@ -17,10 +17,16 @@
17 17
               </el-input>
18 18
             </el-form-item>
19 19
             <el-form-item>
20
-              <el-input class="large-input" v-model="formdata.password" placeholder="请输入验证码">
21
-                <xm-icon name="password" size="small" slot="prefix" :style="{ lineHeight: '36px' }"/>
22
-                <el-button slot="append">发送验证码</el-button>
23
-              </el-input>
20
+              <el-row :gutter="10">
21
+                <el-col :span="18">
22
+                  <el-input class="large-input" v-model="formdata.password" placeholder="请输入验证码">
23
+                    <xm-icon name="password" size="small" slot="prefix" :style="{ lineHeight: '36px' }"/>
24
+                  </el-input>
25
+                </el-col>
26
+                <el-col :span="4">
27
+                  <el-button type="success">验证码</el-button>
28
+                </el-col>
29
+              </el-row>              
24 30
             </el-form-item>
25 31
             <el-form-item>
26 32
               <div class="form-action">

+ 160
- 0
src/views/consultant/edit.vue Parādīt failu

@@ -0,0 +1,160 @@
1
+<template>
2
+  <div>
3
+    <div class="form-wrapper">
4
+      <el-form label-width="80px" :model="detail">
5
+        <el-form-item label="名称">
6
+          <el-input v-model="detail.name"></el-input>
7
+        </el-form-item>
8
+        <el-form-item label="公司">
9
+          <el-input v-model="detail.company"></el-input>
10
+        </el-form-item>
11
+        <el-form-item label="部门">
12
+          <el-input v-model="detail.department"></el-input>
13
+        </el-form-item>
14
+        <el-form-item label="职位">
15
+          <el-input v-model="detail.post"></el-input>
16
+        </el-form-item>
17
+        <el-form-item label="电话">
18
+          <el-input v-model="detail.tel"></el-input>
19
+        </el-form-item>
20
+        <el-form-item label="图片">
21
+          <el-upload
22
+            class="avatar-uploader"
23
+            :action="upFileUrl"
24
+            name='file'
25
+            :show-file-list="false"
26
+            :before-upload="beforeImgUpload"
27
+            :on-success="handleAvatarSuccess">
28
+            <img v-if="detail.photo" :src="detail.photo" class="avatar">
29
+            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
30
+          </el-upload>
31
+        </el-form-item>
32
+        <el-form-item label="状态">
33
+          <el-radio-group v-model="detail.status">
34
+            <el-radio-button :label="0">禁用</el-radio-button>
35
+            <el-radio-button :label="1">启用</el-radio-button>
36
+          </el-radio-group>
37
+        </el-form-item>
38
+        <el-form-item>
39
+          <el-button type="primary" @click="submitForm">保存</el-button>
40
+          <el-button @click="$router.go(-1)">返回</el-button>
41
+        </el-form-item>
42
+      </el-form>
43
+    </div>
44
+  </div>
45
+</template>
46
+
47
+<script>
48
+import { createNamespacedHelpers } from 'vuex'
49
+import apis from '../../config/api'
50
+
51
+const { mapActions: mapPersonActions } = createNamespacedHelpers('persons')
52
+
53
+export default {
54
+  name: 'consultantEdit',
55
+  data () {
56
+    return {
57
+      upFileUrl: apis.file.upload.url,
58
+      detail: {
59
+        name: undefined,
60
+        company: undefined,
61
+        department: undefined,
62
+        post: undefined,
63
+        tel: undefined,
64
+        photo: undefined,
65
+        status: 1,
66
+      },
67
+    }
68
+  },
69
+  created () {
70
+    this.init()
71
+  },
72
+  methods: {
73
+    ...mapPersonActions([
74
+      'getConsultant',
75
+      'editConsultant',
76
+    ]),
77
+    init () {
78
+      if (this.$route.params.id) {
79
+        this.getConsultant({ id: this.$route.params.id }).then((data) => {
80
+          this.detail = data
81
+        })
82
+      }
83
+    },
84
+    beforeImgUpload (file) {
85
+      if (file.type !== 'image/jpeg' && file.type !== 'image/png') {
86
+        this.$message.error('上传图片只能是 JPG 或 PNG 格式!')
87
+        return false
88
+      }
89
+
90
+      this.showLoadding('上传中...')
91
+      return true
92
+    },
93
+  
94
+    handleAvatarSuccess (res) {
95
+      this.detail.photo = res.data
96
+      this.hideLoadding()
97
+    },
98
+
99
+    submitForm () {
100
+      this.showLoadding('保存中...')
101
+      this.editConsultant(this.detail).then((res) => {
102
+        if (res.personId) {
103
+          this.detail = res
104
+        }
105
+
106
+        this.hideLoadding()
107
+        this.$notify.info('保存成功')
108
+      }).catch((err) => {
109
+        this.hideLoadding()
110
+        this.$notify.error(err.message)
111
+      })
112
+    },
113
+
114
+    showLoadding (text) {      
115
+      this.loading = this.$loading({
116
+        text,
117
+        lock: true,
118
+        spinner: 'el-icon-loading',
119
+        background: 'rgba(255, 255, 255, 0.7)'
120
+      })
121
+    },
122
+
123
+    hideLoadding () {
124
+      if (this.loading) this.loading.close()      
125
+    }
126
+  },
127
+}
128
+</script>
129
+
130
+<style lang="scss" scoped>
131
+.form-wrapper {
132
+  width: 60%;
133
+}
134
+</style>
135
+
136
+<style lang="scss">
137
+  .avatar-uploader .el-upload {
138
+    border: 1px dashed #d9d9d9;
139
+    border-radius: 6px;
140
+    cursor: pointer;
141
+    position: relative;
142
+    overflow: hidden;
143
+  }
144
+  .avatar-uploader .el-upload:hover {
145
+    border-color: #409EFF;
146
+  }
147
+  .avatar-uploader-icon {
148
+    font-size: 28px;
149
+    color: #8c939d;
150
+    width: 178px;
151
+    height: 178px;
152
+    line-height: 178px;
153
+    text-align: center;
154
+  }
155
+  .avatar {
156
+    width: 178px;
157
+    height: 178px;
158
+    display: block;
159
+  }
160
+</style>

+ 195
- 0
src/views/dynamic/edit.vue Parādīt failu

@@ -0,0 +1,195 @@
1
+<template>
2
+  <el-form ref="form" :model="dynamic" label-width="160px">
3
+    <el-form-item label="所属楼盘">
4
+      <el-select v-model="dynamic.buildingId" placeholder="请选择">
5
+        <el-option v-for="(build,i) in buildings.list || []" :key="i" :label="build.buildingName" :value="build.buildingId"></el-option>
6
+      </el-select>
7
+    </el-form-item>
8
+    <el-form-item label="项目动态标题">
9
+      <el-input v-model="dynamic.title"></el-input>
10
+    </el-form-item>
11
+    <el-form-item label="描述">
12
+      <el-input v-model="dynamic.desc"></el-input>
13
+    </el-form-item>
14
+    <el-form-item label="主图">
15
+      <el-upload
16
+        class="avatar-uploader"
17
+        :action="upFileUrl"
18
+        name='file'
19
+        :show-file-list="false"
20
+        :before-upload="beforeImgUpload"
21
+        :on-success="handleAvatarSuccess">
22
+        <img v-if="dynamic.imgUrl" :src="dynamic.imgUrl" class="avatar">
23
+        <i v-else class="el-icon-plus avatar-uploader-icon"></i>
24
+      </el-upload>
25
+    </el-form-item>
26
+    <!-- <el-form-item label="链接地址">
27
+      <el-input v-model="dynamic.url"></el-input>
28
+    </el-form-item> -->
29
+    <el-form-item label="内容">
30
+      <div id="websiteEditorElem" style="height: 400px"></div>
31
+    </el-form-item>
32
+    <el-form-item>
33
+      <el-button type="primary" @click="onSubmit">保存</el-button>
34
+      <el-button @click="onCancel">取消</el-button>
35
+    </el-form-item>
36
+  </el-form>
37
+</template>
38
+
39
+<script>
40
+import { createNamespacedHelpers } from 'vuex'
41
+import apis from '../../config/api'
42
+import E from 'wangeditor'
43
+
44
+const { mapState: mapDynamicState, mapActions: mapDynamicActions, mapMutations: mapDynamicMutations } = createNamespacedHelpers('dynamic')
45
+const { mapState: mapBuildingState, mapActions: mapBuildingActions } = createNamespacedHelpers('building')
46
+const { mapActions: mapImgActions } = createNamespacedHelpers('img')
47
+
48
+export default {
49
+  data () {
50
+    return {
51
+      upFileUrl: apis.file.upload.url,
52
+    }
53
+  },
54
+  computed: {
55
+    ...mapDynamicState({
56
+      detail: x => x.detail,
57
+    }),
58
+    dynamic: {
59
+      get () {
60
+        return this.detail
61
+      },
62
+      set (val) {
63
+        return this.updateDetail(val)
64
+      }
65
+    },
66
+    ...mapBuildingState({
67
+      buildings: x => x.buildings
68
+    }),
69
+  },
70
+  methods: {
71
+    ...mapBuildingActions([
72
+      'getBuildings'
73
+    ]),
74
+    ...mapDynamicMutations([
75
+      'updateDetail'
76
+    ]),
77
+    ...mapDynamicActions([
78
+      'getDetail',
79
+      'addDynamics',
80
+      'editDynamics'
81
+    ]),
82
+    ...mapImgActions([
83
+      'uploadImg'
84
+    ]),
85
+    beforeImgUpload (file) {
86
+      if (file.type !== 'image/jpeg' && file.type !== 'image/png') {
87
+        this.$message.error('上传图片只能是 JPG 或 PNG 格式!')
88
+        return false
89
+      }
90
+      // if (file.size / 1024 > 300) {
91
+      //   this.$message.error('图片大小不允许超过300k!')
92
+      //   return false
93
+      // }
94
+      this.loading = this.$loading({
95
+        lock: true,
96
+        text: '上传中...',
97
+        spinner: 'el-icon-loading',
98
+        background: 'rgba(0, 0, 0, 0.7)'
99
+      })
100
+
101
+      return true
102
+    },
103
+    handleAvatarSuccess (res) {
104
+      this.updateDetail({...this.dynamic, imgUrl: res.data})
105
+      this.loading.close()
106
+    },
107
+    onSubmit () {
108
+      if (!this.detail.dynamicId) {
109
+        // 新增
110
+        this.addDynamics({
111
+          detail: JSON.stringify(this.detail)
112
+        }).then(() => {
113
+          this.onCancel()
114
+        })
115
+      } else {
116
+        // 修改
117
+        this.editDynamics({
118
+          detail: JSON.stringify(this.detail)
119
+        }).then(() => {
120
+          this.onCancel()
121
+        })
122
+      }
123
+    },
124
+    onCancel () {
125
+      this.$router.push({name: 'dynamiclist'})
126
+    }
127
+  },
128
+  mounted () {
129
+    const _that = this
130
+    const phoneEditor = new E('#websiteEditorElem')
131
+    phoneEditor.customConfig.onchange = function (html) {
132
+      _that.dynamic = {..._that.dynamic, url: html}
133
+    }
134
+    // phoneEditor.customConfig.uploadImgServer = this.upFileUrl
135
+    // phoneEditor.customConfig.uploadFileName = 'uploadFiles'
136
+
137
+    phoneEditor.customConfig.customUploadImg = function (files, insert) {
138
+      _that.uploadImg(files[0]).then(data => {
139
+        insert(data)
140
+      })
141
+    }
142
+    phoneEditor.customConfig.menus = [
143
+      'head',  // 标题
144
+      'bold',  // 粗体
145
+      'fontSize',  // 字号
146
+      'fontName',  // 字体
147
+      'italic',  // 斜体
148
+      'underline',  // 下划线
149
+      'strikeThrough',  // 删除线
150
+      'foreColor',  // 文字颜色
151
+      'backColor',  // 背景颜色
152
+      'justify',  // 对齐方式
153
+      'image',  // 插入图片
154
+    ]
155
+    phoneEditor.create()
156
+    
157
+    this.getBuildings({
158
+      pageNum: 1,
159
+      pageSize: 100,
160
+    }).then(() => {
161
+      if ((this.$route.query.id || '') !== '') {
162
+        this.getDetail({id: this.$route.query.id}).then((data) => {
163
+          phoneEditor.txt.html(data.url)
164
+        })
165
+      }
166
+    })
167
+  }
168
+}
169
+</script>
170
+
171
+<style lang="scss">
172
+  .avatar-uploader .el-upload {
173
+    border: 1px dashed #d9d9d9;
174
+    border-radius: 6px;
175
+    cursor: pointer;
176
+    position: relative;
177
+    overflow: hidden;
178
+  }
179
+  .avatar-uploader .el-upload:hover {
180
+    border-color: #409EFF;
181
+  }
182
+  .avatar-uploader-icon {
183
+    font-size: 28px;
184
+    color: #8c939d;
185
+    width: 178px;
186
+    height: 178px;
187
+    line-height: 178px;
188
+    text-align: center;
189
+  }
190
+  .avatar {
191
+    width: 178px;
192
+    height: 178px;
193
+    display: block;
194
+  }
195
+</style>

+ 259
- 0
src/views/dynamic/list.vue Parādīt failu

@@ -0,0 +1,259 @@
1
+<template>
2
+  <div>
3
+    <div class="system-table-search">
4
+      <div class="flex-h">
5
+        <div class="flex-item flex-h">
6
+          <el-button size="mini" type="success" @click='addDynamic'>新增项目动态</el-button>
7
+        </div>
8
+        <ul>
9
+          <li>
10
+            <el-input v-model="name" placeholder="标题"></el-input>
11
+          </li>
12
+          <li>
13
+            <el-select v-model="buildingId" placeholder="楼盘">
14
+              <el-option
15
+                v-for="item in buildings.list || []"
16
+                :key="item.buildingId"
17
+                :label="item.buildingName"
18
+                :value="item.buildingId">
19
+              </el-option>
20
+            </el-select>
21
+          </li>
22
+        </ul>
23
+        <el-button
24
+          size="mini"
25
+          type="primary" @click="search">搜索</el-button>
26
+      </div>
27
+      <div class="moreFilter"></div>
28
+    </div>
29
+    <el-table
30
+      :data="dynamics.list || []"
31
+      style="width: 100%">
32
+      <el-table-column
33
+        type="index"
34
+        width="50">
35
+        <template slot-scope="scope">
36
+          <span>{{ GetIndex(scope.$index) }}</span>
37
+        </template>
38
+      </el-table-column>
39
+      <el-table-column
40
+        label="项目动态主图">
41
+        <template slot-scope="scope">
42
+          <div class="header">
43
+            <img :src="scope.row.imgUrl" alt="" />
44
+          </div>
45
+        </template>
46
+      </el-table-column>
47
+      <el-table-column
48
+        prop="title"
49
+        label="标题">
50
+      </el-table-column>
51
+      <el-table-column
52
+        prop="desc"
53
+        label="描述">
54
+      </el-table-column>
55
+      <!-- <el-table-column
56
+        label="链接地址"
57
+        prop="url"
58
+      >
59
+      </el-table-column> -->
60
+      <el-table-column
61
+        label="发布状态"
62
+        width="150"
63
+        >
64
+        <template slot-scope="scope">
65
+          <span>{{scope.row.status == 1 ? '已发布' : '未发布'}}</span>
66
+        </template>
67
+      </el-table-column>
68
+      <el-table-column
69
+        label="发布时间"
70
+        width="150"
71
+        prop="publishDate"
72
+      >
73
+      </el-table-column>
74
+      <el-table-column
75
+        fixed="right"
76
+        label="操作"
77
+        width="180">
78
+        <template slot-scope="scope">
79
+          <el-button type="text" @click="handleEdit(scope.row)" size="small">编辑</el-button>
80
+          <el-button type="text" @click="handlePulic(scope.row)" size="small" v-if="scope.row.status === 0">发布</el-button>
81
+          <el-button type="text" @click="handleUnPulic(scope.row)" size="small" v-if="scope.row.status === 1">取消发布</el-button>
82
+          <el-button @click="handleDel(scope.row)" type="text" size="small">删除</el-button>
83
+        </template>
84
+      </el-table-column>
85
+    </el-table>
86
+    <el-pagination
87
+      small
88
+      style="margin-top:10px;"
89
+      layout="prev, pager, next"
90
+      :current-page.sync="currentPage"
91
+      :pageSize="pageSize"
92
+      :total="dynamics.total || 0"
93
+      @current-change="getList"
94
+    >
95
+    </el-pagination>
96
+  </div>
97
+</template>
98
+
99
+<script>
100
+import { createNamespacedHelpers } from 'vuex';
101
+
102
+const {mapState: mapDynamicState, mapActions: mapDynamicActions} = createNamespacedHelpers('dynamic')
103
+const {mapState: mapBuildingState, mapActions: mapBuildingActions} = createNamespacedHelpers('building')
104
+
105
+export default {
106
+  data() {
107
+    return {
108
+      pageSize: 20,
109
+      currentPage: 1,
110
+      name: '',
111
+      buildingId: '',
112
+    }
113
+  },
114
+  computed: {
115
+    ...mapDynamicState({
116
+      dynamics: x => x.dynamics
117
+    }),
118
+    ...mapBuildingState({
119
+      buildings: x => x.buildings
120
+    })
121
+  },
122
+  methods: {
123
+    ...mapDynamicActions([
124
+      'getDynamics',
125
+      'setDetailNull',
126
+      'deleteDynamics',
127
+      'publicDynamic',
128
+      'cancelDynamic'
129
+    ]),
130
+    ...mapBuildingActions([
131
+      'getBuildings',
132
+    ]),
133
+    GetIndex (inx) {
134
+      return (this.currentPage - 1) * this.pageSize + inx + 1
135
+    },
136
+    FormatDate (date) {
137
+      if (date) {
138
+        return dayjs(date).formate('yyyy-MM-DD HH:mm:ss')
139
+      } else {
140
+        return ''
141
+      }
142
+    },
143
+    getList () {
144
+      this.getDynamics({
145
+        pageNum: this.currentPage,
146
+        pageSize: this.pageSize,
147
+        name: this.name,
148
+        buildingId: this.buildingId
149
+      })
150
+    },
151
+    getBuildingName (id) {
152
+      return ((this.buildings.list || []).filter(x => x.buildingId === id)[0] || {}).buildingName || ''
153
+    },
154
+    search () {
155
+      this.currentPage = 1
156
+      this.getList()
157
+    },
158
+    handleEdit (row) {
159
+      this.setDetailNull()
160
+      this.$router.push({name: 'dynamicedit', query: {id: row.dynamicId}})
161
+    },
162
+    handlePulic (row) {
163
+      this.$confirm('确认发布此数据?', '提示', {
164
+        confirmButtonText: '确定',
165
+        cancelButtonText: '取消',
166
+        type: 'warning'
167
+      }).then(() => {
168
+        this.publicDynamic({
169
+          id: row.dynamicId
170
+        }).then(() => {
171
+          this.getList()
172
+        })
173
+      })
174
+    },
175
+    handleUnPulic (row) {
176
+      this.$confirm('确认取消发布此数据?', '提示', {
177
+        confirmButtonText: '确定',
178
+        cancelButtonText: '取消',
179
+        type: 'warning'
180
+      }).then(() => {
181
+        this.cancelDynamic({
182
+          id: row.dynamicId}).then(() => {
183
+          this.getList()
184
+        })
185
+      })
186
+    },
187
+    handleDel (row) {
188
+      this.$confirm('确认删除此数据?', '提示', {
189
+        confirmButtonText: '确定',
190
+        cancelButtonText: '取消',
191
+        type: 'warning'
192
+      }).then(() => {
193
+        if (row.status === 1) {
194
+          this.$message.error('当前活动处于发布状态,不允许删除!')
195
+          return false
196
+        }
197
+        this.deleteDynamics({
198
+          id: row.dynamicId
199
+        }).then(() => {
200
+          this.getList()
201
+        })
202
+      })
203
+    },
204
+    addDynamic () {
205
+      this.setDetailNull()
206
+      this.$router.push({name: 'dynamicedit'})
207
+    }
208
+  },
209
+  created () {
210
+    this.getBuildings({
211
+      pageNum: 1,
212
+      pageSize: 100,
213
+    }).then(() => {
214
+      this.getList()
215
+    })
216
+  }
217
+}
218
+</script>
219
+
220
+<style lang="scss" scoped>
221
+.header{
222
+  width: 50px;
223
+  height: 50px;
224
+  img{
225
+    width: 100%;
226
+    height: 100%;
227
+  }
228
+}
229
+
230
+.system-table-search{
231
+  width: calc(100% - 40px);
232
+  margin: 20px auto 0;
233
+}
234
+
235
+.system-table-search li{
236
+  margin-right: 20px;
237
+}
238
+
239
+.system-table-search ul{
240
+  font-size: 0;
241
+  white-space: nowrap;
242
+}
243
+
244
+.system-table-search ul>li{
245
+  display: inline-block;
246
+}
247
+
248
+.flex-h {
249
+  display: flex;
250
+  display: -webkit-flex;
251
+}
252
+
253
+.flex-item {
254
+  flex: 1;
255
+  -webkit-flex: 1;
256
+  position: relative;
257
+  overflow: hidden;
258
+}
259
+</style>

+ 39
- 1
src/views/index.js Parādīt failu

@@ -28,8 +28,46 @@ const pages = [
28 28
           title: '置业列表',
29 29
         },
30 30
       },
31
+      {
32
+        path: 'edit/:id?',
33
+        name: 'consultant.edit',
34
+        component: () => import('./consultant/edit.vue'),
35
+        meta: {
36
+          menuShow: true,
37
+          title: '置业管理',
38
+        },
39
+      },
40
+    ]
41
+  },
42
+  {
43
+    path: 'building',
44
+    name: 'building',
45
+    component: () => import('./index.vue'),
46
+    meta: {
47
+      menuShow: true,
48
+      title: '楼盘设置',
49
+    },
50
+    children: [
51
+      {
52
+        path: 'dynamic',
53
+        name: 'dynamiclist',
54
+        component: () => import('./dynamic/list.vue'),
55
+        meta: {
56
+          menuShow: true,
57
+          title: '项目动态列表',
58
+        },
59
+      },
60
+      {
61
+        path: 'dynamic/edit',
62
+        name: 'dynamicedit',
63
+        component: () => import('./dynamic/edit.vue'),
64
+        meta: {
65
+          menuShow: false,
66
+          title: '项目动态编辑',
67
+        },
68
+      }
31 69
     ]
32
-  }
70
+  },
33 71
 ]
34 72
 
35 73
 const flatten = (rts, parents = []) => {