upload-file.vue 6.6 KB

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