# MatchPrizeSetSimple

A simplified prize setting component that provides basic prize type selection and quantity setting functions through dynamic form field configuration, suitable for simplified prize configuration scenarios.

# Import

import PressMatchPrizeSetSimple from 'press-next/press-match-prize-set-simple/press-match-prize-set-simple.vue';

# Usage

# Basic Usage

<template>
  <PressMatchPrizeSetSimple
    :form-fields="formFields"
    @field-select="handleFieldSelect"
    @field-change="handleFieldChange"
    @delete="handleDelete"
    @add="handleAdd"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import PressMatchPrizeSetSimple from 'press-next/press-match-prize-set-simple/press-match-prize-set-simple.vue';

const formFields = ref([
  {
    key: 'type',
    label: 'Prize Type',
    type: 'select',
    placeholder: 'Please select',
    defaultText: 'Please select',
  },
  {
    key: 'quantity',
    label: 'Quantity',
    type: 'stepper',
    stepperValue: 1,
    min: 1,
    max: 999,
    step: 1,
  },
]);

const handleFieldSelect = (field, index) => {
  console.log('Select field:', field.key);
};

const handleFieldChange = (field, index, value) => {
  console.log('Field value changed:', field.key, value);
};

const handleDelete = () => {
  console.log('Delete prize');
};

const handleAdd = () => {
  console.log('Add prize');
};
</script>

# Dynamic Form Field Configuration

The component supports dynamic form field configuration through formFields, including two types: selector and stepper:

<template>
  <PressMatchPrizeSetSimple
    :form-fields="formFields"
    @field-select="handleFieldSelect"
    @field-change="handleFieldChange"
  />
  
  <!-- ActionSheet Field Selector -->
  <PressActionSheet
    v-model:show="showFieldSheet"
    :actions="fieldActions"
    :title="currentFieldLabel"
    @close="onFieldSheetClose"
    @select="handleFieldValueSelect"
  />
</template>

<script setup lang="ts">
import { ref, computed } from 'vue';
import PressMatchPrizeSetSimple from 'press-next/press-match-prize-set-simple/press-match-prize-set-simple.vue';
import PressActionSheet from 'press-ui/press-action-sheet/press-action-sheet.vue';

// Configure form fields
const formFields = ref([
  {
    key: 'type',
    label: 'Prize Type',
    type: 'select',
    placeholder: 'Please select',
    defaultText: 'Please select',
  },
  {
    key: 'quantity',
    label: 'Quantity',
    type: 'stepper',
    stepperValue: 1,
    min: 1,
    max: 999,
    step: 1,
  },
  {
    key: 'level',
    label: 'Prize Level',
    type: 'select',
    placeholder: 'Please select',
    defaultText: 'Please select',
  },
]);

// ActionSheet related states
const showFieldSheet = ref(false);
const currentFieldKey = ref('');
const currentFieldLabel = ref('');

// Field selector options configuration
const fieldOptionsMap = {
  type: [
    { name: 'Physical Prize', value: 'Physical Prize' },
    { name: 'Virtual Prize', value: 'Virtual Prize' },
    { name: 'Cash Reward', value: 'Cash Reward' },
    { name: 'Coupon', value: 'Coupon' },
  ],
  level: [
    { name: 'First Prize', value: 'First Prize' },
    { name: 'Second Prize', value: 'Second Prize' },
    { name: 'Third Prize', value: 'Third Prize' },
    { name: 'Participation Prize', value: 'Participation Prize' },
  ],
};

// Compute current field options list
const fieldActions = computed(() => fieldOptionsMap[currentFieldKey.value] || []);

// Handle field selection
const handleFieldSelect = (field, index) => {
  console.log('Select field:', field.key);
  currentFieldKey.value = field.key;
  currentFieldLabel.value = `Select ${field.label}`;
  
  if (fieldOptionsMap[field.key]) {
    showFieldSheet.value = true;
  }
};

// Field value selection callback (handle echo)
const handleFieldValueSelect = (action) => {
  const fieldIndex = formFields.value.findIndex(f => f.key === currentFieldKey.value);
  if (fieldIndex !== -1) {
    formFields.value[fieldIndex].selectedValue = action.value;
    console.log(`${currentFieldLabel.value}: ${action.value}`);
  }
  showFieldSheet.value = false;
};

// Close selector
const onFieldSheetClose = () => {
  showFieldSheet.value = false;
};

// Handle field value change (stepper)
const handleFieldChange = (field, index, value) => {
  console.log('Field value changed:', field.key, value);
  if (field.type === 'stepper') {
    formFields.value[index].stepperValue = value;
  }
};
</script>

# Custom Field Types

The component supports two field types: select (selector) and stepper (stepper):

<template>
  <PressMatchPrizeSetSimple
    :form-fields="customFields"
    @field-select="handleFieldSelect"
    @field-change="handleFieldChange"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import PressMatchPrizeSetSimple from 'press-next/press-match-prize-set-simple/press-match-prize-set-simple.vue';

const customFields = ref([
  // Selector type field
  {
    key: 'category',
    label: 'Prize Category',
    type: 'select',
    selectedValue: '', // Selected value, will auto-echo
    defaultText: 'Please select category',
  },
  // Stepper type field
  {
    key: 'stock',
    label: 'Stock Quantity',
    type: 'stepper',
    stepperValue: 10,
    min: 0,
    max: 9999,
    step: 5,
  },
]);

const handleFieldSelect = (field, index) => {
  // Handle selector click
  if (field.key === 'category') {
    // Show category selector
  }
};

const handleFieldChange = (field, index, value) => {
  // Handle stepper value change
  if (field.key === 'stock') {
    console.log('Stock updated to:', value);
  }
};
</script>

# API

# Props

| Attribute | Description | Type | Default | |-----------|-------------|------|---------|| | formFields | Form field configuration | FormFieldConfig[] | [] |

# FormFieldConfig Interface

interface FormFieldConfig {
  key: string;                    // Unique field identifier
  label: string;                  // Field label text
  type: 'select' | 'stepper';     // Field type
  placeholder?: string;           // Placeholder text
  selectedValue?: string;         // Selected value (for echo)
  defaultText?: string;           // Default display text
  stepperValue?: number;          // Stepper current value
  min?: number;                   // Stepper minimum value
  max?: number;                   // Stepper maximum value
  step?: number;                  // Stepper step value
}

# Events

Event Description Parameters
field-select Triggered when selector field is clicked (field: FormFieldConfig, index: number)
field-change Triggered when field value changes (stepper) (field: FormFieldConfig, index: number, value: number)
delete Triggered when delete is clicked -
add Triggered when add prize is clicked -

# Features

# Core Functions

  • Dynamic Form Configuration: Flexibly configure form fields through formFields
  • Dual Field Type Support: Supports selector (select) and stepper (stepper)
  • Auto Echo Mechanism: Selector selected values auto-echo
  • Delete Prize Function: Supports deleting current prize configuration
  • Add Prize Function: Supports adding new prize configuration

# Field Type Description

# 1. Selector Field (select)

  • Clicking triggers field-select event
  • Supports external ActionSheet selection
  • Echo implemented through selectedValue
  • Display priority: selectedValue > defaultText > placeholder

# 2. Stepper Field (stepper)

  • Supports numeric increment/decrement operations
  • Configurable min, max, and step values
  • Triggers field-change event when value changes
  • Suitable for quantity, quota, and other numeric configurations

# Simplified Design

  • 🎯 Configuration Driven: Define forms through configuration without modifying component code
  • 🎯 Flexible Extension: Freely combine different types of fields
  • 🎯 Quick Integration: Simple Props and event design
  • 🎯 Complementary Functions: Complements full-featured component

# Use Cases

  • Simplified competition prize setting
  • Quick prize configuration process
  • Mobile prize management
  • Lightweight prize system
  • Dynamic form scenarios

# Theming

# CSS Variables

The component provides the following CSS variables, which can be used to customize styles.

# Spacing System

Name Default Value Description
--pmpss-delete-mr $spacing-sm Delete button right margin
--pmpss-form-gap $spacing-lg Form item gap
--pmpss-add-mt $spacing-lg Add button top margin
--pmpss-add-gap $spacing-sm Add button internal gap
--pmpss-content-padding-tb $spacing-md Content area vertical padding
--pmpss-content-padding-lr $spacing-lg Content area horizontal padding

# Size System

Name Default Value Description
--pmpss-delete-icon-size .4rem Delete icon size
--pmpss-form-item-height .9rem Form item height
--pmpss-form-label-width 1.42rem Form label width
--pmpss-ctrls-icon-size .4rem Control button icon size

# Color System

Name Default Value Description
--pmpss-content-bg linear-gradient(...) Content area background gradient
--pmpss-content-border-color $color-surface-brand-light2 Content area border color
--pmpss-primary-text-color $color-text-primary Primary text color
--pmpss-add-text-color $color-text-primary Add button text color
--pmpss-delete-text-color $color-text-primary Delete button text color
--pmpss-label-text-color $color-text-primary Label text color
--pmpss-cell-border-color $color-divider-light Cell border color
--pmpss-ctrls-text-color $color-text-invert-default Control button text color
--pmpss-ctrls-icon-color $color-text-primary Control button icon color
--pmpss-stepper-input-bg rgba(#eceff2, .4) Stepper input background

# Font System

Name Default Value Description
--pmpss-icon-font-size .4rem IconPlus font size
--pmpss-label-font-size $font-size-md Label font size
--pmpss-add-font-size $font-size-md Add button font size
--pmpss-add-font-weight $font-weight-bold Add button font weight
--pmpss-ctrls-text-font-size $font-size-md Control button font size

# Border Radius System

Name Default Value Description
--pmpss-content-border-radius $border-radius-xs Content area border radius

# Custom Style Example

<template>
  <PressMatchPrizeSetSimple
    :form-fields="formFields"
    class="custom-prize-set"
  />
</template>

<script setup lang="ts">
import { ref } from 'vue';
import PressMatchPrizeSetSimple from 'press-next/press-match-prize-set-simple/press-match-prize-set-simple.vue';

const formFields = ref([
  {
    key: 'quantity',
    label: 'Quantity',
    type: 'stepper',
    stepperValue: 1,
  },
]);
</script>

<style scoped lang="scss">
.custom-prize-set {
  --pmpss-content-bg: linear-gradient(135deg, #f0f8ff 0%, #e6f3ff 100%);
  --pmpss-primary-text-color: #1890ff;
  --pmpss-content-border-color: rgba(24, 144, 255, .2);
}
</style>

# Notes

  1. Component Dependencies:

    • Internally uses the PressStepper component from press-ui
    • Ensure that the press-ui dependency is correctly installed
  2. Form Field Configuration:

    • formFields is required and must contain at least one field configuration
    • Each field's key must be unique
    • type only supports 'select' and 'stepper' types
    • Selector fields should configure defaultText as prompt text when not selected
  3. Event Handling:

    • field-select event is only triggered when type: 'select' field is clicked
    • field-change event is only triggered when type: 'stepper' field value changes
    • Selector needs to work with external components (such as ActionSheet) to implement selection function
    • add and delete events need to implement specific logic in parent component
  4. Echo Mechanism:

    • Selector field implements echo by updating selectedValue
    • Stepper field implements value sync by updating stepperValue
    • It is recommended to wrap formFields with ref to ensure reactive updates
  5. Style Isolation:

    • styleIsolation: 'shared' is enabled in WeChat Mini Program environment
    • Pay attention to style scope when customizing styles

# FAQ

# How to add new form fields?

Simply add new field configurations to the formFields array:

<script setup lang="ts">
import { ref } from 'vue';

const formFields = ref([
  {
    key: 'type',
    label: 'Prize Type',
    type: 'select',
    defaultText: 'Please select',
  },
  {
    key: 'quantity',
    label: 'Quantity',
    type: 'stepper',
    stepperValue: 1,
    min: 1,
    max: 999,
  },
  // Add new field
  {
    key: 'priority',
    label: 'Priority',
    type: 'stepper',
    stepperValue: 0,
    min: 0,
    max: 10,
    step: 1,
  },
]);
</script>

# How to implement selector echo?

Implement echo by updating the field's selectedValue property:

<script setup lang="ts">
import { ref } from 'vue';

const formFields = ref([
  {
    key: 'type',
    label: 'Prize Type',
    type: 'select',
    selectedValue: '', // Initially empty
    defaultText: 'Please select',
  },
]);

// Update selectedValue after user selection
const handleFieldValueSelect = (action) => {
  const fieldIndex = formFields.value.findIndex(f => f.key === 'type');
  if (fieldIndex !== -1) {
    // Will auto-echo after update
    formFields.value[fieldIndex].selectedValue = action.value;
  }
};
</script>

# How to dynamically adjust stepper range?

You can modify the field's min, max, and step properties:

<script setup lang="ts">
import { ref } from 'vue';

const formFields = ref([
  {
    key: 'quantity',
    label: 'Quantity',
    type: 'stepper',
    stepperValue: 10,
    min: 1,
    max: 100,
    step: 1,
  },
]);

// Dynamically adjust range based on business requirements
const adjustRange = (newMax) => {
  const field = formFields.value.find(f => f.key === 'quantity');
  if (field) {
    field.max = newMax;
    // Automatically adjust if current value exceeds new range
    if (field.stepperValue > newMax) {
      field.stepperValue = newMax;
    }
  }
};
</script>

# How to implement field linkage?

Implement field linkage by listening to field-change or field-select events:

<script setup lang="ts">
import { ref } from 'vue';

const formFields = ref([
  {
    key: 'type',
    label: 'Prize Type',
    type: 'select',
    selectedValue: '',
    defaultText: 'Please select',
  },
  {
    key: 'quantity',
    label: 'Quantity',
    type: 'stepper',
    stepperValue: 1,
    min: 1,
    max: 100,
  },
]);

// Field selection callback
const handleFieldValueSelect = (action) => {
  const fieldIndex = formFields.value.findIndex(f => f.key === 'type');
  if (fieldIndex !== -1) {
    formFields.value[fieldIndex].selectedValue = action.value;
    
    // Linkage: Adjust quantity range based on prize type
    const quantityField = formFields.value.find(f => f.key === 'quantity');
    if (quantityField) {
      if (action.value === 'Physical Prize') {
        quantityField.max = 50; // Max 50 for physical prizes
      } else if (action.value === 'Virtual Prize') {
        quantityField.max = 999; // Max 999 for virtual prizes
      }
    }
  }
};
</script>