18f2f183b1b50f36e810dad2c8c7aebd69366bcb..6496b3f36d38f3196c4e41d0b9c329de646a2415
6 小时以前 peng
店铺优惠卷功能使用
6496b3 对比 | 目录
8 小时以前 zxl
店铺绑优惠卷
44f03c 对比 | 目录
1个文件已修改
2个文件已添加
916 ■■■■■ 已修改文件
manager/src/api/coupon-store.js 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
manager/src/api/promotion.js 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
manager/src/views/promotions/coupon/coupon_store.vue 882 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
manager/src/api/coupon-store.js
New file
@@ -0,0 +1,30 @@
import service from "../libs/axios";
export const addStoreCoupon = (params) =>{
  return service({
    url: "/lmk/storeCoupon",
    method: "POST",
    data: params
  })
}
export const getPage = (params) =>{
  return service({
    url: "/lmk/storeCoupon",
    method: "GET",
    params: params
  })
}
export const getPageByStoreCoupon = (params) =>{
  return service({
    url: "/lmk/storeCoupon/getPageByStoreCoupon",
    method: "GET",
    params: params
  })
}
export const changeStatus = (id) =>{
  return service({
    url:  `/lmk/storeCoupon/changeStatus/${id}`,
    method: "POST"
  })
}
manager/src/api/promotion.js
@@ -112,6 +112,10 @@
export const deletePlatformCoupon = ids => {
  return deleteRequest(`/promotion/coupon/${ids}`);
};
//  生成优惠卷
export const generateStoreCoupon = id => {
  return postRequest(`/lmk/storeCoupon/generateStoreCoupon/${id}`);
};
//  更新优惠券状态
export const updatePlatformCouponStatus = params => {
  return putRequest(`/promotion/coupon/status`, params);
manager/src/views/promotions/coupon/coupon_store.vue
New file
@@ -0,0 +1,882 @@
<template>
  <div class="coupon-management">
    <!-- 搜索区域 -->
    <Card class="filter-container">
      <div class="filter-header">
        <Icon type="ios-search" size="18" />
        <span class="filter-title">筛选搜索</span>
        <div class="filter-actions">
          <Button type="primary" @click="getList" size="small">查询搜索</Button>
          <Button @click="handleResetSearch" size="small" style="margin-left: 10px;">重置</Button>
        </div>
      </div>
      <div class="filter-content">
        <Form
          :model="listQuery"
          :label-width="90"
          class="search-form"
          inline
        >
          <FormItem label="店铺">
            <Select
              v-model="listQuery.storeId"
              placeholder="请选择"
              clearable
              style="width: 160px"
              filterable
            >
              <Option
                v-for="store in storeSelectList"
                :key="store.id"
                :label="store.label"
                :value="store.id"
              >
                {{ store.label }}
              </Option>
            </Select>
          </FormItem>
          <FormItem label="生成状态:">
            <Select
              v-model="listQuery.generateStatus"
              placeholder="全部状态"
              clearable
              style="width: 180px"
            >
              <Option value="NOT_GENERATE">没有生成</Option>
              <Option value="GENERATE">生成</Option>
            </Select>
          </FormItem>
          <FormItem label="启用状态:">
            <Select
              v-model="listQuery.status"
              placeholder="全部状态"
              clearable
              style="width: 180px"
            >
              <Option value="ENABLE">启用</Option>
              <Option value="DISABLED">禁用</Option>
            </Select>
          </FormItem>
        </Form>
      </div>
    </Card>
    <!-- 操作按钮区域 -->
    <div class="operation-container">
      <Button
        @click="handleAdd"
        type="primary"
        icon="md-add"
        class="add-btn"
      >添加优惠券</Button>
    </div>
    <!-- 表格区域 -->
    <Card class="table-container">
      <Table
        :loading="listLoading"
        border
        :columns="tableColumns"
        :data="list"
        ref="table"
        class="coupon-table"
      >
        <!-- 生成状态列 -->
        <template slot-scope="{ row }" slot="generateStatus">
          <Tag :color="getStatusColor(row.generateStatus)">
            {{ formatGenerateStatus(row.generateStatus) }}
          </Tag>
        </template>
        <!-- 启用状态列 -->
        <template slot-scope="{ row }" slot="status">
          <i-switch
            v-model="row.status"
            true-value="ENABLE"
            false-value="DISABLED"
            @on-change="(status) => handleStatusChange(row, status)"
          >
            <span slot="open">启用</span>
            <span slot="close">禁用</span>
          </i-switch>
        </template>
        <template slot-scope="{ row }" slot="action">
          <Button
            @click="generalCoupon(row)"
            type="primary"
            class="add-btn"
            v-if="row.generateStatus ==='NOT_GENERATE'"
          >生成优惠卷</Button>
          <Button
            @click="detail(row)"
            style="margin-left: 10px;"
            type="primary"
            class="add-btn"
            :disabled="row.generateStatus === 'NOT_GENERATE'"
          >查看</Button>
        </template>
      </Table>
    </Card>
    <!-- 分页区域 -->
    <div class="pagination-container">
      <Page
        :current="listQuery.pageNumber"
        :page-size="listQuery.pageSize"
        :total="total"
        :page-size-opts="[10, 20, 30, 50]"
        show-elevator
        show-sizer
        show-total
        @on-change="handleCurrentChange"
        @on-page-size-change="handleSizeChange"
      />
    </div>
    <Modal
      v-model="showGeneralQrCode"
      title="二维码"
      width="800"
      :mask-closable="false"
      :loading="codeLoading"
    >
      <vue-qr
        :text="QRCodeUrl"
        :margin="0"
        colorDark="#000"
        colorLight="#fff"
        :size="150"
      ></vue-qr>
      <div slot="footer">
        <Button type="text" @click="closeGeneralQrCode">关闭</Button>
        <!--          <Button type="primary" @click="generalQrCode">确认</Button>-->
      </div>
    </Modal>
    <Modal
      v-model="showCouponStore"
      width="1200"
      :mask-closable="false"
      @on-cancel="handleCancelCouponStore"
    >
      <Table
        :loading="couponStoreLoading"
        border
        :columns="couponStoreColumns"
        :data="couponStoreData"
        ref="table"
      >
        <template slot-scope="{ row }" slot="action">
          <Button
            @click="generalQrCode(row)"
            type="primary"
            class="add-btn"
            v-if="row.claimStatus === 'NOT_CLAIM'"
          >查看二维码</Button>
        </template>
      </Table>
      <Row type="flex" justify="center" class="mt_10">
        <Page
          :current="storeCouponSingleQuery.pageNumber"
          :total="couponStoreTotal"
          :page-size="storeCouponSingleQuery.pageSize"
          @on-change="couponStoreChangePage"
          @on-page-size-change="couponStoreChangePageSize"
          :page-size-opts="[10, 20, 50]"
          size="small"
          show-total
          show-elevator
          show-sizer
        ></Page>
      </Row>
    </Modal>
    <!-- 添加/编辑弹窗 -->
    <Modal
      v-model="dialogVisible"
      :title="dialogTitle"
      width="1200"
      :mask-closable="false"
      @on-cancel="handleCancel"
    >
      <Form
        ref="dataForm"
        :model="temp"
        :label-width="100"
        :rules="formRules"
      >
        <Form-item label="店铺" prop="storeId">
          <Select
            v-model="temp.storeId"
            placeholder="请选择"
            clearable
            style="width: 160px"
            filterable
            @on-change="handleStoreChange"
          >
            <Option
              v-for="store in storeSelectList"
              :key="store.id"
              :label="store.label"
              :value="store.id"
            >
              {{ store.label }}
            </Option>
          </Select>
        </Form-item>
        <FormItem label="已选优惠劵" prop="couponId"  style="margin-bottom: 20px">
          <Input :disabled="true" style="width: 30%;margin-bottom: 20px" v-model="showCoupon" placeholder="请点击选择表格内优惠劵"></Input>
        </FormItem>
        <Table
          :loading="couponLoading"
          border
          :columns="couponColumns"
          :data="couponData"
          ref="table"
          @on-current-change="handleRowClick"
          highlight-row
        ></Table>
        <Row type="flex" justify="center" class="mt_10">
          <Page
            :current="couponSearchForm.pageNumber"
            :total="couponTotal"
            :page-size="couponSearchForm.pageSize"
            @on-change="couponChangePage"
            @on-page-size-change="couponChangePageSize"
            :page-size-opts="[10, 20, 50]"
            size="small"
            show-total
            show-elevator
            show-sizer
          ></Page>
        </Row>
        <FormItem label="生成数量" prop="couponNum">
          <InputNumber
            v-model="temp.couponNum"
            :min="1"
            :max="99999"
            placeholder="请输入生成数量"
            style="width: 100%"
          ></InputNumber>
        </FormItem>
      </Form>
      <div slot="footer">
        <Button @click="dialogVisible = false">取消</Button>
        <Button type="primary" @click="handleSubmit" :loading="submitLoading">确定</Button>
      </div>
    </Modal>
  </div>
</template>
<script>
import vueQr from "vue-qr";
import {addStoreCoupon, getPage, getPageByStoreCoupon,changeStatus} from "../../../api/coupon-store";
import * as API_Order from "@/api/order";
import {promotionsScopeTypeRender, promotionsStatusRender} from "../../../utils/promotions";
import {getPlatformCouponList,generateStoreCoupon} from "../../../api/promotion";
export default {
  components:{
    "vue-qr": vueQr,
  },
  name: 'CouponManagement',
  data() {
    return {
      QRCodeUrl:"",
      showGeneralQrCode:false,
      codeLoading:false,
      codeUrl: this.QRcodeBaseUrl+ '/scanpage/couponStore',
      showCouponStore:false,
      couponStoreTotal:0,
      couponStoreData:[],
      couponStoreLoading:false,
      couponStoreColumns: [
        {
          title: "优惠券名称",
          key: "couponName",
          width: 200,
          align: "center",
          tooltip: true
        },
        {
          title: "优惠券编号",
          key: "couponNo",
          width: 200,
          align: "center",
          tooltip: true
        },
        {
          title: "领取状态",
          key: "claimStatus",
          width: 200,
          align: "center",
          tooltip: true,
          render: (h, params) => {
            const status = params.row.claimStatus;
            const color = status === 'CLAIM' ? 'success' : status === 'NOT_CLAIM' ? 'default' : 'warning';
            const text = status === 'CLAIM' ? '已领取' : status === 'NOT_CLAIM' ? '未领取' : '未知';
            return h('Tag', {
              props: {
                color: color
              }
            }, text);
          }
        },
        {
          title: "操作",
          slot: "action",
          align: "center",
          width: 200,
          fixed: "right"
        }
      ],
      couponSearchForm: {
        // 搜索框初始化对象
        pageNumber: 1, // 当前页数
        pageSize: 10, // 页面大小
        sort: "create_time", // 默认排序字段
        order: "desc", // 默认排序方式
        getType: "", // 默认排序方式
        promotionStatus:"START",
      },
      storeSelectList:[],
      showCoupon:'',
      selectedRowId:'',
      couponTotal:0,
      couponData:[],
      couponLoading:false,
      couponColumns: [
        // 表头
        {
          title: "优惠券名称",
          key: "couponName",
          width: 180,
          tooltip: true,
        },
        {
          title: "面额/折扣",
          key: "price",
          width: 150,
          render: (h, params) => {
            if (params.row.price) {
              return h("priceColorScheme", {props:{value:params.row.price,color:this.$mainColor}} );
            } else {
              return h("div", params.row.couponDiscount + "折");
            }
          },
        },
        {
          title: "获取方式",
          width: 120,
          key: "getType",
          render: (h, params) => {
            if (params.row.getType === "FREE") {
              return h("Tag", { props: { color: "red" } }, "免费获取");
            } else if (params.row.getType === "ACTIVITY") {
              return h("Tag", { props: { color: "volcano" } }, "活动获取");
            } else if (params.row.getType === "INSIDE") {
              return h("Tag", { props: { color: "lime" } }, "内购");
            } else if (params.row.getType === "IGAME") {
              return h("Tag", { props: { color: "lime" } }, "游戏人生");
            } else {
              return h("Tag", { props: { color: "purple" } }, "未知");
            }
          },
        },
        {
          title: "优惠券类型",
          key: "couponType",
          width: 150,
          render: (h, params) => {
            let text = "";
            if (params.row.couponType === "DISCOUNT") {
              return h("Tag", { props: { color: "blue" } }, "打折");
            } else if (params.row.couponType === "PRICE") {
              return h("Tag", { props: { color: "geekblue" } }, "减免现金");
            } else {
              return h("Tag", { props: { color: "purple" } }, "未知");
            }
          },
        },
        {
          title: "品类描述",
          key: "scopeType",
          width: 120,
          render: (h, params) => {
            return promotionsScopeTypeRender(h, params);
          },
        },
        {
          title: "活动时间",
          render: (h, params) => {
            if (
              params?.row?.getType === "ACTIVITY" &&
              params?.row?.rangeDayType === "DYNAMICTIME"
            ) {
              return h("div", "长期有效");
            } else if (params?.row?.startTime && params?.row?.endTime) {
              return h("div", {
                domProps: {
                  innerHTML:
                    params.row.startTime + "<br/>" + params.row.endTime,
                },
              });
            }
          },
        },
        {
          title: "状态",
          width: 100,
          key: "promotionStatus",
          align: "center",
          fixed: "right",
          render: (h, params) => {
            return promotionsStatusRender(h, params);
          },
        },
      ],
      list: [],
      total: 0,
      listLoading: false,
      submitLoading: false,
      storeCouponSingleQuery:{
        pageNumber: 1,
        pageSize: 10,
        refId:""
      },
      listQuery: {
        pageNumber: 1,
        pageSize: 10,
        storeId: "",
        generateStatus: "",
        status: ""
      },
      temp: {
        storeId: '',
        storeName: '',
        couponId: '',
        couponNum: 1,
        couponName: '',
      },
      dialogVisible: false,
      dialogStatus: '',
      dialogTitle: '',
      // 表单验证规则
      formRules: {
        storeId: [
          { required: true, message: '店铺ID不能为空', trigger: 'blur' }
        ],
        storeName: [
          { required: true, message: '店铺名称不能为空', trigger: 'blur' }
        ],
        couponId: [
          { required: true, message: '优惠券ID不能为空', trigger: 'blur' }
        ],
        couponName: [
          { required: true, message: '优惠券名称不能为空', trigger: 'blur' }
        ],
        couponNum: [
          { required: true, type: 'number', message: '生成数量不能为空', trigger: 'blur' }
        ],
      },
      // 表头配置
      tableColumns: [
        {
          type: 'selection',
          width: 60,
          align: 'center'
        },
        {
          title: '店铺名称',
          key: 'storeName',
          align: 'center',
          ellipsis: true,
          tooltip: true
        },
        {
          title: '优惠券名称',
          key: 'couponName',
          align: 'center',
          ellipsis: true,
          tooltip: true
        },
        {
          title: '生成数量',
          key: 'couponNum',
          width: 100,
          align: 'center'
        },
        {
          title: '已领取数量',
          key: 'couponClaimNum',
          width: 120,
          align: 'center'
        },
        {
          title: '生成状态',
          slot: 'generateStatus',
          width: 120,
          align: 'center'
        },
        {
          title: '启用状态',
          slot: 'status',
          width: 120,
          align: 'center'
        },
        {
          title: '操作',
          slot: 'action',
          width: 200,
          align: 'center'
        },
      ]
    }
  },
  methods: {
    closeGeneralQrCode(){
      this.showGeneralQrCode = false;
      this.QRCodeUrl = '';
    },
    generalQrCode(row){
      this.QRCodeUrl = '';
      this.showGeneralQrCode = true
      this.codeLoading = true;
      this.QRCodeUrl = this.codeUrl + "?id="+ row.id;
    },
    detail(row){
      console.log(row)
      this.showCouponStore = true;
      this.storeCouponSingleQuery.refId = row.id
      this.storeCouponSingleQuery.pageSize = 10
      this.storeCouponSingleQuery.pageNumber = 1
      this.getCouponStoreDataList();
    },
    generalCoupon(row){
      generateStoreCoupon(row.id).then(response => {
        this.getList();
      })
    },
    handleStoreChange(storeId) {
      if (storeId) {
        const selectedStore = this.storeSelectList.find(store => store.id === storeId);
        if (selectedStore) {
          this.temp.storeName = selectedStore.label;
        }
      } else {
        this.temp.storeName = '';
      }
      console.log('当前选择:', this.temp.storeId, this.temp.storeName);
    },
    couponChangePage(v) {
      // 改变页码
      this.couponSearchForm.pageNumber = v;
      this.getCouponDataList();
    },
    couponChangePageSize(v) {
      // 改变页数
      this.couponSearchForm.pageNumber = 1;
      this.couponSearchForm.pageSize = v;
      this.getCouponDataList();
    },
    couponStoreChangePage(v) {
      // 改变页码
      this.storeCouponSingleQuery.pageNumber = v;
      this.getCouponStoreDataList();
    },
    couponStoreChangePageSize(v) {
      // 改变页数
      this.storeCouponSingleQuery.pageNumber = 1;
      this.storeCouponSingleQuery.pageSize = v;
      this.getCouponStoreDataList();
    },
    handleRowClick(currentRow ,oldCurrentRow){
      this.temp.couponId = currentRow.id;
      this.temp.couponName = currentRow.couponName;
      this.showCoupon = currentRow.couponName;
      console.log(this.temp.couponId)
    },
    getCouponStoreDataList(){
      this.couponStoreLoading = true;
      getPageByStoreCoupon(this.storeCouponSingleQuery).then((res) =>{
        this.couponStoreLoading =false;
        if (res.code === 200){
          this.couponStoreData = res.data;
          this.couponStoreTotal = res.total;
        }
      })
    },
    getCouponDataList() {
      // 获取数据
      this.couponLoading = true;
      getPlatformCouponList(this.couponSearchForm).then((res) => {
        this.couponLoading = false;
        if (res.success) {
          this.couponData = res.result.records;
          this.couponTotal = res.result.total;
        }
      });
      this.couponTotal = this.couponData.length;
      this.couponLoading = false;
    },
    getStoreSelect(){
      API_Order.getStoreSelect().then(res =>{
        if (res.result){
          this.storeSelectList = res.result;
        }
      })
    },
    // 获取列表数据
    getList() {
      this.listLoading = true;
      // 模拟API调用
      getPage(this.listQuery).then(res =>{
        this.listLoading = false;
        this.list = res.data;
        this.total = res.total;
      })
    },
    // 重置搜索条件
    handleResetSearch() {
      this.listQuery = {
        pageNumber: 1,
        pageSize: 10,
        storeName: "",
        couponName: "",
        generateStatus: "",
        status: ""
      };
      this.getList();
    },
    // 分页大小改变
    handleSizeChange(size) {
      this.listQuery.pageSize = size;
      this.listQuery.pageNumber = 1;
      this.getList();
    },
    // 当前页码改变
    handleCurrentChange(pageNumber) {
      this.listQuery.pageNumber = pageNumber;
      this.getList();
    },
    // 添加优惠券
    handleAdd() {
      this.dialogStatus = 'create';
      this.dialogTitle = '添加优惠券';
      this.dialogVisible = true;
      this.showCoupon="";
      this.temp = {
        storeId: '',
        storeName: '',
        couponId: '',
        couponNum: 1,
        couponName: '',
      };
      this.getCouponDataList();
      this.$nextTick(() => {
        this.$refs.dataForm.resetFields();
      });
    },
    // 状态改变
    handleStatusChange(row, status) {
      const action = status === 'ENABLE' ? '启用' : '禁用';
      changeStatus(row.id).then(response => {
        this.getList();
        this.$Message.success(`已${action}优惠券"${row.couponName}"`);
      })
      // 这里可以添加API调用
    },
    // 格式化生成状态
    formatGenerateStatus(status) {
      const statusMap = {
        'NOT_GENERATE': '没有生成',
        'GENERATE': '生成',
      };
      return statusMap[status] || '未知状态';
    },
    // 获取状态颜色
    getStatusColor(status) {
      const colorMap = {
        'GENERATE': 'success',
        'NOT_GENERATE': 'warning'
      };
      return colorMap[status] || 'default';
    },
    handleCancelCouponStore(){
      this.showCouponStore = false;
    },
    // 弹窗取消
    handleCancel() {
      this.dialogVisible = false;
    },
    // 提交表单
    handleSubmit() {
      this.$refs.dataForm.validate((valid) => {
        if (valid) {
          let form = {...this.temp};
          addStoreCoupon(form).then(res=>{
            if (res.code === 200 ){
              this.$Message.success(res.msg)
            }
            this.dialogVisible = false;
            this.getList();
          })
        }
      });
    }
  },
  mounted() {
    this.getStoreSelect();
    this.getList();
  }
}
</script>
<style scoped lang="less">
.coupon-management {
  padding: 16px;
  background: #f5f7f9;
  min-height: 100vh;
}
.filter-container {
  margin-bottom: 16px;
  .filter-header {
    display: flex;
    align-items: center;
    margin-bottom: 16px;
    .filter-title {
      margin-left: 8px;
      font-weight: 600;
      font-size: 16px;
    }
    .filter-actions {
      margin-left: auto;
    }
  }
  .filter-content {
    .search-form {
      /deep/ .ivu-form-item {
        margin-bottom: 16px;
        margin-right: 16px;
      }
    }
  }
}
.operation-container {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 16px;
  padding: 12px 16px;
  background: #fff;
  border-radius: 4px;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
  .operation-info {
    color: #999;
    font-size: 14px;
  }
}
.table-container {
  margin-bottom: 16px;
  .coupon-table {
    /deep/ .ivu-table-cell {
      padding: 8px 12px;
    }
    .action-btns {
      display: flex;
      justify-content: center;
      button {
        margin: 0 2px;
      }
    }
  }
}
.pagination-container {
  display: flex;
  justify-content: flex-end;
  background: #fff;
  padding: 12px 16px;
  border-radius: 4px;
  box-shadow: 0 1px 1px rgba(0, 0, 0, 0.1);
}
// 响应式调整
@media (max-width: 768px) {
  .coupon-management {
    padding: 8px;
  }
  .filter-content .search-form {
    /deep/ .ivu-form-item {
      width: 100%;
      margin-right: 0;
      .ivu-form-item-content {
        width: 100%;
        .ivu-input, .ivu-select {
          width: 100% !important;
        }
      }
    }
  }
  .operation-container {
    flex-direction: column;
    align-items: flex-start;
    .add-btn {
      margin-bottom: 8px;
    }
  }
  .action-btns {
    flex-direction: column;
    button {
      margin: 2px 0 !important;
      width: 100%;
    }
  }
}
</style>