forked from zhongyidian/super_video
feat: 添加 ModuleSwitcher 组件及其子组件,更新 Husky 配置文档
This commit is contained in:
1 parent
cf7a5d5e81
commit
b9c6308d59
5 files changed
+87
-1
No files matched your search
@@ -1,7 +1,7 @@
|
||||
<script lang="ts" setup>
|
||||
import { getBackgroundImage, IMAGE_PATHS } from '@/utils'
|
||||
import { ImgButton } from '@/components/Button'
|
||||
import { ModuleSwitcher } from '@/components/ModuleSwitcher'
|
||||
import { ModuleSwitcher } from './components/ModuleSwitcher'
|
||||
import { computed, ref, onMounted } from 'vue'
|
||||
|
||||
// 响应式状态
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<div
|
||||
:style="{ backgroundImage: getBackgroundImage(currentImage) }"
|
||||
:class="['module-btn', module.className, { selected: isSelected }]"
|
||||
>
|
||||
<div :class="['btn-mask', module.maskConfig.className]" @click="$emit('click')"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed } from 'vue'
|
||||
import { getBackgroundImage } from '@/utils'
|
||||
|
||||
// 定义模块类型
|
||||
type ModuleType = 'vlog' | 'film' | 'interview'
|
||||
|
||||
// 模块配置接口
|
||||
interface ModuleConfig {
|
||||
type: ModuleType
|
||||
normalImage: string
|
||||
selectedImage: string
|
||||
className: string
|
||||
maskConfig: {
|
||||
className: string
|
||||
position: string
|
||||
size: string
|
||||
transform: string
|
||||
}
|
||||
}
|
||||
|
||||
// Props定义
|
||||
interface Props {
|
||||
module: ModuleConfig
|
||||
isSelected: boolean
|
||||
}
|
||||
|
||||
// Emits定义
|
||||
interface Emits {
|
||||
(e: 'click'): void
|
||||
}
|
||||
|
||||
const props = defineProps<Props>()
|
||||
defineEmits<Emits>()
|
||||
|
||||
// 计算当前显示的图片
|
||||
const currentImage = computed(() => {
|
||||
return props.isSelected ? props.module.selectedImage : props.module.normalImage
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.module-btn {
|
||||
position: absolute;
|
||||
transition:
|
||||
transform 0.2s ease,
|
||||
z-index 0.2s ease;
|
||||
z-index: 1;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.btn-mask {
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.module-btn:hover {
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.module-btn:active {
|
||||
/* transform: scale(0.95); */
|
||||
}
|
||||
|
||||
/* 确保选中的按钮在最上层 */
|
||||
.module-btn.selected {
|
||||
z-index: 20;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,119 @@
|
||||
<template>
|
||||
<div class="module-switcher">
|
||||
<ModuleButton
|
||||
v-for="module in moduleConfigs"
|
||||
:key="module.type"
|
||||
:module="module"
|
||||
:is-selected="selectedModule === module.type"
|
||||
@click="selectModule(module.type)"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { IMAGE_PATHS } from '@/utils'
|
||||
import ModuleButton from './ModuleButton.vue'
|
||||
|
||||
// 定义模块类型
|
||||
type ModuleType = 'vlog' | 'film' | 'interview'
|
||||
|
||||
// 模块配置接口
|
||||
interface ModuleConfig {
|
||||
type: ModuleType
|
||||
normalImage: string
|
||||
selectedImage: string
|
||||
className: string
|
||||
maskConfig: {
|
||||
className: string
|
||||
position: string
|
||||
size: string
|
||||
transform: string
|
||||
}
|
||||
}
|
||||
|
||||
// Props定义
|
||||
interface Props {
|
||||
modelValue?: ModuleType
|
||||
}
|
||||
|
||||
// Emits定义
|
||||
interface Emits {
|
||||
(e: 'update:modelValue', value: ModuleType): void
|
||||
(e: 'change', value: ModuleType): void
|
||||
}
|
||||
|
||||
const props = withDefaults(defineProps<Props>(), {
|
||||
modelValue: 'vlog'
|
||||
})
|
||||
|
||||
const emit = defineEmits<Emits>()
|
||||
|
||||
// 当前选中的模块
|
||||
const selectedModule = ref<ModuleType>(props.modelValue)
|
||||
|
||||
// 模块配置
|
||||
const moduleConfigs: ModuleConfig[] = [
|
||||
{
|
||||
type: 'vlog',
|
||||
normalImage: IMAGE_PATHS.ACTION.MODULE_BTN1,
|
||||
selectedImage: IMAGE_PATHS.ACTION.SELECTED_BTN1,
|
||||
className: 'w-[1235px] h-[830px] left-1/2 -translate-x-1/2 -bottom-6',
|
||||
maskConfig: {
|
||||
className: 'left-10 bottom-[240px] w-[500px] h-[100px] -rotate-[15deg]',
|
||||
position: 'left-10 bottom-[240px]',
|
||||
size: 'w-[500px] h-[100px]',
|
||||
transform: '-rotate-[15deg]'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'film',
|
||||
normalImage: IMAGE_PATHS.ACTION.MODULE_BTN2,
|
||||
selectedImage: IMAGE_PATHS.ACTION.SELECTED_BTN2,
|
||||
className: 'w-[1087px] h-[822px] left-[calc(50%+50px)] -translate-x-1/2 -bottom-4',
|
||||
maskConfig: {
|
||||
className: 'left-[16em] bottom-[50px] w-[500px] h-[100px]',
|
||||
position: 'left-[16em] bottom-[50px]',
|
||||
size: 'w-[500px] h-[100px]',
|
||||
transform: ''
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'interview',
|
||||
normalImage: IMAGE_PATHS.ACTION.MODULE_BTN3,
|
||||
selectedImage: IMAGE_PATHS.ACTION.SELECTED_BTN3,
|
||||
className: 'w-[943px] h-[822px] right-[320px] -bottom-4',
|
||||
maskConfig: {
|
||||
className: 'right-[0em] bottom-[200px] w-[420px] h-[100px] rotate-[15deg]',
|
||||
position: 'right-[0em] bottom-[200px]',
|
||||
size: 'w-[420px] h-[100px]',
|
||||
transform: 'rotate-[15deg]'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
// 选择模块
|
||||
const selectModule = (module: ModuleType) => {
|
||||
if (selectedModule.value === module) return
|
||||
|
||||
selectedModule.value = module
|
||||
emit('update:modelValue', module)
|
||||
emit('change', module)
|
||||
}
|
||||
|
||||
// 监听外部值变化
|
||||
watch(
|
||||
() => props.modelValue,
|
||||
newValue => {
|
||||
selectedModule.value = newValue
|
||||
}
|
||||
)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.module-switcher {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 1000px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1 @@
|
||||
export { default as ModuleSwitcher } from './ModuleSwitcher.vue'
|
||||
Reference in new issue
Block a user