upload-file.vue 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. <template>
  2. <view class="uni-file-picker__files">
  3. <view v-if="!readonly" class="files-button" @click="choose">
  4. <slot></slot>
  5. </view>
  6. <!-- :class="{'is-text-box':showType === 'list'}" -->
  7. <view v-if="list.length > 0" class="uni-file-picker__lists is-text-box" :style="borderStyle">
  8. <!-- ,'is-list-card':showType === 'list-card' -->
  9. <view class="uni-file-picker__lists-box" v-for="(item ,index) in list" :key="index" :class="{
  10. 'files-border':index !== 0 && styles.dividline}" :style="index !== 0 && styles.dividline &&borderLineStyle">
  11. <view class="uni-file-picker__item">
  12. <!-- :class="{'is-text-image':showType === 'list'}" -->
  13. <!-- <view class="files__image is-text-image">
  14. <image class="header-image" :src="item.logo" mode="aspectFit"></image>
  15. </view> -->
  16. <view class="files__name">{{item.name}}</view>
  17. <view v-if="delIcon&&!readonly" class="icon-del-box icon-files" @click="delFile(index)">
  18. <view class="icon-del icon-files"></view>
  19. <view class="icon-del rotate"></view>
  20. </view>
  21. </view>
  22. <view v-if="(item.progress && item.progress !== 100) ||item.progress===0 " class="file-picker__progress">
  23. <progress class="file-picker__progress-item" :percent="item.progress === -1?0:item.progress" stroke-width="4" :backgroundColor="item.errMsg?'#ff5a5f':'#EBEBEB'" />
  24. </view>
  25. <view v-if="item.status === 'error'" class="file-picker__mask" @click.stop="uploadFiles(item,index)">
  26. 点击重试
  27. </view>
  28. </view>
  29. </view>
  30. </view>
  31. </template>
  32. <script>
  33. export default {
  34. name: "uploadFile",
  35. emits: ['uploadFiles', 'choose', 'delFile'],
  36. props: {
  37. filesList: {
  38. type: Array,
  39. default () {
  40. return []
  41. }
  42. },
  43. delIcon: {
  44. type: Boolean,
  45. default: true
  46. },
  47. limit: {
  48. type: [Number, String],
  49. default: 9
  50. },
  51. showType: {
  52. type: String,
  53. default: ''
  54. },
  55. listStyles: {
  56. type: Object,
  57. default () {
  58. return {
  59. // 是否显示边框
  60. border: true,
  61. // 是否显示分隔线
  62. dividline: true,
  63. // 线条样式
  64. borderStyle: {}
  65. }
  66. }
  67. },
  68. readonly: {
  69. type: Boolean,
  70. default: false
  71. }
  72. },
  73. computed: {
  74. list() {
  75. let files = []
  76. this.filesList.forEach(v => {
  77. files.push(v)
  78. })
  79. return files
  80. },
  81. styles() {
  82. let styles = {
  83. border: true,
  84. dividline: true,
  85. 'border-style': {}
  86. }
  87. return Object.assign(styles, this.listStyles)
  88. },
  89. borderStyle() {
  90. let {
  91. borderStyle,
  92. border
  93. } = this.styles
  94. let obj = {}
  95. if (!border) {
  96. obj.border = 'none'
  97. } else {
  98. let width = (borderStyle && borderStyle.width) || 1
  99. width = this.value2px(width)
  100. let radius = (borderStyle && borderStyle.radius) || 5
  101. radius = this.value2px(radius)
  102. obj = {
  103. 'border-width': width,
  104. 'border-style': (borderStyle && borderStyle.style) || 'solid',
  105. 'border-color': (borderStyle && borderStyle.color) || '#eee',
  106. 'border-radius': radius
  107. }
  108. }
  109. let classles = ''
  110. for (let i in obj) {
  111. classles += `${i}:${obj[i]};`
  112. }
  113. return classles
  114. },
  115. borderLineStyle() {
  116. let obj = {}
  117. let {
  118. borderStyle
  119. } = this.styles
  120. if (borderStyle && borderStyle.color) {
  121. obj['border-color'] = borderStyle.color
  122. }
  123. if (borderStyle && borderStyle.width) {
  124. let width = borderStyle && borderStyle.width || 1
  125. let style = borderStyle && borderStyle.style || 0
  126. if (typeof width === 'number') {
  127. width += 'px'
  128. } else {
  129. width = width.indexOf('px') ? width : width + 'px'
  130. }
  131. obj['border-width'] = width
  132. if (typeof style === 'number') {
  133. style += 'px'
  134. } else {
  135. style = style.indexOf('px') ? style : style + 'px'
  136. }
  137. obj['border-top-style'] = style
  138. }
  139. let classles = ''
  140. for (let i in obj) {
  141. classles += `${i}:${obj[i]};`
  142. }
  143. return classles
  144. }
  145. },
  146. methods: {
  147. uploadFiles(item, index) {
  148. this.$emit("uploadFiles", {
  149. item,
  150. index
  151. })
  152. },
  153. choose() {
  154. this.$emit("choose")
  155. },
  156. delFile(index) {
  157. this.$emit('delFile', index)
  158. },
  159. value2px(value) {
  160. if (typeof value === 'number') {
  161. value += 'px'
  162. } else {
  163. value = value.indexOf('px') !== -1 ? value : value + 'px'
  164. }
  165. return value
  166. }
  167. }
  168. }
  169. </script>
  170. <style lang="scss">
  171. .uni-file-picker__files {
  172. /* #ifndef APP-NVUE */
  173. display: flex;
  174. /* #endif */
  175. flex-direction: column;
  176. justify-content: flex-start;
  177. }
  178. .files-button {
  179. // border: 1px red solid;
  180. }
  181. .uni-file-picker__lists {
  182. position: relative;
  183. margin-top: 5px;
  184. overflow: hidden;
  185. }
  186. .file-picker__mask {
  187. /* #ifndef APP-NVUE */
  188. display: flex;
  189. /* #endif */
  190. justify-content: center;
  191. align-items: center;
  192. position: absolute;
  193. right: 0;
  194. top: 0;
  195. bottom: 0;
  196. left: 0;
  197. color: #fff;
  198. font-size: 14px;
  199. background-color: rgba(0, 0, 0, 0.4);
  200. }
  201. .uni-file-picker__lists-box {
  202. position: relative;
  203. }
  204. .uni-file-picker__item {
  205. /* #ifndef APP-NVUE */
  206. display: flex;
  207. /* #endif */
  208. align-items: center;
  209. padding: 8px 10px;
  210. padding-right: 5px;
  211. padding-left: 10px;
  212. }
  213. .files-border {
  214. border-top: 1px #eee solid;
  215. }
  216. .files__name {
  217. flex: 1;
  218. font-size: 14px;
  219. color: #666;
  220. margin-right: 25px;
  221. /* #ifndef APP-NVUE */
  222. word-break: break-all;
  223. word-wrap: break-word;
  224. /* #endif */
  225. }
  226. .icon-files {
  227. /* #ifndef APP-NVUE */
  228. position: static;
  229. background-color: initial;
  230. /* #endif */
  231. }
  232. // .icon-files .icon-del {
  233. // background-color: #333;
  234. // width: 12px;
  235. // height: 1px;
  236. // }
  237. .is-list-card {
  238. border: 1px #eee solid;
  239. margin-bottom: 5px;
  240. border-radius: 5px;
  241. box-shadow: 0 0 2px 0px rgba(0, 0, 0, 0.1);
  242. padding: 5px;
  243. }
  244. .files__image {
  245. width: 40px;
  246. height: 40px;
  247. margin-right: 10px;
  248. }
  249. .header-image {
  250. width: 100%;
  251. height: 100%;
  252. }
  253. .is-text-box {
  254. border: 1px #eee solid;
  255. border-radius: 5px;
  256. }
  257. .is-text-image {
  258. width: 25px;
  259. height: 25px;
  260. margin-left: 5px;
  261. }
  262. .rotate {
  263. position: absolute;
  264. transform: rotate(90deg);
  265. }
  266. .icon-del-box {
  267. /* #ifndef APP-NVUE */
  268. display: flex;
  269. margin: auto 0;
  270. /* #endif */
  271. align-items: center;
  272. justify-content: center;
  273. position: absolute;
  274. top: 0px;
  275. bottom: 0;
  276. right: 5px;
  277. height: 26px;
  278. width: 26px;
  279. // border-radius: 50%;
  280. // background-color: rgba(0, 0, 0, 0.5);
  281. z-index: 2;
  282. transform: rotate(-45deg);
  283. }
  284. .icon-del {
  285. width: 15px;
  286. height: 1px;
  287. background-color: #333;
  288. // border-radius: 1px;
  289. }
  290. /* #ifdef H5 */
  291. @media all and (min-width: 768px) {
  292. .uni-file-picker__files {
  293. max-width: 375px;
  294. }
  295. }
  296. /* #endif */
  297. </style>