Files
uniapp-im-shop/pages/anchor/components/activity.nvue

461 lines
9.8 KiB
Plaintext
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script setup>
import { reactive } from 'vue'
import { useUI } from '../../../utils/use-ui'
import { addLiveActivity } from '@/api/tui-kit'
import { useBarrageState } from '@/uni_modules/tuikit-atomic-x/state/BarrageState';
import { LIVE_BUSINESS } from '@/constants/live-keys'
const { showToast } = useUI()
const props = defineProps({
modelValue: {
type: Boolean,
default: false
},
/**
* 创建人类型1-主播 2-管理员 3-系统
*/
creatorType: {
type: String,
default: ''
},
/**
* 直播间ID
*/
roomId: {
type: String,
default: ''
},
/**
* 群 id
*/
groupID: {
type: String,
default: ''
}
})
const { sendCustomMessage } = useBarrageState(props.roomId);
const emit = defineEmits(['update:modelValue'])
/**
* 根据用户输入的结束时间(分钟)计算开始时间和结束时间,并格式化为 yyyy-MM-dd HH:mm:ss
*/
const calculateTimeRange = endMinutes => {
// 获取当前时间(毫秒)
const now = new Date().getTime()
// 计算结束时间(毫秒)
const endTimeMs = now + endMinutes * 60 * 1000
// 创建 Date 对象
const startDate = new Date(now)
const endDate = new Date(endTimeMs)
// 格式化函数:将 Date 转为 'yyyy-MM-dd HH:mm:ss'
const formatDateTime = date => {
const pad = num => num.toString().padStart(2, '0')
const year = date.getFullYear()
const month = pad(date.getMonth() + 1) // getMonth() 返回 0-11
const day = pad(date.getDate())
const hours = pad(date.getHours())
const minutes = pad(date.getMinutes())
const seconds = pad(date.getSeconds())
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}
return {
startTime: formatDateTime(startDate),
endTime: formatDateTime(endDate)
}
}
const close = () => {
emit('update:modelValue', false)
}
const formData = reactive({
title: '',
// startTime: '',
// endTime: '',
// 结束时间
endTime: '',
roomId: '',
rewardValue: '',
maxParticipants: '',
isRepeat: 0
})
const submitForm = async () => {
if (!formData.title) {
showToast('请填写标题')
return
}
if (!formData.endTime) {
showToast('请填写结束时间')
return
}
if (!formData.rewardValue) {
showToast('请填写奖励值')
return
}
if (!formData.maxParticipants) {
showToast('请填写参与人数')
return
}
// 参与人数不能为0
if (Number(formData.maxParticipants) === 0) {
showToast('参与人数不能为0')
return
}
// 参与人数必须是整数
if (!Number.isInteger(Number(formData.maxParticipants))) {
showToast('参与人数必须是整数')
return
}
// 参与人数不能大于1000
if (Number(formData.maxParticipants) > 1000) {
showToast('参与人数不能大于1000')
return
}
const data = {
title: formData.title,
startTime: calculateTimeRange(Number(formData.endTime)).startTime,
endTime: calculateTimeRange(Number(formData.endTime)).endTime,
rewardValue: Number(formData.rewardValue),
maxParticipants: Number(formData.maxParticipants),
isRepeat: formData.isRepeat,
creatorType: props.creatorType,
roomId: props.roomId
}
const res = await addLiveActivity(data)
console.log('=====发送活动====',res.data)
sendCustomMessage({
liveID: props.roomId,
businessID: LIVE_BUSINESS.SIGN,
data: JSON.stringify(res.data)
});
formData.title = ''
formData.endTime = ''
formData.rewardValue = ''
formData.maxParticipants = ''
close()
}
</script>
<template>
<view class="bottom-drawer-container" v-if="modelValue">
<view class="drawer-overlay" @tap="close"></view>
<view
class="bottom-drawer"
:class="{ 'drawer-open': modelValue }"
@click.stop
>
<view class="drawer-header">
<text class="drawer-title">添加活动</text>
<text class="drawer-done" @tap="submitForm">完成</text>
</view>
<view class="setting-item">
<text class="setting-label">标题</text>
<view class="live-list-quick-join">
<input
v-model="formData.title"
placeholder="请输入标题"
class="quick-join-input"
/>
</view>
</view>
<view class="setting-item">
<text class="setting-label">结束时间(分钟)</text>
<view class="live-list-quick-join">
<input
v-model="formData.endTime"
type="number"
placeholder="请输入结束时间(分钟)"
class="quick-join-input"
/>
</view>
</view>
<view class="setting-item">
<text class="setting-label">奖励值(积分)</text>
<view class="live-list-quick-join">
<input
v-model="formData.rewardValue"
type="number"
placeholder="请输入奖励值"
class="quick-join-input"
/>
</view>
</view>
<view class="setting-item">
<text class="setting-label">参与人数</text>
<view class="live-list-quick-join">
<input
v-model="formData.maxParticipants"
type="number"
placeholder="请输入参与人数"
class="quick-join-input"
/>
</view>
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
.bottom-drawer-container {
position: fixed;
bottom: 0;
left: 0;
right: 0;
top: 0;
z-index: 1000;
}
.drawer-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.4);
}
.bottom-drawer {
position: absolute;
bottom: 0;
left: 0;
right: 0;
background: rgba(34, 38, 46, 1);
border-top-left-radius: 32rpx;
border-top-right-radius: 32rpx;
transform: translateY(100%);
transition-property: transform;
transition-duration: 0.3s;
transition-timing-function: ease;
padding: 32rpx;
}
.drawer-open {
transform: translateY(0);
}
.drawer-header {
flex-direction: row;
justify-content: space-between;
align-items: center;
margin-bottom: 32rpx;
}
.drawer-title {
font-size: 32rpx;
color: #ffffff;
font-weight: 500;
}
.drawer-done {
font-size: 32rpx;
color: #2b65fb;
}
.setting-item {
flex-direction: row;
justify-content: space-between;
align-items: center;
height: 88rpx;
border-bottom-width: 1px;
border-bottom-color: rgba(255, 255, 255, 0.1);
.live-list-quick-join {
flex-direction: row;
align-items: center;
margin: 0 32rpx 24rpx 32rpx;
}
.quick-join-input {
flex: 1;
width: 360rpx;
height: 64rpx;
border-radius: 999rpx;
padding: 10rpx 20rpx;
margin-top: 20rpx;
font-size: 28rpx;
text-align: right;
color: white;
}
}
.setting-label {
font-size: 28rpx;
color: #ffffff;
}
.setting-value {
flex-direction: row;
align-items: center;
}
.setting-text {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.5);
margin-right: 8rpx;
}
.setting-arrow {
width: 24rpx;
height: 24rpx;
}
.volume-settings {
margin-top: 32rpx;
}
.section-title {
font-size: 28rpx;
color: rgba(255, 255, 255, 0.5);
margin-bottom: 24rpx;
}
.slider-item {
margin-bottom: 24rpx;
display: flex;
flex-direction: column;
}
.slider-label {
font-size: 28rpx;
color: #ffffff;
margin-bottom: 16rpx;
}
/* 自定义控制区域样式 */
.custom-slider {
flex: 1;
flex-direction: row;
align-items: center;
margin: 0 20rpx;
}
.control-btn {
width: 60rpx;
height: 60rpx;
border-radius: 30rpx;
display: flex;
justify-content: center;
align-items: center;
border: 2rpx solid #2b6ad6;
}
.minus-btn {
display: flex;
justify-content: center;
align-items: center;
background-color: rgba(43, 106, 214, 0.1);
}
.plus-btn {
display: flex;
align-items: center;
justify-content: center;
background-color: #2b6ad6;
}
.btn-text {
font-size: 32rpx;
font-weight: bold;
color: #ffffff;
}
.plus-btn .btn-text {
color: #ffffff;
}
.progress-section {
flex: 1;
margin: 0 20rpx;
align-items: center;
flex-direction: row;
justify-content: center;
}
.progress-bar {
width: 400rpx;
height: 8rpx;
background-color: rgba(255, 255, 255, 0.3);
border-radius: 4rpx;
position: relative;
overflow: hidden;
margin-right: 16rpx;
}
.progress-fill {
height: 8rpx;
background-color: #2b6ad6;
border-radius: 4rpx;
}
.current-value {
font-size: 24rpx;
color: #ffffff;
font-weight: 600;
text-align: center;
z-index: 10;
}
.voice-effects,
.reverb-effects {
margin-top: 32rpx;
}
.effects-grid {
flex-direction: row;
flex-wrap: wrap;
margin: 0 -8rpx;
}
.effect-item {
margin: 8rpx;
/* background-color: rgba(255, 255, 255, 0.1); */
justify-content: center;
align-items: center;
}
.effect-active {
background-color: rgba(43, 101, 251, 0.2);
border-width: 2rpx;
border-color: #2b65fb;
}
.effect-icon-container {
width: 112rpx;
height: 112rpx;
display: flex;
justify-content: center;
align-items: center;
border-radius: 16rpx;
background-color: rgba(255, 255, 255, 0.1);
margin-bottom: 12rpx;
}
.effect-icon {
width: 48rpx;
height: 48rpx;
margin-bottom: 8rpx;
}
.effect-name {
font-size: 24rpx;
color: #ffffff;
}
</style>