utils.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  1. export const networkReg = /^(http|\/\/)/;
  2. export const isBase64 = (path) => /^data:image\/(\w+);base64/.test(path);
  3. export function sleep(delay) {
  4. return new Promise(resolve => setTimeout(resolve, delay))
  5. }
  6. const isDev = ['devtools'].includes(uni.getSystemInfoSync().platform)
  7. // 缓存图片
  8. let cache = {}
  9. export function isNumber(value) {
  10. return /^-?\d+(\.\d+)?$/.test(value);
  11. }
  12. export function toPx(value, baseSize, isDecimal = false) {
  13. // 如果是数字
  14. if (typeof value === 'number') {
  15. return value
  16. }
  17. // 如果是字符串数字
  18. if (isNumber(value)) {
  19. return value * 1
  20. }
  21. // 如果有单位
  22. if (typeof value === 'string') {
  23. const reg = /^-?([0-9]+)?([.]{1}[0-9]+){0,1}(em|rpx|px|%)$/g
  24. const results = reg.exec(value);
  25. if (!value || !results) {
  26. return 0;
  27. }
  28. const unit = results[3];
  29. value = parseFloat(value);
  30. let res = 0;
  31. if (unit === 'rpx') {
  32. res = uni.upx2px(value);
  33. } else if (unit === 'px') {
  34. res = value * 1;
  35. } else if (unit === '%') {
  36. res = value * toPx(baseSize) / 100;
  37. } else if (unit === 'em') {
  38. res = value * toPx(baseSize || 14);
  39. }
  40. return isDecimal ? res.toFixed(2) * 1 : Math.round(res);
  41. }
  42. return 0
  43. }
  44. // 计算版本
  45. export function compareVersion(v1, v2) {
  46. v1 = v1.split('.')
  47. v2 = v2.split('.')
  48. const len = Math.max(v1.length, v2.length)
  49. while (v1.length < len) {
  50. v1.push('0')
  51. }
  52. while (v2.length < len) {
  53. v2.push('0')
  54. }
  55. for (let i = 0; i < len; i++) {
  56. const num1 = parseInt(v1[i], 10)
  57. const num2 = parseInt(v2[i], 10)
  58. if (num1 > num2) {
  59. return 1
  60. } else if (num1 < num2) {
  61. return -1
  62. }
  63. }
  64. return 0
  65. }
  66. // #ifdef MP
  67. export const prefix = () => {
  68. // #ifdef MP-TOUTIAO
  69. return tt
  70. // #endif
  71. // #ifdef MP-WEIXIN
  72. return wx
  73. // #endif
  74. // #ifdef MP-BAIDU
  75. return swan
  76. // #endif
  77. // #ifdef MP-ALIPAY
  78. return my
  79. // #endif
  80. // #ifdef MP-QQ
  81. return qq
  82. // #endif
  83. // #ifdef MP-360
  84. return qh
  85. // #endif
  86. }
  87. // #endif
  88. const base64ToArrayBuffer = (data) => {
  89. // #ifndef MP-WEIXIN || APP-PLUS
  90. /**
  91. * Base64Binary.decode(base64_string);
  92. * Base64Binary.decodeArrayBuffer(base64_string);
  93. */
  94. const Base64Binary = {
  95. _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
  96. /* will return a Uint8Array type */
  97. decodeArrayBuffer(input) {
  98. const bytes = (input.length / 4) * 3;
  99. const ab = new ArrayBuffer(bytes);
  100. this.decode(input, ab);
  101. return ab;
  102. },
  103. removePaddingChars(input) {
  104. const lkey = this._keyStr.indexOf(input.charAt(input.length - 1));
  105. if (lkey == 64) {
  106. return input.substring(0, input.length - 1);
  107. }
  108. return input;
  109. },
  110. decode(input, arrayBuffer) {
  111. //get last chars to see if are valid
  112. input = this.removePaddingChars(input);
  113. input = this.removePaddingChars(input);
  114. const bytes = parseInt((input.length / 4) * 3, 10);
  115. let uarray;
  116. let chr1, chr2, chr3;
  117. let enc1, enc2, enc3, enc4;
  118. let i = 0;
  119. let j = 0;
  120. if (arrayBuffer)
  121. uarray = new Uint8Array(arrayBuffer);
  122. else
  123. uarray = new Uint8Array(bytes);
  124. input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
  125. for (i = 0; i < bytes; i += 3) {
  126. //get the 3 octects in 4 ascii chars
  127. enc1 = this._keyStr.indexOf(input.charAt(j++));
  128. enc2 = this._keyStr.indexOf(input.charAt(j++));
  129. enc3 = this._keyStr.indexOf(input.charAt(j++));
  130. enc4 = this._keyStr.indexOf(input.charAt(j++));
  131. chr1 = (enc1 << 2) | (enc2 >> 4);
  132. chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
  133. chr3 = ((enc3 & 3) << 6) | enc4;
  134. uarray[i] = chr1;
  135. if (enc3 != 64) uarray[i + 1] = chr2;
  136. if (enc4 != 64) uarray[i + 2] = chr3;
  137. }
  138. return uarray;
  139. }
  140. }
  141. return Base64Binary.decodeArrayBuffer(data)
  142. // #endif
  143. // #ifdef MP-WEIXIN || APP-PLUS
  144. return uni.base64ToArrayBuffer(data)
  145. // #endif
  146. }
  147. /**
  148. * base64转路径
  149. * @param {Object} base64
  150. */
  151. export function base64ToPath(base64) {
  152. const [, format] = /^data:image\/(\w+);base64,/.exec(base64) || [];
  153. return new Promise((resolve, reject) => {
  154. // #ifdef MP
  155. const fs = uni.getFileSystemManager()
  156. //自定义文件名
  157. if (!format) {
  158. reject(new Error('ERROR_BASE64SRC_PARSE'))
  159. }
  160. const time = new Date().getTime();
  161. let pre = prefix()
  162. const filePath = `${pre.env.USER_DATA_PATH}/${time}.${format}`
  163. //let buffer = base64ToArrayBuffer(bodyData)
  164. fs.writeFile({
  165. filePath,
  166. data: base64.split(',')[1], //base64.replace(/^data:\S+\/\S+;base64,/, ''),
  167. encoding: 'base64',
  168. // data: buffer,
  169. // encoding: 'binary',
  170. success() {
  171. resolve(filePath)
  172. },
  173. fail(err) {
  174. reject(err)
  175. }
  176. })
  177. // #endif
  178. // #ifdef H5
  179. // mime类型
  180. let mimeString = base64.split(',')[0].split(':')[1].split(';')[0];
  181. //base64 解码
  182. let byteString = atob(base64.split(',')[1]);
  183. //创建缓冲数组
  184. let arrayBuffer = new ArrayBuffer(byteString.length);
  185. //创建视图
  186. let intArray = new Uint8Array(arrayBuffer);
  187. for (let i = 0; i < byteString.length; i++) {
  188. intArray[i] = byteString.charCodeAt(i);
  189. }
  190. resolve(URL.createObjectURL(new Blob([intArray], {
  191. type: mimeString
  192. })))
  193. // #endif
  194. // #ifdef APP-PLUS
  195. const bitmap = new plus.nativeObj.Bitmap('bitmap' + Date.now())
  196. bitmap.loadBase64Data(base64, () => {
  197. if (!format) {
  198. reject(new Error('ERROR_BASE64SRC_PARSE'))
  199. }
  200. const time = new Date().getTime();
  201. const filePath = `_doc/uniapp_temp/${time}.${format}`
  202. bitmap.save(filePath, {},
  203. () => {
  204. bitmap.clear()
  205. resolve(filePath)
  206. },
  207. (error) => {
  208. bitmap.clear()
  209. reject(error)
  210. })
  211. }, (error) => {
  212. bitmap.clear()
  213. reject(error)
  214. })
  215. // #endif
  216. })
  217. }
  218. /**
  219. * 路径转base64
  220. * @param {Object} string
  221. */
  222. export function pathToBase64(path) {
  223. if (/^data:/.test(path)) return path
  224. return new Promise((resolve, reject) => {
  225. // #ifdef H5
  226. let image = new Image();
  227. image.setAttribute("crossOrigin", 'Anonymous');
  228. image.onload = function() {
  229. let canvas = document.createElement('canvas');
  230. canvas.width = this.naturalWidth;
  231. canvas.height = this.naturalHeight;
  232. canvas.getContext('2d').drawImage(image, 0, 0);
  233. let result = canvas.toDataURL('image/png')
  234. resolve(result);
  235. canvas.height = canvas.width = 0
  236. }
  237. image.src = path + '?v=' + Math.random()
  238. image.onerror = (error) => {
  239. reject(error);
  240. };
  241. // #endif
  242. // #ifdef MP
  243. if (uni.canIUse('getFileSystemManager')) {
  244. uni.getFileSystemManager().readFile({
  245. filePath: path,
  246. encoding: 'base64',
  247. success: (res) => {
  248. resolve('data:image/png;base64,' + res.data)
  249. },
  250. fail: (error) => {
  251. reject(error)
  252. }
  253. })
  254. }
  255. // #endif
  256. // #ifdef APP-PLUS
  257. plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), (entry) => {
  258. entry.file((file) => {
  259. const fileReader = new plus.io.FileReader()
  260. fileReader.onload = (data) => {
  261. resolve(data.target.result)
  262. }
  263. fileReader.onerror = (error) => {
  264. reject(error)
  265. }
  266. fileReader.readAsDataURL(file)
  267. }, reject)
  268. }, reject)
  269. // #endif
  270. })
  271. }
  272. export function getImageInfo(path, useCORS) {
  273. return new Promise(async (resolve, reject) => {
  274. let src = path
  275. if (cache[path] && cache[path].errMsg) {
  276. resolve(cache[path])
  277. } else {
  278. try {
  279. // if (!isBase64 && PLATFORM == UNI_PLATFORM.PLUS && !/^\/?(static|_doc)\//.test(src)) {
  280. // src = await downloadFile(path) as string
  281. // } else
  282. // #ifdef MP || APP-PLUS
  283. if (isBase64(path)) {
  284. src = await base64ToPath(path)
  285. }
  286. // #endif
  287. // #ifdef H5
  288. if(useCORS) {
  289. src = await pathToBase64(path)
  290. }
  291. // #endif
  292. } catch (error) {
  293. reject({
  294. ...error,
  295. src
  296. })
  297. }
  298. uni.getImageInfo({
  299. src,
  300. success: (image) => {
  301. const localReg = /^\.|^\/(?=[^\/])/;
  302. // #ifdef MP-WEIXIN || MP-BAIDU || MP-QQ || MP-TOUTIAO
  303. image.path = localReg.test(src) ? `/${image.path}` : image.path;
  304. // #endif
  305. // #ifdef H5
  306. image.path = image.path.replace(/^\./, window.location.origin)
  307. // #endif
  308. if(this.canvas.createImage) {
  309. const img = this.canvas.createImage()
  310. img.src = image.path
  311. img.onload = function() {
  312. image.path = img
  313. cache[path] = image
  314. resolve(cache[path])
  315. }
  316. img.onerror = function(err) {
  317. reject({err,path})
  318. }
  319. } else if (isDev) {
  320. resolve(image)
  321. } else {
  322. cache[path] = image
  323. resolve(cache[path])
  324. }
  325. },
  326. fail(err) {
  327. console.error({err, path})
  328. reject({err,path})
  329. }
  330. })
  331. }
  332. })
  333. }
  334. export function downloadFile(url) {
  335. if (!url) return Promise.reject({
  336. err: 'no url'
  337. })
  338. return new Promise((resolve, reject) => {
  339. if (cache[url]) {
  340. return reject()
  341. }
  342. cache[url] = 1
  343. uni.downloadFile({
  344. url,
  345. success(res) {
  346. resolve(res)
  347. },
  348. fail(err) {
  349. reject(err)
  350. }
  351. })
  352. })
  353. }
  354. // #ifdef APP-PLUS
  355. const getLocalFilePath = (path) => {
  356. if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path
  357. .indexOf('_downloads') === 0) {
  358. return path
  359. }
  360. if (path.indexOf('file://') === 0) {
  361. return path
  362. }
  363. if (path.indexOf('/storage/emulated/0/') === 0) {
  364. return path
  365. }
  366. if (path.indexOf('/') === 0) {
  367. const localFilePath = plus.io.convertAbsoluteFileSystem(path)
  368. if (localFilePath !== path) {
  369. return localFilePath
  370. } else {
  371. path = path.substr(1)
  372. }
  373. }
  374. return '_www/' + path
  375. }
  376. const getFile = (url) => {
  377. return new Promise((resolve, rejcet) => {
  378. plus.io.resolveLocalFileSystemURL(url, resolve, (err) => {
  379. resolve(false)
  380. })
  381. })
  382. }
  383. const createFile = ({
  384. fs,
  385. url,
  386. target,
  387. name
  388. }) => {
  389. return new Promise((resolve, reject) => {
  390. plus.io.resolveLocalFileSystemURL(url, res1 => {
  391. fs.root.getDirectory(target, {
  392. create: true
  393. }, fileEntry => {
  394. const success = () => {
  395. res1.remove()
  396. resolve()
  397. }
  398. getFile(target + name).then(res => {
  399. if (res) {
  400. res.remove((res2) => {
  401. res1.moveTo(fileEntry, name, success, reject)
  402. })
  403. }
  404. res1.moveTo(fileEntry, name, success, reject)
  405. })
  406. })
  407. }, reject)
  408. })
  409. }
  410. export function useNvue(target, version, timeout) {
  411. return new Promise((resolve, reject) => {
  412. plus.io.requestFileSystem(plus.io.PRIVATE_DOC, async (fs) => {
  413. try {
  414. cache['lime-painter'] = 0
  415. let names = ['uni.webview.1.5.3.js', 'painter.js', 'index.html']
  416. let urls = ['https://gitee.com/dcloud/uni-app/raw/dev/dist/',
  417. 'https://static-6d65bd90-8508-4d6c-abbc-a4ef5c8e49e7.bspapp.com/lime-painter/'
  418. ]
  419. const oldVersion = plus.storage.getItem('lime-painter')
  420. const isFile = await getFile(`${target}${names[1]}`)
  421. if (isFile && oldVersion && compareVersion(oldVersion, version) >= 0) {
  422. resolve()
  423. } else {
  424. for (var i = 0; i < names.length; i++) {
  425. const name = names[i]
  426. const file = await downloadFile(urls[i >= 1 ? 1 : 0] + name)
  427. await createFile({
  428. fs,
  429. url: file.tempFilePath,
  430. target,
  431. name: name.includes('uni.webview') ? 'uni.webview.js' : name
  432. })
  433. }
  434. plus.storage.setItem('lime-painter', version)
  435. cache['lime-painter'] = version
  436. resolve()
  437. }
  438. } catch (e) {
  439. let index = parseInt(timeout / 20)
  440. while (!cache['lime-painter'] && index) {
  441. await sleep(20)
  442. index--
  443. }
  444. if (cache['lime-painter']) {
  445. resolve()
  446. } else {
  447. reject(e)
  448. }
  449. }
  450. }, reject)
  451. })
  452. }
  453. // #endif