config.vue 6.18 KB
<template>
  <collapse-item name="属性" :expanded="true">
    <setting-item-box name="路径" :alone="true">
      <n-upload
        :max="5"
        v-model:file-list="fileList"
        :customRequest="customRequest"
        :onBeforeUpload="beforeUploadHandle"
        @change="handleUploadChange"
      >
        <n-button>上传图片</n-button>
      </n-upload>
    </setting-item-box>
    <setting-item-box name="播放器">
      <setting-item>
        <n-space>
          <n-switch v-model:value="optionData.autoplay" size="small" />
          <n-text>自动播放</n-text>
        </n-space>
      </setting-item>
      <!-- 开启自动播放时,设置间隔时间 -->
      <setting-item name="间隔时间">
        <n-input-number v-model:value="optionData.interval" size="small" placeholder=""></n-input-number>
      </setting-item>
      <setting-item name="轮播方向">
        <n-select v-model:value="optionData.direction" :options="directions" placeholder="选择方向" />
      </setting-item>
      <setting-item name="过渡效果">
        <n-select v-model:value="optionData.effect" :options="effects" placeholder="效果" />
      </setting-item>
      <setting-item name="每页数量">
        <n-input-number v-model:value="optionData.slidesPerview" size="small" placeholder=""></n-input-number>
      </setting-item>
      <setting-item>
        <n-space>
          <n-switch v-model:value="optionData.centeredSlides" size="small" />
          <n-text>居中显示</n-text>
        </n-space>
      </setting-item>
      <setting-item name="图片样式">
        <n-select v-model:value="optionData.fit" :options="fitList" placeholder="样式" />
      </setting-item>
    </setting-item-box>

    <setting-item-box name="指示器">
      <setting-item name="样式">
        <n-select v-model:value="optionData.dotType" :options="dotTypes" placeholder="选择样式" />
      </setting-item>
      <setting-item name="位置">
        <n-select v-model:value="optionData.dotPlacement" :options="dotPlacements" placeholder="选择位置" />
      </setting-item>
      <setting-item>
        <n-space>
          <n-switch v-model:value="optionData.showDots" size="small" />
          <n-text>显示</n-text>
        </n-space>
      </setting-item>
      <setting-item>
        <n-space>
          <n-switch v-model:value="optionData.showArrow" size="small" />
          <n-text>箭头</n-text>
        </n-space>
      </setting-item>
      <setting-item>
        <n-space>
          <n-switch v-model:value="optionData.draggable" size="small" />
          <n-text>拖曳切换</n-text>
        </n-space>
      </setting-item>
    </setting-item-box>
  </collapse-item>
</template>

<script setup lang="ts">
import { PropType, ref, nextTick, watch } from 'vue'
import { option } from './config'
import { CollapseItem, SettingItemBox, SettingItem } from '@/components/Pages/ChartItemSetting'
import { FileTypeEnum } from '@/enums/fileTypeEnum'
import { uploadFile } from '@/api/external/contentSave/content'
import { UploadCustomRequestOptions } from 'naive-ui'
import type { UploadFileInfo } from 'naive-ui'
import { backgroundImageSize } from '@/settings/designSetting'
import { fetchRouteParamsLocation } from '@/utils'

const props = defineProps({
  optionData: {
    type: Object as PropType<typeof option>,
    required: true
  }
})

const fileList = ref<UploadFileInfo[]>([])

watch(
  () => props.optionData,
  newValue => {
    fileList.value = newValue?.dataset as UploadFileInfo[]
  },
  {
    immediate: true
  }
)

// 上传图片前置处理
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
//@ts-ignore
const beforeUploadHandle = async ({ file }) => {
  const type = file.file.type
  const size = file.file.size
  if (size > 1024 * 1024 * backgroundImageSize) {
    window['$message'].warning(`图片超出 ${backgroundImageSize}M 限制,请重新上传!`)
    return false
  }
  if (type !== FileTypeEnum.PNG && type !== FileTypeEnum.JPEG && type !== FileTypeEnum.GIF) {
    window['$message'].warning('文件格式不符合,请重新上传!')
    return false
  }
  return true
}

const handleUploadChange = (data: { fileList: UploadFileInfo[] }) => {
  props.optionData.dataset = data.fileList as never as any
}

// 自定义上传操作
const customRequest = (options: UploadCustomRequestOptions) => {
  const { file } = options
  nextTick(async () => {
    if (file.file) {
      // 修改名称
      const newNameFile = new File([file.file], `${fetchRouteParamsLocation()}`, {
        type: file.file.type
      })
      let uploadParams = new FormData()
      uploadParams.append('file', newNameFile)
      const uploadRes = await uploadFile(uploadParams)
      if (uploadRes) {
        fileList.value.push({
          id: -Math.random() + '',
          name: uploadRes?.fileName,
          status: 'finished',
          url: uploadRes?.fileStaticUri
        })
        const fileArr = fileList.value.filter((item: UploadFileInfo) => {
          return item.status === 'finished'
        })
        fileList.value = fileArr
        props.optionData.dataset = fileList.value as never as any
        window['$message'].success('添加图片成功!')
      }
    } else {
      window['$message'].error('添加图片失败,请稍后重试!')
    }
  })
}

// 字典
const dotTypes = [
  {
    label: '点',
    value: 'dot'
  },
  {
    label: '线',
    value: 'line'
  }
]
const directions = [
  {
    label: '水平方向',
    value: 'horizontal'
  },
  {
    label: '垂直方向',
    value: 'vertical'
  }
]
const effects = [
  {
    label: 'slide',
    value: 'slide'
  },
  {
    label: 'fade',
    value: 'fade'
  },
  {
    label: 'card',
    value: 'card'
  },
  {
    label: 'custom',
    value: 'custom'
  }
]
const dotPlacements = [
  {
    label: '上边',
    value: 'top'
  },
  {
    label: '下边',
    value: 'bottom'
  },
  {
    label: '左边',
    value: 'left'
  },
  {
    label: '右边',
    value: 'right'
  }
]

// 适应类型
const fitList = [
  {
    value: 'fill',
    label: 'fill'
  },
  {
    value: 'contain',
    label: 'contain'
  },
  {
    value: 'cover',
    label: 'cover'
  },
  {
    value: 'scale-down',
    label: 'scale-down'
  },
  {
    value: 'none',
    label: 'none'
  }
]
</script>