# MatchOperationPopup

A match operation popup component for displaying match information and providing operation options, supporting functions like match reset and score adjustment.

# Features

  • 🎮 Match Information Display - Clearly display match title, team information, game mode, etc.
  • ⚙️ Operation Management - Support various match operations like match reset and score adjustment
  • 🏷️ Status Display - Real-time display of match status information
  • 🎨 Custom Styles - Rich CSS variables for theme customization
  • 🔧 Slot Support - Support custom operation buttons
  • Lightweight & Efficient - Optimized code structure with excellent performance

# Use Cases

  • E-sports match management operations
  • Online game battle management
  • Sports event operation control
  • Match referee system

# Import

import PressMatchOperationPopup from 'press-next/press-match-operation-popup/press-match-operation-popup';

# Code Demo

# Basic Usage

<template>
  <PressMatchOperationPopup
    :show="showPopup"
    :title="title"
    :match-info="matchInfo"
    :operations="operations"
    @close="handleClose"
    @operation-click="handleOperationClick"
  />
</template>

<script setup>
import { ref } from 'vue';
import PressMatchOperationPopup from 'press-next/press-match-operation-popup/press-match-operation-popup.vue';
import { getMockData } from './demo-data';

// Use mock data
const componentProps = getMockData();

const showPopup = ref(false);
const title = ref('Match Operations');
const matchInfo = ref(componentProps.matchInfo);
const operations = ref(componentProps.operations);

// Event handlers
const handleClose = () => {
  showPopup.value = false;
};

const handleOperationClick = (operation) => {
  console.log('Operation clicked:', operation);
  // Handle specific operation logic
};
</script>

# Custom Match Information

<template>
  <PressMatchOperationPopup
    :show="true"
    :title="'Match Management'"
    :match-info="customMatchInfo"
    :operations="operations"
    @close="handleClose"
    @operation-click="handleOperationClick"
  />
</template>

<script setup>
import { ref } from 'vue';

const customMatchInfo = ref({
  id: 1,
  title: 'Finals BO5',
  gameMode: 'Competitive Mode',
  mapName: 'Training Ground',
  playerCount: 'Five Players',
  status: 'in-progress',
  statusText: 'In Progress',
  leftTeam: {
    id: 1,
    name: 'King Team',
    avatar: 'https://placehold.co/144x144'
  },
  rightTeam: {
    id: 2,
    name: 'Champion Team',
    avatar: 'https://placehold.co/144x144'
  }
});

const operations = ref([
  {
    id: 'pause',
    name: 'Pause Match',
    icon: 'pmg-icon-pause',
    action: 'pause'
  },
  {
    id: 'end',
    name: 'End Match',
    icon: 'pmg-icon-end',
    action: 'end'
  }
]);

const handleClose = () => {
  console.log('Close popup');
};

const handleOperationClick = (operation) => {
  console.log('Execute operation:', operation.action);
};
</script>

# Custom Operation Buttons

<template>
  <PressMatchOperationPopup
    :show="showPopup"
    :title="title"
    :match-info="matchInfo"
    :operations="customOperations"
    @close="handleClose"
    @operation-click="handleOperationClick"
  />
</template>

<script setup>
import { ref } from 'vue';

const customOperations = ref([
  {
    id: 'reset',
    name: 'Reset Match',
    icon: 'pmg-icon-reset',
    action: 'reset'
  },
  {
    id: 'change-score',
    name: 'Adjust Score',
    icon: 'pmg-icon-rejudge',
    action: 'change-score'
  },
  {
    id: 'export',
    name: 'Export Data',
    icon: 'pmg-icon-export',
    action: 'export'
  },
  {
    id: 'settings',
    name: 'Match Settings',
    icon: 'pmg-icon-settings',
    action: 'settings'
  }
]);

const handleOperationClick = (operation) => {
  switch (operation.action) {
    case 'reset':
      console.log('Reset match');
      break;
    case 'change-score':
      console.log('Adjust score');
      break;
    case 'export':
      console.log('Export data');
      break;
    case 'settings':
      console.log('Match settings');
      break;
  }
};
</script>

# Custom Styles

<template>
  <PressMatchOperationPopup
    :show="showPopup"
    :title="title"
    :match-info="matchInfo"
    :operations="operations"
    :custom-class="'custom-operation-popup'"
    @close="handleClose"
    @operation-click="handleOperationClick"
  />
</template>

<script setup>
import { ref } from 'vue';

// Component data...
</script>

<style>
.custom-operation-popup {
  --op-match-card-bg: #f8f9fa;
  --op-title-bg: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  --op-title-color: #ffffff;
  --op-operation-icon-color: #667eea;
  --op-operation-text-color: #333333;
}
</style>

# API

# Props

Attribute Description Type Default
custom-class Custom CSS class string ''
z-index PopupPlus z-index number 100
title PopupPlus title string 'Match Operations'
show Whether to show popup boolean false
match-info Match information MatchInfo {}
operations Operations list OperationItem[] []

# MatchInfo Data Structure

interface TeamInfo {
  id: string | number; // Team ID
  name: string; // Team name
  avatar?: string; // Team avatar URL
}

interface MatchInfo {
  id: string | number; // Match ID
  title: string; // Match title, e.g., "Round of 16 BO3"
  gameMode: string; // Game mode, e.g., "Classic (Third Person)"
  mapName: string; // Map name, e.g., "Resort Island"
  playerCount: string; // Player count, e.g., "Four Players"
  status: 'not-started' | 'in-progress' | 'finished'; // Match status
  statusText: string; // Status text, e.g., "Not Started"
  leftTeam: TeamInfo; // Left team information
  rightTeam: TeamInfo; // Right team information
}

# OperationItem Data Structure

interface OperationItem {
  id: string; // Operation ID
  name: string; // Operation name
  icon: string; // Operation icon class name
  action: string; // Operation identifier
}

# Slots

Name Description
title Custom match title
vs Custom VS area
operations Custom operation buttons

Slot Usage Notes:

  • The title slot replaces the default match title area, allowing custom title styles and content
  • The vs slot replaces the default VS area, allowing custom battle display effects
  • The operations slot replaces the default operation button list, you need to handle click events yourself
  • Slot content completely replaces the default content, please ensure proper interactive elements are provided

# Custom Slots Usage

<template>
  <div class="demo-wrap">
    <h3>Custom Slots Usage</h3>
    <PressButton @click="showSlotPopup = true">
      Show Custom Slots Popup
    </PressButton>

    <PressMatchOperationPopup
      :show="showSlotPopup"
      :match-info="matchInfo"
      :operations="operations"
      @close="onSlotClose"
      @operation-click="onSlotOperationClick"
    >
      <!-- Custom title -->
      <template #title>
        <div class="custom-title">
          <div class="custom-title-icon">
            <div class="pmg-iconfont pmg-icon-trophy" />
          </div>
          <div class="custom-title-text">
            {{ matchInfo.title }}
          </div>
          <div class="custom-title-badge">
            Final
          </div>
        </div>
      </template>

      <!-- Custom VS area -->
      <template #vs>
        <div class="custom-vs">
          <div class="custom-vs-icon">
            <div class="pmg-iconfont pmg-icon-vs" />
          </div>
          <div class="custom-vs-status">
            <div class="custom-vs-status-text">
              {{ matchInfo.statusText }}
            </div>
            <div class="custom-vs-time">
              Start at 15:30
            </div>
          </div>
        </div>
      </template>

      <!-- Custom operation buttons -->
      <template #operations>
        <div class="custom-operations">
          <div
            v-for="operation in operations"
            :key="operation.id"
            class="custom-operation-item"
            @click="onSlotOperationClick(operation)"
          >
            <div class="custom-operation-icon">
              <div :class="`pmg-iconfont ${operation.icon}`" />
            </div>
            <div class="custom-operation-content">
              <div class="custom-operation-name">
                {{ operation.name }}
              </div>
              <div class="custom-operation-desc">
                Click to execute {{ operation.name }} operation
              </div>
            </div>
            <div class="custom-operation-arrow">
              <div class="pmg-iconfont pmg-icon-arrow-right" />
            </div>
          </div>
        </div>
      </template>
    </PressMatchOperationPopup>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import PressButton from 'press-ui/press-button/press-button.vue';
import { getMockData } from './demo-data';

const componentProps = getMockData();
const showSlotPopup = ref(false);

// Custom slots event handling
const onSlotClose = () => {
  console.log('Slots usage - Close popup');
  showSlotPopup.value = false;
};

const onSlotOperationClick = (operation) => {
  console.log('Slots usage - Operation click:', operation);
  showSlotPopup.value = false;
};
</script>

<style scoped>
.custom-title {
  display: flex;
  align-items: center;
  padding: 16px 20px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  border-radius: 8px 8px 0 0;
}

.custom-title-icon {
  margin-right: 12px;
}

.custom-title-icon .pmg-iconfont {
  font-size: 20px;
  color: #ffd700;
}

.custom-title-text {
  flex: 1;
  font-size: 16px;
  font-weight: 600;
  color: #ffffff;
}

.custom-title-badge {
  padding: 4px 12px;
  background: rgba(255, 255, 255, 0.2);
  border-radius: 12px;
  font-size: 12px;
  color: #ffffff;
}

.custom-vs {
  display: flex;
  flex-direction: column;
  align-items: center;
  padding: 16px;
  background: linear-gradient(45deg, #ff6b6b, #ee5a24);
  border-radius: 50%;
  width: 80px;
  height: 80px;
  justify-content: center;
}

.custom-vs-icon .pmg-iconfont {
  font-size: 24px;
  color: #ffffff;
  font-weight: bold;
}

.custom-vs-status {
  text-align: center;
}

.custom-vs-status-text {
  font-size: 10px;
  color: #ffffff;
  font-weight: 600;
}

.custom-vs-time {
  font-size: 8px;
  color: rgba(255, 255, 255, 0.8);
}

.custom-operations {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 20px;
}

.custom-operation-item {
  display: flex;
  align-items: center;
  padding: 16px;
  background: #ffffff;
  border-radius: 12px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
  cursor: pointer;
  transition: all 0.3s ease;
}

.custom-operation-item:hover {
  transform: translateY(-2px);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}

.custom-operation-icon {
  width: 40px;
  height: 40px;
  border-radius: 8px;
  background: linear-gradient(135deg, #1890ff, #096dd9);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-right: 16px;
}

.custom-operation-icon .pmg-iconfont {
  font-size: 18px;
  color: #ffffff;
}

.custom-operation-content {
  flex: 1;
}

.custom-operation-name {
  font-size: 16px;
  font-weight: 600;
  color: #333333;
  margin-bottom: 4px;
}

.custom-operation-desc {
  font-size: 12px;
  color: #999999;
}

.custom-operation-arrow .pmg-iconfont {
  font-size: 14px;
  color: #cccccc;
}
</style>

# Events

Event Description Parameters
close Triggered when popup is closed -
operation-click Triggered when operation button clicked operation: OperationItem

# Notes

# Usage Recommendations

  1. Team Avatars: It is recommended to set default placeholder images for team avatars to avoid blank display when loading fails
  2. Operation Icons: Ensure operation icon class names are defined in the project, recommend using a unified icon library
  3. Match Status: Dynamically update statusText and status fields according to actual match status
  4. Operation Permissions: In actual use, control available operation options based on user permissions
  5. Responsive Adaptation: On small screen devices, it's recommended to appropriately adjust related size variables

# Performance Optimization

  • Use v-show to control popup display, avoid frequent creation and destruction
  • Recommend using virtual scrolling for large operation lists
  • Avatar images are recommended to use CDN acceleration

# Compatibility

  • Support Vue 3.0+
  • Compatible with modern browsers (Chrome 60+, Firefox 60+, Safari 12+)
  • Support WeChat Mini Program, Alipay Mini Program and other platforms

# Theme Customization

# CSS Variables

The component provides the following CSS variables, which can be used to customize styles. For usage, please refer to ConfigProvider component.

# Size Properties (Width/Height)

Name Default Value Description
--op-match-card-height 3.62rem Match card height
--op-title-texture-width 100% Title texture width
--op-title-texture-height .065rem Title texture height
--op-content-height 100% Content area height
--op-teams-width 100% Teams area width
--op-team-max-width 1.68rem Single team max width
--op-team-name-width 100% Team name width
--op-team-avatar-size 1.44rem Team avatar size
--op-vs-width 1.72rem VS area width
--op-operation-item-width .8rem Operation item width
--op-operation-item-height .76rem Operation item height
--op-operation-icon-size .4rem Operation icon size

# Spacing Properties (Margin/Padding/Gap)

Name Default Value Description
--op-title-padding .06rem .48rem Title padding
--op-content-padding .8rem $spacing-lg $spacing-lg Content area padding
--op-status-padding .03rem .16rem Status label padding
--op-team-avatar-margin-bottom $spacing-sm Team avatar bottom margin
--op-teams-gap $spacing-lg Teams gap
--op-vs-gap $spacing-sm VS area gap
--op-operations-margin-top $spacing-md Operations area top margin
--op-operations-gap 1.6rem Operation items gap
--op-operation-icon-margin-bottom .06rem Operation icon bottom margin

# Color Properties (Color/Background)

Name Default Value Description
--op-match-card-bg $color-surface-default Match card background
--op-title-bg #d9e2ff Title background
--op-title-color $color-text-primary Title text color
--op-team-name-color $color-text-primary Team name color
--op-vs-color $color-text-primary VS text color
--op-status-bg #eceff2 Status label background
--op-status-color $color-text-secondary Status text color
--op-game-info-color #a3abb4 Game info color
--op-operation-icon-color #000915 Operation icon color
--op-operation-text-color #212124 Operation text color

# Font Properties (Font)

Name Default Value Description
--op-title-font-size $font-size-md Title font size
--op-title-font-weight $font-weight-bold Title font weight
--op-team-name-font-size $font-size-sm Team name font size
--op-team-name-font-weight $font-weight-bold Team name font weight
--op-vs-font-size .8rem VS text size
--op-vs-font-weight $font-weight-bold VS text weight
--op-vs-line-height 1 VS text line height
--op-status-font-size $font-size-xs Status text size
--op-game-info-font-size $font-size-xs Game info font size
--op-operation-text-font-size $font-size-xs Operation text size

# Border Properties (Border/Border-Radius)

Name Default Value Description
--op-team-avatar-border .01rem solid $color-divider-light Team avatar border
--op-match-card-radius $border-radius-sm Match card border radius
--op-team-avatar-radius $border-radius-circle Team avatar border radius
--op-operation-icon-radius $border-radius-xs Operation icon border radius

# Shadow Properties (Box-Shadow)

Name Default Value Description
--op-match-card-shadow 0 .08rem .08rem 0 #ebeff2 Match card bottom shadow

# Position Properties (Position/Top/Left/Z-Index)

Name Default Value Description
--op-title-section-top 0 Title section top position
--op-title-section-left 50% Title section left position
--op-title-texture-top 0 Title texture top position
--op-title-texture-left 50% Title texture left position
--op-title-z-index 2 Title z-index

# Transform Properties (Transform)

Name Default Value Description
--op-title-section-transform translateX(-50%) Title section transform
--op-title-texture-transform translateX(-50%) Title texture transform
--op-operation-active-scale .95 Operation item active scale

# Transition Properties (Transition)

Name Default Value Description
--op-operation-transition transform .2s ease Operation item transition

# Layout Properties (Flex)

Name Default Value Description
--op-team-flex 1 Team flex property

# Other Properties (Others)

Name Default Value Description
--op-title-texture-content '' Title texture content
--op-title-clip-path polygon(0% 0%, 100% 0%, 95% 100%, 5% 100%) Title clip path