upload-file.vue 6.8 KB

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