轮播图新增视频功能

v1.0.0
于肖磊 2024-09-11 17:28:05 +08:00
parent e6f22e1816
commit 52c04e9b78
16 changed files with 190 additions and 72 deletions

View File

@ -1,9 +1,9 @@
@font-face {
font-family: "iconfont"; /* Project id 4607934 */
src: url('iconfont.woff2?t=1725414216013') format('woff2'),
url('iconfont.woff?t=1725414216013') format('woff'),
url('iconfont.ttf?t=1725414216013') format('truetype'),
url('iconfont.svg?t=1725414216013#iconfont') format('svg');
src: url('iconfont.woff2?t=1726043407380') format('woff2'),
url('iconfont.woff?t=1726043407380') format('woff'),
url('iconfont.ttf?t=1726043407380') format('truetype'),
url('iconfont.svg?t=1726043407380#iconfont') format('svg');
}
.iconfont {
@ -14,6 +14,10 @@
-moz-osx-font-smoothing: grayscale;
}
.icon-bofang:before {
content: "\e798";
}
.icon-a-miaosha:before {
content: "\e797";
}

File diff suppressed because one or more lines are too long

View File

@ -5,6 +5,13 @@
"css_prefix_text": "icon-",
"description": "web端",
"glyphs": [
{
"icon_id": "41814968",
"name": "播放 (2)",
"font_class": "bofang",
"unicode": "e798",
"unicode_decimal": 59288
},
{
"icon_id": "41708758",
"name": "秒杀",

View File

@ -14,6 +14,8 @@
/>
<missing-glyph />
<glyph glyph-name="bofang" unicode="&#59288;" d="M512 844.8c-255.488 0-460.8-205.312-460.8-460.8s205.312-460.8 460.8-460.8 460.8 205.312 460.8 460.8-205.312 460.8-460.8 460.8z m173.824-506.88L488.96 224.768a52.5824 52.5824 0 0 0-79.616 46.08V497.152c0 39.7312 44.032 64.8704 79.616 46.08l196.864-113.152c33.536-20.992 33.536-71.168 0-92.16z" horiz-adv-x="1024" />
<glyph glyph-name="a-miaosha" unicode="&#59287;" d="M501.504-102.4V300.629333H248.746667l313.770666 492.373334v-350.72h248.32L501.589333-102.4z" horiz-adv-x="1024" />
<glyph glyph-name="close-b" unicode="&#59205;" d="M512-128C229.6832-128 0 101.6832 0 384S229.6832 896 512 896s512-229.6832 512-512-229.6832-512-512-512z m0 984.610133C251.392 856.610133 39.389867 644.608 39.389867 384S251.392-88.610133 512-88.610133 984.610133 123.392 984.610133 384 772.608 856.610133 512 856.610133zM330.990933 183.296a19.694933 19.694933 0 0 0-13.9264 33.621333L679.082667 578.901333a19.694933 19.694933 0 1 0 27.8528-27.8528L344.917333 189.098667a19.592533 19.592533 0 0 0-13.9264-5.802667zM693.009067 183.296a19.592533 19.592533 0 0 0-13.9264 5.768533L317.098667 551.082667a19.694933 19.694933 0 1 0 27.8528 27.8528L706.901333 216.917333a19.694933 19.694933 0 0 0-13.9264-33.621333z" horiz-adv-x="1024" />

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 69 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -209,7 +209,7 @@
<div v-if="!isEmpty(icon_value)" class="upload-del-icon" @click.stop="del_icon_event">
<icon name="close-o" color="c" size="14"></icon>
</div>
<div class="flex-col gap-5 align-c">
<div class="flex-col gap-10 align-c">
<icon :name="!isEmpty(icon_value) ? icon_value : 'add'" :size="upload_size == '100%' ? '36' : Number(size) / 2 + ''" color="c"></icon>
<slot></slot>
</div>

View File

@ -25,16 +25,34 @@
@slide-change="slideChange"
>
<swiper-slide v-for="(item, index) in form.carousel_list" :key="index">
<div class="item-image flex jc-c align-c w h" :style="img_style">
<div class="item-image flex jc-c align-c w h re" :style="img_style">
<image-empty v-model="item.carousel_img[0]" :style="img_style" :fit="img_fit" error-style="width:5rem;height:5rem"></image-empty>
<div v-if="new_style.video_is_show == '1' && item.carousel_video.length > 0" :class="{'x-middle': new_style.video_location == 'center', 'right-0': new_style.video_location == 'flex-end' }" class="z-deep video-class flex-row abs gap-10 align-c oh" :style="video_style">
<template v-if="new_style.video_type == 'img'">
<image-empty v-model="new_style.video_img[0]" class="video_img" error-img-style="width: 1.4rem;height: 1.4rem;" />
</template>
<template v-else>
<el-icon :class="`iconfont ${ !isEmpty(new_style.video_icon_class) ? 'icon-' + new_style.video_icon_class : 'icon-bofang' } size-14`" :style="`color:${new_style.video_icon_color};`" />
</template>
<span v-if="!isEmpty(item.video_title)" :style="`color:${new_style.video_title_color};font-size: ${new_style.video_title_size}px;`">{{ item.video_title }}</span>
</div>
</div>
</swiper-slide>
<swiper-slide v-for="(item, index1) in seat_list" :key="index1">
<div class="item-image flex jc-c align-c w h" :style="img_style">
<div class="item-image flex jc-c align-c w h re" :style="img_style">
<image-empty v-model="item.carousel_img[0]" :style="img_style" :fit="img_fit" error-style="width:5rem;height:5rem"></image-empty>
<div v-if="new_style.video_is_show == '1' && item.carousel_video.length > 0" :class="{'x-middle': new_style.video_location == 'center', 'right-0': new_style.video_location == 'flex-end' }" class="z-deep video-class flex-row abs gap-10 align-c oh" :style="video_style">
<template v-if="new_style.video_type == 'img'">
<image-empty v-model="new_style.video_img[0]" class="video_img" error-img-style="width: 1.4rem;height: 1.4rem;" />
</template>
<template v-else>
<el-icon :class="`iconfont ${ !isEmpty(new_style.video_icon_class) ? 'icon-' + new_style.video_icon_class : 'icon-bofang' } size-14`" :style="`color:${new_style.video_icon_color};`" />
</template>
<span v-if="!isEmpty(item.video_title)" :style="`color:${new_style.video_title_color};font-size: ${new_style.video_title_size}px;`">{{ item.video_title }}</span>
</div>
</div>
</swiper-slide>
<div v-if="new_style.is_show == '1'" :class="{'dot-center': new_style.indicator_location == 'center', 'dot-right': new_style.indicator_location == 'flex-end' }" class="dot flex abs" :style="`bottom: ${new_style.indicator_bottom}px;`">
<div v-if="new_style.is_show == '1'" :class="{'x-middle': new_style.indicator_location == 'center', 'right-0': new_style.indicator_location == 'flex-end' }" class="dot flex abs" :style="`bottom: ${new_style.indicator_bottom}px;`">
<template v-if="new_style.indicator_style == 'num'">
<div :style="indicator_style" class="dot-item">
<span class="num-active">{{ actived_index + 1 }}</span><span>/{{ form.carousel_list.length }}</span>
@ -48,7 +66,7 @@
</div>
</template>
<script setup lang="ts">
import { common_styles_computer, radius_computer, get_math } from '@/utils';
import { common_styles_computer, radius_computer, get_math, gradient_computer, padding_computer } from '@/utils';
import { isEmpty, cloneDeep, throttle } from 'lodash';
import { Swiper, SwiperSlide } from 'swiper/vue';
import { Autoplay, EffectCoverflow } from 'swiper/modules';
@ -136,7 +154,19 @@ const interval_list = ref({
})
const interval_types = computed(() => interval_type.value == 'card' );
//
const video_style = computed(() => {
let style = `bottom: ${new_style.value.video_bottom}px;`;
if (!isEmpty(new_style.value.video_radius)) {
style += radius_computer(new_style.value.video_radius)
}
const data = {
color_list: new_style.value.video_color_list,
direction: new_style.value.video_direction,
}
style += gradient_computer(data) + padding_computer(new_style.value.video_padding) + `color: ${new_style.value.video_title_color};`;
return style;
});
// 使
watchEffect(() => {
//#region
@ -165,10 +195,7 @@ watchEffect(() => {
length: carousel_length
};
// key
// ,
throttle(() => {
carouselKey.value = get_math();
}, 1000);
carouselKey.value = get_math();
}
//#endregion
});
@ -189,15 +216,8 @@ const slideChange = (swiper: { realIndex: number }) => {
}
</script>
<style lang="scss" scoped>
.dot-center {
left: 50%;
transform: translateX(-50%);
}
.dot-right {
right: 0;
}
.dot {
z-index: 3;
z-index: 1;
.dot-item {
margin: 0 0.3rem;
&.active {
@ -228,4 +248,11 @@ const slideChange = (swiper: { realIndex: number }) => {
height: v-bind(newHeight);
}
}
.video_img {
max-width: 6rem;
height: 1.4rem;
}
.video-class {
max-width: 100%;
}
</style>

View File

@ -32,19 +32,19 @@
<div class="flex-col align-c jc-c gap-20 w">
<div class="upload_style">
<upload v-model="item.carousel_img" :limit="1" size="100%">
<p class="upload-text">上传图片</p>
<span class="upload-text">上传图片</span>
</upload>
</div>
<el-form-item label="图片链接" class="w">
<url-value v-model="item.carousel_link"></url-value>
</el-form-item>
<div class="upload_style">
<upload v-model="item.carousel_video" :limit="1" type="icon" is-icon size="100%">
<p class="upload-text">上传视频</p>
<upload v-model="item.carousel_video" :limit="1" type="video" size="100%">
<span class="upload-text">上传视频</span>
</upload>
</div>
<el-form-item label="按钮名称" class="w mb-16">
<el-input v-model="form.title" placeholder="请输入视频按钮名称" clearable></el-input>
<el-form-item v-if="item.carousel_video.length > 0" label="按钮名称" class="w">
<el-input v-model="item.video_title" placeholder="请输入视频按钮名称" clearable></el-input>
</el-form-item>
</div>
<el-icon class="iconfont icon-close-o size-16 abs cr-c top-de-5 right-de-5" @click="remove(index)" />
@ -72,6 +72,7 @@ const add = () => {
carousel_img: [],
carousel_video: [],
carousel_link: {},
video_title: "视频名称"
});
};
const remove = (index: number) => {
@ -84,6 +85,10 @@ const remove = (index: number) => {
padding-left: 1.6rem;
padding-right: 2rem;
padding-top: 4.6rem;
padding-bottom: 1.6rem;
:deep(.el-form-item) {
margin-bottom: 0;
}
}
.upload_style {
width: 100%;
@ -93,10 +98,8 @@ const remove = (index: number) => {
color: $cr-info-dark;
}
.upload-text {
font-weight: 500;
font-size: 1.4rem;
color: #999999;
line-height: 2rem;
text-align: left;
font-style: normal;
}

View File

@ -18,16 +18,60 @@
<card-container>
<carousel-indicator :value="form"></carousel-indicator>
</card-container>
<div class="divider-line"></div>
<card-container>
<div class="mb-12">视频按钮是否显示</div>
<el-form-item label="是否显示">
<el-switch v-model="form.is_show" active-value="1" inactive-value="0"/>
</el-form-item>
<el-form-item label="圆角">
<radius :value="form" @update:value="radius_change"></radius>
</el-form-item>
</card-container>
<template v-if="is_video">
<div class="divider-line"></div>
<card-container>
<div class="mb-12">视频按钮</div>
<el-form-item label="是否显示">
<el-switch v-model="form.video_is_show" active-value="1" inactive-value="0"/>
</el-form-item>
<template v-if="form.video_is_show == '1'">
<el-form-item label="图标样式">
<div class="flex-col gap-10">
<el-radio-group v-model="form.video_type" class="mb-10">
<el-radio value="img">图片</el-radio>
<el-radio value="icon">图标</el-radio>
</el-radio-group>
<template v-if="form.video_type == 'img'">
<upload v-model="form.video_img" :limit="1" size="50"></upload>
</template>
<template v-else>
<upload v-model:icon-value="form.video_icon_class" type="icon" is-icon :limit="1" size="50"></upload>
<color-picker v-model="form.video_icon_color" default-color="#ff6868"></color-picker>
</template>
</div>
</el-form-item>
<el-form-item label="位置">
<el-radio-group v-model="form.video_location" is-button>
<el-tooltip content="左对齐" placement="top" effect="light">
<el-radio-button value="flex-start"><icon name="iconfont icon-left"></icon></el-radio-button>
</el-tooltip>
<el-tooltip content="居中" placement="top" effect="light">
<el-radio-button value="center"><icon name="iconfont icon-center"></icon></el-radio-button>
</el-tooltip>
<el-tooltip content="右对齐" placement="top" effect="light">
<el-radio-button value="flex-end"><icon name="iconfont icon-right"></icon></el-radio-button>
</el-tooltip>
</el-radio-group>
</el-form-item>
<el-form-item label="下边距">
<slider v-model="form.video_bottom" :min="0" :max="100"></slider>
</el-form-item>
<el-form-item label="按钮名称">
<color-text-size-group v-model:color="form.video_title_color" v-model:size="form.video_title_size" default-color="#666" :type-list="['color', 'size']"></color-text-size-group>
</el-form-item>
<el-form-item label="背景色">
<mult-color-picker :value="form.video_color_list" :type="form.video_direction" @update:value="mult_color_picker_event"></mult-color-picker>
</el-form-item>
<el-form-item label="圆角">
<radius :value="form.video_radius"></radius>
</el-form-item>
<el-form-item label="内边距">
<padding :value="form.video_padding"></padding>
</el-form-item>
</template>
</card-container>
</template>
</el-form>
<div class="divider-line"></div>
<common-styles :value="form.common_style" @update:value="common_styles_update" />
@ -41,20 +85,29 @@ const props = defineProps({
type: Object,
default: () => {},
},
content: {
type: Object,
default: () => {},
}
});
const state = reactive({
form: props.value,
new_content: props.content,
});
// 使toRefs
const { form } = toRefs(state);
const { form, new_content } = toRefs(state);
const is_video = computed(() => new_content.value.carousel_list.length > 0 && (new_content.value.carousel_list.findIndex((item: any) => item.carousel_video.length > 0)) > 0);
// form,emit
const emit = defineEmits(['update:value']);
//
const radius_change = (radius: any) => {
form.value = Object.assign(form.value, pick(radius, ['radius', 'radius_top_left', 'radius_top_right', 'radius_bottom_left', 'radius_bottom_right']));
emit('update:value', form.value);
};
const mult_color_picker_event = (arry: color_list[], type: number) => {
form.value.video_color_list = arry;
form.value.video_direction = type.toString();
};
//
const common_styles_update = (val: Object) => {

View File

@ -469,10 +469,7 @@ watchEffect(() => {
notice_length: notice_length,
};
// key
// ,
throttle(() => {
carouselKey.value = get_math();
}, 1000);
carouselKey.value = get_math();
}
});
//#endregion

View File

@ -141,10 +141,7 @@ watch(props.value, (val) => {
is_roll: display_is_roll,
};
// key
// ,
throttle(() => {
carouselKey.value = get_math();
}, 1000);
carouselKey.value = get_math();
}
nextTick(() => {
if (!isEmpty(bannerImg.value)) {

View File

@ -76,7 +76,7 @@ const container_background_style = computed(() => {
return gradient_computer(styles) + radius_computer(new_style.value.container_radius) + background_computer(styles) + `overflow:hidden;`;
});
//
const img_style = ref('');
const img_style = computed(() => `height: ${ new_style.value.title_height }px; width: ${ new_style.value.title_width }px`);
//
const topic_style = computed(() => {
//
@ -108,14 +108,6 @@ const notice_list = computed(() => {
//
watchEffect(() => {
//#region
if (form.value.notice_style == 'card') {
img_style.value = `height: ${ new_style.value.title_height }px; width: ${ new_style.value.title_width }px`;
} else if (!isEmpty(form.value.img)) {
img_style.value = `height: ${ new_style.value.title_height }px; width: ${ new_style.value.title_width }px`;
}
//#endregion
//#region
const time = (new_style.value?.interval_time || 2) * 1000;
const direction = form.value.direction;
@ -134,10 +126,7 @@ watchEffect(() => {
notice_length: notice_length
};
// key
// ,
throttle(() => {
carouselKey.value = get_math();
}, 1000);
carouselKey.value = get_math();
}
//#endregion
});

View File

@ -434,10 +434,7 @@ watchEffect(() => {
//
slides_per_group.value = new_style.value.rolling_fashion == 'translation' ? 1 : form.value.carousel_col;
// key
// ,
throttle(() => {
carouselKey.value = get_math();
}, 1000);
carouselKey.value = get_math();
});
//

View File

@ -5,6 +5,7 @@ interface carousel_list {
carousel_img: uploadList[];
carousel_video: uploadList[];
carousel_link: object;
video_title: string;
}
interface defaultSearch {
content: {
@ -27,6 +28,19 @@ interface defaultSearch {
indicator_size: number;
indicator_bottom: number;
indicator_radius: radiusStyle;
video_is_show: string;
video_type: string;
video_radius: radiusStyle;
video_padding: paddingStyle;
video_img: uploadList[];
video_icon_class: string;
video_icon_color: string;
video_location: string;
video_bottom: number;
video_title_color: string;
video_title_size: number;
video_color_list: color_list[];
video_direction: string;
actived_color: string;
color: string;
common_style: object;
@ -42,17 +56,20 @@ const defaultSearch: defaultSearch = {
{
carousel_img: [],
carousel_video: [],
carousel_link: {}
carousel_link: {},
video_title: '视频名称'
},
{
carousel_img: [],
carousel_video: [],
carousel_link: {}
carousel_link: {},
video_title: '视频名称'
},
{
carousel_img: [],
carousel_video: [],
carousel_link: {}
carousel_link: {},
video_title: '视频名称'
}
]
},
@ -75,6 +92,31 @@ const defaultSearch: defaultSearch = {
radius_bottom_left: 4,
radius_bottom_right: 4,
},
video_is_show: '1',
video_type: 'icon',
video_radius: {
radius: 20,
radius_top_left: 20,
radius_top_right: 20,
radius_bottom_left: 20,
radius_bottom_right: 20,
},
video_padding: {
padding: 0,
padding_top: 3,
padding_bottom: 3,
padding_left: 6,
padding_right: 12,
},
video_img: [],
video_icon_class: '',
video_icon_color: '#ff6868',
video_location: 'center',
video_bottom: 20,
video_title_color: '#666',
video_title_size: 12,
video_color_list: [{ color: '#F0F0F0', color_percentage: undefined }],
video_direction: '180deg',
actived_color: '#2A94FF',
color: '#DDDDDD',
common_style: {