基础框架 兼容视频格式

  • 基础框架 兼容视频格式 修改 \src\components\Upload\src\BasicUpload.vue 数据库新增 vue
bash 复制代码
<template>
  <div class="w-full">
    <div class="upload">
      <div class="upload-card">
        <!--图片列表-->
        <div
          class="upload-card-item"
          :style="getCSSProperties"
          v-for="(item, index) in imgList"
          :key="`img_${index}`"
        >
          <div v-if="type == 'video'" class="upload-card-item-info upload-card-item-info2">
            <video style="width: 100%; height: 100%;" controls :src="item"></video>
            <div class="img-box-actions2">
              <n-icon size="18" class="mx-2 action-icon" @click="remove(index)">
                <DeleteOutlined />
              </n-icon>
            </div>
          </div>
          <div v-else-if="type=='singleGraph'||type=='multiGraph'" class="upload-card-item-info">
            <div class="img-box">
              <img :src="item" />
            </div>
            <div class="img-box-actions">
              <n-icon size="18" class="mx-2 action-icon" @click="preview(item)">
                <EyeOutlined />
              </n-icon>
              <n-icon size="18" class="mx-2 action-icon" @click="remove(index)">
                <DeleteOutlined />
              </n-icon>
            </div>
          </div>
          <div v-else class="upload-card-item-info">
            <div style="width: 100%;height: 100%;display: flex;justify-content: center;align-items: center;">
              <n-icon size="40" :depth="4"><FileOutlined /></n-icon>
            </div>
            <div class="img-box-actions">
              <n-icon size="18" class="mx-2 action-icon" @click="remove(index)">
                <DeleteOutlined />
              </n-icon>
            </div>
          </div>
        </div>

        <!--上传图片 v-if="imgList.length < maxNumber"  -->
        <div v-if="imgList.length < maxNumber"
          class="upload-card-item upload-card-item-select-picture"
          :style="getCSSProperties"
        >
          <n-upload
            v-bind="$props"
            :file-list-style="{ display: 'none' }"
            @before-upload="beforeUpload"
            @finish="finish"
            style="display:flex;justify-content: center;"
          >
            <div class="flex flex-col justify-center" >
              <n-icon size="18" class="m-auto">
                <PlusOutlined />
              </n-icon>
              <span class="upload-title">点击上传</span>
            </div>
          </n-upload>
        </div>
      </div>
    </div>

    <!--上传图片-->
    <div >
      <n-alert title="提醒" type="info" closable v-if="helpText" class="flex w-full">
        {{ helpText }}
      </n-alert>
    </div>

  </div>

  <!--预览图片-->
  <n-modal
    v-model:show="showModal"
    preset="card"
    title="预览"
    :bordered="false"
    :style="{ width: '520px' }"
  >
    <img :src="previewUrl" />
  </n-modal>
</template>

<script lang="ts">
  import { defineComponent, toRefs, reactive, computed, watch } from 'vue';
  import { EyeOutlined, DeleteOutlined, PlusOutlined,FileOutlined } from '@vicons/antd';
  import { basicProps } from './props';
  import { useMessage, useDialog } from 'naive-ui';
  import { ResultEnum } from '@/enums/httpEnum';
  import componentSetting from '@/settings/componentSetting';
  import { useGlobSetting } from '@/hooks/setting';
  import { isString } from '@/utils/is';

  const globSetting = useGlobSetting();

  export default defineComponent({
    name: 'BasicUpload',
    components: { EyeOutlined, DeleteOutlined, PlusOutlined,FileOutlined },
    props: {
      ...basicProps,
    },
    emits: ['uploadChange', 'delete'],
    setup(props, { emit }) {
      const getCSSProperties = computed(() => {
        return {
          width: `${props.width}px`,
          height: `${props.height}px`,
          max: `${props.max}`,
        };
      });
      console.log('props:', props)
      const message = useMessage();
      const dialog = useDialog();

      const state = reactive({
        showModal: false,
        previewUrl: '',
        originalImgList: [] as string[],
        imgList: [] as string[],
      });

      //赋值默认图片显示
      watch(
        () => props.value,
        () => {
          if(props.value){
            state.imgList = props.value.map((item) => {
              return getImgUrl(item);
            });
            state.originalImgList  = props.value;
          }
        },
        { immediate: true }
      );

      //预览
      function preview(url: string) {
        state.showModal = true;
        state.previewUrl = url;
      }

      //删除
      function remove(index: number) {
        dialog.info({
          title: '提示',
          content: '你确定要删除吗?',
          positiveText: '确定',
          negativeText: '取消',
          onPositiveClick: () => {
            state.imgList.splice(index, 1);
            state.originalImgList.splice(index, 1);
            emit('uploadChange', state.originalImgList);
            emit('delete', state.originalImgList);
          },
          onNegativeClick: () => {},
        });
      }

      //组装完整图片地址
      function getImgUrl(url: string): string {
        const { imgUrl } = globSetting;
        return /(^http|https:\/\/)/g.test(url) ? url : `${imgUrl}${url}`;
      }

      function checkFileType(fileType:string[],filetype: string) {
        if(filetype.indexOf('/')!=-1){
          return fileType.includes(`.${filetype}`) || fileType.includes(`.${filetype.split('/')[1]}`);
        }
        return fileType.includes(filetype);
        // return componentSetting.upload.fileType.includes(fileType);
      }

      //上传之前
      function beforeUpload({ file }) {
        const fileInfo = file.file;
        const { maxSize, accept } = props;
        const acceptRef = (isString(accept) && accept.split(',')) || [];

        // 设置最大值,则判断
        if (maxSize && fileInfo.size / 1024 / 1024 >= maxSize) {
          message.error(`上传文件最大值不能超过${maxSize}M`);
          return false;
        }

        // 设置类型,则判断
        // let fileType : string[] = componentSetting.upload.fileType;
        // fileType = [...fileType,...acceptRef];
        // if (acceptRef.length > 0 && !checkFileType(fileInfo.type)) {
        if (!checkFileType(acceptRef,fileInfo.type)) {
          message.error(`您上传的格式为:${fileInfo.type.split('/')[1]},只能上传文件类型为${acceptRef.join(',')}`);
          return false;
        }

        return true;
      }

      //上传结束
      function finish({ event: Event }) {
        const res = eval('(' + (Event.target?Event.target.response:event.target.response)+ ')');
        const infoField = componentSetting.upload.apiSetting.infoField;
        const { code } = res;
        const message = res.msg || res.message || '上传失败';
        const result = res[infoField];
        //成功
        if (code === ResultEnum.SUCCESS) {
          let imgUrl: string = getImgUrl(result);
          state.imgList.push(imgUrl);
          state.originalImgList.push(result);
          emit('uploadChange', state.originalImgList);
        } else message.error(message);
      }
      return {
        ...toRefs(state),
        finish,
        preview,
        remove,
        beforeUpload,
        getCSSProperties,
      };
    },
  });
</script>

<style lang="less">
  .upload {
    width: 100%;
    overflow: hidden;

    &-card {
      width: auto;
      height: auto;
      display: flex;
      flex-wrap: wrap;
      align-items: center;

      &-item {
        margin: 0 8px 8px 0;
        position: relative;
        padding: 8px;
        border: 1px solid #d9d9d9;
        border-radius: 2px;
        display: flex;
        justify-content: center;
        flex-direction: column;
        align-items: center;

        &:hover {
          background: 0 0;

          .upload-card-item-info::before {
            opacity: 1;
          }
          .upload-card-item-info2::before {
            content: normal;
          }
          
          &-info::before {
            opacity: 1;
          }
        }

        &-info {
          position: relative;
          height: 100%;
          width: 100%;
          padding: 0;
          overflow: hidden;

          &:hover {
            .img-box-actions {
              opacity: 1;
            }
          }

          &::before {
            position: absolute;
            z-index: 1;
            width: 100%;
            height: 100%;
            background-color: rgba(0, 0, 0, 0.5);
            opacity: 0;
            transition: all 0.3s;
            content: ' ';
          }

          .img-box {
            position: relative;
            //padding: 8px;
            //border: 1px solid #d9d9d9;
            border-radius: 2px;
          }

          .img-box-actions {
            position: absolute;
            top: 50%;
            left: 50%;
            z-index: 10;
            white-space: nowrap;
            transform: translate(-50%, -50%);
            opacity: 0;
            transition: all 0.3s;
            display: flex;
            align-items: center;
            justify-content: space-between;

            &:hover {
              background: 0 0;
            }

            .action-icon {
              color: rgba(255, 255, 255, 0.85);

              &:hover {
                cursor: pointer;
                color: #fff;
              }
            }
          }


          .img-box-actions2 {
            position: absolute;
            top: 0;
            right: 0;
            z-index: 10;
            background: rgba(0, 0, 0, 0.5);

            .action-icon {
              color: rgba(255, 255, 255, 0.85);

              &:hover {
                cursor: pointer;
                color: #fff;
              }
            }
          }






          
        }
      }

      &-item-select-picture {
        border: 1px dashed #d9d9d9;
        border-radius: 2px;
        cursor: pointer;
        background: #fafafa;
        color: #666;

        .upload-title {
          color: #666;
        }
      }
    }
  }
</style>
相关推荐
互联网搬砖老肖2 小时前
React的单向数据绑定
前端·javascript·react.js
NoneCoder2 小时前
React 生命周期与 Hook 理解解析
前端·react.js·面试
盛夏绽放2 小时前
Python常用高阶函数全面解析:通俗易懂的指南
前端·windows·python
深空数字孪生3 小时前
前端性能优化:如何让网页加载更快?
前端·性能优化
阿乐今天敲代码没3 小时前
echarts实现项目进度甘特图
前端·echarts·甘特图
john_Asura3 小时前
Vue 前端全方位性能优化指南
前端·vue.js·性能优化
日晞4 小时前
深浅拷贝?
开发语言·前端·javascript
Bonnie_12154 小时前
05-jenkins学习之旅-vue前项目部署实践
vue.js·学习·jenkins
沐土Arvin5 小时前
性能优化关键:link、script和meta的正确打开方式
开发语言·前端·javascript·设计模式·性能优化·html
叶九灵不灵5 小时前
node入门:安装和npm使用
前端·npm·node.js