upload.js 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352
  1. var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
  2. var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  3. if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
  4. else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  5. return c > 3 && r && Object.defineProperty(target, key, r), r;
  6. };
  7. var __rest = (this && this.__rest) || function (s, e) {
  8. var t = {};
  9. for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
  10. t[p] = s[p];
  11. if (s != null && typeof Object.getOwnPropertySymbols === "function")
  12. for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
  13. if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
  14. t[p[i]] = s[p[i]];
  15. }
  16. return t;
  17. };
  18. import { isObject, SuperComponent, wxComponent } from '../common/src/index';
  19. import props from './props';
  20. import config from '../common/config';
  21. import { isOverSize } from '../common/utils';
  22. const { prefix } = config;
  23. const name = `${prefix}-upload`;
  24. let Upload = class Upload extends SuperComponent {
  25. constructor() {
  26. super(...arguments);
  27. this.externalClasses = [`${prefix}-class`];
  28. this.options = {
  29. multipleSlots: true,
  30. };
  31. this.data = {
  32. classPrefix: name,
  33. prefix,
  34. current: false,
  35. proofs: [],
  36. customFiles: [],
  37. customLimit: 0,
  38. column: 4,
  39. dragBaseData: {},
  40. rows: 0,
  41. dragWrapStyle: '',
  42. dragList: [],
  43. dragging: true,
  44. dragLayout: false,
  45. };
  46. this.properties = props;
  47. this.controlledProps = [
  48. {
  49. key: 'files',
  50. event: 'success',
  51. },
  52. ];
  53. this.observers = {
  54. 'files, max, draggable'(files, max) {
  55. this.handleLimit(files, max);
  56. },
  57. gridConfig() {
  58. this.updateGrid();
  59. },
  60. };
  61. this.lifetimes = {
  62. ready() {
  63. this.handleLimit(this.data.customFiles, this.data.max);
  64. this.updateGrid();
  65. },
  66. };
  67. this.methods = {
  68. uploadFiles(files) {
  69. return new Promise((resolve) => {
  70. const task = this.data.requestMethod(files);
  71. if (task instanceof Promise) {
  72. return task;
  73. }
  74. resolve({});
  75. });
  76. },
  77. startUpload(files) {
  78. if (typeof this.data.requestMethod === 'function') {
  79. return this.uploadFiles(files)
  80. .then(() => {
  81. files.forEach((file) => {
  82. file.percent = 100;
  83. });
  84. this.triggerSuccessEvent(files);
  85. })
  86. .catch((err) => {
  87. this.triggerFailEvent(err);
  88. });
  89. }
  90. this.triggerSuccessEvent(files);
  91. this.handleLimit(this.data.customFiles, this.data.max);
  92. return Promise.resolve();
  93. },
  94. onAddTap() {
  95. const { disabled, mediaType, source } = this.properties;
  96. if (disabled)
  97. return;
  98. if (source === 'media') {
  99. this.chooseMedia(mediaType);
  100. }
  101. else {
  102. this.chooseMessageFile(mediaType);
  103. }
  104. },
  105. chooseMedia(mediaType) {
  106. const { config, sizeLimit, customLimit } = this.data;
  107. wx.chooseMedia(Object.assign(Object.assign({ count: customLimit, mediaType }, config), { success: (res) => {
  108. const files = [];
  109. res.tempFiles.forEach((temp) => {
  110. const { size, fileType, tempFilePath, width, height, duration, thumbTempFilePath } = temp, res = __rest(temp, ["size", "fileType", "tempFilePath", "width", "height", "duration", "thumbTempFilePath"]);
  111. if (isOverSize(size, sizeLimit)) {
  112. let title = `${fileType === 'image' ? '图片' : '视频'}大小超过限制`;
  113. if (typeof sizeLimit !== 'number') {
  114. title = sizeLimit.message.replace('{sizeLimit}', sizeLimit === null || sizeLimit === void 0 ? void 0 : sizeLimit.size);
  115. }
  116. wx.showToast({ icon: 'none', title });
  117. return;
  118. }
  119. const name = this.getRandFileName(tempFilePath);
  120. files.push(Object.assign({ name, type: this.getFileType(mediaType, tempFilePath, fileType), url: tempFilePath, size: size, width: width, height: height, duration: duration, thumb: thumbTempFilePath, percent: 0 }, res));
  121. });
  122. this.afterSelect(files);
  123. }, fail: (err) => {
  124. this.triggerFailEvent(err);
  125. }, complete: (res) => {
  126. this.triggerEvent('complete', res);
  127. } }));
  128. },
  129. chooseMessageFile(mediaType) {
  130. const { max, config, sizeLimit } = this.properties;
  131. wx.chooseMessageFile(Object.assign(Object.assign({ count: max, type: Array.isArray(mediaType) ? 'all' : mediaType }, config), { success: (res) => {
  132. const files = [];
  133. res.tempFiles.forEach((temp) => {
  134. const { size, type: fileType, path: tempFilePath } = temp, res = __rest(temp, ["size", "type", "path"]);
  135. if (isOverSize(size, sizeLimit)) {
  136. let title = `${fileType === 'image' ? '图片' : '视频'}大小超过限制`;
  137. if (typeof sizeLimit !== 'number') {
  138. title = sizeLimit.message.replace('{sizeLimit}', sizeLimit === null || sizeLimit === void 0 ? void 0 : sizeLimit.size);
  139. }
  140. wx.showToast({ icon: 'none', title });
  141. return;
  142. }
  143. const name = this.getRandFileName(tempFilePath);
  144. files.push(Object.assign({ name, type: this.getFileType(mediaType, tempFilePath, fileType), url: tempFilePath, size: size, percent: 0 }, res));
  145. });
  146. this.afterSelect(files);
  147. }, fail: (err) => this.triggerFailEvent(err), complete: (res) => this.triggerEvent('complete', res) }));
  148. },
  149. afterSelect(files) {
  150. this._trigger('select-change', {
  151. files: [...this.data.customFiles],
  152. currentSelectedFiles: [files],
  153. });
  154. this._trigger('add', { files });
  155. this.startUpload(files);
  156. },
  157. dragVibrate(e) {
  158. var _a;
  159. const { vibrateType } = e;
  160. const { draggable } = this.data;
  161. const dragVibrate = (_a = draggable === null || draggable === void 0 ? void 0 : draggable.vibrate) !== null && _a !== void 0 ? _a : true;
  162. const dragCollisionVibrate = draggable === null || draggable === void 0 ? void 0 : draggable.collisionVibrate;
  163. if ((dragVibrate && vibrateType === 'longPress') || (dragCollisionVibrate && vibrateType === 'touchMove')) {
  164. wx.vibrateShort({
  165. type: 'light',
  166. });
  167. }
  168. },
  169. dragStatusChange(e) {
  170. const { dragging } = e;
  171. this.setData({ dragging });
  172. },
  173. dragEnd(e) {
  174. const { dragCollisionList } = e;
  175. let files = [];
  176. if (dragCollisionList.length === 0) {
  177. files = this.data.customFiles;
  178. }
  179. else {
  180. files = dragCollisionList.reduce((list, item) => {
  181. const { realKey, data, fixed } = item;
  182. if (!fixed) {
  183. list[realKey] = Object.assign({}, data);
  184. }
  185. return list;
  186. }, []);
  187. }
  188. this.triggerDropEvent(files);
  189. },
  190. triggerDropEvent(files) {
  191. const { transition } = this.properties;
  192. if (transition.backTransition) {
  193. const timer = setTimeout(() => {
  194. this.triggerEvent('drop', { files });
  195. clearTimeout(timer);
  196. }, transition.duration);
  197. }
  198. else {
  199. this.triggerEvent('drop', { files });
  200. }
  201. },
  202. };
  203. }
  204. onProofTap(e) {
  205. var _a;
  206. this.onFileClick(e);
  207. const { index } = e.currentTarget.dataset;
  208. wx.previewImage({
  209. urls: this.data.customFiles.filter((file) => file.percent !== -1).map((file) => file.url),
  210. current: (_a = this.data.customFiles[index]) === null || _a === void 0 ? void 0 : _a.url,
  211. });
  212. }
  213. handleLimit(customFiles, max) {
  214. if (max === 0) {
  215. max = 20;
  216. }
  217. this.setData({
  218. customFiles: customFiles.length > max ? customFiles.slice(0, max) : customFiles,
  219. customLimit: max - customFiles.length,
  220. dragging: true,
  221. });
  222. this.initDragLayout();
  223. }
  224. triggerSuccessEvent(files) {
  225. this._trigger('success', { files: [...this.data.customFiles, ...files] });
  226. }
  227. triggerFailEvent(err) {
  228. this.triggerEvent('fail', err);
  229. }
  230. onFileClick(e) {
  231. const { file } = e.currentTarget.dataset;
  232. this.triggerEvent('click', { file });
  233. }
  234. getFileType(mediaType, tempFilePath, fileType) {
  235. if (fileType)
  236. return fileType;
  237. if (mediaType.length === 1) {
  238. return mediaType[0];
  239. }
  240. const videoType = ['avi', 'wmv', 'mkv', 'mp4', 'mov', 'rm', '3gp', 'flv', 'mpg', 'rmvb'];
  241. const temp = tempFilePath.split('.');
  242. const postfix = temp[temp.length - 1];
  243. if (videoType.includes(postfix.toLocaleLowerCase())) {
  244. return 'video';
  245. }
  246. return 'image';
  247. }
  248. getRandFileName(filePath) {
  249. const extIndex = filePath.lastIndexOf('.');
  250. const extName = extIndex === -1 ? '' : filePath.substr(extIndex);
  251. return parseInt(`${Date.now()}${Math.floor(Math.random() * 900 + 100)}`, 10).toString(36) + extName;
  252. }
  253. onDelete(e) {
  254. const { index } = e.currentTarget.dataset;
  255. this.deleteHandle(index);
  256. }
  257. deleteHandle(index) {
  258. const { customFiles } = this.data;
  259. const delFile = customFiles[index];
  260. this.triggerEvent('remove', { index, file: delFile });
  261. }
  262. updateGrid() {
  263. let { gridConfig = {} } = this.properties;
  264. if (!isObject(gridConfig))
  265. gridConfig = {};
  266. const { column = 4, width = 160, height = 160 } = gridConfig;
  267. this.setData({
  268. gridItemStyle: `width:${width}rpx;height:${height}rpx`,
  269. column: column,
  270. });
  271. }
  272. initDragLayout() {
  273. const { draggable, disabled } = this.properties;
  274. if (!draggable || disabled)
  275. return;
  276. this.initDragList();
  277. this.initDragBaseData();
  278. }
  279. initDragList() {
  280. let i = 0;
  281. const { column, customFiles, customLimit } = this.data;
  282. const dragList = [];
  283. customFiles.forEach((item, index) => {
  284. dragList.push({
  285. realKey: i,
  286. sortKey: index,
  287. tranX: `${(index % column) * 100}%`,
  288. tranY: `${Math.floor(index / column) * 100}%`,
  289. data: Object.assign({}, item),
  290. });
  291. i += 1;
  292. });
  293. if (customLimit > 0) {
  294. const listLength = dragList.length;
  295. dragList.push({
  296. realKey: listLength,
  297. sortKey: listLength,
  298. tranX: `${(listLength % column) * 100}%`,
  299. tranY: `${Math.floor(listLength / column) * 100}%`,
  300. fixed: true,
  301. });
  302. }
  303. this.data.rows = Math.ceil(dragList.length / column);
  304. this.setData({
  305. dragList,
  306. });
  307. }
  308. initDragBaseData() {
  309. const { classPrefix, rows, column, customFiles } = this.data;
  310. if (customFiles.length === 0) {
  311. this.setData({
  312. dragBaseData: {},
  313. dragWrapStyle: '',
  314. dragLayout: false,
  315. });
  316. return;
  317. }
  318. const query = this.createSelectorQuery();
  319. const selectorGridItem = `.${classPrefix} >>> .t-grid-item`;
  320. const selectorGrid = `.${classPrefix} >>> .t-grid`;
  321. query.select(selectorGridItem).boundingClientRect();
  322. query.select(selectorGrid).boundingClientRect();
  323. query.selectViewport().scrollOffset();
  324. query.exec((res) => {
  325. const [{ width, height }, { left, top }, { scrollTop }] = res;
  326. const dragBaseData = {
  327. rows,
  328. classPrefix,
  329. itemWidth: width,
  330. itemHeight: height,
  331. wrapLeft: left,
  332. wrapTop: top + scrollTop,
  333. columns: column,
  334. };
  335. const dragWrapStyle = `height: ${rows * height}px`;
  336. this.setData({
  337. dragBaseData,
  338. dragWrapStyle,
  339. dragLayout: true,
  340. }, () => {
  341. const timer = setTimeout(() => {
  342. this.setData({ dragging: false });
  343. clearTimeout(timer);
  344. }, 0);
  345. });
  346. });
  347. }
  348. };
  349. Upload = __decorate([
  350. wxComponent()
  351. ], Upload);
  352. export default Upload;