config.vue 6.63 KB
<template>
  <collapse-item :name="t('information.attribute')" :expanded="true">
    <setting-item-box :name="t('information.path')" :alone="true">
      <n-upload
        :max="5"
        v-model:file-list="fileList"
        :customRequest="customRequest"
        :onBeforeUpload="beforeUploadHandle"
        @change="handleUploadChange"
      >
        <n-button>{{t('information.uploadImage')}}</n-button>
      </n-upload>
    </setting-item-box>
    <setting-item-box :name="t('information.player')">
      <setting-item>
        <n-space>
          <n-switch v-model:value="optionData.autoplay" size="small" />
          <n-text>{{t('information.autoplay')}}</n-text>
        </n-space>
      </setting-item>
      <!-- 开启自动播放时,设置间隔时间 -->
      <setting-item :name="t('information.intervalTime')">
        <n-input-number v-model:value="optionData.interval" size="small" placeholder=""></n-input-number>
      </setting-item>
      <setting-item :name="t('information.rotaDirection')">
        <n-select v-model:value="optionData.direction" :options="directions" placeholder="选择方向" />
      </setting-item>
      <setting-item :name="t('information.transition')">
        <n-select v-model:value="optionData.effect" :options="effects" placeholder="效果" />
      </setting-item>
      <setting-item :name="t('information.perPage')">
        <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>{{ t('information.centerShow') }}</n-text>
        </n-space>
      </setting-item>
      <setting-item :name="t('information.imageStyle')">
        <n-select v-model:value="optionData.fit" :options="fitList" placeholder="样式" />
      </setting-item>
    </setting-item-box>

    <setting-item-box :name="t('information.indicator')">
      <setting-item :name="t('common.styleText')">
        <n-select v-model:value="optionData.dotType" :options="dotTypes" placeholder="选择样式" />
      </setting-item>
      <setting-item :name="t('common.positionText')">
        <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>{{t('common.displayText')}}</n-text>
        </n-space>
      </setting-item>
      <setting-item>
        <n-space>
          <n-switch v-model:value="optionData.showArrow" size="small" />
          <n-text>{{t('information.arrow')}}</n-text>
        </n-space>
      </setting-item>
      <setting-item>
        <n-space>
          <n-switch v-model:value="optionData.draggable" size="small" />
          <n-text>{{t('information.dragSwitch')}}</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 t = window['$t']

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(`${t('external.page.imageExceedsText')} ${backgroundImageSize}M ${t('external.page.placeuploadText')}`)
    return false
  }
  if (type !== FileTypeEnum.PNG && type !== FileTypeEnum.JPEG && type !== FileTypeEnum.GIF) {
    window['$message'].warning(t('external.page.fileUploadText'))
    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(t('information.addedImageOk'))
      }
    } else {
      window['$message'].error(t('information.addedImageFail'))
    }
  })
}

// 字典
const dotTypes = [
  {
    label: t('information.drop'),
    value: 'dot'
  },
  {
    label: t('information.line'),
    value: 'line'
  }
]
const directions = [
  {
    label: t('information.horizontal'),
    value: 'horizontal'
  },
  {
    label: t('information.vertical'),
    value: 'vertical'
  }
]
const effects = [
  {
    label: 'slide',
    value: 'slide'
  },
  {
    label: 'fade',
    value: 'fade'
  },
  {
    label: 'card',
    value: 'card'
  },
  {
    label: 'custom',
    value: 'custom'
  }
]
const dotPlacements = [
  {
    label: t('information.top'),
    value: 'top'
  },
  {
    label: t('information.bottom'),
    value: 'bottom'
  },
  {
    label: t('information.left'),
    value: 'left'
  },
  {
    label: t('information.right'),
    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>