zxl
1 天以前 dee9014b7fe406a241d396737649f3c3f9a0df05
店铺绑定抽奖活动
2个文件已添加
874 ■■■■■ 已修改文件
manager/src/api/prize-store.js 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
manager/src/views/activity-prize/prize-store.vue 845 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
manager/src/api/prize-store.js
New file
@@ -0,0 +1,29 @@
import service from "../libs/axios";
export const getPage = (params) =>{
  return service({
    url: "/lmk/scan-prize/page",
    method: "GET",
    params: params
  })
}
export const add = (params) =>{
  return service({
    url: "/lmk/scan-prize",
    method: "POST",
    data: params
  })
}
export const changeStatus = (params) =>{
  return service({
    url: "/lmk/scan-prize/changeStatus/" +params,
    method: "POST",
  })
}
export const generateStorePrize = (params) =>{
  return service({
    url: "/lmk/scan-prize/generateStorePrize/" +params,
    method: "POST",
  })
}
manager/src/views/activity-prize/prize-store.vue
New file
@@ -0,0 +1,845 @@
<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="DISABLE">禁用</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="DISABLE"
            @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="generalStorePrize(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="showActivityPrize" placeholder="请点击选择表格内抽奖活动"></Input>
        </FormItem>
        <Table
          :loading="activityPrizeLoading"
          border
          :columns="activityPrizeColumns"
          :data="activityPrizeData"
          ref="table"
          @on-current-change="handleRowClick"
          highlight-row
        ></Table>
        <Row type="flex" justify="center" class="mt_10">
          <Page
            :current="activityPrizeSearchForm.pageNumber"
            :total="activityPrizeTotal"
            :page-size="activityPrizeSearchForm.pageSize"
            @on-change="activityPrizeChangePage"
            @on-page-size-change="activityPrizeChangePageSize"
            :page-size-opts="[10, 20, 50]"
            size="small"
            show-total
            show-elevator
            show-sizer
          ></Page>
        </Row>
        <FormItem label="生成数量" prop="couponNum">
          <InputNumber
            v-model="temp.generateNum"
            :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 { getPage,add,changeStatus,generateStorePrize} from "@/api/prize-store.js"
import * as API_Activity_Prize from "@/api/activity-prize.js"
import * as API_Order from "@/api/order";
import {promotionsScopeTypeRender, promotionsStatusRender} from "../../utils/promotions";
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"
        }
      ],
      activityPrizeSearchForm:{
        pageSize:10,
        pageNumber:1,
        activityName:'',
        endTime:'',
        beginTime:'',
        enableStatus:'ON',
        popup:true
      },
      storeSelectList:[],
      showActivityPrize:'',
      selectedRowId:'',
      activityPrizeTotal:0,
      activityPrizeData:[],
      activityPrizeLoading:false,
      activityPrizeColumns:[
        {
          title: '活动名称',
          key: 'activityName',
          minWidth: 100,
        },
        {
          title: '活动描述',
          key: 'activityDes',
          minWidth: 100,
        },
        {
          title: '开始时间',
          key: 'beginTime',
          minWidth: 100,
          render: (h, params) => {
            return h('div', [
              h('div', this.formatDate(params.row.beginTime)),
            ])
          }
        },
        {
          title: '结束时间',
          key: 'endTime',
          minWidth: 100,
          render: (h, params) => {
            return h('div', [
              h('div', this.formatDate(params.row.endTime)),
            ])
          }
        },
        {
          title: '每日最大抽奖上限',
          key: 'maxPrize',
          minWidth: 100,
        },
        {
          title: '初始化抽奖次数',
          key: 'prizeNum',
          minWidth: 100,
        },
        {
          title: '是否开启活动',
          key: 'enableStatus',
          minWidth: 100,
          render: (h, params) => {
            return h('Tag', {
              props: {
                color: params.row.enableStatus  === 'ON' ? 'green' : 'default'
              }
            }, params.row.enableStatus === 'ON' ? '开启' : '关闭')
          }
        },
      ],
      list: [],
      total: 0,
      listLoading: false,
      submitLoading: false,
      storeCouponSingleQuery:{
        pageNumber: 1,
        pageSize: 10,
        refId:""
      },
      listQuery: {
        pageNumber: 1,
        pageSize: 10,
        storeId: "",
        generateStatus: "",
        status: ""
      },
      temp: {
        storeId: '',
        storeName: '',
        prizeActivityId: '',
        generateNum: 1,
        prizeActivityName: '',
      },
      dialogVisible: false,
      dialogStatus: '',
      dialogTitle: '',
      // 表单验证规则
      formRules: {
        storeId: [
          { required: true, message: '店铺不能为空', trigger: 'blur' }
        ],
        storeName: [
          { required: true, message: '店铺名称不能为空', trigger: 'blur' }
        ],
        prizeActivityId: [
          { required: true, message: '抽奖活动Id不能为空', trigger: 'blur' }
        ],
        prizeActivityName: [
          { required: true, message: '抽奖活动名称不能为空', trigger: 'blur' }
        ],
        generateNum: [
          { 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: 'prizeActivityName',
          align: 'center',
          ellipsis: true,
          tooltip: true
        },
        {
          title: '生成数量',
          key: 'generateNum',
          width: 100,
          align: 'center'
        },
        {
          title: '已领取数量',
          key: 'claimNum',
          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();
    },
    generalStorePrize(row){
      generateStorePrize(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);
    },
    activityPrizeChangePage(v) {
      // 改变页码
      this.activityPrizeSearchForm.pageNumber = v;
      this.getActivityPrizeDataList();
    },
    activityPrizeChangePageSize(v) {
      // 改变页数
      this.activityPrizeSearchForm.pageNumber = 1;
      this.activityPrizeSearchForm.pageSize = v;
      this.getActivityPrizeDataList();
    },
    couponStoreChangePage(v) {
      // 改变页码
      this.storeCouponSingleQuery.pageNumber = v;
      this.getCouponStoreDataList();
    },
    couponStoreChangePageSize(v) {
      // 改变页数
      this.storeCouponSingleQuery.pageNumber = 1;
      this.storeCouponSingleQuery.pageSize = v;
      this.getCouponStoreDataList();
    },
    handleRowClick(currentRow ,oldCurrentRow){
      console.log(currentRow)
      this.temp.prizeActivityId = currentRow.id;
      this.temp.prizeActivityName = currentRow.activityName;
      this.showActivityPrize = currentRow.activityName;
      console.log(this.temp.couponId)
    },
    getCouponStoreDataList(){
      this.couponStoreLoading = true;
      // API_Activity_Prize(this.storeCouponSingleQuery).then((res) =>{
      //   this.couponStoreLoading =false;
      //   if (res.code === 200){
      //     this.couponStoreData = res.data;
      //     this.couponStoreTotal = res.total;
      //   }
      // })
    },
    getActivityPrizeDataList() {
      // 获取数据
      this.activityPrizeLoading = true;
      API_Activity_Prize.getPage(this.activityPrizeSearchForm).then((res) => {
        this.activityPrizeLoading = false;
        if (res.code === 200) {
          this.activityPrizeData = res.data;
          this.activityPrizeTotal = res.total;
        }
      });
      this.activityPrizeTotal = this.activityPrizeData.length;
      this.activityPrizeLoading = false;
    },
    getStoreSelect(){
      API_Order.getStoreSelect().then(res =>{
        if (res.result){
          this.storeSelectList = res.result;
        }
      })
    },
    // 获取列表数据
    getList() {
      this.listLoading = true;
      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.showActivityPrize="";
      this.temp = {
        storeId: '',
        storeName: '',
        couponId: '',
        couponNum: 1,
        couponName: '',
      };
      this.getActivityPrizeDataList();
      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.prizeActivityName}"`);
      })
      // 这里可以添加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};
          add(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>