文件
shanghaipeiwan/pwuniapp/pages/activity/create.vue

425 行
10 KiB
Vue

此文件含有模棱两可的 Unicode 字符

此文件含有可能会与其他字符混淆的 Unicode 字符。 如果您是想特意这样的,可以安全地忽略该警告。 使用 Escape 按钮显示他们。

<template>
<view class="create-activity-container">
<!-- 模式选择 Tab (AA制 / 项目制) -->
<view class="mode-switch-wrap">
<view
class="mode-item btn-active"
:class="{ active: form.payType === 'AA' }"
@click="form.payType = 'AA'"
>
<image class="mode-svg" :src="ICONS.bolt" mode="aspectFit" />
<view class="mode-text-box">
<text class="mode-title">AA制车队</text>
<text class="mode-desc">报名人均平摊费用</text>
</view>
</view>
<view
class="mode-item btn-active"
:class="{ active: form.payType === 'PROJECT' }"
@click="form.payType = 'PROJECT'"
>
<image class="mode-svg" :src="ICONS.trophy" mode="aspectFit" />
<view class="mode-text-box">
<text class="mode-title">项目制悬赏</text>
<text class="mode-desc">房主全额悬赏奖金池</text>
</view>
</view>
</view>
<!-- 品类选择 -->
<view class="form-card">
<view class="card-label">选择活动品类</view>
<view class="game-pills">
<view
v-for="g in games"
:key="g"
class="game-pill btn-active"
:class="{ selected: form.game === g }"
@click="form.game = g"
>
{{ g }}
</view>
</view>
</view>
<!-- 基础信息录入 -->
<view class="form-card">
<view class="input-row">
<text class="row-label">活动标题</text>
<input
class="row-input"
v-model="form.title"
placeholder="如:三里屯火锅探店 / 百星五排极速冲分"
placeholder-class="ph"
/>
</view>
<view class="input-row">
<text class="row-label">活动时段</text>
<input
class="row-input"
v-model="form.startTime"
placeholder="如:今晚 20:30 / 周六 18:30"
placeholder-class="ph"
/>
</view>
<view class="input-row">
<text class="row-label">地点/频道</text>
<input
class="row-input"
v-model="form.location"
placeholder="如:朝阳区聚宝源 / 开黑语音 1 号房间"
placeholder-class="ph"
/>
</view>
</view>
<!-- 席位与费用配置 -->
<view class="form-card">
<view class="stepper-row">
<view class="stepper-info">
<text class="row-label">招募席位 (人)</text>
<text class="sub-label">包含房主在内的车队总人数</text>
</view>
<view class="stepper-box">
<button class="step-btn btn-active" :disabled="form.maxParticipants <= 2" @click="changeParticipants(-1)">-</button>
<text class="step-val">{{ form.maxParticipants }} 人</text>
<button class="step-btn btn-active" :disabled="form.maxParticipants >= 10" @click="changeParticipants(1)">+</button>
</view>
</view>
<view class="input-row" v-if="form.payType === 'AA'">
<text class="row-label">人均分摊 (元/人)</text>
<input
class="row-input"
type="digit"
v-model="form.aaFee"
placeholder="如:30"
placeholder-class="ph"
/>
</view>
<view class="input-row" v-else>
<text class="row-label">悬赏总奖金池 (元)</text>
<input
class="row-input"
type="digit"
v-model="form.totalFee"
placeholder="如:300"
placeholder-class="ph"
/>
</view>
<view class="calc-preview">
<text class="preview-label">预算测算:</text>
<text class="preview-val highlight">
{{ form.payType === 'AA' ? `总费用预估约 ¥${calcTotalFee} (人均 ¥${form.aaFee || 0})` : `参与者免费报名,全员争夺 ¥${form.totalFee || 0} 奖金池` }}
</text>
</view>
</view>
<!-- 底部发起操作栏 (适配安全区) -->
<view class="bottom-bar">
<button class="btn-submit btn-active" @click="handleSubmit">
立即发起组队活动
</button>
</view>
</view>
</template>
<script setup>
import { ref, computed } from 'vue';
import { ICONS } from '@/common/icons.js';
import { ACTIVITIES_LIST } from '@/common/mock.js';
const games = ['王者荣耀', '和平精英', '美食陪吃', '同城陪玩', '下午茶陪喝', '英雄联盟'];
const form = ref({
payType: 'AA',
game: '王者荣耀',
title: '',
startTime: '今晚 20:30',
location: '开黑语音 1 号频道',
maxParticipants: 5,
aaFee: 25,
totalFee: 125,
});
const calcTotalFee = computed(() => {
if (form.value.payType === 'AA') {
return (Number(form.value.aaFee) || 0) * form.value.maxParticipants;
}
return Number(form.value.totalFee) || 0;
});
const changeParticipants = (delta) => {
form.value.maxParticipants = Math.max(2, Math.min(10, form.value.maxParticipants + delta));
};
const handleSubmit = () => {
if (!form.value.title.trim()) {
form.value.title = `【${form.value.game}】今晚极速开黑车队`;
}
const newActivity = {
id: `act_${Date.now()}`,
game: form.value.game,
title: form.value.title,
payType: form.value.payType,
totalFee: calcTotalFee.value,
aaFee: Number(form.value.aaFee) || 0,
currentParticipants: 1,
maxParticipants: form.value.maxParticipants,
startTime: form.value.startTime,
location: form.value.location,
creatorNickname: '超能电竞玩家',
creatorAvatar: 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=150&h=150&fit=crop',
participants: [
{
id: 'u_888',
nickname: '超能电竞玩家',
avatar: 'https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=150&h=150&fit=crop',
checkedIn: true
}
]
};
ACTIVITIES_LIST.unshift(newActivity);
uni.showToast({
title: '活动发起成功!车队已就绪',
icon: 'success',
duration: 1500
});
setTimeout(() => {
uni.navigateBack();
}, 1200);
};
</script>
<style lang="scss" scoped>
.create-activity-container {
min-height: 100vh;
background-color: #0A0F1D;
padding: 24rpx 32rpx calc(160rpx + env(safe-area-inset-bottom));
}
.mode-switch-wrap {
display: flex;
gap: 16rpx;
margin-bottom: 24rpx;
.mode-item {
flex: 1;
background: #151D30;
border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 20rpx;
padding: 20rpx;
display: flex;
align-items: center;
gap: 14rpx;
.mode-svg {
width: 40rpx;
height: 40rpx;
}
.mode-text-box {
display: flex;
flex-direction: column;
.mode-title {
font-size: 26rpx;
font-weight: 700;
color: #F8FAFC;
margin-bottom: 4rpx;
}
.mode-desc {
font-size: 18rpx;
color: #64748B;
}
}
&.active {
background: linear-gradient(135deg, rgba(99, 102, 241, 0.18) 0%, rgba(139, 92, 246, 0.1) 100%);
border-color: #6366F1;
box-shadow: 0 0 16rpx rgba(99, 102, 241, 0.3);
.mode-title {
color: #818CF8;
}
}
}
}
.form-card {
background: #151D30;
border-radius: 24rpx;
padding: 28rpx;
margin-bottom: 24rpx;
border: 1px solid rgba(255, 255, 255, 0.06);
.card-label {
font-size: 26rpx;
font-weight: 700;
color: #F8FAFC;
margin-bottom: 20rpx;
}
.game-pills {
display: flex;
flex-wrap: wrap;
gap: 14rpx;
.game-pill {
font-size: 24rpx;
color: #94A3B8;
background: rgba(255, 255, 255, 0.04);
border: 1px solid rgba(255, 255, 255, 0.08);
padding: 10rpx 24rpx;
border-radius: 28rpx;
&.selected {
background: rgba(99, 102, 241, 0.2);
color: #818CF8;
border-color: #6366F1;
font-weight: 600;
}
}
}
.input-row {
display: flex;
align-items: center;
padding: 20rpx 0;
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
&:last-child {
border-bottom: none;
}
.row-label {
width: 220rpx;
font-size: 26rpx;
color: #CBD5E1;
}
.row-input {
flex: 1;
font-size: 26rpx;
color: #F8FAFC;
}
.ph {
color: #475569;
}
}
.stepper-row {
display: flex;
justify-content: space-between;
align-items: center;
padding-bottom: 20rpx;
border-bottom: 1px solid rgba(255, 255, 255, 0.04);
.stepper-info {
display: flex;
flex-direction: column;
.row-label {
font-size: 26rpx;
color: #CBD5E1;
font-weight: 600;
}
.sub-label {
font-size: 20rpx;
color: #64748B;
margin-top: 4rpx;
}
}
.stepper-box {
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.04);
border-radius: 16rpx;
padding: 6rpx;
.step-btn {
width: 68rpx;
height: 68rpx;
line-height: 64rpx;
padding: 0;
background: #1E2942;
color: #FFF;
font-size: 32rpx;
border-radius: 12rpx;
border: none;
margin: 0;
}
.step-val {
font-size: 28rpx;
color: #F8FAFC;
font-weight: 600;
margin: 0 20rpx;
font-variant-numeric: tabular-nums;
}
}
}
.calc-preview {
margin-top: 20rpx;
padding: 16rpx 20rpx;
background: rgba(99, 102, 241, 0.08);
border-radius: 14rpx;
display: flex;
align-items: center;
.preview-label {
font-size: 22rpx;
color: #94A3B8;
}
.preview-val {
font-size: 22rpx;
color: #10B981;
font-weight: 600;
font-variant-numeric: tabular-nums;
}
}
}
.bottom-bar {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: calc(120rpx + env(safe-area-inset-bottom));
padding: 0 32rpx env(safe-area-inset-bottom);
box-sizing: border-box;
background-color: rgba(21, 29, 48, 0.95);
backdrop-filter: blur(12px);
border-top: 1px solid rgba(255, 255, 255, 0.08);
display: flex;
align-items: center;
z-index: 100;
max-width: 450px;
margin: 0 auto;
.btn-submit {
flex: 1;
background: linear-gradient(135deg, #6366F1 0%, #8B5CF6 100%);
color: #FFF;
font-size: 28rpx;
font-weight: 700;
border-radius: 44rpx;
height: 84rpx;
line-height: 84rpx;
box-shadow: 0 4rpx 20rpx rgba(99, 102, 241, 0.4);
margin: 0;
}
}
</style>