@netang/quasar 0.2.7 → 0.2.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -21,7 +21,6 @@
21
21
  :name="errorIcon"
22
22
  />
23
23
  </div>
24
-
25
24
  <!-- 默认插槽 -->
26
25
  <slot />
27
26
  </slot>
@@ -58,7 +57,6 @@
58
57
  :name="errorIcon"
59
58
  />
60
59
  </div>
61
-
62
60
  <!-- 默认插槽 -->
63
61
  <slot />
64
62
  </slot>
@@ -39,6 +39,8 @@ export default {
39
39
  props: {
40
40
  // 值
41
41
  modelValue: [String, Array],
42
+ // 上传器类型
43
+ uploaderType: String,
42
44
  // 上传文件类型, 可选值 file image video audio
43
45
  type: {
44
46
  type: String,
@@ -99,6 +101,9 @@ export default {
99
101
 
100
102
  // 创建上传器
101
103
  const uploader = $n_uploader.create({
104
+ // 上传器类型
105
+ uploaderType: props.uploaderType,
106
+ // 上传文件类型, 可选值 file image video audio
102
107
  type: props.type,
103
108
  // 声明属性
104
109
  props,
@@ -315,6 +315,21 @@
315
315
  />
316
316
 
317
317
  <!-- 播放图标 -->
318
+ <n-thumbnail
319
+ class="rounded-borders cursor-pointer"
320
+ :src="fileItem.json.p"
321
+ :size="currentSize / 1.5"
322
+ title="播放"
323
+ @click.prevent.stop="uploader.play(fileItem)"
324
+ v-else-if="fileItem.json.p"
325
+ >
326
+ <div class="absolute-full no-padding row items-center justify-center">
327
+ <q-icon
328
+ name="play_circle"
329
+ :size="toPx(currentSize / 3)"
330
+ />
331
+ </div>
332
+ </n-thumbnail>
318
333
  <q-icon
319
334
  class="n-uploader-query__item__icon__icon cursor-pointer"
320
335
  name="play_circle"
@@ -431,13 +446,14 @@ import $n_getImage from '../../utils/getImage'
431
446
  import $n_previewImage from '../../utils/previewImage'
432
447
 
433
448
  import NDragger from '../dragger'
449
+ import NThumbnail from '../thumbnail'
434
450
 
435
451
  import { NUploaderKey } from '../../utils/symbols'
436
452
 
437
453
  import {
438
454
  // 上传状态
439
455
  UPLOAD_STATUS,
440
- } from '../../utils/useUploader'
456
+ } from '../../utils/uploader'
441
457
 
442
458
  export default {
443
459
 
@@ -451,6 +467,7 @@ export default {
451
467
  */
452
468
  components: {
453
469
  NDragger,
470
+ NThumbnail,
454
471
  },
455
472
 
456
473
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@netang/quasar",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
 
5
5
  "description": "netang-quasar",
6
6
  "scripts": {
package/utils/config.js CHANGED
@@ -1,4 +1,5 @@
1
1
  import $n_get from 'lodash/get'
2
+ import $n_merge from 'lodash/merge'
2
3
 
3
4
  // 用户配置 参数
4
5
  // userConfig: {
@@ -26,14 +27,21 @@ export const configs = {
26
27
  routers: {},
27
28
  // 表格配置
28
29
  tablesConfig: {},
30
+ // 组件配置
31
+ components: {},
29
32
  // 对话框组件
30
33
  dialogComponents: {},
31
- // 格式化上传文件 hash
32
- formatUploadFileHash: null,
33
- // 格式化上传网络链接
34
- formatUploadNet: null,
35
- // 获取文件地址
36
- getFileUrl: null,
34
+ // 上传器配置
35
+ uploader: {
36
+ // 如果是 Minio 上传, 则在后面加上下划线
37
+ hasMinioSuffix: true,
38
+ // 格式化上传文件 hash
39
+ formatUploadFileHash: null,
40
+ // 格式化上传网络链接
41
+ formatUploadNet: null,
42
+ // 获取文件地址
43
+ getFileUrl: null,
44
+ },
37
45
  }
38
46
 
39
47
  /**
@@ -41,7 +49,7 @@ export const configs = {
41
49
  * @param options
42
50
  */
43
51
  export function settings(options) {
44
- Object.assign(configs, options)
52
+ $n_merge(configs, options)
45
53
  }
46
54
 
47
55
  /**
package/utils/getFile.js CHANGED
@@ -50,11 +50,16 @@ export default function getFile(src) {
50
50
  }
51
51
 
52
52
  const {
53
- // type,
53
+ type,
54
54
  domain,
55
- } = $n_uploader.getUpload()
56
-
57
- return useFileUrl(domain, src)
55
+ } = $n_uploader.getUpload(
56
+ null,
57
+ src && src.slice(-1) === '_'
58
+ ? 'minio'
59
+ : ''
60
+ )
61
+
62
+ return useFileUrl({ type, domain, src })
58
63
  }
59
64
  }
60
65
 
package/utils/getImage.js CHANGED
@@ -130,7 +130,16 @@ export default function getImage(src, options) {
130
130
  const {
131
131
  type,
132
132
  domain,
133
- } = $n_uploader.getUpload(null, $n_get(options, 'upload', ''))
133
+ } = $n_uploader.getUpload(
134
+ null,
135
+ $n_has(options, 'upload')
136
+ ? options.upload
137
+ : (
138
+ src && src.slice(-1) === '_'
139
+ ? 'minio'
140
+ : ''
141
+ )
142
+ )
134
143
 
135
144
  // 判断图片上传方式
136
145
  switch (type) {
@@ -219,7 +228,7 @@ export default function getImage(src, options) {
219
228
  // #endif
220
229
  // --------------------------------------------------
221
230
 
222
- return useFileUrl(domain, src)
231
+ return useFileUrl({ type, domain, src })
223
232
  }
224
233
  }
225
234
 
package/utils/index.js CHANGED
@@ -24,6 +24,7 @@ import getImage from './getImage'
24
24
  import getTime from './getTime'
25
25
  import loading from './loading'
26
26
  import notify from './notify'
27
+ import play from './play'
27
28
  import previewImage from './previewImage'
28
29
  import price from './price'
29
30
  import timestamp from './timestamp'
@@ -57,6 +58,7 @@ export default {
57
58
  getTime,
58
59
  loading,
59
60
  notify,
61
+ play,
60
62
  previewImage,
61
63
  price,
62
64
  timestamp,
package/utils/play.js ADDED
@@ -0,0 +1,40 @@
1
+ import { Platform, Screen, Dialog } from 'quasar'
2
+
3
+ import $n_getFile from './getFile'
4
+
5
+ /**
6
+ * 播放视频 / 音频
7
+ */
8
+ export default function play(hash) {
9
+
10
+ const src = $n_getFile(hash)
11
+
12
+ let width
13
+ let height
14
+ let fullWidth = false
15
+ let fullHeight = false
16
+ let ok = true
17
+ let style = ''
18
+
19
+ if (Platform.is.mobile) {
20
+ width = Screen.width - 48 - 32
21
+ height = Screen.height - 48 - 32 - 6 - 52
22
+ fullWidth = true
23
+ fullHeight = true
24
+ } else {
25
+ width = 800 - 32
26
+ height = 400 - 32 - 6
27
+ ok = false
28
+ style = 'width:800px;max-width:800px;height:400px;max-height:400px;'
29
+ }
30
+
31
+ Dialog.create({
32
+ message: `<video style="width:${width}px;height:${height}px;" playsinline autoplay controls src="${src}" type="video/mp4" muted="muted"></video>`,
33
+ style,
34
+ html: true,
35
+ dark: true,
36
+ ok,
37
+ fullWidth,
38
+ fullHeight,
39
+ })
40
+ }
package/utils/uploader.js CHANGED
@@ -10,6 +10,7 @@ import $n_uniq from 'lodash/uniq'
10
10
  import $n_find from 'lodash/find'
11
11
  import $n_isFunction from 'lodash/isFunction'
12
12
 
13
+ import $n_storage from '@netang/utils/storage'
13
14
  import $n_isValidArray from '@netang/utils/isValidArray'
14
15
  import $n_isValidObject from '@netang/utils/isValidObject'
15
16
  import $n_isValidString from '@netang/utils/isValidString'
@@ -24,6 +25,7 @@ import $n_isValidValue from '@netang/utils/isValidValue'
24
25
  import $n_http from '@netang/utils/http'
25
26
  import $n_getThrowMessage from '@netang/utils/getThrowMessage'
26
27
  import $n_runAsync from '@netang/utils/runAsync'
28
+ import $n_numberDeep from '@netang/utils/numberDeep'
27
29
 
28
30
  import $n_$ruleValid from './$ruleValid'
29
31
  import $n_toast from './toast'
@@ -34,25 +36,76 @@ import $n_getImage from './getImage'
34
36
  import $n_getFile from './getFile'
35
37
  import $n_config from './config'
36
38
  import $n_timestamp from './timestamp'
39
+ import $n_play from './play'
37
40
 
41
+ import copy from './copy'
38
42
  import { configs } from './config'
39
43
 
40
- import copy from './copy'
44
+ /**
45
+ * 文件类型映射
46
+ */
47
+ export const FilE_TYPE = {
48
+ file: 1,
49
+ image: 2,
50
+ video: 3,
51
+ audio: 4,
52
+ }
41
53
 
42
- import {
43
- // 文件类型映射
44
- FilE_TYPE,
45
- // 文件名称映射
46
- FilE_NAME,
47
- // 上传状态
48
- UPLOAD_STATUS,
49
- // 上传至服务器
50
- uploadServer,
51
- } from './useUploader'
54
+ /**
55
+ * 文件名称映射
56
+ */
57
+ export const FilE_NAME = {
58
+ 1: '文件',
59
+ 2: '图片',
60
+ 3: '视频',
61
+ 4: '音频',
62
+ }
63
+
64
+ /**
65
+ * 上传状态
66
+ */
67
+ export const UPLOAD_STATUS = {
68
+ // 等待上传中
69
+ waiting: 1,
70
+ // 检查 hash 中
71
+ hashChecking: 2,
72
+ // 检查 hash 完成
73
+ hashChecked: 3,
74
+ // 检查是否存在服务器中
75
+ existChecking: 4,
76
+ // 检查是否存在服务器完成
77
+ existChecked: 5,
78
+ // 上传中
79
+ uploading: 6,
80
+ // 上传完成
81
+ success: 7,
82
+ // 上传失败
83
+ fail: 8,
84
+ }
52
85
 
53
86
  // 文件数量
54
87
  let _fileNum = 0
55
88
 
89
+ /**
90
+ * 将 base64 转换为 File
91
+ */
92
+ function dataUrlToFile(dataUrl) {
93
+ const arr = dataUrl.split(',')
94
+ const mime = arr[0].match(/:(.*?);/)[1]
95
+ const bstr = window.atob(arr[1])
96
+ let n = bstr.length
97
+ const arrayBuffer = new Uint8Array(n)
98
+ while (n--) {
99
+ arrayBuffer[n] = bstr.charCodeAt(n)
100
+ }
101
+ const blob = new Blob([arrayBuffer], { type: mime })
102
+
103
+ return {
104
+ arrayBuffer,
105
+ file: new File([blob], String($n_timestamp()), { type: blob.type }),
106
+ }
107
+ }
108
+
56
109
  /**
57
110
  * 创建上传器
58
111
  */
@@ -64,6 +117,8 @@ function create(options) {
64
117
  const $q = useQuasar()
65
118
 
66
119
  const {
120
+ // 上传器类型
121
+ uploaderType,
67
122
  // 上传文件输入框节点
68
123
  fileRef,
69
124
  // 更新值方法(初始化上传列表时不更新值)
@@ -72,6 +127,8 @@ function create(options) {
72
127
  onUpdate,
73
128
 
74
129
  } = Object.assign({
130
+ // 上传器类型
131
+ uploaderType: null,
75
132
  // 更新值方法
76
133
  onUpdateModelValue: null,
77
134
  // 更新方法
@@ -115,7 +172,7 @@ function create(options) {
115
172
  /**
116
173
  * 上传配置
117
174
  */
118
- const configUpload = getUpload()
175
+ const configUpload = getUpload(null, uploaderType)
119
176
 
120
177
  const configLimit = Object.assign(
121
178
  {
@@ -567,13 +624,16 @@ function create(options) {
567
624
  const hash = spark.end(false)
568
625
  if (hash) {
569
626
  // 设置文件 hash
570
- fileItem.hash = hash
627
+ fileItem.hash = await formatFileItemHash(hash)
571
628
  // 标题
572
629
  fileItem.title = title
573
630
  // 设置文件状态
574
631
  fileItem.status = UPLOAD_STATUS.hashChecked
575
632
  // 设置文件检查进度
576
633
  fileItem.progress = 100
634
+
635
+ // 设置单个文件信息
636
+ await setFileItemInfo(fileItem, setFileFail)
577
637
  return
578
638
  }
579
639
  }
@@ -645,7 +705,7 @@ function create(options) {
645
705
  // --------------------------------------------------
646
706
  const {
647
707
  formatUploadNet,
648
- } = configs
708
+ } = configs.uploader
649
709
  if ($n_isFunction(formatUploadNet)) {
650
710
  files = formatUploadNet(files, props.type === 'image')
651
711
  }
@@ -743,7 +803,7 @@ function create(options) {
743
803
  /**
744
804
  * 文件输入框更新
745
805
  */
746
- function fileChange(e) {
806
+ async function fileChange(e) {
747
807
 
748
808
  try {
749
809
  // 获取上传文件
@@ -762,7 +822,7 @@ function create(options) {
762
822
  for (const file of files) {
763
823
 
764
824
  // 创建单个文件
765
- const fileItem = createFileItem(file)
825
+ const fileItem = await createFileItem(file)
766
826
  if (fileItem !== false) {
767
827
 
768
828
  // 如果只能上传一个
@@ -889,10 +949,7 @@ function create(options) {
889
949
  // 上传至服务器
890
950
  await uploadServer({
891
951
  fileType: FilE_TYPE[props.type],
892
- configUpload,
893
952
  waitUploadFileLists,
894
- // uploadFileLists,
895
- // checkFileError,
896
953
  setFileSuccess,
897
954
  setFileFail,
898
955
  })
@@ -979,7 +1036,7 @@ function create(options) {
979
1036
  const fileReader = new FileReader()
980
1037
 
981
1038
  // 文件加载
982
- fileReader.onload = function(e) {
1039
+ fileReader.onload = async function(e) {
983
1040
 
984
1041
  // 追加 array buffer
985
1042
  spark.append(e.target.result)
@@ -1008,55 +1065,36 @@ function create(options) {
1008
1065
  return
1009
1066
  }
1010
1067
 
1011
- // 下一步
1012
- function next(hash) {
1013
- if (
1014
- // 如果开启去重
1015
- props.unique
1016
- // 如果该文件 hash 在上传文件列表中
1017
- && $n_findIndex(uploadFileLists.value, { hash }) > -1
1018
- ) {
1019
- // 轻提示
1020
- $n_toast({
1021
- message: '该文件已存在,不可重复上传',
1022
- })
1023
-
1024
- // 设置文件上传失败
1025
- setFileFail(fileItem, '已存在')
1026
-
1027
- // 删除单个文件
1028
- deleteFileItem(fileItem)
1029
-
1030
- } else {
1031
- // 设置文件 hash
1032
- fileItem.hash = hash
1033
- // 设置文件状态
1034
- fileItem.status = UPLOAD_STATUS.hashChecked
1035
- // 设置文件检查进度
1036
- fileItem.progress = 100
1037
- }
1068
+ if (
1069
+ // 如果开启去重
1070
+ props.unique
1071
+ // 如果该文件 hash 在上传文件列表中
1072
+ && $n_findIndex(uploadFileLists.value, { hash }) > -1
1073
+ ) {
1074
+ // 轻提示
1075
+ $n_toast({
1076
+ message: '该文件已存在,不可重复上传',
1077
+ })
1038
1078
 
1039
- // 完成回调
1040
- resolve()
1041
- }
1079
+ // 设置文件上传失败
1080
+ setFileFail(fileItem, '已存在')
1042
1081
 
1043
- // 格式化上传文件 hash
1044
- // --------------------------------------------------
1045
- const {
1046
- formatUploadFileHash,
1047
- } = configs
1048
- if ($n_isFunction(formatUploadFileHash)) {
1049
- $n_runAsync(formatUploadFileHash)(hash, fileItem)
1050
- .then(function (newHash) {
1051
- // 下一步
1052
- next($n_isValidString(newHash) ? newHash : hash)
1053
- })
1054
- return
1082
+ // 删除单个文件
1083
+ deleteFileItem(fileItem)
1084
+
1085
+ } else {
1086
+ // 设置文件 hash
1087
+ fileItem.hash = await formatFileItemHash(hash)
1088
+ // 设置文件状态
1089
+ fileItem.status = UPLOAD_STATUS.hashChecked
1090
+ // 设置文件检查进度
1091
+ fileItem.progress = 100
1055
1092
  }
1056
- // --------------------------------------------------
1057
1093
 
1058
- // 下一步
1059
- next(hash)
1094
+ // 设置单个文件信息
1095
+ await setFileItemInfo(fileItem, setFileFail)
1096
+
1097
+ resolve()
1060
1098
  }
1061
1099
  }
1062
1100
 
@@ -1279,7 +1317,7 @@ function create(options) {
1279
1317
  /**
1280
1318
  * 创建单个文件
1281
1319
  */
1282
- function createFileItem(file) {
1320
+ async function createFileItem(file) {
1283
1321
 
1284
1322
  // 单个文件示例
1285
1323
  // name: "123.jpg"
@@ -1344,10 +1382,11 @@ function create(options) {
1344
1382
  props.type === 'image'
1345
1383
  && file.type.toLowerCase().startsWith('image')
1346
1384
  ) {
1347
- // 获取图片预览地址
1348
- const img = new Image()
1349
- img.src = window.URL.createObjectURL(file)
1350
- fileItem.__img = img.src
1385
+ // 设置单个文件信息
1386
+ const res = await setFileItemInfo(fileItem, setFileFail)
1387
+ if (! res) {
1388
+ return false
1389
+ }
1351
1390
  }
1352
1391
 
1353
1392
  return fileItem
@@ -1510,43 +1549,6 @@ function create(options) {
1510
1549
  }
1511
1550
  }
1512
1551
 
1513
- /**
1514
- * 播放
1515
- */
1516
- function play({ hash, __img }) {
1517
-
1518
- const src = __img ? __img : $n_getFile(hash)
1519
-
1520
- let width
1521
- let height
1522
- let fullWidth = false
1523
- let fullHeight = false
1524
- let ok = true
1525
- let style = ''
1526
-
1527
- if ($q.platform.is.mobile) {
1528
- width = $q.screen.width - 48 - 32
1529
- height = $q.screen.height - 48 - 32 - 6 - 52
1530
- fullWidth = true
1531
- fullHeight = true
1532
- } else {
1533
- width = 800 - 32
1534
- height = 400 - 32 - 6
1535
- ok = false
1536
- style = 'width:800px;max-width:800px;height:400px;max-height:400px;'
1537
- }
1538
-
1539
- $q.dialog({
1540
- message: `<video style="width:${width}px;height:${height}px;" playsinline autoplay controls src="${src}" type="video/mp4" muted="muted"></video>`,
1541
- style,
1542
- html: true,
1543
- dark: true,
1544
- ok,
1545
- fullWidth,
1546
- fullHeight,
1547
- })
1548
- }
1549
-
1550
1552
  /**
1551
1553
  * 复制地址
1552
1554
  */
@@ -1563,6 +1565,472 @@ function create(options) {
1563
1565
  }
1564
1566
  }
1565
1567
 
1568
+ /**
1569
+ * ==============================【私有函数】==============================
1570
+ */
1571
+
1572
+ /**
1573
+ * 格式化单个文件 hash
1574
+ */
1575
+ async function formatFileItemHash(hash) {
1576
+
1577
+ const {
1578
+ hasMinioSuffix,
1579
+ formatUploadFileHash,
1580
+ } = configs.uploader
1581
+
1582
+ if (hasMinioSuffix && configUpload.type === 'minio') {
1583
+ hash += '_'
1584
+ }
1585
+
1586
+ // 如果有格式化上传文件 hash
1587
+ if ($n_isFunction(formatUploadFileHash)) {
1588
+ hash = await $n_runAsync(formatUploadFileHash)(hash)
1589
+ }
1590
+
1591
+ return hash
1592
+ }
1593
+
1594
+ /**
1595
+ * 获取图片信息
1596
+ */
1597
+ function getImageInfo(fileItem) {
1598
+ return new Promise(function (resolve) {
1599
+ const img = new Image()
1600
+ img.src = window.URL.createObjectURL(fileItem.file)
1601
+ fileItem.__img = img.src
1602
+ img.onload = function() {
1603
+ fileItem.json = {
1604
+ w: this.naturalWidth,
1605
+ h: this.naturalHeight,
1606
+ }
1607
+ resolve(true)
1608
+ }
1609
+ img.onerror = function() {
1610
+ resolve(false)
1611
+ }
1612
+ })
1613
+ }
1614
+
1615
+ /**
1616
+ * 获取媒体信息
1617
+ */
1618
+ function getMediaInfo(fileItem, type) {
1619
+ return new Promise(function (resolve) {
1620
+ const dom = document.createElement(type)
1621
+ dom.src = URL.createObjectURL(fileItem.file)
1622
+ dom.onerror = function() {
1623
+ resolve(false)
1624
+ }
1625
+
1626
+ // 如果为视频
1627
+ if (type === 'video') {
1628
+ dom.currentTime = 3
1629
+ dom.oncanplay = async function() {
1630
+
1631
+ fileItem.json = {
1632
+ w: this.videoWidth ? this.videoWidth : this.width,
1633
+ h: this.videoHeight ? this.videoHeight : this.height,
1634
+ d: this.duration,
1635
+ }
1636
+
1637
+ // 获取视频缩略图 hash
1638
+ const p = await getVideoThumbHash(dom, fileItem.json)
1639
+ if (p) {
1640
+ fileItem.json.p = p
1641
+ }
1642
+
1643
+ resolve(true)
1644
+ }
1645
+
1646
+ // 否则为音频
1647
+ } else {
1648
+ dom.onloadedmetadata = function() {
1649
+ fileItem.json = {
1650
+ d: this.duration,
1651
+ }
1652
+ resolve(true)
1653
+ }
1654
+ }
1655
+ })
1656
+ }
1657
+
1658
+ /**
1659
+ * 获取视频缩略图 hash
1660
+ */
1661
+ function getVideoThumbHash(dom, { w, h }) {
1662
+ return new Promise(async function (resolve) {
1663
+
1664
+ const canvas = document.createElement('canvas')
1665
+ const ctx = canvas.getContext('2d')
1666
+ canvas.setAttribute('width', w)
1667
+ canvas.setAttribute('height', h)
1668
+ ctx.drawImage(dom, 0, 0, w, h)
1669
+
1670
+ const {
1671
+ arrayBuffer,
1672
+ file,
1673
+ } = dataUrlToFile(canvas.toDataURL('image/jpeg', 0.8))
1674
+
1675
+ // 获取缩略图 hash
1676
+ const spark = new SparkMD5.ArrayBuffer()
1677
+ spark.append(arrayBuffer)
1678
+ const hash = spark.end(false)
1679
+ if (! hash) {
1680
+ resolve(false)
1681
+ return
1682
+ }
1683
+
1684
+ // 创建原始单个文件
1685
+ const fileItem = Object.assign(createRawFileItem(), {
1686
+ // 设置文件 file
1687
+ file,
1688
+ // 设置文件类型
1689
+ type: FilE_TYPE.image,
1690
+ // 设置文件后缀
1691
+ ext: 'jpg',
1692
+ // 设置文件大小
1693
+ size: file.size,
1694
+ // 设置文件 hash
1695
+ hash: await formatFileItemHash(hash),
1696
+ // 设置文件 json
1697
+ json: {
1698
+ w,
1699
+ h,
1700
+ },
1701
+ })
1702
+
1703
+ // 上传至服务器
1704
+ await uploadServer({
1705
+ fileType: FilE_TYPE.image,
1706
+ waitUploadFileLists: [ fileItem ],
1707
+ setFileSuccess(fileItem) {
1708
+ resolve(fileItem.hash)
1709
+ },
1710
+ setFileFail() {
1711
+ resolve(false)
1712
+ },
1713
+ })
1714
+ })
1715
+ }
1716
+
1717
+ /**
1718
+ * 设置单个文件信息
1719
+ */
1720
+ function setFileItemInfo(fileItem, setFileFail) {
1721
+ return new Promise(async function (resolve) {
1722
+
1723
+ // 如果已经设置过了
1724
+ if (
1725
+ $n_has(fileItem.json, 'w')
1726
+ || $n_has(fileItem.json, 'd')
1727
+ ) {
1728
+ resolve(true)
1729
+ return
1730
+ }
1731
+
1732
+ let res
1733
+
1734
+ // 如果为图片
1735
+ // --------------------------------------------------
1736
+ if (fileItem.type === FilE_TYPE.image) {
1737
+ res = await getImageInfo(fileItem)
1738
+
1739
+ // 如果为视频
1740
+ // --------------------------------------------------
1741
+ } else if (fileItem.type === FilE_TYPE.video) {
1742
+ res = await getMediaInfo(fileItem, 'video')
1743
+
1744
+ // 如果为音频
1745
+ // --------------------------------------------------
1746
+ } else if (fileItem.type === FilE_TYPE.audio) {
1747
+ res = await getMediaInfo(fileItem, 'audio')
1748
+
1749
+ // 否则为文件
1750
+ } else {
1751
+ // 先判断是否为图片
1752
+ res = await getImageInfo(fileItem)
1753
+ if (! res) {
1754
+ // 再判断是否为视频
1755
+ res = await getMediaInfo(fileItem, 'video')
1756
+ if (! res) {
1757
+ // 最后再判断是否为音频
1758
+ res = await getMediaInfo(fileItem, 'video')
1759
+ }
1760
+ }
1761
+ }
1762
+ // --------------------------------------------------
1763
+
1764
+ if (res) {
1765
+ resolve(true)
1766
+ } else {
1767
+ // 设置文件上传失败
1768
+ setFileFail(fileItem)
1769
+ resolve(false)
1770
+ }
1771
+ })
1772
+ }
1773
+
1774
+ /**
1775
+ * 获取上传参数
1776
+ */
1777
+ async function getUploadParams(type, bucket = 'public') {
1778
+
1779
+ // 缓存名
1780
+ const cacheName = `upload_params_${type}_${bucket}`
1781
+
1782
+ // 获取缓存
1783
+ const cache = $n_storage.get(cacheName)
1784
+ if (cache !== null) {
1785
+ return cache
1786
+ }
1787
+
1788
+ // 请求数据
1789
+ const { status, data } = await $n_http({
1790
+ url: $n_config('apiFileUrl') + 'get_upload_params',
1791
+ data: {
1792
+ // 类型
1793
+ type,
1794
+ // 空间名称
1795
+ bucket,
1796
+ },
1797
+ })
1798
+
1799
+ // 如果成功
1800
+ if (! status || ! $n_isValidObject(data)) {
1801
+ return false
1802
+ }
1803
+
1804
+ // 【生产模式】
1805
+ // --------------------------------------------------
1806
+ // #ifdef IS_PRO
1807
+ // 保存缓存(6 小时)
1808
+ $n_storage.set(cacheName, data, 21600000)
1809
+ // #endif
1810
+ // --------------------------------------------------
1811
+
1812
+ return data
1813
+ }
1814
+
1815
+ /**
1816
+ * 删除上传参数缓存
1817
+ */
1818
+ function deleteUploadParams(type, bucket = 'public') {
1819
+ $n_storage.delete(`upload_params_${type}_${bucket}`)
1820
+ }
1821
+
1822
+ /**
1823
+ * 上传至服务器
1824
+ */
1825
+ async function uploadServer(options) {
1826
+
1827
+ const {
1828
+ fileType,
1829
+ waitUploadFileLists,
1830
+ setFileSuccess,
1831
+ setFileFail,
1832
+ warn,
1833
+ } = Object.assign({
1834
+ warn: true,
1835
+ }, options)
1836
+
1837
+ // 获取上传参数
1838
+ const uploadParams = await getUploadParams(configUpload.type)
1839
+ if (uploadParams === false) {
1840
+ for (const fileItem of waitUploadFileLists) {
1841
+ setFileFail(fileItem, '上传失败')
1842
+ }
1843
+ if (warn) {
1844
+ $n_toast({
1845
+ message: `获取[${configUpload.type}]上传参数失败`,
1846
+ })
1847
+ }
1848
+ return false
1849
+ }
1850
+
1851
+ // 是否上传 minio 备份
1852
+ // --------------------------------------------------
1853
+ let backupParams = null
1854
+ let backupConfig = null
1855
+ if (configUpload.type !== 'minio') {
1856
+ backupConfig = getUpload(null, 'minio')
1857
+ // 如果同步
1858
+ if (backupConfig.sync === true) {
1859
+ backupParams = await getUploadParams(backupConfig.type)
1860
+ if (backupParams === false) {
1861
+ for (const fileItem of waitUploadFileLists) {
1862
+ setFileFail(fileItem, '上传失败')
1863
+ }
1864
+ if (warn) {
1865
+ $n_toast({
1866
+ message: `获取[${backupConfig.type}]上传参数失败`,
1867
+ })
1868
+ }
1869
+ return false
1870
+ }
1871
+ }
1872
+ }
1873
+ // --------------------------------------------------
1874
+
1875
+ // 批量上传
1876
+ for (const fileItem of waitUploadFileLists) {
1877
+ // 上传单个文件
1878
+ await uploadFileItem(fileItem)
1879
+ }
1880
+
1881
+ /**
1882
+ * 上传单个文件
1883
+ */
1884
+ async function uploadFileItem(fileItem) {
1885
+
1886
+ // 设置文件状态
1887
+ fileItem.status = UPLOAD_STATUS.uploading
1888
+
1889
+ // 上传文件
1890
+ const upload = async function(configUpload, uploadParams, startPercent, halfPercent) {
1891
+
1892
+ const {
1893
+ // 上传地址
1894
+ url,
1895
+ // 文件名
1896
+ fileName,
1897
+ // 键值名
1898
+ keyName,
1899
+ // 上传数据
1900
+ data,
1901
+ } = uploadParams
1902
+
1903
+ // 请求数据
1904
+ const httpData = Object.assign({}, data)
1905
+ // 文件
1906
+ httpData[fileName] = fileItem.file
1907
+ // 自定义文件 key
1908
+ httpData[keyName] = fileItem.hash
1909
+
1910
+ const { status, data: res } = await $n_http({
1911
+ // 上传地址
1912
+ url,
1913
+ // 数据
1914
+ data: httpData,
1915
+ // 关闭错误提醒
1916
+ warn: false,
1917
+ // 关闭检查结果 code
1918
+ checkCode: false,
1919
+ // 不包含头部鉴权认证
1920
+ token: false,
1921
+ // 开启上传
1922
+ upload: true,
1923
+ // 取消请求
1924
+ onCancel(cancel) {
1925
+ // 设置中断上传
1926
+ fileItem.abort = function(msg) {
1927
+ cancel($n_isValidString(msg) ? msg : '已取消')
1928
+ }
1929
+ },
1930
+ // 监听上传进度
1931
+ onUploadProgress(percent) {
1932
+ // 设置上传进度
1933
+ fileItem.progress = Math.round(startPercent + (halfPercent ? percent / 2 : percent))
1934
+ },
1935
+ })
1936
+
1937
+ // 如果请求失败
1938
+ if (! status) {
1939
+ // 设置文件上传失败
1940
+ setFileFail(fileItem, res.msg)
1941
+ // 删除上传参数缓存
1942
+ deleteUploadParams(configUpload.type)
1943
+ return false
1944
+ }
1945
+
1946
+ return res
1947
+ }
1948
+
1949
+ const resUpload = await upload(configUpload, uploadParams, 0, !! backupParams)
1950
+ if (resUpload === false) {
1951
+ return false
1952
+ }
1953
+
1954
+ // 是否已备份
1955
+ let is_backup = 0
1956
+
1957
+ // 上传至备份服务器
1958
+ // --------------------------------------------------
1959
+ if (backupParams) {
1960
+ const res = await upload(backupConfig, backupParams, 50, true)
1961
+ if (res === false) {
1962
+ return false
1963
+ }
1964
+ is_backup = 1
1965
+ }
1966
+ // --------------------------------------------------
1967
+
1968
+ const {
1969
+ title,
1970
+ type,
1971
+ hash,
1972
+ ext,
1973
+ size,
1974
+ json,
1975
+ } = fileItem
1976
+
1977
+ // 请求数据
1978
+ const data = {
1979
+ // 类型
1980
+ type: configUpload.type,
1981
+ // 需上传的文件类型
1982
+ file_type: fileType,
1983
+ // 文件
1984
+ file: {
1985
+ // 标题
1986
+ title: title || '',
1987
+ // 类型
1988
+ type,
1989
+ // hash
1990
+ hash,
1991
+ // 后缀
1992
+ ext,
1993
+ // 文件大小
1994
+ size,
1995
+ // 文件 json
1996
+ json,
1997
+ // 是否已备份
1998
+ is_backup,
1999
+ },
2000
+ // 结果
2001
+ result: $n_isValidObject(resUpload) ? resUpload : {},
2002
+ }
2003
+
2004
+ // 请求 - 上传文件至 cdn
2005
+ const { status: statusCallback, data: resCallback } = await $n_http({
2006
+ url: $n_config('apiFileUrl') + 'upload_callback',
2007
+ data,
2008
+ // 关闭错误提示
2009
+ warn: false,
2010
+ })
2011
+
2012
+ // 请求失败
2013
+ if (! statusCallback || ! $n_isValidObject(resCallback)) {
2014
+ // 设置文件上传失败
2015
+ setFileFail(fileItem, resCallback.msg || '上传失败')
2016
+ return false
2017
+ }
2018
+
2019
+ // 格式化 json
2020
+ const _json = $n_json.parse(resCallback.json)
2021
+ Object.assign(fileItem, resCallback, {
2022
+ json: $n_isValidObject(_json) ? $n_numberDeep(_json) : {},
2023
+ })
2024
+
2025
+ // 设置文件上传成功
2026
+ setFileSuccess(fileItem)
2027
+
2028
+ return true
2029
+ }
2030
+
2031
+ return true
2032
+ }
2033
+
1566
2034
  return {
1567
2035
  // 上传文件列表
1568
2036
  query: uploadFileLists,
@@ -1595,7 +2063,9 @@ function create(options) {
1595
2063
  // 修改文件名
1596
2064
  editFileTitle,
1597
2065
  // 播放视频/音频
1598
- play,
2066
+ play({ hash, __img }) {
2067
+ $n_play(__img ? __img : hash)
2068
+ },
1599
2069
  // 复制地址
1600
2070
  copyUrl,
1601
2071
  }
@@ -8,19 +8,19 @@ import { configs } from './config'
8
8
  /**
9
9
  * 获取文件 url
10
10
  */
11
- export default function useFileUrl(domain, src) {
11
+ export default function useFileUrl(e) {
12
12
 
13
13
  // 获取文件地址
14
14
  const {
15
15
  getFileUrl,
16
- } = configs
16
+ } = configs.uploader
17
17
 
18
18
  if ($n_isFunction(getFileUrl)) {
19
- const res = getFileUrl(domain, src)
19
+ const res = getFileUrl(e)
20
20
  if ($n_isValidString(res)) {
21
21
  return res
22
22
  }
23
23
  }
24
24
 
25
- return $n_slash(domain, 'end', true) + src
25
+ return $n_slash(e.domain, 'end', true) + e.src
26
26
  }
@@ -1,303 +0,0 @@
1
- import $n_storage from '@netang/utils/storage'
2
- import $n_isValidObject from '@netang/utils/isValidObject'
3
- import $n_isValidString from '@netang/utils/isValidString'
4
- import $n_http from '@netang/utils/http'
5
- import $n_numberDeep from '@netang/utils/numberDeep'
6
- import $n_json from '@netang/utils/json'
7
-
8
- import { getUpload } from './uploader'
9
-
10
- import $n_toast from './toast'
11
- import $n_config from './config'
12
-
13
- /**
14
- * 文件类型映射
15
- */
16
- export const FilE_TYPE = {
17
- file: 1,
18
- image: 2,
19
- video: 3,
20
- audio: 4,
21
- }
22
-
23
- /**
24
- * 文件名称映射
25
- */
26
- export const FilE_NAME = {
27
- 1: '文件',
28
- 2: '图片',
29
- 3: '视频',
30
- 4: '音频',
31
- }
32
-
33
- /**
34
- * 上传状态
35
- */
36
- export const UPLOAD_STATUS = {
37
- // 等待上传中
38
- waiting: 1,
39
- // 检查 hash 中
40
- hashChecking: 2,
41
- // 检查 hash 完成
42
- hashChecked: 3,
43
- // 检查是否存在服务器中
44
- existChecking: 4,
45
- // 检查是否存在服务器完成
46
- existChecked: 5,
47
- // 上传中
48
- uploading: 6,
49
- // 上传完成
50
- success: 7,
51
- // 上传失败
52
- fail: 8,
53
- }
54
-
55
- /**
56
- * 获取上传参数
57
- */
58
- export async function getUploadParams(type, bucket = 'public') {
59
-
60
- // 缓存名
61
- const cacheName = `upload_params_${type}_${bucket}`
62
-
63
- // 获取缓存
64
- const cache = $n_storage.get(cacheName)
65
- if (cache !== null) {
66
- return cache
67
- }
68
-
69
- // 请求数据
70
- const { status, data } = await $n_http({
71
- url: $n_config('apiFileUrl') + 'get_upload_params',
72
- data: {
73
- // 类型
74
- type,
75
- // 空间名称
76
- bucket,
77
- },
78
- })
79
-
80
- // 如果成功
81
- if (! status || ! $n_isValidObject(data)) {
82
- return false
83
- }
84
-
85
- // 【生产模式】
86
- // --------------------------------------------------
87
- // #ifdef IS_PRO
88
- // 保存缓存(6 小时)
89
- $n_storage.set(cacheName, data, 21600000)
90
- // #endif
91
- // --------------------------------------------------
92
-
93
- return data
94
- }
95
-
96
- /**
97
- * 删除上传参数缓存
98
- */
99
- export function deleteUploadParams(type, bucket = 'public') {
100
- $n_storage.delete(`upload_params_${type}_${bucket}`)
101
- }
102
-
103
- /**
104
- * 上传至服务器
105
- */
106
- export async function uploadServer(params) {
107
-
108
- const {
109
- fileType,
110
- configUpload,
111
- waitUploadFileLists,
112
- // uploadFileLists,
113
- // checkFileError,
114
- setFileSuccess,
115
- setFileFail,
116
- } = params
117
-
118
- // 获取上传参数
119
- const uploadParams = await getUploadParams(configUpload.type)
120
- if (uploadParams === false) {
121
- for (const fileItem of waitUploadFileLists) {
122
- setFileFail(fileItem, '上传失败')
123
- }
124
- $n_toast({
125
- message: `获取[${configUpload.type}]上传参数失败`,
126
- })
127
- return
128
- }
129
-
130
- // 是否上传 minio 备份
131
- // --------------------------------------------------
132
- let backupParams = null
133
- let backupConfig = null
134
- if (configUpload.type !== 'minio') {
135
- backupConfig = getUpload(null, 'minio')
136
- // 如果同步
137
- if (backupConfig.sync === true) {
138
- backupParams = await getUploadParams(backupConfig.type)
139
- if (backupParams === false) {
140
- for (const fileItem of waitUploadFileLists) {
141
- setFileFail(fileItem, '上传失败')
142
- }
143
- $n_toast({
144
- message: `获取[${backupConfig.type}]上传参数失败`,
145
- })
146
- return
147
- }
148
- }
149
- }
150
- // --------------------------------------------------
151
-
152
- // 批量上传
153
- for (const fileItem of waitUploadFileLists) {
154
- // 上传单个文件
155
- await uploadFileItem(fileItem)
156
- }
157
-
158
- /**
159
- * 上传单个文件
160
- */
161
- async function uploadFileItem(fileItem) {
162
-
163
- // 设置文件状态
164
- fileItem.status = UPLOAD_STATUS.uploading
165
-
166
- // 上传文件
167
- const upload = async function(configUpload, uploadParams, startPercent, halfPercent) {
168
-
169
- const {
170
- // 上传地址
171
- url,
172
- // 文件名
173
- fileName,
174
- // 键值名
175
- keyName,
176
- // 上传数据
177
- data,
178
- } = uploadParams
179
-
180
- // 请求数据
181
- const httpData = Object.assign({}, data)
182
- // 文件
183
- httpData[fileName] = fileItem.file
184
- // 自定义文件 key
185
- httpData[keyName] = fileItem.hash
186
-
187
- const { status, data: res } = await $n_http({
188
- // 上传地址
189
- url,
190
- // 数据
191
- data: httpData,
192
- // 关闭错误提醒
193
- warn: false,
194
- // 关闭检查结果 code
195
- checkCode: false,
196
- // 不包含头部鉴权认证
197
- token: false,
198
- // 开启上传
199
- upload: true,
200
- // 取消请求
201
- onCancel(cancel) {
202
- // 设置中断上传
203
- fileItem.abort = function(msg) {
204
- cancel($n_isValidString(msg) ? msg : '已取消')
205
- }
206
- },
207
- // 监听上传进度
208
- onUploadProgress(percent) {
209
- // 设置上传进度
210
- fileItem.progress = Math.round(startPercent + (halfPercent ? percent / 2 : percent))
211
- },
212
- })
213
-
214
- // 如果请求失败
215
- if (! status) {
216
- // 设置文件上传失败
217
- setFileFail(fileItem, res.msg)
218
- // 删除上传参数缓存
219
- deleteUploadParams(configUpload.type)
220
- return false
221
- }
222
-
223
- return res
224
- }
225
- const resUpload = await upload(configUpload, uploadParams, 0, !! backupParams)
226
- if (resUpload === false) {
227
- return false
228
- }
229
-
230
- // 是否已备份
231
- let is_backup = 0
232
-
233
- // 上传至备份服务器
234
- // --------------------------------------------------
235
- if (backupParams) {
236
- const res = await upload(backupConfig, backupParams, 50, true)
237
- if (res === false) {
238
- return false
239
- }
240
- is_backup = 1
241
- }
242
- // --------------------------------------------------
243
-
244
- const {
245
- title,
246
- type,
247
- hash,
248
- ext,
249
- size,
250
- json,
251
- } = fileItem
252
-
253
- // 请求 - 上传文件至 cdn
254
- const { status: statusCallback, data: resCallback } = await $n_http({
255
- url: $n_config('apiFileUrl') + 'upload_callback',
256
- data: {
257
- // 类型
258
- type: configUpload.type,
259
- // 需上传的文件类型
260
- file_type: fileType,
261
- // 文件
262
- file: {
263
- // 标题
264
- title: title || '',
265
- // 类型
266
- type,
267
- // hash
268
- hash,
269
- // 后缀
270
- ext,
271
- // 文件大小
272
- size,
273
- // 文件 json
274
- json,
275
- // 是否已备份
276
- is_backup,
277
- },
278
- // 结果
279
- result: $n_isValidObject(resUpload) ? resUpload : {},
280
- },
281
- // 关闭错误提示
282
- warn: false,
283
- })
284
-
285
- // 请求失败
286
- if (! statusCallback || ! $n_isValidObject(resCallback)) {
287
- // 设置文件上传失败
288
- setFileFail(fileItem, resCallback.msg || '上传失败')
289
- return false
290
- }
291
-
292
- // 格式化 json
293
- const _json = $n_json.parse(resCallback.json)
294
- Object.assign(fileItem, resCallback, {
295
- json: $n_isValidObject(_json) ? $n_numberDeep(_json) : {},
296
- })
297
-
298
- // 设置文件上传成功
299
- setFileSuccess(fileItem)
300
-
301
- return true
302
- }
303
- }