upload-file.vue 6.5 KB

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