50
+    method: 'post',
51
+    data: qs.stringify(data)
52
+  })
53
+}
54
+
55
+export function fetchGoodsList(data) {
56
+  if (data === undefined) {
57
+    data = {}
58
+  }
59
+  data['admin_id'] = store.getters.token
60
+  return request({
61
+    url: '/admin/live/goods/list',
62
+    method: 'post',
63
+    data: qs.stringify(data)
64
+  })
65
+}
66
+
67
+export function createGoods(data) {
68
+  if (data === undefined) {
69
+    data = {}
70
+  }
71
+  data['admin_id'] = store.getters.token
72
+  return request({
73
+    url: '/admin/live/goods/create',
74
+    method: 'post',
75
+    data: qs.stringify(data)
76
+  })
77
+}
78
+
79
+export function updateGoods(data) {
80
+  if (data === undefined) {
81
+    data = {}
82
+  }
83
+  data['admin_id'] = store.getters.token
84
+  return request({
85
+    url: '/admin/live/goods/update',
86
+    method: 'post',
87
+    data: qs.stringify(data)
88
+  })
89
+}
90
+
91
+export function auditGoods(data) {
92
+  if (data === undefined) {
93
+    data = {}
94
+  }
95
+  data['admin_id'] = store.getters.token
96
+  return request({
97
+    url: '/admin/live/goods/audit',
98
+    method: 'post',
99
+    data: qs.stringify(data)
100
+  })
101
+}
102
+
103
+export function deleteGoods(data) {
104
+  if (data === undefined) {
105
+    data = {}
106
+  }
107
+  data['admin_id'] = store.getters.token
108
+  return request({
109
+    url: '/admin/live/goods/delete',
110
+    method: 'post',
111
+    data: qs.stringify(data)
112
+  })
113
+}
114
+
115
+export function fetchRoomGoodsList(data) {
116
+  if (data === undefined) {
117
+    data = {}
118
+  }
119
+  data['admin_id'] = store.getters.token
120
+  return request({
121
+    url: '/admin/room/goods/list',
122
+    method: 'post',
123
+    data: qs.stringify(data)
124
+  })
125
+}
126
+
127
+export function addRoomGoods(data) {
128
+  if (data === undefined) {
129
+    data = {}
130
+  }
131
+  data['admin_id'] = store.getters.token
132
+  return request({
133
+    url: '/admin/room/goods/add',
134
+    method: 'post',
135
+    data: qs.stringify(data)
136
+  })
137
+}
138
+
139
+export function publishRoomGoods(data) {
140
+  if (data === undefined) {
141
+    data = {}
142
+  }
143
+  data['admin_id'] = store.getters.token
144
+  return request({
145
+    url: '/admin/room/goods/publish',
146
+    method: 'post',
147
+    data: qs.stringify(data)
148
+  })
149
+}
150
+
151
+export function offRoomGoods(data) {
152
+  if (data === undefined) {
153
+    data = {}
154
+  }
155
+  data['admin_id'] = store.getters.token
156
+  return request({
157
+    url: '/admin/room/goods/off',
158
+    method: 'post',
159
+    data: qs.stringify(data)
160
+  })
161
+}
162
+
163
+export function updateRoomGoods(data) {
164
+  if (data === undefined) {
165
+    data = {}
166
+  }
167
+  data['admin_id'] = store.getters.token
168
+  return request({
169
+    url: '/admin/room/goods/update',
170
+    method: 'post',
171
+    data: qs.stringify(data)
172
+  })
173
+}

+ 0 - 0
src/api/uploadFile.js


+ 1 - 0
src/icons/svg/live.svg

@@ -0,0 +1 @@
1
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1590488890414" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5471" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M866.3 723.2c19.6 0 35.5-15.9 35.5-35.5 0-0.7 0.1-1 0.1-1.4V345.1c0-0.4-0.1-0.7-0.1-1.4 0-19.6-15.9-35.5-35.5-35.5-6 0-11.6 1.5-16.5 4.1h-0.2l-108.3 58.5v-87c0-49.3-39.9-89.2-89.2-89.2h-446c-49.3 0-89.2 39.9-89.2 89.2v446c0 49.3 39.9 89.2 89.2 89.2h446c49.3 0 89.2-39.9 89.2-89.2v-69.3l108.9 58.8c4.9 2.3 10.3 3.9 16.1 3.9z" p-id="5472"></path></svg>

+ 1 - 0
src/icons/svg/order.svg

@@ -0,0 +1 @@
1
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1590489068967" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7923" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M234.41187483 992.49378741a133.62303423 133.62303423 0 0 1-133.43998896-133.43998897V164.94620156A133.62303423 133.62303423 0 0 1 234.41187483 31.50621259h555.26777297a133.62303423 133.62303423 0 0 1 133.43998897 133.43998897v694.01607427a133.62303423 133.62303423 0 0 1-133.43998897 133.43998895z m0-902.23004882a74.86550821 74.86550821 0 0 0-74.7739856 74.77398558v694.01607427a74.86550821 74.86550821 0 0 0 74.7739856 74.77398558h555.26777297a74.86550821 74.86550821 0 0 0 74.7739856-74.77398558V164.94620156a74.86550821 74.86550821 0 0 0-74.7739856-74.77398558z" p-id="7924"></path><path d="M292.34569718 541.37876299a29.37876299 29.37876299 0 1 1 0-58.66600335h439.30860564a29.37876299 29.37876299 0 1 1 0 58.66600335zM292.34569718 680.12706427a29.37876299 29.37876299 0 1 1 0-58.29991287h299.73660072a29.37876299 29.37876299 0 1 1 0 58.75752601zM292.34569718 402.1728486a29.37876299 29.37876299 0 1 1 0-58.75752601h439.30860564a29.37876299 29.37876299 0 1 1 0 58.75752601z" p-id="7925"></path></svg>

+ 1 - 0
src/icons/svg/warehouse.svg

@@ -0,0 +1 @@
1
+<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1590489008972" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="7027" width="128" height="128" xmlns:xlink="http://www.w3.org/1999/xlink"><defs><style type="text/css"></style></defs><path d="M220.4 96h583.1c42.4 0 78.1 31.9 82.7 74.1l73.2 665.7c2.6 23.5-5 47-20.7 64.6C923 918 900.4 928 876.8 928H147.2c-23.7 0-46.2-10.1-62-27.7-15.8-17.6-23.3-41.1-20.7-64.6L137.7 170c4.7-42.1 40.3-74 82.7-74zM304 345.6c0 114.9 93.1 208 208 208s208-93.1 208-208c-0.1-22.9-18.7-41.4-41.6-41.4-22.9 0-41.5 18.5-41.6 41.4 0 68.9-55.9 124.8-124.8 124.8s-124.8-55.9-124.8-124.8c0.1-14.9-7.8-28.7-20.7-36.2-12.9-7.5-28.8-7.5-41.7 0-13 7.5-20.9 21.3-20.8 36.2z m0 0" p-id="7028"></path></svg>

+ 3 - 0
src/main.js

@@ -12,6 +12,7 @@ import '@/styles/index.scss' // global css
12 12
 import App from './App'
13 13
 import store from './store'
14 14
 import router from './router'
15
+import * as math from 'mathjs'
15 16
 
16 17
 import './icons' // icon
17 18
 import './permission' // permission control
@@ -41,6 +42,8 @@ Object.keys(filters).forEach(key => {
41 42
   Vue.filter(key, filters[key])
42 43
 })
43 44
 
45
+Vue.prototype.$math = math
46
+
44 47
 Vue.config.productionTip = false
45 48
 
46 49
 new Vue({

+ 35 - 4
src/router/index.js

@@ -85,15 +85,46 @@ export const constantRoutes = [
85 85
  * the routes that need to be dynamically loaded based on user roles
86 86
  */
87 87
 export const asyncRoutes = [
88
+  // {
89
+  //   path: '/order',
90
+  //   component: Layout,
91
+  //   children: [
92
+  //     {
93
+  //       path: '',
94
+  //       component: () => import('@/views/order/index'),
95
+  //       name: 'Order',
96
+  //       meta: { title: '订单详情', icon: 'icon', noCache: true }
97
+  //     }
98
+  //   ]
99
+  // },
88 100
   {
89
-    path: '/order',
101
+    path: '/live',
90 102
     component: Layout,
103
+    meta: { title: '直播', icon: 'live', noCache: true },
91 104
     children: [
92 105
       {
93
-        path: '',
94
-        component: () => import('@/views/order/index'),
106
+        path: 'room',
107
+        component: () => import('@/views/live/room'),
108
+        name: 'Room',
109
+        meta: { title: '直播间列表', icon: 'table', noCache: true }
110
+      },
111
+      {
112
+        path: 'order',
113
+        component: () => import('@/views/live/order'),
95 114
         name: 'Order',
96
-        meta: { title: '订单详情', icon: 'icon', noCache: true }
115
+        meta: { title: '订单', icon: 'order', noCache: true }
116
+      },
117
+      {
118
+        path: 'goods',
119
+        component: () => import('@/views/live/goods'),
120
+        name: 'Goods',
121
+        meta: { title: '商品库', icon: 'warehouse', noCache: true }
122
+      },
123
+      {
124
+        path: 'roomGoods',
125
+        component: () => import('@/views/live/roomGoods'),
126
+        name: 'roomGoods',
127
+        meta: { title: '直播间商品库', icon: 'warehouse', noCache: true }
97 128
       }
98 129
     ]
99 130
   },

+ 2 - 2
src/utils/request.js

@@ -1,11 +1,11 @@
1 1
 import axios from 'axios'
2 2
 import { MessageBox, Message } from 'element-ui'
3 3
 import store from '@/store'
4
-import { getToken } from '@/utils/auth'
4
+// import { getToken } from '@/utils/auth'
5 5
 
6 6
 // create an axios instance
7 7
 const service = axios.create({
8
-  baseURL: 'http://kodo.xfoto.com.cn/api', // url = base url + request url
8
+  baseURL: 'http://jh.kodo.com.cn/api', // url = base url + request url
9 9
   // withCredentials: true, // send cookies when cross-domain requests
10 10
   timeout: 5000 // request timeout
11 11
 })

+ 386 - 0
src/views/live/goods.vue

@@ -0,0 +1,386 @@
1
+<template>
2
+  <div class="app-container">
3
+    <div class="filter-container">
4
+      <el-button v-waves class="filter-item" type="primary" icon="el-icon-circle-plus-outline" @click="handleCreate">
5
+        新增
6
+      </el-button>
7
+      <el-button v-waves :loading="refreshNetworkLoading" class="filter-item" type="primary" icon="el-icon-refresh" @click="handleRefreshAudit">
8
+        刷新审核状态
9
+      </el-button>
10
+      <el-checkbox v-model="showGoodsID" class="filter-item" style="margin-left:15px;">
11
+        商品ID
12
+      </el-checkbox>
13
+      <el-checkbox v-model="showWXGoodsID" class="filter-item" style="margin-left:15px;">
14
+        商品微信ID
15
+      </el-checkbox>
16
+    </div>
17
+
18
+    <el-table
19
+      id="goods-table"
20
+      v-loading="listLoading"
21
+      :data="list"
22
+      border
23
+      fit
24
+      highlight-current-row
25
+      style="width: 100%;"
26
+    >
27
+      <el-table-column v-if="showGoodsID" label="商品ID" prop="id" align="center" width="80">
28
+        <template slot-scope="{row}">
29
+          <span>{{ row.goods_id }}</span>
30
+        </template>
31
+      </el-table-column>
32
+      <el-table-column v-if="showWXGoodsID" label="微信商品ID" prop="id" align="center" width="80">
33
+        <template slot-scope="{row}">
34
+          <span>{{ row.wx_goods_id }}</span>
35
+        </template>
36
+      </el-table-column>
37
+      <el-table-column label="商品图片" align="center" width="130px">
38
+        <template slot-scope="{row}">
39
+          <el-image
40
+            style="width: 100px; height: 100px"
41
+            :src="row.goods_img"
42
+            fit="contain"
43
+          />
44
+        </template>
45
+      </el-table-column>
46
+      <el-table-column label="商品名称" align="center">
47
+        <template slot-scope="{row}">
48
+          <span>{{ row.name }}</span>
49
+        </template>
50
+      </el-table-column>
51
+      <el-table-column label="价格" align="center" width="150px">
52
+        <template slot-scope="{row}">
53
+          <span v-if="row.price_type === 1">{{ row.price / 100 }}元</span>
54
+          <span v-if="row.price_type === 3">原价:{{ row.price / 100 }}元 <br> 折扣价:{{ row.price2 / 100 }}元</span>
55
+        </template>
56
+      </el-table-column>
57
+      <el-table-column label="审核状态" align="center" width="150px">
58
+        <template slot-scope="{row}">
59
+          <el-tag :type="row.audit_status | statusFilter">
60
+            {{ statusOptions[row.audit_status] }}
61
+          </el-tag>
62
+        </template>
63
+      </el-table-column>
64
+      <el-table-column label="动作" align="center" class-name="small-padding fixed-width" fixed="right">
65
+        <template slot-scope="{row,$index}">
66
+          <el-button type="danger" size="mini" @click="handleDelete(row, $index)">
67
+            删除
68
+          </el-button>
69
+          <el-button v-if="row.audit_status === 2" type="primary" size="mini" @click="handleUpdate(row, $index)">
70
+            更新
71
+          </el-button>
72
+        </template>
73
+      </el-table-column>
74
+    </el-table>
75
+
76
+    <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.num" @pagination="getList" />
77
+
78
+    <el-dialog :visible.sync="dialogFormVisible" width="700px">
79
+      <el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="80px" style="width: 550px; margin-left:50px;">
80
+        <el-form-item label="商品名称" prop="goods_name">
81
+          <el-row>
82
+            <el-input
83
+              v-model="temp.goods_name"
84
+              placeholder="请输入商品名"
85
+              :disabled="dialogStatus === 'update'"
86
+              maxlength="28"
87
+              show-word-limit
88
+              style="width: 450px"
89
+            />
90
+          </el-row>
91
+        </el-form-item>
92
+        <el-form-item label="商品价格" prop="price">
93
+          <el-row>
94
+            <el-col :span="6">
95
+              <el-radio v-model="temp.price_type" :label="1">一口价</el-radio>
96
+            </el-col>
97
+            <el-col :span="8">
98
+              <span>价格</span>
99
+              <el-input v-model="temp.price1" :disabled="temp.price_type !== 1" style="width:100px">
100
+                <span slot="suffix">元</span>
101
+              </el-input>
102
+            </el-col>
103
+          </el-row>
104
+          <el-row style="margin-top: 12px">
105
+            <el-col :span="6">
106
+              <el-radio v-model="temp.price_type" :label="3">显示折扣价</el-radio>
107
+            </el-col>
108
+            <el-col :span="9">
109
+              <span>原价</span>
110
+              <el-input v-model="temp.price2" :disabled="temp.price_type !== 3" prop="price2" style="width:100px">
111
+                <span slot="suffix">元</span>
112
+              </el-input>
113
+            </el-col>
114
+            <el-col :span="9">
115
+              <span>折扣价</span>
116
+              <el-input v-model="temp.price3" :disabled="temp.price_type !== 3" prop="price3" style="width:100px">
117
+                <span slot="suffix">元</span>
118
+              </el-input>
119
+            </el-col>
120
+          </el-row>
121
+        </el-form-item>
122
+        <el-form-item label="商品封面" prop="goods_img">
123
+          <el-image
124
+            v-if="dialogStatus === 'update'"
125
+            style="width: 150px; height: 150px"
126
+            :src="temp.goods_img"
127
+            fit="contain"
128
+          />
129
+          <el-upload
130
+            v-else
131
+            drag
132
+            :multiple="false"
133
+            :limit="1"
134
+            action="https://jh.kodo.com.cn/api/upload"
135
+            :on-success="handleUploadSuccess"
136
+            :file-list="temp.imgList"
137
+            list-type="picture"
138
+            style="width: 450px"
139
+          >
140
+            <i class="el-icon-upload" />
141
+            <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
142
+            <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
143
+          </el-upload>
144
+        </el-form-item>
145
+      </el-form>
146
+      <div slot="footer" class="dialog-footer">
147
+        <el-button @click="dialogFormVisible = false">
148
+          取消
149
+        </el-button>
150
+        <el-button v-waves :loading="submitNetworkLoading" type="primary" @click="dialogStatus==='create'?createData():updateData()">
151
+          提交审核
152
+        </el-button>
153
+      </div>
154
+    </el-dialog>
155
+  </div>
156
+</template>
157
+
158
+<script>
159
+import { fetchGoodsList, createGoods, auditGoods, deleteGoods, updateGoods } from '@/api/live'
160
+import waves from '@/directive/waves' // waves directive
161
+import Pagination from '@/components/Pagination' // secondary package based on el-pagination
162
+
163
+export default {
164
+  name: 'ComplexTable',
165
+  components: { Pagination },
166
+  directives: { waves },
167
+  filters: {
168
+    statusFilter(status) {
169
+      const statusMap = {
170
+        0: 'info',
171
+        1: '',
172
+        2: 'success',
173
+        3: 'danger'
174
+      }
175
+      return statusMap[status]
176
+    }
177
+  },
178
+  data() {
179
+    var validatePrice = (rule, value, callback) => {
180
+      if (this.temp.price_type === 1) {
181
+        if (this.temp.price1 === '') {
182
+          callback(new Error('价格不能为空'))
183
+        } else {
184
+          callback()
185
+        }
186
+      } else {
187
+        if (this.temp.price2 === '') {
188
+          callback(new Error('原价不能为空'))
189
+        } else if (this.temp.price3 === '') {
190
+          callback(new Error('折扣价不能为空'))
191
+        } else if (parseFloat(this.temp.price2) <= parseFloat(this.temp.price3)) {
192
+          callback(new Error('折扣价不能大于原价'))
193
+        }
194
+      }
195
+    }
196
+    return {
197
+      list: null,
198
+      total: 0,
199
+      listLoading: true,
200
+      listQuery: {
201
+        page: 1,
202
+        num: 20
203
+      },
204
+      temp: {
205
+        goods_name: '',
206
+        price_type: 1,
207
+        price: '',
208
+        price1: '',
209
+        price2: '',
210
+        price3: '',
211
+        goods_img: '',
212
+        imgList: []
213
+      },
214
+      statusOptions: ['未审核', '审核中', '审核通过', '审核失败'],
215
+      dialogFormVisible: false,
216
+      dialogStatus: '',
217
+      rules: {
218
+        goods_name: [{ required: true, message: 'title is required', trigger: 'blur' }],
219
+        price: [{ validator: validatePrice, trigger: 'blur' }],
220
+        goods_img: [{ required: true, message: 'title is required', trigger: 'changed' }]
221
+      },
222
+      submitNetworkLoading: false,
223
+      refreshNetworkLoading: false,
224
+      showGoodsID: false,
225
+      showWXGoodsID: false
226
+    }
227
+  },
228
+  created() {
229
+    this.getList()
230
+  },
231
+  methods: {
232
+    getList() {
233
+      this.listLoading = true
234
+      var _self = this
235
+      fetchGoodsList(this.listQuery).then(response => {
236
+        _self.list = response.data.goods_list
237
+        _self.total = response.data.count
238
+        // Just to simulate the time of the request
239
+        this.listLoading = false
240
+        this.refreshNetworkLoading = false
241
+        this.submitNetworkLoading = false
242
+      })
243
+    },
244
+
245
+    resetTemp() {
246
+      this.temp = {
247
+        goods_name: '',
248
+        price_type: 1,
249
+        price: '',
250
+        price1: '',
251
+        price2: '',
252
+        price3: '',
253
+        goods_img: '',
254
+        imgList: []
255
+      }
256
+    },
257
+
258
+    handleUploadChanged(file, fileList) {
259
+      this.temp.imgList = [{ name: file.name, url: file.url }]
260
+    },
261
+
262
+    handleUploadSuccess(response, file, fileList) {
263
+      this.temp.goods_img = response.data.file_path
264
+    },
265
+
266
+    handleFilter() {
267
+      this.getList()
268
+    },
269
+
270
+    handleCreate() {
271
+      this.resetTemp()
272
+      this.dialogFormVisible = true
273
+      this.dialogStatus = 'create'
274
+    },
275
+
276
+    createData() {
277
+      var _self = this
278
+      this.$refs['dataForm'].validate((valid) => {
279
+        if (valid) {
280
+          // this.submitNetworkLoading = true
281
+          const goods = Object.assign({}, this.temp)
282
+          if (goods.price_type === 1) {
283
+            goods.price = this.$math.multiply(this.$math.bignumber(parseFloat(this.temp.price1)), this.$math.bignumber(100)).d[0]
284
+            goods.price2 = 0
285
+          } else if (goods.price_type === 3) {
286
+            goods.price = this.$math.multiply(this.$math.bignumber(parseFloat(this.temp.price2)), this.$math.bignumber(100)).d[0]
287
+            goods.price2 = this.$math.multiply(this.$math.bignumber(parseFloat(this.temp.price3)), this.$math.bignumber(100)).d[0]
288
+          }
289
+
290
+          createGoods(goods).then(response => {
291
+            _self.getList()
292
+            _self.resetTemp()
293
+            _self.dialogFormVisible = false
294
+
295
+            _self.$notify({
296
+              title: '创建商品成功',
297
+              type: 'success',
298
+              duration: 2000
299
+            })
300
+          })
301
+        }
302
+      })
303
+    },
304
+
305
+    handleDelete(row, index) {
306
+      var _self = this
307
+      this.$confirm(`确定要删除 ${row.name}`, '', {
308
+        distinguishCancelAndClose: true,
309
+        confirmButtonText: '删除',
310
+        cancelButtonText: '取消',
311
+        type: 'error'
312
+      })
313
+        .then(() => {
314
+          deleteGoods(row).then(response => {
315
+            _self.$notify({
316
+              title: '删除商品成功',
317
+              type: 'success',
318
+              duration: 2000
319
+            })
320
+          })
321
+        })
322
+        .catch(action => {
323
+
324
+        })
325
+    },
326
+
327
+    handleRefreshAudit() {
328
+      this.refreshNetworkLoading = true
329
+      var _self = this
330
+      auditGoods().then(response => {
331
+        _self.getList()
332
+        _self.$notify({
333
+          title: '刷新审核状态成功',
334
+          type: 'success',
335
+          duration: 2000
336
+        })
337
+      })
338
+    },
339
+
340
+    handleUpdate(row, index) {
341
+      this.resetTemp()
342
+      this.dialogFormVisible = true
343
+      this.dialogStatus = 'update'
344
+      const goods = Object.assign({}, row)
345
+      this.temp.goods_id = goods.goods_id
346
+      this.temp.goods_name = goods.name
347
+      this.temp.goods_img = goods.goods_img
348
+      this.temp.price_type = goods.price_type
349
+      if (this.temp.price_type === 1) {
350
+        this.temp.price1 = `${parseInt(goods.price) / 100}`
351
+        this.temp.price2 = ''
352
+        this.temp.price3 = ''
353
+      } else {
354
+        this.temp.price1 = ''
355
+        this.temp.price3 = `${parseInt(goods.price2) / 100}`
356
+        this.temp.price2 = `${parseInt(goods.price) / 100}`
357
+      }
358
+    },
359
+
360
+    updateData() {
361
+      this.submitNetworkLoading = true
362
+      var _self = this
363
+
364
+      const goods = Object.assign({}, this.temp)
365
+      if (goods.price_type === 1) {
366
+        goods.price = this.$math.multiply(this.$math.bignumber(parseFloat(this.temp.price1)), this.$math.bignumber(100)).d[0]
367
+        goods.price2 = 0
368
+      } else if (goods.price_type === 3) {
369
+        goods.price = this.$math.multiply(this.$math.bignumber(parseFloat(this.temp.price2)), this.$math.bignumber(100)).d[0]
370
+        goods.price2 = this.$math.multiply(this.$math.bignumber(parseFloat(this.temp.price3)), this.$math.bignumber(100)).d[0]
371
+      }
372
+      updateGoods(goods).then(response => {
373
+        _self.getList()
374
+        this.resetTemp()
375
+        this.dialogFormVisible = false
376
+        this.dialogStatus = ''
377
+        _self.$notify({
378
+          title: '更新成功',
379
+          type: 'success',
380
+          duration: 2000
381
+        })
382
+      })
383
+    }
384
+  }
385
+}
386
+</script>

+ 177 - 0
src/views/live/order.vue

@@ -0,0 +1,177 @@
1
+<template>
2
+  <div class="app-container">
3
+    <div class="filter-container">
4
+      <el-input v-model="listQuery.query" placeholder="顾客名字,顾客电话" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
5
+      <el-select v-model="listQuery.pay_status" placeholder="支付状态" clearable class="filter-item" style="width: 130px">
6
+        <el-option v-for="(item, index) in statusOptions" :key="item" :value="index" :label="item" />
7
+      </el-select>
8
+      <el-button v-waves :loading="searchNetworkLoading" class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
9
+        搜索
10
+      </el-button>
11
+      <el-checkbox v-model="showOrderID" class="filter-item" style="margin-left:15px;">
12
+        订单ID
13
+      </el-checkbox>
14
+      <el-checkbox v-model="showTransactionID" class="filter-item" style="margin-left:15px;">
15
+        商户号交易单号
16
+      </el-checkbox>
17
+    </div>
18
+
19
+    <el-table
20
+      id="order-table"
21
+      v-loading="listLoading"
22
+      :data="list"
23
+      border
24
+      fit
25
+      highlight-current-row
26
+      style="width: 100%;"
27
+    >
28
+      <el-table-column v-if="showOrderID" label="订单ID" prop="id" align="center">
29
+        <template slot-scope="{row}">
30
+          <span>{{ row.order_id }}</span>
31
+        </template>
32
+      </el-table-column>
33
+      <el-table-column v-if="showTransactionID" label="商户号交易单号" align="center">
34
+        <template slot-scope="{row}">
35
+          <span>{{ row.transaction_id }}</span>
36
+        </template>
37
+      </el-table-column>
38
+      <el-table-column label="商品" align="center" width="110px">
39
+        <template slot-scope="{row}">
40
+          <el-image
41
+            style="width: 80px; height: 80px"
42
+            :src="row.goods_img"
43
+            fit="contain"
44
+          />
45
+        </template>
46
+      </el-table-column>
47
+      <el-table-column label="商品名称" align="center">
48
+        <template slot-scope="{row}">
49
+          <span>{{ row.goods_name }}</span>
50
+          <span style="color: #409EFF">x {{ row.amount }}</span>
51
+        </template>
52
+      </el-table-column>
53
+      <el-table-column label="总金额" align="center">
54
+        <template slot-scope="{row}">
55
+          <span>{{ row.total_fee / 100 }}元</span>
56
+        </template>
57
+      </el-table-column>
58
+      <el-table-column label="顾客名称" align="center">
59
+        <template slot-scope="{row}">
60
+          <span>{{ row.name }}</span>
61
+        </template>
62
+      </el-table-column>
63
+      <el-table-column label="顾客电话" align="center">
64
+        <template slot-scope="{row}">
65
+          <span>{{ row.phone }}</span>
66
+        </template>
67
+      </el-table-column>
68
+      <el-table-column label="顾客地址" align="center">
69
+        <template slot-scope="{row}">
70
+          <span>{{ row.province + row.city + row.county + row.address }}</span>
71
+        </template>
72
+      </el-table-column>
73
+      <el-table-column label="直播主题" align="center">
74
+        <template slot-scope="{row}">
75
+          <span>{{ row.room_name }}</span>
76
+        </template>
77
+      </el-table-column>
78
+      <el-table-column label="快递单号" align="center">
79
+        <template slot-scope="{row}">
80
+          <span>{{ row.tracking_number }}</span>
81
+        </template>
82
+      </el-table-column>
83
+      <el-table-column label="支付状态" align="center" width="150px">
84
+        <template slot-scope="{row}">
85
+          <el-tag :type="row.pay_status | statusFilter">
86
+            {{ statusOptions[row.pay_status] }}
87
+          </el-tag>
88
+        </template>
89
+      </el-table-column>
90
+      <el-table-column label="时间" align="center" width="150px">
91
+        <template slot-scope="{row}">
92
+          <span>{{ row.paid_at }}</span>
93
+        </template>
94
+      </el-table-column>
95
+      <el-table-column label="Actions" align="center" class-name="small-padding fixed-width" fixed="right" width="100">
96
+        <template slot-scope="{row,$index}">
97
+          <el-button v-if="(row.tracking_number === null || row.tracking_number === '') && row.pay_status === 1" type="primary" @click="handleDelivery(row, $index)">发货</el-button>
98
+          <el-button v-else-if="row.tracking_number !== null && row.pay_status === 1" type="success" disabled>已发货</el-button>
99
+          <el-button v-else type="info" disabled>发货</el-button>
100
+        </template>
101
+      </el-table-column>
102
+    </el-table>
103
+
104
+    <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.num" @pagination="getList" />
105
+  </div>
106
+</template>
107
+
108
+<script>
109
+import { fetchOrderList, deliveryOrder } from '@/api/live'
110
+import waves from '@/directive/waves' // waves directive
111
+import Pagination from '@/components/Pagination' // secondary package based on el-pagination
112
+
113
+export default {
114
+  name: 'ComplexTable',
115
+  components: { Pagination },
116
+  directives: { waves },
117
+  filters: {
118
+    statusFilter(status) {
119
+      const statusMap = {
120
+        1: 'success',
121
+        0: 'warn',
122
+        2: 'danger'
123
+      }
124
+      return statusMap[status]
125
+    }
126
+  },
127
+  data() {
128
+    return {
129
+      tableKey: 0,
130
+      list: null,
131
+      total: 0,
132
+      listLoading: true,
133
+      searchNetworkLoading: false,
134
+      statusOptions: ['支付中', '已支付', '支付失败'],
135
+      showOrderID: false,
136
+      showTransactionID: false,
137
+
138
+      listQuery: {
139
+        page: 1,
140
+        num: 20,
141
+        pay_status: '',
142
+        query: ''
143
+      }
144
+    }
145
+  },
146
+  created() {
147
+    this.getList()
148
+  },
149
+  methods: {
150
+    getList(query) {
151
+      this.listLoading = true
152
+      var _self = this
153
+      fetchOrderList(this.listQuery).then(response => {
154
+        _self.list = response.data.orders
155
+        _self.total = response.data.count
156
+        // Just to simulate the time of the request
157
+        _self.listLoading = false
158
+        _self.searchNetworkLoading = false
159
+      })
160
+    },
161
+
162
+    handleFilter() {
163
+      this.searchNetworkLoading = true
164
+      this.getList(this.listQuery.title)
165
+    },
166
+
167
+    handleDelivery(row, index) {
168
+      this.listLoading = true
169
+      var _self = this
170
+      deliveryOrder(row).then(response => {
171
+        _self.$set(_self.list, index, response.data.order)
172
+        _self.listLoading = false
173
+      })
174
+    }
175
+  }
176
+}
177
+</script>

+ 362 - 0
src/views/live/room.vue

@@ -0,0 +1,362 @@
1
+<template>
2
+  <div class="app-container">
3
+    <div class="filter-container">
4
+      <el-input v-model="listQuery.query" placeholder="搜索直播主题" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
5
+      <el-select v-model="listQuery.live_status" placeholder="直播状态" clearable class="filter-item" style="width: 130px">
6
+        <el-option v-for="(k, v) in statusOptions" :key="k" :value="v" :label="k" />
7
+      </el-select>
8
+      <el-button v-waves :loading="networkLoading" class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
9
+        搜索
10
+      </el-button>
11
+      <el-button v-waves :loading="networkLoading" class="filter-item" type="primary" icon="el-icon-refresh" @click="handleRefresh">
12
+        从微信获取直播列表
13
+      </el-button>
14
+    </div>
15
+
16
+    <el-table
17
+      id="room-table"
18
+      :key="tableKey"
19
+      ref="multipleTable"
20
+      v-loading="listLoading"
21
+      :data="list"
22
+      border
23
+      fit
24
+      highlight-current-row
25
+      style="width: 100%;"
26
+    >
27
+      <el-table-column label="room_id" prop="房间号" align="center" width="80">
28
+        <template slot-scope="{row}">
29
+          <span>{{ row.room_id }}</span>
30
+        </template>
31
+      </el-table-column>
32
+      <el-table-column label="直播主题" align="center">
33
+        <template slot-scope="{row}">
34
+          <span>{{ row.name }}</span>
35
+        </template>
36
+      </el-table-column>
37
+      <el-table-column label="主播" align="center">
38
+        <template slot-scope="{row}">
39
+          <el-avatar shape="square" :src="row.anchor_avatar" />
40
+          <span>{{ row.anchor_name }}</span>
41
+        </template>
42
+      </el-table-column>
43
+      <el-table-column label="直播状态" align="center">
44
+        <template slot-scope="{row}">
45
+          <el-tag :type="row.live_status | statusFilter">
46
+            {{ statusOptions[row.live_status] }}
47
+          </el-tag>
48
+        </template>
49
+      </el-table-column>
50
+      <el-table-column label="直播封面" align="center">
51
+        <template slot-scope="{row}">
52
+          <el-image
53
+            style="width: 100px; height: 100px"
54
+            :src="row.cover_img"
55
+            fit="contain"
56
+          />
57
+        </template>
58
+      </el-table-column>
59
+      <el-table-column label="直播分享卡片" align="center">
60
+        <template slot-scope="{row}">
61
+          <el-image
62
+            style="width: 200px; height: 160px"
63
+            :src="row.share_img"
64
+            fit="contain"
65
+          />
66
+        </template>
67
+      </el-table-column>
68
+      <el-table-column label="Actions" align="center" class-name="small-padding fixed-width" fixed="right">
69
+        <template slot-scope="{row}">
70
+          <el-button v-if="row.live_status == 102 || row.live_status == 101" type="primary" @click="handleAddGoods(row)">添加商品</el-button>
71
+          <el-button v-else type="info" disabled>添加商品</el-button>
72
+        </template>
73
+      </el-table-column>
74
+    </el-table>
75
+
76
+    <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.num" @pagination="getList" />
77
+
78
+    <el-dialog :title="dialogTitle" :visible.sync="dialogFormVisible">
79
+      <el-table
80
+        id="room-table"
81
+        v-loading="goodsListLoading"
82
+        :data="goodsList"
83
+        fit
84
+        highlight-current-row
85
+        height="400px"
86
+        style="width: 100%;"
87
+        @selection-change="handleSelectionChange"
88
+      >
89
+        <el-table-column
90
+          type="selection"
91
+          width="30"
92
+        />
93
+        <el-table-column label="商品图片" align="center">
94
+          <template slot-scope="{row}">
95
+            <el-image
96
+              style="width: 60px; height: 60px"
97
+              :src="row.goods_img"
98
+              fit="contain"
99
+            />
100
+          </template>
101
+        </el-table-column>
102
+        <el-table-column label="商品名称" align="center">
103
+          <template slot-scope="{row}">
104
+            <span>{{ row.name }}</span>
105
+          </template>
106
+        </el-table-column>
107
+        <el-table-column label="价格" align="center" width="150px">
108
+          <template slot-scope="{row}">
109
+            <span v-if="row.price_type === 1">{{ row.price / 100 }}元</span>
110
+            <span v-if="row.price_type === 3">原价:{{ row.price / 100 }}元 <br> 折扣价:{{ row.price2 / 100 }}元</span>
111
+          </template>
112
+        </el-table-column>
113
+        <pagination v-show="goodsTotal>0" :total="goodsTotal" :page.sync="goodsListQuery.page" :limit.sync="goodsListQuery.num" @pagination="getGoodsList" />
114
+      </el-table>
115
+      <div slot="footer" class="dialog-footer">
116
+        <el-button @click="handleUnaddGoods">
117
+          取消
118
+        </el-button>
119
+        <el-button :disabled="temp.goods_list.length === 0" type="primary" @click="handleAddGoodsNextStep()">
120
+          下一步
121
+        </el-button>
122
+      </div>
123
+    </el-dialog>
124
+    <el-dialog :title="dialogTitle" :visible.sync="dialogForAddGoodsFormVisible">
125
+      <el-table
126
+        id="room-table"
127
+        :data="temp.goods_list"
128
+        fit
129
+        highlight-current-row
130
+        height="300px"
131
+        style="width: 100%;"
132
+        @selection-change="handleSelectionChange"
133
+      >
134
+        <el-table-column label="商品图片" align="center">
135
+          <template slot-scope="{row}">
136
+            <el-image
137
+              style="width: 60px; height: 60px"
138
+              :src="row.goods_img"
139
+              fit="contain"
140
+            />
141
+          </template>
142
+        </el-table-column>
143
+        <el-table-column label="商品名称" align="center">
144
+          <template slot-scope="{row}">
145
+            <span>{{ row.name }}</span>
146
+          </template>
147
+        </el-table-column>
148
+        <el-table-column label="价格" align="center" width="150px">
149
+          <template slot-scope="{row}">
150
+            <span v-if="row.price_type === 1">{{ row.price / 100 }}元</span>
151
+            <span v-if="row.price_type === 3">原价:{{ row.price / 100 }}元 <br> 折扣价:{{ row.price2 / 100 }}元</span>
152
+          </template>
153
+        </el-table-column>
154
+        <el-table-column label="库存" align="center" width="150px">
155
+          <template slot-scope="{row}">
156
+            <el-input-number v-model="row.inventory" :min="1" size="small" label="描述文字" @change="handleInventoryChanged" />
157
+          </template>
158
+        </el-table-column>
159
+        <pagination :total="temp.goods_list.length" />
160
+      </el-table>
161
+      <div slot="footer" class="dialog-footer">
162
+        <el-button @click="handleUnaddGoods">
163
+          取消
164
+        </el-button>
165
+        <el-button type="primary" @click="handleAddGoodsPrevStep">
166
+          上一步
167
+        </el-button>
168
+        <el-button v-waves :loading="networkLoading" :disabled="addGoodsEnable" type="primary" @click="handleAddGoodsToRoom()">
169
+          添加
170
+        </el-button>
171
+      </div>
172
+    </el-dialog>
173
+  </div>
174
+</template>
175
+
176
+<script>
177
+import { addRoomGoods, fetchGoodsList, fetchRoomList, refreshWxRoomList } from '@/api/live'
178
+import waves from '@/directive/waves' // waves directive
179
+import Pagination from '@/components/Pagination' // secondary package based on el-pagination
180
+
181
+export default {
182
+  name: 'ComplexTable',
183
+  components: { Pagination },
184
+  directives: { waves },
185
+  filters: {
186
+    statusFilter(status) {
187
+      const statusMap = {
188
+        101: '',
189
+        102: 'success',
190
+        103: 'info',
191
+        104: 'danger',
192
+        105: 'danger',
193
+        106: 'danger',
194
+        107: 'warning'
195
+
196
+      }
197
+      return statusMap[status]
198
+    }
199
+  },
200
+  data() {
201
+    return {
202
+      tableKey: 0,
203
+      list: null,
204
+      total: 0,
205
+      listLoading: true,
206
+      listQuery: {
207
+        page: 1,
208
+        num: 20,
209
+        query: '',
210
+        live_status: ''
211
+      },
212
+
213
+      statusOptions: {
214
+        101: '直播中',
215
+        102: '未开始',
216
+        103: '已结束',
217
+        104: '禁播',
218
+        105: '暂停中',
219
+        106: '异常',
220
+        107: '已过期'
221
+      },
222
+      networkLoading: false,
223
+      dialogFormVisible: false,
224
+      dialogTitle: '',
225
+
226
+      goodsList: null,
227
+      goodsTotal: 0,
228
+      goodsListLoading: true,
229
+      goodsListQuery: {
230
+        page: 1,
231
+        num: 20,
232
+        room_id: ''
233
+      },
234
+
235
+      temp: {
236
+        room_id: '',
237
+        anchor_id: '',
238
+        goods_list: []
239
+      },
240
+      dialogForAddGoodsFormVisible: false,
241
+      addGoodsEnable: false
242
+    }
243
+  },
244
+  created() {
245
+    this.getList()
246
+  },
247
+  methods: {
248
+    getList() {
249
+      this.listLoading = true
250
+      var _self = this
251
+      fetchRoomList(this.listQuery).then(response => {
252
+        _self.list = response.data.rooms
253
+        _self.total = response.data.count
254
+        // Just to simulate the time of the request
255
+        _self.listLoading = false
256
+        _self.networkLoading = false
257
+      })
258
+    },
259
+
260
+    getGoodsList(room_id) {
261
+      this.goodsListLoading = true
262
+      var _self = this
263
+      this.goodsListQuery.room_id = room_id
264
+      fetchGoodsList(this.goodsListQuery).then(response => {
265
+        _self.goodsList = response.data.goods_list
266
+        _self.goodsTotal = response.data.count
267
+        // Just to simulate the time of the request
268
+        this.goodsListLoading = false
269
+      })
270
+    },
271
+
272
+    resetTemp() {
273
+      this.goodsList = null
274
+      this.goodsTotal = 0
275
+      this.goodsListQuery = {
276
+        page: 1,
277
+        num: 20,
278
+        room_id: ''
279
+      }
280
+
281
+      this.temp = {
282
+        room_id: '',
283
+        anchor_id: '',
284
+        goods_list: []
285
+      }
286
+    },
287
+
288
+    handleFilter() {
289
+      this.getList()
290
+    },
291
+
292
+    handleRefresh() {
293
+      this.listLoading = true
294
+      this.networkLoading = true
295
+      var _self = this
296
+      refreshWxRoomList().then(response => {
297
+        fetchRoomList().then(response => {
298
+          _self.list = response.data.rooms
299
+          _self.total = response.data.count
300
+          // Just to simulate the time of the request
301
+          this.listLoading = false
302
+          _self.networkLoading = false
303
+        })
304
+      })
305
+    },
306
+
307
+    handleAddGoods(row) {
308
+      this.dialogFormVisible = true
309
+      this.dialogTitle = row.name
310
+      this.temp.room_id = row.room_id
311
+      this.temp.anchor_id = row.anchor_id
312
+      this.getGoodsList(row.room_id)
313
+    },
314
+
315
+    handleSelectionChange(v) {
316
+      this.temp.goods_list = v
317
+      this.$set(this.temp, 'goods_list', v)
318
+    },
319
+
320
+    handleUnaddGoods() {
321
+      this.dialogForAddGoodsFormVisible = false
322
+      this.dialogFormVisible = false
323
+      this.resetTemp()
324
+    },
325
+
326
+    handleAddGoodsNextStep() {
327
+      this.dialogForAddGoodsFormVisible = true
328
+      console.log(this.temp)
329
+      this.temp.goods_list = this.temp.goods_list.map(goods => {
330
+        goods.inventory = ''
331
+        return goods
332
+      })
333
+    },
334
+
335
+    handleInventoryChanged(v) {
336
+      this.temp.goods_list.filter(v => {
337
+        return v.inventory !== ''
338
+      })
339
+    },
340
+
341
+    handleAddGoodsPrevStep() {
342
+      this.dialogForAddGoodsFormVisible = false
343
+    },
344
+
345
+    handleAddGoodsToRoom() {
346
+      var _self = this
347
+      this.networkLoading = true
348
+      const params = Object.assign({}, this.temp)
349
+      params.goods_list = JSON.stringify(this.temp.goods_list)
350
+      addRoomGoods(params).then(response => {
351
+        console.log(response)
352
+        if (response.status === 200) {
353
+          _self.dialogForAddGoodsFormVisible = false
354
+          _self.dialogFormVisible = false
355
+          _self.networkLoading = false
356
+          _self.resetTemp()
357
+        }
358
+      })
359
+    }
360
+  }
361
+}
362
+</script>

+ 216 - 0
src/views/live/roomGoods.vue

@@ -0,0 +1,216 @@
1
+<template>
2
+  <div class="app-container">
3
+    <div class="filter-container">
4
+      <el-checkbox v-model="showGoodsID" class="filter-item" style="margin-left:15px;">
5
+        商品ID
6
+      </el-checkbox>
7
+      <el-checkbox v-model="showWXGoodsID" class="filter-item" style="margin-left:15px;">
8
+        微信商品ID
9
+      </el-checkbox>
10
+      <el-checkbox v-model="showRoomID" class="filter-item" style="margin-left:15px;">
11
+        直播间ID
12
+      </el-checkbox>
13
+    </div>
14
+
15
+    <el-table
16
+      id="goods-table"
17
+      v-loading="listLoading"
18
+      :data="list"
19
+      border
20
+      fit
21
+      highlight-current-row
22
+      style="width: 100%;"
23
+    >
24
+      <el-table-column v-if="showRoomID" label="房间ID" prop="id" align="center">
25
+        <template slot-scope="{row}">
26
+          <span>{{ row.room_id }}</span>
27
+        </template>
28
+      </el-table-column>
29
+      <el-table-column label="直播主题" prop="id" align="center">
30
+        <template slot-scope="{row}">
31
+          <span>{{ row.room_name }}</span>
32
+        </template>
33
+      </el-table-column>
34
+      <el-table-column label="主播" prop="id" align="center">
35
+        <template slot-scope="{row}">
36
+          <span>{{ row.anchor_name }}</span>
37
+        </template>
38
+      </el-table-column>
39
+      <el-table-column v-if="showGoodsID" label="商品ID" prop="id" align="center">
40
+        <template slot-scope="{row}">
41
+          <span>{{ row.goods_id }}</span>
42
+        </template>
43
+      </el-table-column>
44
+      <el-table-column v-if="showWXGoodsID" label="微信商品ID" prop="id" align="center">
45
+        <template slot-scope="{row}">
46
+          <span>{{ row.wx_goods_id }}</span>
47
+        </template>
48
+      </el-table-column>
49
+      <el-table-column label="商品名称" align="center">
50
+        <template slot-scope="{row}">
51
+          <span>{{ row.goods_name }}</span>
52
+        </template>
53
+      </el-table-column>
54
+      <el-table-column label="商品图片" align="center" width="120px">
55
+        <template slot-scope="{row}">
56
+          <el-image
57
+            style="width: 90px; height: 90px"
58
+            :src="row.goods_img"
59
+            fit="contain"
60
+          />
61
+        </template>
62
+      </el-table-column>
63
+      <el-table-column label="价格" align="center" width="150px">
64
+        <template slot-scope="{row}">
65
+          <span v-if="row.price_type === 1">{{ row.price / 100 }}元</span>
66
+          <span v-if="row.price_type === 3">原价:{{ row.price / 100 }}元 <br> 折扣价:{{ row.price2 / 100 }}元</span>
67
+        </template>
68
+      </el-table-column>
69
+      <el-table-column label="商品状态" align="center">
70
+        <template slot-scope="{row}">
71
+          <el-tag :type="row.goods_status | statusFilter">{{ statusOptions[row.goods_status] }}</el-tag>
72
+        </template>
73
+      </el-table-column>
74
+      <el-table-column label="库存" align="center" width="200px">
75
+        <template slot-scope="{row}">
76
+          <div v-if="!row.isEditable">
77
+            <span v-if="row.inventory > 0">{{ row.inventory }}</span>
78
+            <el-tag v-else type="danger">库存不足</el-tag>
79
+          </div>
80
+          <div v-if="row.isEditable">
81
+            <el-input v-model="inventory" style="width:50px;" @keyup.enter.native="handleInventoryChanged(row)" />
82
+            <el-button type="info" size="mini" @click="handleUpdateCancel(row)">取消</el-button>
83
+          </div>
84
+        </template>
85
+      </el-table-column>
86
+      <el-table-column label="销售数量" align="center">
87
+        <template slot-scope="{row}">
88
+          <span>{{ row.sale_count }}</span>
89
+        </template>
90
+      </el-table-column>
91
+      <el-table-column label="动作" align="center" class-name="small-padding fixed-width" fixed="right" width="200">
92
+        <template slot-scope="{row}">
93
+          <el-button v-if="(row.goods_status === 1 || row.goods_status === 2) && (row.room_status == 102 || row.room_status == 101)" type="success" size="mini" @click="handlePublish(row)">
94
+            上架
95
+          </el-button>
96
+          <el-button v-else-if="(row.goods_status === 0) && (row.room_status == 102 || row.room_status == 101)" type="danger" size="mini" @click="handleOff(row)">
97
+            下架
98
+          </el-button>
99
+          <el-button v-else type="info" size="mini" disabled @click="handleOff(row)">
100
+            已结束
101
+          </el-button>
102
+          <el-button type="primary" size="mini" @click="handleUpdate(row)">
103
+            更新
104
+          </el-button>
105
+        </template>
106
+      </el-table-column>
107
+    </el-table>
108
+
109
+    <pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.num" @pagination="getList" />
110
+  </div>
111
+</template>
112
+
113
+<script>
114
+import { fetchRoomGoodsList, publishRoomGoods, offRoomGoods, updateRoomGoods } from '@/api/live'
115
+import waves from '@/directive/waves' // waves directive
116
+import Pagination from '@/components/Pagination' // secondary package based on el-pagination
117
+
118
+export default {
119
+  name: 'ComplexTable',
120
+  components: { Pagination },
121
+  directives: { waves },
122
+  filters: {
123
+    statusFilter(status) {
124
+      const statusMap = {
125
+        0: 'success',
126
+        1: 'info',
127
+        2: 'danger'
128
+      }
129
+      return statusMap[status]
130
+    }
131
+  },
132
+  data() {
133
+    return {
134
+      list: null,
135
+      total: 0,
136
+      listLoading: true,
137
+      listQuery: {
138
+        page: 1,
139
+        num: 20
140
+      },
141
+
142
+      temp: {
143
+        goods_name: '',
144
+        price_type: '1',
145
+        price: '',
146
+        price2: ''
147
+      },
148
+
149
+      statusOptions: ['已上架', '草稿', '已下架'],
150
+      showGoodsID: false,
151
+      showWXGoodsID: false,
152
+      showRoomID: false,
153
+      inventory: 0
154
+    }
155
+  },
156
+  created() {
157
+    this.getList()
158
+  },
159
+  methods: {
160
+    getList() {
161
+      this.listLoading = true
162
+      var _self = this
163
+      fetchRoomGoodsList(this.listQuery).then(response => {
164
+        _self.list = response.data.goods_list.map(goods => {
165
+          goods.isEditable = false
166
+          return goods
167
+        })
168
+        _self.total = response.data.count
169
+        // Just to simulate the time of the request
170
+        this.listLoading = false
171
+      })
172
+    },
173
+
174
+    handleFilter() {
175
+      this.getList()
176
+    },
177
+
178
+    handleOff(row) {
179
+      var _self = this
180
+      this.$alert(`确定从${row.room_name}下架${row.goods_name}`, '下架产品', {
181
+        confirmButtonText: '下架',
182
+        callback: action => {
183
+          offRoomGoods(row).then(response => {
184
+            _self.getList()
185
+          })
186
+        }
187
+      })
188
+    },
189
+
190
+    handlePublish(row) {
191
+      var _self = this
192
+      publishRoomGoods(row).then(response => {
193
+        _self.getList()
194
+      })
195
+    },
196
+
197
+    handleUpdate(row) {
198
+      row.isEditable = true
199
+      this.inventory = row.inventory
200
+    },
201
+
202
+    handleUpdateCancel(row) {
203
+      row.isEditable = false
204
+    },
205
+
206
+    handleInventoryChanged(row) {
207
+      var _self = this
208
+      const goods = row
209
+      goods.inventory = this.inventory
210
+      updateRoomGoods(goods).then(response => {
211
+        _self.getList()
212
+      })
213
+    }
214
+  }
215
+}
216
+</script>

adminSystem - Gogs: Go Git Service

暂无描述

LICENSE 1.1KB

    The MIT License (MIT) Copyright 2015 Bogdan Chadkin <trysound@yandex.ru> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.