魏熙美 hace 6 años
padre
commit
49c719034c
Se han modificado 6 ficheros con 602 adiciones y 2 borrados
  1. 15
    1
      src/config/api.js
  2. 1
    1
      src/store/index.js
  3. 132
    0
      src/store/modules/goods.js
  4. 209
    0
      src/views/goods/edit.vue
  5. 188
    0
      src/views/goods/list.vue
  6. 57
    0
      src/views/index.js

+ 15
- 1
src/config/api.js Ver fichero

@@ -1,4 +1,4 @@
1
-const commPrefix = '/api/admin/'
1
+const commPrefix = '/api/admin'
2 2
 
3 3
 const apis = {
4 4
   system: {
@@ -127,6 +127,20 @@ const apis = {
127 127
       url: `${commPrefix}/customer/add`
128 128
     }
129 129
   },
130
+  goods:{
131
+    list:{
132
+      method:'get',
133
+      url: `${commPrefix}/taGoods`
134
+    },
135
+    detail: {
136
+      method: 'get',
137
+      url: `${commPrefix}/taGoods/:id`
138
+    },
139
+    add: {
140
+      method: 'post',
141
+      url: `${commPrefix}/customer/add`
142
+    }
143
+  },
130 144
   newsType: {
131 145
     list: {
132 146
       method: 'get',

+ 1
- 1
src/store/index.js Ver fichero

@@ -3,7 +3,6 @@ import Vuex from 'vuex'
3 3
 import system from './system'
4 4
 import apartment from './modules/apartment'
5 5
 import news from './modules/news'
6
-
7 6
 Vue.use(Vuex)
8 7
 
9 8
 const store = new Vuex.Store({
@@ -15,6 +14,7 @@ const store = new Vuex.Store({
15 14
     customer: require('./modules/customer').default,
16 15
     building: require('./modules/building').default,
17 16
     img: require('./modules/img').default,
17
+    goods: require('./modules/goods').default,
18 18
     news
19 19
   }
20 20
 })

+ 132
- 0
src/store/modules/goods.js Ver fichero

@@ -0,0 +1,132 @@
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
+    getGoods ({ commit }, payload) {
23
+      return new Promise((resolve, reject) => {
24
+        request({
25
+          ...apis.goods.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
+    getGoodsDetail ({ commit }, payload) {
40
+      return new Promise((resolve, reject) => {
41
+        request({
42
+          ...apis.goods.detail,
43
+          urlData: 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
+          if (typeof message === 'string') {
66
+            reject(message)
67
+          }
68
+        })
69
+      })
70
+    },
71
+    editDynamics (_, payload) {
72
+      return new Promise((resolve, reject) => {
73
+        request({
74
+          ...apis.dynamic.edit,
75
+          data: payload.detail,
76
+        }).then((data) => {
77
+          resolve(data)
78
+        }).catch((err) => {
79
+          const message = err.message || err.msg
80
+
81
+          if (typeof message === 'string') {
82
+            reject(message)
83
+          }
84
+        })
85
+      })
86
+    },
87
+    deleteDynamics (_, payload) {
88
+      return new Promise((resolve, reject) => {
89
+        request({
90
+          ...apis.dynamic.delete,
91
+          ...payload
92
+        }).then(() => {
93
+          resolve()
94
+        }).catch(() => {
95
+          reject()
96
+        })
97
+      })
98
+    },
99
+    publicDynamic (_, payload) {
100
+      return new Promise((resolve, reject) => {
101
+        request({
102
+          ...apis.dynamic.public,
103
+          urlData: payload,
104
+        }).then((data) => {
105
+          resolve(data)
106
+        }).catch((err) => {
107
+          const message = err.message || err.msg
108
+
109
+          if (typeof message === 'string') {
110
+            reject(message)
111
+          }
112
+        })
113
+      })
114
+    },
115
+    cancelDynamic (_, payload) {
116
+      return new Promise((resolve, reject) => {
117
+        request({
118
+          ...apis.dynamic.cancel,
119
+          urlData: payload,
120
+        }).then((data) => {
121
+          resolve(data)
122
+        }).catch((err) => {
123
+          const message = err.message || err.msg
124
+
125
+          if (typeof message === 'string') {
126
+            reject(message)
127
+          }
128
+        })
129
+      })
130
+    }
131
+  }
132
+}

+ 209
- 0
src/views/goods/edit.vue Ver fichero

@@ -0,0 +1,209 @@
1
+<template>
2
+  <div>
3
+    <div class="form-wrapper">
4
+      <el-form label-width="100px" :model="detail">
5
+        <el-form-item label="商品图片:">
6
+          <el-upload
7
+            class="avatar-uploader"
8
+            :action="upFileUrl"
9
+            name='file'
10
+            :show-file-list="false"
11
+            :before-upload="beforeImgUpload"
12
+            :on-success="handleAvatarSuccess">
13
+            <img v-if="detail.imgUrl" :src="detail.imgUrl" class="avatar">
14
+            <i v-else class="el-icon-plus avatar-uploader-icon"></i>
15
+          </el-upload>
16
+        </el-form-item>
17
+        <el-form-item label="商品名称:">
18
+          <el-input v-model="detail.goodsName"></el-input>
19
+        </el-form-item>
20
+        <el-form-item label="所需积分:">
21
+          <el-input v-model="detail.pointPrice"></el-input>
22
+        </el-form-item>
23
+        <el-form-item label="商品数量:">
24
+          <el-input v-model="detail.totalNum"></el-input>
25
+        </el-form-item>
26
+        <el-form-item label="剩余数量:">
27
+          <el-input v-model="detail.inventory"></el-input>
28
+        </el-form-item>
29
+        <el-form-item label="授权项目:">
30
+          <el-select v-model="detail.buildings" placeholder="请选择">
31
+            <el-option v-for="(build,i) in buildings.list || []" :key="i" :label="build.buildingName" :value="build.buildingId"></el-option>
32
+          </el-select>
33
+        </el-form-item>
34
+        <el-form-item label="商品详情:">
35
+            <div id="websiteEditorElem" style="height: 400px"></div>
36
+        </el-form-item>
37
+        <el-form-item label="状态:">
38
+          <el-radio-group v-model="detail.status">
39
+            <el-radio-button :label="0">禁用</el-radio-button>
40
+            <el-radio-button :label="1">启用</el-radio-button>
41
+          </el-radio-group>
42
+        </el-form-item>
43
+        <el-form-item label="领取地址:">
44
+          <el-input v-model="detail.tel"></el-input>
45
+        </el-form-item>
46
+        <el-form-item>
47
+          <el-button type="primary" @click="submitForm">保存</el-button>
48
+          <el-button @click="$router.go(-1)">返回</el-button>
49
+        </el-form-item>
50
+      </el-form>
51
+    </div>
52
+  </div>
53
+</template>
54
+
55
+<script>
56
+import { createNamespacedHelpers } from "vuex";
57
+import apis from "../../config/api";
58
+import E from "wangeditor";
59
+
60
+const { mapActions: mapGoodsActions } = createNamespacedHelpers("goods");
61
+const {
62
+  mapState: mapBuildingState,
63
+  mapActions: mapBuildingActions
64
+} = createNamespacedHelpers("building");
65
+export default {
66
+  name: "goodsEdit",
67
+  data() {
68
+    return {
69
+      upFileUrl: apis.file.upload.url,
70
+      detail: {}
71
+    };
72
+  },
73
+  created() {
74
+    this.init();
75
+  },
76
+  computed: {
77
+    ...mapBuildingState({
78
+      buildings: x => x.buildings
79
+    })
80
+  },
81
+  methods: {
82
+    ...mapBuildingActions(["getBuildings"]),
83
+    ...mapGoodsActions(["getGoodsDetail", "editConsultant"]),
84
+    init() {
85
+      if (this.$route.params.id) {
86
+        this.getGoodsDetail({ id: this.$route.params.id }).then(data => {
87
+          this.detail = data;
88
+        });
89
+      }
90
+    },
91
+    beforeImgUpload(file) {
92
+      if (file.type !== "image/jpeg" && file.type !== "image/png") {
93
+        this.$message.error("上传图片只能是 JPG 或 PNG 格式!");
94
+        return false;
95
+      }
96
+
97
+      this.showLoadding("上传中...");
98
+      return true;
99
+    },
100
+
101
+    handleAvatarSuccess(res) {
102
+      this.detail.photo = res.data;
103
+      this.hideLoadding();
104
+    },
105
+
106
+    submitForm() {
107
+      this.showLoadding("保存中...");
108
+      this.editConsultant(this.detail)
109
+        .then(res => {
110
+          if (res.personId) {
111
+            this.detail = res;
112
+          }
113
+
114
+          this.hideLoadding();
115
+          this.$notify.info("保存成功");
116
+        })
117
+        .catch(err => {
118
+          this.hideLoadding();
119
+          this.$notify.error(err.message);
120
+        });
121
+    },
122
+
123
+    showLoadding(text) {
124
+      this.loading = this.$loading({
125
+        text,
126
+        lock: true,
127
+        spinner: "el-icon-loading",
128
+        background: "rgba(255, 255, 255, 0.7)"
129
+      });
130
+    },
131
+
132
+    hideLoadding() {
133
+      if (this.loading) this.loading.close();
134
+    }
135
+  },
136
+  mounted() {
137
+    const _that = this;
138
+    const phoneEditor = new E("#websiteEditorElem");
139
+    phoneEditor.customConfig.onchange = function(html) {
140
+      _that.dynamic = { ..._that.dynamic, url: html };
141
+    };
142
+    // phoneEditor.customConfig.uploadImgServer = this.upFileUrl
143
+    // phoneEditor.customConfig.uploadFileName = 'uploadFiles'
144
+
145
+    phoneEditor.customConfig.customUploadImg = function(files, insert) {
146
+      _that.uploadImg(files[0]).then(data => {
147
+        insert(data);
148
+      });
149
+    };
150
+    phoneEditor.customConfig.menus = [
151
+      "head", // 标题
152
+      "bold", // 粗体
153
+      "fontSize", // 字号
154
+      "fontName", // 字体
155
+      "italic", // 斜体
156
+      "underline", // 下划线
157
+      "strikeThrough", // 删除线
158
+      "foreColor", // 文字颜色
159
+      "backColor", // 背景颜色
160
+      "justify", // 对齐方式
161
+      "image" // 插入图片
162
+    ];
163
+    phoneEditor.create()
164
+
165
+    // this.getBuildings({
166
+    //   pageNum: 1,
167
+    //   pageSize: 100
168
+    // }).then(() => {
169
+    //   if ((this.$route.query.id || "") !== "") {
170
+    //     this.getDetail({ id: this.$route.query.id }).then(data => {
171
+    //       phoneEditor.txt.html(data.url);
172
+    //     });
173
+    //   }
174
+    // });
175
+  }
176
+};
177
+</script>
178
+
179
+<style lang="scss" scoped>
180
+.form-wrapper {
181
+  width: 60%;
182
+}
183
+</style>
184
+
185
+<style lang="scss">
186
+.avatar-uploader .el-upload {
187
+  border: 1px dashed #d9d9d9;
188
+  border-radius: 6px;
189
+  cursor: pointer;
190
+  position: relative;
191
+  overflow: hidden;
192
+}
193
+.avatar-uploader .el-upload:hover {
194
+  border-color: #409eff;
195
+}
196
+.avatar-uploader-icon {
197
+  font-size: 28px;
198
+  color: #8c939d;
199
+  width: 178px;
200
+  height: 178px;
201
+  line-height: 178px;
202
+  text-align: center;
203
+}
204
+.avatar {
205
+  width: 178px;
206
+  height: 178px;
207
+  display: block;
208
+}
209
+</style>

+ 188
- 0
src/views/goods/list.vue Ver fichero

@@ -0,0 +1,188 @@
1
+<template>
2
+<div class="list">
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="filterData.goodsName" placeholder="商品名称"></el-input>
11
+          </li>
12
+
13
+        </ul>
14
+        <el-button
15
+          size="mini"
16
+          type="primary" @click="search">查询</el-button>
17
+      </div>
18
+      <div class="moreFilter"></div>
19
+    </div>
20
+  <el-table
21
+    :data="list || []"
22
+    style="width: 100%">
23
+    <el-table-column
24
+      label="商品图片">
25
+      <template slot-scope="scope">
26
+          <div class="header">
27
+            <img :src="scope.row.imgUrl" alt="" />
28
+          </div>
29
+        </template>
30
+    </el-table-column>
31
+    <el-table-column
32
+      prop="goodsName"
33
+      label="商品名称">
34
+    </el-table-column>
35
+    <el-table-column
36
+      prop="pointPrice"
37
+      label="所需积分">
38
+    </el-table-column>
39
+    <el-table-column
40
+      prop="totalNum"
41
+      label="总数量">
42
+    </el-table-column>
43
+    <el-table-column
44
+      label="已经兑换数量">
45
+      <template slot-scope="scope">
46
+        <span  >{{scope.row.totalNum -scope.row.inventory }}</span>
47
+      </template>
48
+    </el-table-column>
49
+    <el-table-column
50
+      prop="inventory"
51
+      label="剩余数量">
52
+    </el-table-column>
53
+    <el-table-column   label="状态">
54
+      <template slot-scope="scope">
55
+        <span :style="{color:(scope.row.status == 1?'':'red')}" >{{scope.row.status == 1 ? '已上架' : '未上架'}}</span>
56
+      </template>
57
+    </el-table-column>
58
+    <el-table-column
59
+      fixed="right"
60
+      label="操作">
61
+      <template slot-scope="scope">
62
+        <el-button type="text" @click="toDetail(scope.row)" size="small">{{scope.row.status == 1?'下架':'上架'}}</el-button>
63
+        <el-button type="text" @click="toDetail(scope.row)" size="small">编辑</el-button>
64
+      </template>
65
+    </el-table-column>
66
+  </el-table>
67
+  <el-pagination
68
+    small
69
+    style="margin-top:10px;"
70
+    layout="prev, pager, next"
71
+    :current-page.sync="pageNavi.current"
72
+    :pageSize="pageNavi.size"
73
+    :total="pageNavi.total || 0"
74
+    @current-change="getConsultants"
75
+  >
76
+  </el-pagination>
77
+</div>
78
+</template>
79
+
80
+<script>
81
+import { createNamespacedHelpers } from "vuex";
82
+
83
+const { mapActions: mapGoodsActions } = createNamespacedHelpers("goods");
84
+
85
+export default {
86
+  name: "goods-list",
87
+  data() {
88
+    return {
89
+      filterData: {
90
+        goodsName: ""
91
+      },
92
+      list: [],
93
+      pageNavi: {
94
+        current: 1,
95
+        size: 20,
96
+        total: 0
97
+      }
98
+    };
99
+  },
100
+  computed: {},
101
+  methods: {
102
+    ...mapGoodsActions(["getGoods"]),
103
+    getList() {
104
+      const pageNumber = this.pageNavi.current || 1;
105
+      const pageSize = this.pageNavi.size;
106
+
107
+      this.getGoods({
108
+        ...this.filterData,
109
+        pageNumber,
110
+        pageSize
111
+      })
112
+        .then(res => {
113
+          const { records, ...pageNavi } = res;
114
+
115
+          this.list = records;
116
+          this.pageNavi = pageNavi;
117
+        })
118
+        .catch(err => {
119
+          this.$notify.error(err.msg || err.message);
120
+        });
121
+    },
122
+    addDynamic() {
123
+      this.$router.push({ name: "consultant.list" });
124
+    },
125
+    toDetail(row) {
126
+      this.$router.push({
127
+        name: "goods.edit",
128
+        params: { id: row.goodsId }
129
+      });
130
+    },
131
+    search() {
132
+      this.pageNavi.current = 1;
133
+      this.getList();
134
+    },
135
+    newPage(page) {
136
+      this.$router.replace({ name: "consultant.list", query: { page } });
137
+    }
138
+  },
139
+  created() {
140
+    this.pageNavi.current = this.$route.query.page || 1;
141
+
142
+    this.getList();
143
+  }
144
+};
145
+</script>
146
+
147
+<style lang="scss" scoped>
148
+.list {
149
+  .header {
150
+    width: 50px;
151
+    height: 50px;
152
+    border-radius: 50%;
153
+  }
154
+  img {
155
+      width: 100%;
156
+      height: 100%;
157
+    }
158
+}
159
+.system-table-search {
160
+  width: calc(100% - 40px);
161
+  margin: 20px auto 0;
162
+}
163
+
164
+.system-table-search li {
165
+  margin-right: 20px;
166
+}
167
+
168
+.system-table-search ul {
169
+  font-size: 0;
170
+  white-space: nowrap;
171
+}
172
+
173
+.system-table-search ul > li {
174
+  display: inline-block;
175
+}
176
+
177
+.flex-h {
178
+  display: flex;
179
+  align-items: center;
180
+}
181
+
182
+.flex-item {
183
+  flex: 1;
184
+  -webkit-flex: 1;
185
+  position: relative;
186
+  overflow: hidden;
187
+}
188
+</style>

+ 57
- 0
src/views/index.js Ver fichero

@@ -192,6 +192,63 @@ const pages = [
192 192
       }
193 193
     ]
194 194
   },
195
+  {
196
+    path: 'pointsmall',
197
+    name: 'pointsmall',
198
+    redirect: 'pointsmall/list',
199
+    component: () => import('./index.vue'),
200
+    meta: {
201
+      menuShow: true,
202
+      title: '积分商城',
203
+    },
204
+    children: [
205
+      {
206
+        path: 'list',
207
+        name: 'goods.list',
208
+        component: () => import('./goods/list.vue'),
209
+        meta: {
210
+          menuShow: true,
211
+          title: '商品列表',
212
+        },
213
+      },
214
+      {
215
+        path: 'goods/edit',
216
+        name: 'goods.edit',
217
+        component: () => import('./goods/edit.vue'),
218
+        meta: {
219
+          menuShow: false,
220
+          title: '编辑商品',
221
+        },
222
+      },
223
+      {
224
+        path: 'edit/:id?',
225
+        name: 'pointsmall.edit',
226
+        component: () => import('./consultant/edit.vue'),
227
+        meta: {
228
+          menuShow: true,
229
+          title: '积分获取',
230
+        },
231
+      },
232
+      {
233
+        path: 'edit/:id?',
234
+        name: 'consultant.edit',
235
+        component: () => import('./consultant/edit.vue'),
236
+        meta: {
237
+          menuShow: true,
238
+          title: '商品核销',
239
+        },
240
+      },
241
+      {
242
+        path: 'edit/:id?',
243
+        name: 'consultant.edit',
244
+        component: () => import('./consultant/edit.vue'),
245
+        meta: {
246
+          menuShow: true,
247
+          title: '兑换记录',
248
+        },
249
+      },
250
+    ]
251
+  },
195 252
 ]
196 253
 
197 254
 const flatten = (rts, parents = []) => {