wangfei 6 年 前
コミット
3cf9be4590
共有7 個のファイルを変更した571 個の追加2 個の削除を含む
  1. 22
    0
      src/config/api.js
  2. 3
    1
      src/store/index.js
  3. 84
    0
      src/store/modules/propaganda.js
  4. 33
    1
      src/views/building/edit.vue
  5. 185
    0
      src/views/cms/propagandaEdit.vue
  6. 226
    0
      src/views/cms/propagandaList.vue
  7. 18
    0
      src/views/index.js

+ 22
- 0
src/config/api.js ファイルの表示

@@ -202,6 +202,28 @@ const apis = {
202 202
       method: 'put',
203 203
       url: `${commPrefix}/buildingDynamic/cancel/:id`
204 204
     }
205
+  },
206
+  propaganda: {
207
+    list: {
208
+      method: 'get',
209
+      url: `${commPrefix}/propagandaList`
210
+    },
211
+    detail: {
212
+      method: 'get',
213
+      url: `${commPrefix}/propaganda/:id`
214
+    },
215
+    add: {
216
+      method: 'post',
217
+      url: `${commPrefix}/propaganda/add`
218
+    },
219
+    update: {
220
+      method: 'put',
221
+      url: `${commPrefix}/propaganda/update`
222
+    },
223
+    delete: {
224
+      method: 'delete',
225
+      url: `${commPrefix}/propaganda/delete/:id`
226
+    }
205 227
   }
206 228
 }
207 229
 

+ 3
- 1
src/store/index.js ファイルの表示

@@ -10,6 +10,7 @@ import apartment from './modules/apartment'
10 10
 import comment from './modules/comment'
11 11
 import banner from './modules/banner'
12 12
 import dynamic from './modules/dynamic'
13
+import propaganda from './modules/propaganda'
13 14
 
14 15
 Vue.use(Vuex)
15 16
 
@@ -24,7 +25,8 @@ const store = new Vuex.Store({
24 25
     apartment,
25 26
     comment,
26 27
     banner,
27
-    dynamic
28
+    dynamic,
29
+    propaganda
28 30
   }
29 31
 })
30 32
 

+ 84
- 0
src/store/modules/propaganda.js ファイルの表示

@@ -0,0 +1,84 @@
1
+import lodash from 'lodash'
2
+import { interact, replaceApiParams } from '../../utils'
3
+import apis from '../../config/api'
4
+
5
+export default {
6
+  namespaced: true,
7
+  state: {
8
+    propagandas: {},
9
+    detail: {}
10
+  },
11
+  mutations: {
12
+    updateList (state, payload) {
13
+      state.propagandas = payload
14
+    },
15
+    updateDetail (state, payload) {
16
+      state.detail = payload
17
+    }
18
+  },
19
+  actions: {
20
+    setDetailNull ({ commit }) {
21
+      commit('updateDetail', {})
22
+    },
23
+    getPropagandas ({ commit }, payload) {
24
+      return new Promise((resolve, reject) => {
25
+        const api = lodash.get(apis, 'propaganda.list')
26
+        interact(api, payload).then((data) => {
27
+          commit('updateList', data)
28
+          resolve(data)
29
+        }).catch(({ message }) => {
30
+          if (typeof message === 'string') {
31
+            reject(message)
32
+          }
33
+        })
34
+      })
35
+    },
36
+    getDetail ({ commit }, payload) {
37
+      return new Promise((resolve, reject) => {
38
+        const api = replaceApiParams(lodash.get(apis, 'propaganda.detail'), payload)
39
+        interact(api).then((data) => {
40
+          commit('updateDetail', data)
41
+          resolve(data)
42
+        }).catch(({ message }) => {
43
+          if (typeof message === 'string') {
44
+            reject(message)
45
+          }
46
+        })
47
+      })
48
+    },
49
+    addPropaganda (_, payload) {
50
+      return new Promise((resolve, reject) => {
51
+        const api = lodash.get(apis, 'propaganda.add')
52
+        interact(api, payload).then((data) => {
53
+          resolve(data)
54
+        }).catch(({ message }) => {
55
+          if (typeof message === 'string') {
56
+            reject(message)
57
+          }
58
+        })
59
+      })
60
+    },
61
+    editPropaganda (_, payload) {
62
+      return new Promise((resolve, reject) => {
63
+        const api = lodash.get(apis, 'propaganda.update')
64
+        interact(api, payload).then((data) => {
65
+          resolve(data)
66
+        }).catch(({ message }) => {
67
+          if (typeof message === 'string') {
68
+            reject(message)
69
+          }
70
+        })
71
+      })
72
+    },
73
+    deletePropaganda (_, payload) {
74
+      return new Promise((resolve, reject) => {
75
+        const api = replaceApiParams(lodash.get(apis, 'propaganda.delete'), payload)
76
+        interact(api).then(() => {
77
+          resolve()
78
+        }).catch(() => {
79
+          reject()
80
+        })
81
+      })
82
+    }
83
+  }
84
+}

+ 33
- 1
src/views/building/edit.vue ファイルの表示

@@ -32,6 +32,19 @@
32 32
             <el-option v-for="(t,i) in propertyType" :key="i" :label="t.name" :value="t.id"></el-option>
33 33
           </el-select>
34 34
         </el-form-item>
35
+        <el-form-item label="销售状态">
36
+          <el-input v-model="building.marketStatus"></el-input>
37
+        </el-form-item>
38
+        <el-form-item label="标签">
39
+          <el-select
40
+            v-model="tags"
41
+            multiple
42
+            filterable
43
+            allow-create
44
+            default-first-option
45
+            placeholder="请输入标签">
46
+          </el-select>
47
+        </el-form-item>
35 48
         <el-form-item label="项目主图">
36 49
           <el-upload
37 50
             :action="upFileUrl"
@@ -48,6 +61,18 @@
48 61
             <img width="100%" :src="dialogImageUrl" alt="">
49 62
           </el-dialog>
50 63
         </el-form-item>
64
+        <el-form-item label="排序">
65
+          <el-input v-model="building.orderNo"></el-input>
66
+        </el-form-item>
67
+        <el-form-item label="优惠信息">
68
+          <el-input v-model="building.discount"></el-input>
69
+        </el-form-item>
70
+        <el-form-item label="首页推荐">
71
+          <el-radio-group v-model="building.isMain">
72
+            <el-radio :label="1">是</el-radio>
73
+            <el-radio :label="0">否</el-radio>
74
+          </el-radio-group>
75
+        </el-form-item>
51 76
         <el-form-item label="项目备注">
52 77
           <div id="websiteEditorElem" style="height: 400px"></div>
53 78
         </el-form-item>
@@ -198,6 +223,7 @@ export default {
198 223
       showHx: false,
199 224
       markers: [],
200 225
       imgList: [],
226
+      tags: [],
201 227
       buildingProperty: [],
202 228
       aparments: [],
203 229
       aparmentInfo: {},
@@ -322,7 +348,12 @@ export default {
322 348
           orderNo: (i + 1)
323 349
         }
324 350
       })
325
-      const building = {...this.building, img: imgs, propertyType: this.buildingProperty.join(',')}
351
+      const tag = this.tags.map(x => {
352
+        return {
353
+          tagName: x
354
+        }
355
+      })
356
+      const building = {...this.building, img: imgs, propertyType: this.buildingProperty.join(','), tag}
326 357
       if (!building.buildingId) {
327 358
         // 新增
328 359
         this.addBuilding({
@@ -448,6 +479,7 @@ export default {
448 479
             url: x.url
449 480
           }
450 481
         })
482
+        this.tags = data.buildingTag.map(x => x.tagName)
451 483
       })
452 484
     } else {
453 485
       phoneEditor.txt.html('')

+ 185
- 0
src/views/cms/propagandaEdit.vue ファイルの表示

@@ -0,0 +1,185 @@
1
+<template>
2
+  <el-form ref="form" :model="propaganda" label-width="160px">
3
+    <el-form-item label="主图">
4
+      <el-upload
5
+        class="avatar-uploader"
6
+        :action="upFileUrl"
7
+        name='uploadFiles'
8
+        :show-file-list="false"
9
+        :before-upload="beforeImgUpload"
10
+        :on-success="handleAvatarSuccess">
11
+        <img v-if="propaganda.imgUrl" :src="propaganda.imgUrl" class="avatar">
12
+        <i v-else class="el-icon-plus avatar-uploader-icon"></i>
13
+      </el-upload>
14
+    </el-form-item>
15
+    <el-form-item label="跳转类型">
16
+      <el-select v-model="propaganda.skipType" @change="skipTypeChange" placeholder="请选择">
17
+        <el-option label="楼盘" value="building"></el-option>
18
+        <el-option label="活动" value="activity"></el-option>
19
+      </el-select>
20
+    </el-form-item>
21
+    <el-form-item label="选择跳转主体">
22
+      <el-select v-model="propaganda.skipId" placeholder="请选择">
23
+        <el-option v-for="(item,i) in skipList" :key="i" :label="item.name" :value="item.id"></el-option>
24
+      </el-select>
25
+    </el-form-item>
26
+    <el-form-item>
27
+      <el-button type="primary" @click="onSubmit">保存</el-button>
28
+      <el-button @click="onCancel">取消</el-button>
29
+    </el-form-item>
30
+  </el-form>
31
+</template>
32
+
33
+<script>
34
+import { createNamespacedHelpers } from 'vuex'
35
+import apis from '../../config/api'
36
+
37
+const { mapState: mapPropagandaState, mapActions: mapPropagandaActions, mapMutations: mapPropagandaMutations } = createNamespacedHelpers('propaganda')
38
+const { mapState: mapBuildingState, mapActions: mapBuildingActions } = createNamespacedHelpers('building')
39
+const { mapState: mapActivityState, mapActions: mapActivityActions } = createNamespacedHelpers('activity')
40
+const { mapActions: mapImgActions } = createNamespacedHelpers('img')
41
+
42
+export default {
43
+  data () {
44
+    return {
45
+      upFileUrl: apis.file.upload.url,
46
+    }
47
+  },
48
+  computed: {
49
+    ...mapPropagandaState({
50
+      detail: x => x.detail,
51
+    }),
52
+    propaganda: {
53
+      get () {
54
+        return this.detail
55
+      },
56
+      set (val) {
57
+        return this.updateDetail(val)
58
+      }
59
+    },
60
+    ...mapBuildingState({
61
+      buildings: x => x.buildings
62
+    }),
63
+    ...mapActivityState({
64
+      activitys: x => x.activitys
65
+    }),
66
+    skipList() {
67
+      if (!this.propaganda.skipType || this.propaganda.skipType == ''){
68
+        return []
69
+      }
70
+      return this.propaganda.skipType === 'building' ? (this.buildings.list || []).map(x => {
71
+        return {
72
+          id: x.buildingId,
73
+          name: x.buildingName
74
+        }
75
+      }) : (this.activitys.records || []).map(x => {
76
+        return {
77
+          id: x.activityId,
78
+          name: x.title
79
+        }
80
+      })
81
+    }
82
+  },
83
+  methods: {
84
+    ...mapBuildingActions([
85
+      'getBuildings'
86
+    ]),
87
+    ...mapActivityActions([
88
+      'getActivitys',
89
+    ]),
90
+    ...mapPropagandaMutations([
91
+      'updateDetail'
92
+    ]),
93
+    ...mapPropagandaActions([
94
+      'getDetail',
95
+      'addPropaganda',
96
+      'editPropaganda'
97
+    ]),
98
+    ...mapImgActions([
99
+      'uploadImg'
100
+    ]),
101
+    skipTypeChange () {
102
+      this.propaganda = {...this.propaganda, skipId: ''}
103
+    },
104
+    beforeImgUpload (file) {
105
+      if (file.type !== 'image/jpeg' && file.type !== 'image/png') {
106
+        this.$message.error('上传图片只能是 JPG 或 PNG 格式!')
107
+        return false
108
+      }
109
+      // if (file.size / 1024 > 300) {
110
+      //   this.$message.error('图片大小不允许超过300k!')
111
+      //   return false
112
+      // }
113
+      this.loading = this.$loading({
114
+        lock: true,
115
+        text: '上传中...',
116
+        spinner: 'el-icon-loading',
117
+        background: 'rgba(0, 0, 0, 0.7)'
118
+      })
119
+
120
+      return true
121
+    },
122
+    handleAvatarSuccess (res) {
123
+      this.updateDetail({...this.propaganda, imgUrl: res.data[0]})
124
+      this.loading.close()
125
+    },
126
+    onSubmit () {
127
+      if (!this.detail.propagandaId) {
128
+        // 新增
129
+        this.addPropaganda(JSON.stringify(this.detail)).then(() => {
130
+          this.onCancel()
131
+        })
132
+      } else {
133
+        // 修改
134
+        this.editPropaganda(JSON.stringify(this.detail)).then(() => {
135
+          this.onCancel()
136
+        })
137
+      }
138
+    },
139
+    onCancel () {
140
+      this.$router.push({name: 'propagandaList'})
141
+    }
142
+  },
143
+  mounted () {
144
+    this.getBuildings({
145
+      pageNum: 1,
146
+      pageSize: 100,
147
+    }).then(() => {
148
+      this.getActivitys({
149
+        pageNum: 1,
150
+        pageSize: 100,
151
+      }).then(() => {
152
+        if ((this.$route.query.id || '') !== '') {
153
+          this.getDetail({id: this.$route.query.id})
154
+        }
155
+      })
156
+    })
157
+  }
158
+}
159
+</script>
160
+
161
+<style lang="scss">
162
+  .avatar-uploader .el-upload {
163
+    border: 1px dashed #d9d9d9;
164
+    border-radius: 6px;
165
+    cursor: pointer;
166
+    position: relative;
167
+    overflow: hidden;
168
+  }
169
+  .avatar-uploader .el-upload:hover {
170
+    border-color: #409EFF;
171
+  }
172
+  .avatar-uploader-icon {
173
+    font-size: 28px;
174
+    color: #8c939d;
175
+    width: 178px;
176
+    height: 178px;
177
+    line-height: 178px;
178
+    text-align: center;
179
+  }
180
+  .avatar {
181
+    width: 178px;
182
+    height: 178px;
183
+    display: block;
184
+  }
185
+</style>

+ 226
- 0
src/views/cms/propagandaList.vue ファイルの表示

@@ -0,0 +1,226 @@
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='addPropaganda'>新增宣传</el-button>
7
+        </div>
8
+      </div>
9
+    </div>
10
+    <el-table
11
+      :data="propagandas.records || []"
12
+      style="width: 100%">
13
+      <el-table-column
14
+        type="index"
15
+        width="50">
16
+        <template slot-scope="scope">
17
+          <span>{{ GetIndex(scope.$index) }}</span>
18
+        </template>
19
+      </el-table-column>
20
+      <el-table-column
21
+        label="主图">
22
+        <template slot-scope="scope">
23
+          <div class="header">
24
+            <img :src="scope.row.imgUrl" alt="" />
25
+          </div>
26
+        </template>
27
+      </el-table-column>
28
+      <el-table-column
29
+        prop="skipType"
30
+        label="跳转类型">
31
+        <template slot-scope="scope">
32
+          <span>
33
+            {{getSkipType(scope.row.skipType)}}
34
+          </span>
35
+        </template>
36
+      </el-table-column>
37
+      <el-table-column
38
+        label="跳转内容名称">
39
+        <template slot-scope="scope">
40
+          <span>{{getSkipName(scope.row.skipType,scope.row.skipId)}}</span>
41
+        </template>
42
+      </el-table-column>
43
+      <el-table-column
44
+        label="创建时间"
45
+        width="200"
46
+        prop="createDate"
47
+      >
48
+      </el-table-column>
49
+      <el-table-column
50
+        fixed="right"
51
+        label="操作"
52
+        width="180">
53
+        <template slot-scope="scope">
54
+          <el-button type="text" @click="handleEdit(scope.row)" size="small">编辑</el-button>
55
+          <el-button @click="handleDel(scope.row)" type="text" size="small">删除</el-button>
56
+        </template>
57
+      </el-table-column>
58
+    </el-table>
59
+    <el-pagination
60
+      small
61
+      style="margin-top:10px;"
62
+      layout="prev, pager, next"
63
+      :current-page.sync="currentPage"
64
+      :pageSize="pageSize"
65
+      :total="propagandas.total || 0"
66
+      @current-change="getList"
67
+    >
68
+    </el-pagination>
69
+  </div>
70
+</template>
71
+
72
+<script>
73
+import { createNamespacedHelpers } from 'vuex';
74
+
75
+const {mapState: mapPropagandaState, mapActions: mapPropagandaActions} = createNamespacedHelpers('propaganda')
76
+
77
+const {mapState: mapBuildingState, mapActions: mapBuildingActions} = createNamespacedHelpers('building')
78
+
79
+const {mapState: mapActivityState, mapActions: mapActivityActions} = createNamespacedHelpers('activity')
80
+
81
+export default {
82
+  data() {
83
+    return {
84
+      pageSize: 20,
85
+      currentPage: 1,
86
+    }
87
+  },
88
+  computed: {
89
+    ...mapPropagandaState({
90
+      propagandas: x => x.propagandas
91
+    }),
92
+    ...mapBuildingState({
93
+      buildings: x => x.buildings
94
+    }),
95
+    ...mapActivityState({
96
+      activitys: x => x.activitys
97
+    })
98
+  },
99
+  methods: {
100
+    ...mapPropagandaActions([
101
+      'getPropagandas',
102
+      'setDetailNull',
103
+      'deletePropaganda'
104
+    ]),
105
+    ...mapBuildingActions([
106
+      'getBuildings',
107
+    ]),
108
+    ...mapActivityActions([
109
+      'getActivitys',
110
+    ]),
111
+    GetIndex (inx) {
112
+      return (this.currentPage - 1) * this.pageSize + inx + 1
113
+    },
114
+    FormatDate (date) {
115
+      if (date) {
116
+        return date.split('T')[0] === '0001-01-01' ? '' : date.split('T')[0] + '  ' + date.split('T')[1]
117
+      } else {
118
+        return ''
119
+      }
120
+    },
121
+    getList () {
122
+      this.getPropagandas({
123
+        pageNum: this.currentPage,
124
+        pageSize: this.pageSize
125
+      })
126
+    },
127
+    getSkipType (type) {
128
+      if (type==='building') {
129
+        return '楼盘'
130
+      }
131
+      if (type==='activity') {
132
+        return '活动'
133
+      }
134
+      return ''
135
+    },
136
+    getSkipName (type,id) {
137
+      if (type === 'building') {
138
+        return this.getBuildingName(id)
139
+      } else {
140
+        return this.getActivityName(id)
141
+      }
142
+    },
143
+    getBuildingName (id) {
144
+      return ((this.buildings.list || []).filter(x => x.buildingId === id)[0] || {}).buildingName || ''
145
+    },
146
+    getActivityName (id) {
147
+      return ((this.activitys.records || []).filter(x => x.activityId === id)[0] || {}).title || ''
148
+    },
149
+    handleEdit (row) {
150
+      this.setDetailNull()
151
+      this.$router.push({name: 'propagandaEdit', query: {id: row.propagandaId}})
152
+    },
153
+    handleDel (row) {
154
+      this.$confirm('确认删除此数据?', '提示', {
155
+        confirmButtonText: '确定',
156
+        cancelButtonText: '取消',
157
+        type: 'warning'
158
+      }).then(() => {
159
+        this.deletePropagandas({
160
+          id: row.propagandaId
161
+        }).then(() => {
162
+          this.getList()
163
+        })
164
+      })
165
+    },
166
+    addPropaganda () {
167
+      this.setDetailNull()
168
+      this.$router.push({name: 'propagandaEdit'})
169
+    }
170
+  },
171
+  created () {
172
+    this.getBuildings({
173
+      pageNum: 1,
174
+      pageSize: 100,
175
+    }).then(() => {
176
+      this.getActivitys({
177
+        pageNum: 1,
178
+        pageSize: 100,
179
+      }).then(() => {
180
+        this.getList()
181
+      })
182
+    })
183
+  }
184
+}
185
+</script>
186
+
187
+<style lang="scss" scoped>
188
+.header{
189
+  width: 50px;
190
+  height: 50px;
191
+  img{
192
+    width: 100%;
193
+    height: 100%;
194
+  }
195
+}
196
+
197
+.system-table-search{
198
+  width: calc(100% - 40px);
199
+  margin: 20px auto 0;
200
+}
201
+
202
+.system-table-search li{
203
+  margin-right: 20px;
204
+}
205
+
206
+.system-table-search ul{
207
+  font-size: 0;
208
+  white-space: nowrap;
209
+}
210
+
211
+.system-table-search ul>li{
212
+  display: inline-block;
213
+}
214
+
215
+.flex-h {
216
+  display: flex;
217
+  display: -webkit-flex;
218
+}
219
+
220
+.flex-item {
221
+  flex: 1;
222
+  -webkit-flex: 1;
223
+  position: relative;
224
+  overflow: hidden;
225
+}
226
+</style>

+ 18
- 0
src/views/index.js ファイルの表示

@@ -18,6 +18,24 @@ const pages = [
18 18
       title: 'CMS管理',
19 19
     },
20 20
     children: [
21
+      {
22
+        path: 'propagandaList',
23
+        name: 'propagandaList',
24
+        component: () => import('./cms/propagandaList.vue'),
25
+        meta: {
26
+          menuShow: true,
27
+          title: '宣传设置',
28
+        },
29
+      },
30
+      {
31
+        path: 'propagandaEdit',
32
+        name: 'propagandaEdit',
33
+        component: () => import('./cms/propagandaEdit.vue'),
34
+        meta: {
35
+          menuShow: false,
36
+          title: '宣传设置',
37
+        },
38
+      },
21 39
       {
22 40
         path: 'pageBannerList',
23 41
         name: 'pageBannerList',