Browse Source

优惠商品调整

zhengjinyi 2 years ago
parent
commit
ec1081e5d1

+ 32 - 1
src/api/member/member.js

@@ -86,7 +86,6 @@ export function fetchFindPackage() {
     method: 'get'
   })
 }
-
 export function updatePrice(params) {
   return request({
     url: '/svip/member/updatePrice',
@@ -94,3 +93,35 @@ export function updatePrice(params) {
     params
   })
 }
+export function updateSort(params) {
+  return request({
+    url: '/svip/member/updateSort',
+    method: 'get',
+    params
+  })
+}
+export function saveSvipProduct(id) {
+  return request({
+    url: '/svip/member/saveSvipProduct/' + id,
+    method: 'post'
+  })
+}
+export function delSvipProduct(id) {
+  return request({
+    url: '/svip/member/delSvipProduct/' + id,
+    method: 'post'
+  })
+}
+export function getAdsImage() {
+  return request({
+    url: '/svip/member/getAdsImage',
+    method: 'get'
+  })
+}
+export function saveAdsImage(data) {
+  return request({
+    url: '/svip/member/saveAdsImage',
+    method: 'post',
+    data: data
+  })
+}

+ 119 - 0
src/components/UploadFile/index.vue

@@ -0,0 +1,119 @@
+<template>
+  <div>
+    <el-upload
+      ref="fileUpload"
+      :data="data"
+      :auto-upload="autoUpload"
+      :class="{ 'el-upload-hidden': !chooseState}"
+      :action="action"
+      :headers="headers"
+      :on-success="uploadSuccess"
+      :on-remove="handleRemove"
+      :on-change="handleChange"
+      :before-upload="beforeUpload"
+      :on-error="uploadError"
+      :limit="limit"
+      :multiple="multiple"
+      :accept="accept"
+      :file-list="fileList"
+    >
+      <div v-if="tip" slot="tip" class="el-upload__tip">{{ tip }}</div>
+      <el-button size="mini" type="primary">选择文件</el-button>
+    </el-upload>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+export default {
+  name: 'UploadFile',
+  props: {
+    tip: {
+      type: String,
+      default: ''
+    },
+    multiple: {
+      type: Boolean,
+      default: false
+    },
+    limit: {
+      type: Number,
+      default: 1
+    },
+    accept: {
+      type: String,
+      default: '.doc,.ppt,.pdf'
+    },
+    listType: {
+      type: String,
+      default: 'picture-card'
+    },
+    fileList: {
+      type: Array,
+      default: () => []
+    },
+    uuid: {
+      type: Number,
+      default: 0
+    },
+    beforeUpload: {
+      type: Function,
+      default: () => true
+    },
+    autoUpload: {
+      type: Boolean,
+      default: true
+    },
+    data: {
+      type: Object,
+      default: () => ({})
+    },
+    mode: {
+      type: String,
+      default: 'brand'
+    }
+  },
+  data() {
+    return {
+      dialogVisible: false,
+      dialogImageUrl: ''
+    }
+  },
+  computed: {
+    ...mapGetters(['token']),
+    chooseState() {
+      return this.fileList.length < this.limit
+    },
+    action() {
+      if (this.mode === 'document') {
+        return process.env.VUE_APP_UPLOAD_API + '/upload/file'
+      } else {
+        return process.env.VUE_APP_UPLOAD_API + '/shop/upload/file'
+      }
+    },
+    headers() {
+      return {
+        'X-Token': this.token
+      }
+    }
+  },
+  methods: {
+    // 上传成功
+    uploadSuccess(response, file, fileList) {
+      this.$emit('success', { response, file, fileList })
+    },
+    // 删除
+    handleRemove(file, fileList) {
+      this.$emit('remove', { file, fileList })
+    },
+    // 变化
+    handleChange(file, fileList) {
+      this.$emit('change', { file, fileList })
+    },
+    // 上传失败
+    uploadError(err, file, fileList) {
+      this.$emit('error', { err, file, fileList })
+    }
+  }
+}
+</script>

+ 112 - 0
src/components/UploadImage/index.vue

@@ -0,0 +1,112 @@
+<template>
+  <div>
+    <el-upload
+      ref="upload"
+      :class="{ 'el-upload-hidden': !chooseState }"
+      :list-type="listType"
+      :action="action"
+      :headers="headers"
+      :on-success="uploadImageSuccess"
+      :on-remove="handleImageRemove"
+      :before-upload="beforeUpload"
+      :on-error="uploadError"
+      :on-preview="handlePictureCardPreview"
+      :limit="limit"
+      :multiple="multiple"
+      :accept="accept"
+      :file-list="imageList"
+    >
+      <div v-if="tip" slot="tip" class="el-upload__tip">{{ tip }}</div>
+      <button v-if="trigger" ref="trigger" slot="trigger" size="small" type="primary">选取文件</button>
+      <i slot="default" class="el-icon-plus" />
+    </el-upload>
+    <el-dialog :visible.sync="dialogVisible">
+      <img width="100%" :src="dialogImageUrl">
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+export default {
+  props: {
+    tip: {
+      type: String,
+      default: ''
+    },
+    multiple: {
+      type: Boolean,
+      default: false
+    },
+    limit: {
+      type: Number,
+      default: 1
+    },
+    accept: {
+      type: String,
+      default: '.jpg,.png,.gif'
+    },
+    listType: {
+      type: String,
+      default: 'picture-card'
+    },
+    imageList: {
+      type: Array,
+      default: () => []
+    },
+    uuid: {
+      type: Number,
+      default: 0
+    },
+    beforeUpload: {
+      type: Function,
+      default: () => true
+    },
+    trigger: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      dialogVisible: false,
+      dialogImageUrl: ''
+    }
+  },
+  computed: {
+    ...mapGetters(['token']),
+    chooseState() {
+      return this.imageList.length < this.limit
+    },
+    action() {
+      return process.env.VUE_APP_CORE_API + '/tools/image/upload/multi'
+    },
+    headers() {
+      return {
+        'X-Token': this.token
+      }
+    }
+  },
+  methods: {
+    // 上传成功
+    uploadImageSuccess(response, file, fileList) {
+      this.$emit('success', { response, file, fileList })
+    },
+    // 删除
+    handleImageRemove(file, fileList) {
+      this.$emit('remove', { file, fileList })
+    },
+    // 上传失败
+    uploadError(err, file, fileList) {
+      this.$emit('error', { err, file, fileList })
+    },
+    handlePictureCardPreview(file) {
+      this.dialogImageUrl = file.url
+      this.dialogVisible = true
+    },
+    handleClick() {
+      this.$refs.trigger.click()
+    }
+  }
+}
+</script>

+ 1 - 1
src/views/member/coupon/edit.vue

@@ -160,7 +160,7 @@
       />
     </el-dialog>
     <!-- 商品弹框 -->
-    <el-dialog title="选择供应商" :visible.sync="dialogProductVisible" width="50%">
+    <el-dialog title="选择商" :visible.sync="dialogProductVisible" width="50%">
       <div class="filter-container">
         <div class="filter-control">
           <span>商品Id:</span>

+ 23 - 16
src/views/member/member/list.vue

@@ -123,7 +123,7 @@
         <div class="club-container" style="width: 100%;height: 600px;padding-top: 40px;">
           <div class="filter-container">
             <div class="filter-control">
-              <el-form :model="form" label-width="120px">
+              <el-form :model="vipForm" label-width="120px">
                 <el-form-item label="机构" :hidden="!hiddenItem">
                   <el-button type="primary" size="mini" icon="el-icon-plus" @click="handleDialogVisible">请选择机构</el-button>
                 </el-form-item>
@@ -134,19 +134,17 @@
                     <el-table-column prop="linkMan" label="联系人" align="center" width="120" />
                     <el-table-column prop="contractMobile" label="手机号" align="center" width="120" />
                     <el-table-column label="操作" align="center" width="120">
-                      <template slot-scope="{ row }">
-                        <el-button type="danger" size="mini" @click="deleteClub(row)">删除</el-button>
-                      </template>
+                      <el-button type="danger" size="mini" @click="deleteClub">删除</el-button>
                     </el-table-column>
                   </el-table>
                 </el-form-item>
                 <el-form-item label="赠送会员">
-                  <el-input v-model="form.month" style="width: 150px">
+                  <el-input v-model="vipForm.month" style="width: 150px">
                     <template slot="append">个月</template>
                   </el-input>
                 </el-form-item>
                 <el-form-item>
-                  <el-button type="primary" @click="save()">保存</el-button>
+                  <el-button type="primary" :disabled="saveDisabled" @click="handleSaveVip">保存</el-button>
                 </el-form-item>
               </el-form>
             </div>
@@ -338,11 +336,11 @@ export default {
       // 会员列表总数
       total: 0,
       tableData: [],
-      form: {
+      vipForm: {
         clubId: 0,
         userId: 0,
         contractMobile: 0,
-        month: 0
+        month: ''
       },
       dialogTableVisible: false,
       // 选择机构总数
@@ -364,6 +362,9 @@ export default {
   computed: {
     disabled() {
       return this.clubRadio === null
+    },
+    saveDisabled() {
+      return !(this.vipForm.clubId > 0 && this.vipForm.month !== '')
     }
   },
   created() {
@@ -375,6 +376,9 @@ export default {
       this.$refs.table.clearSelection()
       this.$refs.table.toggleRowSelection(row)
       this.clubRadio = row.clubId
+      this.vipForm.clubId = row.clubId
+      this.vipForm.userId = row.userId
+      this.vipForm.contractMobile = row.contractMobile
       this.rows = row
       console.log('clubRadio', this.clubRadio)
     },
@@ -406,17 +410,20 @@ export default {
       console.log(this.clubData)
     },
     // 清除机构
-    deleteClub(row) {
+    deleteClub() {
       this.clubData = []
       this.hiddenItem = true
     },
-    async save() {
-      this.form.clubId = this.clubData[0].clubId
-      this.form.userId = this.clubData[0].userId
-      this.form.contractMobile = this.clubData[0].contractMobile
-      const res = await saveSvip(this.form)
-      if (res.code === 1) {
-        this.deleteClub()
+    async handleSaveVip() {
+      try {
+        await saveSvip(this.vipForm)
+        this.$message.success('操作成功')
+        setTimeout(() => {
+          this.deleteClub()
+          this.vipForm.month = ''
+        }, 2000)
+      } catch (error) {
+        console.log(error)
       }
     },
     handleTagsList(row) {

+ 149 - 0
src/views/member/product/components/proDialog.vue

@@ -0,0 +1,149 @@
+<template>
+  <el-dialog
+    title="添加商品"
+    :visible.sync="visible"
+    width="1100px"
+    :close-on-click-modal="false"
+    :show-close="false"
+  >
+    <div class="filter-container">
+      <div class="filter-control">
+        <span>商品ID:</span>
+        <el-input
+          v-model="listQuery.productId"
+          placeholder="商品ID"
+          clearable
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>商品名称:</span>
+        <el-input
+          v-model="listQuery.name"
+          placeholder="商品名称"
+          clearable
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <span>供应商名称:</span>
+        <el-input
+          v-model="listQuery.shopName"
+          placeholder="供应商名称"
+          clearable
+          style="width:160px;"
+          @keyup.enter.native="getList"
+          @clear="getList"
+        />
+      </div>
+      <div class="filter-control">
+        <el-button type="primary" @click="getList">查询</el-button>
+      </div>
+    </div>
+    <el-table ref="table" v-loading="isLoading" :data="list" height="400px" border @select="handleSelect">
+      <el-table-column type="selection" width="50" />
+      <el-table-column prop="productId" label="商品ID" align="center" width="80" />
+      <el-table-column prop="coupon" label="商品图片" align="center" width="100">
+        <template v-if="row.productId" slot-scope="{ row }">
+          <el-popover
+            placement="top-start"
+            title=""
+            width="180"
+            trigger="hover"
+          >
+            <img :src="row.mainImage" alt="" style="width:100px;height:100px;">
+            <img slot="reference" :src="row.mainImage" alt="" style="width:50px;height:50px;">
+          </el-popover>
+        </template>
+      </el-table-column>
+      <el-table-column prop="name" label="商品名称" align="center" />
+      <el-table-column prop="shopName" label="供应商" align="center" width="250" />
+      <el-table-column prop="price" label="机构价" align="center" width="160">
+        <template slot-scope="{ row }">
+          ¥{{ row.price ? row.price : '0.00' }}
+        </template>
+      </el-table-column>
+    </el-table>
+    <!-- 页码 -->
+    <pagination
+      :total="total"
+      :page-sizes="[20]"
+      :page-size="20"
+      :page.sync="listQuery.pageNum"
+      :limit.sync="listQuery.pageSize"
+      @pagination="getList"
+    />
+    <div slot="footer">
+      <el-button @click="handleCanle">取 消</el-button>
+      <el-button type="primary" :disabled="disabled" @click="handleAddProConfirm(productRadio)">确 定</el-button>
+    </div>
+  </el-dialog>
+</template>
+
+<script>
+import { fetchProductList } from '@/api/member/member'
+
+export default {
+  name: 'ProDialog',
+  filters: {
+    NumFormat(value) {
+      // 处理金额
+      return Number(value).toFixed(2)
+    }
+  },
+  data() {
+    return {
+      visible: true,
+      listQuery: {
+        productId: '', // 商品id
+        name: '', // 商品名称
+        shopName: '', // 供应商名称
+        pageNum: 1,
+        pageSize: 20
+      },
+      list: [],
+      total: 0,
+      productRadio: null,
+      isLoading: true
+    }
+  },
+  computed: {
+    disabled() {
+      return this.productRadio === null
+    }
+  },
+  created() {
+    this.getList()
+  },
+  methods: {
+    async getList() {
+      this.isLoading = true
+      const res = await fetchProductList(this.listQuery)
+      this.list = res.data.results
+      this.total = res.data.totalRecord
+      this.isLoading = false
+    },
+    // 选择供应商
+    handleSelect(selection, row) {
+      this.$refs.table.clearSelection()
+      this.$refs.table.toggleRowSelection(row)
+      this.productRadio = row.productId
+    },
+    handleAddProConfirm() {
+      // 确认选择商品
+      this.$emit('confirm', this.productRadio)
+    },
+    handleCanle() {
+      // 取消弹窗
+      this.$emit('cancel')
+    }
+  }
+}
+</script>
+<style lang="scss" scoped>
+::v-deep{
+  thead .el-checkbox{display: none !important;}
+}
+</style>

+ 177 - 18
src/views/member/product/list.vue

@@ -1,15 +1,15 @@
 <template>
   <div class="app-container">
-    <el-tabs v-model="activeName" type="border-card">
+    <el-tabs v-model="activeName" type="border-card" @tab-click="handleClick">
       <el-tab-pane label="商品列表" name="first" />
       <el-tab-pane label="宣传图" name="second" />
       <template v-if="activeName === 'first'">
         <div class="filter-container">
           <div class="filter-control">
-            <span>商品Id:</span>
+            <span>商品ID:</span>
             <el-input
               v-model="listQuery.productId"
-              placeholder="商品Id"
+              placeholder="商品ID"
               clearable
               @keyup.enter.native="getList"
               @clear="getList"
@@ -45,7 +45,7 @@
           </div>
           <div class="filter-control">
             <el-button type="primary" @click="getList">查询</el-button>
-            <el-button type="primary" @click="getList">添加</el-button>
+            <el-button type="primary" @click="proDialogVisible =true">添加</el-button>
           </div>
         </div>
         <el-table v-loading="isLoading" :data="tableData" border style="width: 100%">
@@ -58,8 +58,8 @@
                 width="180"
                 trigger="hover"
               >
-                <img :src="row.productImage" alt="" style="width:150px;height:150px;">
-                <img slot="reference" :src="row.productImage" alt="" style="width:30px;height:30px;">
+                <img :src="row.productImage" alt="" style="width:100px;height:100px;">
+                <img slot="reference" :src="row.productImage" alt="" style="width:50px;height:50px;">
               </el-popover>
             </template>
           </el-table-column>
@@ -76,7 +76,11 @@
               ¥{{ row.priceType === 2 ? row.discountPrice : row.price * row.discount * 0.01 }}
             </template>
           </el-table-column>
-          <el-table-column prop="sort" label="排序值" align="center" width="50" />
+          <el-table-column label="排序" width="80" align="center">
+            <template slot-scope="{row}">
+              <el-input v-model="row.sort" maxlength="4" minlength="1" @blur="handleOnInputBlur(row)" />
+            </template>
+          </el-table-column>
           <el-table-column prop="status" label="优惠状态" align="center" width="100">
             <template slot-scope="{ row }">
               <span v-if="row.status === 0" class="el-span-zero">
@@ -89,9 +93,9 @@
           </el-table-column>
           <el-table-column prop="addTime" label="添加时间" align="center" width="100" />
           <el-table-column label="操作" align="center" width="180">
-            <template>
+            <template slot-scope="{ row }">
               <el-button type="primary" size="mini">编辑</el-button>
-              <el-button type="danger" size="mini">删除</el-button>
+              <el-button type="danger" size="mini" @click="handeleDelPro(row.id)">删除</el-button>
             </template>
           </el-table-column>
         </el-table>
@@ -104,14 +108,37 @@
           :page.sync="listQuery.pageNum"
           :limit.sync="listQuery.pageSize"
         />
+        <!--  选择商品弹窗 -->
+        <pro-dialog v-if="proDialogVisible" ref="proDialog" @confirm="handleAddProductConfirm" @cancel="handleCancel" />
       </template>
       <template v-else>
-        <div class="coupon-content">
-          <div class="filter-control">
-            <span>pc端宣传图:</span>
-          </div>
-          <div class="filter-control">
-            <span>小程序宣传图:</span>
+        <div class="club-container" style="width: 100%;height: 650px;padding-top: 40px;">
+          <el-form ref="submitForm" class="doctor-edit-form" label-width="140px" :model="formData" :rules="rules">
+            <el-form-item label="PC端:" prop="doctorImage">
+              <div class="form-label-tip">宣传图</div>
+              <el-input v-show="false" v-model="formData.pcImage" />
+              <upload-image
+                tip="提示:建议图片分辨率1920px*510px"
+                :image-list="pcImageList"
+                :before-upload="beforeDoctorImageUpload"
+                @success="uploadDoctorImageSuccess"
+                @remove="handleDoctorImageRemove"
+              />
+            </el-form-item>
+            <el-form-item label="小程序端:" prop="banner">
+              <div class="form-label-tip">宣传图</div>
+              <el-input v-show="false" v-model="formData.appletsImage" />
+              <upload-image
+                tip="提示:建议图片分辨率351px*170px"
+                :image-list="appletsImageList"
+                :before-upload="beforeBannerUpload"
+                @success="uploadBannerSuccess"
+                @remove="handleBannerRemove"
+              />
+            </el-form-item>
+          </el-form>
+          <div class="submit-btn" style="padding-left: 137px;">
+            <el-button type="primary" :disabled="disabled" @click="submitSave">保存</el-button>
           </div>
         </div>
       </template>
@@ -119,9 +146,13 @@
   </div>
 </template>
 <script>
-import { fetchFindProductList } from '@/api/member/member'
+import { fetchFindProductList, updateSort, saveAdsImage, getAdsImage } from '@/api/member/member'
+import { delSvipProduct, saveSvipProduct } from '@/api/member/member'
+import UploadImage from '@/components/UploadImage'
+import ProDialog from './components/proDialog'
 export default {
   name: 'MemberProduct',
+  components: { UploadImage, ProDialog },
   data() {
     return {
       activeName: 'first',
@@ -133,10 +164,28 @@ export default {
         pageNum: 0,
         pageSize: 20
       },
+      formData: {
+        pcImage: '',
+        appletsImage: ''
+      },
+      // PC端宣传图
+      pcImageList: [],
+      // 小程序端宣传图
+      appletsImageList: [],
+      rules: {
+        pcImage: [{ required: true, message: '请上传PC端宣传图', trigger: 'change' }],
+        appletsImage: [{ required: true, message: '请上传小程序端宣传图', trigger: 'change' }]
+      },
       // 超级会员商品列表
       total: 0,
       isLoading: true,
-      tableData: []
+      tableData: [],
+      proDialogVisible: false
+    }
+  },
+  computed: {
+    disabled() {
+      return !(this.formData.pcImage !== '' > 0 && this.formData.appletsImage !== '')
     }
   },
   created() {
@@ -149,7 +198,117 @@ export default {
       this.tableData = res.data.results
       this.total = res.data.totalRecord
       this.isLoading = false
-      console.log(this.tableData)
+    },
+    handleOnInputBlur(row) {
+      // 更新排序
+      updateSort({ id: row.id, sort: row.sort }).then(response => {
+        this.$message({
+          message: '操作成功',
+          type: 'success',
+          duration: 1000
+        })
+        this.getList()
+      })
+    },
+    // tab切换
+    handleClick(tab, event) {
+      if (tab.name === 'second') {
+        this.getAdsImageData()
+      }
+    },
+    async getAdsImageData() {
+      try {
+        this.pcImageList = []
+        this.appletsImageList = []
+        const res = await getAdsImage(this.formData)
+        console.log('res', res.data)
+        this.formData.pcImage = res.data.pcImage
+        this.formData.appletsImage = res.data.appletsImage
+        this.pcImageList.push({ url: res.data.pcImage, name: 'doctor' })
+        this.appletsImageList.push({ url: res.data.appletsImage, name: 'doctor' })
+        console.log('pcImageList', this.pcImageList)
+        console.log('appletsImageList', this.appletsImageList)
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    async submitSave() {
+      // 保存
+      try {
+        console.log('formData', this.formData)
+        await saveAdsImage(this.formData)
+        this.$message.success('保存成功')
+        setTimeout(() => {
+          this.getAdsImageData()
+        }, 2000)
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    // PC端宣传图上传
+    uploadDoctorImageSuccess({ response, file, fileList }) {
+      this.pcImageList = fileList
+      this.formData.pcImage = response.data
+    },
+    handleDoctorImageRemove({ file, fileList }) {
+      this.pcImageList = fileList
+      this.formData.pcImage = ''
+    },
+    beforeDoctorImageUpload(file) {
+      const flag = file.size / 1024 / 1024 < 2
+      if (!flag) {
+        this.$message.error('上传图片大小不能超过 2MB!')
+      }
+      return flag
+    },
+    // 小程序端宣传图上传
+    uploadBannerSuccess({ response, file, fileList }) {
+      this.appletsImageList = fileList
+      this.formData.appletsImage = fileList.length || ''
+    },
+    handleBannerRemove({ file, fileList }) {
+      this.appletsImageList = fileList
+      this.formData.appletsImage = fileList.length || ''
+    },
+    beforeBannerUpload(file) {
+      const flag = file.size / 1024 / 1024 < 2
+      if (!flag) {
+        this.$message.error('上传图片大小不能超过 2MB!')
+      }
+      return flag
+    },
+    async handeleDelPro(id) {
+      await this.$confirm('确认要删除该商品吗?', {
+        confirmButtonText: '确定',
+        cancelButtonText: '取消',
+        type: 'warning'
+      })
+      this.delSvipProductSubmit(id)
+    },
+    async delSvipProductSubmit(id) {
+      try {
+        await delSvipProduct(id)
+        this.$message.success('操作成功')
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    async handleAddProductConfirm(id) {
+      // 确认添加商品
+      try {
+        await saveSvipProduct(id)
+        this.$message.success('添加成功')
+        this.handleCancel()
+        this.getList()
+      } catch (error) {
+        console.log(error)
+      }
+    },
+    handleCancel() {
+      // 取消选择添加商品
+      this.proDialogVisible = false
+      this.$refs.proDialog.visible = false
     }
   }
 }