# MatchChangeScorePopup

A popup component for modifying match scores, used by referees or administrators to adjust team scores with support for dual team score adjustment and both teams lose functionality.

# Features

  • 🎯 Score Adjustment - Support increasing/decreasing both team scores, range 0-999
  • πŸ‘₯ Dual Team Display - Clearly display two team information and current scores
  • βš–οΈ Both Teams Lose - One-click both teams lose functionality
  • 🎨 Custom Styles - Rich CSS variables for theme customization
  • πŸ”§ Slot Support - Support custom confirm button and both lose button slots
  • πŸ”’ Data Validation - Automatically limit score range, prevent abnormal input
  • ⚑ Lightweight & Efficient - Optimized code structure with excellent performance

# Use Cases

  • E-sports match score correction
  • Sports event score adjustment
  • Online game battle result modification
  • Match management system

# Import

import PressMatchChangeScorePopup from 'press-next/press-match-change-score-popup/press-match-change-score-popup';

# Code Demo

# Basic Usage

<template>
  <div class="demo-wrap">
    <h3>Basic Usage</h3>
    <PressButton @click="showBasicPopup = true">
      Show Basic Score Change Popup
    </PressButton>

    <PressMatchChangeScorePopup
      :show="showBasicPopup"
      :z-index="componentProps.zIndex"
      :left-team="componentProps.leftTeam"
      :right-team="componentProps.rightTeam"
      :initial-left-score="componentProps.initialLeftScore"
      :initial-right-score="componentProps.initialRightScore"
      :custom-class="componentProps.customClass"
      @close="onBasicClose"
      @confirm="onBasicConfirm"
      @both-lose="onBasicBothLose"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue';
import PressButton from 'press-ui/press-button/press-button.vue';
import PressMatchChangeScorePopup from 'press-next/press-match-change-score-popup/press-match-change-score-popup.vue';
import { getMockData } from './demo-data';

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

// PopupPlus display state
const showBasicPopup = ref(false);

// Basic usage event handlers
const onBasicConfirm = (leftScore, rightScore) => {
  console.log('Basic usage - Confirm score change:', { leftScore, rightScore });
  showBasicPopup.value = false;
};

const onBasicClose = () => {
  console.log('Basic usage - Close popup');
  showBasicPopup.value = false;
};

const onBasicBothLose = (leftScore, rightScore) => {
  console.log('Basic usage - Both teams lose:', { leftScore, rightScore });
  showBasicPopup.value = false;
};
</script>

# Custom Slots Usage

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

    <PressMatchChangeScorePopup
      :show="showSlotPopup"
      :z-index="componentProps.zIndex"
      :left-team="componentProps.leftTeam"
      :right-team="componentProps.rightTeam"
      :initial-left-score="componentProps.initialLeftScore"
      :initial-right-score="componentProps.initialRightScore"
      @close="onSlotClose"
      @confirm="onSlotConfirm"
      @both-lose="onSlotBothLose"
    >
      <!-- Custom confirm button -->
      <template #confirm-btn>
        <PressButton
          :class="`${prefix}__custom-confirm`"
          size="small"
          type="primary"
          @click="onSlotConfirm"
        >
          Custom Confirm
        </PressButton>
      </template>
      
      <!-- Custom both lose button -->
      <template #bothLoseBtn>
        <div :class="`${prefix}__custom-both-lose`" @click="onSlotBothLose">
          <div class="pmg-iconfont pmg-icon-warning" />
          <div :class="`${prefix}__custom-both-lose-text`">
            Custom Both Lose
          </div>
        </div>
      </template>
    </PressMatchChangeScorePopup>
  </div>
</template>

<script setup>
import { ref } from 'vue';
import PressButton from 'press-ui/press-button/press-button.vue';
import PressMatchChangeScorePopup from 'src/packages/press-match-change-score-popup/press-match-change-score-popup.vue';
import { getMockData } from 'src/packages/press-match-change-score-popup/demo-data';

const prefix = 'pm-change-score-popup';

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

// PopupPlus display state
const showSlotPopup = ref(false);

// Custom slots event handlers
const onSlotConfirm = (leftScore, rightScore) => {
  if (leftScore !== undefined && rightScore !== undefined) {
    console.log('Slots usage - Confirm score change:', { leftScore, rightScore });
  } else {
    console.log('Slots usage - Custom confirm button clicked');
  }
  showSlotPopup.value = false;
};

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

const onSlotBothLose = (leftScore, rightScore) => {
  if (leftScore !== undefined && rightScore !== undefined) {
    console.log('Slots usage - Both teams lose:', { leftScore, rightScore });
  } else {
    console.log('Slots usage - Custom both lose button clicked');
  }
  showSlotPopup.value = false;
};
</script>

<style scoped lang="scss">
.pm-change-score-popup {
  &__custom-confirm {
    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
    border: none;
  }

  &__custom-both-lose {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 8px 16px;
    background: rgba(255, 107, 107, 0.1);
    border-radius: 8px;
    cursor: pointer;
    transition: all 0.3s ease;

    &:hover {
      background: rgba(255, 107, 107, 0.2);
    }

    .pmg-iconfont {
      color: #ff6b6b;
      font-size: 16px;
    }
  }

  &__custom-both-lose-text {
    color: #ff6b6b;
    font-size: 14px;
    font-weight: 500;
  }
}
</style>

# Custom Styles

<template>
  <PressMatchChangeScorePopup
    :show="showPopup"
    :left-team="leftTeam"
    :right-team="rightTeam"
    :initial-left-score="1"
    :initial-right-score="2"
    custom-class="custom-score-popup"
    @close="handleClose"
    @confirm="handleConfirm"
  />
</template>

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

const showPopup = ref(true);
const leftTeam = ref({ name: 'Red Team', avatar: '' });
const rightTeam = ref({ name: 'Blue Team', avatar: '' });

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

const handleConfirm = (leftScore, rightScore) => {
  console.log('Score confirmed:', leftScore, rightScore);
};
</script>

<style>
.custom-score-popup {
  --csp-popup-bg: #f8f9fa;
  --csp-score-btn-bg: #007bff;
  --csp-team-info-name-color: #333;
}
</style>

# API

# Props

Attribute Description Type Default
custom-class Custom CSS class string ''
z-index PopupPlus z-index number 100
title PopupPlus title string 'ζ”Ήεˆ€ζ―”εˆ†'
show Whether to show popup boolean false
left-team Left team information TeamInfo { name: '战队名称A' }
right-team Right team information TeamInfo { name: '战队名称A' }
initial-left-score Initial left team score number 0
initial-right-score Initial right team score number 5
slot-confirm-btn Whether to use confirm btn slot boolean false
slot-both-lose-btn Whether to use both lose slot boolean false

# TeamInfo Data Structure

interface TeamInfo {
  name: string; // Team name
  avatar?: string; // Team avatar URL, optional
}

# Events

Event Description Parameters
close Triggered when popup is closed -
confirm Triggered when score is confirmed leftScore: number, rightScore: number
both-lose Triggered when both teams lose leftScore: number, rightScore: number

# Slots

Slot Name Description Parameters
confirm-btn Custom confirm button -
bothLoseBtn Custom both lose button -

Slot Usage Notes:

  • The confirm-btn slot replaces the default confirm button, you need to handle click events yourself
  • The bothLoseBtn slot replaces the default both lose button, you need to handle click events yourself
  • Slot content completely replaces the default buttons, please ensure proper interactive elements are provided

# Notes

# Usage Recommendations

  1. Score Range: Component automatically limits score range to 0-999, values outside range will be adjusted automatically
  2. Team Avatars: It is recommended to set default placeholder images for team avatars to avoid blank display when loading fails
  3. Popup Z-Index: When using in complex pages, pay attention to adjusting z-index to avoid layer conflicts
  4. Event Handling: Ensure proper handling of confirm and both-lose events to update business data
  5. Slot Usage: When using custom slots, slot content completely replaces default buttons, please ensure you handle click events yourself
  6. 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
  • Reasonably use computed to optimize data calculation
  • Avoid complex data processing inside the popup

# 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
--csp-head-confirm-width 1.4rem Confirm button width
--csp-head-confirm-height .56rem Confirm button height
--csp-content-team-min-height 1.12rem Team content min height
--csp-team-info-avatar-size .8rem Team avatar size
--csp-content-team-score-width 2rem Score area width
--csp-content-team-score-height .44rem Score area height
--csp-score-number-width 1.14rem Score number width
--csp-score-number-height .44rem Score number height
--csp-score-btn-size .44rem Score button size
--csp-score-btn-sub-width .272rem Decrease button width
--csp-score-btn-sub-height .04rem Decrease button height
--csp-warning-height .96rem Warning area height

# Spacing Properties (Margin/Padding/Gap)

Name Default Value Description
--csp-popup-head-padding-top $spacing-md PopupPlus head top padding
--csp-popup-head-margin-bottom $spacing-lg PopupPlus head bottom margin
--csp-content-team-padding .32rem 0 .16rem Team content padding
--csp-popup-content-margin-bottom .4rem PopupPlus content bottom margin
--csp-team-info-avatar-margin-right $spacing-sm Team avatar right margin
--csp-content-team-score-margin auto 0 Score area margin
--csp-content-team-score-gap 0 Score area gap
--csp-warning-padding-bottom .28rem Warning area bottom padding
--csp-warning-gap $spacing-xs Warning area gap

# Color Properties (Color/Background)

Name Default Value Description
--csp-popup-bg $color-surface-default PopupPlus background color
--csp-score-btn-bg $color-icon-dark Score button background
--csp-score-btn-disabled-bg $color-surface-secondary Disabled button background
--csp-score-btn-sub-bg $color-text-primary Decrease button background
--csp-score-number-bg rgba(247, 249, 250, 1) Score number background
--csp-score-btn-color $color-text-invert-light Score button text color
--csp-score-number-color $color-text-primary Score number color
--csp-team-info-name-color $color-text-primary Team name color
--csp-warning-icon-color $color-icon-dark Warning icon color
--csp-warning-text-color $color-text-primary Warning text color

# Font Properties (Font)

Name Default Value Description
--csp-head-confirm-font-size $font-size-sm Confirm button font size
--csp-team-info-name-font-size $font-size-lg Team name font size
--csp-score-number-font-size $font-size-md Score number font size
--csp-score-number-font-weight $font-weight-bold Score number font weight
--csp-score-btn-icon-font-size .38rem Score button icon size
--csp-warning-text-font-size .32rem Warning text font size
--csp-warning-icon-font-size $font-size-xl Warning icon font size

# Border Properties (Border/Border-Radius)

Name Default Value Description
--csp-content-team-border-bottom .02rem solid #eaeff2 Team content bottom border
--csp-team-info-avatar-border-radius $border-radius-circle Team avatar border radius
--csp-score-btn-sub-border-radius $border-radius-xs Decrease button border radius

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

Name Default Value Description
--csp-popup-position relative PopupPlus position
--csp-popup-head-position relative PopupPlus head position

# Layout Properties (Flex)

Name Default Value Description
--csp-team-info-flex 1 Team info flex value
--csp-score-btn-flex-shrink 0 Score button flex shrink

# Other Properties (Others)

Name Default Value Description
--csp-team-info-avatar-object-fit cover Team avatar object fit