Sfoglia il codice sorgente

满减相关代码优化

yjwang 20 ore fa
parent
commit
38c9f81b22

+ 23 - 0
src/api/hisStore/storePromotion.js

@@ -59,3 +59,26 @@ export function exportStorePromotion(query) {
     params: query
   })
 }
+
+export function getOrderPromotionDetail(orderId) {
+  return request({
+    url: '/store/storePromotion/order/' + orderId,
+    method: 'get'
+  })
+}
+
+export function getPromotionReportStats(query) {
+  return request({
+    url: '/store/storePromotion/report/stats',
+    method: 'get',
+    params: query
+  })
+}
+
+export function listPromotionReportOrders(query) {
+  return request({
+    url: '/store/storePromotion/report/orders',
+    method: 'get',
+    params: query
+  })
+}

+ 74 - 6
src/views/course/coursePlaySourceConfig/index.vue

@@ -174,6 +174,17 @@
           <el-tag prop="isMall" v-for="(item, index) in isMallOptions" v-if="scope.row.isMall==item.dictValue">{{item.dictLabel}}</el-tag>
         </template>
       </el-table-column>
+      <el-table-column
+        v-hasPermi="['course:playSourceConfig:courseMini']"
+        label="是否看课小程序"
+        align="center"
+        prop="isCourseMini"
+        width="120px"
+      >
+        <template slot-scope="scope">
+          <el-tag>{{ getIsCourseMiniLabel(scope.row.isCourseMini) }}</el-tag>
+        </template>
+      </el-table-column>
       <el-table-column label="状态" align="center" prop="status" width="100px">
         <template slot-scope="scope">
           <el-tag
@@ -279,6 +290,28 @@
             />
           </el-select>
         </el-form-item>
+        <el-form-item
+          v-hasPermi="['course:playSourceConfig:courseMini']"
+          label="是否看课小程序"
+          prop="isCourseMini"
+        >
+          <el-select
+            v-model="form.isCourseMini"
+            placeholder="请选择是否看课小程序"
+            style="width: 220px"
+            size="small"
+          >
+            <el-option
+              v-for="item in isCourseMiniOptions"
+              :key="item.dictValue"
+              :label="item.dictLabel"
+              :value="item.dictValue"
+            />
+          </el-select>
+          <div class="form-tip-text">
+            请认真选择:该标识主要用于区分 APP 用户与小程序用户,影响用户归属与业务统计。
+          </div>
+        </el-form-item>
         <el-form-item label="状态" prop="status">
           <el-select
             v-model="form.status"
@@ -398,6 +431,7 @@ import {list, get, update, add, del,getProtocolConfig,updateProtocolConfig} from
 import {updateIsTownOn} from "@/api/system/config";
 import { allList } from '@/api/company/company'
 import { resetForm } from '@/utils/common'
+import { checkPermi } from '@/utils/permission'
 import Treeselect from "@riophae/vue-treeselect";
 import {listDept} from "@/api/system/dept";
 import "@riophae/vue-treeselect/dist/vue-treeselect.css";
@@ -491,9 +525,19 @@ export default {
           dictValue: 0
         }
       ],
+      isCourseMiniOptions:[
+        {
+          dictLabel: "是",
+          dictValue: 1
+        },
+        {
+          dictLabel: "否",
+          dictValue: 0
+        }
+      ],
       title: null,
       open: false,
-      form: {isMall:0},
+      form: {isMall:0, isCourseMini: 1},
       rules: {
         name: [
           { required: true, message: "名称不能为空", trigger: "blur" }
@@ -697,7 +741,8 @@ export default {
     handleAdd() {
       this.reset()
       this.open = true
-        this.form.isMall = 0;
+      this.form.isMall = 0;
+      this.form.isCourseMini = 1;
       this.title = "添加小程序配置"
     },
     handleUpdate(row) {
@@ -706,7 +751,8 @@ export default {
       get(id).then(response => {
         this.form = {
           ...response.data,
-          type: response.data.type.toString()
+          type: response.data.type.toString(),
+          isCourseMini: response.data.isCourseMini == null ? 1 : response.data.isCourseMini
         }
         this.searchCompanies("");
         this.open = true
@@ -732,10 +778,20 @@ export default {
       this.multiple = !selection.length
     },
     submitForm() {
+      if (checkPermi(['course:playSourceConfig:courseMini'])) {
+        if (this.form.isCourseMini === null || this.form.isCourseMini === undefined || this.form.isCourseMini === '') {
+          this.msgError('请选择是否看课小程序')
+          return
+        }
+      }
       this.$refs["form"].validate(valid => {
         if (valid) {
+          const submitData = { ...this.form }
+          if (!checkPermi(['course:playSourceConfig:courseMini'])) {
+            delete submitData.isCourseMini
+          }
           if (this.form.id != null) {
-            update(this.form).then(response => {
+            update(submitData).then(response => {
               const {code, msg} = response
               if (code !== 200) {
                 this.msgError(msg)
@@ -746,7 +802,7 @@ export default {
               this.getList();
             });
           } else {
-            add(this.form).then(response => {
+            add(submitData).then(response => {
               const {code, msg} = response
               if (code !== 200) {
                 this.msgError(msg)
@@ -777,6 +833,7 @@ export default {
         msgDataFormat: 'JSON',
         type: '1',
         isMall: 0,
+        isCourseMini: 1,
         status: 0
 
 
@@ -792,6 +849,12 @@ export default {
       };
       return statusMap[status] || '未知';
     },
+    getIsCourseMiniLabel(value) {
+      if (value == null || value === 1) {
+        return '是'
+      }
+      return '否'
+    },
     // 处理隐私协议配置
     async handlePrivacyConfig(row) {
       try {
@@ -891,5 +954,10 @@ export default {
 </script>
 
 <style scoped>
-
+.form-tip-text {
+  margin-top: 6px;
+  line-height: 1.5;
+  font-size: 12px;
+  color: #909399;
+}
 </style>

+ 74 - 0
src/views/hisStore/components/productAfterSalesOrder.vue

@@ -320,6 +320,61 @@
 
         </el-descriptions>
 
+        <div style="margin: 60px 0px 20px 0px">
+          <span class="font-small">费用信息</span>
+        </div>
+        <el-descriptions :column="4" border>
+          <el-descriptions-item label="商品合计">
+            <span v-if="order != null">
+              ¥{{ order.totalPrice.toFixed(2) }}
+            </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="应付金额">
+            <span v-if="order != null">
+              ¥{{ order.payPrice.toFixed(2) }}
+            </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="运费">
+            <span v-if="order != null">
+              ¥{{ order.payPostage.toFixed(2) }}
+            </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="优惠券">
+            <span v-if="order != null">
+              ¥{{ order.couponPrice.toFixed(2) }}
+            </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="活动名称" v-if="orderPromotion != null">
+            <span>{{ orderPromotion.activityTitle }}</span>
+          </el-descriptions-item>
+          <el-descriptions-item label="活动类型" v-if="orderPromotion != null">
+            <span>{{ orderPromotion.tierTypeLabel }}</span>
+          </el-descriptions-item>
+          <el-descriptions-item label="活动档位" v-if="orderPromotion != null">
+            <span>{{ orderPromotion.matchedTierDesc }}</span>
+          </el-descriptions-item>
+          <el-descriptions-item label="活动优惠" v-if="orderPromotion != null">
+            <span class="color-danger">
+              ¥{{ formatPromotionDiscount(orderPromotion.promotionDiscountAmount) }}
+            </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="积分抵扣">
+            <span v-if="order != null">
+              ¥{{ order.deductionPrice.toFixed(2) }}
+            </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="实付金额">
+            <span v-if="order != null">
+              ¥{{ order.payMoney.toFixed(2) }}
+            </span>
+          </el-descriptions-item>
+          <el-descriptions-item label="代收金额">
+            <span v-if="order != null">
+              ¥{{ order.payDelivery.toFixed(2) }}
+            </span>
+          </el-descriptions-item>
+        </el-descriptions>
+
         <div style="margin-top: 20px">
           <svg-icon icon-class="marker" style="color: #606266"></svg-icon>
           <span class="font-small">操作信息</span>
@@ -417,6 +472,7 @@
 
 <script>
 import {getStoreAfterSales,cancel,refund,audit1,audit2,updateStoreAfterSales,getExpress} from "@/api/hisStore/storeAfterSales";
+import { getOrderPromotionDetail } from "@/api/hisStore/storePromotion";
 
 import productOrder from "./productOrder";
 export default {
@@ -463,6 +519,7 @@ export default {
       items:[],
       store: null,
       logs:[],
+      orderPromotion: null,
       form:{
         refundAmount:0,
       },
@@ -489,6 +546,12 @@ export default {
     });
   },
   methods: {
+    formatPromotionDiscount(amount) {
+      if (amount == null || amount === '') {
+        return '0.00';
+      }
+      return Number(amount).toFixed(2);
+    },
     submitForm() {
       var id=this.afterSales.id;
       this.addForm.id = id;
@@ -595,6 +658,7 @@ export default {
       });
     },
     getStoreAfterSales(id){
+        this.orderPromotion = null;
         getStoreAfterSales(id).then(response => {
             this.afterSales = response.afterSales;
             this.logs = response.logs;
@@ -602,7 +666,17 @@ export default {
             this.user=response.user;
             this.order=response.order;
             this.store=response.store;
+            if (this.order && this.order.id) {
+              this.loadOrderPromotion(this.order.id);
+            }
         });
+     },
+     loadOrderPromotion(orderId) {
+       getOrderPromotionDetail(orderId).then(response => {
+         this.orderPromotion = response.data || null;
+       }).catch(() => {
+         this.orderPromotion = null;
+       });
      }
   }
 };

+ 31 - 0
src/views/hisStore/components/productOrder.vue

@@ -470,6 +470,20 @@
                 ¥{{order.couponPrice.toFixed(2)}}
               </span>
           </el-descriptions-item>
+          <el-descriptions-item label="活动名称" v-if="orderPromotion != null">
+              <span>{{ orderPromotion.activityTitle }}</span>
+          </el-descriptions-item>
+          <el-descriptions-item label="活动类型" v-if="orderPromotion != null">
+              <span>{{ orderPromotion.tierTypeLabel }}</span>
+          </el-descriptions-item>
+          <el-descriptions-item label="活动档位" v-if="orderPromotion != null">
+              <span>{{ orderPromotion.matchedTierDesc }}</span>
+          </el-descriptions-item>
+          <el-descriptions-item label="活动优惠" v-if="orderPromotion != null">
+              <span class="color-danger">
+                ¥{{ formatPromotionDiscount(orderPromotion.promotionDiscountAmount) }}
+              </span>
+          </el-descriptions-item>
           <el-descriptions-item label="积分抵扣"  >
               <span v-if="order!=null">
                 ¥{{order.deductionPrice.toFixed(2)}}
@@ -744,6 +758,7 @@ import {auditPayRemain,addTuiMoney,syncExpress,updateExpress,getEroOrder,refundO
  editTuiMoney,getExpress,finishOrder,listStoreOrder, getStoreOrder, delStoreOrder, addStoreOrder,
   updateStoreOrder, exportStoreOrder,updateDeliveryId, createErpOrder,updateErp,getStoreOrderAddress,
   getStoreOrderPhone,getCommentInfo,updateCommentInfo} from "@/api/hisStore/storeOrder";
+import { getOrderPromotionDetail } from "@/api/hisStore/storePromotion";
 import { getTcmScheduleList } from "@/api/company/schedule";
 export default {
   name: "order",
@@ -821,6 +836,7 @@ export default {
       erpOrder:null,
       auditLogs: [],
       storeScrm: null,
+      orderPromotion: null,
     };
   },
   created() {
@@ -848,6 +864,12 @@ export default {
     });
   },
   methods: {
+    formatPromotionDiscount(amount) {
+      if (amount == null || amount === '') {
+        return '0.00';
+      }
+      return Number(amount).toFixed(2);
+    },
     handleAddress(){
         const id = this.order.id;
         getStoreOrderAddress(id).then(response =>{
@@ -1091,6 +1113,7 @@ export default {
     getOrder(orderId){
         this.orderId=orderId;
         this.certificates = null;
+        this.orderPromotion = null;
         getStoreOrder(orderId).then(response => {
             this.order = response.order;
             this.storeScrm=response.storeScrm;
@@ -1106,8 +1129,16 @@ export default {
             this.payments=response.payments;
             this.tuiMoneyLogs=response.tuiMoneyLogs;
             this.auditLogs = response.auditLogs;
+            this.loadOrderPromotion(orderId);
         });
      },
+     loadOrderPromotion(orderId) {
+       getOrderPromotionDetail(orderId).then(response => {
+         this.orderPromotion = response.data || null;
+       }).catch(() => {
+         this.orderPromotion = null;
+       });
+     },
      //回复订单评论
      replyComment(){
       let _this = this;

+ 367 - 0
src/views/hisStore/storePromotion/PromotionReportDialog.vue

@@ -0,0 +1,367 @@
+<template>
+  <el-dialog
+    :title="dialogTitle"
+    :visible.sync="visible"
+    width="92%"
+    top="4vh"
+    append-to-body
+    :close-on-click-modal="false"
+    @close="handleClose"
+  >
+    <el-row :gutter="16" class="stats-row">
+      <el-col :span="6">
+        <el-card shadow="never" class="stats-card">
+          <div class="stats-label">参与人数</div>
+          <div class="stats-value">{{ stats.participantCount || 0 }}</div>
+        </el-card>
+      </el-col>
+      <el-col :span="6">
+        <el-card shadow="never" class="stats-card">
+          <div class="stats-label">订单量</div>
+          <div class="stats-value">{{ stats.orderCount || 0 }}</div>
+        </el-card>
+      </el-col>
+      <el-col :span="6">
+        <el-card shadow="never" class="stats-card">
+          <div class="stats-label">优惠金额(元)</div>
+          <div class="stats-value">{{ formatMoney(stats.discountAmount) }}</div>
+        </el-card>
+      </el-col>
+      <el-col :span="6">
+        <el-card shadow="never" class="stats-card">
+          <div class="stats-label">成交额(元)</div>
+          <div class="stats-value">{{ formatMoney(stats.transactionAmount) }}</div>
+        </el-card>
+      </el-col>
+    </el-row>
+
+    <el-form :model="queryParams" ref="queryForm" :inline="true" label-width="88px" class="mt16">
+      <el-form-item label="订单号" prop="orderCode">
+        <el-input v-model="queryParams.orderCode" placeholder="请输入订单号" clearable size="small" style="width: 180px" @keyup.enter.native="handleQuery"/>
+      </el-form-item>
+      <el-form-item label="所属公司" prop="companyId">
+        <el-select
+          v-model="queryParams.companyId"
+          placeholder="请选择公司"
+          clearable
+          filterable
+          size="small"
+          style="width: 180px"
+          @change="handleCompanyChange"
+        >
+          <el-option
+            v-for="item in companyOptions"
+            :key="item.companyId"
+            :label="item.companyName"
+            :value="item.companyId"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="所属销售" prop="companyUserId">
+        <el-select
+          v-model="queryParams.companyUserId"
+          placeholder="请先选择公司"
+          clearable
+          filterable
+          size="small"
+          style="width: 180px"
+          :disabled="!queryParams.companyId"
+          :loading="companyUserLoading"
+          @change="handleCompanyUserChange"
+        >
+          <el-option
+            v-for="item in companyUserOptions"
+            :key="item.userId"
+            :label="item.nickName"
+            :value="item.userId"
+          />
+        </el-select>
+      </el-form-item>
+      <el-form-item label="用户昵称" prop="nickname">
+        <el-input v-model="queryParams.nickname" placeholder="请输入用户昵称" clearable size="small" style="width: 160px" @keyup.enter.native="handleQuery"/>
+      </el-form-item>
+      <el-form-item label="订单来源" prop="orderSourceType">
+        <el-select v-model="queryParams.orderSourceType" placeholder="全部" clearable size="small" style="width: 140px">
+          <el-option v-for="item in orderSourceOptions" :key="item.value" :label="item.label" :value="item.value"/>
+        </el-select>
+      </el-form-item>
+      <el-form-item>
+        <el-button type="cyan" icon="el-icon-search" size="mini" @click="handleQuery">搜索</el-button>
+        <el-button icon="el-icon-refresh" size="mini" @click="resetQuery">重置</el-button>
+      </el-form-item>
+    </el-form>
+
+    <el-tabs v-model="activeStatus" type="card" @tab-click="handleStatusTab">
+      <el-tab-pane label="全部订单" name="all"/>
+      <el-tab-pane v-for="item in statusOptions" :key="item.dictValue" :label="item.dictLabel" :name="String(item.dictValue)"/>
+    </el-tabs>
+
+    <el-table v-loading="loading" :data="orderList" border height="420">
+      <el-table-column label="订单号" align="center" prop="orderCode" min-width="180" show-overflow-tooltip/>
+      <el-table-column label="店铺名称" align="center" prop="storeName" min-width="120" show-overflow-tooltip/>
+      <el-table-column label="商家ID" align="center" prop="merchantId" width="120"/>
+      <el-table-column label="店铺ID" align="center" prop="storeSeq" width="120"/>
+      <el-table-column label="所属公司" align="center" prop="companyName" min-width="120" show-overflow-tooltip/>
+      <el-table-column label="所属员工" align="center" prop="companyUserNickName" min-width="100" show-overflow-tooltip/>
+      <el-table-column label="用户昵称" align="center" prop="nickname" min-width="100" show-overflow-tooltip/>
+      <el-table-column label="收件人" align="center" prop="realName" width="100"/>
+      <el-table-column label="订单金额" align="center" prop="totalPrice" width="100">
+        <template slot-scope="scope">{{ formatMoney(scope.row.totalPrice) }}</template>
+      </el-table-column>
+      <el-table-column label="应付金额" align="center" prop="payPrice" width="100">
+        <template slot-scope="scope">{{ formatMoney(scope.row.payPrice) }}</template>
+      </el-table-column>
+      <el-table-column label="优惠金额" align="center" prop="promotionDiscountAmount" width="100">
+        <template slot-scope="scope">{{ formatMoney(scope.row.promotionDiscountAmount) }}</template>
+      </el-table-column>
+      <el-table-column label="订单来源" align="center" width="90">
+        <template slot-scope="scope">
+          <el-tag size="mini" :type="scope.row.orderSourceType === 1 ? 'success' : 'info'">
+            {{ scope.row.orderSourceType === 1 ? '销售订单' : '商城订单' }}
+          </el-tag>
+        </template>
+      </el-table-column>
+      <el-table-column label="订单状态" align="center" prop="status" width="90">
+        <template slot-scope="scope">
+          <el-tag size="mini">{{ getStatusLabel(scope.row.status) }}</el-tag>
+        </template>
+      </el-table-column>
+    </el-table>
+
+    <pagination
+      v-show="total > 0"
+      :total="total"
+      :page.sync="queryParams.pageNum"
+      :limit.sync="queryParams.pageSize"
+      @pagination="loadOrders"
+    />
+  </el-dialog>
+</template>
+
+<script>
+import { getPromotionReportStats, listPromotionReportOrders } from '@/api/hisStore/storePromotion'
+import { getCompanyList } from '@/api/company/company'
+import { getUserList } from '@/api/company/companyUser'
+
+export default {
+  name: 'PromotionReportDialog',
+  data() {
+    return {
+      visible: false,
+      loading: false,
+      activity: null,
+      stats: {
+        participantCount: 0,
+        orderCount: 0,
+        discountAmount: 0,
+        transactionAmount: 0
+      },
+      orderList: [],
+      total: 0,
+      activeStatus: 'all',
+      statusOptions: [],
+      companyOptions: [],
+      companyUserOptions: [],
+      companyUserLoading: false,
+      orderSourceOptions: [
+        { value: 1, label: '销售订单' },
+        { value: 2, label: '商城订单' }
+      ],
+      queryParams: {
+        pageNum: 1,
+        pageSize: 10,
+        activityId: null,
+        orderCode: null,
+        companyId: null,
+        companyUserId: null,
+        nickname: null,
+        status: null,
+        orderSourceType: null
+      }
+    }
+  },
+  computed: {
+    dialogTitle() {
+      if (!this.activity) {
+        return '活动报表统计'
+      }
+      return `活动报表统计 - ${this.activity.title || ''}`
+    }
+  },
+  methods: {
+    open(row) {
+      this.activity = row
+      this.visible = true
+      this.queryParams.activityId = row.id
+      this.resetQueryParams()
+      this.loadStatusOptions()
+      this.loadCompanyOptions()
+      this.loadData()
+    },
+    handleClose() {
+      this.activity = null
+      this.orderList = []
+      this.total = 0
+      this.activeStatus = 'all'
+    },
+    resetQueryParams() {
+      this.queryParams = {
+        pageNum: 1,
+        pageSize: 10,
+        activityId: this.activity ? this.activity.id : null,
+        orderCode: null,
+        companyId: null,
+        companyUserId: null,
+        nickname: null,
+        status: null,
+        orderSourceType: null
+      }
+      this.companyUserOptions = []
+      this.activeStatus = 'all'
+    },
+    loadCompanyOptions() {
+      if (this.companyOptions.length) {
+        return Promise.resolve(this.companyOptions)
+      }
+      return getCompanyList().then(res => {
+        this.companyOptions = this.normalizeCompanyOptions(res.data)
+        return this.companyOptions
+      }).catch(() => {
+        this.companyOptions = []
+        this.$message.error('加载公司列表失败')
+        return []
+      })
+    },
+    normalizeCompanyOptions(list) {
+      return (list || [])
+        .map(item => ({
+          companyId: item.companyId != null ? item.companyId : item.dictValue,
+          companyName: item.companyName || item.dictLabel
+        }))
+        .filter(item => item.companyId != null && item.companyName)
+    },
+    normalizeCompanyUserOptions(list) {
+      return (list || [])
+        .map(item => ({
+          userId: item.userId,
+          nickName: item.nickName || item.userName || item.phonenumber || ('员工' + item.userId)
+        }))
+        .filter(item => item.userId != null)
+    },
+    loadStatusOptions() {
+      if (this.statusOptions.length) {
+        return
+      }
+      this.getDicts('store_order_status').then(res => {
+        this.statusOptions = res.data || []
+      })
+    },
+    handleCompanyChange(companyId) {
+      this.queryParams.companyUserId = null
+      this.companyUserOptions = []
+      if (!companyId) {
+        this.handleQuery()
+        return
+      }
+      this.loadCompanyUserOptions(companyId)
+    },
+    handleCompanyUserChange() {
+      this.handleQuery()
+    },
+    loadCompanyUserOptions(companyId) {
+      this.companyUserLoading = true
+      return getUserList(companyId).then(res => {
+        this.companyUserOptions = this.normalizeCompanyUserOptions(res.data)
+        this.handleQuery()
+      }).catch(() => {
+        this.companyUserOptions = []
+        this.$message.error('加载销售列表失败')
+      }).finally(() => {
+        this.companyUserLoading = false
+      })
+    },
+    handleStatusTab() {
+      this.queryParams.status = this.activeStatus === 'all' ? null : Number(this.activeStatus)
+      this.queryParams.pageNum = 1
+      this.loadData()
+    },
+    handleQuery() {
+      this.queryParams.pageNum = 1
+      this.loadData()
+    },
+    resetQuery() {
+      this.resetQueryParams()
+      this.loadData()
+    },
+    loadData() {
+      this.loadStats()
+      this.loadOrders()
+    },
+    loadStats() {
+      getPromotionReportStats(this.buildQuery()).then(res => {
+        this.stats = res.data || {
+          participantCount: 0,
+          orderCount: 0,
+          discountAmount: 0,
+          transactionAmount: 0
+        }
+      })
+    },
+    loadOrders() {
+      this.loading = true
+      listPromotionReportOrders(this.buildQuery()).then(res => {
+        this.orderList = res.rows || []
+        this.total = res.total || 0
+        this.loading = false
+      }).catch(() => {
+        this.loading = false
+      })
+    },
+    buildQuery() {
+      const query = { ...this.queryParams }
+      if (query.orderSourceType === '' || query.orderSourceType === undefined) {
+        query.orderSourceType = null
+      }
+      if (query.companyId === '' || query.companyId === undefined) {
+        query.companyId = null
+      }
+      if (query.companyUserId === '' || query.companyUserId === undefined) {
+        query.companyUserId = null
+      }
+      return query
+    },
+    formatMoney(value) {
+      if (value == null || value === '') {
+        return '0.00'
+      }
+      return Number(value).toFixed(2)
+    },
+    getStatusLabel(status) {
+      const item = this.statusOptions.find(opt => String(opt.dictValue) === String(status))
+      return item ? item.dictLabel : status
+    }
+  }
+}
+</script>
+
+<style scoped>
+.stats-row {
+  margin-bottom: 8px;
+}
+.stats-card {
+  text-align: center;
+}
+.stats-label {
+  font-size: 13px;
+  color: #909399;
+  margin-bottom: 8px;
+}
+.stats-value {
+  font-size: 22px;
+  font-weight: 600;
+  color: #303133;
+}
+.mt16 {
+  margin-top: 16px;
+}
+</style>

+ 16 - 8
src/views/hisStore/storePromotion/index.vue

@@ -58,17 +58,18 @@
         </template>
       </el-table-column>
       <el-table-column label="适用范围" align="center" prop="scopeTypeLabel" width="100"/>
-      <el-table-column label="每人限次" align="center" width="80">
-        <template slot-scope="scope">{{ scope.row.limitPerUser === 0 ? '不限' : scope.row.limitPerUser + '次' }}</template>
-      </el-table-column>
+<!--      <el-table-column label="每人限次" align="center" width="80">-->
+<!--        <template slot-scope="scope">{{ scope.row.limitPerUser === 0 ? '不限' : scope.row.limitPerUser + '次' }}</template>-->
+<!--      </el-table-column>-->
       <el-table-column label="状态" align="center" width="90">
         <template slot-scope="scope">
           <el-tag size="mini" :type="displayStatusTag(scope.row.displayStatus)">{{ scope.row.displayStatusLabel }}</el-tag>
         </template>
       </el-table-column>
-      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="240" fixed="right">
+      <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="300" fixed="right">
         <template slot-scope="scope">
           <el-button size="mini" type="text" @click="handleDetail(scope.row)" v-hasPermi="['store:storePromotion:query']">详情</el-button>
+          <el-button size="mini" type="text" @click="handleReport(scope.row)" v-hasPermi="['store:storePromotion:query']">报表统计</el-button>
           <el-button v-if="canEdit(scope.row)" size="mini" type="text" icon="el-icon-edit" @click="handleUpdate(scope.row)" v-hasPermi="['store:storePromotion:edit']">编辑</el-button>
           <el-button v-if="canEnable(scope.row)" size="mini" type="text" @click="handleEnable(scope.row)" v-hasPermi="['store:storePromotion:enable']">启用</el-button>
           <el-button v-if="canDisable(scope.row)" size="mini" type="text" @click="handleDisable(scope.row)" v-hasPermi="['store:storePromotion:disable']">停用</el-button>
@@ -212,9 +213,9 @@
           <el-form-item label="可叠加优惠券">
             <el-switch v-model="form.isStackable" :active-value="1" :inactive-value="0"/>
           </el-form-item>
-          <el-form-item label="每人限次">
-            <el-input-number v-model="form.limitPerUser" :min="0" :precision="0"/> <span class="tip-text">0 表示不限</span>
-          </el-form-item>
+<!--          <el-form-item label="每人限次">-->
+<!--            <el-input-number v-model="form.limitPerUser" :min="0" :precision="0"/> <span class="tip-text">0 表示不限</span>-->
+<!--          </el-form-item>-->
           <el-form-item label="备注">
             <el-input v-model="form.remark" type="textarea" placeholder="备注"/>
           </el-form-item>
@@ -236,7 +237,7 @@
         <el-descriptions-item label="结束时间">{{ parseTime(detail.endTime) }}</el-descriptions-item>
         <el-descriptions-item label="阶梯类型">{{ detail.tierTypeLabel || (detail.tierType === 2 ? '折扣' : '金额') }}</el-descriptions-item>
         <el-descriptions-item label="适用范围">{{ detail.scopeTypeLabel }}</el-descriptions-item>
-        <el-descriptions-item label="每人限次">{{ detail.limitPerUser === 0 ? '不限' : detail.limitPerUser }}</el-descriptions-item>
+<!--        <el-descriptions-item label="每人限次">{{ detail.limitPerUser === 0 ? '不限' : detail.limitPerUser }}</el-descriptions-item>-->
         <el-descriptions-item label="上不封顶">{{ detail.tierType === 2 ? '-' : (detail.isCapped === 1 ? '是' : '否') }}</el-descriptions-item>
         <el-descriptions-item label="叠加优惠券">{{ detail.isStackable === 1 ? '是' : '否' }}</el-descriptions-item>
         <el-descriptions-item v-if="detail.remark" label="备注" :span="2">{{ detail.remark }}</el-descriptions-item>
@@ -283,10 +284,13 @@
         <div v-else class="detail-empty">暂无商品数据</div>
       </div>
     </el-dialog>
+
+    <promotion-report-dialog ref="promotionReportDialog"/>
   </div>
 </template>
 
 <script>
+import PromotionReportDialog from './PromotionReportDialog'
 import {
   listStorePromotion, getStorePromotion, addStorePromotion, updateStorePromotion,
   delStorePromotion, enableStorePromotion, disableStorePromotion, exportStorePromotion
@@ -296,6 +300,7 @@ import { listStoreProduct } from '@/api/hisStore/storeProduct'
 
 export default {
   name: 'StorePromotion',
+  components: { PromotionReportDialog },
   data() {
     return {
       loading: false,
@@ -607,6 +612,9 @@ export default {
         this.detailOpen = true
       })
     },
+    handleReport(row) {
+      this.$refs.promotionReportDialog.open(row)
+    },
     addTier() {
       if (this.form.tiers.length >= 10) {
         this.msgWarning('最多10档')