mirror of
				https://gitee.com/hhyykk/ipms-sjy-ui.git
				synced 2025-11-04 20:28:45 +08:00 
			
		
		
		
	营销:适配商城装修组件【轮播图】
This commit is contained in:
		@@ -1,27 +1,30 @@
 | 
			
		||||
import { DiyComponent } from '@/components/DiyEditor/util'
 | 
			
		||||
import { ComponentStyle, DiyComponent } from '@/components/DiyEditor/util'
 | 
			
		||||
 | 
			
		||||
/** 轮播图属性 */
 | 
			
		||||
export interface CarouselProperty {
 | 
			
		||||
  // 选择模板
 | 
			
		||||
  swiperType: number
 | 
			
		||||
  // 图片圆角
 | 
			
		||||
  borderRadius: number
 | 
			
		||||
  // 页面边距
 | 
			
		||||
  pageMargin: number
 | 
			
		||||
  // 图片边距
 | 
			
		||||
  imageMargin: number
 | 
			
		||||
  // 分页类型
 | 
			
		||||
  pagingType: 'bullets' | 'fraction' | 'progressbar'
 | 
			
		||||
  // 一行个数
 | 
			
		||||
  rowIndividual: number
 | 
			
		||||
  // 添加图片
 | 
			
		||||
  // 类型:默认 | 卡片
 | 
			
		||||
  type: 'default' | 'card'
 | 
			
		||||
  // 指示器样式:点 | 数字
 | 
			
		||||
  indicator: 'dot' | 'number'
 | 
			
		||||
  // 是否自动播放
 | 
			
		||||
  autoplay: boolean
 | 
			
		||||
  // 播放间隔
 | 
			
		||||
  interval: number
 | 
			
		||||
  // 轮播内容
 | 
			
		||||
  items: CarouselItemProperty[]
 | 
			
		||||
  // 组件样式
 | 
			
		||||
  style: ComponentStyle
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 轮播内容属性
 | 
			
		||||
export interface CarouselItemProperty {
 | 
			
		||||
  title: string
 | 
			
		||||
  // 类型:图片 | 视频
 | 
			
		||||
  type: 'img' | 'video'
 | 
			
		||||
  // 图片链接
 | 
			
		||||
  imgUrl: string
 | 
			
		||||
  link: string
 | 
			
		||||
  // 视频链接
 | 
			
		||||
  videoUrl: string
 | 
			
		||||
  // 跳转链接
 | 
			
		||||
  url: string
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 定义组件
 | 
			
		||||
@@ -30,15 +33,18 @@ export const component = {
 | 
			
		||||
  name: '轮播图',
 | 
			
		||||
  icon: 'system-uicons:carousel',
 | 
			
		||||
  property: {
 | 
			
		||||
    swiperType: 0, // 选择模板
 | 
			
		||||
    borderRadius: 0, // 图片圆角
 | 
			
		||||
    pageMargin: 0, // 页面边距
 | 
			
		||||
    imageMargin: 0, // 图片边距
 | 
			
		||||
    pagingType: 'bullets', // 分页类型
 | 
			
		||||
    rowIndividual: 2, // 一行个数
 | 
			
		||||
    type: 'default',
 | 
			
		||||
    indicator: 'dot',
 | 
			
		||||
    autoplay: false,
 | 
			
		||||
    interval: 3,
 | 
			
		||||
    items: [
 | 
			
		||||
      { imgUrl: 'https://static.iocoder.cn/mall/banner-01.jpg' },
 | 
			
		||||
      { imgUrl: 'https://static.iocoder.cn/mall/banner-02.jpg' }
 | 
			
		||||
    ] as CarouselItemProperty[]
 | 
			
		||||
      { type: 'img', imgUrl: 'https://static.iocoder.cn/mall/banner-01.jpg', videoUrl: '' },
 | 
			
		||||
      { type: 'img', imgUrl: 'https://static.iocoder.cn/mall/banner-02.jpg', videoUrl: '' }
 | 
			
		||||
    ] as CarouselItemProperty[],
 | 
			
		||||
    style: {
 | 
			
		||||
      bgType: 'color',
 | 
			
		||||
      bgColor: '#fff',
 | 
			
		||||
      marginBottom: 8
 | 
			
		||||
    } as ComponentStyle
 | 
			
		||||
  }
 | 
			
		||||
} as DiyComponent<CarouselProperty>
 | 
			
		||||
 
 | 
			
		||||
@@ -6,70 +6,38 @@
 | 
			
		||||
  >
 | 
			
		||||
    <Icon icon="tdesign:image" class="text-gray-8 text-120px!" />
 | 
			
		||||
  </div>
 | 
			
		||||
  <!-- 一行一个 -->
 | 
			
		||||
  <div
 | 
			
		||||
    v-if="property.swiperType === 0"
 | 
			
		||||
    class="flex flex-col"
 | 
			
		||||
    :style="{
 | 
			
		||||
      paddingLeft: property.pageMargin + 'px',
 | 
			
		||||
      paddingRight: property.pageMargin + 'px'
 | 
			
		||||
    }"
 | 
			
		||||
  >
 | 
			
		||||
    <div v-for="(item, index) in property.items" :key="index">
 | 
			
		||||
      <div
 | 
			
		||||
        class="img-item"
 | 
			
		||||
        :style="{
 | 
			
		||||
          marginBottom: property.imageMargin + 'px',
 | 
			
		||||
          borderRadius: property.borderRadius + 'px'
 | 
			
		||||
        }"
 | 
			
		||||
      >
 | 
			
		||||
        <img alt="" :src="item.imgUrl" />
 | 
			
		||||
        <div v-if="item.title" class="title">{{ item.title }}</div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </div>
 | 
			
		||||
  <div v-else class="relative">
 | 
			
		||||
    <el-carousel
 | 
			
		||||
      height="174px"
 | 
			
		||||
      :type="property.type === 'card' ? 'card' : ''"
 | 
			
		||||
      :autoplay="property.autoplay"
 | 
			
		||||
      :interval="property.interval * 1000"
 | 
			
		||||
      :indicator-position="property.indicator === 'number' ? 'none' : undefined"
 | 
			
		||||
      @change="handleIndexChange"
 | 
			
		||||
    >
 | 
			
		||||
      <el-carousel-item v-for="(item, index) in property.items" :key="index">
 | 
			
		||||
        <el-image class="h-full w-full" :src="item.imgUrl" />
 | 
			
		||||
      </el-carousel-item>
 | 
			
		||||
    </el-carousel>
 | 
			
		||||
    <div
 | 
			
		||||
      v-if="property.indicator === 'number'"
 | 
			
		||||
      class="absolute p-y-2px bottom-10px right-10px rounded-xl bg-black p-x-8px text-10px text-white opacity-40"
 | 
			
		||||
      >{{ currentIndex }} / {{ property.items.length }}</div
 | 
			
		||||
    >
 | 
			
		||||
  </div>
 | 
			
		||||
  <el-carousel height="174px" v-else :type="property.swiperType === 3 ? 'card' : ''">
 | 
			
		||||
    <el-carousel-item v-for="(item, index) in property.items" :key="index">
 | 
			
		||||
      <div class="img-item" :style="{ borderRadius: property.borderRadius + 'px' }">
 | 
			
		||||
        <img alt="" :src="item.imgUrl" />
 | 
			
		||||
        <div v-if="item.title" class="title">{{ item.title }}</div>
 | 
			
		||||
      </div>
 | 
			
		||||
    </el-carousel-item>
 | 
			
		||||
  </el-carousel>
 | 
			
		||||
</template>
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
import { CarouselProperty } from './config'
 | 
			
		||||
 | 
			
		||||
/** 页面顶部导航栏 */
 | 
			
		||||
defineOptions({ name: 'NavigationBar' })
 | 
			
		||||
/** 轮播图 */
 | 
			
		||||
defineOptions({ name: 'Carousel' })
 | 
			
		||||
 | 
			
		||||
const props = defineProps<{ property: CarouselProperty }>()
 | 
			
		||||
defineProps<{ property: CarouselProperty }>()
 | 
			
		||||
 | 
			
		||||
const currentIndex = ref(0)
 | 
			
		||||
const handleIndexChange = (index: number) => {
 | 
			
		||||
  currentIndex.value = index + 1
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
<style scoped lang="scss">
 | 
			
		||||
.img-item {
 | 
			
		||||
  width: 100%;
 | 
			
		||||
  position: relative;
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
  &:last-child {
 | 
			
		||||
    margin: 0 !important;
 | 
			
		||||
  }
 | 
			
		||||
  /* 图片 */
 | 
			
		||||
  img {
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    display: block;
 | 
			
		||||
  }
 | 
			
		||||
  .title {
 | 
			
		||||
    height: 36px;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    background-color: rgba(51, 51, 51, 0.8);
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    line-height: 36px;
 | 
			
		||||
    color: #fff;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    bottom: 0;
 | 
			
		||||
    left: 0;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
</style>
 | 
			
		||||
<style scoped lang="scss"></style>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,103 +1,120 @@
 | 
			
		||||
<template>
 | 
			
		||||
  <el-form label-width="80px" :model="formData">
 | 
			
		||||
    <el-form-item label="选择模板" prop="swiperType">
 | 
			
		||||
      <el-radio-group v-model="formData.swiperType">
 | 
			
		||||
        <el-tooltip class="item" content="一行一个" placement="bottom">
 | 
			
		||||
          <el-radio-button :label="0">
 | 
			
		||||
            <Icon icon="icon-park-twotone:multi-picture-carousel" />
 | 
			
		||||
          </el-radio-button>
 | 
			
		||||
        </el-tooltip>
 | 
			
		||||
        <el-tooltip class="item" content="轮播海报" placement="bottom">
 | 
			
		||||
          <el-radio-button :label="1">
 | 
			
		||||
            <Icon icon="system-uicons:carousel" />
 | 
			
		||||
          </el-radio-button>
 | 
			
		||||
        </el-tooltip>
 | 
			
		||||
        <el-tooltip class="item" content="多图单行" placement="bottom">
 | 
			
		||||
          <el-radio-button :label="2">
 | 
			
		||||
            <Icon icon="icon-park-twotone:carousel" />
 | 
			
		||||
          </el-radio-button>
 | 
			
		||||
        </el-tooltip>
 | 
			
		||||
        <el-tooltip class="item" content="立体轮播" placement="bottom">
 | 
			
		||||
          <el-radio-button :label="3">
 | 
			
		||||
            <Icon icon="ic:round-view-carousel" />
 | 
			
		||||
          </el-radio-button>
 | 
			
		||||
        </el-tooltip>
 | 
			
		||||
      </el-radio-group>
 | 
			
		||||
    </el-form-item>
 | 
			
		||||
 | 
			
		||||
    <el-text tag="p">添加图片</el-text>
 | 
			
		||||
    <el-text type="info" size="small"> 拖动左上角的小圆点可对其排序 </el-text>
 | 
			
		||||
 | 
			
		||||
    <!-- 图片广告 -->
 | 
			
		||||
    <div v-if="formData.items[0]">
 | 
			
		||||
      <draggable
 | 
			
		||||
        :list="formData.items"
 | 
			
		||||
        :force-fallback="true"
 | 
			
		||||
        :animation="200"
 | 
			
		||||
        handle=".drag-icon"
 | 
			
		||||
        class="m-t-8px"
 | 
			
		||||
      >
 | 
			
		||||
        <template #item="{ element, index }">
 | 
			
		||||
          <div class="mb-4px flex flex-row gap-4px rounded bg-gray-100 p-8px">
 | 
			
		||||
            <div class="flex flex-col items-start justify-between">
 | 
			
		||||
              <Icon icon="ic:round-drag-indicator" class="drag-icon cursor-move" />
 | 
			
		||||
              <Icon
 | 
			
		||||
                icon="ep:delete"
 | 
			
		||||
                class="cursor-pointer text-red-5"
 | 
			
		||||
                @click="handleDeleteImage(index)"
 | 
			
		||||
                v-if="formData.items.length > 1"
 | 
			
		||||
              />
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="flex flex-1 flex-col items-center justify-between gap-8px">
 | 
			
		||||
              <UploadImg
 | 
			
		||||
                v-model="element.imgUrl"
 | 
			
		||||
                draggable="false"
 | 
			
		||||
                height="80px"
 | 
			
		||||
                width="100%"
 | 
			
		||||
                class="min-w-80px"
 | 
			
		||||
              />
 | 
			
		||||
              <!-- 标题 -->
 | 
			
		||||
              <el-input v-model="element.title" placeholder="标题,选填" />
 | 
			
		||||
              <!-- 输入链接 -->
 | 
			
		||||
              <el-input placeholder="链接,选填" v-model="element.link" />
 | 
			
		||||
            </div>
 | 
			
		||||
          </div>
 | 
			
		||||
  <ComponentContainerProperty v-model="formData.style">
 | 
			
		||||
    <el-form label-width="80px" :model="formData">
 | 
			
		||||
      <el-card header="样式设置" class="property-group" shadow="never">
 | 
			
		||||
        <el-form-item label="样式" prop="type">
 | 
			
		||||
          <el-radio-group v-model="formData.type">
 | 
			
		||||
            <el-tooltip class="item" content="默认" placement="bottom">
 | 
			
		||||
              <el-radio-button label="default">
 | 
			
		||||
                <Icon icon="system-uicons:carousel" />
 | 
			
		||||
              </el-radio-button>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
            <el-tooltip class="item" content="卡片" placement="bottom">
 | 
			
		||||
              <el-radio-button label="card">
 | 
			
		||||
                <Icon icon="ic:round-view-carousel" />
 | 
			
		||||
              </el-radio-button>
 | 
			
		||||
            </el-tooltip>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="指示器" prop="indicator">
 | 
			
		||||
          <el-radio-group v-model="formData.indicator">
 | 
			
		||||
            <el-radio label="dot">小圆点</el-radio>
 | 
			
		||||
            <el-radio label="number">数字</el-radio>
 | 
			
		||||
          </el-radio-group>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="是否轮播" prop="autoplay">
 | 
			
		||||
          <el-switch v-model="formData.autoplay" />
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
        <el-form-item label="播放间隔" prop="interval" v-if="formData.autoplay">
 | 
			
		||||
          <el-slider
 | 
			
		||||
            v-model="formData.interval"
 | 
			
		||||
            :max="10"
 | 
			
		||||
            :min="0.5"
 | 
			
		||||
            :step="0.5"
 | 
			
		||||
            show-input
 | 
			
		||||
            input-size="small"
 | 
			
		||||
            :show-input-controls="false"
 | 
			
		||||
          />
 | 
			
		||||
          <el-text type="info">单位:秒</el-text>
 | 
			
		||||
        </el-form-item>
 | 
			
		||||
      </el-card>
 | 
			
		||||
      <el-card header="内容设置" class="property-group" shadow="never">
 | 
			
		||||
        <el-text type="info" size="small"> 拖动左上角的小圆点可对其排序 </el-text>
 | 
			
		||||
        <template v-if="formData.items[0]">
 | 
			
		||||
          <draggable
 | 
			
		||||
            :list="formData.items"
 | 
			
		||||
            :force-fallback="true"
 | 
			
		||||
            :animation="200"
 | 
			
		||||
            handle=".drag-icon"
 | 
			
		||||
            class="m-t-8px"
 | 
			
		||||
            item-key="index"
 | 
			
		||||
          >
 | 
			
		||||
            <template #item="{ element, index }">
 | 
			
		||||
              <div class="content mb-4px flex flex-col gap-4px rounded bg-gray-50 p-8px">
 | 
			
		||||
                <div
 | 
			
		||||
                  class="m--8px m-b-8px flex flex-row items-center justify-between bg-gray-100 p-8px"
 | 
			
		||||
                >
 | 
			
		||||
                  <Icon icon="ic:round-drag-indicator" class="drag-icon cursor-move" />
 | 
			
		||||
                  <Icon
 | 
			
		||||
                    icon="ep:delete"
 | 
			
		||||
                    class="cursor-pointer text-red-5"
 | 
			
		||||
                    @click="handleDeleteImage(index)"
 | 
			
		||||
                    v-if="formData.items.length > 1"
 | 
			
		||||
                  />
 | 
			
		||||
                </div>
 | 
			
		||||
                <el-form-item label="类型" prop="type" class="m-b-8px!" label-width="50px">
 | 
			
		||||
                  <el-radio-group v-model="element.type">
 | 
			
		||||
                    <el-radio label="img">图片</el-radio>
 | 
			
		||||
                    <el-radio label="video">视频</el-radio>
 | 
			
		||||
                  </el-radio-group>
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <el-form-item
 | 
			
		||||
                  label="图片"
 | 
			
		||||
                  class="m-b-8px!"
 | 
			
		||||
                  label-width="50px"
 | 
			
		||||
                  v-if="element.type === 'img'"
 | 
			
		||||
                >
 | 
			
		||||
                  <UploadImg
 | 
			
		||||
                    v-model="element.imgUrl"
 | 
			
		||||
                    draggable="false"
 | 
			
		||||
                    height="80px"
 | 
			
		||||
                    width="100%"
 | 
			
		||||
                    class="min-w-80px"
 | 
			
		||||
                  />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
                <template v-else>
 | 
			
		||||
                  <el-form-item label="封面" class="m-b-8px!" label-width="50px">
 | 
			
		||||
                    <UploadImg
 | 
			
		||||
                      v-model="element.imgUrl"
 | 
			
		||||
                      draggable="false"
 | 
			
		||||
                      height="80px"
 | 
			
		||||
                      width="100%"
 | 
			
		||||
                      class="min-w-80px"
 | 
			
		||||
                    />
 | 
			
		||||
                  </el-form-item>
 | 
			
		||||
                  <el-form-item label="视频" class="m-b-8px!" label-width="50px">
 | 
			
		||||
                    <UploadFile
 | 
			
		||||
                      v-model="element.videoUrl"
 | 
			
		||||
                      :file-type="['mp4']"
 | 
			
		||||
                      :limit="1"
 | 
			
		||||
                      :file-size="100"
 | 
			
		||||
                      class="min-w-80px"
 | 
			
		||||
                    />
 | 
			
		||||
                  </el-form-item>
 | 
			
		||||
                </template>
 | 
			
		||||
                <el-form-item label="链接" class="m-b-8px!" label-width="50px">
 | 
			
		||||
                  <el-input placeholder="链接" v-model="element.url" />
 | 
			
		||||
                </el-form-item>
 | 
			
		||||
              </div>
 | 
			
		||||
            </template>
 | 
			
		||||
          </draggable>
 | 
			
		||||
        </template>
 | 
			
		||||
      </draggable>
 | 
			
		||||
    </div>
 | 
			
		||||
    <el-button @click="handleAddImage" type="primary" plain class="w-full"> 添加图片 </el-button>
 | 
			
		||||
    <el-form-item label="一行个数" prop="rowIndividual" v-show="formData.swiperType === 2">
 | 
			
		||||
      <!-- 单选框 -->
 | 
			
		||||
      <el-radio-group v-model="formData.rowIndividual">
 | 
			
		||||
        <el-radio :label="2">2个</el-radio>
 | 
			
		||||
        <el-radio :label="3">3个</el-radio>
 | 
			
		||||
        <el-radio :label="4">4个</el-radio>
 | 
			
		||||
        <el-radio :label="5">5个</el-radio>
 | 
			
		||||
        <el-radio :label="6">6个</el-radio>
 | 
			
		||||
      </el-radio-group>
 | 
			
		||||
    </el-form-item>
 | 
			
		||||
    <el-form-item label="分页类型" prop="pagingType">
 | 
			
		||||
      <el-radio-group v-model="formData.pagingType">
 | 
			
		||||
        <el-radio :label="0">不显示</el-radio>
 | 
			
		||||
        <el-radio label="bullets">样式一</el-radio>
 | 
			
		||||
        <el-radio label="fraction">样式二</el-radio>
 | 
			
		||||
        <el-radio label="progressbar">样式三</el-radio>
 | 
			
		||||
      </el-radio-group>
 | 
			
		||||
    </el-form-item>
 | 
			
		||||
    <el-form-item label="图片圆角" prop="borderRadius">
 | 
			
		||||
      <el-slider v-model="formData.borderRadius" :max="30" />
 | 
			
		||||
    </el-form-item>
 | 
			
		||||
    <el-form-item label="页面边距" prop="pageMargin" v-show="formData.swiperType === 0">
 | 
			
		||||
      <el-slider v-model="formData.pageMargin" :max="20" />
 | 
			
		||||
    </el-form-item>
 | 
			
		||||
    <el-form-item
 | 
			
		||||
      label="图片边距"
 | 
			
		||||
      prop="imageMargin"
 | 
			
		||||
      v-show="formData.swiperType === 0 || formData.swiperType === 2"
 | 
			
		||||
    >
 | 
			
		||||
      <el-slider v-model="formData.imageMargin" :max="20" />
 | 
			
		||||
    </el-form-item>
 | 
			
		||||
  </el-form>
 | 
			
		||||
        <el-button @click="handleAddImage" type="primary" plain class="w-full">
 | 
			
		||||
          添加图片
 | 
			
		||||
        </el-button>
 | 
			
		||||
      </el-card>
 | 
			
		||||
    </el-form>
 | 
			
		||||
  </ComponentContainerProperty>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script setup lang="ts">
 | 
			
		||||
@@ -117,7 +134,7 @@ const handleAddImage = () => {
 | 
			
		||||
  formData.value.items.push({} as CarouselItemProperty)
 | 
			
		||||
}
 | 
			
		||||
// 删除图片
 | 
			
		||||
const handleDeleteImage = (index) => {
 | 
			
		||||
const handleDeleteImage = (index: number) => {
 | 
			
		||||
  formData.value.items.splice(index, 1)
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
 
 | 
			
		||||
@@ -385,12 +385,18 @@ $toolbar-height: 42px;
 | 
			
		||||
      /* 属性面板分组 */
 | 
			
		||||
      :deep(.property-group) {
 | 
			
		||||
        margin: 0 -20px;
 | 
			
		||||
        &.el-card {
 | 
			
		||||
          border: none;
 | 
			
		||||
        }
 | 
			
		||||
        /* 属性分组名称 */
 | 
			
		||||
        .el-card__header {
 | 
			
		||||
          border: none;
 | 
			
		||||
          background: var(--el-bg-color-page);
 | 
			
		||||
          padding: 8px 32px;
 | 
			
		||||
        }
 | 
			
		||||
        .el-card__body {
 | 
			
		||||
          border: none;
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -138,7 +138,7 @@ watch(
 | 
			
		||||
      // 情况1.1:逗号分隔的多值
 | 
			
		||||
      if (props.modelValue.includes(',')) {
 | 
			
		||||
        files.concat(props.modelValue.split(','))
 | 
			
		||||
      } else {
 | 
			
		||||
      } else if (props.modelValue.length > 0) {
 | 
			
		||||
        files.push(props.modelValue)
 | 
			
		||||
      }
 | 
			
		||||
    } else if (isArray(props.modelValue)) {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user