bri-components 1.6.0 → 1.6.2

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bri-components",
3
- "version": "1.6.0",
3
+ "version": "1.6.2",
4
4
  "author": "dengshanghui",
5
5
  "description": "a component lib for vue project",
6
6
  "main": "src/index.js",
@@ -37,6 +37,8 @@
37
37
  "jsonlint": "^1.6.3",
38
38
  "minio": "7.1.0",
39
39
  "stream": "^0.0.2",
40
+ "video.js": "^8.23.3",
41
+ "videojs-contrib-hls": "^5.15.0",
40
42
  "view-design": "4.7.0",
41
43
  "viewerjs": "^1.10.2",
42
44
  "vue-codemirror": "^4.0.6",
@@ -23,7 +23,6 @@
23
23
  @dragover.prevent="dragOver = true"
24
24
  @dragleave.prevent="dragOver = false"
25
25
  >
26
-
27
26
  <!-- 编辑 -->
28
27
  <div
29
28
  v-if="!disabled"
@@ -89,6 +88,7 @@
89
88
  :propsObj="propsObj"
90
89
  :emptyShowVal="emptyShowVal"
91
90
  :isShowEditIcon="isShowEditIcon"
91
+ @click.native.stop="0"
92
92
  @deleteItem="clickDeteItem"
93
93
  @editItemName="handleEditName"
94
94
  ></upload-list>
@@ -103,18 +103,18 @@
103
103
  import uploadList from "./uploadList.vue";
104
104
 
105
105
  const prefixCls = "ivu-upload";
106
- const imageType = ["jpg", "png", "gif", "jpeg", "tiff", "swf"];
107
- const documentType = ["txt", "doc", "xls", "ppt", "docx", "xlsx", "pptx", "pdf", "xmind"];
108
- const videoType = ["flv", "rmvb", "mp4", "mvb"];
109
- const audioType = ["wma", "mp3", "m4a"];
110
- const packageType = ["rar", "zip"];
111
- const fileTypes = [
112
- ...documentType,
113
- ...imageType,
114
- ...videoType,
115
- ...audioType,
116
- ...packageType
117
- ];
106
+ const fileTypesMap = {
107
+ document: ["txt", "doc", "xls", "ppt", "docx", "xlsx", "pptx", "pdf", "xmind"],
108
+ image: ["jpg", "png", "gif", "jpeg", "tiff", "swf"],
109
+ video: ["flv", "rmvb", "mp4", "mvb"],
110
+ audio: ["wma", "mp3", "m4a"],
111
+ // text: ["log", "csv", "html", "json"],
112
+ package: ["rar", "zip"]
113
+ };
114
+ const allFileTypes = Object.entries(fileTypesMap).reduce((arr, fileTypeArr, fileTypeIndex, map) => [
115
+ ...arr,
116
+ ...fileTypeArr[1]
117
+ ], []);
118
118
 
119
119
  export default {
120
120
  name: "BriUpload",
@@ -145,24 +145,25 @@
145
145
  computed: {
146
146
  selfPropsObj () {
147
147
  return {
148
- _fileType: "file", // "file", "image"
148
+ _fileType: "file", // "file", "image", "video"
149
149
  _showMode: this.isHeightAuto ? "old" : "inline", // 宽度为100%、且不在表格字段里的 显示老版
150
150
 
151
151
  _multiple: true,
152
152
  _useType: "drag",
153
153
  _maxSize: 1024 * 1024 * 2, // 根据四局要求,限制文件为2G
154
154
  _format: [],
155
+ _accept: [],
155
156
 
156
157
  ...this.propsObj,
157
158
  ...this.commonDealPropsObj
158
159
  };
159
160
  },
160
161
  subType () {
161
- return this.selfPropsObj._fileType;
162
+ return this.selfPropsObj._fileType || "file";
162
163
  },
163
164
  showMode () {
164
165
  return this.isInTable
165
- ? this.selfPropsObj._inTableStyle == "list" && this.disabled
166
+ ? this.selfPropsObj._inTableStyle === "list" && this.disabled
166
167
  ? "tableList"
167
168
  : "inline"
168
169
  : this.selfPropsObj._showMode;
@@ -178,9 +179,13 @@
178
179
  },
179
180
  // 限制文件格式
180
181
  accept () {
181
- return (this.subType === "image" ? imageType : fileTypes)
182
- .map(type => `.${type}`)
183
- .join();
182
+ const types = this.selfPropsObj._accept && this.selfPropsObj._accept.length
183
+ ? this.selfPropsObj._accept
184
+ : this.subType === "file"
185
+ ? allFileTypes
186
+ : fileTypesMap[this.subType];
187
+
188
+ return types.map(type => `.${type}`).join();
184
189
  },
185
190
  isShowEditIcon () {
186
191
  // 因为编辑name 需要这三个参数,因此没有这三个参数时不显示此按钮
@@ -250,10 +255,7 @@
250
255
  },
251
256
  dealUpload (files) {
252
257
  if (!this.disabled) {
253
- let postFiles = Array.prototype.slice.call(files);
254
- if (!this.multipleMode) {
255
- postFiles = postFiles.slice(0, 1);
256
- }
258
+ let postFiles = this.multipleMode ? [...files] : [...files].slice(0, 1);
257
259
  postFiles.forEach(fileItem => {
258
260
  if (
259
261
  (!this.format.length || this.format.some(item => item.toLocaleLowerCase() === fileItem.name.split(".").pop().toLocaleLowerCase())) &&
@@ -1,23 +1,26 @@
1
1
  <template>
2
2
  <div class="BriUploadImage">
3
3
  <div
4
- class="BriUploadImage-set"
5
4
  ref="viewerImage"
5
+ class="BriUploadImage-set"
6
6
  >
7
7
  <div
8
- v-if="value[propsObj._key] || propsObj._default || percent"
9
- :class="['BriUploadImage-set-img', isAvatar ? 'BriUploadImage-set-avatar' : '']"
8
+ v-if="curVal || propsObj._default || percent"
9
+ :class="{
10
+ 'BriUploadImage-set-img': true,
11
+ 'BriUploadImage-set-avatar': isAvatar
12
+ }"
10
13
  :style="{
11
- backgroundImage: `url(${$imageResize(value[propsObj._key] || propsObj._default, imageResizeConfig)})`,
14
+ backgroundImage: `url(${$imageResize(curVal || propsObj._default, imageResizeConfig)})`,
12
15
  borderRadius: propsObj.radius ? '50%' : ''
13
16
  }"
14
17
  >
15
18
  <img
16
- :data-original="value[propsObj._key]"
19
+ :data-original="curVal"
17
20
  style="display:none"
18
21
  >
19
22
  <div
20
- v-if="value[propsObj._key] && propsObj._canAction"
23
+ v-if="curVal && canAction"
21
24
  class="BriUploadImage-set-action"
22
25
  >
23
26
  <Icon
@@ -33,6 +36,7 @@
33
36
  @click.native="handleRemove"
34
37
  ></Icon>
35
38
  </div>
39
+
36
40
  <!-- 上传进度 -->
37
41
  <div
38
42
  v-if="percent"
@@ -50,8 +54,8 @@
50
54
  <span v-else>{{ percent }}%</span>
51
55
  </i-circle>
52
56
  </div>
53
-
54
57
  </div>
58
+
55
59
  <div class="wrap">
56
60
  <Button type="default">点击上传</Button>
57
61
  <input
@@ -72,8 +76,8 @@
72
76
  @on-visible-change="visibleChange"
73
77
  >
74
78
  <dsh-cropper
75
- class="BriUploadImage-cropper"
76
79
  ref="cropper"
80
+ class="BriUploadImage-cropper"
77
81
  :src="imgSrc"
78
82
  alt="Source Image"
79
83
  :cropmove="cropImage"
@@ -99,17 +103,32 @@
99
103
  ],
100
104
  components: {},
101
105
  props: {
102
- value: Object,
103
- propsObj: Object,
104
- // 上传的是阿里云还是本地
105
- requestOssType: {
106
- type: String,
107
- default: "default"
106
+ value: {
107
+ type: Object,
108
+ default () {
109
+ return {};
110
+ }
111
+ },
112
+ propsObj: {
113
+ type: Object,
114
+ default () {
115
+ return {};
116
+ }
108
117
  },
118
+
109
119
  isAvatar: {
110
120
  type: Boolean,
111
121
  default: false
112
122
  },
123
+ // 上传的是阿里云还是本地
124
+ requestOssType: {
125
+ type: String,
126
+ default: "default",
127
+ validator (val) {
128
+ // "default"代表阿里云
129
+ return ["default", "local"].includes(val);
130
+ }
131
+ },
113
132
  // 阿里云上传方式
114
133
  ossType: {
115
134
  type: String,
@@ -118,126 +137,143 @@
118
137
  },
119
138
  data () {
120
139
  return {
140
+ inputType: "file",
141
+
142
+ // 头像
143
+ avatarModal: false,
144
+ imgSrc: "",
145
+ cropImg: "",
146
+
121
147
  operationMap: {
122
148
  cancel: {
123
149
  name: "取消",
124
150
  type: "cancel",
125
151
  btnType: "cancel",
126
- event: "cancelAvatarModal"
152
+ event: "closeAvatarModal"
127
153
  },
128
154
  confirm: {
129
155
  name: "确认",
130
156
  type: "confirm",
131
157
  btnType: "primary",
132
- event: "photoSubmit"
158
+ event: "submitCropImage"
133
159
  }
134
- },
135
- // 头像
136
- avatarModal: false,
137
- inputType: "file",
138
- imgSrc: "",
139
- cropImg: ""
160
+ }
140
161
  };
141
162
  },
142
163
  computed: {
143
- modalPropsObj () {
164
+ selfPropsObj () {
144
165
  return {
145
- title: this.propsObj._name || "修改头像",
146
- class: "bri-modal",
147
- width: 450
166
+ ...this.propsObj
148
167
  };
149
168
  },
169
+ controlKey () {
170
+ return this.selfPropsObj._key;
171
+ },
172
+ controlName () {
173
+ return this.selfPropsObj._name;
174
+ },
175
+ // 使用操作图标
176
+ canAction () {
177
+ return this.selfPropsObj._canAction;
178
+ },
150
179
  imageResizeConfig () {
151
- return this.propsObj._imageResizeConfig || {
180
+ return this.selfPropsObj._imageResizeConfig || {
152
181
  m: "fixed",
153
182
  w: 100,
154
183
  h: 100
155
184
  };
156
185
  },
157
186
  finalRequestOssType () {
158
- return this.propsObj._requestOssType || this.requestOssType || "default";
187
+ return this.selfPropsObj._requestOssType || this.requestOssType;
159
188
  },
160
189
  acceptType () {
161
- return this.propsObj._acceptType || "*";
162
- }
163
- },
164
- created () {
165
- },
166
- methods: {
167
- // 打开修改头像
168
- openAvatar () {
169
- this.avatarModal = true;
190
+ return this.selfPropsObj._acceptType || "*";
170
191
  },
171
- // 关闭修改头像
172
- cancelAvatarModal () {
173
- this.avatarModal = false;
174
- // this.inputType = "file";
192
+
193
+ modalPropsObj () {
194
+ return {
195
+ title: this.controlName || "修改头像",
196
+ class: "bri-modal",
197
+ width: 450
198
+ };
175
199
  },
176
- // 头像模态框状态变化,关闭后改变input框类型,保证上传能够连续上传同一张图片
177
- visibleChange (bool) {
178
- if (!bool) {
179
- this.inputType = "file";
200
+
201
+ curVal: {
202
+ get () {
203
+ return this.value[this.controlKey];
204
+ },
205
+ set (val) {
206
+ this.value[this.controlKey] = val;
180
207
  }
181
- },
208
+ }
209
+ },
210
+ created () {},
211
+ methods: {
182
212
  setImage (e) {
183
- if (e.target.files.length != 0) {
213
+ if (e.target.files.length) {
184
214
  const file = e.target.files[0];
185
215
  if (!file.type.includes("image/")) {
186
216
  this.$Message.error("请选择一张图片");
187
- return;
188
217
  }
189
- if (typeof FileReader === "function") {
218
+ else if (typeof FileReader !== "function") {
219
+ this.$Message.error("Sorry, FileReader API not supported");
220
+ }
221
+ else {
190
222
  const reader = new FileReader();
191
- if (this.propsObj._kind == "uploadImage" && !this.propsObj.cropper) {
223
+ if (this.propsObj._kind === "uploadImage" && !this.propsObj.cropper) {
192
224
  reader.onload = (event) => {
193
- let data = event.target.result;
194
225
  this.inputType = "text";
195
- if (this.finalRequestOssType === "local") {
196
- // base64转文件
197
- const imgFile = this.dataURLtoFile(data, "");
198
- this.handlePost(imgFile);
199
- } else {
200
- data = data.split(",")[1];
201
- let dataBuffer = Buffer.from(data, "base64");
202
- this.handlePost(dataBuffer);
203
- }
226
+ this.dealPostImage(event.target.result); // event.target.result是base64格式
204
227
  };
205
228
  reader.readAsDataURL(file);
206
- } else {
229
+ }
230
+ // 使用裁剪
231
+ else {
207
232
  reader.onload = (event) => {
208
- this.imgSrc = event.target.result;
209
- // rebuild cropperjs with the updated source
210
- this.$refs.cropper.replace(event.target.result);
211
233
  this.inputType = "text";
234
+ this.imgSrc = event.target.result;
235
+ this.$refs.cropper.replace(event.target.result); // event.target.result是base64格式
212
236
  };
213
237
  reader.readAsDataURL(file);
214
- this.avatarModal = true;
238
+
239
+ this.openAvatarModal();
215
240
  }
216
- } else {
217
- alert("Sorry, FileReader API not supported");
218
241
  }
219
242
  }
220
243
  },
244
+ // 提交裁剪后的图片
245
+ submitCropImage () {
246
+ this.cropImage();
247
+ this.dealPostImage(this.cropImg);
248
+
249
+ this.closeAvatarModal();
250
+ },
251
+
252
+ // 获取裁剪的图片
221
253
  cropImage () {
222
254
  // get image data for post processing, e.g. upload or setting image src
223
- this.cropImg = this.$refs.cropper.getCroppedCanvas().toDataURL();
255
+ this.cropImg = this.$refs.cropper.getCroppedCanvas().toDataURL(); // base64格式
224
256
  },
225
- // 获取裁剪后的图片,转成file
226
- photoSubmit () {
227
- this.cropImg = this.$refs.cropper.getCroppedCanvas().toDataURL();
257
+ // 处理图片的提交
258
+ dealPostImage (data) {
259
+ // local好像是minio在用
228
260
  if (this.finalRequestOssType === "local") {
229
261
  // base64转文件
230
- const imgFile = this.dataURLtoFile(this.cropImg, "");
262
+ // {
263
+ // lastModified: 1752065308269
264
+ // name: ".png"
265
+ // size: 528557
266
+ // type: "image/png"
267
+ // webkitRelativePath: ""
268
+ // }
269
+ const imgFile = this.dataURLtoFile(data, "");
231
270
  this.handlePost(imgFile);
271
+ // console.dir(imgFile); // object类型
232
272
  } else {
233
- let data = this.cropImg;
234
- data = data.split(",")[1];
235
-
236
- let dataBuffer = Buffer.from(data, "base64");
273
+ const dataBuffer = Buffer.from(data.split(",")[1], "base64");
237
274
  this.handlePost(dataBuffer);
275
+ // console.dir(dataBuffer); // object类型
238
276
  }
239
-
240
- this.cancelAvatarModal();
241
277
  },
242
278
  // 将图片Base64 转成文件
243
279
  dataURLtoFile (dataurl, filename) {
@@ -251,15 +287,17 @@
251
287
  while (n--) {
252
288
  u8arr[n] = bstr.charCodeAt(n);
253
289
  }
254
- return new File([u8arr], `${filename}.${extension}`, {type: mime});
290
+ return new File([u8arr], `${filename}.${extension}`, { type: mime });
255
291
  },
292
+
256
293
  successCb (response, res) {
257
- this.value[this.propsObj._key] = res.data.downloadUrl;
294
+ this.curVal = res.data.downloadUrl;
258
295
  this.$emit("change", res);
259
296
  },
260
297
  handleError (err) {
261
298
  alert(err);
262
299
  },
300
+
263
301
  // 点击文件预览
264
302
  handlePreview (file) {
265
303
  let viewerImage = this.$refs.viewerImage;
@@ -276,11 +314,26 @@
276
314
  // 点击文件删除 - fileList服务器的数据列表
277
315
  handleRemove (file) {
278
316
  this.inputType = "file"; // 删除后可以重新上传
279
- this.value[this.propsObj._key] = "";
317
+ this.curVal = "";
280
318
  this.change(this.value);
281
319
  },
282
320
  change (...params) {
283
321
  this.$emit("change", ...params);
322
+ },
323
+
324
+ // 打开修改头像
325
+ openAvatarModal () {
326
+ this.avatarModal = true;
327
+ },
328
+ // 关闭修改头像
329
+ closeAvatarModal () {
330
+ this.avatarModal = false;
331
+ },
332
+ // 头像模态框状态变化,关闭后改变input框类型,保证上传能够连续上传同一张图片
333
+ visibleChange (bool) {
334
+ if (!bool) {
335
+ this.inputType = "file";
336
+ }
284
337
  }
285
338
  }
286
339
  };
@@ -247,9 +247,14 @@
247
247
  <script>
248
248
  import Viewer from "viewerjs";
249
249
  import axios from "axios";
250
+ // import DshVideoPlayer from "../../../other/DshVideoPlayer.vue";
250
251
 
251
252
  export default {
252
253
  name: "uploadList",
254
+ mixins: [],
255
+ components: {
256
+ // DshVideoPlayer
257
+ },
253
258
  props: {
254
259
  showMode: {
255
260
  type: String,
@@ -426,6 +431,7 @@
426
431
  }
427
432
  });
428
433
  },
434
+
429
435
  // 获取不同类型文件的图片
430
436
  getFileImage (fileItem) {
431
437
  if (!fileItem.mimetype) {
@@ -451,12 +457,17 @@
451
457
  }
452
458
  },
453
459
  getBtns (fileItem) {
454
- return ["image", "application/pdf", "text/plain"].some(type => fileItem.mimetype.includes(type)) ||
455
- fileItem.mimetype.includes("wordprocessingml.document") ||
456
- fileItem.mimetype.includes("application/msword") ||
457
- fileItem.mimetype.includes("presentationml.presentation") ||
458
- fileItem.mimetype.includes("application/vnd.ms-powerpoint") ||
459
- fileItem.mimetype.includes("spreadsheetml.sheet")
460
+ return [
461
+ "image", "video/mp4",
462
+ "text/plain",
463
+ // "text/csv", // 好像是便签,如果预览会直接下载
464
+ "application/pdf", "wordprocessingml.document", "spreadsheetml.sheet", // excel
465
+ "application/octet-stream", // 日志 .log
466
+ // "application/zip",
467
+ "application/msword",
468
+ "application/vnd.ms-powerpoint",
469
+ "presentationml.presentation"
470
+ ].some(type => fileItem.mimetype.includes(type))
460
471
  ? undefined
461
472
  : ["canDelete", "canEdit", "canDownload"];
462
473
  }
@@ -43,36 +43,39 @@ export default {
43
43
  return this.propsObj._archiveKey || [];
44
44
  },
45
45
  percentColor () {
46
- if (Number(this.percent) === 100) {
47
- return "#5cb85c";
48
- } else {
49
- return "#6090ed";
50
- }
46
+ return Number(this.percent) === 100 ? "#5cb85c" : "#6090ed";
51
47
  }
52
48
  },
53
49
  methods: {
54
50
  handlePost (file, callback) {
55
51
  this.$https({
56
52
  url: this.computedUrlModule,
57
- params: {
58
- token: this.$route.query && this.$route.query.token
59
- },
53
+ params: {},
60
54
  callback: res => {
61
55
  this.inputType = "file";
62
56
  if (res.ossType === "ali-oss") {
63
57
  // 上传到阿里云res
64
- this[this.computedOssType](file, res, callback);
65
- } else if (res.ossType === "local") {
58
+ if (this.computedOssType === "binaryMultipartUpload") {
59
+ this.binaryMultipartUpload(file, res, callback);
60
+ }
61
+ else if (this.computedOssType === "multipartUpload") {
62
+ this.multipartUpload(file, res, callback);
63
+ }
64
+ }
65
+ else if (res.ossType === "local") {
66
66
  this.localUpload(file, res, callback);
67
- } else if (res.ossType === "minio") {
67
+ }
68
+ else if (res.ossType === "minio") {
68
69
  this.minioUpload(file, res, callback);
69
- } else {
70
+ }
71
+ else {
70
72
  console.log(`请开发这种类型‘${res.ossType}’的上传模式`);
71
73
  }
72
74
 
73
75
  }
74
76
  });
75
77
  },
78
+
76
79
  localUpload (file, res, callback) {
77
80
  let fileBody = {
78
81
  groupKey: this.computedGroupKey,
@@ -107,92 +110,6 @@ export default {
107
110
  callback && callback(error);
108
111
  });
109
112
  },
110
- multipartUpload (file, res, callback) {
111
- let type = file.name.substring(file.name.lastIndexOf(".") + 1).toLowerCase();
112
- let remoteName = `${this.randomTimeStampFn()}.${type}`;
113
- let officeFileDefaultType = "";
114
- if (!file.type) {
115
- switch (type) {
116
- case "xls":
117
- officeFileDefaultType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
118
- break;
119
- case "xlsx":
120
- officeFileDefaultType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
121
- break;
122
- case "doc":
123
- officeFileDefaultType = "application/msword";
124
- break;
125
- case "docx":
126
- officeFileDefaultType = "application/msword";
127
- break;
128
- case "ppt":
129
- officeFileDefaultType = "application/vnd.ms-powerpoint";
130
- break;
131
- case "pptx":
132
- officeFileDefaultType = "application/vnd.ms-powerpoint";
133
- break;
134
- default:
135
- officeFileDefaultType = "";
136
- }
137
- }
138
-
139
- // 上传成功的回调参数
140
- let callbackBody = {
141
- name: file.name,
142
- mimetype: file.type || officeFileDefaultType,
143
- size: file.size,
144
- path: remoteName,
145
- bucket: res.ossConfig.bucket,
146
- filetoken: res.filetoken,
147
- groupKey: this.computedGroupKey,
148
- archiveKey: this.archiveKey[this.archiveKey.length - 1]
149
- };
150
-
151
- let ossCallback = {
152
- callbackUrl: res.ossHost + res.confirmPath,
153
- callbackBodyType: "application/json",
154
- callbackBody: this.transferCallBody(callbackBody)
155
- };
156
-
157
- let newOss = {
158
- ...res.ossConfig,
159
- refreshSTSToken: async () => {
160
- // 向您搭建的STS服务获取临时访问凭证。
161
- return {
162
- accessKeyId: res.ossConfig.accessKeyId, // 自己账户的accessKeyId或临时秘钥
163
- accessKeySecret: res.ossConfig.accessKeySecret, // 自己账户的accessKeySecret或临时秘钥
164
- stsToken: res.ossConfig.stsToken // 从STS服务获取的安全令牌(SecurityToken)。
165
- };
166
- },
167
- // 刷新临时访问凭证的时间间隔,单位为毫秒。
168
- refreshSTSTokenInterval: 3600 * 1000
169
- };
170
-
171
- new Oss(newOss).multipartUpload(remoteName, file, {
172
- progress: (percentage) => {
173
- this.inProgress(Number((percentage * 100).toFixed(1)));
174
- this.handleProgress && this.handleProgress(percentage, file);
175
- },
176
- headers: {
177
- "x-oss-callback": this.base64Encode(JSON.stringify(ossCallback)),
178
- "Content-Disposition": type === "pdf" ? `inline;filename=${encodeURI(file.name)}` : `attachment;filename=${encodeURI(file.name)}`
179
- }
180
- }).then(response => {
181
- this.uploadSuccess = true;
182
- this.percent = 100;
183
- setTimeout(() => {
184
- this.percent = 0;
185
- this.uploadSuccess = false;
186
- }, 500);
187
- this.successCb && this.successCb(response, response.data, file);
188
- callback && callback(response.data);
189
- }).catch((err, response) => {
190
- this.percent = 0;
191
- this.uploadSuccess = false;
192
- this.handleError && this.handleError(err, response, file);
193
- callback && callback(err);
194
- });
195
- },
196
113
  minioUpload (file, res, callback) {
197
114
  let type = file.name.substring(file.name.lastIndexOf(".") + 1).toLowerCase();
198
115
  let remoteName = `${this.randomTimeStampFn()}.${type}`;
@@ -282,6 +199,92 @@ export default {
282
199
  };
283
200
  };
284
201
  },
202
+ multipartUpload (file, res, callback) {
203
+ let type = file.name.substring(file.name.lastIndexOf(".") + 1).toLowerCase();
204
+ let remoteName = `${this.randomTimeStampFn()}.${type}`;
205
+ let officeFileDefaultType = "";
206
+ if (!file.type) {
207
+ switch (type) {
208
+ case "xls":
209
+ officeFileDefaultType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
210
+ break;
211
+ case "xlsx":
212
+ officeFileDefaultType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
213
+ break;
214
+ case "doc":
215
+ officeFileDefaultType = "application/msword";
216
+ break;
217
+ case "docx":
218
+ officeFileDefaultType = "application/msword";
219
+ break;
220
+ case "ppt":
221
+ officeFileDefaultType = "application/vnd.ms-powerpoint";
222
+ break;
223
+ case "pptx":
224
+ officeFileDefaultType = "application/vnd.ms-powerpoint";
225
+ break;
226
+ default:
227
+ officeFileDefaultType = "";
228
+ }
229
+ }
230
+
231
+ // 上传成功的回调参数
232
+ let callbackBody = {
233
+ name: file.name,
234
+ mimetype: file.type || officeFileDefaultType,
235
+ size: file.size,
236
+ path: remoteName,
237
+ bucket: res.ossConfig.bucket,
238
+ filetoken: res.filetoken,
239
+ groupKey: this.computedGroupKey,
240
+ archiveKey: this.archiveKey[this.archiveKey.length - 1]
241
+ };
242
+
243
+ let ossCallback = {
244
+ callbackUrl: res.ossHost + res.confirmPath,
245
+ callbackBodyType: "application/json",
246
+ callbackBody: this.transferCallBody(callbackBody)
247
+ };
248
+
249
+ let newOss = {
250
+ ...res.ossConfig,
251
+ refreshSTSToken: async () => {
252
+ // 向您搭建的STS服务获取临时访问凭证。
253
+ return {
254
+ accessKeyId: res.ossConfig.accessKeyId, // 自己账户的accessKeyId或临时秘钥
255
+ accessKeySecret: res.ossConfig.accessKeySecret, // 自己账户的accessKeySecret或临时秘钥
256
+ stsToken: res.ossConfig.stsToken // 从STS服务获取的安全令牌(SecurityToken)。
257
+ };
258
+ },
259
+ // 刷新临时访问凭证的时间间隔,单位为毫秒。
260
+ refreshSTSTokenInterval: 3600 * 1000
261
+ };
262
+
263
+ new Oss(newOss).multipartUpload(remoteName, file, {
264
+ progress: (percentage) => {
265
+ this.inProgress(Number((percentage * 100).toFixed(1)));
266
+ this.handleProgress && this.handleProgress(percentage, file);
267
+ },
268
+ headers: {
269
+ "x-oss-callback": this.base64Encode(JSON.stringify(ossCallback)),
270
+ "Content-Disposition": type === "pdf" ? `inline;filename=${encodeURI(file.name)}` : `attachment;filename=${encodeURI(file.name)}`
271
+ }
272
+ }).then(response => {
273
+ this.uploadSuccess = true;
274
+ this.percent = 100;
275
+ setTimeout(() => {
276
+ this.percent = 0;
277
+ this.uploadSuccess = false;
278
+ }, 500);
279
+ this.successCb && this.successCb(response, response.data, file);
280
+ callback && callback(response.data);
281
+ }).catch((err, response) => {
282
+ this.percent = 0;
283
+ this.uploadSuccess = false;
284
+ this.handleError && this.handleError(err, response, file);
285
+ callback && callback(err);
286
+ });
287
+ },
285
288
  // bri-upload-image 用的是这种方式
286
289
  binaryMultipartUpload (file, res, callback) {
287
290
  let type = "jpg";
@@ -342,14 +345,16 @@ export default {
342
345
  this.handleError && this.handleError(err, response, file);
343
346
  callback && callback(err);
344
347
  });
345
-
346
348
  },
349
+
350
+ // 处理上传进度
347
351
  inProgress (percent) {
348
352
  if (percent === 100 && !this.uploadSuccess) {
349
353
  this.percent = 99.9;
350
354
  } else {
351
355
  this.percent = percent;
352
356
  }
357
+
353
358
  if (this.percent >= 100) {
354
359
  this.percent = 100;
355
360
  setTimeout(() => {
@@ -170,7 +170,9 @@
170
170
  {{ emptyShowVal }}
171
171
  </div>
172
172
  </div>
173
- <div v-else-if="propsObj._enterType === 'calculate'"
173
+
174
+ <div
175
+ v-else-if="propsObj._enterType === 'calculate'"
174
176
  class="DshCoordinates-show"
175
177
  >
176
178
  <span :class="{'nodata': !showVal}">{{ showVal || '暂无内容' }}</span>
@@ -319,7 +319,7 @@
319
319
  }
320
320
 
321
321
  // 处理最大值最小值
322
- const {min, max} = this;
322
+ const { min, max } = this;
323
323
  if (val !== null) {
324
324
  if (val > max) {
325
325
  val = max;
@@ -76,7 +76,7 @@ export function getStyle (element, styleName) {
76
76
  function firstUpperCase (str) {
77
77
  return str.toString()[0].toUpperCase() + str.toString().slice(1);
78
78
  }
79
- export {firstUpperCase};
79
+ export { firstUpperCase };
80
80
 
81
81
  // Warn
82
82
  export function warnProp (component, prop, correctType, wrongType) {
@@ -127,7 +127,7 @@ function deepCopy (data) {
127
127
  return o;
128
128
  }
129
129
 
130
- export {deepCopy};
130
+ export { deepCopy };
131
131
 
132
132
  // scrollTop animation
133
133
  export function scrollTop (el, from = 0, to, duration = 500, endCallback) {
@@ -181,7 +181,7 @@ function findComponentUpward (context, componentName, componentNames) {
181
181
  }
182
182
  return parent;
183
183
  }
184
- export {findComponentUpward};
184
+ export { findComponentUpward };
185
185
 
186
186
  // Find component downward
187
187
  export function findComponentDownward (context, componentName) {
@@ -311,8 +311,8 @@ export function setMatchMedia () {
311
311
  return {
312
312
  media: mediaQuery,
313
313
  matches: false,
314
- on () {},
315
- off () {}
314
+ on () { },
315
+ off () { }
316
316
  };
317
317
  };
318
318
  window.matchMedia = window.matchMedia || matchMediaPolyfill;
@@ -159,7 +159,6 @@
159
159
  <script>
160
160
  import userAndDepartMixin from "../mixins/userAndDepartMixin.js";
161
161
  import BriTreeItem from "../../list/BriTreeItem.vue";
162
- import BriCard from "../../list/BriCard.vue";
163
162
 
164
163
  export default {
165
164
  name: "selectDepartments",
@@ -167,8 +166,7 @@
167
166
  userAndDepartMixin
168
167
  ],
169
168
  components: {
170
- BriTreeItem,
171
- BriCard
169
+ BriTreeItem
172
170
  },
173
171
  props: {},
174
172
  data () {
@@ -39,7 +39,10 @@
39
39
  :type="getIcon(depart)"
40
40
  @click.stop="toggleChildren(depart)"
41
41
  />
42
- <span v-else style="margin-right:1px"></span>
42
+ <span
43
+ v-else
44
+ style="margin-right:1px"
45
+ ></span>
43
46
  <Icon
44
47
  v-if="useIcon"
45
48
  custom="bico-font bri-qiye bico-qiye"
@@ -199,7 +202,7 @@
199
202
  this.$emit("showAddModal", parent);
200
203
  },
201
204
  deleteDepart (current) {
202
- this.departSelected = {_key: "noDepart"};
205
+ this.departSelected = { _key: "noDepart" };
203
206
  this.$emit("deleteDepart", current);
204
207
  },
205
208
  // 提示删除
@@ -119,7 +119,7 @@
119
119
  headerCellClass: () => {
120
120
  return "bri-table-th";
121
121
  },
122
- bodyCellClass: ({rowIndex}) => {
122
+ bodyCellClass: ({ rowIndex }) => {
123
123
  return "bri-table-td";
124
124
  },
125
125
  ...(this.propsObj.cellStyleOption || {})
@@ -374,7 +374,7 @@
374
374
  placeholder: "请输入节点名称",
375
375
  size: "small"
376
376
  },
377
- directives: [{name: "focus"}],
377
+ directives: [{ name: "focus" }],
378
378
  style: {
379
379
  width: "200px"
380
380
  },
@@ -433,7 +433,7 @@
433
433
  handleUp (data) {
434
434
  const index = this.treeData.findIndex(item => item._key === data._key);
435
435
  if (index > 0) {
436
- const prevData = {...this.treeData[index - 1]};
436
+ const prevData = { ...this.treeData[index - 1] };
437
437
  this.treeData.splice(index - 1, 1);
438
438
  this.treeData.splice(index, 0, prevData);
439
439
  this.onChange();
@@ -442,7 +442,7 @@
442
442
  handleDown (data) {
443
443
  const index = this.treeData.findIndex(item => item._key === data._key);
444
444
  if (index < this.treeData.length - 1) {
445
- const nextData = {...this.treeData[index]};
445
+ const nextData = { ...this.treeData[index] };
446
446
  this.treeData.splice(index, 1);
447
447
  this.treeData.splice(index + 1, 0, nextData);
448
448
  this.onChange();
@@ -212,7 +212,6 @@
212
212
  <script>
213
213
  import tableBaseMixin from "./mixins/tableBaseMixin.js";
214
214
  import DshFlatTableMixin from "./mixins/DshFlatTableMixin.js";
215
- import DshDivider from "../controls/base/DshDivider.vue";
216
215
 
217
216
  export default {
218
217
  name: "DshFlatTable",
@@ -220,9 +219,7 @@
220
219
  tableBaseMixin,
221
220
  DshFlatTableMixin
222
221
  ],
223
- components: {
224
- DshDivider
225
- },
222
+ components: {},
226
223
  props: {},
227
224
  data () {
228
225
  return {};
@@ -710,7 +710,7 @@
710
710
  },
711
711
  // 绑定同步滚动
712
712
  handleScroll (el, scrollList) {
713
- scrollList.forEach(({ref, direction} = item) => {
713
+ scrollList.forEach(({ ref, direction } = item) => {
714
714
  this.$refs[ref] && (this.$refs[ref][direction] = el.target[direction]);
715
715
  });
716
716
  },
@@ -0,0 +1,184 @@
1
+ <template>
2
+ <div class="video-container">
3
+ <video
4
+ ref="videoPlayer"
5
+ id="videoPlayer"
6
+ class="video-js vjs-big-play-centered"
7
+ controls
8
+ preload="auto"
9
+ width="100%"
10
+ height="100%"
11
+ >
12
+ <!-- <source
13
+ :src="src"
14
+ type="application/x-mpegURL"
15
+ /> -->
16
+ </video>
17
+
18
+ <!-- <div v-else>
19
+ <video
20
+ id="video"
21
+ width="640"
22
+ height="360"
23
+ poster="/video/cover.png"
24
+ controls
25
+ autoplay
26
+ loop
27
+ preload="auto"
28
+ playsinline="true"
29
+ webkit-playsinline="true"
30
+ x5-video-player-type="h5"
31
+ x5-video-player-fullscreen="true"
32
+ x5-video-orientation="portraint"
33
+ οnclick="play()"
34
+ >
35
+ <source
36
+ :src="attachmentLink"
37
+ type="video/mp4"
38
+ >
39
+ <source
40
+ src="/video/text.ogg"
41
+ type="video/ogg; codecs=dirac, speex"
42
+ >
43
+
44
+ <div class="fallback">
45
+ <p>You must have an HTML5 capable browser.</p>
46
+ </div>
47
+ </video>
48
+ </div> -->
49
+ </div>
50
+ </template>
51
+
52
+ <script>
53
+ import videojs from "video.js"; // 视频播放器插件
54
+ import "video.js/dist/video-js.css";
55
+ import "videojs-contrib-hls"; // 播放hls流插件
56
+
57
+ export default {
58
+ name: "DshVideoPlayer",
59
+ props: {
60
+ // 默认mp4
61
+ videoType: {
62
+ type: String
63
+ },
64
+ src: {
65
+ type: String,
66
+ required: true
67
+ },
68
+ options: {
69
+ type: Object,
70
+ default: () => ({})
71
+ }
72
+ },
73
+ data () {
74
+ return {
75
+ player: null
76
+ // attachmentLink: "https://e-sign.dms.t.cn-np.com/files/m3u8_file/c4b94118-3c8d-4410-9987-985c2b44c278/c4b94118-3c8d-4410-9987-985c2b44c278.m3u8"
77
+ // attachmentLink: "http://10.233.0.231:801/gs/66322263001320007102.m3u8" // 十二师治超站门口
78
+ // attachmentLink: "http://10.233.0.231:801/gs/66322263001320007101.m3u8" // 十二师治超站称重位
79
+ // attachmentLink: "http://10.233.0.231:801/gs/66322263001320007128.m3u8" // 石火山隧道
80
+ // attachmentLink: "http://staging.bridata.com:6203/api/ossfile/apaas-local/56a2725229d6e59440f77ce47dbd67ab.mp4"
81
+ // attachmentLink: "http://staging.bridata.com:6203/api/ossfile/apaas-local/6f9f0f4a42be671a47cc31343aef9a20.mp4"
82
+ };
83
+ },
84
+ computed: {
85
+ sourceType () {
86
+ return this.videoType === "m3u8"
87
+ ? "application/x-mpegURL" // 告诉videojs,这是一个hls流
88
+ : "video/mp4";
89
+ },
90
+ finalOptions () {
91
+ return {
92
+ autoplay: false, // 设置自动播放
93
+ // controls: true, // 显示播放的控件
94
+ sources: [
95
+ {
96
+ // src: this.src || this.attachmentLink, // 地址
97
+ src: this.src, // 地址
98
+ type: this.sourceType
99
+ }
100
+ ],
101
+ fluid: true,
102
+ liveui: true,
103
+ html5: {
104
+ hls: {
105
+ overrideNative: true,
106
+ debug: true
107
+ }
108
+ },
109
+ playbackRates: [0.7, 1.0, 1.5, 2.0], // 播放速度
110
+ aspectRatio: "16:9",
111
+ notSupportedMessage: "此视频暂无法播放,请稍后再试", // 允许覆盖Video.js无法播放媒体源时显示的默认信息。
112
+ preload: "auto", // 预加载
113
+ muted: true, // 是否静音,设置了它为true,才可实现自动播放,同时视频也被静音(Chrome66及以上版本,禁止音视频的自动播放)
114
+ volume: 0.5, // 初始音量 (0-1)
115
+ // audioOnlyMode: false, // 是否仅音频模式
116
+ // audioPosterMode: false, // 音频海报模式
117
+ // breakpoints: {
118
+ // audio: {
119
+ // width: 300 // 音频模式下的播放器宽度
120
+ // }
121
+ // },
122
+
123
+ ...this.options
124
+ };
125
+ }
126
+ },
127
+ watch: {
128
+ src (newSrc) {
129
+ if (this.player) {
130
+ this.player.src({
131
+ src: newSrc,
132
+ type: this.sourceType
133
+ });
134
+ }
135
+ }
136
+ },
137
+ mounted () {
138
+ this.initPlayer();
139
+ // // 使用 $nextTick 解决vedio报错 The element or ID supplied is not valid. (videojs)
140
+ // this.$nextTick(() => {
141
+ // this.initPlayer();
142
+ // });
143
+ },
144
+ beforeDestroy () {
145
+ if (this.player) {
146
+ this.player.dispose();
147
+ }
148
+ },
149
+ methods: {
150
+ initPlayer () {
151
+ this.player = videojs(this.$refs.videoPlayer, this.finalOptions, this.onPlayerReady);
152
+ // this.player = videojs("videoPlayer", this.finalOptions, this.onPlayerReady);
153
+ },
154
+ onPlayerReady () {
155
+ // console.log("Player ready", this.finalOptions);
156
+ },
157
+
158
+ playVideo () {
159
+ let video = document.getElementById("video");
160
+ video.play();
161
+ }
162
+ }
163
+ };
164
+ </script>
165
+
166
+ <style lang="less" scoped>
167
+ .video-container {
168
+ width: 100%;
169
+ height: 100%;
170
+ background-color: #000;
171
+ }
172
+ </style>
173
+ <style lang="less">
174
+ .video-js {
175
+ width: 100%;
176
+ // height: 100%!important; // 放开也不管用
177
+ }
178
+ // 暂停播放按钮居中
179
+ ::v-deep .video-js .vjs-big-play-button {
180
+ top: 50%;
181
+ left: 50%;
182
+ transform: translate(-50%, -50%);
183
+ }
184
+ </style>
package/src/index.js CHANGED
@@ -101,6 +101,7 @@ import DshMenuNav from "./components/other/DshMenuNav.vue";
101
101
  import BriCode from "./components/other/BriCode.vue";
102
102
  import BriCollapseTree from "./components/other/BriCollapseTree.vue";
103
103
  import BriGantt from "./components/other/BriGantt.vue";
104
+ import DshVideoPlayer from "./components/other/DshVideoPlayer.vue";
104
105
 
105
106
  // small
106
107
  import DshBtnModal from "./components/small/DshBtnModal.vue";
@@ -224,6 +225,7 @@ export {
224
225
  BriIframe,
225
226
  BriSvg,
226
227
  DshColorPanel,
228
+ DshVideoPlayer,
227
229
 
228
230
  // small
229
231
  DshRender,