zhengnaiwen_citu 4 месяцев назад
Родитель
Сommit
cc5fd3ff8d

+ 30 - 0
src/api/accumulatePoint.js

@@ -19,3 +19,33 @@ export function getAccumulatePoint (data) {
 export function getAccumulatePointRule () {
   return http.get('/employee/score/rule/detail')
 }
+
+// 积分 商品列表
+export function getAccumulatePointProduct (data) {
+  return http.post('/score/product/list', data)
+}
+
+// 积分 商品保存
+export function saveAccumulatePointProduct (data) {
+  return http.post('/score/product/save', data)
+}
+
+// 积分 商品删除
+export function deleteAccumulatePointProduct (data) {
+  return http.post('/score/product/delete', data)
+}
+
+// 积分 商品详情
+export function getAccumulatePointProductDetails (data) {
+  return http.post('/score/product/detail', data)
+}
+
+// 积分 兑换
+export function exchangeAccumulatePointProduct (data) {
+  return http.post('/score/product/exchange', data)
+}
+
+// 积分 查积分消费记录
+export function getAccumulatePointProductHistory (data) {
+  return http.post('/score/consumption/record/user/page', data)
+}

+ 19 - 0
src/components/AutoComponents/MPagination/index.vue

@@ -0,0 +1,19 @@
+<template>
+  <el-pagination
+    v-on="$listeners"
+    v-bind="$attrs"
+    background
+    layout="total, prev, pager, next, jumper"
+  >
+  </el-pagination>
+</template>
+
+<script>
+export default {
+  name: 'MPagination'
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 2 - 4
src/components/AutoComponents/MTable/index.vue

@@ -35,15 +35,13 @@
     </el-table>
     <slot></slot>
     <div class="pt-3 text-right" v-if="total">
-      <el-pagination
+      <m-pagination
         @current-change="handleCurrentChange"
         :current-page="pageCurrent"
-        background
         :page-size="pageSize"
-        layout="total, prev, pager, next, jumper"
         :total="total"
       >
-      </el-pagination>
+      </m-pagination>
     </div>
   </m-card>
 </template>

+ 10 - 0
src/styles/orangeTheme.scss

@@ -62,6 +62,7 @@ $theme-colors: (
   "orange": $theme-color  // 新增橙色
 );
 // 生成按钮样式
+$LIGHTEN_BASE: 1%;
 @each $type, $color in $theme-colors {
   @if $type == "default" {
     .el-button--default {
@@ -198,6 +199,15 @@ $theme-colors: (
         }
       }
     }
+
+    .text-#{$type} {
+      color: $color;
+    }
+    @for $i from 0 through 40 {
+      .text-#{$type}-lighten--#{$i} {
+        color: lighten($color, $i * $LIGHTEN_BASE);
+      }
+    }
   }
 }
 

+ 100 - 0
src/views/accumulatePoints/accumulatePointsMotivate/accumulatePointsMotivateHistory.vue

@@ -0,0 +1,100 @@
+<template>
+  <m-dialog ref="dialog" title="积分兑换记录">
+    <m-table
+      clearHeader
+      shadow="never"
+      v-loading="loading"
+      :items="items"
+      :headers="headers"
+      :page-size="pageInfo.size"
+      :page-current="pageInfo.current"
+      :total="total"
+      @page-change="onPageChange"
+      @sort-change="onSortChange"
+    >
+    </m-table>
+
+  </m-dialog>
+</template>
+
+<script>
+import {
+  getAccumulatePointProductHistory
+} from '@/api/accumulatePoint'
+export default {
+  name: 'accumulatePointsMotivateHistory',
+  data () {
+    return {
+      loading: false,
+      items: [],
+      headers: [
+        {
+          label: '兑换物品',
+          prop: 'scoreProductName'
+        },
+        {
+          label: '兑换数量',
+          prop: 'num',
+          align: 'center'
+        },
+        {
+          label: '兑换积分',
+          prop: 'score',
+          align: 'center'
+        },
+        {
+          label: '兑换时间',
+          prop: 'createDate'
+        }
+      ],
+      pageInfo: {
+        current: 1,
+        size: 10
+      },
+      total: 0,
+      orders: [
+        {
+          column: 'create_date',
+          asc: false
+        }
+      ]
+    }
+  },
+  methods: {
+    open () {
+      this.$refs.dialog.open()
+      this.pageInfo.current = 1
+      this.onInit()
+    },
+    async onInit () {
+      this.loading = true
+      try {
+        const { data } = await getAccumulatePointProductHistory({
+          page: {
+            ...this.pageInfo,
+            orders: this.orders
+          }
+        })
+        this.items = data.records
+        this.total = data.total
+      } catch (error) {
+        this.$message.error(error)
+      } finally {
+        this.loading = false
+      }
+    },
+    onPageChange (index) {
+      this.pageInfo.current = index
+      this.onInit()
+    },
+    onSortChange (orders) {
+      this.orders = orders
+      this.onInit()
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 186 - 2
src/views/accumulatePoints/accumulatePointsMotivate/index.vue

@@ -1,15 +1,199 @@
 <template>
   <div class="pa-3 white">
-    <el-empty></el-empty>
+    <m-search class="mb-3" :items="searchItems" v-model="searchValues" @search="onSearch"></m-search>
+    <m-card :body-style="{ padding: '0px' }" v-loading="loading">
+      <div slot="header" class="clearfix">
+        <span>兑换列表</span>
+        <div class="tools">
+          <span class="mr-3">
+            已使用积分:<span class="text-link" @click="onHistory">{{ itemData.canUsedScore ?? 0 }}</span>
+          </span>
+          <span>
+            可用积分:{{ itemData.canUsed ?? 0 }}
+          </span>
+          <!-- <m-button type="orange" @click="onHistory">兑换记录</m-button> -->
+        </div>
+      </div>
+      <el-row>
+        <el-col :span="6" v-for="item in items" :key="item.scoreProductId" class="pa-3">
+          <el-card :body-style="{ padding: '0px' }" shadow="hover" :class="item.remainingQuantity <= 0 ? 'cardDisabled' : ''">
+            <div class="d-flex align-center justify-center font-36 text-orange">
+              <span class="mdi mdi-gift"></span>
+            </div>
+            <div class="text-center pa-3">
+              <div>{{ item.productName }}</div>
+              <div class="font-12" style="color: grey">{{ item.productDescription }}</div>
+              <el-tag size="small" type="orange" class="ma-3">{{ item.productScore }}积分</el-tag>
+              <div>
+                <span v-if="item.remainingQuantity <= 0" class="font-14" style="color: grey;">已兑换完</span>
+                <m-button v-else type="primary" text size="mini" @click="onExchange(item)">我要兑换 (剩余{{ item.remainingQuantity }})</m-button>
+              </div>
+            </div>
+          </el-card>
+        </el-col>
+      </el-row>
+      <div class="pa-3 text-center">
+        <m-pagination
+          @current-change="handleCurrentChange"
+          :current-page="pageInfo.current"
+          :page-size="pageInfo.size"
+          :total="total"
+        >
+        </m-pagination>
+      </div>
+    </m-card>
+    <AccumulatePointsMotivateHistory ref="accumulatePointsMotivateHistoryRefs"></AccumulatePointsMotivateHistory>
   </div>
 </template>
 
 <script>
+import AccumulatePointsMotivateHistory from './accumulatePointsMotivateHistory.vue'
+import {
+  getAccumulatePointProduct,
+  exchangeAccumulatePointProduct,
+  getAccumulatePoint
+} from '@/api/accumulatePoint'
 export default {
-  name: 'accumulatePointsMotivate'
+  name: 'accumulatePointsMotivate',
+  components: {
+    AccumulatePointsMotivateHistory
+  },
+  data () {
+    return {
+      searchItems: [
+        {
+          label: '名称',
+          prop: 'productName',
+          type: 'input',
+          options: {
+            placeholder: '请输入名称'
+          }
+        }
+      ],
+      searchValues: {
+        productName: null
+      },
+      pageInfo: {
+        current: 1,
+        size: 12
+      },
+      total: 0,
+      orders: [
+        {
+          asc: false,
+          column: 'create_date'
+        }
+      ],
+      items: [],
+      loading: false,
+      itemData: {}
+    }
+  },
+  created () {
+    this.getDetails()
+    this.onInit()
+  },
+  methods: {
+    async onInit () {
+      this.loading = true
+      try {
+        const { data } = await getAccumulatePointProduct({
+          page: {
+            ...this.pageInfo,
+            orders: this.orders
+          },
+          entity: {
+            ...this.searchValues
+          }
+        })
+        this.items = data.records
+        this.total = data.total
+      } catch (error) {
+        this.$message.error(error)
+      } finally {
+        this.loading = false
+      }
+    },
+    async getDetails () {
+      try {
+        const { data } = await getAccumulatePoint({})
+        this.itemData = data.entity
+        this.itemData.canUsed = this.itemData.score - this.itemData.canUsedScore
+      } catch (error) {
+        this.$message.error(error)
+      }
+    },
+    handleCurrentChange (index) {
+      this.pageInfo.current = index
+      this.onInit()
+    },
+    onHistory () {
+      this.$refs.accumulatePointsMotivateHistoryRefs.open()
+    },
+    onSearch () {
+      this.pageInfo.current = 1
+      this.onInit()
+    },
+    onExchange (item) {
+      if (item.remainingQuantity <= 0) {
+        this.$message.error('该商品已兑换完')
+        return
+      }
+      this.$confirm(`确认兑换${item.productName}吗?`).then(async () => {
+        try {
+          await exchangeAccumulatePointProduct({
+            scoreProductId: item.scoreProductId,
+            num: 1
+          })
+          this.$message.success('兑换成功')
+          this.onInit()
+        } catch (error) {
+          this.$snackbar.error(error)
+        }
+      }).catch(_ => {})
+    }
+  }
 }
 </script>
 
 <style lang="scss" scoped>
+.tools {
+  float: right;
+  display: flex;
+  align-items: center;
+  height: 60px;
+  ::v-deep .el-button {
+    padding: 9px 15px;
+    font-size: 12px;
+    border-radius: 3px;
+  }
+}
+.clearfix:before,
+.clearfix:after {
+  display: table;
+  content: "";
+}
+.clearfix:after {
+  clear: both
+}
+::v-deep .el-card__header {
+  padding-top: 0;
+  padding-bottom: 0;
+  height: 60px;
+  line-height: 60px;
+}
 
+.cardDisabled {
+  position: relative;
+  &::after {
+    content: "";
+    position: absolute;
+    top: 0;
+    left: 0;
+    width: 100%;
+    height: 100%;
+    background-color: rgba(141, 141, 141, .2);
+    z-index: 1;
+  }
+}
 </style>

+ 124 - 0
src/views/accumulatePoints/accumulatePointsMotivateManage/accumulatePointsMotivateManageEdit.vue

@@ -0,0 +1,124 @@
+<template>
+  <m-dialog ref="dialog" :title="`产品${itemData.scoreProductId ? '编辑' : '新增'}`" @sure="onSure">
+    <m-form :items="formItems" v-model="formValues"></m-form>
+  </m-dialog>
+</template>
+
+<script>
+import {
+  saveAccumulatePointProduct,
+  getAccumulatePointProductDetails
+} from '@/api/accumulatePoint'
+export default {
+  name: 'accumulatePointsMotivateManageEdit',
+  data () {
+    return {
+      formValues: {},
+      itemData: {}
+    }
+  },
+  computed: {
+    formItems () {
+      return [
+        {
+          label: '产品名称',
+          prop: 'productName',
+          type: 'input',
+          rules: [
+            { required: true, message: '请输入产品名称', trigger: 'blur' }
+          ],
+          options: {
+            placeholder: '请输入产品名称'
+          }
+        },
+        {
+          label: '产品描述',
+          prop: 'productDescription',
+          type: 'input',
+          options: {
+            placeholder: '请输入产品描述'
+          },
+          rules: [
+            { required: true, message: '请输入产品描述', trigger: 'blur' }
+          ]
+        },
+        {
+          label: '产品兑换积分',
+          prop: 'productScore',
+          type: 'number',
+          options: {
+            placeholder: '请输入产品兑换积分'
+          },
+          rules: [
+            { required: true, message: '请输入产品兑换积分', trigger: 'blur' }
+          ]
+        },
+        {
+          label: '剩余数量',
+          prop: 'remainingQuantity',
+          type: 'number',
+          options: {
+            placeholder: '请输入剩余数量'
+          },
+          rules: [
+            { required: true, message: '请输入剩余数量', trigger: 'blur' }
+          ]
+        }
+      ]
+    }
+  },
+  methods: {
+    async open (item) {
+      this.$refs.dialog.open()
+      if (!item) {
+        this.itemData = {}
+        this.formValues = {
+          productName: null,
+          productDescription: null,
+          productScore: 0,
+          remainingQuantity: 0
+        }
+        return
+      }
+      this.loading = true
+      try {
+        const { data } = await getAccumulatePointProductDetails({
+          scoreProductId: item.scoreProductId
+        })
+        this.itemData = data
+        this.formValues = {
+          productName: data.productName,
+          productDescription: data.productDescription,
+          productScore: data.productScore,
+          remainingQuantity: data.remainingQuantity
+        }
+      } catch (error) {
+        this.$message.error(error)
+      } finally {
+        this.loading = false
+      }
+    },
+    async onSure () {
+      const params = {
+        scoreProductId: this.itemData.scoreProductId,
+        ...this.formValues
+      }
+      this.loading = true
+      try {
+        await saveAccumulatePointProduct(params)
+        this.$message.success('操作成功')
+        this.$refs.dialog.close()
+        this.$emit('success')
+      } catch (error) {
+        this.$message.error(error)
+      } finally {
+        this.loading = false
+      }
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 136 - 0
src/views/accumulatePoints/accumulatePointsMotivateManage/index.vue

@@ -0,0 +1,136 @@
+<template>
+  <div class="pa-3 white">
+    <m-search class="mb-3" :items="searchItems" v-model="searchValues" @search="onSearch"></m-search>
+    <m-table
+      v-loading="loading"
+      :items="items"
+      :headers="headers"
+      :page-size="pageInfo.size"
+      :page-current="pageInfo.current"
+      :total="total"
+      @page-change="onPageChange"
+      @sort-change="onSortChange"
+    >
+      <template #card-tools>
+        <m-button type="orange" icon="el-icon-plus" @click="onAdd">新增</m-button>
+      </template>
+      <template #actions="{ row }">
+        <m-button type="primary" text @click="onEdit(row)">编辑</m-button>
+        <m-button type="danger" text @click="onDelete(row)">删除</m-button>
+      </template>
+    </m-table>
+    <AccumulatePointsMotivateManageEdit ref="accumulatePointsMotivateManageEditRefs" @success="onInit"></AccumulatePointsMotivateManageEdit>
+  </div>
+</template>
+
+<script>
+import {
+  getAccumulatePointProduct,
+  deleteAccumulatePointProduct
+} from '@/api/accumulatePoint'
+import AccumulatePointsMotivateManageEdit from './accumulatePointsMotivateManageEdit.vue'
+export default {
+  name: 'accumulatePointsMotivateManage',
+  components: {
+    AccumulatePointsMotivateManageEdit
+  },
+  data () {
+    return {
+      searchItems: [
+        {
+          label: '产品名称',
+          prop: 'productName',
+          type: 'input',
+          options: {
+            placeholder: '请输入名称'
+          }
+        }
+      ],
+      searchValues: {
+        productName: null
+      },
+      headers: [
+        { label: '产品名称', prop: 'productName' },
+        { label: '产品描述', prop: 'productDescription' },
+        { label: '产品兑换积分', prop: 'productScore', align: 'center' },
+        { label: '剩余数量', prop: 'remainingQuantity', align: 'center' },
+        { label: '创建日期', prop: 'createDate' },
+        { label: '操作', prop: 'actions' }
+      ],
+      items: [],
+      total: 0,
+      pageInfo: {
+        current: 1,
+        size: 10
+      },
+      orders: [
+        {
+          column: 'create_date',
+          asc: false
+        }
+      ],
+      loading: false
+    }
+  },
+  created () {
+    this.onInit()
+  },
+  methods: {
+    async onInit () {
+      this.loading = true
+      try {
+        const { data } = await getAccumulatePointProduct({
+          page: {
+            ...this.pageInfo,
+            orders: this.orders
+          },
+          entity: {
+            ...this.searchValues
+          }
+        })
+        this.items = data.records
+        this.total = data.total
+      } catch (error) {
+        this.$message.error(error)
+      } finally {
+        this.loading = false
+      }
+    },
+    onAdd () {
+      this.$refs.accumulatePointsMotivateManageEditRefs.open()
+    },
+    onEdit (item) {
+      this.$refs.accumulatePointsMotivateManageEditRefs.open(item)
+    },
+    onDelete (row) {
+      this.$confirm('确定删除吗?', '提示')
+        .then(async () => {
+          try {
+            await deleteAccumulatePointProduct({ scoreProductId: row.scoreProductId })
+            this.$message.success('删除成功')
+            this.onInit()
+          } catch (error) {
+            this.$message.error(error)
+          }
+        })
+        .catch(_ => {})
+    },
+    onSearch () {
+      this.pageInfo.current = 1
+      this.onInit()
+    },
+    onPageChange (index) {
+      this.pageInfo.current = index
+      this.onInit()
+    },
+    onSortChange (val) {
+      this.orders = val
+      this.onInit()
+    }
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+  /* 自定义样式 */
+</style>