需要添加直播接口

This commit is contained in:
cbb
2026-01-12 17:52:15 +08:00
parent 83fec2617c
commit 13af9eb303
281 changed files with 313157 additions and 104 deletions

View File

@@ -0,0 +1,557 @@
<template>
<!-- 美颜面板组件 -->
<!-- 使用方式: <BeautyPanel v-model="showBeautyPanel" @adjust-beauty="handleAdjustBeauty" @reset="handleReset" /> -->
<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="slider-section" v-if="currentOptionName !== '关闭'">
<view class="control-container">
<view class="custom-slider">
<!-- 减号按钮 -->
<view style="width: 40rpx; height: 40rpx;" @tap="decreaseValue">
<text class="btn-text">-</text>
</view>
<!-- 进度条区域 -->
<view class="progress-section">
<!-- 进度条背景 -->
<view class="progress-bar">
<view
class="progress-fill"
:style="{ width: (currentRealValue / 100 * 400) + 'rpx' }"
></view>
</view>
<!-- 当前数值显示 - 定位在进度条右侧 -->
<text class="current-value">{{ currentRealValue }}</text>
</view>
<!-- 加号按钮 -->
<view style="width: 40rpx; height: 40rpx;" @tap="increaseValue">
<text class="btn-text">+</text>
</view>
</view>
</view>
</view>
<!-- 功能标签页 -->
<!-- <view class="feature-tabs">
<view
v-for="(tab, index) in featureTabs"
:key="index"
class="tab-item"
:class="{ 'active': activeTabIndex === index }"
@tap="switchTab(index)"
>
<text class="tab-text" :class="{ 'active-text': activeTabIndex === index }">{{ tab.name }}</text>
<view v-if="tab.icon" class="tab-icon">
<image :src="tab.icon" mode="aspectFit" class="icon-image" />
</view>
</view>
</view> -->
<!-- 详细选项区域 -->
<view class="options-section">
<view class="options-grid">
<view
v-for="(option, index) in currentOptions"
:key="index"
class="option-item"
:class="{ 'selected': selectedOptionIndex === index }"
@tap="selectOption(index)"
>
<view class="option-icon-container">
<image :src="option.icon" mode="aspectFit" class="option-icon" />
</view>
<text class="option-name">{{ option.name }}</text>
</view>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { ref, computed, watch } from 'vue'
import { useBaseBeautyState } from '@/uni_modules/tuikit-atomic-x/state/BaseBeautyState'
const {
setSmoothLevel,
setWhitenessLevel,
setRuddyLevel,
whitenessLevel,
ruddyLevel,
smoothLevel,
realUiValues,
setRealUiValue,
getRealUiValue,
resetRealUiValues
} = useBaseBeautyState(uni.$liveID)
/**
* 美颜面板组件
*
* Props:
* - modelValue: Boolean - 控制面板显示/隐藏
*
* Events:
* - update:modelValue - 更新面板显示状态
* - adjust-beauty - 调整美颜参数事件
* - reset - 重置事件
*/
// Props 定义
const props = defineProps({
modelValue: {
type: Boolean,
default: false
}
})
// Emits 定义
const emit = defineEmits(['update:modelValue', 'adjust-beauty', 'reset'])
// 响应式数据
const activeTabIndex = ref(0)
const selectedOptionIndex = ref(0) // 默认选中"关闭"
const featureTabs = ref([
{ name: '美颜', icon: null },
// { name: '美体', icon: null },
// { name: '滤镜', icon: null },
// { name: '贴纸', icon: null },
// { name: '风格整妆', icon: null },
// { name: '重置', icon: '/static/images/edit.png' }
])
const beautyOptions = ref([
{ name: '关闭', icon: '/static/images/beauty-close.png' },
{ name: '美白', icon: '/static/images/whiteness.png' },
{ name: '磨皮', icon: '/static/images/smooth.png' },
{ name: '红润', icon: '/static/images/live-ruddy.png' },
// { name: '对比度', icon: '/static/images/setting.png' },
// { name: '饱和', icon: '/static/images/setting.png' }
])
const bodyOptions = ref([
{ name: '瘦脸', icon: '/static/images/beauty.png' },
{ name: '大眼', icon: '/static/images/beauty.png' },
{ name: '瘦身', icon: '/static/images/beauty.png' },
{ name: '长腿', icon: '/static/images/beauty.png' }
])
const filterOptions = ref([
{ name: '原图', icon: '/static/images/beauty.png' },
{ name: '暖色', icon: '/static/images/beauty.png' },
{ name: '冷色', icon: '/static/images/beauty.png' },
{ name: '黑白', icon: '/static/images/beauty.png' }
])
const stickerOptions = ref([
{ name: '无', icon: '/static/images/close.png' },
{ name: '帽子', icon: '/static/images/gift.png' },
{ name: '眼镜', icon: '/static/images/gift.png' },
{ name: '胡子', icon: '/static/images/gift.png' }
])
const styleOptions = ref([
{ name: '自然', icon: '/static/images/beauty.png' },
{ name: '清新', icon: '/static/images/beauty.png' },
{ name: '复古', icon: '/static/images/beauty.png' },
{ name: '时尚', icon: '/static/images/beauty.png' }
])
// 计算属性
const currentOptions = computed(() => {
const optionsMap = {
0: beautyOptions.value,
1: bodyOptions.value,
2: filterOptions.value,
3: stickerOptions.value,
4: styleOptions.value
}
return optionsMap[activeTabIndex.value] || beautyOptions.value
})
// 获取当前选项名称
const currentOptionName = computed(() => {
return currentOptions.value[selectedOptionIndex.value]?.name || '关闭'
})
// 获取当前激活的美颜效果名称(排除"关闭"选项)
const activeBeautyOption = computed(() => {
const options = currentOptions.value
for (let i = 0; i < options.length; i++) {
const option = options[i]
if (option.name !== '关闭') {
// 检查这个美颜效果是否有值
let hasValue = false
switch (option.name) {
case '美白':
hasValue = getRealUiValue('whiteness') > 0
break
case '红润':
hasValue = getRealUiValue('ruddy') > 0
break
case '磨皮':
hasValue = getRealUiValue('smooth') > 0
break
}
if (hasValue) {
return option.name
}
}
}
return null
})
// 获取当前选项对应的真实UI显示值显示用户拖动的真实数据
const currentRealValue = computed(() => {
switch (currentOptionName.value) {
case '美白':
return getRealUiValue('whiteness')
case '红润':
return getRealUiValue('ruddy')
case '磨皮':
return getRealUiValue('smooth')
case '关闭':
default:
return 0
}
})
// 监听外部状态变化只在初始化时设置真实的UI值
watch([smoothLevel, whitenessLevel, ruddyLevel], () => {
// 只在组件初始化时如果真实UI值未设置过才从API状态初始化
// 这样可以保持用户拖动的真实数据不被覆盖
if (getRealUiValue('whiteness') === 0 && whitenessLevel.value > 0) {
setRealUiValue('whiteness', Math.round(whitenessLevel.value * 10))
}
if (getRealUiValue('ruddy') === 0 && ruddyLevel.value > 0) {
setRealUiValue('ruddy', Math.round(ruddyLevel.value * 10))
}
if (getRealUiValue('smooth') === 0 && smoothLevel.value > 0) {
setRealUiValue('smooth', Math.round(smoothLevel.value * 10))
}
}, { immediate: true })
// 监听面板显示状态当面板打开时初始化UI值
watch(() => props.modelValue, (newValue) => {
if (newValue) {
// 面板打开时只有在真实UI值未设置过的情况下才从API状态初始化
// 这样可以保持用户上次拖动的真实数据
if (getRealUiValue('whiteness') === 0 && whitenessLevel.value > 0) {
setRealUiValue('whiteness', Math.round((whitenessLevel.value || 0) * 10))
}
if (getRealUiValue('ruddy') === 0 && ruddyLevel.value > 0) {
setRealUiValue('ruddy', Math.round((ruddyLevel.value || 0) * 10))
}
if (getRealUiValue('smooth') === 0 && smoothLevel.value > 0) {
setRealUiValue('smooth', Math.round((smoothLevel.value || 0) * 10))
}
}
})
// 方法
/**
* 关闭面板
*/
const close = () => {
emit('update:modelValue', false)
}
/**
* 减少数值
*/
const decreaseValue = () => {
const newValue = Math.max(0, currentRealValue.value - 10)
updateBeautyValue(newValue)
}
/**
* 增加数值
*/
const increaseValue = () => {
const newValue = Math.min(100, currentRealValue.value + 10)
updateBeautyValue(newValue)
}
/**
* 更新美颜数值
*/
const updateBeautyValue = (uiValue) => {
const currentOption = currentOptions.value[selectedOptionIndex.value]
// 保存真实的UI拖动值到全局状态
switch (currentOption.name) {
case '美白':
setRealUiValue('whiteness', uiValue)
break
case '红润':
setRealUiValue('ruddy', uiValue)
break
case '磨皮':
setRealUiValue('smooth', uiValue)
break
case '关闭':
return
}
// 如果UI值超过90API调用时限制为90
const limitedUiValue = uiValue > 90 ? 90 : uiValue
const apiValue = limitedUiValue / 10 // 转换为接口值0-9
// 调用对应的设置方法,传入转换后的参数值
switch (currentOption.name) {
case '美白':
setWhitenessLevel({ whitenessLevel: apiValue })
break
case '红润':
setRuddyLevel({ ruddyLevel: apiValue })
break
case '磨皮':
setSmoothLevel({ smoothLevel: apiValue })
break
}
emit('adjust-beauty', {
type: featureTabs.value[activeTabIndex.value].name,
option: currentOption.name,
value: uiValue
})
}
/**
* 切换标签页
*/
const switchTab = (index) => {
activeTabIndex.value = index
selectedOptionIndex.value = 0
// 如果是重置标签,触发重置事件
if (index === 5) {
emit('reset')
// 重置所有美颜参数
setSmoothLevel({ smoothLevel: 0 })
setWhitenessLevel({ whitenessLevel: 0 })
setRuddyLevel({ ruddyLevel: 0 })
selectedOptionIndex.value = 0
activeTabIndex.value = 0
}
}
/**
* 选择选项
*/
const selectOption = (index) => {
const currentOption = currentOptions.value[index]
// 如果选择"关闭",重置当前选中的美颜效果
if (currentOption.name === '关闭') {
// 获取当前选中的美颜效果在更新selectedOptionIndex之前
const currentSelectedOption = currentOptions.value[selectedOptionIndex.value]
// 根据当前选中的美颜效果来重置对应的参数
switch (currentSelectedOption?.name) {
case '美白':
setWhitenessLevel({ whitenessLevel: 0 })
setRealUiValue('whiteness', 0)
break
case '红润':
setRuddyLevel({ ruddyLevel: 0 })
setRealUiValue('ruddy', 0)
break
case '磨皮':
setSmoothLevel({ smoothLevel: 0 })
setRealUiValue('smooth', 0)
break
default:
// 如果当前选中的不是具体的美颜选项,则重置所有
setSmoothLevel({ smoothLevel: 0 })
setWhitenessLevel({ whitenessLevel: 0 })
setRuddyLevel({ ruddyLevel: 0 })
resetRealUiValues()
break
}
}
selectedOptionIndex.value = index
emit('adjust-beauty', {
type: featureTabs.value[activeTabIndex.value].name,
option: currentOption.name,
value: currentRealValue.value // 使用UI显示值0-100
})
}
</script>
<style>
.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;
flex-direction: column;
}
.drawer-open {
transform: translateY(0);
}
/* 滑块区域 */
.slider-section {
padding: 40rpx 48rpx 20rpx;
background-color: rgba(34, 38, 46, 1);
}
/* 自定义控制区域样式 */
.control-container {
flex-direction: row;
align-items: center;
justify-content: space-between;
}
.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-self: center;
align-items: center;
background-color: rgba(43, 106, 214, 0.1);
}
.plus-btn {
display: flex;
align-items: center;
justify-self: 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;
}
/* 详细选项区域 */
.options-section {
flex: 1;
background-color: rgba(34, 38, 46, 1);
padding: 20rpx 48rpx;
}
.options-grid {
flex-direction: row;
flex-wrap: wrap;
justify-content: space-between;
}
.option-item {
width: 120rpx;
margin-bottom: 30rpx;
align-items: center;
padding: 16rpx 12rpx;
border-radius: 12rpx;
border: 2rpx solid transparent;
}
.option-item.selected {
border-color: #2b6ad6;
background-color: #2b6ad6;
}
.option-icon-container {
width: 60rpx;
height: 60rpx;
margin-bottom: 12rpx;
justify-content: center;
align-items: center;
}
.option-icon {
width: 60rpx;
height: 60rpx;
}
.option-name {
font-size: 22rpx;
color: #ffffff;
text-align: center;
}
</style>