Merge remote-tracking branch 'origin/dev-yxl' into dev-sws

v1.0.0
sws 2024-09-23 17:35:04 +08:00
commit bf81c23507
13 changed files with 295 additions and 20 deletions

View File

@ -0,0 +1,60 @@
<template>
<div class="img-outer re oh" :style="com_style">
<div :style="icon_style" class="flex-row">
<icon :name="form.icon_class" :color="form.icon_color" :size="form.icon_size"></icon>
</div>
</div>
</template>
<script setup lang="ts">
import { radius_computer, padding_computer } from '@/utils';
const props = defineProps({
value: {
type: Object,
default: () => {
return {};
},
required: true
},
sourceList: {
type: Object,
default: () => {
return {};
}
},
isPercentage: {
type: Boolean,
default: false
}
});
//
const form = reactive(props.value);
const com_style = computed(() => {
let style = `${ set_count() } background-color: ${ form.com_bg }; ${ radius_computer(form.bg_radius) }`;
if (form.border_show == '1') {
style += `border: ${form.border_size}px ${form.border_style} ${form.border_color};`;
}
return style;
});
const icon_style = computed(() => {
let style = `transform: rotate(${form.icon_rotate}deg);${ padding_computer(form.icon_padding) };`;
if (form.icon_location == 'center') {
style += `justify-content: center;`;
} else if (form.icon_location == 'left') {
style += `justify-content: flex-start;`;
} else if (form.icon_location == 'right') {
style += `justify-content: flex-end;`;
}
return style;
});
const set_count = () => {
if (props.isPercentage) {
return '';
} else {
return `width: ${ form.com_width }px; height: ${ form.com_height }px;`;
}
};
</script>
<style lang="scss" scoped>
</style>

View File

@ -0,0 +1,148 @@
<template>
<div class="w h bg-f">
<el-form :model="form" label-width="70">
<card-container>
<div class="mb-12">文本设置</div>
<el-form-item label="选择图标">
<upload v-model:icon-value="form.icon_class" :limit="1" size="50" is-icon type="icon" @update:model-value="icon_change('1')"></upload>
</el-form-item>
<el-form-item label="数据字段">
<el-select v-model="form.data_source_id" value-key="id" clearable filterable placeholder="请选择数据字段" size="default" class="flex-1" @change="icon_change('2')">
<el-option v-for="item in options.filter((item) => item.type == 'icon')" :key="item.field" :label="item.name" :value="item.field" />
</el-select>
</el-form-item>
<el-form-item label="链接">
<url-value v-model="form.icon_link"></url-value>
</el-form-item>
<el-form-item label="图标颜色">
<color-picker v-model="form.icon_color" default-color="#FF3F3F"></color-picker>
</el-form-item>
<el-form-item label="图标大小">
<slider v-model="form.icon_size" :max="100"></slider>
</el-form-item>
<el-form-item label="图标位置">
<el-radio-group v-model="form.icon_location" is-button>
<el-tooltip content="左对齐" placement="top" effect="light">
<el-radio-button value="left"><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="right"><icon name="iconfont icon-right"></icon></el-radio-button>
</el-tooltip>
</el-radio-group>
</el-form-item>
<el-form-item label="内边距">
<padding :value="form.icon_padding" @update:value="padding_change"></padding>
</el-form-item>
<el-form-item label="旋转角度">
<slider v-model="form.icon_rotate" :max="1000"></slider>
</el-form-item>
<el-form-item label="是否置底">
<el-switch v-model="form.bottom_up" active-value="1" inactive-value="0" />
</el-form-item>
</card-container>
<div class="bg-f5 divider-line" />
<card-container>
<div class="mb-12">容器设置</div>
<el-form-item label="容器宽度">
<slider v-model="form.com_width" :max="1000"></slider>
</el-form-item>
<el-form-item label="容器高度">
<slider v-model="form.com_height" :max="1000"></slider>
</el-form-item>
<el-form-item label="背景颜色">
<color-picker v-model="form.com_bg"></color-picker>
</el-form-item>
<el-form-item label="圆角">
<radius :value="form.bg_radius" @update:value="bg_radius_change"></radius>
</el-form-item>
</card-container>
<div class="bg-f5 divider-line" />
<card-container>
<div class="mb-12">边框设置</div>
<el-form-item label="边框显示">
<el-switch v-model="form.border_show" active-value="1" inactive-value="0"/>
</el-form-item>
<template v-if="form.border_show == '1'">
<el-form-item label="边框颜色">
<color-picker v-model="form.border_color" default-color="#FF3F3F"></color-picker>
</el-form-item>
<el-form-item label="边框样式">
<el-radio-group v-model="form.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 label="边框粗细">
<slider v-model="form.border_size" :max="1000"></slider>
</el-form-item>
</template>
</card-container>
</el-form>
</div>
</template>
<script setup lang="ts">
import { location_compute } from '@/utils';
import { pick, cloneDeep } from 'lodash';
const props = defineProps({
value: {
type: Object,
default: () => ({}),
},
options: {
type: Array<any>,
default: () => [],
},
});
//
const state = reactive({
diy_data: props.value,
});
// 使toRefs
const { diy_data } = toRefs(state);
const form = ref(diy_data.value.com_data);
const center_height = defineModel('height', { type: Number, default: 0 });
const padding_change = (padding: any) => {
form.value.icon_padding = Object.assign(form.value.icon_padding, pick(padding, ['padding', 'padding_top', 'padding_bottom', 'padding_left', 'padding_right']));
};
const bg_radius_change = (radius: any) => {
form.value.bg_radius = Object.assign(form.value.bg_radius, pick(radius, ['radius', 'radius_top_left', 'radius_top_right', 'radius_bottom_left', 'radius_bottom_right']));
};
const icon_change = (key: string) => {
if (key == '2') {
form.value.icon_title = '';
} else {
form.value.data_source_id = '';
}
};
watch(
diy_data,
(val) => {
diy_data.value.location.x = location_compute(form.value.com_width, val.location.x, 390);
diy_data.value.location.y = location_compute(form.value.com_height, val.location.y, center_height.value);
diy_data.value.location.record_x = location_compute(form.value.com_width, val.location.record_x, 390);
diy_data.value.location.record_y = location_compute(form.value.com_height, val.location.record_y, center_height.value);
diy_data.value.location.staging_y = location_compute(form.value.com_height, val.location.staging_y, center_height.value);
form.value.staging_height = form.value.com_height;
},
{ immediate: true, deep: true }
);
</script>
<style lang="scss" scoped>
.card.mb-8 {
.el-form-item:last-child {
margin-bottom: 0;
}
}
.border-style-item {
width: 3rem;
height: 2rem;
}
</style>

View File

@ -7,7 +7,7 @@
<upload v-model="form.img" :limit="1" size="50" @update:model-value="img_src_change('1')"></upload>
</el-form-item>
<el-form-item label="数据字段">
<el-select v-model="form.data_source_id" value-key="id" clearable filterable placeholder="请选择图片数据字段" size="default" class="flex-1" @change="img_src_change('2')">
<el-select v-model="form.data_source_id" value-key="id" clearable filterable placeholder="请选择数据字段" size="default" class="flex-1" @change="img_src_change('2')">
<el-option v-for="item in options.filter(item => item.type == 'images')" :key="item.field" :label="item.name" :value="item.field" />
</el-select>
</el-form-item>

View File

@ -29,7 +29,7 @@
<slider v-model="form.line_size" :min="1" :max="100"></slider>
</el-form-item>
<el-form-item label="线条颜色">
<color-picker v-model="form.line_color" default-color="#FF3F3F"></color-picker>
<color-picker v-model="form.line_color"></color-picker>
</el-form-item>
<el-form-item label="是否置底">
<el-switch v-model="form.bottom_up" active-value="1" inactive-value="0" />

View File

@ -7,7 +7,7 @@
<el-input v-model="form.text_title" placeholder="请输入文本内容" type="textarea" clearable :rows="3" @input="text_change('1')"></el-input>
</el-form-item>
<el-form-item label="数据字段">
<el-select v-model="form.data_source_id" value-key="id" clearable filterable placeholder="请选择图片数据字段" size="default" class="flex-1" @change="text_change('2')">
<el-select v-model="form.data_source_id" value-key="id" clearable filterable placeholder="请选择数据字段" size="default" class="flex-1" @change="text_change('2')">
<el-option v-for="item in options.filter((item) => item.type == 'text')" :key="item.field" :label="item.name" :value="item.field" />
</el-select>
</el-form-item>
@ -73,7 +73,7 @@
<slider v-model="form.com_height" :max="1000"></slider>
</el-form-item>
<el-form-item label="背景颜色">
<color-picker v-model="form.com_bg" default-color="#FF3F3F"></color-picker>
<color-picker v-model="form.com_bg"></color-picker>
</el-form-item>
<el-form-item label="圆角">
<radius :value="form.bg_radius" @update:value="bg_radius_change"></radius>

View File

@ -34,7 +34,7 @@
<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>
<span v-if="!isEmpty(item.video_title)" :style="`color:${new_style.video_title_color};font-size: ${new_style.video_title_size}px;text-wrap: nowrap;`">{{ item.video_title }}</span>
</div>
</div>
</swiper-slide>
@ -48,7 +48,7 @@
<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>
<span v-if="!isEmpty(item.video_title)" :style="`color:${new_style.video_title_color};font-size: ${new_style.video_title_size}px;text-wrap: nowrap;`">{{ item.video_title }}</span>
</div>
</div>
</swiper-slide>
@ -309,5 +309,7 @@ const slideChange = (swiper: { realIndex: number }) => {
}
.video-class {
max-width: 100%;
margin-right: 10px;
margin-left: 10px;
}
</style>

View File

@ -82,6 +82,44 @@ export const line_com_data = {
bottom_up: '1',
}
// icon的默认值
export const icon_com_data = {
com_width: 36,
com_height: 36,
staging_height: 36,
icon_class: '',
data_source_id: '',
data_source_list: {},
icon_link: {},
is_rich_icon: '0',
is_up_down: '1',
icon_color: '#000',
icon_weight: 'normal',
icon_size: 12,
icon_option: 'none',
icon_location: 'left',
icon_padding: {
padding: 0,
padding_top: 0,
padding_bottom: 0,
padding_left: 0,
padding_right: 0,
},
icon_rotate: 0,
border_show: '0',
border_color: '#FF5D5D',
border_style: 'solid',
bg_radius: {
radius: 0,
radius_top_left: 0,
radius_top_right: 0,
radius_bottom_left: 0,
radius_bottom_right: 0,
},
border_size: 1,
com_bg: '',
bottom_up: '1',
}
// 判断两个矩形是否有交集或者被包裹
export const isRectangleIntersecting = (rect1: react1, rect2: react1) => {
// 矩形的格式为 { x, y, width, height }

View File

@ -66,7 +66,20 @@
.vdr-handle.vdr-handle-bm,
.vdr-handle.vdr-handle-br {
display: block !important;
z-index: 2;
z-index: 1;
}
}
:deep(.plug-in-show-tabs.vdr-handle-z-index.vdr-container) {
.vdr-handle.vdr-handle-tl,
.vdr-handle.vdr-handle-tr,
.vdr-handle.vdr-handle-tm,
.vdr-handle.vdr-handle-ml,
.vdr-handle.vdr-handle-mr,
.vdr-handle.vdr-handle-bl,
.vdr-handle.vdr-handle-bm,
.vdr-handle.vdr-handle-br {
display: block !important;
z-index: 0;
}
}
.plug-in-border {

View File

@ -41,7 +41,7 @@
<div class="w h" @mousedown.prevent="start_drag" @mousemove.prevent="move_drag" @mouseup.prevent="end_drag">
<DraggableContainer v-if="draggable_container" :reference-line-visible="true" :disabled="false" reference-line-color="#ddd" @selectstart.prevent @contextmenu.prevent @dragstart.prevent>
<!-- @mouseover="on_choose(index)" -->
<Vue3DraggableResizable v-for="(item, index) in diy_data" :key="item.id" v-model:w="item.com_data.com_width" v-model:h="item.com_data.com_height" :min-w="0" :min-h="0" :class="{ 'plug-in-show-tabs': item.show_tabs == '1'}" :init-w="item.com_data.com_width" :init-h="item.com_data.com_height" :x="item.location.x" :y="item.location.y" :parent="true" :draggable="is_draggable" @mousedown.stop="on_choose(index, item.show_tabs)" @click.stop="on_choose(index, item.show_tabs)" @drag-end="dragEndHandle($event, index)" @resizing="resizingHandle($event, item.key, index)" @resize-end="resizingHandle($event, item.key, index)">
<Vue3DraggableResizable v-for="(item, index) in diy_data" :key="item.id" v-model:w="item.com_data.com_width" v-model:h="item.com_data.com_height" :min-w="0" :min-h="0" :class="{ 'plug-in-show-tabs': item.show_tabs == '1', 'vdr-handle-z-index': item.com_data.bottom_up == '1'}" :init-w="item.com_data.com_width" :init-h="item.com_data.com_height" :x="item.location.x" :y="item.location.y" :parent="true" :draggable="is_draggable" @mousedown.stop="on_choose(index, item.show_tabs)" @click.stop="on_choose(index, item.show_tabs)" @drag-end="dragEndHandle($event, index)" @resizing="resizingHandle($event, item.key, index)" @resize-end="resizingHandle($event, item.key, index)">
<div v-if="item.show_tabs == '1'" class="plug-in-right" chosenClass="close">
<el-icon class="iconfont icon-del" @click.stop="del(index)" />
<el-icon class="iconfont icon-copy" @click.stop="copy(index)" />
@ -56,6 +56,9 @@
<template v-else-if="item.key == 'auxiliary-line'">
<model-lines :key="item.id" :value="item.com_data" :source-list="props.sourceList"></model-lines>
</template>
<template v-else-if="item.key == 'icon'">
<model-icon :key="item.id" :value="item.com_data" :source-list="props.sourceList"></model-icon>
</template>
</div>
</Vue3DraggableResizable>
</DraggableContainer>
@ -82,7 +85,7 @@
<script setup lang="ts">
import { cloneDeep, isEmpty } from 'lodash';
import { get_math } from '@/utils';
import { text_com_data, img_com_data, line_com_data, isRectangleIntersecting } from "./index-default";
import { text_com_data, img_com_data, line_com_data, icon_com_data, isRectangleIntersecting } from "./index-default";
//
const app = getCurrentInstance();
//#region
@ -115,6 +118,11 @@ const components = reactive([
name: '线条',
com_data: line_com_data,
},
{
key: 'icon',
name: '图标',
com_data: icon_com_data,
},
],
},
]);

View File

@ -11,6 +11,9 @@
<template v-else-if="item.key == 'auxiliary-line'">
<model-lines :key="item.com_data" :value="item.com_data" :source-list="form.data_source_content" :is-percentage="true"></model-lines>
</template>
<template v-else-if="item.key == 'icon'">
<model-icon :key="item.com_data" :value="item.com_data" :source-list="form.data_source_content" :is-percentage="true"></model-icon>
</template>
</div>
</div>
</div>

View File

@ -32,6 +32,9 @@
<template v-else-if="diy_data.key == 'auxiliary-line'">
<model-lines-style :key="key" v-model:height="center_height" :value="diy_data"></model-lines-style>
</template>
<template v-else-if="diy_data.key == 'icon'">
<model-icon-style :key="key" v-model:height="center_height" :value="diy_data"></model-icon-style>
</template>
<template v-else>
<div class="w h flex align-c bg-f">
<no-data></no-data>

View File

@ -6,7 +6,7 @@
<template v-if="theme == '6'">
<div :class="['flex-row align-c jc-sb ptb-15 mlr-10 gap-20', { 'br-b-e': index != list.length - 1 }]">
<div v-if="is_show('title')" :class="text_line" :style="trends_config('title')">{{ item.title }}</div>
<div v-if="is_show('price')" class="num nowrap" :style="`color: ${new_style.shop_price_color}`">
<div v-if="is_show('price') && !isEmpty(item.min_price)" class="num nowrap" :style="`color: ${new_style.shop_price_color}`">
<span class="identifying">{{ item.show_price_symbol }}</span
><span :style="trends_config('price')">{{ item.min_price }}</span>
<span v-if="is_show('price_unit')" class="identifying">{{ item.show_price_unit }}</span>
@ -31,12 +31,12 @@
</div>
<div v-if="!['3', '4', '5'].includes(form.theme)" class="flex-col gap-5 oh">
<div :class="[form.is_price_solo == '1' ? 'flex-row align-c nowrap' : 'flex-col gap-5']">
<div v-if="is_show('price')" class="num" :style="`color: ${new_style.shop_price_color}`">
<div v-if="is_show('price') && !isEmpty(item.min_price)" class="num" :style="`color: ${new_style.shop_price_color}`">
<span class="identifying">{{ item.show_price_symbol }}</span
><span :style="trends_config('price')">{{ item.min_price }}</span>
<span v-if="is_show('price_unit')" class="identifying">{{ item.show_price_unit }}</span>
</div>
<div v-if="show_content && is_show('original_price')" class="size-10 flex">
<div v-if="show_content && is_show('original_price') && !isEmpty(item.min_original_price)" class="size-10 flex">
<span class="original-price-left"></span
><span :class="['original-price text-line-1', { 'flex-1': form.is_price_solo == '1' }]"
>{{ item.show_original_price_symbol }}{{ item.min_original_price }}
@ -66,12 +66,12 @@
</div>
<div v-else class="flex-row align-c jc-sb">
<div class="flex-row align-c nowrap">
<div v-if="is_show('price')" class="num" :style="`color: ${new_style.shop_price_color}`">
<div v-if="is_show('price') && !isEmpty(item.min_price)" class="num" :style="`color: ${new_style.shop_price_color}`">
<span class="identifying">{{ item.show_price_symbol }}</span
><span :style="trends_config('price')">{{ item.min_price }}</span>
<span v-if="is_show('price_unit')" class="identifying">{{ item.show_price_unit }}</span>
</div>
<div v-if="show_content && is_show('original_price')" class="size-10 flex">
<div v-if="show_content && is_show('original_price') && !isEmpty(item.min_original_price)" class="size-10 flex">
<span class="original-price-left"></span
><span :class="['original-price text-line-1', { 'flex-1': form.is_price_solo == '1' }]"
>{{ item.show_original_price_symbol }}{{ item.min_original_price }}
@ -115,12 +115,12 @@
</div>
<div class="flex-row align-c jc-sb">
<div class="flex-row align-c nowrap">
<div v-if="is_show('price')" class="num" :style="`color: ${new_style.shop_price_color}`">
<div v-if="is_show('price') && !isEmpty(item.min_price)" class="num" :style="`color: ${new_style.shop_price_color}`">
<span class="identifying">{{ item.show_price_symbol }}</span
><span :style="trends_config('price')">{{ item.min_price }}</span>
<span v-if="is_show('price_unit')" class="identifying">{{ item.show_price_unit }}</span>
</div>
<div v-if="show_content && is_show('original_price')" class="size-10 flex">
<div v-if="show_content && is_show('original_price') && !isEmpty(item.min_original_price)" class="size-10 flex">
<span class="original-price-left"></span
><span :class="['original-price text-line-1', { 'flex-1': form.is_price_solo == '1' }]"
>{{ item.show_original_price_symbol }}{{ item.min_original_price }}

View File

@ -66,13 +66,13 @@
</div>
<div class="flex-row align-e gap-10 jc-sb">
<div class="flex-col gap-5">
<div v-if="is_show('price')" class="num" :style="`color: ${new_style.shop_price_color}`">
<div v-if="is_show('price') && !isEmpty(item.min_price)" class="num" :style="`color: ${new_style.shop_price_color}`">
<span v-if="form.shop_style_type == '1'" class="size-10 pr-4"></span>
<span class="identifying">{{ item.show_price_symbol }}</span
><span :style="trends_config('price')">{{ item.min_price }}</span>
<span v-if="is_show('price_unit')" class="identifying">{{ item.show_price_unit }}</span>
</div>
<div v-if="is_show('original_price')" class="size-11 flex" :style="`color: ${new_style.original_price_color}`">
<div v-if="is_show('original_price') && !isEmpty(item.min_original_price)" class="size-11 flex" :style="`color: ${new_style.original_price_color}`">
<span class="original-price text-line-1 flex-1"
>{{ item.show_original_price_symbol }}{{ item.min_original_price }}
<template v-if="is_show('original_price_unit')">
@ -127,13 +127,13 @@
</div>
<div class="flex-row align-e gap-10 jc-sb">
<div class="flex-col gap-5">
<div v-if="is_show('price')" class="num" :style="`color: ${new_style.shop_price_color}`">
<div v-if="is_show('price') && !isEmpty(item.min_price)" class="num" :style="`color: ${new_style.shop_price_color}`">
<span v-if="form.shop_style_type == '1'" class="size-10 pr-4"></span>
<span class="identifying">{{ item.show_price_symbol }}</span
><span :style="trends_config('price')">{{ item.min_price }}</span>
<span v-if="is_show('price_unit')" class="identifying">{{ item.show_price_unit }}</span>
</div>
<div v-if="is_show('original_price')" class="size-11 flex" :style="`color: ${new_style.original_price_color}`">
<div v-if="is_show('original_price') && !isEmpty(item.min_original_price)" class="size-11 flex" :style="`color: ${new_style.original_price_color}`">
<span class="original-price text-line-1 flex-1"
>{{ item.show_original_price_symbol }}{{ item.min_original_price }}
<template v-if="is_show('original_price_unit')">