Commit 9003c7171fc5e152c7d65aa7dc3ca1981ba879be

Authored by fengwotao
1 parent 6ee8698a

perf(external/Composes): 新增自定义轮播图功能

... ... @@ -29,12 +29,12 @@ const props = defineProps({
29 29 }
30 30 })
31 31
32   -//三维静态文件
  32 +//三维模型静态文件
33 33 const filePath = ref()
34 34
35 35 filePath.value = ['src/assets/external/models/fbx/Samba Dancing.fbx']
36 36
37   -//三维加载事件相关
  37 +//三维模型加载事件相关
38 38 const show = ref(false)
39 39
40 40 const currentModelIndex = ref()
... ... @@ -55,7 +55,7 @@ const onProcess = (event: any, index: number) => {
55 55 show.value = false
56 56 }
57 57 }
58   -//三维加载事件
  58 +//三维模型加载事件相关
59 59
60 60 const { w, h } = toRefs(props.chartConfig.attr)
61 61 </script>
... ...
  1 +import { PublicConfigClass } from '@/packages/public'
  2 +import { CreateComponentType } from '@/packages/index.d'
  3 +import { OverrideCarouselConfig } from './index'
  4 +import cloneDeep from 'lodash/cloneDeep'
  5 +
  6 +export const option = {
  7 + // 图片资源列表
  8 + dataset: [],
  9 + // 自动播放
  10 + autoplay: true,
  11 + // 自动播放的间隔(ms)
  12 + interval: 5000,
  13 + // 每页显示的图片数量
  14 + slidesPerview: 1,
  15 + // 轮播方向
  16 + direction: 'horizontal',
  17 + // 拖曳切换
  18 + draggable: true,
  19 + // 居中显示
  20 + centeredSlides: false,
  21 + // 过渡效果
  22 + effect: 'slide',
  23 + // 是否显示指示点
  24 + showDots: true,
  25 + // 指示器样式
  26 + dotType: 'dot',
  27 + // 指示器位置
  28 + dotPlacement: 'bottom',
  29 + // 显示箭头
  30 + showArrow: false,
  31 + // 图片样式
  32 + fit: 'contain'
  33 +}
  34 +
  35 +export default class Config extends PublicConfigClass implements CreateComponentType {
  36 + public key = OverrideCarouselConfig.key
  37 + public chartConfig = cloneDeep(OverrideCarouselConfig)
  38 + public option = cloneDeep(option)
  39 +}
... ...
  1 +<template>
  2 + <collapse-item name="属性" :expanded="true">
  3 + <setting-item-box name="路径" :alone="true">
  4 + <n-upload
  5 + :max="5"
  6 + v-model:file-list="fileList"
  7 + :customRequest="customRequest"
  8 + :onBeforeUpload="beforeUploadHandle"
  9 + @change="handleUploadChange"
  10 + >
  11 + <n-button>上传图片</n-button>
  12 + </n-upload>
  13 + </setting-item-box>
  14 + <setting-item-box name="播放器">
  15 + <setting-item>
  16 + <n-space>
  17 + <n-switch v-model:value="optionData.autoplay" size="small" />
  18 + <n-text>自动播放</n-text>
  19 + </n-space>
  20 + </setting-item>
  21 + <!-- 开启自动播放时,设置间隔时间 -->
  22 + <setting-item name="间隔时间">
  23 + <n-input-number v-model:value="optionData.interval" size="small" placeholder=""></n-input-number>
  24 + </setting-item>
  25 + <setting-item name="轮播方向">
  26 + <n-select v-model:value="optionData.direction" :options="directions" placeholder="选择方向" />
  27 + </setting-item>
  28 + <setting-item name="过渡效果">
  29 + <n-select v-model:value="optionData.effect" :options="effects" placeholder="效果" />
  30 + </setting-item>
  31 + <setting-item name="每页数量">
  32 + <n-input-number v-model:value="optionData.slidesPerview" size="small" placeholder=""></n-input-number>
  33 + </setting-item>
  34 + <setting-item>
  35 + <n-space>
  36 + <n-switch v-model:value="optionData.centeredSlides" size="small" />
  37 + <n-text>居中显示</n-text>
  38 + </n-space>
  39 + </setting-item>
  40 + <setting-item name="图片样式">
  41 + <n-select v-model:value="optionData.fit" :options="fitList" placeholder="样式" />
  42 + </setting-item>
  43 + </setting-item-box>
  44 +
  45 + <setting-item-box name="指示器">
  46 + <setting-item name="样式">
  47 + <n-select v-model:value="optionData.dotType" :options="dotTypes" placeholder="选择样式" />
  48 + </setting-item>
  49 + <setting-item name="位置">
  50 + <n-select v-model:value="optionData.dotPlacement" :options="dotPlacements" placeholder="选择位置" />
  51 + </setting-item>
  52 + <setting-item>
  53 + <n-space>
  54 + <n-switch v-model:value="optionData.showDots" size="small" />
  55 + <n-text>显示</n-text>
  56 + </n-space>
  57 + </setting-item>
  58 + <setting-item>
  59 + <n-space>
  60 + <n-switch v-model:value="optionData.showArrow" size="small" />
  61 + <n-text>箭头</n-text>
  62 + </n-space>
  63 + </setting-item>
  64 + <setting-item>
  65 + <n-space>
  66 + <n-switch v-model:value="optionData.draggable" size="small" />
  67 + <n-text>拖曳切换</n-text>
  68 + </n-space>
  69 + </setting-item>
  70 + </setting-item-box>
  71 + </collapse-item>
  72 +</template>
  73 +
  74 +<script setup lang="ts">
  75 +import { PropType, ref, nextTick, watch } from 'vue'
  76 +import { option } from './config'
  77 +import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
  78 +import { FileTypeEnum } from '@/enums/fileTypeEnum'
  79 +import { uploadFile } from '@/api/external/contentSave/content'
  80 +import { UploadCustomRequestOptions } from 'naive-ui'
  81 +import type { UploadFileInfo } from 'naive-ui'
  82 +import { backgroundImageSize } from '@/settings/designSetting'
  83 +import { fetchRouteParamsLocation } from '@/utils'
  84 +
  85 +const props = defineProps({
  86 + optionData: {
  87 + type: Object as PropType<typeof option>,
  88 + required: true
  89 + }
  90 +})
  91 +
  92 +const fileList = ref<UploadFileInfo[]>([])
  93 +
  94 +watch(
  95 + () => props.optionData,
  96 + newValue => {
  97 + console.log(newValue)
  98 + fileList.value = newValue?.dataset
  99 + },
  100 + {
  101 + immediate: true
  102 + }
  103 +)
  104 +
  105 +// 上传图片前置处理
  106 +// eslint-disable-next-line @typescript-eslint/ban-ts-comment
  107 +//@ts-ignore
  108 +const beforeUploadHandle = async ({ file }) => {
  109 + const type = file.file.type
  110 + const size = file.file.size
  111 + if (size > 1024 * 1024 * backgroundImageSize) {
  112 + window['$message'].warning(`图片超出 ${backgroundImageSize}M 限制,请重新上传!`)
  113 + return false
  114 + }
  115 + if (type !== FileTypeEnum.PNG && type !== FileTypeEnum.JPEG && type !== FileTypeEnum.GIF) {
  116 + window['$message'].warning('文件格式不符合,请重新上传!')
  117 + return false
  118 + }
  119 + return true
  120 +}
  121 +
  122 +const handleUploadChange = (data: { fileList: UploadFileInfo[] }) => {
  123 + console.log(data.fileList)
  124 + props.optionData.dataset = data.fileList as never as any
  125 +}
  126 +
  127 +// 自定义上传操作
  128 +const customRequest = (options: UploadCustomRequestOptions) => {
  129 + const { file } = options
  130 + nextTick(async () => {
  131 + if (file.file) {
  132 + // 修改名称
  133 + const newNameFile = new File([file.file], `${fetchRouteParamsLocation()}`, {
  134 + type: file.file.type
  135 + })
  136 + let uploadParams = new FormData()
  137 + uploadParams.append('file', newNameFile)
  138 + const uploadRes = await uploadFile(uploadParams)
  139 + if (uploadRes) {
  140 + fileList.value.push({
  141 + id: -Math.random() + '',
  142 + name: uploadRes?.fileName,
  143 + status: 'finished',
  144 + url: uploadRes?.fileStaticUri
  145 + })
  146 + const fileArr = fileList.value.filter((item: UploadFileInfo) => {
  147 + return item.status === 'finished'
  148 + })
  149 + fileList.value = fileArr
  150 + console.log(fileList.value)
  151 + props.optionData.dataset = fileList.value as never as any
  152 + window['$message'].success('添加图片成功!')
  153 + }
  154 + } else {
  155 + window['$message'].error('添加图片失败,请稍后重试!')
  156 + }
  157 + })
  158 +}
  159 +
  160 +// 字典
  161 +const dotTypes = [
  162 + {
  163 + label: '点',
  164 + value: 'dot'
  165 + },
  166 + {
  167 + label: '线',
  168 + value: 'line'
  169 + }
  170 +]
  171 +const directions = [
  172 + {
  173 + label: '水平方向',
  174 + value: 'horizontal'
  175 + },
  176 + {
  177 + label: '垂直方向',
  178 + value: 'vertical'
  179 + }
  180 +]
  181 +const effects = [
  182 + {
  183 + label: 'slide',
  184 + value: 'slide'
  185 + },
  186 + {
  187 + label: 'fade',
  188 + value: 'fade'
  189 + },
  190 + {
  191 + label: 'card',
  192 + value: 'card'
  193 + },
  194 + {
  195 + label: 'custom',
  196 + value: 'custom'
  197 + }
  198 +]
  199 +const dotPlacements = [
  200 + {
  201 + label: '上边',
  202 + value: 'top'
  203 + },
  204 + {
  205 + label: '下边',
  206 + value: 'bottom'
  207 + },
  208 + {
  209 + label: '左边',
  210 + value: 'left'
  211 + },
  212 + {
  213 + label: '右边',
  214 + value: 'right'
  215 + }
  216 +]
  217 +
  218 +// 适应类型
  219 +const fitList = [
  220 + {
  221 + value: 'fill',
  222 + label: 'fill'
  223 + },
  224 + {
  225 + value: 'contain',
  226 + label: 'contain'
  227 + },
  228 + {
  229 + value: 'cover',
  230 + label: 'cover'
  231 + },
  232 + {
  233 + value: 'scale-down',
  234 + label: 'scale-down'
  235 + },
  236 + {
  237 + value: 'none',
  238 + label: 'none'
  239 + }
  240 +]
  241 +</script>
... ...
  1 +import { ConfigType, PackagesCategoryEnum, ChartFrameEnum } from '@/packages/index.d'
  2 +import { ChatCategoryEnum, ChatCategoryEnumName } from '@/packages/components/Informations/index.d'
  3 +import { useWidgetKey } from '@/packages/external/useWidgetKey'
  4 +
  5 +const { key, conKey, chartKey } = useWidgetKey('OverrideCarousel', true)
  6 +
  7 +export const OverrideCarouselConfig: ConfigType = {
  8 + key,
  9 + chartKey,
  10 + conKey,
  11 + title: '自定义轮播图',
  12 + category: ChatCategoryEnum.MORE,
  13 + categoryName: ChatCategoryEnumName.MORE,
  14 + package: PackagesCategoryEnum.INFORMATIONS,
  15 + chartFrame: ChartFrameEnum.COMMON,
  16 + image: 'photo.png'
  17 +}
... ...
  1 +<template>
  2 + <div>
  3 + <n-carousel
  4 + :autoplay="autoplay"
  5 + :interval="interval"
  6 + :centered-slides="centeredSlides"
  7 + :direction="direction"
  8 + :dot-placement="dotPlacement"
  9 + :dot-type="dotType"
  10 + :draggable="draggable"
  11 + :effect="effect"
  12 + :slides-per-view="slidesPerview"
  13 + :show-arrow="showArrow"
  14 + :show-dots="showDots"
  15 + >
  16 + <n-image
  17 + v-for="(item, index) in option.dataset"
  18 + :key="index"
  19 + :object-fit="fit"
  20 + preview-disabled
  21 + :src="item.url"
  22 + :fallback-src="requireErrorImg()"
  23 + :width="w"
  24 + :height="h"
  25 + ></n-image>
  26 + </n-carousel>
  27 + </div>
  28 +</template>
  29 +<script setup lang="ts">
  30 +import { PropType, toRefs, shallowReactive, watch } from 'vue'
  31 +import { CreateComponentType } from '@/packages/index.d'
  32 +import { requireErrorImg } from '@/utils'
  33 +import { useChartDataFetch } from '@/hooks'
  34 +import { useChartEditStore } from '@/store/modules/chartEditStore/chartEditStore'
  35 +import { option as configOption } from './config'
  36 +
  37 +const props = defineProps({
  38 + chartConfig: {
  39 + type: Object as PropType<CreateComponentType>,
  40 + required: true
  41 + }
  42 +})
  43 +
  44 +const option: any = shallowReactive({
  45 + dataset: configOption.dataset
  46 +})
  47 +
  48 +const { w, h } = toRefs(props.chartConfig.attr)
  49 +const {
  50 + autoplay,
  51 + interval,
  52 + slidesPerview,
  53 + direction,
  54 + draggable,
  55 + centeredSlides,
  56 + effect,
  57 + dotType,
  58 + dotPlacement,
  59 + showArrow,
  60 + showDots,
  61 + fit
  62 +} = toRefs(props.chartConfig.option)
  63 +
  64 +watch(
  65 + () => props.chartConfig.option.dataset,
  66 + (newData: any) => {
  67 + option.dataset = newData
  68 + },
  69 + {
  70 + immediate: true,
  71 + deep: false
  72 + }
  73 +)
  74 +
  75 +useChartDataFetch(props.chartConfig, useChartEditStore, (newData: any) => {
  76 + option.dataset = newData
  77 +})
  78 +</script>
... ...
... ... @@ -58,6 +58,7 @@ const props = defineProps({
58 58 const uploadFileListRef = ref()
59 59
60 60 // 上传图片前置处理
  61 +// eslint-disable-next-line @typescript-eslint/ban-ts-comment
61 62 //@ts-ignore
62 63 const beforeUploadHandle = async ({ file }) => {
63 64 uploadFileListRef.value = []
... ...
... ... @@ -3,6 +3,7 @@ import { ComposesList } from '@/packages/components/external/Composes'
3 3 import { ConfigType, PackagesCategoryEnum } from '@/packages/index.d'
4 4 import { ClockConfig } from '@/packages/components/external/Decorates/Mores/Icon'
5 5 import { OverrideImageConfig } from '@/packages/components/external/Informations/Mores/OverrideImage'
  6 +import {OverrideCarouselConfig } from '@/packages/components/external/Informations/Mores/OverrideCarousel'
6 7
7 8 export function useInjectLib(packagesList: EPackagesType) {
8 9
... ... @@ -10,6 +11,7 @@ export function useInjectLib(packagesList: EPackagesType) {
10 11
11 12 addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.DECORATES, ClockConfig)
12 13 addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.INFORMATIONS, OverrideImageConfig)
  14 + addWidgetToCategoryByCategoryName(packagesList, PackagesCategoryEnum.INFORMATIONS, OverrideCarouselConfig)
13 15 }
14 16
15 17 /**
... ...