skyouc
2024-12-21 c9c263dc43ad90f95f24a036cee9e6b47afb596c
uni_modules/uni-file-picker/components/uni-file-picker/upload-file.vue
@@ -1,325 +1,325 @@
<template>
   <view class="uni-file-picker__files">
      <view v-if="!readonly" class="files-button" @click="choose">
         <slot></slot>
      </view>
      <!-- :class="{'is-text-box':showType === 'list'}" -->
      <view v-if="list.length > 0" class="uni-file-picker__lists is-text-box" :style="borderStyle">
         <!-- ,'is-list-card':showType === 'list-card' -->
         <view class="uni-file-picker__lists-box" v-for="(item ,index) in list" :key="index" :class="{
            'files-border':index !== 0 && styles.dividline}"
          :style="index !== 0 && styles.dividline &&borderLineStyle">
            <view class="uni-file-picker__item">
               <!-- :class="{'is-text-image':showType === 'list'}" -->
               <!--    <view class="files__image is-text-image">
                  <image class="header-image" :src="item.logo" mode="aspectFit"></image>
               </view> -->
               <view class="files__name">{{item.name}}</view>
               <view v-if="delIcon&&!readonly" class="icon-del-box icon-files" @click="delFile(index)">
                  <view class="icon-del icon-files"></view>
                  <view class="icon-del rotate"></view>
               </view>
            </view>
            <view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
               <progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4"
                :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
            </view>
            <view v-if="item.status === 'error'" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
               点击重试
            </view>
         </view>
      </view>
   </view>
</template>
<script>
   export default {
      name: "uploadFile",
      emits:['uploadFiles','choose','delFile'],
      props: {
         filesList: {
            type: Array,
            default () {
               return []
            }
         },
         delIcon: {
            type: Boolean,
            default: true
         },
         limit: {
            type: [Number, String],
            default: 9
         },
         showType: {
            type: String,
            default: ''
         },
         listStyles: {
            type: Object,
            default () {
               return {
                  // 是否显示边框
                  border: true,
                  // 是否显示分隔线
                  dividline: true,
                  // 线条样式
                  borderStyle: {}
               }
            }
         },
         readonly:{
            type:Boolean,
            default:false
         }
      },
      computed: {
         list() {
            let files = []
            this.filesList.forEach(v => {
               files.push(v)
            })
            return files
         },
         styles() {
            let styles = {
               border: true,
               dividline: true,
               'border-style': {}
            }
            return Object.assign(styles, this.listStyles)
         },
         borderStyle() {
            let {
               borderStyle,
               border
            } = this.styles
            let obj = {}
            if (!border) {
               obj.border = 'none'
            } else {
               let width = (borderStyle && borderStyle.width) || 1
               width = this.value2px(width)
               let radius = (borderStyle && borderStyle.radius) || 5
               radius = this.value2px(radius)
               obj = {
                  'border-width': width,
                  'border-style': (borderStyle && borderStyle.style) || 'solid',
                  'border-color': (borderStyle && borderStyle.color) || '#eee',
                  'border-radius': radius
               }
            }
            let classles = ''
            for (let i in obj) {
               classles += `${i}:${obj[i]};`
            }
            return classles
         },
         borderLineStyle() {
            let obj = {}
            let {
               borderStyle
            } = this.styles
            if (borderStyle && borderStyle.color) {
               obj['border-color'] = borderStyle.color
            }
            if (borderStyle && borderStyle.width) {
               let width = borderStyle && borderStyle.width || 1
               let style = borderStyle && borderStyle.style || 0
               if (typeof width === 'number') {
                  width += 'px'
               } else {
                  width = width.indexOf('px') ? width : width + 'px'
               }
               obj['border-width'] = width
               if (typeof style === 'number') {
                  style += 'px'
               } else {
                  style = style.indexOf('px') ? style : style + 'px'
               }
               obj['border-top-style'] = style
            }
            let classles = ''
            for (let i in obj) {
               classles += `${i}:${obj[i]};`
            }
            return classles
         }
      },
      methods: {
         uploadFiles(item, index) {
            this.$emit("uploadFiles", {
               item,
               index
            })
         },
         choose() {
            this.$emit("choose")
         },
         delFile(index) {
            this.$emit('delFile', index)
         },
         value2px(value) {
            if (typeof value === 'number') {
               value += 'px'
            } else {
               value = value.indexOf('px') !== -1 ? value : value + 'px'
            }
            return value
         }
      }
   }
</script>
<style lang="scss">
   .uni-file-picker__files {
      /* #ifndef APP-NVUE */
      display: flex;
      /* #endif */
      flex-direction: column;
      justify-content: flex-start;
   }
   .files-button {
      // border: 1px red solid;
   }
   .uni-file-picker__lists {
      position: relative;
      margin-top: 5px;
      overflow: hidden;
   }
   .file-picker__mask {
      /* #ifndef APP-NVUE */
      display: flex;
      /* #endif */
      justify-content: center;
      align-items: center;
      position: absolute;
      right: 0;
      top: 0;
      bottom: 0;
      left: 0;
      color: #fff;
      font-size: 14px;
      background-color: rgba(0, 0, 0, 0.4);
   }
   .uni-file-picker__lists-box {
      position: relative;
   }
   .uni-file-picker__item {
      /* #ifndef APP-NVUE */
      display: flex;
      /* #endif */
      align-items: center;
      padding: 8px 10px;
      padding-right: 5px;
      padding-left: 10px;
   }
   .files-border {
      border-top: 1px #eee solid;
   }
   .files__name {
      flex: 1;
      font-size: 14px;
      color: #666;
      margin-right: 25px;
      /* #ifndef APP-NVUE */
      word-break: break-all;
      word-wrap: break-word;
      /* #endif */
   }
   .icon-files {
      /* #ifndef APP-NVUE */
      position: static;
      background-color: initial;
      /* #endif */
   }
   // .icon-files .icon-del {
   //    background-color: #333;
   //    width: 12px;
   //    height: 1px;
   // }
   .is-list-card {
      border: 1px #eee solid;
      margin-bottom: 5px;
      border-radius: 5px;
      box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.1);
      padding: 5px;
   }
   .files__image {
      width: 40px;
      height: 40px;
      margin-right: 10px;
   }
   .header-image {
      width: 100%;
      height: 100%;
   }
   .is-text-box {
      border: 1px #eee solid;
      border-radius: 5px;
   }
   .is-text-image {
      width: 25px;
      height: 25px;
      margin-left: 5px;
   }
   .rotate {
      position: absolute;
      transform: rotate(90deg);
   }
   .icon-del-box {
      /* #ifndef APP-NVUE */
      display: flex;
      margin: auto 0;
      /* #endif */
      align-items: center;
      justify-content: center;
      position: absolute;
      top: 0px;
      bottom: 0;
      right: 5px;
      height: 26px;
      width: 26px;
      // border-radius: 50%;
      // background-color: rgba(0, 0, 0, 0.5);
      z-index: 2;
      transform: rotate(-45deg);
   }
   .icon-del {
      width: 15px;
      height: 1px;
      background-color: #333;
      // border-radius: 1px;
   }
   /* #ifdef H5 */
   @media all and (min-width: 768px) {
      .uni-file-picker__files {
         max-width: 375px;
      }
   }
   /* #endif */
</style>
<template>
   <view class="uni-file-picker__files">
      <view v-if="!readonly" class="files-button" @click="choose">
         <slot></slot>
      </view>
      <!-- :class="{'is-text-box':showType === 'list'}" -->
      <view v-if="list.length > 0" class="uni-file-picker__lists is-text-box" :style="borderStyle">
         <!-- ,'is-list-card':showType === 'list-card' -->
         <view class="uni-file-picker__lists-box" v-for="(item ,index) in list" :key="index" :class="{
            'files-border':index !== 0 && styles.dividline}"
          :style="index !== 0 && styles.dividline &&borderLineStyle">
            <view class="uni-file-picker__item">
               <!-- :class="{'is-text-image':showType === 'list'}" -->
               <!--    <view class="files__image is-text-image">
                  <image class="header-image" :src="item.logo" mode="aspectFit"></image>
               </view> -->
               <view class="files__name">{{item.name}}</view>
               <view v-if="delIcon&&!readonly" class="icon-del-box icon-files" @click="delFile(index)">
                  <view class="icon-del icon-files"></view>
                  <view class="icon-del rotate"></view>
               </view>
            </view>
            <view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
               <progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4"
                :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
            </view>
            <view v-if="item.status === 'error'" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
               点击重试
            </view>
         </view>
      </view>
   </view>
</template>
<script>
   export default {
      name: "uploadFile",
      emits:['uploadFiles','choose','delFile'],
      props: {
         filesList: {
            type: Array,
            default () {
               return []
            }
         },
         delIcon: {
            type: Boolean,
            default: true
         },
         limit: {
            type: [Number, String],
            default: 9
         },
         showType: {
            type: String,
            default: ''
         },
         listStyles: {
            type: Object,
            default () {
               return {
                  // 是否显示边框
                  border: true,
                  // 是否显示分隔线
                  dividline: true,
                  // 线条样式
                  borderStyle: {}
               }
            }
         },
         readonly:{
            type:Boolean,
            default:false
         }
      },
      computed: {
         list() {
            let files = []
            this.filesList.forEach(v => {
               files.push(v)
            })
            return files
         },
         styles() {
            let styles = {
               border: true,
               dividline: true,
               'border-style': {}
            }
            return Object.assign(styles, this.listStyles)
         },
         borderStyle() {
            let {
               borderStyle,
               border
            } = this.styles
            let obj = {}
            if (!border) {
               obj.border = 'none'
            } else {
               let width = (borderStyle && borderStyle.width) || 1
               width = this.value2px(width)
               let radius = (borderStyle && borderStyle.radius) || 5
               radius = this.value2px(radius)
               obj = {
                  'border-width': width,
                  'border-style': (borderStyle && borderStyle.style) || 'solid',
                  'border-color': (borderStyle && borderStyle.color) || '#eee',
                  'border-radius': radius
               }
            }
            let classles = ''
            for (let i in obj) {
               classles += `${i}:${obj[i]};`
            }
            return classles
         },
         borderLineStyle() {
            let obj = {}
            let {
               borderStyle
            } = this.styles
            if (borderStyle && borderStyle.color) {
               obj['border-color'] = borderStyle.color
            }
            if (borderStyle && borderStyle.width) {
               let width = borderStyle && borderStyle.width || 1
               let style = borderStyle && borderStyle.style || 0
               if (typeof width === 'number') {
                  width += 'px'
               } else {
                  width = width.indexOf('px') ? width : width + 'px'
               }
               obj['border-width'] = width
               if (typeof style === 'number') {
                  style += 'px'
               } else {
                  style = style.indexOf('px') ? style : style + 'px'
               }
               obj['border-top-style'] = style
            }
            let classles = ''
            for (let i in obj) {
               classles += `${i}:${obj[i]};`
            }
            return classles
         }
      },
      methods: {
         uploadFiles(item, index) {
            this.$emit("uploadFiles", {
               item,
               index
            })
         },
         choose() {
            this.$emit("choose")
         },
         delFile(index) {
            this.$emit('delFile', index)
         },
         value2px(value) {
            if (typeof value === 'number') {
               value += 'px'
            } else {
               value = value.indexOf('px') !== -1 ? value : value + 'px'
            }
            return value
         }
      }
   }
</script>
<style lang="scss">
   .uni-file-picker__files {
      /* #ifndef APP-NVUE */
      display: flex;
      /* #endif */
      flex-direction: column;
      justify-content: flex-start;
   }
   .files-button {
      // border: 1px red solid;
   }
   .uni-file-picker__lists {
      position: relative;
      margin-top: 5px;
      overflow: hidden;
   }
   .file-picker__mask {
      /* #ifndef APP-NVUE */
      display: flex;
      /* #endif */
      justify-content: center;
      align-items: center;
      position: absolute;
      right: 0;
      top: 0;
      bottom: 0;
      left: 0;
      color: #fff;
      font-size: 14px;
      background-color: rgba(0, 0, 0, 0.4);
   }
   .uni-file-picker__lists-box {
      position: relative;
   }
   .uni-file-picker__item {
      /* #ifndef APP-NVUE */
      display: flex;
      /* #endif */
      align-items: center;
      padding: 8px 10px;
      padding-right: 5px;
      padding-left: 10px;
   }
   .files-border {
      border-top: 1px #eee solid;
   }
   .files__name {
      flex: 1;
      font-size: 14px;
      color: #666;
      margin-right: 25px;
      /* #ifndef APP-NVUE */
      word-break: break-all;
      word-wrap: break-word;
      /* #endif */
   }
   .icon-files {
      /* #ifndef APP-NVUE */
      position: static;
      background-color: initial;
      /* #endif */
   }
   // .icon-files .icon-del {
   //    background-color: #333;
   //    width: 12px;
   //    height: 1px;
   // }
   .is-list-card {
      border: 1px #eee solid;
      margin-bottom: 5px;
      border-radius: 5px;
      box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.1);
      padding: 5px;
   }
   .files__image {
      width: 40px;
      height: 40px;
      margin-right: 10px;
   }
   .header-image {
      width: 100%;
      height: 100%;
   }
   .is-text-box {
      border: 1px #eee solid;
      border-radius: 5px;
   }
   .is-text-image {
      width: 25px;
      height: 25px;
      margin-left: 5px;
   }
   .rotate {
      position: absolute;
      transform: rotate(90deg);
   }
   .icon-del-box {
      /* #ifndef APP-NVUE */
      display: flex;
      margin: auto 0;
      /* #endif */
      align-items: center;
      justify-content: center;
      position: absolute;
      top: 0px;
      bottom: 0;
      right: 5px;
      height: 26px;
      width: 26px;
      // border-radius: 50%;
      // background-color: rgba(0, 0, 0, 0.5);
      z-index: 2;
      transform: rotate(-45deg);
   }
   .icon-del {
      width: 15px;
      height: 1px;
      background-color: #333;
      // border-radius: 1px;
   }
   /* #ifdef H5 */
   @media all and (min-width: 768px) {
      .uni-file-picker__files {
         max-width: 375px;
      }
   }
   /* #endif */
</style>