商品和文章等的角标和轮播方式更新

master
于肖磊 2024-11-20 17:26:00 +08:00
parent d17c8e9962
commit f66c607da4
11 changed files with 456 additions and 183 deletions

2
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,2 @@
{
}

View File

@ -1369,4 +1369,27 @@ button[disabled].bg-grey {
word-break: break-all;
overflow-wrap: break-word;
word-wrap: break-word;
}
/* 指示器上下显示 */
.indicator_up_down_location {
position: absolute;
z-index: 1;
padding-top: 10px;
padding-bottom: 10px;
display: flex;
flex-direction: column;
}
.indicator_up_down_location .dot-item {
margin: 0.3rem 0;
}
/* 指示器左右显示 */
.indicator_about_location {
position: absolute;
z-index: 1;
padding-right: 10px;
padding-left: 10px;
display: flex;
}
.indicator_about_location .dot-item {
margin: 0 0.3rem;
}

View File

@ -12,6 +12,39 @@ const app = getApp();
export function is_obj_empty(obj) {
return Object.keys(obj).length === 0;
}
/**
* 处理指示器的显示问题
*
* @param style_object 样式对象
* @returns 返回对应的值
*/
export function get_indicator_style(style_object) {
const { indicator_radius, indicator_style, indicator_size, color, indicator_new_location } = style_object;
let styles = '';
if (!isEmpty(indicator_radius)) {
styles += radius_computer(indicator_radius);
}
// 数字类型的指示器
if (indicator_style == 'num') {
styles += `color: ${color || '#DDDDDD'};`;
styles += `font-size: ${indicator_size * 2}rpx;`;
} else if (indicator_style == 'elliptic') {
// 宽的指示器按照宽高1:3 来计算
styles += `background: ${color || '#DDDDDD'};`;
if (['left', 'right'].includes(indicator_new_location)) {
styles += `width: ${indicator_size * 2 }rpx; height: ${indicator_size * 6}rpx;`;
} else {
styles += `width: ${indicator_size * 6}rpx; height: ${indicator_size * 2}rpx;`;
}
} else {
// 圆点指示器
styles += `background: ${color || '#DDDDDD'};`;
styles += `width: ${indicator_size * 2}rpx; height: ${indicator_size * 2}rpx;`;
}
return styles;
}
/**
* 判断对象数组等是否为空
*/

View File

@ -7,12 +7,16 @@
<view v-for="(item, index) in data_list" :key="index" class="item oh" :style="article_style" :data-value="item.data.url" @tap="url_event">
<view :class="article_theme == '0' ? 'flex-row oh' : 'flex-col oh'" :style="article_img_style">
<template v-if="article_theme !== '3'">
<template v-if="item.new_cover.length > 0">
<image :src="item.new_cover[0].url" class="img" :style="img_radius + img_size" mode="aspectFill" />
</template>
<template v-else>
<image :src="item.data.cover" class="img" :style="img_radius + img_size" mode="aspectFill" />
</template>
<view class="oh pr wh-auto ht-auto">
<template v-if="item.new_cover.length > 0">
<image :src="item.new_cover[0].url" class="img" :style="img_radius + img_size" mode="aspectFill" />
</template>
<template v-else>
<image :src="item.data.cover" class="img" :style="img_radius + img_size" mode="aspectFill" />
</template>
<!-- 角标 -->
<subscriptIndex :propValue="propValue"></subscriptIndex>
</view>
</template>
<view class="jc-sb flex-1" :class="article_theme == '3' ? 'flex-row align-c' : 'flex-col'" :style="article_theme !== '0' ? content_padding : ''">
<div class="flex-col" :class="article_theme == '3' ? 'flex-1 flex-width' : ''" :style="'gap:' + name_desc_space + 'px;'">
@ -33,17 +37,21 @@
</view>
</view>
<view v-else class="oh" :class="article_theme_class">
<swiper class="swiper" circular :autoplay="is_roll ? true : false" :interval="interval_time" :style="'height:' + carousel_height_computer">
<swiper class="swiper" circular :autoplay="is_roll ? true : false" :interval="interval_time" :next-margin="next_margin" :display-multiple-items="slides_per_group" :style="'height:' + carousel_height_computer">
<swiper-item v-for="(item1, index1) in article_carousel_list" :key="index1">
<view class="flex-row" :style="article_spacing">
<view v-for="(item, index) in item1.carousel_list" :key="index" class="item oh" :style="article_style" :data-value="item.data.url" @tap="url_event">
<view class="oh flex-col" :style="article_img_style">
<template v-if="item.new_cover.length > 0">
<image :src="item.new_cover[0].url" class="img" :style="img_radius + article_item_height" mode="aspectFill" />
</template>
<template v-else>
<image :src="item.data.cover" class="img" :style="img_radius + article_item_height" mode="aspectFill" />
</template>
<view class="flex-row ht-auto" :style="article_spacing">
<view v-for="(item, index) in item1.carousel_list" :key="index" class="item oh ht-auto" :style="article_style" :data-value="item.data.url" @tap="url_event">
<view class="oh flex-col ht-auto" :style="article_img_style">
<view class="oh pr wh-auto ht-auto">
<template v-if="item.new_cover.length > 0">
<image :src="item.new_cover[0].url" class="img" :style="img_radius + 'height:100%;'" mode="aspectFill" />
</template>
<template v-else>
<image :src="item.data.cover" class="img" :style="img_radius + 'height:100%;'" mode="aspectFill" />
</template>
<!-- 角标 -->
<subscriptIndex :propValue="propValue"></subscriptIndex>
</view>
<view class="jc-sb flex-1 flex-col" :style="article_theme !== '0' ? content_padding : ''">
<div class="flex-col" :style="'gap:' + name_desc_space + 'px;'">
<div class="title text-line-2" :style="article_name + article_name_height_computer">{{ item.new_title ? item.new_title : item.data.title }}</div>
@ -73,9 +81,13 @@
<script>
const app = getApp();
import { common_styles_computer, common_img_computer, padding_computer, radius_computer, get_math, gradient_handle, background_computer } from '@/common/js/common/common.js';
import subscriptIndex from '@/components/diy/modules/subscript/index.vue';
var system = app.globalData.get_system_info(null, null, true);
var sys_width = app.globalData.window_width_handle(system.windowWidth);
export default {
components: {
subscriptIndex,
},
props: {
propValue: {
type: Object,
@ -127,7 +139,7 @@
content_spacing: '',
//
article_spacing: '',
article_item_height: '',
// article_item_height: '',
article_style: '',
article_img_style: '',
@ -147,6 +159,9 @@
article_carousel_list: [],
//
name_desc_space: 0,
//
slides_per_group: 1,
next_margin: '0rpx',
};
},
watch: {
@ -194,6 +209,9 @@
article_spacing: `gap: ${new_style.article_spacing}px;`,
//
name_desc_space: parseInt(new_style.name_desc_space),
next_margin: new_style.rolling_fashion == 'translation' ? '-' + new_style.article_spacing_margin + 'px' : '0rpx',
//
slides_per_group: new_style.rolling_fashion == 'translation' ? Number(new_content.carousel_col) + 1 : 1,
});
//
const product_style_list = [
@ -266,17 +284,17 @@
const temp_carousel_col = new_content.carousel_col || '1';
// (gap * gap) /
let gap = temp_carousel_col !== '0' ? (new_style.article_spacing * temp_carousel_col) / (Number(temp_carousel_col) + 1) : '0';
const multicolumn_columns_width = `width:calc(${100 / (Number(temp_carousel_col) + 1)}% - ${gap * 2}rpx);min-width:calc(${100 / (Number(temp_carousel_col) + 1)}% - ${gap * 2}rpx)`;
const multicolumn_columns_width = new_style.rolling_fashion == 'translation' ? `margin-right: ${ new_style.article_spacing }px;width:100%;` : `width:calc(${100 / (Number(temp_carousel_col) + 1)}% - ${gap * 2}rpx);min-width:calc(${100 / (Number(temp_carousel_col) + 1)}% - ${gap * 2}rpx);`;
//
this.setData({
//
interval_time: (new_style.interval_time || 2) * 1000,
//
is_roll: new_style.is_roll,
article_item_height: `height: ${new_style.article_height * 2}rpx`,
// article_item_height: `height: ${new_style.article_height }px`,
article_style: this.content_radius + multicolumn_columns_width + gradient,
//
carousel_height_computer: (new_style.name_size * 2 + new_style.article_height) * 2 + 'rpx',
carousel_height_computer: new_style.name_size * 2 + new_style.article_height + 'px',
//
article_name_height_computer: `height:${new_style.name_size * 2.4 * 2}rpx;line-height:${new_style.name_size * 1.2 * 2}rpx;`,
article_img_style: background_computer(article_data)
@ -284,26 +302,41 @@
//
const cloneList = JSON.parse(JSON.stringify(this.data_list));
//
if (cloneList.length > 0) {
//
const num = Number(temp_carousel_col) + 1;
console.log(new_style.rolling_fashion);
if (new_style.rolling_fashion != 'translation') {
if (cloneList.length > 0) {
//
const num = Number(temp_carousel_col) + 1;
//
let nav_list = [];
//
const split_num = Math.ceil(cloneList.length / num);
for (let i = 0; i < split_num; i++) {
nav_list.push({ carousel_list: cloneList.slice(i * num, (i + 1) * num) });
}
this.setData({
article_carousel_list: nav_list,
});
} else {
//
this.setData({
article_carousel_list: [{ carousel_list: cloneList }],
});
}
} else {
//
let nav_list = [];
//
const split_num = Math.ceil(cloneList.length / num);
for (let i = 0; i < split_num; i++) {
nav_list.push({ carousel_list: cloneList.slice(i * num, (i + 1) * num) });
}
cloneList.forEach((item) => {
nav_list.push({
carousel_list: [item],
});
});
this.setData({
article_carousel_list: nav_list,
});
} else {
//
this.setData({
article_carousel_list: [{ carousel_list: cloneList }],
});
}
}
if (this.propIsCommonStyle) {
this.setData({
style_container: common_styles_computer(new_style.common_style),

View File

@ -2,74 +2,29 @@
<view v-if="data_source_content_list.length > 0">
<view v-for="(item1, index1) in data_source_content_list" :key="index1" :style="style_container">
<view class="custom-container wh-auto ht-auto" :style="style_img_container">
<view class="wh-auto pr" :style="'height:' + form.height * scale + 'px;'">
<view v-for="(item, index) in form.custom_list" :key="item.id" class="main-content" :style="{ left: get_percentage_count(item.location.x, div_width), top: get_percentage_count(item.location.y, div_height), width: get_percentage_count(item.com_data.com_width, div_width), height: get_percentage_count(item.com_data.com_height, div_height), 'z-index': custom_list_length > 0 ? custom_list_length - index : 0 }">
<template v-if="item.key == 'text'">
<model-text :propKey="propKey" :propValue="item.com_data" :propScale="scale" :propSourceList="item1" :propSourceType="data_source" @url_event="url_event($event, index)"></model-text>
</template>
<template v-else-if="item.key == 'img'">
<model-image :propKey="propKey" :propValue="item.com_data" :propScale="scale" :propSourceList="item1" :propSourceType="data_source" @url_event="url_event($event, index)"></model-image>
</template>
<template v-else-if="item.key == 'auxiliary-line'">
<model-lines :propKey="propKey" :propValue="item.com_data" :propScale="scale" :propSourceList="item1" :propSourceType="data_source"></model-lines>
</template>
<template v-else-if="item.key == 'icon'">
<model-icon :propKey="propKey" :propValue="item.com_data" :propScale="scale" :propSourceList="item1" :propSourceType="data_source" @url_event="url_event($event, index)"></model-icon>
</template>
<template v-else-if="item.key == 'panel'">
<model-panel :propKey="propKey" :propValue="item.com_data" :propScale="scale" :propSourceList="item1" :propSourceType="data_source" @url_event="url_event($event, index)"></model-panel>
</template>
</view>
</view>
<dataRendering :propCustomList="form.custom_list" :propSourceList="item1" :propSourceType="form.data_source" :propDataHeight="form.height" :propScale="scale" :propDataIndex="index1" @url_event="url_event"></dataRendering>
</view>
</view>
</view>
<view v-else>
<view :style="style_container">
<view class="custom-container wh-auto ht-auto" :style="style_img_container">
<view class="wh-auto pr" :style="'height:' + form.height * scale + 'px;'">
<view v-for="(item, index) in form.custom_list" :key="item.id" class="main-content" :style="{ left: get_percentage_count(item.location.x, div_width), top: get_percentage_count(item.location.y, div_height), width: get_percentage_count(item.com_data.com_width, div_width), height: get_percentage_count(item.com_data.com_height, div_height), 'z-index': custom_list_length > 0 ? custom_list_length - index : 0 }">
<template v-if="item.key == 'text'">
<model-text :propKey="propKey" :propValue="item.com_data" :propScale="scale" @url_event="url_event"></model-text>
</template>
<template v-else-if="item.key == 'img'">
<model-image :propKey="propKey" :propValue="item.com_data" :propScale="scale" @url_event="url_event"></model-image>
</template>
<template v-else-if="item.key == 'auxiliary-line'">
<model-lines :propKey="propKey" :propValue="item.com_data" :propScale="scale"></model-lines>
</template>
<template v-else-if="item.key == 'icon'">
<model-icon :propKey="propKey" :propValue="item.com_data" :propScale="scale" @url_event="url_event"></model-icon>
</template>
<template v-else-if="item.key == 'panel'">
<model-panel :propKey="propKey" :propValue="item.com_data" :propScale="scale" @url_event="url_event"></model-panel>
</template>
</view>
</view>
<dataRendering :propCustomList="form.custom_list" :propDataHeight="form.height" :propScale="scale"></dataRendering>
</view>
</view>
</view>
</template>
<script>
import { common_styles_computer, common_img_computer, percentage_count } from '@/common/js/common/common.js';
import { common_styles_computer, common_img_computer, percentage_count, isEmpty } from '@/common/js/common/common.js';
const app = getApp();
import modelText from '@/components/diy/modules/custom/model-text.vue';
import modelLines from '@/components/diy/modules/custom/model-lines.vue';
import modelImage from '@/components/diy/modules/custom/model-image.vue';
import modelIcon from '@/components/diy/modules/custom/model-icon.vue';
import modelPanel from '@/components/diy/modules/custom/model-panel.vue';
import { isEmpty } from '../../common/js/common/common';
import dataRendering from '@/components/diy/modules/custom/data-rendering.vue';
var system = app.globalData.get_system_info(null, null, true);
var sys_width = app.globalData.window_width_handle(system.windowWidth);
export default {
components: {
modelText,
modelLines,
modelImage,
modelIcon,
modelPanel,
dataRendering
},
props: {
propValue: {
@ -172,13 +127,6 @@ import { isEmpty } from '../../common/js/common/common';
data_source: '',
};
},
computed: {
get_percentage_count() {
return (num, container_size) => {
return num * this.scale + 'px';
};
},
},
watch: {
propKey(val) {
//
@ -239,8 +187,9 @@ import { isEmpty } from '../../common/js/common/common';
data_source: !isEmpty(new_form.data_source)? new_form.data_source : '',
});
},
url_event(e, index = 0) {
if (this.data_source == 'goods') {
url_event(e) {
if (this.data_source == 'goods' && this.data_source_content_list.length > 0) {
const index = e.currentTarget.dataset.index;
const list = this.data_source_content_list[index];
if (!isEmpty(list)) {
app.globalData.goods_data_cache_handle(list.data.id, list.data);

View File

@ -17,11 +17,15 @@
</block>
<block v-else>
<block v-if="!isEmpty(item)">
<view v-if="!isEmpty(item.new_cover)" :style="img_size">
<imageEmpty :propImageSrc="item.new_cover[0]" :propStyle="content_img_radius" propErrorStyle="width: 100rpx;height: 100rpx;"></imageEmpty>
</view>
<view v-else :style="img_size">
<imageEmpty :propImageSrc="item.images" :propStyle="content_img_radius" propErrorStyle="width: 100rpx;height: 100rpx;"></imageEmpty>
<view class="oh re" :class="img_size">
<view v-if="!isEmpty(item.new_cover)" :style="img_size">
<imageEmpty :propImageSrc="item.new_cover[0]" :propStyle="content_img_radius" propErrorStyle="width: 100rpx;height: 100rpx;"></imageEmpty>
</view>
<view v-else :style="img_size">
<imageEmpty :propImageSrc="item.images" :propStyle="content_img_radius" propErrorStyle="width: 100rpx;height: 100rpx;"></imageEmpty>
</view>
<!-- 角标 -->
<subscriptIndex :propValue="propValue"></subscriptIndex>
</view>
</block>
<view v-if="is_show('title') || is_show('simple_desc') || is_show('price') || is_show('original_price') || is_show('sales_count') || is_show('plugins_view_icon') || form.is_shop_show == '1'" class="flex-col flex-1 jc-sb content gap-10" :style="content_style">
@ -107,17 +111,21 @@
</view>
</block>
<block v-else>
<swiper circular="true" :autoplay="new_style.is_roll == '1'" :interval="new_style.interval_time * 1000" :duration="500" :style="{ width: '100%', height: new_style.content_outer_height * 2 + 'rpx' }">
<swiper circular="true" :autoplay="new_style.is_roll == '1'" :interval="new_style.interval_time * 1000" :duration="500" :next-margin="new_style.rolling_fashion == 'translation' ? '-' + content_outer_spacing_magin : '0rpx'" :display-multiple-items="slides_per_group" :style="{ width: '100%', height: new_style.content_outer_height * 2 + 'rpx' }">
<swiper-item v-for="(item1, index1) in shop_content_list" :key="index1">
<view class="flex-row" :style="onter_style">
<view class="flex-row wh-auto ht-auto" :style="onter_style">
<view v-for="(item, index) in item1.split_list" :key="index" class="pr oh" :style="layout_style" :data-index="index1" :data-split-index="index" :data-value="item.goods_url" @tap.stop="url_event">
<view :class="layout_type" :style="layout_img_style">
<block v-if="!isEmpty(item)">
<view v-if="!isEmpty(item.new_cover)" :class="'flex-img' + theme">
<imageEmpty :propImageSrc="item.new_cover[0]" :propStyle="content_img_radius" propErrorStyle="width: 100rpx;height: 100rpx;"></imageEmpty>
</view>
<view v-else :class="'flex-img' + theme">
<imageEmpty :propImageSrc="item.images" :propStyle="content_img_radius" propErrorStyle="width: 100rpx;height: 100rpx;"></imageEmpty>
<view class="oh re" :class="'flex-img' + theme">
<view v-if="!isEmpty(item.new_cover)" :class="'flex-img' + theme">
<imageEmpty :propImageSrc="item.new_cover[0]" :propStyle="content_img_radius" propErrorStyle="width: 100rpx;height: 100rpx;"></imageEmpty>
</view>
<view v-else :class="'flex-img' + theme">
<imageEmpty :propImageSrc="item.images" :propStyle="content_img_radius" propErrorStyle="width: 100rpx;height: 100rpx;"></imageEmpty>
</view>
<!-- 角标 -->
<subscriptIndex :propValue="propValue"></subscriptIndex>
</view>
</block>
<view v-if="is_show('title') || is_show('simple_desc') || is_show('price') || is_show('plugins_view_icon') || is_show('original_price') || form.is_shop_show == '1'" class="flex-col flex-1 jc-sb content gap-10" :style="content_style">
@ -175,6 +183,7 @@
const app = getApp();
import { isEmpty, common_styles_computer, common_img_computer, gradient_handle, padding_computer, radius_computer, background_computer } from '@/common/js/common/common.js';
import imageEmpty from '@/components/diy/modules/image-empty.vue';
import subscriptIndex from '@/components/diy/modules/subscript/index.vue';
import componentBadge from '@/components/badge/badge';
var system = app.globalData.get_system_info(null, null, true);
var sys_width = app.globalData.window_width_handle(system.windowWidth);
@ -182,6 +191,7 @@
components: {
imageEmpty,
componentBadge,
subscriptIndex
},
props: {
propValue: {
@ -217,6 +227,7 @@
content_padding: '', //
theme: '', //
content_outer_spacing: '', //
content_outer_spacing_magin: '', //
//
outer_class: '',
onter_style: '',
@ -230,6 +241,7 @@
style_container: '', //
style_img_container: '',
shop_content_list: [],
slides_per_group: 1,
//
title_style: '',
price_style: '',
@ -325,6 +337,7 @@
content_padding: padding_computer(new_style.shop_padding) + 'box-sizing: border-box;', //
theme: new_form.theme, //
content_outer_spacing: new_style.content_outer_spacing, //
content_outer_spacing_magin: new_style.content_outer_spacing * 2 + 'rpx',
onter_style: new_form.theme == '6' ? radius_computer(new_style.shop_radius) : `gap: ${new_style.content_outer_spacing * 2 + 'rpx'};`,
//
layout_type: ['0', '4'].includes(new_form.theme) ? 'flex-row wh-auto ht-auto oh' : 'flex-col wh-auto ht-auto oh',
@ -343,35 +356,47 @@
score_style: this.trends_config(new_style, 'score'),
button_style: this.trends_config(new_style, 'button', 'buy_button') + button_gradient,
simple_desc: this.trends_config(new_style, 'simple_desc', 'desc'),
shop_content_list: this.get_shop_content_list(new_list, new_form),
shop_content_list: this.get_shop_content_list(new_list, new_form, new_style),
slides_per_group: new_style.rolling_fashion == 'translation' ? new_form.carousel_col : 1,
img_size: img_style,
});
}
},
get_shop_content_list(list, form) {
get_shop_content_list(list, form, new_style) {
//
const cloneList = JSON.parse(JSON.stringify(list));
//
if (cloneList.length > 0) {
//
const num = form.carousel_col;
if (new_style.rolling_fashion != 'translation') {
//
if (cloneList.length > 0) {
//
const num = form.carousel_col;
//
let nav_list = [];
//
const split_num = Math.ceil(cloneList.length / num);
for (let i = 0; i < split_num; i++) {
nav_list.push({
split_list: cloneList.slice(i * num, (i + 1) * num),
});
}
return nav_list;
} else {
//
return [
{
split_list: cloneList,
},
];
}
} else {
//
let nav_list = [];
//
const split_num = Math.ceil(cloneList.length / num);
for (let i = 0; i < split_num; i++) {
cloneList.forEach((item) => {
nav_list.push({
split_list: cloneList.slice(i * num, (i + 1) * num),
split_list: [item],
});
}
});
return nav_list;
} else {
//
return [
{
split_list: cloneList,
},
];
}
},
get_text_line(form) {
@ -388,12 +413,17 @@
const radius = form.theme == '6' ? '' : radius_computer(new_style.shop_radius);
const gradient = form.theme != '6' ? gradient_handle(new_style?.shop_color_list || [], new_style?.shop_direction || '') : '';
let size_style = ``;
if (['1', '4'].includes(form.theme)) {
size_style = `width: calc((100% - ${new_style.content_outer_spacing * 2 + 'rpx'}) / 2);`;
} else if (form.theme == '3') {
size_style = `width: calc((100% - ${new_style.content_outer_spacing * 4 + 'rpx'}) / 3);`;
} else if (form.theme == '5') {
size_style = `width: ${this.get_multicolumn_columns_width(new_style, form)};min-width: ${this.get_multicolumn_columns_width(new_style, form)};height: ${new_style.content_outer_height * 2 + 'rpx'};`;
//
if (new_style.rolling_fashion != 'translation') {
if (['1', '4'].includes(form.theme)) {
size_style = `width: calc((100% - ${new_style.content_outer_spacing * 2 + 'rpx'}) / 2);`;
} else if (form.theme == '3') {
size_style = `width: calc((100% - ${new_style.content_outer_spacing * 4 + 'rpx'}) / 3);`;
} else if (form.theme == '5') {
size_style = `width: ${this.get_multicolumn_columns_width(new_style, form)};min-width: ${this.get_multicolumn_columns_width(new_style, form)};height: ${new_style.content_outer_height * 2 + 'rpx'};`;
}
} else {
size_style = `margin-right: ${ new_style.content_outer_spacing * 2 }rpx;width: 100%;height: 100%;`;
}
return `${radius} ${size_style} ${ gradient }`;
},

View File

@ -0,0 +1,85 @@
<template>
<view class="wh-auto pr" :style="'height:' + propDataHeight * propScale + 'px;'">
<view v-for="(item, index) in propCustomList" :key="item.id" class="main-content"
:style="{ left: get_percentage_count(item.location.x), top: get_percentage_count(item.location.y), width: get_percentage_count(item.com_data.com_width), height: get_percentage_count(item.com_data.com_height), 'z-index': propCustomList.length - 1 > 0 ? (propCustomList.length - 1) - index : 0 }">
<template v-if="item.key == 'text'">
<model-text :propKey="item.id" :propValue="item.com_data" :propScale="propScale" :propSourceList="propSourceList" :propSourceType="propSourceType" :data-index="propDataIndex" @url_event="url_event"></model-text>
</template>
<template v-else-if="item.key == 'img'">
<model-image :propKey="item.id" :propValue="item.com_data" :propScale="propScale" :propSourceList="propSourceList" :propSourceType="propSourceType" :data-index="propDataIndex" @url_event="url_event"></model-image>
</template>
<template v-else-if="item.key == 'auxiliary-line'">
<model-lines :propKey="item.id" :propValue="item.com_data" :propScale="propScale" :propSourceList="propSourceList" :propSourceType="propSourceType"></model-lines>
</template>
<template v-else-if="item.key == 'icon'">
<model-icon :propKey="item.id" :propValue="item.com_data" :propScale="propScale" :propSourceList="propSourceList" :propSourceType="propSourceType" :data-index="propDataIndex" @url_event="url_event"></model-icon>
</template>
<template v-else-if="item.key == 'panel'">
<model-panel :propKey="item.id" :propValue="item.com_data" :propScale="propScale" :propSourceList="propSourceList" :propSourceType="propSourceType" :data-index="propDataIndex" @url_event="url_event"></model-panel>
</template>
</view>
</view>
</template>
<script>
import modelText from '@/components/diy/modules/custom/model-text.vue';
import modelLines from '@/components/diy/modules/custom/model-lines.vue';
import modelImage from '@/components/diy/modules/custom/model-image.vue';
import modelIcon from '@/components/diy/modules/custom/model-icon.vue';
import modelPanel from '@/components/diy/modules/custom/model-panel.vue';
export default {
components: {
modelText,
modelLines,
modelImage,
modelIcon,
modelPanel,
},
props: {
propCustomList: {
type: Array,
default: () => {
return [];
},
required: true,
},
propSourceList: {
type: Object,
default: () => {
return {};
}
},
propSourceType: {
type: String,
default: ''
},
propDataHeight: {
type: Number,
default: 0,
},
propScale: {
type: Number,
default: 1,
},
propDataIndex: {
type: Number,
default: 1,
}
},
data() {
return {};
},
computed: {
get_percentage_count() {
return (num) => {
return num * this.propScale + 'px';
};
},
},
methods: {
url_event(e) {
this.$emit('url_event', e);
}
},
};
</script>

View File

@ -4,8 +4,7 @@
</view>
</template>
<script>
import { radius_computer, padding_computer, gradient_handle } from '@/common/js/common/common.js';
import { isEmpty } from '../../../../common/js/common/common';
import { radius_computer, padding_computer, gradient_handle, isEmpty } from '@/common/js/common/common.js';
export default {
props: {

View File

@ -8,7 +8,7 @@
</template>
<script>
import { padding_computer } from '@/common/js/common/common.js';
import { padding_computer, radius_computer } from '@/common/js/common/common.js';
export default {
props: {
propValue: {
@ -38,7 +38,7 @@
this.setData({
video_img: new_content.video_img.length > 0 ? new_content.video_img[0].url : '',
video: new_content.video.length > 0 ? new_content.video[0].url : '',
style_container: padding_computer(this.propDataStyle.chunk_padding) + 'box-sizing: border-box;',
style_container: padding_computer(this.propDataStyle.chunk_padding) + radius_computer(this.propDataStyle.img_radius) + 'box-sizing: border-box;',
});
}
},

View File

@ -0,0 +1,93 @@
<template>
<view v-if="form.seckill_subscript_show == '1'" class="corner-marker" :style="corner_marker">
<view class="flex-row nowrap" :style="corner_img_marker">
<template v-if="form.subscript_type == 'img-icon'">
<template v-if="!isEmpty(form.subscript_img_src)">
<image :src="form.subscript_img_src[0].url" mode="aspectFill" :style="img_style" />
</template>
<template v-else>
<iconfont :name="'icon-' + form.subscript_icon_class" propContainerDisplay="flex" :size="new_style.subscript_style.text_or_icon_size * 2 + 'rpx'" :color="new_style.subscript_style.text_or_icon_color"></iconfont>
</template>
</template>
<template v-else>
<span class="text-line-1" :style="text_size">{{ form.subscript_text }}</span>
</template>
</view>
</view>
</template>
<script>
import { common_img_computer, common_styles_computer, isEmpty } from '@/common/js/common/common.js';
import iconfont from '@/components/iconfont/iconfont';
export default {
components: {
iconfont,
},
props: {
propValue: {
type: Object,
default: () => ({}),
},
},
data() {
return {
form: {},
new_style: {},
corner_img_marker: '',
img_style: '',
text_size: '',
};
},
created() {
this.init();
},
methods: {
isEmpty,
//
init() {
if (!isEmpty(this.propValue) && !isEmpty(this.propValue.style.subscript_style)) {
const new_content = this.propValue.content || {};
const new_style = this.propValue.style || {};
//
this.setData({
form: new_content,
new_style: new_style,
corner_marker: this.get_corner_marker(new_style),
text_size: `font-size: ${ new_style.subscript_style.text_or_icon_size * 2 }rpx;color: ${ new_style.subscript_style.text_or_icon_color };`,
corner_img_marker: common_img_computer(new_style.subscript_style),
img_style: `height: ${new_style.subscript_style.img_height * 2}rpx; width: ${new_style.subscript_style.img_width * 2}rpx`,
});
}
},
get_corner_marker(new_style) {
const { subscript_style } = new_style;
let location = common_styles_computer(subscript_style);
//
const { seckill_subscript_location, top_or_bottom_spacing, left_or_right_spacing } = subscript_style;
// 线
if (seckill_subscript_location == 'top-left') {
location += `top: ${ top_or_bottom_spacing }px;left: ${ left_or_right_spacing }px;`;
} else if (seckill_subscript_location == 'top-center') {
location += 'top: 0;left: 50%;transform: translateX(-50%);';
} else if (seckill_subscript_location == 'top-right') {
location += `top: ${ top_or_bottom_spacing }px;right:${ left_or_right_spacing }px;`;
} else if (seckill_subscript_location == 'bottom-left') {
location += `bottom: ${ top_or_bottom_spacing }px;left: ${ left_or_right_spacing }px;`;
} else if (seckill_subscript_location == 'bottom-center') {
location += 'bottom: 0;left: 50%;transform: translateX(-50%);';
} else if (seckill_subscript_location == 'bottom-right') {
location += `bottom: ${ top_or_bottom_spacing }px;right: ${ left_or_right_spacing }px;`;
}
return location;
},
},
};
</script>
<style>
.corner-marker {
position: absolute;
max-width: 100%;
}
</style>

View File

@ -1,23 +1,23 @@
<template>
<view :style="style_container">
<view :style="style_img_container">
<swiper circular="true" :autoplay="new_style.is_roll == '1'" :interval="new_style.interval_time * 1000" :duration="500" :style="{ height: new_height }" @change="slideChange">
<swiper-item v-for="(item, index) in nav_content_list" :key="index">
<view class="flex-row align-c wh-auto ht-auto">
<view class="banner-img flex-row flex-wrap wh-auto" :class="'banner-img-' + propKey" :style="space">
<view v-for="(item1, index1) in item.split_list" :key="index1" class="flex-col gap-10 align-c" :style="group_width + nav_title_space" :data-value="item1.link.page" @tap="url_open_event">
<view v-if="['image_with_text', 'image'].includes(nav_style)" class="flex-row align-c jc-c">
<view class="top-img" :style="img_size">
<imageEmpty :propImageSrc="item1.img[0]" :propStyle="img_style" propErrorStyle="width: 60rpx;height: 60rpx;"></imageEmpty>
</view>
<view class="pr" :style="style_img_container">
<swiper circular="true" :autoplay="new_style.is_roll == '1'" :interval="new_style.interval_time * 1000" :duration="500" :display-multiple-items="slides_per_group" :style="{ height: new_height }" @change="slideChange">
<swiper-item v-for="(item, index) in nav_content_list" :key="index" class="swiper-item">
<view class="banner-img flex-row flex-wrap wh-auto" :class="'banner-img-' + propKey" :style="space">
<view v-for="(item1, index1) in item.split_list" :key="index1" class="flex-col gap-10 align-c" :style="group_width + nav_title_space" :data-value="item1.link.page" @tap="url_open_event">
<view v-if="['image_with_text', 'image'].includes(nav_style)" class="flex-row align-c jc-c pr">
<view class="top-img" :style="img_size">
<imageEmpty :propImageSrc="item1.img[0]" :propStyle="img_style" propErrorStyle="width: 60rpx;height: 60rpx;"></imageEmpty>
</view>
<view v-if="['image_with_text', 'text'].includes(nav_style)" class="wh-auto size-12 ma-0 nowrap oh tc" :style="text_style">{{ item1.title }}</view>
<!-- 角标 -->
<subscriptIndex :propValue="propValue"></subscriptIndex>
</view>
<view v-if="['image_with_text', 'text'].includes(nav_style)" class="wh-auto size-12 ma-0 nowrap oh tc" :style="text_style">{{ item1.title }}</view>
</view>
</view>
</swiper-item>
</swiper>
<view v-if="form.display_style == 'slide' && new_style.is_show == '1'" :style="{ 'justify-content': new_style.indicator_location || 'center' }" class="dot flex-row">
<view v-if="form.display_style == 'slide' && new_style.is_show == '1'" :class="['left', 'right'].includes(new_style.indicator_new_location) ? 'indicator_up_down_location' : 'indicator_about_location'" :style="indicator_location_style">
<block v-if="new_style.indicator_style == 'num'">
<view :style="indicator_style" class="dot-item">
<text :style="{ color: new_style.actived_color }">{{ actived_index + 1 }}</text>
@ -34,11 +34,13 @@
<script>
const app = getApp();
import { isEmpty, common_styles_computer, common_img_computer, radius_computer } from '@/common/js/common/common.js';
import { isEmpty, common_styles_computer, common_img_computer, radius_computer, get_indicator_style } from '@/common/js/common/common.js';
import imageEmpty from '@/components/diy/modules/image-empty.vue';
import subscriptIndex from '@/components/diy/modules/subscript/index.vue';
export default {
components: {
imageEmpty,
subscriptIndex,
},
props: {
propValue: {
@ -73,6 +75,8 @@
nav_title_space: 'row-gap:20rpx', //
space: 'row-gap:20rpx', //
img_size: '72rpx',
slides_per_group: 1,
indicator_location_style: '',
};
},
watch: {
@ -88,6 +92,19 @@
init() {
const new_content = this.propValue.content;
const new_style = this.propValue.style;
let group = 1;
let group_width = `width: ${100 / (new_content.single_line || 4)}%;`;
//
if (new_content?.display_style == 'slide') {
if (new_content.row == 1 && new_style.rolling_fashion == 'translation') {
group = new_content.single_line || 4;
group_width = 'width: 100%;';
} else {
group = 1;
group_width = `width: ${100 / (new_content.single_line || 4)}%;`;
}
}
this.setData({
form: new_content,
new_style: new_style,
@ -95,14 +112,16 @@
style_img_container: common_img_computer(new_style.common_style, this.propIndex),
img_style: radius_computer(new_style), //
text_style: `font-size: ${new_style.title_size * 2 || 24}rpx; color: ${new_style.title_color || '#000'};`, //
indicator_style: this.get_indicator_style(new_style), //
indicator_style: get_indicator_style(new_style), //
actived_color: new_style.actived_color || '#2A94FF', //
group_width: `width: ${100 / (new_content.single_line || 4)}%;`, //
slides_per_group: group, //
group_width: group_width, //
nav_title_space: 'row-gap:' + (new_style.title_space || 0) * 2 + 'rpx', //
space: 'row-gap:' + (new_style.space || 0) * 2 + 'rpx', //
img_size: 'width:' + (new_style.img_size || 0) * 2 + 'rpx;height:' + (new_style.img_size || 0) * 2 + 'rpx;', //
nav_style: new_content.nav_style || 'image_with_text', //
nav_content_list: this.get_nav_content_list(new_content),
nav_content_list: this.get_nav_content_list(new_content, new_style),
indicator_location_style: this.get_indicator_location_style(new_style),
});
setTimeout(() => {
const query = uni.createSelectorQuery().in(this);
@ -120,23 +139,33 @@
.exec(); //
}, 50);
},
get_nav_content_list(data) {
get_nav_content_list(data, new_style) {
//
const list = JSON.parse(JSON.stringify(data.nav_content_list || Array(4)));
//
if (list.length > 0 && data.display_style == 'slide') {
//
let nav_list = [];
//
const num = (data.single_line || 4) * (data.row || 1);
//
const split_num = Math.ceil(list.length / num);
for (let i = 0; i < split_num; i++) {
nav_list.push({
split_list: list.slice(i * num, (i + 1) * num),
if (data.row == 1 && new_style.rolling_fashion == 'translation') {
//
list.forEach((item) => {
nav_list.push({
split_list: [item],
});
});
return nav_list;
} else {
//
const num = (data.single_line || 4) * (data.row || 1);
//
const split_num = Math.ceil(list.length / num);
for (let i = 0; i < split_num; i++) {
nav_list.push({
split_list: list.slice(i * num, (i + 1) * num),
});
}
return nav_list;
}
return nav_list;
} else {
//
return [
@ -146,25 +175,29 @@
];
}
},
get_indicator_style(data) {
const { indicator_radius, indicator_style, indicator_size, color } = data;
//
get_indicator_location_style(new_style) {
const { indicator_new_location, indicator_location, indicator_bottom } = new_style;
let styles = '';
if (!isEmpty(indicator_radius)) {
styles += radius_computer(indicator_radius);
}
//
if (indicator_style == 'num') {
styles += `color: ${color || '#DDDDDD'};`;
styles += `font-size: ${indicator_size * 2}rpx;`;
} else if (indicator_style == 'elliptic') {
// 1:3
styles += `background: ${color || '#DDDDDD'};`;
styles += `width: ${indicator_size * 6}rpx; height: ${indicator_size * 2}rpx;`;
if (['left', 'right'].includes(indicator_new_location)) {
if (indicator_location == 'flex-start') {
styles += `top: 0px;`;
} else if (indicator_location == 'center') {
styles += `top: 50%; transform: translateY(-50%);`;
} else {
styles += `bottom: 0px;`;
}
} else {
//
styles += `background: ${color || '#DDDDDD'};`;
styles += `width: ${indicator_size * 2}rpx; height: ${indicator_size * 2}rpx;`;
if (indicator_location == 'flex-start') {
styles += `left: 0px;`;
} else if (indicator_location == 'center') {
styles += `left: 50%; transform: translateX(-50%);`;
} else {
styles += `right: 0px;`;
}
}
// 使
styles += `${ !isEmpty(indicator_new_location) ? `${indicator_new_location}: ${ indicator_bottom }px;` : `bottom: ${ indicator_bottom }px;` }`;
return styles;
},
slideChange(e) {
@ -185,17 +218,10 @@
width: 72rpx;
border-radius: 8rpx;
}
.dot {
margin-top: 20rpx;
margin-bottom: 8rpx;
}
.dot .dot-item {
margin: 0 6rpx;
}
.gap-x-10 {
row-gap: 20rpx;
}
::v-deep .uni-swiper-wrapper, ::v-deep .swiper-item {
overflow: unset !important;
}
</style>