# MatchJoinTeamPopup 加入战队弹窗

用于展示战队信息并允许用户申请加入战队的弹窗组件,包含战队成员展示、参赛必读入口和加入操作。

# 引入

import PressMatchJoinTeamPopup from 'press-next/press-match-join-team-popup/press-match-join-team-popup';

# 代码演示

# 基础用法

<template>
  <PressButton @click="show = true">
    加入战队
  </PressButton>

  <PressMatchJoinTeamPopup
    :show="show"
    title="加入阵营并参赛"
    :team-data="teamData"
    button-text="申请加入"
    @close="handleClose"
    @confirm="handleConfirm"
    @member-click="handleMemberClick"
    @add-click="handleAddClick"
    @read-rules-click="handleReadRulesClick"
  />
</template>

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

const show = ref(false);
const teamData = ref({
  id: 1,
  teamName: '王者战队',
  members: [
    {
      id: 1,
      name: '队长小明',
      avatar: 'https://example.com/avatar1.jpg',
      isCaptain: true,
    },
    {
      id: 2,
      name: '队员小红',
      avatar: 'https://example.com/avatar2.jpg',
      isCaptain: false,
    },
    {
      id: 3,
      name: '队员小李',
      avatar: 'https://example.com/avatar3.jpg',
      isCaptain: false,
    },
  ],
  maxMembers: 5,
  showAddButton: true,
  addButtonText: '邀请队友',
});

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

const handleConfirm = () => {
  console.log('申请加入战队');
  // 发送加入申请
  applyToJoinTeam();
  show.value = false;
};

const handleMemberClick = (member) => {
  console.log('点击成员:', member);
  // 查看成员详情
  viewMemberProfile(member);
};

const handleAddClick = () => {
  console.log('点击邀请队友');
  // 打开邀请界面
  openInviteDialog();
};

const handleReadRulesClick = () => {
  console.log('查看参赛必读');
  // 跳转到规则页面
  navigateToRules();
};

// API调用函数
const applyToJoinTeam = async () => {
  // 发送加入申请到服务器
};

const viewMemberProfile = (member) => {
  // 查看成员详情
};

const openInviteDialog = () => {
  // 打开邀请对话框
};

const navigateToRules = () => {
  // 跳转到参赛规则页面
};
</script>

# 高级用法

<template>
  <PressMatchJoinTeamPopup
    :show="show"
    title="加入精英战队"
    :team-data="teamData"
    button-text="立即申请"
    custom-class="custom-join-team-popup"
    @close="handleClose"
    @confirm="handleConfirm"
    @member-click="handleMemberClick"
    @add-click="handleAddClick"
    @read-rules-click="handleReadRulesClick"
  >
    <!-- 自定义底部按钮 -->
    <template #foot-btn>
      <div class="custom-buttons">
        <PressButton
          type="default"
          @click="handleCancel"
        >
          取消
        </PressButton>
        <PressButton
          type="primary"
          @click="handleApply"
        >
          申请加入
        </PressButton>
      </div>
    </template>
  </PressMatchJoinTeamPopup>
</template>

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

const show = ref(false);
const teamData = ref({
  id: 2,
  teamName: '精英战队 Elite Squad',
  members: [
    {
      id: 1,
      name: '队长Pro',
      avatar: 'https://example.com/captain.jpg',
      isCaptain: true,
      level: 'Diamond',
      winRate: '85%',
    },
    {
      id: 2,
      name: 'Ace选手',
      avatar: 'https://example.com/ace.jpg',
      isCaptain: false,
      level: 'Master',
      winRate: '78%',
    },
    {
      id: 3,
      name: 'Support王',
      avatar: 'https://example.com/support.jpg',
      isCaptain: false,
      level: 'Diamond',
      winRate: '82%',
    },
    {
      id: 4,
      name: 'Jungle神',
      avatar: 'https://example.com/jungle.jpg',
      isCaptain: false,
      level: 'Master',
      winRate: '90%',
    },
  ],
  maxMembers: 5,
  showAddButton: false, // 不显示添加按钮
  requirements: {
    minLevel: 'Diamond',
    minWinRate: '70%',
  },
});

const handleClose = () => {
  console.log('弹窗关闭');
  show.value = false;
};

const handleConfirm = () => {
  console.log('默认确认操作');
  show.value = false;
};

const handleMemberClick = (member) => {
  console.log('查看成员详情:', member);
  
  // 显示成员详细信息弹窗
  showMemberDetails({
    name: member.name,
    level: member.level,
    winRate: member.winRate,
    isCaptain: member.isCaptain,
  });
};

const handleAddClick = () => {
  console.log('邀请新成员');
  // 这个例子中不会触发,因为showAddButton为false
};

const handleReadRulesClick = () => {
  console.log('查看参赛必读');
  
  // 跳转到详细规则页面
  window.open('/match/rules', '_blank');
};

const handleCancel = () => {
  console.log('取消加入');
  show.value = false;
};

const handleApply = async () => {
  console.log('申请加入精英战队');
  
  try {
    // 检查用户是否满足加入条件
    const userQualified = await checkUserQualification();
    
    if (!userQualified) {
      showMessage('您的等级或胜率不满足加入条件');
      return;
    }
    
    // 发送加入申请
    await submitJoinApplication(teamData.value.id);
    
    showMessage('申请已提交,请等待队长审核');
    show.value = false;
  } catch (error) {
    console.error('申请失败:', error);
    showMessage('申请失败,请稍后重试');
  }
};

// 工具函数
const showMemberDetails = (member) => {
  // 显示成员详情弹窗
  console.log('显示成员详情:', member);
};

const checkUserQualification = async () => {
  // 检查用户资格
  return true; // 示例返回
};

const submitJoinApplication = async (teamId) => {
  // 提交加入申请
  console.log('提交申请到团队:', teamId);
};

const showMessage = (message) => {
  // 显示提示消息
  console.log('提示:', message);
};
</script>

<style scoped>
.custom-buttons {
  display: flex;
  gap: 12px;
}

.custom-buttons .press-button {
  flex: 1;
}
</style>

# 动态战队数据

<template>
  <div class="demo-controls">
    <PressButton @click="loadTeamData('full')">满员战队</PressButton>
    <PressButton @click="loadTeamData('recruiting')">招募中</PressButton>
    <PressButton @click="loadTeamData('elite')">精英战队</PressButton>
  </div>

  <PressMatchJoinTeamPopup
    :show="show"
    :title="currentTeam.title"
    :team-data="currentTeam.data"
    :button-text="currentTeam.buttonText"
    @close="show = false"
    @confirm="handleDynamicConfirm"
    @member-click="handleMemberClick"
    @add-click="handleAddClick"
    @read-rules-click="handleReadRulesClick"
  />
</template>

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

const show = ref(false);
const currentTeam = reactive({
  title: '',
  data: null,
  buttonText: '',
});

const teamConfigs = {
  full: {
    title: '战队已满员',
    buttonText: '申请替补',
    data: {
      id: 1,
      teamName: '满员战队',
      members: Array.from({ length: 5 }, (_, i) => ({
        id: i + 1,
        name: `队员${i + 1}`,
        avatar: `https://example.com/avatar${i + 1}.jpg`,
        isCaptain: i === 0,
      })),
      maxMembers: 5,
      showAddButton: false,
    },
  },
  recruiting: {
    title: '加入战队',
    buttonText: '立即加入',
    data: {
      id: 2,
      teamName: '招募战队',
      members: Array.from({ length: 3 }, (_, i) => ({
        id: i + 1,
        name: `队员${i + 1}`,
        avatar: `https://example.com/avatar${i + 1}.jpg`,
        isCaptain: i === 0,
      })),
      maxMembers: 5,
      showAddButton: true,
      addButtonText: '邀请好友',
    },
  },
  elite: {
    title: '申请加入精英战队',
    buttonText: '提交申请',
    data: {
      id: 3,
      teamName: '精英战队',
      members: Array.from({ length: 4 }, (_, i) => ({
        id: i + 1,
        name: `精英${i + 1}`,
        avatar: `https://example.com/elite${i + 1}.jpg`,
        isCaptain: i === 0,
        level: 'Master',
      })),
      maxMembers: 5,
      showAddButton: false,
    },
  },
};

const loadTeamData = (type) => {
  const config = teamConfigs[type];
  Object.assign(currentTeam, config);
  show.value = true;
};

const handleDynamicConfirm = () => {
  console.log(`${currentTeam.title}确认操作`);
  show.value = false;
};

const handleMemberClick = (member) => {
  console.log('点击成员:', member);
};

const handleAddClick = () => {
  console.log('点击添加按钮');
};

const handleReadRulesClick = () => {
  console.log('查看参赛必读');
};
</script>

# API

# Props

参数 说明 类型 默认值
show 是否显示弹窗 boolean false
title 弹窗标题 string '加入阵营并参赛'
teamData 战队数据 TeamData undefined
buttonText 按钮文案 string '申请加入'
customClass 自定义CSS类名 string ''

# TeamData 数据结构

interface TeamMember {
  id?: string | number;
  name: string;
  avatar: string;
  isCaptain?: boolean;
  [key: string]: any; // 支持扩展字段
}

interface TeamData {
  id?: string | number;
  teamName: string;
  members: TeamMember[];
  maxMembers?: number;
  showAddButton?: boolean;
  addButtonText?: string;
}

# Events

事件名 说明 回调参数
close 弹窗关闭时触发 -
confirm 确认按钮点击时触发 -
memberClick 点击成员时触发 member: TeamMember
addClick 点击添加按钮时触发 -
readRulesClick 点击参赛必读时触发 -

# Slots

插槽名 说明 参数
foot-btn 自定义底部按钮区域 -

# CSS 变量

组件提供了下列 CSS 变量,可用于自定义样式:

# 间距系统

CSS 变量 说明 默认值
--pmjtp-title-icon-ml 标题图标间距 $spacing-xs

# 颜色系统

CSS 变量 说明 默认值
--pmjtp-bg-color 背景色 #fff
--pmjtp-ctrls-text-color 控制按钮颜色 $color-text-invert-default

# 字体系统

CSS 变量 说明 默认值
--pmjtp-ctrls-font-size 控制按钮字体大小 $font-size-sm
--pmjtp-ctrls-icon-size 控制按钮图标大小 $font-size-sm

# 使用示例

/* 自定义加入战队弹窗样式 */
:root {
  --pmjtp-bg-color: #f5f5f5;
  --pmjtp-ctrls-text-color: #1890ff;
  --pmjtp-title-icon-ml: 8px;
}

/* 或通过customClass覆盖 */
.custom-join-team-popup {
  --pmjtp-ctrls-font-size: 16px;
  --pmjtp-ctrls-icon-size: 18px;
}

# 使用场景

# 1. 战队招募

  • 展示战队成员信息
  • 允许用户申请加入战队
  • 提供参赛规则查看入口

# 2. 团队管理

  • 查看战队当前成员状态
  • 支持邀请新成员加入
  • 管理战队人员配置

# 3. 比赛报名

  • 通过加入战队参与比赛
  • 了解战队实力和成员
  • 确认参赛资格和规则

# 注意事项

  1. 战队数据:确保传入完整的战队数据结构
  2. 成员头像:建议使用高清头像图片,尺寸建议 80x80 像素以上
  3. 权限控制:根据用户权限显示不同的操作按钮
  4. 状态管理:合理处理战队满员、招募中等不同状态
  5. 小程序兼容:支持微信小程序的 virtualHost 配置
  6. 响应式设计:组件会根据成员数量自动调整布局

# 依赖组件

  • PressMatchPopUp:基础弹窗组件
  • PressButton:按钮组件
  • PressMatchTeamItem:战队成员展示组件