visit-frequency-member-list-dialog.vue 7.49 KB
<template>
  <el-dialog
    :visible.sync="visibleSync"
    :title="`到店${visitCount}次的会员列表`"
    :width="'1200px'"
    append-to-body
    custom-class="visit-frequency-member-dialog"
    :close-on-click-modal="false"
    @closed="handleClosed"
  >
    <div v-loading="loading" class="member-list-wrapper">
      <NCC-table
        v-loading="loading"
        :data="memberList"
        :header-cell-style="{ background: '#f5f7fa', color: '#606266' }"
      >
        <!-- 会员编码 -->
        <el-table-column label="会员编码" width="150" align="center">
          <template slot-scope="scope">
            <div class="member-code-info">
              <i class="el-icon-postcard member-code-icon"></i>
              <span class="text-nowrap">{{ scope.row.MemberId || '无' }}</span>
            </div>
          </template>
        </el-table-column>

        <!-- 会员名称 -->
        <el-table-column label="会员名称" min-width="120" align="center">
          <template slot-scope="scope">
            <div class="member-name-info">
              <i class="el-icon-user-solid member-name-icon"></i>
              <span class="text-nowrap">{{ scope.row.MemberName || '无' }}</span>
            </div>
          </template>
        </el-table-column>

        <!-- 手机号 -->
        <el-table-column label="手机号" width="130" align="center">
          <template slot-scope="scope">
            <div class="phone-info">
              <i class="el-icon-phone phone-icon"></i>
              <span class="text-nowrap">{{ scope.row.Mobile || '无' }}</span>
            </div>
          </template>
        </el-table-column>

        <!-- 归属门店 -->
        <el-table-column label="归属门店" min-width="150" align="center">
          <template slot-scope="scope">
            <div class="store-info">
              <i class="el-icon-office-building store-icon"></i>
              <span class="text-nowrap">{{ scope.row.StoreName || '无' }}</span>
            </div>
          </template>
        </el-table-column>

        <!-- 到店次数 -->
        <el-table-column label="到店次数" width="100" align="center">
          <template slot-scope="scope">
            <el-tag type="info" size="small">{{ scope.row.VisitCount || 0 }}次</el-tag>
          </template>
        </el-table-column>

        <!-- 首次到店时间 -->
        <el-table-column label="首次到店时间" width="160" align="center">
          <template slot-scope="scope">
            <div class="time-info">
              <i class="el-icon-time time-icon"></i>
              <span class="text-nowrap">{{ formatDateTime(scope.row.FirstVisitTime) || '无' }}</span>
            </div>
          </template>
        </el-table-column>

        <!-- 最后到店时间 -->
        <el-table-column label="最后到店时间" width="160" align="center">
          <template slot-scope="scope">
            <div class="time-info">
              <i class="el-icon-time time-icon"></i>
              <span class="text-nowrap">{{ formatDateTime(scope.row.LastVisitTime) || '无' }}</span>
            </div>
          </template>
        </el-table-column>
      </NCC-table>

      <!-- 分页 -->
      <div class="pagination-wrapper" v-if="pagination.total > 0">
        <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="pagination.pageIndex"
          :page-sizes="[10, 20, 50, 100]"
          :page-size="pagination.pageSize"
          layout="total, sizes, prev, pager, next, jumper"
          :total="pagination.total"
        ></el-pagination>
      </div>
    </div>
  </el-dialog>
</template>

<script>
import request from '@/utils/request'
import dayjs from 'dayjs'

export default {
  name: 'VisitFrequencyMemberListDialog',
  props: {
    visible: { type: Boolean, default: false },
    visitCount: { type: Number, default: 0 },
    startTime: { type: [Date, String], default: null },
    endTime: { type: [Date, String], default: null },
    storeIds: { type: Array, default: () => [] }
  },
  data() {
    return {
      visibleSync: false,
      loading: false,
      memberList: [],
      pagination: {
        pageIndex: 1,
        pageSize: 20,
        total: 0
      }
    }
  },
  watch: {
    visible: {
      immediate: true,
      handler(v) {
        this.visibleSync = v
        if (v && this.visitCount > 0) {
          this.pagination.pageIndex = 1
          this.fetchData()
        }
      }
    },
    visitCount: {
      handler() {
        if (this.visibleSync && this.visitCount > 0) {
          this.pagination.pageIndex = 1
          this.fetchData()
        }
      }
    }
  },
  methods: {
    async fetchData() {
      if (!this.visitCount || this.visitCount <= 0) {
        this.$message.warning('到店次数不能为空')
        return
      }

      this.loading = true
      try {
        const res = await request({
          url: '/api/Extend/LqReport/get-visit-frequency-member-list',
          method: 'POST',
          data: {
            visitCount: this.visitCount,
            startTime: this.startTime ? dayjs(this.startTime).toDate() : null,
            endTime: this.endTime ? dayjs(this.endTime).toDate() : null,
            storeIds: this.storeIds || [],
            pageIndex: this.pagination.pageIndex,
            pageSize: this.pagination.pageSize
          }
        })

        if (res.code === 200 && res.data) {
          this.memberList = res.data.List || []
          this.pagination.total = res.data.Total || 0
        } else {
          this.$message.error(res.msg || '获取会员列表失败')
        }
      } catch (error) {
        console.error('获取会员列表失败:', error)
        this.$message.error('获取会员列表失败: ' + (error.message || '未知错误'))
      } finally {
        this.loading = false
      }
    },
    handleSizeChange(val) {
      this.pagination.pageSize = val
      this.pagination.pageIndex = 1
      this.fetchData()
    },
    handleCurrentChange(val) {
      this.pagination.pageIndex = val
      this.fetchData()
    },
    handleClosed() {
      this.memberList = []
      this.pagination = {
        pageIndex: 1,
        pageSize: 20,
        total: 0
      }
      this.$emit('update:visible', false)
    },
    formatDateTime(dateTime) {
      if (!dateTime) return ''
      return dayjs(dateTime).format('YYYY-MM-DD HH:mm:ss')
    }
  }
}
</script>

<style lang="scss" scoped>
      ::v-deep .el-dialog {
    border-radius: 14px;
  }
.visit-frequency-member-dialog {
  .el-dialog {
    border-radius: 12px;
    overflow: hidden;
  }

  .el-dialog__header {
    padding: 20px 24px;
    border-bottom: 1px solid #e4e7ed;
    background: #409EFF;
    color: #fff;

    .el-dialog__title {
      color: #fff;
      font-size: 18px;
      font-weight: 600;
    }

    .el-dialog__close {
      color: #fff;
      font-size: 20px;

      &:hover {
        color: rgba(255, 255, 255, 0.8);
      }
    }
  }

  .el-dialog__body {
    padding: 24px;
    background: #f5f7fa;
  }
}

.member-list-wrapper {
  background: #fff;
  border-radius: 8px;
  padding: 20px;
  min-height: 400px;

  .member-code-info,
  .member-name-info,
  .phone-info,
  .store-info,
  .time-info {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;

    i {
      color: #409EFF;
      font-size: 16px;
    }

    .text-nowrap {
      white-space: nowrap;
      overflow: hidden;
      text-overflow: ellipsis;
    }
  }

  .pagination-wrapper {
    margin-top: 20px;
    display: flex;
    justify-content: flex-end;
  }
}
</style>