Merge branch 'dev-yxl' of gitee.com:zongzhige/shopxo-diy into dev

v1.1.0
gongfuxiang 2024-12-26 01:34:52 +08:00
commit 3bff8fca71
11 changed files with 284 additions and 98 deletions

View File

@ -0,0 +1,61 @@
<template>
<el-form-item label="边框">
<el-switch v-model="border_show" active-value="1" inactive-value="0" />
</el-form-item>
<template v-if="border_show == '1'">
<el-form-item v-if="typeList.includes('color')" label="边框颜色">
<color-picker v-model="border_color" :default-color="defaultColor"></color-picker>
</el-form-item>
<el-form-item v-if="typeList.includes('style')" label="边框样式">
<el-radio-group v-model="border_style">
<el-radio value="dashed"><div class="border-style-item" style="border: 1px dashed #979797"></div></el-radio>
<el-radio value="solid"><div class="border-style-item" style="border: 1px solid #979797"></div></el-radio>
<el-radio value="dotted"><div class="border-style-item" style="border: 1px dotted #979797"></div></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item v-if="typeList.includes('size')" label="边框粗细">
<padding :value="border_size" :max="100"></padding>
</el-form-item>
</template>
</template>
<script setup lang="ts">
interface Props {
defaultColor?: string;
typeList?: string[]; // 3
}
const props = withDefaults(defineProps<Props>(), {
defaultColor: '',
typeList: () => ['color', 'style', 'size'],
});
const border_show = defineModel('show', {
type: String,
default: '0',
});
const border_color = defineModel('color', {
type: String,
default: '#FF3F3F',
});
const border_style = defineModel('style', {
type: String,
default: 'solid',
});
const border_size = defineModel('size', {
type: Object,
default: {
padding: 0,
padding_top: 0,
padding_bottom: 0,
padding_left: 0,
padding_right: 0,
},
});
</script>
<style lang="scss" scoped>
.border-style-item {
width: 3rem;
height: 2rem;
}
</style>

View File

@ -1,48 +1,51 @@
<template>
<div :style="style_container">
<div class="w h re" :style="style_img_container">
<template v-if="data_source_content_list.length > 0 && form.data_source_direction == 'vertical'">
<div class="flex-row flex-wrap" :style="`row-gap: ${ new_style.row_gap }px;column-gap: ${ new_style.column_gap }px;`">
<div v-for="(item1, index1) in data_source_content_list" :key="index1" :style="`width: ${ gap_width }`">
<div :style="style_chunk_container">
<div class="w h oh" :style="style_chunk_img_container">
<data-rendering :custom-list="form.custom_list" :source-list="item1" :data-height="form.height" :scale="scale" :is-custom="form.is_custom_data == '1'" :show-data="form?.show_data || { data_key: 'id', data_name: 'name' }"></data-rendering>
<div :style="style_img_container">
<div :style="style_content_container">
<div class="w h re" :style="style_content_img_container">
<template v-if="data_source_content_list.length > 0 && form.data_source_direction == 'vertical'">
<div class="flex-row flex-wrap" :style="`row-gap: ${ new_style.row_gap }px;column-gap: ${ new_style.column_gap }px;`">
<div v-for="(item1, index1) in data_source_content_list" :key="index1" :style="`width: ${ gap_width }`">
<div :style="style_chunk_container">
<div class="w h oh" :style="style_chunk_img_container">
<data-rendering :custom-list="form.custom_list" :source-list="item1" :data-height="form.height" :scale="scale" :is-custom="form.is_custom_data == '1'" :show-data="form?.show_data || { data_key: 'id', data_name: 'name' }"></data-rendering>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<div v-else-if="data_source_content_list.length > 0 && ['vertical-scroll', 'horizontal'].includes(form.data_source_direction)" class="oh" :style="form.data_source_direction == 'horizontal' ? `height:100%;` : `height: ${ swiper_height }px;`">
<swiper :key="carouselKey" class="w flex" :direction="form.data_source_direction == 'horizontal' ? 'horizontal': 'vertical'" :height="swiper_height" :loop="true" :autoplay="autoplay" :slides-per-view="slides_per_view" :slides-per-group="slides_per_group" :space-between="space_between" :allow-touch-move="false" :pause-on-mouse-enter="true" :modules="modules" @slide-change="slideChange">
<swiper-slide v-for="(item1, index1) in data_source_content_list" :key="index1">
<div :style="style_chunk_container">
<div class="w h oh" :style="style_chunk_img_container">
<data-rendering :custom-list="form.custom_list" :source-list="item1" :data-height="form.height" :scale="scale" :is-custom="form.is_custom_data == '1'" :show-data="form?.show_data || { data_key: 'id', data_name: 'name' }"></data-rendering>
</div>
</div>
</swiper-slide>
</swiper>
<div v-if="new_style.is_show == '1' && dot_list.length > 1" :class="['left', 'right'].includes(new_style.indicator_new_location) ? 'indicator_up_down_location' : 'indicator_about_location'" :style="indicator_location_style">
<template v-if="new_style.indicator_style == 'num'">
<div :style="indicator_style" class="dot-item">
<span class="num-active">{{ actived_index + 1 }}</span><span>/{{ dot_list.length }}</span>
</div>
</template>
<div v-else-if="data_source_content_list.length > 0 && ['vertical-scroll', 'horizontal'].includes(form.data_source_direction)" class="oh" :style="form.data_source_direction == 'horizontal' ? `height:100%;` : `height: ${ swiper_height }px;`">
<swiper :key="carouselKey" class="w flex" :direction="form.data_source_direction == 'horizontal' ? 'horizontal': 'vertical'" :height="swiper_height" :loop="true" :autoplay="autoplay" :slides-per-view="slides_per_view" :slides-per-group="slides_per_group" :space-between="space_between" :allow-touch-move="false" :pause-on-mouse-enter="true" :modules="modules" @slide-change="slideChange">
<swiper-slide v-for="(item1, index1) in data_source_content_list" :key="index1">
<div :style="style_chunk_container">
<div class="w h oh" :style="style_chunk_img_container">
<data-rendering :custom-list="form.custom_list" :source-list="item1" :data-height="form.height" :scale="scale" :is-custom="form.is_custom_data == '1'" :show-data="form?.show_data || { data_key: 'id', data_name: 'name' }"></data-rendering>
</div>
</div>
</swiper-slide>
</swiper>
<div v-if="new_style.is_show == '1' && dot_list.length > 1" :class="['left', 'right'].includes(new_style.indicator_new_location) ? 'indicator_up_down_location' : 'indicator_about_location'" :style="indicator_location_style">
<template v-if="new_style.indicator_style == 'num'">
<div :style="indicator_style" class="dot-item">
<span class="num-active">{{ actived_index + 1 }}</span><span>/{{ dot_list.length }}</span>
</div>
</template>
<template v-else>
<div v-for="(item, index) in dot_list" :key="index" :style="indicator_style" :class="{ 'dot-item': true, active: actived_index == index }" />
</template>
</div>
</div>
<template v-else>
<div v-for="(item, index) in dot_list" :key="index" :style="indicator_style" :class="{ 'dot-item': true, active: actived_index == index }" />
<div :style="style_chunk_container">
<div class="w h oh" :style="style_chunk_img_container">
<data-rendering :custom-list="form.custom_list" :data-height="form.height" :scale="scale"></data-rendering>
</div>
</div>
</template>
</div>
</div>
<template v-else>
<div :style="style_chunk_container">
<div class="w h oh" :style="style_chunk_img_container">
<data-rendering :custom-list="form.custom_list" :data-height="form.height" :scale="scale"></data-rendering>
</div>
</div>
</template>
</div>
</div>
</template>
<script setup lang="ts">
import { isEmpty, cloneDeep } from 'lodash';
@ -92,11 +95,15 @@ const gap_width = computed(() => {
const scale = ref(1);
//
watchEffect(() => {
const { common_style, data_style } = new_style.value;
const { common_style, data_style, data_content_style } = new_style.value;
//
const outer_spacing = common_style.margin_left + common_style.margin_right + common_style.padding_left + common_style.padding_right;
//
const content_spacing = data_content_style.margin_left + data_content_style.margin_right + data_content_style.padding_left + data_content_style.padding_right;
//
const internal_spacing = data_style.margin_left + data_style.margin_right + data_style.padding_left + data_style.padding_right;
//
const width = 390 - outer_spacing - internal_spacing - props.outerContainerPadding;
const width = 390 - outer_spacing - internal_spacing - content_spacing - props.outerContainerPadding;
//
scale.value = width / 390;
});
@ -104,7 +111,10 @@ watchEffect(() => {
//
const style_container = computed(() => common_styles_computer(new_style.value.common_style));
const style_img_container = computed(() => common_img_computer(new_style.value.common_style));
//
const style_content_container = computed(() => common_styles_computer(new_style.value.data_content_style));
const style_content_img_container = computed(() => common_img_computer(new_style.value.data_content_style));
//
const style_chunk_container = computed(() => common_styles_computer(new_style.value.data_style));
const style_chunk_img_container = computed(() => common_img_computer(new_style.value.data_style));

View File

@ -50,6 +50,22 @@
</div>
</el-form-item>
</card-container>
<div class="bg-f5 divider-line" />
<card-container>
<div class="mb-12">内容样式</div>
<el-form-item label="背景">
<background-common v-model:color_list="form.data_content_style.color_list" v-model:direction="form.data_content_style.direction" v-model:img_style="form.data_content_style.background_img_style" v-model:img="form.data_content_style.background_img" @mult_color_picker_event="mult_content_color_picker_event" />
</el-form-item>
<el-form-item label="外间距">
<margin :value="form.data_content_style"></margin>
</el-form-item>
<el-form-item label="内间距">
<padding :value="form.data_content_style"></padding>
</el-form-item>
<el-form-item label="圆角">
<radius :value="form.data_content_style"></radius>
</el-form-item>
</card-container>
</el-form>
<div class="bg-f5 divider-line" />
<common-styles :value="form.common_style" />
@ -72,7 +88,12 @@ const state = reactive({
});
// 使toRefs
const { form, data } = toRefs(state);
//
const mult_content_color_picker_event = (arry: color_list[], type: number) => {
form.value.data_content_style.color_list = arry;
form.value.data_content_style.direction = type.toString();
}
//
const mult_color_picker_event = (arry: color_list[], type: number) => {
form.value.data_style.color_list = arry;
form.value.data_style.direction = type.toString();

View File

@ -1,36 +1,40 @@
<template>
<template v-if="data_source_content_list.length > 0 && form.data_source_direction == 'vertical'">
<div class="flex-row flex-wrap" :style="`row-gap: ${ new_style.row_gap }px;column-gap: ${ new_style.column_gap }px;`">
<div v-for="(item1, index1) in data_source_content_list" :key="index1" :style="`width: ${ gap_width }`">
<div :style="style_container">
<div class="w h oh" :style="style_img_container">
<data-rendering :custom-list="form.custom_list" :source-list="item1" :is-custom="form.is_custom_data == '1'" :show-data="form?.show_data || { data_key: 'id', data_name: 'name' }" :data-height="form.height" :scale="scale"></data-rendering>
<div :style="style_content_container">
<div :style="style_content_img_container">
<template v-if="data_source_content_list.length > 0 && form.data_source_direction == 'vertical'">
<div class="flex-row flex-wrap" :style="`row-gap: ${ new_style.row_gap }px;column-gap: ${ new_style.column_gap }px;`">
<div v-for="(item1, index1) in data_source_content_list" :key="index1" :style="`width: ${ gap_width }`">
<div :style="style_container">
<div class="w h oh" :style="style_img_container">
<data-rendering :custom-list="form.custom_list" :source-list="item1" :is-custom="form.is_custom_data == '1'" :show-data="form?.show_data || { data_key: 'id', data_name: 'name' }" :data-height="form.height" :scale="scale"></data-rendering>
</div>
</div>
</div>
</div>
</template>
<div v-else-if="data_source_content_list.length > 0 && ['vertical-scroll', 'horizontal'].includes(form.data_source_direction)" class="oh" :style="form.data_source_direction == 'horizontal' ? `height:100%;` : `height: ${ swiper_height }px;`">
<swiper :key="carouselKey" class="w flex" :direction="form.data_source_direction == 'horizontal' ? 'horizontal': 'vertical'" :height="swiper_height" :loop="true" :autoplay="autoplay" :slides-per-view="slides_per_view" :slides-per-group="slides_per_group" :space-between="space_between" :allow-touch-move="false" :pause-on-mouse-enter="true" :modules="modules" @slide-change="slideChange">
<swiper-slide v-for="(item1, index1) in data_source_content_list" :key="index1">
<div :style="style_container">
<div class="w h oh" :style="style_img_container">
<data-rendering :custom-list="form.custom_list" :source-list="item1" :is-custom="form.is_custom_data == '1'" :show-data="form?.show_data || { data_key: 'id', data_name: 'name' }" :data-height="form.height" :scale="scale"></data-rendering>
</div>
</div>
</swiper-slide>
</swiper>
</div>
</div>
</template>
<div v-else-if="data_source_content_list.length > 0 && ['vertical-scroll', 'horizontal'].includes(form.data_source_direction)" class="oh" :style="form.data_source_direction == 'horizontal' ? `height:100%;` : `height: ${ swiper_height }px;`">
<swiper :key="carouselKey" class="w flex" :direction="form.data_source_direction == 'horizontal' ? 'horizontal': 'vertical'" :height="swiper_height" :loop="true" :autoplay="autoplay" :slides-per-view="slides_per_view" :slides-per-group="slides_per_group" :space-between="space_between" :allow-touch-move="false" :pause-on-mouse-enter="true" :modules="modules" @slide-change="slideChange">
<swiper-slide v-for="(item1, index1) in data_source_content_list" :key="index1">
<div :style="style_container">
<template v-else>
<div class="oh" :style="style_container">
<div class="w h oh" :style="style_img_container">
<data-rendering :custom-list="form.custom_list" :source-list="item1" :is-custom="form.is_custom_data == '1'" :show-data="form?.show_data || { data_key: 'id', data_name: 'name' }" :data-height="form.height" :scale="scale"></data-rendering>
<data-rendering :custom-list="form.custom_list" :data-height="form.height" :scale="scale"></data-rendering>
</div>
</div>
</swiper-slide>
</swiper>
</template>
</div>
</div>
<template v-else>
<div class="oh" :style="style_container">
<div class="w h oh" :style="style_img_container">
<data-rendering :custom-list="form.custom_list" :data-height="form.height" :scale="scale"></data-rendering>
</div>
</div>
</template>
</template>
<script setup lang="ts">
import { background_computer, get_math, gradient_computer, margin_computer, padding_computer, radius_computer } from '@/utils';
import { background_computer, common_img_computer, common_styles_computer, get_math, gradient_computer, margin_computer, padding_computer, radius_computer } from '@/utils';
import { isEmpty } from "lodash";
import { Swiper, SwiperSlide } from 'swiper/vue';
import { Autoplay } from 'swiper/modules';
@ -86,6 +90,45 @@ interface new_style {
data_background_img: uploadList[];
data_background_img_style: string;
}
//
const defalt_style: any = {
color_list: [{ color: '', color_percentage: undefined }],
direction: '180deg',
background_img_style: '2',
background_img: [],
radius: 0,
radius_top_left: 0,
radius_top_right: 0,
radius_bottom_left: 0,
radius_bottom_right: 0,
padding: 0,
padding_top: 0,
padding_bottom: 0,
padding_left: 0,
padding_right: 0,
margin: 0,
margin_top: 0,
margin_bottom: 0,
margin_left: 0,
margin_right: 0,
};
//
const style_content_container = computed(() => {
if (!isEmpty(new_style.value.data_content_style)) {
return common_styles_computer(new_style.value.data_content_style);
} else {
// 使
return common_styles_computer(defalt_style);
}
});
const style_content_img_container = computed(() => {
if (!isEmpty(new_style.value.data_content_style)) {
return common_img_computer(new_style.value.data_content_style);
} else {
return common_img_computer(defalt_style);
}
});
//
const style_container = computed(() => {
if (!isEmpty(new_style.value)) {

View File

@ -94,6 +94,24 @@
</el-form-item>
</card-container>
<div class="bg-f5 divider-line" />
<template v-if="tabs_content.data_type == 'custom'">
<card-container>
<div class="mb-12">内容样式</div>
<el-form-item label="背景">
<background-common :key="form.carouselKey" v-model:color_list="form.data_content_style.color_list" v-model:direction="form.data_content_style.direction" v-model:img_style="form.data_content_style.background_img_style" v-model:img="form.data_content_style.background_img" @mult_color_picker_event="data_content_mult_color_picker_event" />
</el-form-item>
<el-form-item v-if="tabs_content.data_type == 'custom'" label="外间距">
<margin :key="form.carouselKey" :value="form.data_content_style"></margin>
</el-form-item>
<el-form-item label="内间距">
<padding :key="form.carouselKey" :value="form.data_content_style"></padding>
</el-form-item>
<el-form-item label="圆角">
<radius :key="form.carouselKey" :value="form.data_content_style"></radius>
</el-form-item>
</card-container>
<div class="bg-f5 divider-line" />
</template>
</template>
<template v-if="tabs_content.data_type === 'goods'">
<card-container>
@ -200,6 +218,11 @@ const img_radius_change = (radius: radiusStyle) => {
'radius_bottom_right',
]));
}
//
const data_content_mult_color_picker_event = (arry: string[], type: number) => {
form.value.data_content_style.color_list = arry;
form.value.data_content_style.direction = type.toString();
}
//
const data_mult_color_picker_event = (arry: string[], type: number) => {
form.value.data_color_list = arry;

View File

@ -186,6 +186,27 @@ const data_style = {
radius_bottom_left: 4,
radius_bottom_right: 4,
},
data_content_style: {
color_list: [{ color: '', color_percentage: undefined }],
direction: '180deg',
background_img_style: '2',
background_img: [],
radius: 0,
radius_top_left: 0,
radius_top_right: 0,
radius_bottom_left: 0,
radius_bottom_right: 0,
padding: 0,
padding_top: 0,
padding_bottom: 0,
padding_left: 0,
padding_right: 0,
margin: 0,
margin_top: 0,
margin_bottom: 0,
margin_left: 0,
margin_right: 0,
},
column_gap: 0,
row_gap: 0,
indicator_style: 'dot',

View File

@ -182,19 +182,14 @@ const style_location_container = computed(() => {
});
//
const style_location_img_container = computed(() => {
const { location_background_img, location_background_img_style, location_padding, location_border_direction, location_border_size, location_border_color, location_margin } = new_style.value;
const { location_background_img, location_background_img_style, location_padding, location_border_size, location_border_color, location_margin, location_border_style = 'solid' } = new_style.value;
const style = {
background_img: location_background_img,
background_img_style: location_background_img_style,
}
let border = ``;
if (new_style.value.location_border_show == '1') {
//
if (location_border_direction == 'all') {
border += `border: ${location_border_size}px solid ${location_border_color};`;
} else {
border += `border-${location_border_direction}: ${location_border_size}px solid ${location_border_color};`;
}
border += `border-width: ${location_border_size.padding_top}px ${location_border_size.padding_right}px ${location_border_size.padding_bottom}px ${location_border_size.padding_left}px;border-style: ${ location_border_style };border-color: ${location_border_color};`
}
const height = 32 - location_margin.margin_top - location_margin.margin_bottom;
return background_computer(style) + padding_computer(location_padding) + radius_computer(new_style.value.location_radius) + border + `height: ${height}px;line-height: ${height}px;`;

View File

@ -82,8 +82,14 @@ const default_data = {
location_right_icon_size: 12,
location_border_show: '0',
location_border_color: '#FF3F3F',
location_border_direction: 'all',
location_border_size: 1,
location_border_style: 'solid',
location_border_size: {
padding: 0,
padding_top: 0,
padding_right: 0,
padding_bottom: 0,
padding_left: 0,
},
location_radius: {
radius: 0,
radius_top_left: 0,

View File

@ -102,26 +102,8 @@
<el-form-item label="外边距">
<margin :value="form.location_margin"></margin>
</el-form-item>
<el-form-item label="边框">
<el-switch v-model="form.location_border_show" active-value="1" inactive-value="0" />
</el-form-item>
<template v-if="form.location_border_show == '1'">
<el-form-item label="边框颜色">
<color-picker v-model="form.location_border_color" default-color="#FF3F3F"></color-picker>
</el-form-item>
<el-form-item label="边框位置">
<el-radio-group v-model="form.location_border_direction">
<el-radio value="all">全部</el-radio>
<el-radio value="left">左侧</el-radio>
<el-radio value="right">右侧</el-radio>
<el-radio value="top">上边框</el-radio>
<el-radio value="bottom">下边框</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item label="边框粗细">
<slider v-model="form.location_border_size" :max="100"></slider>
</el-form-item>
</template>
<!-- 边框处理 -->
<border-config v-model:show="form.location_border_show" v-model:color="form.location_border_color" v-model:style="form.location_border_style" v-model:size="form.location_border_size" :type-list="['color', 'style', 'size']" default-color="#FF3F3F"></border-config>
</card-container>
</template>
<div class="bg-f5 divider-line" />
@ -214,10 +196,6 @@ const location_mult_color_picker_event = (arry: color_list[], type: number) => {
form.value.location_color_list = arry;
form.value.location_direction = type.toString();
};
//
const location_background_img_change = (val: uploadList[]) => {
form.value.location_background_img = val;
};
const change_immersive_style = (val: string | number | boolean) => {
if (val === '0') {

View File

@ -99,6 +99,7 @@ interface defaultSearch {
indicator_size: number;
indicator_radius: radiusStyle;
data_style: object;
data_content_style: object;
row_gap: number;
column_gap: number;
// 通用样式
@ -176,6 +177,27 @@ const defaultSearch: defaultSearch = {
margin_left: 0,
margin_right: 0,
},
data_content_style: {
color_list: [{ color: '', color_percentage: undefined }],
direction: '180deg',
background_img_style: '2',
background_img: [],
radius: 0,
radius_top_left: 0,
radius_top_right: 0,
radius_bottom_left: 0,
radius_bottom_right: 0,
padding: 0,
padding_top: 0,
padding_bottom: 0,
padding_left: 0,
padding_right: 0,
margin: 0,
margin_top: 0,
margin_bottom: 0,
margin_left: 0,
margin_right: 0,
},
row_gap: 0,
column_gap: 0,
common_style: {

View File

@ -82,8 +82,8 @@ interface DefaultFooterNav {
location_right_icon_size: number;
location_border_show: string;
location_border_color: string;
location_border_direction: string;
location_border_size: number;
location_border_style: string;
location_border_size: paddingStyle;
location_radius: radiusStyle;
location_padding: paddingStyle;
location_margin: marginStyle;
@ -184,8 +184,14 @@ const defaultFooterNav: DefaultFooterNav = {
location_right_icon_size: 12,
location_border_show: '0',
location_border_color: '#FF3F3F',
location_border_direction: 'all',
location_border_size: 1,
location_border_style: 'solid',
location_border_size: {
padding: 0,
padding_top: 0,
padding_right: 0,
padding_bottom: 0,
padding_left: 0,
},
location_radius: {
radius: 0,
radius_top_left: 0,