You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

321 rivejä
7.4 KiB

  1. <template>
  2. <view class="lsj-file" :style="[getStyles]">
  3. <view ref="lsj" class="hFile" :style="[getStyles]" @click="onClick">
  4. <slot><view class="defview" :style="[getStyles]">点击上传</view></slot>
  5. </view>
  6. </view>
  7. </template>
  8. <script>
  9. // 查看文档:https://ext.dcloud.net.cn/plugin?id=5459
  10. import {LsjFile} from './LsjFile.js'
  11. export default {
  12. name: 'Lsj-upload',
  13. props: {
  14. // 打印日志
  15. debug: {type: Boolean,default: false},
  16. // 自动上传
  17. instantly: {type: Boolean,default: false},
  18. // 上传接口参数设置
  19. option: {type: Object,default: ()=>{}},
  20. // 文件大小上限
  21. size: { type: Number, default: 10 },
  22. // 文件选择个数上限,超出后不触发点击
  23. count: { type: Number, default: 9 },
  24. // 允许上传的文件格式(多个以逗号隔开)
  25. formats: { type: String, default:''},
  26. // input file选择限制
  27. accept: {type: String,default: ''},
  28. // 微信选择文件类型
  29. //all=从所有文件选择,
  30. //video=只能选择视频文件,
  31. //image=只能选择图片文件,
  32. //file=可以选择除了图片和视频之外的其它的文件
  33. wxFileType: { type: String, default: 'all' },
  34. // webviewID需唯一,不同窗口也不要同Id
  35. childId: { type: String, default: 'lsjUpload' },
  36. // 文件选择触发面宽度
  37. width: { type: String, default: '100%' },
  38. // 文件选择触发面高度
  39. height: { type: String, default: '80rpx' },
  40. // top,left,bottom,right仅position=absolute时才需要传入
  41. top: { type: [String, Number], default: '' },
  42. left: { type: [String, Number], default: '' },
  43. bottom: { type: [String, Number], default: '' },
  44. right: { type: [String, Number], default: '' },
  45. // nvue不支持跟随窗口滚动
  46. position: {
  47. type: String,
  48. // #ifdef APP-NVUE
  49. default: 'absolute',
  50. // #endif
  51. // #ifndef APP-NVUE
  52. default: 'static',
  53. // #endif
  54. },
  55. },
  56. data() {
  57. return {
  58. }
  59. },
  60. watch: {
  61. option(v) {
  62. // #ifdef APP-PLUS
  63. this.lsjFile&&this.show();
  64. // #endif
  65. }
  66. },
  67. updated() {
  68. // #ifdef APP-PLUS
  69. if (this.isShow) {
  70. this.lsjFile&&this.show();
  71. }
  72. // #endif
  73. },
  74. computed: {
  75. getStyles() {
  76. let styles = {
  77. width: this.width,
  78. height: this.height
  79. }
  80. if (this.position == 'absolute') {
  81. styles['top'] = this.top
  82. styles['bottom'] = this.bottom
  83. styles['left'] = this.left
  84. styles['right'] = this.right
  85. styles['position'] = 'fixed'
  86. }
  87. return styles
  88. }
  89. },
  90. mounted() {
  91. this._size = 0;
  92. let WEBID = this.childId + new Date().getTime();
  93. this.lsjFile = new LsjFile({
  94. id: WEBID,
  95. debug: this.debug,
  96. width: this.width,
  97. height: this.height,
  98. option: this.option,
  99. instantly: this.instantly,
  100. // 限制条件
  101. prohibited: {
  102. // 大小
  103. size: this.size,
  104. // 允许上传的格式
  105. formats: this.formats,
  106. // 限制选择的格式
  107. accept: this.accept,
  108. count: this.count
  109. },
  110. onchange: this.onchange,
  111. onprogress: this.onprogress,
  112. });
  113. this.create();
  114. },
  115. beforeDestroy() {
  116. // #ifdef APP-PLUS
  117. this.lsjFile.dom.close();
  118. // #endif
  119. },
  120. methods: {
  121. setFiles(array) {
  122. if (array instanceof Map) {
  123. for (let [key, item] of array) {
  124. item['progress'] = 100;
  125. item['type'] = 'success';
  126. this.lsjFile.files.set(key,item);
  127. }
  128. }
  129. else if (Array.isArray(array)) {
  130. array.forEach(item=>{
  131. if (item.name) {
  132. item['progress'] = 100;
  133. item['type'] = 'success';
  134. this.lsjFile.files.set(item.name,item);
  135. }
  136. });
  137. }
  138. this.onchange(this.lsjFile.files);
  139. },
  140. setData() {
  141. this.lsjFile&&this.lsjFile.setData(...arguments);
  142. },
  143. getDomStyles(callback) {
  144. // #ifndef APP-NVUE
  145. let view = uni
  146. .createSelectorQuery()
  147. .in(this)
  148. .select('.lsj-file')
  149. view.fields(
  150. {
  151. size: true,
  152. rect: true
  153. },
  154. ({ height, width, top, left, right, bottom }) => {
  155. uni.createSelectorQuery()
  156. .selectViewport()
  157. .scrollOffset(({ scrollTop }) => {
  158. return callback({
  159. top: parseInt(top) + parseInt(scrollTop) + 'px',
  160. left: parseInt(left) + 'px',
  161. width: parseInt(width) + 'px',
  162. height: parseInt(height) + 'px'
  163. })
  164. })
  165. .exec()
  166. }
  167. ).exec()
  168. // #endif
  169. // #ifdef APP-NVUE
  170. const dom = weex.requireModule('dom')
  171. dom.getComponentRect(this.$refs.lsj, ({ size: { height, width, top, left, right, bottom } }) => {
  172. return callback({
  173. top: parseInt(top) + 'px',
  174. left: parseInt(left) + 'px',
  175. width: parseInt(width) + 'px',
  176. height: parseInt(height) + 'px',
  177. right: parseInt(right) + 'px',
  178. bottom: parseInt(bottom) + 'px'
  179. })
  180. })
  181. // #endif
  182. },
  183. show() {
  184. this.isShow = true;
  185. // #ifdef APP-PLUS
  186. this.lsjFile&&this.getDomStyles(styles => {
  187. this.lsjFile.dom.setStyle(styles)
  188. });
  189. // #endif
  190. // #ifdef H5
  191. this.lsjFile.dom.style.display = 'inline'
  192. // #endif
  193. },
  194. hide() {
  195. this.isShow = false;
  196. // #ifdef APP-PLUS
  197. this.lsjFile&&this.lsjFile.dom.setStyle({
  198. top: '-100px',
  199. left:'0px',
  200. width: '1px',
  201. height: '100px',
  202. });
  203. // #endif
  204. // #ifdef H5
  205. this.lsjFile.dom.style.display = 'none'
  206. // #endif
  207. },
  208. /**
  209. * 手动提交上传
  210. * @param {string}name 文件名称,不传则上传所有type等于waiting和fail的文件
  211. */
  212. upload(name) {
  213. this.lsjFile&&this.lsjFile.upload(name);
  214. },
  215. /**
  216. * @returns {Map} 已选择的文件Map集
  217. */
  218. onchange(files) {
  219. this.$emit('change',files);
  220. this._size = files.size;
  221. return files.size >= this.count ? this.hide() : this.show();
  222. },
  223. /**
  224. * @returns {object} 当前上传中的对象
  225. */
  226. onprogress(item,end=false) {
  227. this.$emit('progress',item);
  228. if (end) {
  229. setTimeout(()=>{
  230. this.$emit('uploadEnd',item);
  231. },0);
  232. }
  233. },
  234. /**
  235. * 移除组件内缓存的某条数据
  236. * @param {string}name 文件名称,不指定默认清除所有文件
  237. */
  238. clear(name) {
  239. this.lsjFile.clear(name);
  240. },
  241. // 创建选择器
  242. create() {
  243. // 若iOS端服务端处理不了跨域就将hybrid目录内的html放到服务端去,并将此处path改成服务器上的地址
  244. let path = '/static/html/uploadFile.html';
  245. let dom = this.lsjFile.create(path);
  246. // #ifdef H5
  247. this.$refs.lsj.$el.appendChild(dom);
  248. // #endif
  249. // #ifndef APP-PLUS
  250. this.show();
  251. // #endif
  252. // #ifdef APP-PLUS
  253. dom.setStyle({position: this.position});
  254. dom.loadURL(path);
  255. setTimeout(()=>{
  256. // #ifdef APP-NVUE
  257. plus.webview.currentWebview().append(dom);
  258. // #endif
  259. // #ifndef APP-NVUE
  260. this.$root.$scope.$getAppWebview().append(dom);
  261. // #endif
  262. this.show();
  263. },300)
  264. // #endif
  265. },
  266. // 点击选择附件
  267. onClick() {
  268. if (this._size >= this.count) {
  269. this.toast(`只允许上传${this.count}个文件`);
  270. return;
  271. }
  272. // #ifdef MP-WEIXIN
  273. if (!this.isShow) {return;}
  274. let count = this.count - this._size;
  275. this.lsjFile.chooseMessageFile(this.wxFileType,count);
  276. // #endif
  277. },
  278. toast(msg) {
  279. uni.showToast({
  280. title: msg,
  281. icon: 'none'
  282. });
  283. },
  284. newguid() {
  285. return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
  286. var r = Math.random() * 16 | 0,
  287. v = c == 'x' ? r : (r & 0x3 | 0x8);
  288. return v.toString(16);
  289. });
  290. },
  291. }
  292. }
  293. </script>
  294. <style scoped>
  295. .lsj-file {
  296. display: inline-block;
  297. }
  298. .defview {
  299. background-color: #007aff;
  300. color: #fff;
  301. border-radius: 10rpx;
  302. display: flex;
  303. align-items: center;
  304. justify-content: center;
  305. font-size: 28rpx;
  306. }
  307. .hFile {
  308. position: relative;
  309. overflow: hidden;
  310. }
  311. </style>