Răsfoiți Sursa

Merge branch 'dev' into 'test'

Dev

See merge request quanshu/mp-ui-pc!343
世轩 3 ani în urmă
părinte
comite
9142f13f8c

+ 38 - 0
src/api/business/goods.js

@@ -59,3 +59,41 @@ export function salesiteGoodsExport( data) {
   })
 }
 
+/**
+ * Post 方式上传文件
+ */
+export function setCamiloShip(data, config = {},goodsId) {
+  var formData  = new FormData()
+  Object.keys(data).forEach(key => {
+    formData.append(key, data[key])
+  })
+  return request({
+    url: `/api/v1/mp/admin/goods/card/import/${goodsId}`,
+    method: 'post',
+    data: formData ,
+    ...config,
+    headers: {
+      'Content-Type': 'multipart/form-data'
+    }
+  })
+}
+
+
+// 下载卡密导入模板
+export function cradDownload() {
+  return request({
+    url: '/api/v1/mp/admin/goods/card/template/download',
+    method: 'post',
+  })
+}
+
+// 查看卡密列表
+export function cradCamiloList(urlParams, data) {
+  return request({
+    url: '/api/v1/mp/admin/goods/card/list',
+    method: 'post',
+    data,
+    urlParams
+  })
+}
+

+ 69 - 0
src/components/Camilo/index.vue

@@ -0,0 +1,69 @@
+<template>
+  <div>
+    <el-dialog title="查看卡密" :visible.sync="camiloShow" :before-close="close">
+      <el-table :data="camiloData">
+        <el-table-column property="cardNo" label="卡号" min-width="250"></el-table-column>
+        <el-table-column property="cardPwd" label="密码(激活码)" min-width="250"></el-table-column>
+      </el-table>
+      <pagination :total="total" :page.sync="pageParams.pageNum" :limit.sync="pageParams.pageSize"
+                  @pagination="getList()"/>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import {cradCamiloList} from "../../api/business/goods";
+
+export default {
+  name: "camilo",
+  props: {
+    camiloShow: {
+      type: Boolean,
+      default: true
+    },
+    camiloGoodsId: {
+      type: Number,
+      default: 0
+    },
+  },
+  data() {
+    return {
+      pageParams: {
+        pageNum: 1,
+        pageSize: 10
+      },
+      loading: false,
+      camiloData: [],
+      total: 0,
+    };
+  },
+  mounted() {
+    this.getList()
+  },
+  methods: {
+    close() {
+      this.$emit('cancel')
+    },
+    getList() {
+      if (this.loading) {
+        return
+      }
+      this.loading = true
+      cradCamiloList('pageNum=' + this.pageParams.pageNum + '&pageSize=' + this.pageParams.pageSize + '&', {goodsId: this.camiloGoodsId}).then(res => {
+        this.loading = false
+        if (res.code === 0) {
+          this.camiloData = res.rows
+          this.total = res.total
+        }
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+
+  }
+}
+</script>
+
+<style lang="scss" scoped>
+
+</style>

+ 6 - 4
src/views/business/coupon/add.vue

@@ -8,7 +8,7 @@
             <el-input v-model="addData.title" :readonly="readonly" placeholder="请输入券名称" :maxlength="32" show-word-limit />
           </el-form-item>
           <el-form-item label="使用场景:" prop="type">
-            <el-radio-group v-model="addData.type" :disabled="readonly">
+            <el-radio-group v-model="addData.type" :disabled="readonly || addData.status !== 'init'">
               <el-radio :label="2">门店消费</el-radio>
               <el-radio :label="1">盲票购买</el-radio>
             </el-radio-group>
@@ -54,14 +54,14 @@
             <el-input type="textarea" rows="4" :readonly="readonly" v-model="addData.description" placeholder="请输入使用说明 对用户可见"/>
           </el-form-item>
           <el-form-item v-if="addData.type === 2" label="使用范围:" prop="useArea">
-            <el-radio-group v-model="addData.useArea" :disabled="readonly">
+            <el-radio-group v-model="addData.useArea" :disabled="readonly || addData.status !== 'init'">
               <el-radio :label="2">进票门店</el-radio>
               <el-radio :label="1">指定门店</el-radio>
               <el-radio :label="0">所有门店</el-radio>
             </el-radio-group>
           </el-form-item>
           <el-form-item v-else label="使用范围:" prop="useArea">
-            <el-radio-group v-model="addData.useArea" :disabled="readonly">
+            <el-radio-group v-model="addData.useArea" :disabled="readonly || addData.status !== 'init'">
               <el-radio :label="0">所有盲票</el-radio>
               <el-radio :label="3">线上盲票</el-radio>
               <el-radio :label="4">线下盲票</el-radio>
@@ -172,6 +172,7 @@ export default {
         type: 2,
         channelSharedRate:0,
         minOrderAmt:0,
+        status: '',
       },
       addIng: false,
       excludeBoxIds: [],
@@ -209,10 +210,11 @@ export default {
   created() {
     if (this.id) {
       getCouponDetail(this.id).then(res => {
-        const { couponId, title, quantity, discount, channelSharedRate, minOrderAmt, dueDays, description, ticketBoxList, channelList } = res.data
+        const { couponId, title, quantity, discount, channelSharedRate, minOrderAmt, dueDays, description, ticketBoxList, channelList, status } = res.data
         this.addData = {
           type: JSON.parse(res.data.type).value,
           useArea: JSON.parse(res.data.useArea).value,
+          status: JSON.parse(res.data.status).value,
           discount: accDiv(discount, 100),
           minOrderAmt: accDiv(minOrderAmt, 100),
           couponId, title, quantity, channelSharedRate, dueDays, description, ticketBoxList

+ 1 - 1
src/views/business/coupon/index.vue

@@ -73,7 +73,7 @@
       <el-table-column fixed="right" align="right" label="操作" width="150">
         <template slot-scope="{row}">
           <el-button v-hasPermi="['business:coupon:query']" type="text" @click="$router.push({ name: 'CouponQuery', query: { id: row.couponId } })">查看</el-button>
-          <el-button v-if="JSON.parse(row.status).value === 'init'" v-hasPermi="['business:coupon:edit']" type="text" @click="$router.push({ name: 'CouponEdit', query: { id: row.couponId } })">编辑</el-button>
+          <el-button v-hasPermi="['business:coupon:edit']" type="text" @click="$router.push({ name: 'CouponEdit', query: { id: row.couponId } })">编辑</el-button>
           <el-button v-if="JSON.parse(row.status).value === 'off' || JSON.parse(row.status).value === 'init'" v-hasPermi="['business:coupon:on']" type="text" @click="setStatus(row, 'on')">上架</el-button>
           <el-button v-if="JSON.parse(row.status).value === 'on'" v-hasPermi="['business:coupon:off']" type="text" @click="setStatus(row, 'off')">下架</el-button>
           <el-button v-if="JSON.parse(row.status).value === 'init'" v-hasPermi="['business:coupon:remove']" class="del" type="text" @click="del(row)">删除</el-button>

+ 145 - 70
src/views/business/goods/add.vue

@@ -2,6 +2,16 @@
   <div class="app-container goods-add">
     <el-divider content-position="left">商品信息</el-divider>
     <el-form ref="addItem" :rules="rules" :model="addData" label-width="120px">
+      <el-row :gutter="40" style="width: 500px">
+        <el-col :span="23">
+          <el-form-item label="商品类型:" prop="type">
+            <el-radio-group v-model="addData.type" :disabled="addData.goodsId">
+              <el-radio :label="1">实物商品</el-radio>
+              <el-radio :label="2">卡密商品</el-radio>
+            </el-radio-group>
+          </el-form-item>
+        </el-col>
+      </el-row>
       <el-row :gutter="40" style="width: 600px">
         <el-col :span="23">
           <el-form-item label="商品名称:" prop="title">
@@ -10,7 +20,7 @@
         </el-col>
         <el-col :span="23">
           <el-form-item label="商品主图:" prop="picUrl">
-            <Upload v-model="mainPicUrl" :limit="10" />
+            <Upload v-model="mainPicUrl" :limit="10"/>
             <div class="tip">第一张图片将作为商品列表图片,最多上传10张,多张图片之间可随意调整位置,支持jpg、png格式,推荐750*750px;</div>
           </el-form-item>
         </el-col>
@@ -18,12 +28,12 @@
       <el-row :gutter="40" style="width: 500px">
         <el-col :span="23">
           <el-form-item label="支持盲豆兑换:" prop="exchangeShow">
-<!--            <el-switch-->
-<!--              v-model="addData.exchangeShow"-->
-<!--              :active-value="1"-->
-<!--              :inactive-value="0"-->
-<!--            />-->
-<!--            <div class="tip">关闭则不再兑换大厅显示,不支持盲豆兑换。</div>-->
+            <!--            <el-switch-->
+            <!--              v-model="addData.exchangeShow"-->
+            <!--              :active-value="1"-->
+            <!--              :inactive-value="0"-->
+            <!--            />-->
+            <!--            <div class="tip">关闭则不再兑换大厅显示,不支持盲豆兑换。</div>-->
             <el-radio-group v-model="addData.exchangeShow">
               <el-radio :label="0">不支持</el-radio>
               <el-radio :label="1">支持</el-radio>
@@ -37,7 +47,8 @@
           <el-form-item label="商品分类:" prop="categoryId">
             <el-cascader
               v-model="addData.categoryId" clearable
-              :options="goodsCategoryItemsList" :props="{ expandTrigger: 'hover', value: 'categoryId',label: 'name', children: 'goodsCategoryList', }"></el-cascader>
+              :options="goodsCategoryItemsList"
+              :props="{ expandTrigger: 'hover', value: 'categoryId',label: 'name', children: 'goodsCategoryList', }"></el-cascader>
           </el-form-item>
         </el-col>
       </el-row>
@@ -50,9 +61,9 @@
               filterable
               clearable
             >
-              <el-option :label="item.name" :value="item.id" v-for="(item, index) in SupplierList" :key="index" />
+              <el-option :label="item.name" :value="item.id" v-for="(item, index) in SupplierList" :key="index"/>
             </el-select>
-            <a style="margin-left: 20px;color:#3983EF;" @click="handleAdd">添加供应商</a>
+            <a style="margin-left: 20px;color: #1890FF;" @click="handleAdd">添加供应商</a>
           </el-form-item>
 
         </el-col>
@@ -65,7 +76,7 @@
         </el-col>
       </el-row>
 
-       <el-row :gutter="40" style="width: 500px">
+      <el-row :gutter="40" style="width: 500px">
         <el-col :span="23">
           <el-form-item label="商品标签:">
             <el-select
@@ -74,21 +85,22 @@
               multiple
               clearable
             >
-              <el-option :label="item.name" :value="item.tagId" v-for="(item, index) in goodsTagItemsList" :key="index" />
+              <el-option :label="item.name" :value="item.tagId" v-for="(item, index) in goodsTagItemsList"
+                         :key="index"/>
             </el-select>
           </el-form-item>
         </el-col>
-         <el-col :span="23">
-           <el-form-item label="商家信息:">
-             <Upload v-model="MerchantInformation" :limit="10" />
-             <div class="tip">上传商家营业执照</div>
-           </el-form-item>
-         </el-col>
+        <el-col :span="23">
+          <el-form-item label="商家信息:">
+            <Upload v-model="MerchantInformation" :limit="10"/>
+            <div class="tip">上传商家营业执照</div>
+          </el-form-item>
+        </el-col>
       </el-row>
       <el-divider content-position="left">价格库存</el-divider>
       <el-row>
         <el-col :span="23">
-          <el-form-item label="启用多SKU:">
+          <el-form-item label="启用多SKU:" v-if="addData.type == '1'">
             <el-switch
               v-model="addData.multiSku"
               :active-value="1"
@@ -100,7 +112,7 @@
       <el-row>
         <el-col :span="22">
           <el-form-item prop="skuList">
-            <Spec ref="spec" @valid="update" :multiSku="addData.multiSku" />
+            <Spec ref="spec" @valid="update" :multiSku="addData.multiSku"/>
           </el-form-item>
         </el-col>
       </el-row>
@@ -128,7 +140,7 @@
           </el-form-item>
         </el-col>
         <el-col :span="23">
-          <el-form-item label="盲豆划线价:" >
+          <el-form-item label="盲豆划线价:">
             <el-input v-model="addData.originPrice" type="number" placeholder="请输入盲豆数量">
               <template slot="append">盲豆</template>
             </el-input>
@@ -148,18 +160,23 @@
           </el-form-item>
         </el-col>
         <el-col :span="23">
-          <el-form-item label="库存:" prop="quantity">
+          <el-form-item label="库存:" prop="quantity" v-if="addData.type == '1'">
             <el-input v-model="addData.quantity" type="number" placeholder="请输入商品库存">
               <template slot="append">件</template>
             </el-input>
           </el-form-item>
         </el-col>
+        <el-col :span="23">
+          <el-form-item label="卡密使用链接:" v-if="addData.type == '2'">
+            <el-input v-model="addData.useLink" placeholder="请输入商品采购链接"/>
+          </el-form-item>
+        </el-col>
       </el-row>
       <!-- <el-divider content-position="left">商品详情</el-divider> -->
       <el-row>
         <el-col :span="22">
           <el-form-item label="商品详情" prop="description">
-            <wang-editor ref="editor" v-model="addData.description" />
+            <wang-editor ref="editor" v-model="addData.description"/>
           </el-form-item>
         </el-col>
       </el-row>
@@ -183,12 +200,12 @@ import Upload from '@/components/DragImageUpload'
 import WangEditor from '@/components/WangEditor'
 import Spec from './components/spec'
 import TinyEditor from '@/components/TinyEditor'
-import { getGoodsDetail, addGoods } from '@/api/business/goods'
-import { goodsCategoryListTree } from '@/api/business/category'
-import { getSupplierList } from '@/api/business/supplier'
-import { goodsTagItems } from '@/api/business/tag'
-import { publicFileGetUrl } from "@/api/common"
-import { accDiv, accMul } from '@/utils/util'
+import {getGoodsDetail, addGoods} from '@/api/business/goods'
+import {goodsCategoryListTree} from '@/api/business/category'
+import {getSupplierList} from '@/api/business/supplier'
+import {goodsTagItems} from '@/api/business/tag'
+import {publicFileGetUrl} from "@/api/common"
+import {accDiv, accMul} from '@/utils/util'
 import AddSupplier from "../supplier/components/addSupplier";
 export default {
   name: 'GoodsAdd',
@@ -197,7 +214,7 @@ export default {
     WangEditor,
     Upload,
     Spec,
-    AddSupplier
+    AddSupplier,
   },
   data() {
     return {
@@ -207,46 +224,56 @@ export default {
       SupplierList: [],
       goodsTagItemsList: [],
       addData: {
+        type: 1,
         multiSku: 0,
         description: '',
         originPrice: 0,
         exchangeShow: 0,
       },
-      createShow:false,
+      createShow: false,
       rules: {
-        title: [{ required: true, message: '请输入商品名称', trigger: 'blur' }],
-        picUrl: [{ required: true, message: '请上传商品图片', trigger: 'change' }],
-        categoryId: [{ required: true, message: '请选择商品分类', trigger: 'change' }],
-        supplierId: [{ required: true, message: '请选择供应商', trigger: 'change' }],
-        exchangeShow: [{ required: true, message: '请选择是否支持盲豆兑换', trigger: 'change' }],
-        multiSku: [{ required: true, message: '请选择SKU类型', trigger: 'change' }],
+        title: [{required: true, message: '请输入商品名称', trigger: 'blur'}],
+        picUrl: [{required: true, message: '请上传商品图片', trigger: 'change'}],
+        categoryId: [{required: true, message: '请选择商品分类', trigger: 'change'}],
+        supplierId: [{required: true, message: '请选择供应商', trigger: 'change'}],
+        exchangeShow: [{required: true, message: '请选择是否支持盲豆兑换', trigger: 'change'}],
+        multiSku: [{required: true, message: '请选择SKU类型', trigger: 'change'}],
         value: [
-          { required: true, message: '请输商品入价格', trigger: 'blur' },
-          { pattern: /^([1-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/, message: "请输入正确的金额,最多两位小数", trigger: ["blur", "change"] }
+          {required: true, message: '请输商品入价格', trigger: 'blur'},
+          {
+            pattern: /^([1-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/,
+            message: "请输入正确的金额,最多两位小数",
+            trigger: ["blur", "change"]
+          }
         ],
         exchangePrice: [
-          { required: true,message:'请输入盲豆数量', trigger: 'blur' },
-          { pattern: /^([1-9]\d*)$/, message: "请输入正确盲豆数量", trigger: ["blur", "change"] }
+          {required: true, message: '请输入盲豆数量', trigger: 'blur'},
+          {pattern: /^([1-9]\d*)$/, message: "请输入正确盲豆数量", trigger: ["blur", "change"]}
         ],
         discountRate: [
-          { required: true,message:'请输入回收折扣', trigger: 'blur' },
+          {required: true, message: '请输入回收折扣', trigger: 'blur'},
           {
             pattern:
-              /^([1-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/,
+              /^([0-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/,
             message: "请输入合法的数字,最多两位小数",
             trigger: ["blur", "change"],
           },
         ],
         cost: [
-          { required: false, message: '请输入商品成本', trigger: 'blur' },
-          { pattern: /^([1-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/, message: "请输入正确的金额,最多两位小数", trigger: ["blur", "change"] }
+          {required: false, message: '请输入商品成本', trigger: 'blur'},
+          {
+            pattern: /^([1-9]\d*(\.\d{1,2})?|([0](\.([0][1-9]|[1-9]\d{0,1}))))$/,
+            message: "请输入正确的金额,最多两位小数",
+            trigger: ["blur", "change"]
+          }
         ],
         quantity: [
-          { required: true, message: '请输入库存', trigger: 'blur' },
-          { pattern: /^([1-9]\d*)$/, message: "请输入正确的数字", trigger: ["blur", "change"] }
+          {required: true, message: '请输入库存', trigger: 'blur'},
+          {pattern: /^([1-9]\d*)$/, message: "请输入正确的数字", trigger: ["blur", "change"]}
         ],
-        description: [{ required: true, message: '请输入商品详情', trigger: 'blur' }]
-      }
+        description: [{required: true, message: '请输入商品详情', trigger: 'blur'}]
+      },
+
     }
   },
   computed: {
@@ -259,10 +286,12 @@ export default {
         }) : []
       },
       set(val) {
-        this.$set(this.addData, 'picUrl', val.map(item => { return item.fileName }).toString())
+        this.$set(this.addData, 'picUrl', val.map(item => {
+          return item.fileName
+        }).toString())
       }
     },
-    MerchantInformation:{
+    MerchantInformation: {
       get() {
         return this.addData.merchantInfo ? this.addData.merchantInfo.split(',').map(item => {
           return {
@@ -271,7 +300,9 @@ export default {
         }) : []
       },
       set(val) {
-        this.$set(this.addData, 'merchantInfo', val.map(item => { return item.fileName }).toString())
+        this.$set(this.addData, 'merchantInfo', val.map(item => {
+          return item.fileName
+        }).toString())
       }
     }
   },
@@ -281,13 +312,53 @@ export default {
     this.getGoodsTagItems()
     if (this.id) {
       getGoodsDetail(this.id).then(res => {
-        const { goodsId, title, goodsCode, picUrl,merchantInfo, exchangeShow, multiSku, value, exchangePrice, originPrice, discountRate, cost, quantity, description, skuList, categoryId, supplierId, shoppingLink, tagIds } = res.data
+        const {
+          goodsId,
+          title,
+          type,
+          goodsCode,
+          picUrl,
+          merchantInfo,
+          exchangeShow,
+          multiSku,
+          value,
+          exchangePrice,
+          originPrice,
+          discountRate,
+          cost,
+          quantity,
+          description,
+          skuList,
+          categoryId,
+          supplierId,
+          shoppingLink,
+          tagIds,
+          useLink
+        } = res.data
         this.addData = {
           value: accDiv(value, 100),
           cost: cost == '' || cost == null ? '' : accDiv(cost, 100),
-          goodsId, title, goodsCode, picUrl,merchantInfo, exchangeShow, multiSku, exchangePrice, discountRate, originPrice, quantity, description, skuList, categoryId, supplierId, shoppingLink, tagIds
+          goodsId,
+          title,
+          type,
+          goodsCode,
+          picUrl,
+          merchantInfo,
+          exchangeShow,
+          multiSku,
+          exchangePrice,
+          discountRate,
+          originPrice,
+          quantity,
+          description,
+          skuList,
+          categoryId,
+          supplierId,
+          shoppingLink,
+          tagIds,
+          useLink
         }
-        if(description) {
+        if (description) {
           this.$refs.editor.setContent(description)
         }
         if (multiSku && skuList instanceof Array && skuList.length > 0) {
@@ -299,25 +370,26 @@ export default {
     }
   },
   methods: {
-    getGoodsCategoryItems(){
-      goodsCategoryListTree("",{}).then(res => {
+    getGoodsCategoryItems() {
+      goodsCategoryListTree("", {}).then(res => {
         this.goodsCategoryItemsList = res && res.rows
       })
     },
     //获取供应商
-    getSupplierItems(){
-      getSupplierList('',{name:""}).then(res => {
+    getSupplierItems() {
+      getSupplierList('', {name: ""}).then(res => {
         this.SupplierList = res && res.rows
       })
     },
     handleAdd() {
       this.createShow = true;
     },
-    close(){
+    close() {
       this.createShow = false;
       this.getSupplierItems()
     },
-    getGoodsTagItems(){
+
+    getGoodsTagItems() {
       goodsTagItems({}).then(res => {
         this.goodsTagItemsList = res && res.data
       })
@@ -333,14 +405,16 @@ export default {
       this.$refs.addItem.validate((valid, items) => {
         if (valid) {
           this.addData.skuList = skuList
-          const { value, categoryId, cost,exchangePrice, description, ...rest } = this.addData
-          addGoods({...rest, ...{
-            value: accMul(value, 100),
-            cost: cost == '' || cost == null ? '' : accMul(cost, 100),
-            exchangePrice: accMul(exchangePrice, 1),
-            description: encodeURI(description),
-            categoryId:categoryId[1],
-          }}).then(res => {
+          const {value, categoryId, cost, exchangePrice, description, ...rest} = this.addData
+          addGoods({
+            ...rest, ...{
+              value: accMul(value, 100),
+              cost: cost == '' || cost == null ? '' : accMul(cost, 100),
+              exchangePrice: accMul(exchangePrice, 1),
+              description: encodeURI(description),
+              categoryId: categoryId[1],
+            }
+          }).then(res => {
             if (res.code === 0) {
               this.$message({
                 message: this.addData.goodsId ? '修改成功!' : '添加成功!',
@@ -351,7 +425,7 @@ export default {
             }
           })
         } else {
-          if (items && Object.keys(items).length>0) {
+          if (items && Object.keys(items).length > 0) {
             this.$message({
               message: items[Object.keys(items)[0]][0].message,
               type: 'warning'
@@ -369,6 +443,7 @@ export default {
     font-size: 12px;
     color: #999;
   }
+
   .el-divider {
     .is-left {
       color: #409EFF;

+ 256 - 69
src/views/business/goods/index.vue

@@ -19,10 +19,19 @@
           @keyup.enter.native="queryParams.pageNum = 1;getList()"
         />
       </el-form-item>
+      <el-form-item label="商品类型" prop="type">
+        <el-select v-model="queryParams.type" placeholder="请选择是否支持兑换" clearable
+                   @change="queryParams.pageNum = 1;getList()">
+          <el-option label="全部" value=""/>
+          <el-option label="实物商品" value="1"/>
+          <el-option label="卡密商品" value="2"/>
+        </el-select>
+      </el-form-item>
       <el-form-item label="商品分类" prop="categoryIdList">
         <el-cascader
           v-model="queryParams.categoryIdList" collapse-tags clearable
-          :options="goodsCategoryItemsList" :props="{ expandTrigger: 'hover', value: 'categoryId',label: 'name', children: 'goodsCategoryList', multiple: true, }"
+          :options="goodsCategoryItemsList"
+          :props="{ expandTrigger: 'hover', value: 'categoryId',label: 'name', children: 'goodsCategoryList', multiple: true, }"
           @change="queryParams.pageNum = 1;getList()"></el-cascader>
       </el-form-item>
       <el-form-item label="商品标签" prop="tagId">
@@ -32,43 +41,49 @@
           clearable
           @change="queryParams.pageNum = 1;getList()"
         >
-          <el-option :label="item.name" :value="item.tagId" v-for="(item, index) in goodsTagItemsList" :key="index" />
+          <el-option :label="item.name" :value="item.tagId" v-for="(item, index) in goodsTagItemsList" :key="index"/>
         </el-select>
       </el-form-item>
-      <br>
       <el-form-item label="上架状态" prop="status">
-        <el-select v-model="queryParams.status" placeholder="请选择商品状态" clearable @change="queryParams.pageNum = 1;getList()">
-          <el-option label="全部" value="" />
-          <el-option label="待上架" value="init" />
-          <el-option label="已上架" value="on" />
-          <el-option label="已下架" value="off" />
+        <el-select v-model="queryParams.status" placeholder="请选择商品状态" clearable
+                   @change="queryParams.pageNum = 1;getList()">
+          <el-option label="全部" value=""/>
+          <el-option label="待上架" value="init"/>
+          <el-option label="已上架" value="on"/>
+          <el-option label="已下架" value="off"/>
         </el-select>
       </el-form-item>
       <el-form-item label="是否支持兑换" prop="exchangeShow">
-        <el-select v-model="queryParams.exchangeShow" placeholder="请选择是否支持兑换" clearable @change="queryParams.pageNum = 1;getList()">
-          <el-option label="全部" value="" />
-          <el-option label="支持兑换" value="1" />
-          <el-option label="不支持兑换" value="0" />
-          <el-option label="盲票商品" value="2" />
+        <el-select v-model="queryParams.exchangeShow" placeholder="请选择是否支持兑换" clearable
+                   @change="queryParams.pageNum = 1;getList()">
+          <el-option label="全部" value=""/>
+          <el-option label="支持兑换" value="1"/>
+          <el-option label="不支持兑换" value="0"/>
+          <el-option label="盲票商品" value="2"/>
         </el-select>
       </el-form-item>
       <el-form-item label="供应商" prop="supplierId">
-        <el-select v-model="queryParams.supplierId" placeholder="请选择供应商" filterable clearable  @clear="queryParams.pageNum = 1;getList()" @change="queryParams.pageNum = 1;getList()">
-          <el-option :label="item.name" :value="item.id" v-for="(item, index) in SupplierList" :key="index" />
+        <el-select v-model="queryParams.supplierId" placeholder="请选择供应商" filterable clearable
+                   @clear="queryParams.pageNum = 1;getList()" @change="queryParams.pageNum = 1;getList()">
+          <el-option :label="item.name" :value="item.id" v-for="(item, index) in SupplierList" :key="index"/>
         </el-select>
       </el-form-item>
       <br>
       <el-form-item label="商品成本" prop="minCost">
-        <el-input v-model="queryParams.minCost" placeholder="最低成本" clearable @keyup.enter.native="queryParams.pageNum = 1;getList()" />
+        <el-input v-model="queryParams.minCost" placeholder="最低成本" clearable
+                  @keyup.enter.native="queryParams.pageNum = 1;getList()"/>
       </el-form-item>
       <el-form-item label="-" prop="maxCost">
-        <el-input v-model="queryParams.maxCost" placeholder="最高成本" clearable @keyup.enter.native="queryParams.pageNum = 1;getList()" />
+        <el-input v-model="queryParams.maxCost" placeholder="最高成本" clearable
+                  @keyup.enter.native="queryParams.pageNum = 1;getList()"/>
       </el-form-item>
       <el-form-item label="价格" prop="minValue">
-        <el-input v-model="queryParams.minValue" placeholder="最低价格" clearable @keyup.enter.native="queryParams.pageNum = 1;getList()" />
+        <el-input v-model="queryParams.minValue" placeholder="最低价格" clearable
+                  @keyup.enter.native="queryParams.pageNum = 1;getList()"/>
       </el-form-item>
       <el-form-item label="-" prop="maxValue">
-        <el-input v-model="queryParams.maxValue" placeholder="最高价格" clearable @keyup.enter.native="queryParams.pageNum = 1;getList()" />
+        <el-input v-model="queryParams.maxValue" placeholder="最高价格" clearable
+                  @keyup.enter.native="queryParams.pageNum = 1;getList()"/>
       </el-form-item>
       <el-form-item>
         <el-button type="primary" icon="el-icon-search" @click="queryParams.pageNum = 1;getList()">搜索</el-button>
@@ -77,26 +92,29 @@
     </el-form>
     <el-row :gutter="10" class="mb8">
       <el-col :span="1.5">
-        <el-button v-hasPermi="['business:goods:add']" type="primary" icon="el-icon-plus" size="mini" @click="$router.push({ name: 'GoodsAdd' })">添加商品</el-button>
+        <el-button v-hasPermi="['business:goods:add']" type="primary" icon="el-icon-plus" size="mini"
+                   @click="$router.push({ name: 'GoodsAdd' })">添加商品
+        </el-button>
         <!-- <el-button v-hasPermi="['business:goods:on']" type="primary" plain size="mini">上架</el-button> -->
         <!-- <el-button v-hasPermi="['business:goods:off']" type="primary" plain size="mini">下架</el-button> -->
         <!-- <el-button v-hasPermi="['business:goods:remove']" type="danger" plain size="mini">删除</el-button> -->
       </el-col>
-        <el-col :span="1.5">
-          <el-button
-            type="infor"
-            plain
-            icon="el-icon-download"
-            size="mini"
-            @click="handleOrderExport"
-            v-hasPermi="['business:goods:export']"
-          >导出商品</el-button>
+      <el-col :span="1.5">
+        <el-button
+          type="infor"
+          plain
+          icon="el-icon-download"
+          size="mini"
+          @click="handleOrderExport"
+          v-hasPermi="['business:goods:export']"
+        >导出商品
+        </el-button>
       </el-col>
       <right-toolbar :showSearch.sync="showSearch" @queryTable="getList"></right-toolbar>
     </el-row>
 
-    <el-table v-loading="loading" :data="tableData"  @sort-change="sortChannelId">
-      <el-table-column label="商品ID" prop="goodsId" width="60" />
+    <el-table v-loading="loading" :data="tableData" @sort-change="sortChannelId">
+      <el-table-column label="商品ID" prop="goodsId" width="60"/>
       <el-table-column label="商品图片" prop="picUrl" align="center">
         <template slot-scope="{row}">
           <div v-if="row.picUrl">
@@ -109,15 +127,15 @@
           <span v-else>-</span>
         </template>
       </el-table-column>
-      <el-table-column label="商品名称" prop="title" />
+      <el-table-column label="商品名称" prop="title"/>
       <el-table-column label="价格" prop="value" sortable="custom">
         <template slot-scope="{row}">
-          ¥{{$numberFormat(row.value)}}
+          ¥{{ $numberFormat(row.value) }}
         </template>
       </el-table-column>
       <el-table-column label="商品成本" prop="cost" sortable="custom" min-width="100px">
         <template slot-scope="{row}">
-          ¥{{$numberFormat(row.cost)}}
+          ¥{{ $numberFormat(row.cost) }}
         </template>
       </el-table-column>
       <el-table-column label="是否支持兑换" prop="exchangeShow" min-width="100px">
@@ -127,41 +145,115 @@
           <span v-if="row.exchangeShow == '2'">盲票商品</span>
         </template>
       </el-table-column>
-      <el-table-column label="盲豆兑换数量" prop="exchangePrice" sortable="custom" min-width="125" />
-      <el-table-column label="销量" prop="exchangedQty" sortable="custom" />
-      <el-table-column label="库存" prop="quantity" sortable="custom" />
+      <el-table-column label="商品类型" prop="type" min-width="100px">
+        <template slot-scope="{row}">
+          <span v-if="row.type == '1'">实物商品</span>
+          <span v-if="row.type == '2'">卡密商品</span>
+        </template>
+      </el-table-column>
+      <el-table-column label="盲豆兑换数量" prop="exchangePrice" sortable="custom" min-width="125"/>
+      <el-table-column label="销量" prop="exchangedQty" sortable="custom"/>
+      <el-table-column label="库存" prop="quantity" sortable="custom"/>
       <el-table-column label="状态" prop="status">
         <template slot-scope="{row}">
-          <el-tag :type="JSON.parse(row.status).value === 'on' ? 'success' : 'info'">{{ JSON.parse(row.status).desc }}</el-tag>
+          <el-tag :type="JSON.parse(row.status).value === 'on' ? 'success' : 'info'">{{
+              JSON.parse(row.status).desc
+            }}
+          </el-tag>
         </template>
       </el-table-column>
-      <el-table-column label="排序" prop="sortWeight"  sortable="custom" align="center" width="140px">
+      <el-table-column label="排序" prop="sortWeight" sortable="custom" align="center" width="140px">
         <template slot-scope="{row, $index}">
-            <el-input-number v-model="row.sortWeight" @change="handleSortChange($index,row.sortWeight)" controls-position="right" size="small"></el-input-number>
+          <el-input-number v-model="row.sortWeight" @change="handleSortChange($index,row.sortWeight)"
+                           controls-position="right" size="small"></el-input-number>
         </template>
       </el-table-column>
       <el-table-column fixed="right" align="center" label="操作" width="140">
         <template slot-scope="{row}">
           <!-- <el-button v-hasPermi="['business:goods:query']" type="text">查看</el-button> -->
-          <el-button v-hasPermi="['business:goods:edit']" type="text" @click="$router.push({ name: 'GoodsEdit', query: { id: row.goodsId } })">编辑</el-button>
-          <el-button v-if="JSON.parse(row.status).value === 'off' || JSON.parse(row.status).value === 'init'" v-hasPermi="['business:goods:on']" type="text" @click="setStatus(row, 'on')">上架</el-button>
-          <el-button v-if="JSON.parse(row.status).value === 'on'" v-hasPermi="['business:goods:off']" type="text" @click="setStatus(row, 'off')">下架</el-button>
-          <el-button v-if="JSON.parse(row.status).value === 'init'" v-hasPermi="['business:coupon:remove']" class="del" type="text" @click="del(row)">删除</el-button>
+          <el-button v-hasPermi="['business:goods:edit']" type="text" @click="handleCamilo(row.goodsId)" v-if="row.type === 2">
+            查看卡密
+          </el-button>
+          <el-button v-hasPermi="['business:goods:edit']" type="text" @click="handleImport(row.goodsId)"
+                     v-if="row.type === 2">添加卡密
+          </el-button>
+          <el-button v-hasPermi="['business:goods:edit']" type="text"
+                     @click="$router.push({ name: 'GoodsEdit', query: { id: row.goodsId } })">编辑
+          </el-button>
+          <el-button v-if="JSON.parse(row.status).value === 'off' || JSON.parse(row.status).value === 'init'"
+                     v-hasPermi="['business:goods:on']" type="text" @click="setStatus(row, 'on')">上架
+          </el-button>
+          <el-button v-if="JSON.parse(row.status).value === 'on'" v-hasPermi="['business:goods:off']" type="text"
+                     @click="setStatus(row, 'off')">下架
+          </el-button>
+          <el-button v-if="JSON.parse(row.status).value === 'init'" v-hasPermi="['business:coupon:remove']" class="del"
+                     type="text" @click="del(row)">删除
+          </el-button>
         </template>
       </el-table-column>
     </el-table>
-    <pagination :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize" @pagination="getList()" />
+    <pagination :total="total" :page.sync="queryParams.pageNum" :limit.sync="queryParams.pageSize"
+                @pagination="getList()"/>
+    <!--    查看卡密-->
+    <camilo v-if="camiloShow" @cancel="cancel" :camiloShow="camiloShow" :camiloGoodsId="camiloGoodsId"></camilo>
+    <!--    导入卡密-->
+    <el-dialog :title="upload.title" :visible.sync="upload.open" width="400px" append-to-body>
+      <a style="color: #1890FF;" @click="downloadExcel">下载Excel模版</a>
+      <div style="padding-top: 20px; text-align: center">
+        <el-upload
+          ref="upload"
+          :limit="1"
+          :data="reqData"
+          accept=".xlsx, .xls"
+          :headers="upload.headers"
+          :action="upload.url"
+          :disabled="upload.isUploading"
+          :on-progress="handleFileUploadProgress"
+          :on-success="handleFileSuccess"
+          :auto-upload="false"
+          :http-request="reqUploadFile"
+          :on-exceed="exceedMax"
+          drag
+        >
+          <i class="el-icon-upload"></i>
+          <div class="el-upload__text">将文件拖到此处,或<em>点击上传</em></div>
+          <div class="el-upload__tip text-center" slot="tip">
+            <span>仅允许导入 xls xlsx 格式文件。</span>
+          </div>
+        </el-upload>
+      </div>
+
+      <div slot="footer" class="dialog-footer">
+        <el-button @click="upload.open = false">取 消</el-button>
+        <el-button type="primary" @click="submitFileForm">确 定</el-button>
+      </div>
+    </el-dialog>
   </div>
 </template>
 <script>
-import { publicFileGetUrl } from "@/api/common"
-import { getGoodsList, delGoods, setGoodsStatus, setTableData, salesiteGoodsExport} from '@/api/business/goods'
-import { goodsCategoryListTree } from '@/api/business/category'
-import { goodsTagItems } from '@/api/business/tag'
-import { accMul } from '@/utils/util'
-import { getSupplierList } from '@/api/business/supplier'
+
+import Camilo from '@/components/Camilo'
+import {publicFileGetUrl} from "@/api/common"
+import {
+  getGoodsList,
+  delGoods,
+  setGoodsStatus,
+  setTableData,
+  salesiteGoodsExport,
+  setCamiloShip, cradDownload
+} from '@/api/business/goods'
+import {goodsCategoryListTree} from '@/api/business/category'
+import {goodsTagItems} from '@/api/business/tag'
+import {accMul} from '@/utils/util'
+import {getSupplierList} from '@/api/business/supplier'
+import {randomStr20} from '@/utils/util'
+import {getToken, getSign} from "@/utils/auth";
+
 export default {
   name: 'List',
+  components: {
+    Camilo
+  },
   data() {
     return {
       IMG_URL: publicFileGetUrl,
@@ -173,6 +265,17 @@ export default {
       goodsCategoryItemsList: [],
       goodsTagItemsList: [],
       SupplierList: [],
+      camiloShow: false,
+      // 用户导入参数
+      upload: {
+        open: false,// 是否显示弹出层(用户导入)
+        title: "",// 弹出层标题(用户导入)
+        isUploading: false,// 是否禁用上传
+        url: "",// 上传的地址
+        headers: {},//请求头
+      },
+      reqData: {},
+      camiloGoodsId: null,
     }
   },
   created() {
@@ -183,24 +286,24 @@ export default {
   },
   methods: {
     //获取供应商
-    getSupplierItems(){
-      getSupplierList('',{}).then(res => {
+    getSupplierItems() {
+      getSupplierList('', {}).then(res => {
         this.SupplierList = res && res.rows
       })
     },
 
     //切换排序
-    sortChannelId(row){
-      if (row){
-        let prop =  row.prop == 'commRate' ? ('t1.'+ row.prop) : row.prop;
+    sortChannelId(row) {
+      if (row) {
+        let prop = row.prop == 'commRate' ? ('t1.' + row.prop) : row.prop;
         this.queryParams.orderByColumn = prop
-        this.queryParams.isAsc = row.order=='ascending'?"asc":"desc";
+        this.queryParams.isAsc = row.order == 'ascending' ? "asc" : "desc";
         this.getList()
       }
     },
 
     //步进器修改
-    handleSortChange(index,sortWeight){
+    handleSortChange(index, sortWeight) {
       this.tableData[index].sortWeight = sortWeight
       let data = {
         goodsId: this.tableData[index].goodsId,
@@ -209,13 +312,96 @@ export default {
       setTableData(data)
     },
 
-    getGoodsCategoryItems(){
-      goodsCategoryListTree("",{}).then(res => {
+    //取消查看卡密
+    cancel() {
+      this.camiloShow = false
+    },
+    //下载excel模版表格
+    downloadExcel() {
+      cradDownload().then(response => {
+        this.download(response.msg);
+      })
+    },
+    //查看卡密
+    handleCamilo(id){
+      this.camiloGoodsId = id
+      this.camiloShow = true
+    },
+    //上传卡密按钮操作
+    handleImport(id) {
+      this.camiloGoodsId = id
+      this.upload.title = "添加卡密";
+      this.upload.open = true;
+      this.getHttpHeader(id)
+    },
+    // 文件上传中处理
+    handleFileUploadProgress(event, file, fileList) {
+      this.upload.isUploading = true;
+    },
+    // 文件上传成功处理
+    handleFileSuccess(response, file, fileList) {
+      this.upload.open = false;
+      this.upload.isUploading = false;
+      this.getList();
+    },
+    // 超出限制时的提示
+    exceedMax() {
+      this.$message({
+        message: '请移除已有文件后再进行上传',
+        type: 'warning'
+      })
+    },
+    // 提交上传文件
+    submitFileForm() {
+      this.$refs.upload.submit();
+    },
+    //请求头
+    getHttpHeader(id) {
+      let timestamp = parseInt(new Date().getTime()),
+        nonce = randomStr20();
+      var sign = getSign(this.reqData || {}, timestamp)
+      let url = process.env.VUE_APP_BASE_API + `/api/v1/mp/admin/goods/card/import/${id}` + '?sign=' + sign + '&nonce=' + nonce;
+      this.upload.url = url
+      var headers = {
+        "Authorization": "Bearer " + getToken(),
+        "x-zz-timestamp": timestamp
+      }
+      this.upload.headers = headers
+    },
+
+    // 自定义文件上传的实现
+    reqUploadFile(param) {
+      var data = this.reqData || {}
+      var params = {
+        file: param.file,
+        ...data
+      }
+      this.vloading = this.$loading({
+        lock: true,
+        text: "正在导出商品.....",
+        background: "rgba(0, 0, 0, 0.7)",
+      });
+      setCamiloShip(params, this.headers, this.camiloGoodsId).then(response => {
+        this.vloading.close();
+        this.upload.open = false;
+        this.upload.isUploading = false;
+        this.$refs.upload.clearFiles();
+        this.$message({
+          message: '导入成功',
+          type: 'success'
+        })
+      }).catch(() => {
+        this.vloading.close();
+      })
+    },
+
+    getGoodsCategoryItems() {
+      goodsCategoryListTree("", {}).then(res => {
         this.goodsCategoryItemsList = res && res.rows
       })
     },
 
-    getGoodsTagItems(){
+    getGoodsTagItems() {
       goodsTagItems({}).then(res => {
         this.goodsTagItemsList = res && res.data
       })
@@ -229,24 +415,25 @@ export default {
       // if (reset) {
       //   this.queryParams = { pageNum: 1, pageSize: 20, orderByColumn: '', isAsc: '', }
       // }
-      if(this.queryParams.categoryIdList){
+      if (this.queryParams.categoryIdList) {
         for (let i = 0; i < this.queryParams.categoryIdList.length; i++) {
-          if(this.queryParams.categoryIdList[i][1]){
+          if (this.queryParams.categoryIdList[i][1]) {
             this.queryParams.categoryIdList[i] = this.queryParams.categoryIdList[i][1]
           }
         }
       }
-      getGoodsList('pageNum='+this.queryParams.pageNum + '&pageSize='+this.queryParams.pageSize+'&orderByColumn='+ this.queryParams.orderByColumn +'&isAsc='+ this.queryParams.isAsc +'&', {
+      getGoodsList('pageNum=' + this.queryParams.pageNum + '&pageSize=' + this.queryParams.pageSize + '&orderByColumn=' + this.queryParams.orderByColumn + '&isAsc=' + this.queryParams.isAsc + '&', {
         title: this.queryParams.title,
         goodsId: this.queryParams.goodsId,
+        type: this.queryParams.type ? Number(this.queryParams.type) : this.queryParams.type,
         categoryIdList: this.queryParams.categoryIdList,
         tagId: this.queryParams.tagId,
         status: this.queryParams.status,
         exchangeShow: this.queryParams.exchangeShow, supplierId: this.queryParams.supplierId,
-        minCost: this.queryParams.minCost?accMul(this.queryParams.minCost, 100):this.queryParams.minCost,
-        maxCost: this.queryParams.maxCost?accMul(this.queryParams.maxCost, 100):this.queryParams.maxCost,
-        minValue: this.queryParams.minValue?accMul(this.queryParams.minValue, 100):this.queryParams.minValue,
-        maxValue: this.queryParams.maxValue?accMul(this.queryParams.maxValue, 100):this.queryParams.maxValue
+        minCost: this.queryParams.minCost ? accMul(this.queryParams.minCost, 100) : this.queryParams.minCost,
+        maxCost: this.queryParams.maxCost ? accMul(this.queryParams.maxCost, 100) : this.queryParams.maxCost,
+        minValue: this.queryParams.minValue ? accMul(this.queryParams.minValue, 100) : this.queryParams.minValue,
+        maxValue: this.queryParams.maxValue ? accMul(this.queryParams.maxValue, 100) : this.queryParams.maxValue
       }).then(res => {
         this.loading = false
         if (res.code === 0) {
@@ -261,7 +448,7 @@ export default {
 
     // 重置
     resetQuery() {
-      this.queryParams = { pageNum: 1, pageSize: 10, orderByColumn: '', isAsc: '',}
+      this.queryParams = {pageNum: 1, pageSize: 10, orderByColumn: '', isAsc: '',}
       this.getList();
     },
 

+ 8 - 0
src/views/order/deliver/index.vue

@@ -282,6 +282,7 @@
         :on-success="handleFileSuccess"
         :auto-upload="false"
         :http-request="reqUploadFile"
+        :on-exceed="exceedMax"
         drag
       >
         <i class="el-icon-upload"></i>
@@ -524,6 +525,13 @@ export default {
       this.upload.isUploading = false;
       this.getList();
     },
+    // 超出限制时的提示
+    exceedMax() {
+      this.$message({
+        message:  '请移除已有文件后再进行上传',
+        type: 'warning'
+      })
+    },
     // 提交上传文件
     submitFileForm() {
       this.$refs.upload.submit();