|
@@ -2,412 +2,422 @@ import $api from '@/api'
|
|
|
import store from '@/store'
|
|
|
|
|
|
/**
|
|
|
- * 校验blob授权是否过期
|
|
|
- * */
|
|
|
+ * 校验blob授权是否过期
|
|
|
+ * */
|
|
|
function checkSas(sasTs) {
|
|
|
- let curTimestamp = (new Date()).getTime()
|
|
|
- if (curTimestamp >= sasTs) {
|
|
|
- return true
|
|
|
- } else {
|
|
|
- return false
|
|
|
- }
|
|
|
+ let curTimestamp = (new Date()).getTime()
|
|
|
+ if (curTimestamp >= sasTs) {
|
|
|
+ return true
|
|
|
+ } else {
|
|
|
+ return false
|
|
|
+ }
|
|
|
}
|
|
|
export default {
|
|
|
- // vueScroll全局配置工具;
|
|
|
- vueScrollOpt: {
|
|
|
- mode: 'native',
|
|
|
- // 设置 vuescroll的大小类型, 可选的有percent, number.
|
|
|
- // 设置为percent会把 vuescroll 的 height 和 width 设置成100%,
|
|
|
- // 设置成number的话 vuescroll 会自动计算父元素的大小,并将height和width设置成对应的数值。
|
|
|
- // 提示:如果父元素的尺寸为百分比大小时建议设置成number,如果父元素大小为一个固定的px的值,那么设置为百分比比较合适一些。
|
|
|
- sizeStrategy: 'percent',
|
|
|
- // 是否开启监听 dom resize
|
|
|
- detectResize: false,
|
|
|
- // 下拉刷新相关(slide mode)
|
|
|
- pullRefresh: {
|
|
|
- enable: false,
|
|
|
- // 下拉刷新的提示
|
|
|
- tips: {
|
|
|
- deactive: 'Pull to Refresh',
|
|
|
- active: 'Release to Refresh',
|
|
|
- start: 'Refreshing...',
|
|
|
- beforeDeactive: 'Refresh Successfully!'
|
|
|
- }
|
|
|
- },
|
|
|
- // 上推加载相关
|
|
|
- pushLoad: {
|
|
|
- enable: false,
|
|
|
- tips: {
|
|
|
- deactive: 'Push to Load',
|
|
|
- active: 'Release to Load',
|
|
|
- start: 'Loading...',
|
|
|
- beforeDeactive: 'Load Successfully!'
|
|
|
- },
|
|
|
- auto: false,
|
|
|
- autoLoadDistance: 0
|
|
|
- },
|
|
|
- paging: false,
|
|
|
- zooming: true,
|
|
|
- // 快照
|
|
|
- snapping: {
|
|
|
- enable: false,
|
|
|
- width: 100,
|
|
|
- height: 100
|
|
|
- },
|
|
|
- /* shipped scroll options */
|
|
|
- scroller: {
|
|
|
- /*
|
|
|
- 允许滚动出边界
|
|
|
- true 或者 false 或者一个数组指定哪个方向可以超出边界,可选项分别是:
|
|
|
- ['top','bottom','left','right']
|
|
|
- */
|
|
|
- bouncing: true,
|
|
|
- /** Enable locking to the main axis if user moves only slightly on one of them at start */
|
|
|
- locking: true,
|
|
|
- /** 最小缩放级别 */
|
|
|
- minZoom: 0.5,
|
|
|
- /** 最大缩放级别 */
|
|
|
- maxZoom: 3,
|
|
|
- /** 滚动速度的倍速 **/
|
|
|
- speedMultiplier: 1,
|
|
|
- /** 到达边界时应用于减速的改变量 **/
|
|
|
- penetrationDeceleration: 0.03,
|
|
|
- /** 到达边界时应用于加速的改变量 **/
|
|
|
- penetrationAcceleration: 0.08,
|
|
|
- /** Whether call e.preventDefault event when sliding the content or not */
|
|
|
- preventDefault: true,
|
|
|
- /** Whether call preventDefault when (mouse/touch)move */
|
|
|
- preventDefaultOnMove: true
|
|
|
- },
|
|
|
- scrollPanel: {
|
|
|
- // 组件加载完后的初始滚动量
|
|
|
- initialScrollY: false,
|
|
|
- initialScrollX: false,
|
|
|
- // 是否禁止x或y方向上的滚动
|
|
|
- scrollingX: false,
|
|
|
- scrollingY: true,
|
|
|
- speed: 300,
|
|
|
- // 滚动动画
|
|
|
- easing: undefined,
|
|
|
- // 是否有一个padding样式,样式的大小应该和rail/bar的大小是一样。可以用来阻止内容被滚动条遮住一部分
|
|
|
- padding: false,
|
|
|
- // 有时候原声滚动条可能在左侧,
|
|
|
- // 请查看 https://github.com/YvesCoding/vuescroll/issues/64
|
|
|
- verticalNativeBarPos: 'right'
|
|
|
- },
|
|
|
- // 滚动条滚动的地方
|
|
|
- rail: {
|
|
|
- background: '#000',
|
|
|
- opacity: 0,
|
|
|
- border: 'none',
|
|
|
- /** Rail's size(Height/Width) , default -> 6px */
|
|
|
- size: '6px',
|
|
|
- /** Specify rail's border-radius, or the border-radius of rail and bar will be equal to the rail's size. default -> false **/
|
|
|
- specifyBorderRadius: false,
|
|
|
- /** Rail the distance from the two ends of the X axis and Y axis. **/
|
|
|
- gutterOfEnds: null,
|
|
|
- /** Rail the distance from the side of container. **/
|
|
|
- gutterOfSide: '0px',
|
|
|
- /** Whether to keep rail show or not, default -> false, event content height is not enough */
|
|
|
- keepShow: false
|
|
|
- },
|
|
|
- bar: {
|
|
|
- /** 当不做任何操作时滚动条自动消失的时间 */
|
|
|
- showDelay: 1000,
|
|
|
- /** Specify bar's border-radius, or the border-radius of rail and bar will be equal to the rail's size. default -> false **/
|
|
|
- specifyBorderRadius: false,
|
|
|
- /** 是否只在滚动的时候现实滚动条 */
|
|
|
- onlyShowBarOnScroll: false,
|
|
|
- /** 是否保持显示 */
|
|
|
- keepShow: false,
|
|
|
- /** 滚动条颜色, default -> #00a650 */
|
|
|
- background: 'rgb(58,58,58)',
|
|
|
- /** 滚动条透明度, default -> 1 */
|
|
|
- opacity: 1,
|
|
|
- /** Styles when you hover scrollbar, it will merge into the current style */
|
|
|
- hoverStyle: false
|
|
|
- },
|
|
|
- scrollButton: {
|
|
|
- enable: false,
|
|
|
- background: 'rgb(3, 185, 118)',
|
|
|
- opacity: 1,
|
|
|
- step: 180,
|
|
|
- mousedownStep: 30
|
|
|
- }
|
|
|
- },
|
|
|
+ // vueScroll全局配置工具;
|
|
|
+ vueScrollOpt: {
|
|
|
+ mode: 'native',
|
|
|
+ // 设置 vuescroll的大小类型, 可选的有percent, number.
|
|
|
+ // 设置为percent会把 vuescroll 的 height 和 width 设置成100%,
|
|
|
+ // 设置成number的话 vuescroll 会自动计算父元素的大小,并将height和width设置成对应的数值。
|
|
|
+ // 提示:如果父元素的尺寸为百分比大小时建议设置成number,如果父元素大小为一个固定的px的值,那么设置为百分比比较合适一些。
|
|
|
+ sizeStrategy: 'percent',
|
|
|
+ // 是否开启监听 dom resize
|
|
|
+ detectResize: false,
|
|
|
+ // 下拉刷新相关(slide mode)
|
|
|
+ pullRefresh: {
|
|
|
+ enable: false,
|
|
|
+ // 下拉刷新的提示
|
|
|
+ tips: {
|
|
|
+ deactive: 'Pull to Refresh',
|
|
|
+ active: 'Release to Refresh',
|
|
|
+ start: 'Refreshing...',
|
|
|
+ beforeDeactive: 'Refresh Successfully!'
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 上推加载相关
|
|
|
+ pushLoad: {
|
|
|
+ enable: false,
|
|
|
+ tips: {
|
|
|
+ deactive: 'Push to Load',
|
|
|
+ active: 'Release to Load',
|
|
|
+ start: 'Loading...',
|
|
|
+ beforeDeactive: 'Load Successfully!'
|
|
|
+ },
|
|
|
+ auto: false,
|
|
|
+ autoLoadDistance: 0
|
|
|
+ },
|
|
|
+ paging: false,
|
|
|
+ zooming: true,
|
|
|
+ // 快照
|
|
|
+ snapping: {
|
|
|
+ enable: false,
|
|
|
+ width: 100,
|
|
|
+ height: 100
|
|
|
+ },
|
|
|
+ /* shipped scroll options */
|
|
|
+ scroller: {
|
|
|
+ /*
|
|
|
+ 允许滚动出边界
|
|
|
+ true 或者 false 或者一个数组指定哪个方向可以超出边界,可选项分别是:
|
|
|
+ ['top','bottom','left','right']
|
|
|
+ */
|
|
|
+ bouncing: true,
|
|
|
+ /** Enable locking to the main axis if user moves only slightly on one of them at start */
|
|
|
+ locking: true,
|
|
|
+ /** 最小缩放级别 */
|
|
|
+ minZoom: 0.5,
|
|
|
+ /** 最大缩放级别 */
|
|
|
+ maxZoom: 3,
|
|
|
+ /** 滚动速度的倍速 **/
|
|
|
+ speedMultiplier: 1,
|
|
|
+ /** 到达边界时应用于减速的改变量 **/
|
|
|
+ penetrationDeceleration: 0.03,
|
|
|
+ /** 到达边界时应用于加速的改变量 **/
|
|
|
+ penetrationAcceleration: 0.08,
|
|
|
+ /** Whether call e.preventDefault event when sliding the content or not */
|
|
|
+ preventDefault: true,
|
|
|
+ /** Whether call preventDefault when (mouse/touch)move */
|
|
|
+ preventDefaultOnMove: true
|
|
|
+ },
|
|
|
+ scrollPanel: {
|
|
|
+ // 组件加载完后的初始滚动量
|
|
|
+ initialScrollY: false,
|
|
|
+ initialScrollX: false,
|
|
|
+ // 是否禁止x或y方向上的滚动
|
|
|
+ scrollingX: false,
|
|
|
+ scrollingY: true,
|
|
|
+ speed: 300,
|
|
|
+ // 滚动动画
|
|
|
+ easing: undefined,
|
|
|
+ // 是否有一个padding样式,样式的大小应该和rail/bar的大小是一样。可以用来阻止内容被滚动条遮住一部分
|
|
|
+ padding: false,
|
|
|
+ // 有时候原声滚动条可能在左侧,
|
|
|
+ // 请查看 https://github.com/YvesCoding/vuescroll/issues/64
|
|
|
+ verticalNativeBarPos: 'right'
|
|
|
+ },
|
|
|
+ // 滚动条滚动的地方
|
|
|
+ rail: {
|
|
|
+ background: '#000',
|
|
|
+ opacity: 0,
|
|
|
+ border: 'none',
|
|
|
+ /** Rail's size(Height/Width) , default -> 6px */
|
|
|
+ size: '6px',
|
|
|
+ /** Specify rail's border-radius, or the border-radius of rail and bar will be equal to the rail's size. default -> false **/
|
|
|
+ specifyBorderRadius: false,
|
|
|
+ /** Rail the distance from the two ends of the X axis and Y axis. **/
|
|
|
+ gutterOfEnds: null,
|
|
|
+ /** Rail the distance from the side of container. **/
|
|
|
+ gutterOfSide: '0px',
|
|
|
+ /** Whether to keep rail show or not, default -> false, event content height is not enough */
|
|
|
+ keepShow: false
|
|
|
+ },
|
|
|
+ bar: {
|
|
|
+ /** 当不做任何操作时滚动条自动消失的时间 */
|
|
|
+ showDelay: 1000,
|
|
|
+ /** Specify bar's border-radius, or the border-radius of rail and bar will be equal to the rail's size. default -> false **/
|
|
|
+ specifyBorderRadius: false,
|
|
|
+ /** 是否只在滚动的时候现实滚动条 */
|
|
|
+ onlyShowBarOnScroll: false,
|
|
|
+ /** 是否保持显示 */
|
|
|
+ keepShow: false,
|
|
|
+ /** 滚动条颜色, default -> #00a650 */
|
|
|
+ background: 'rgb(58,58,58)',
|
|
|
+ /** 滚动条透明度, default -> 1 */
|
|
|
+ opacity: 1,
|
|
|
+ /** Styles when you hover scrollbar, it will merge into the current style */
|
|
|
+ hoverStyle: false
|
|
|
+ },
|
|
|
+ scrollButton: {
|
|
|
+ enable: false,
|
|
|
+ background: 'rgb(3, 185, 118)',
|
|
|
+ opacity: 1,
|
|
|
+ step: 180,
|
|
|
+ mousedownStep: 30
|
|
|
+ }
|
|
|
+ },
|
|
|
|
|
|
- // wangEditor菜单配置
|
|
|
- wangEditorMenu: [
|
|
|
- 'head', // 标题
|
|
|
- 'bold', // 粗体
|
|
|
- 'fontSize', // 字号
|
|
|
- 'fontName', // 字体
|
|
|
- 'italic', // 斜体
|
|
|
- 'underline', // 下划线
|
|
|
- 'strikeThrough', // 删除线
|
|
|
- 'foreColor', // 文字颜色
|
|
|
- 'link', // 插入链接
|
|
|
+ // wangEditor菜单配置
|
|
|
+ wangEditorMenu: [
|
|
|
+ 'head', // 标题
|
|
|
+ 'bold', // 粗体
|
|
|
+ 'fontSize', // 字号
|
|
|
+ 'fontName', // 字体
|
|
|
+ 'italic', // 斜体
|
|
|
+ 'underline', // 下划线
|
|
|
+ 'strikeThrough', // 删除线
|
|
|
+ 'foreColor', // 文字颜色
|
|
|
+ 'link', // 插入链接
|
|
|
'video', //插入视频
|
|
|
- 'justify', // 对齐方式
|
|
|
- 'image', // 插入图片
|
|
|
- 'table', // 表格
|
|
|
- 'undo', // 撤销
|
|
|
- ],
|
|
|
- // 生成随机UUID工具
|
|
|
- randomId: function() {
|
|
|
- return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
|
|
|
- },
|
|
|
- // 生成随机UUID工具
|
|
|
- guid: function() {
|
|
|
- return (this.randomId() + this.randomId() + '-' + this.randomId() + '-' + this.randomId() + '-' + this.randomId() + '-' + this.randomId() + this.randomId() + this.randomId())
|
|
|
- },
|
|
|
-
|
|
|
+ 'justify', // 对齐方式
|
|
|
+ 'image', // 插入图片
|
|
|
+ 'table', // 表格
|
|
|
+ 'undo', // 撤销
|
|
|
+ ],
|
|
|
+ // 生成随机UUID工具
|
|
|
+ randomId: function() {
|
|
|
+ return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1)
|
|
|
+ },
|
|
|
+ // 生成随机UUID工具
|
|
|
+ guid: function() {
|
|
|
+ return (this.randomId() + this.randomId() + '-' + this.randomId() + '-' + this.randomId() + '-' + this.randomId() +
|
|
|
+ '-' + this.randomId() + this.randomId() + this.randomId())
|
|
|
+ },
|
|
|
+
|
|
|
// 正则判断是否为标准的URL格式
|
|
|
isURL(url) {
|
|
|
- const strRegex = '^((https|http|ftp)://)?'//(https或http或ftp):// 可有可无
|
|
|
- + '(([\\w_!~*\'()\\.&=+$%-]+: )?[\\w_!~*\'()\\.&=+$%-]+@)?' //ftp的user@ 可有可无
|
|
|
- + '(([0-9]{1,3}\\.){3}[0-9]{1,3}' // IP形式的URL- 3位数字.3位数字.3位数字.3位数字
|
|
|
- + '|' // 允许IP和DOMAIN(域名)
|
|
|
- + '(localhost)|' //匹配localhost
|
|
|
- + '([\\w_!~*\'()-]+\\.)*' // 域名- 至少一个[英文或数字_!~*\'()-]加上.
|
|
|
- + '\\w+\\.' // 一级域名 -英文或数字 加上.
|
|
|
- + '[a-zA-Z]{1,6})' // 顶级域名- 1-6位英文
|
|
|
- + '(:[0-9]{1,5})?' // 端口- :80 ,1-5位数字
|
|
|
- + '((/?)|' // url无参数结尾 - 斜杆或这没有
|
|
|
- + '(/[\\w_!~*\'()\\.;?:@&=+$,%#-]+)+/?)$';//请求参数结尾- 英文或数字和[]内的各种字符
|
|
|
- const re = new RegExp(strRegex, 'i'); // 大小写不敏感
|
|
|
- if (re.test(encodeURI(url))) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- return false;
|
|
|
+ const strRegex = '^((https|http|ftp)://)?' //(https或http或ftp):// 可有可无
|
|
|
+ +
|
|
|
+ '(([\\w_!~*\'()\\.&=+$%-]+: )?[\\w_!~*\'()\\.&=+$%-]+@)?' //ftp的user@ 可有可无
|
|
|
+ +
|
|
|
+ '(([0-9]{1,3}\\.){3}[0-9]{1,3}' // IP形式的URL- 3位数字.3位数字.3位数字.3位数字
|
|
|
+ +
|
|
|
+ '|' // 允许IP和DOMAIN(域名)
|
|
|
+ +
|
|
|
+ '(localhost)|' //匹配localhost
|
|
|
+ +
|
|
|
+ '([\\w_!~*\'()-]+\\.)*' // 域名- 至少一个[英文或数字_!~*\'()-]加上.
|
|
|
+ +
|
|
|
+ '\\w+\\.' // 一级域名 -英文或数字 加上.
|
|
|
+ +
|
|
|
+ '[a-zA-Z]{1,6})' // 顶级域名- 1-6位英文
|
|
|
+ +
|
|
|
+ '(:[0-9]{1,5})?' // 端口- :80 ,1-5位数字
|
|
|
+ +
|
|
|
+ '((/?)|' // url无参数结尾 - 斜杆或这没有
|
|
|
+ +
|
|
|
+ '(/[\\w_!~*\'()\\.;?:@&=+$,%#-]+)+/?)$'; //请求参数结尾- 英文或数字和[]内的各种字符
|
|
|
+ const re = new RegExp(strRegex, 'i'); // 大小写不敏感
|
|
|
+ if (re.test(encodeURI(url))) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
},
|
|
|
|
|
|
- // 数据结构转换工具
|
|
|
- jsonTransform(obj) {
|
|
|
- let arr = []
|
|
|
- if (obj.datas.length) {
|
|
|
- let item = {}
|
|
|
- let attrLength = obj.keys.length
|
|
|
- for (let i = 0; i < obj.datas.length; i++) {
|
|
|
- for (let j = 0; j < attrLength; j++) {
|
|
|
- item[obj.keys[j]] = obj.datas[i][j]
|
|
|
- }
|
|
|
- arr.push(item)
|
|
|
- item = {}
|
|
|
- }
|
|
|
- }
|
|
|
- return arr || null
|
|
|
- },
|
|
|
+ // 数据结构转换工具
|
|
|
+ jsonTransform(obj) {
|
|
|
+ let arr = []
|
|
|
+ if (obj.datas.length) {
|
|
|
+ let item = {}
|
|
|
+ let attrLength = obj.keys.length
|
|
|
+ for (let i = 0; i < obj.datas.length; i++) {
|
|
|
+ for (let j = 0; j < attrLength; j++) {
|
|
|
+ item[obj.keys[j]] = obj.datas[i][j]
|
|
|
+ }
|
|
|
+ arr.push(item)
|
|
|
+ item = {}
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return arr || null
|
|
|
+ },
|
|
|
|
|
|
- /**
|
|
|
- *对Date的扩展,将 Date 转化为指定格式的String
|
|
|
- *月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符,
|
|
|
- *年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
|
|
|
- *例子:
|
|
|
- *(new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
|
|
|
- *(new Date()).Format("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18
|
|
|
- */
|
|
|
- formatTime (timestamp, fmt = 'yyyy-MM-dd hh:mm:ss') {
|
|
|
- let d = new Date()
|
|
|
- d.setTime(timestamp)
|
|
|
- var o = {
|
|
|
- 'M+': d.getMonth() + 1, //月份
|
|
|
- 'd+': d.getDate(), //日
|
|
|
- 'h+': d.getHours(), //小时
|
|
|
- 'm+': d.getMinutes(), //分
|
|
|
- 's+': d.getSeconds(), //秒
|
|
|
- 'q+': Math.floor((d.getMonth() + 3) / 3), //季度
|
|
|
- 'S': d.getMilliseconds() //毫秒
|
|
|
- }
|
|
|
- if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (d.getFullYear() + '').substr(4 - RegExp.$1.length))
|
|
|
- for (var k in o)
|
|
|
- if (new RegExp('(' + k + ')').test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
|
|
|
- return fmt
|
|
|
- },
|
|
|
+ /**
|
|
|
+ *对Date的扩展,将 Date 转化为指定格式的String
|
|
|
+ *月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符,
|
|
|
+ *年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字)
|
|
|
+ *例子:
|
|
|
+ *(new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423
|
|
|
+ *(new Date()).Format("yyyy-M-d h:m:s.S") ==> 2006-7-2 8:9:4.18
|
|
|
+ */
|
|
|
+ formatTime(timestamp, fmt = 'yyyy-MM-dd hh:mm:ss') {
|
|
|
+ let d = new Date()
|
|
|
+ d.setTime(timestamp)
|
|
|
+ var o = {
|
|
|
+ 'M+': d.getMonth() + 1, //月份
|
|
|
+ 'd+': d.getDate(), //日
|
|
|
+ 'h+': d.getHours(), //小时
|
|
|
+ 'm+': d.getMinutes(), //分
|
|
|
+ 's+': d.getSeconds(), //秒
|
|
|
+ 'q+': Math.floor((d.getMonth() + 3) / 3), //季度
|
|
|
+ 'S': d.getMilliseconds() //毫秒
|
|
|
+ }
|
|
|
+ if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (d.getFullYear() + '').substr(4 - RegExp.$1.length))
|
|
|
+ for (var k in o)
|
|
|
+ if (new RegExp('(' + k + ')').test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (('00' + o[
|
|
|
+ k]).substr(('' + o[k]).length)))
|
|
|
+ return fmt
|
|
|
+ },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 字节格式转换
|
|
|
+ * @param {any} bytes
|
|
|
+ */
|
|
|
+ bytesToSize(bytes) {
|
|
|
+ if (bytes === 0) return '0 B';
|
|
|
+ let k = 1024,
|
|
|
+ sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
|
|
|
+ i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
|
+ return (bytes / Math.pow(k, i)).toFixed(2) + ' ' + sizes[i];
|
|
|
+ },
|
|
|
|
|
|
- /**
|
|
|
- * 字节格式转换
|
|
|
- * @param {any} bytes
|
|
|
- */
|
|
|
- bytesToSize(bytes) {
|
|
|
- if (bytes === 0) return '0 B';
|
|
|
- let k = 1024,
|
|
|
- sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'],
|
|
|
- i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
|
- return (bytes / Math.pow(k, i)).toFixed(2) + ' ' + sizes[i];
|
|
|
- },
|
|
|
-
|
|
|
/* 采用原生Xhr来发送HTTP请求 避免携带token访问blob报错 */
|
|
|
getFile(url) {
|
|
|
- return new Promise((resolve, reject) => {
|
|
|
- var xhr = new XMLHttpRequest();
|
|
|
- var formData = new FormData();
|
|
|
- xhr.open('get', url); //url填写后台的接口地址,如果是post,在formData append参数(参考原文地址)
|
|
|
- // xhr.responseType = 'arraybuffer';
|
|
|
- xhr.onload = function (e) {
|
|
|
- resolve(e.currentTarget.response)
|
|
|
- };
|
|
|
- xhr.send(formData);
|
|
|
- })
|
|
|
- },
|
|
|
+ return new Promise((resolve, reject) => {
|
|
|
+ var xhr = new XMLHttpRequest();
|
|
|
+ var formData = new FormData();
|
|
|
+ xhr.open('get', url); //url填写后台的接口地址,如果是post,在formData append参数(参考原文地址)
|
|
|
+ // xhr.responseType = 'arraybuffer';
|
|
|
+ xhr.onload = function(e) {
|
|
|
+ resolve(e.currentTarget.response)
|
|
|
+ };
|
|
|
+ xhr.send(formData);
|
|
|
+ })
|
|
|
+ },
|
|
|
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取blob授权
|
|
|
- * @param {type,data} param
|
|
|
- * type:'file/blobR/blobRW',
|
|
|
- * data: 对应的API参数
|
|
|
- */
|
|
|
- getSas(param) {
|
|
|
- return new Promise((r, j) => {
|
|
|
- switch (param.type) {
|
|
|
- case 'file'://单文件授权
|
|
|
- if (!store.state.fileSas || checkSas(store.state.fileSas.timeout)) {
|
|
|
- $api.uploadFile.urlSasR({
|
|
|
- params: param.data
|
|
|
- }).then(
|
|
|
- (res) => {
|
|
|
- if (res.error == null) {
|
|
|
- r(res.result.data)
|
|
|
- } else {
|
|
|
- j(500)
|
|
|
- }
|
|
|
- },
|
|
|
- (err) => {
|
|
|
- j(500)
|
|
|
- }
|
|
|
- )
|
|
|
- } else {
|
|
|
- r(store.state.fileSas)
|
|
|
- }
|
|
|
- break
|
|
|
- case 'blobR'://容器只读权限
|
|
|
- if (!store.state.blobR || checkSas(store.state.blobR.timeout)) {
|
|
|
- $api.uploadFile.blobSasR(param.data).then(
|
|
|
- (res) => {
|
|
|
- if (res.error == null) {
|
|
|
- //store.commit('setBlobR')
|
|
|
- r(res.result.data)
|
|
|
- } else {
|
|
|
- j(500)
|
|
|
- }
|
|
|
- },
|
|
|
- (err) => {
|
|
|
- j(500)
|
|
|
- }
|
|
|
- )
|
|
|
- } else {
|
|
|
- r(store.state.blobR)
|
|
|
- }
|
|
|
- break
|
|
|
- case 'blobRW':
|
|
|
- if (!store.state.blobRW || checkSas(store.state.blobRW.timeout)) {
|
|
|
- $api.uploadFile.blobSasRCW(param.data).then(
|
|
|
- (res) => {
|
|
|
- if (res.error == null) {
|
|
|
- store.commit('setBlobRW', res.result.data)
|
|
|
- r(res.result.data)
|
|
|
- } else {
|
|
|
- j(500)
|
|
|
- }
|
|
|
- },
|
|
|
- (err) => {
|
|
|
- j(500)
|
|
|
- }
|
|
|
- )
|
|
|
- } else {
|
|
|
- r(store.state.blobRW)
|
|
|
- }
|
|
|
- break
|
|
|
- default:
|
|
|
- j('getSas() 参数错误:type')
|
|
|
- }
|
|
|
- })
|
|
|
- },
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取blob授权
|
|
|
+ * @param {type,data} param
|
|
|
+ * type:'file/blobR/blobRW',
|
|
|
+ * data: 对应的API参数
|
|
|
+ */
|
|
|
+ getSas(param) {
|
|
|
+ return new Promise((r, j) => {
|
|
|
+ switch (param.type) {
|
|
|
+ case 'file': //单文件授权
|
|
|
+ if (!store.state.fileSas || checkSas(store.state.fileSas.timeout)) {
|
|
|
+ $api.uploadFile.urlSasR({
|
|
|
+ params: param.data
|
|
|
+ }).then(
|
|
|
+ (res) => {
|
|
|
+ if (res.error == null) {
|
|
|
+ r(res.result.data)
|
|
|
+ } else {
|
|
|
+ j(500)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ (err) => {
|
|
|
+ j(500)
|
|
|
+ }
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ r(store.state.fileSas)
|
|
|
+ }
|
|
|
+ break
|
|
|
+ case 'blobR': //容器只读权限
|
|
|
+ if (!store.state.blobR || checkSas(store.state.blobR.timeout)) {
|
|
|
+ $api.uploadFile.blobSasR(param.data).then(
|
|
|
+ (res) => {
|
|
|
+ if (res.error == null) {
|
|
|
+ //store.commit('setBlobR')
|
|
|
+ r(res.result.data)
|
|
|
+ } else {
|
|
|
+ j(500)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ (err) => {
|
|
|
+ j(500)
|
|
|
+ }
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ r(store.state.blobR)
|
|
|
+ }
|
|
|
+ break
|
|
|
+ case 'blobRW':
|
|
|
+ if (!store.state.blobRW || checkSas(store.state.blobRW.timeout)) {
|
|
|
+ $api.uploadFile.blobSasRCW(param.data).then(
|
|
|
+ (res) => {
|
|
|
+ if (res.error == null) {
|
|
|
+ store.commit('setBlobRW', res.result.data)
|
|
|
+ r(res.result.data)
|
|
|
+ } else {
|
|
|
+ j(500)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ (err) => {
|
|
|
+ j(500)
|
|
|
+ }
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ r(store.state.blobRW)
|
|
|
+ }
|
|
|
+ break
|
|
|
+ default:
|
|
|
+ j('getSas() 参数错误:type')
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
|
|
|
|
|
|
- /**
|
|
|
- * 获取个人容器授权
|
|
|
- */
|
|
|
- getPrivateSas() {
|
|
|
- return new Promise((r, j) => {
|
|
|
- if (!store.state.privateSas || checkSas(store.state.privateSas.timeout)) {
|
|
|
- $api.uploadFile.blobSasRCW({
|
|
|
- name: store.state.userInfo.TEAMModelId,
|
|
|
- role: 'teacher'
|
|
|
- }).then(
|
|
|
- (res) => {
|
|
|
- if (res.error == null) {
|
|
|
- store.commit('setPrivateSas', res.result.data)
|
|
|
- res.result.data.sas = '?' + res.result.data.sas
|
|
|
- r(res.result.data)
|
|
|
- } else {
|
|
|
- j(500)
|
|
|
- }
|
|
|
- },
|
|
|
- (err) => {
|
|
|
- j(500)
|
|
|
- }
|
|
|
- )
|
|
|
- } else {
|
|
|
- console.log(store)
|
|
|
- r(store.state.privateSas)
|
|
|
- }
|
|
|
- })
|
|
|
- },
|
|
|
- /**
|
|
|
- * 获取学校容器授权
|
|
|
- */
|
|
|
- getSchoolSas() {
|
|
|
- return new Promise((r, j) => {
|
|
|
- if (!store.state.schoolSas || checkSas(store.state.schoolSas.timeout)) {
|
|
|
- $api.uploadFile.blobSasRCW({
|
|
|
- name: store.state.userInfo.schoolCode,
|
|
|
- role: 'school'
|
|
|
- }).then(
|
|
|
- (res) => {
|
|
|
- if (res.error == null) {
|
|
|
- store.commit('setSchoolSas', res.result.data)
|
|
|
- res.result.data.sas = '?' + res.result.data.sas
|
|
|
- r(res.result.data)
|
|
|
- } else {
|
|
|
- j(500)
|
|
|
- }
|
|
|
- },
|
|
|
- (err) => {
|
|
|
- j(500)
|
|
|
- }
|
|
|
- )
|
|
|
- } else {
|
|
|
- r(store.state.schoolSas)
|
|
|
- }
|
|
|
- })
|
|
|
- },
|
|
|
- /**
|
|
|
- * 获取单个文件授权
|
|
|
- */
|
|
|
- getFileSas(param) {
|
|
|
- return new Promise((r, j) => {
|
|
|
- $api.uploadFile.urlSasR(
|
|
|
- {
|
|
|
- params: param
|
|
|
- }
|
|
|
- ).then(
|
|
|
- (res) => {
|
|
|
- if (res.error == null) {
|
|
|
- //store.commit('setBlobRW', res.result.data)
|
|
|
- r(res.result.data)
|
|
|
- } else {
|
|
|
- j(500)
|
|
|
- }
|
|
|
- },
|
|
|
- (err) => {
|
|
|
- j(500)
|
|
|
- }
|
|
|
- )
|
|
|
- })
|
|
|
- },
|
|
|
-
|
|
|
+ /**
|
|
|
+ * 获取个人容器授权
|
|
|
+ */
|
|
|
+ getPrivateSas() {
|
|
|
+ return new Promise((r, j) => {
|
|
|
+ if (!store.state.privateSas || checkSas(store.state.privateSas.timeout)) {
|
|
|
+ $api.uploadFile.blobSasRCW({
|
|
|
+ name: store.state.userInfo.TEAMModelId,
|
|
|
+ role: 'teacher'
|
|
|
+ }).then(
|
|
|
+ (res) => {
|
|
|
+ if (res.error == null) {
|
|
|
+ store.commit('setPrivateSas', res.result.data)
|
|
|
+ res.result.data.sas = '?' + res.result.data.sas
|
|
|
+ r(res.result.data)
|
|
|
+ } else {
|
|
|
+ j(500)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ (err) => {
|
|
|
+ j(500)
|
|
|
+ }
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ console.log(store)
|
|
|
+ r(store.state.privateSas)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 获取学校容器授权
|
|
|
+ */
|
|
|
+ getSchoolSas() {
|
|
|
+ return new Promise((r, j) => {
|
|
|
+ if (!store.state.schoolSas || checkSas(store.state.schoolSas.timeout)) {
|
|
|
+ $api.uploadFile.blobSasRCW({
|
|
|
+ name: store.state.userInfo.schoolCode,
|
|
|
+ role: 'school'
|
|
|
+ }).then(
|
|
|
+ (res) => {
|
|
|
+ if (res.error == null) {
|
|
|
+ store.commit('setSchoolSas', res.result.data)
|
|
|
+ res.result.data.sas = '?' + res.result.data.sas
|
|
|
+ r(res.result.data)
|
|
|
+ } else {
|
|
|
+ j(500)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ (err) => {
|
|
|
+ j(500)
|
|
|
+ }
|
|
|
+ )
|
|
|
+ } else {
|
|
|
+ r(store.state.schoolSas)
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+ /**
|
|
|
+ * 获取单个文件授权
|
|
|
+ */
|
|
|
+ getFileSas(param) {
|
|
|
+ return new Promise((r, j) => {
|
|
|
+ $api.uploadFile.urlSasR({
|
|
|
+ params: param
|
|
|
+ }).then(
|
|
|
+ (res) => {
|
|
|
+ if (res.error == null) {
|
|
|
+ //store.commit('setBlobRW', res.result.data)
|
|
|
+ r(res.result.data)
|
|
|
+ } else {
|
|
|
+ j(500)
|
|
|
+ }
|
|
|
+ },
|
|
|
+ (err) => {
|
|
|
+ j(500)
|
|
|
+ }
|
|
|
+ )
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
/* 获取视频第一帧 */
|
|
|
getVideoBase64(url) {
|
|
|
return new Promise(function(resolve, reject) {
|
|
@@ -430,7 +440,7 @@ export default {
|
|
|
var img = new Image()
|
|
|
img.src = require('@/assets/icon/icon_play.png')
|
|
|
img.setAttribute('crossOrigin', 'anonymous');
|
|
|
- img.onload = function () {
|
|
|
+ img.onload = function() {
|
|
|
//画图
|
|
|
canvas.getContext("2d").drawImage(img, 55, 25, 40, 40);
|
|
|
var data = canvas.toDataURL('image/jpeg');
|
|
@@ -440,12 +450,14 @@ export default {
|
|
|
});
|
|
|
})
|
|
|
},
|
|
|
-
|
|
|
+
|
|
|
/* 上传视频到BLob */
|
|
|
- async doUploadVideo(vm,file,editor){
|
|
|
+ async doUploadVideo(vm, file, editor) {
|
|
|
vm.$Spin.show({
|
|
|
render: (h) => {
|
|
|
- return h('div', [
|
|
|
+ return h('div', {
|
|
|
+ 'class': 'my-spin',
|
|
|
+ }, [
|
|
|
h('Icon', {
|
|
|
'class': 'demo-spin-icon-load',
|
|
|
props: {
|
|
@@ -474,48 +486,48 @@ export default {
|
|
|
posterBase64 + ' class="richText-video"></img>')
|
|
|
editor.change()
|
|
|
vm.$Spin.hide();
|
|
|
- },
|
|
|
- isEqual: function( x, y ) {
|
|
|
- // If both x and y are null or undefined and exactly the same
|
|
|
- if ( x === y ) {
|
|
|
- return true;
|
|
|
- }
|
|
|
- // If they are not strictly equal, they both need to be Objects
|
|
|
- if ( ! ( x instanceof Object ) || ! ( y instanceof Object ) ) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- //They must have the exact same prototype chain,the closest we can do is
|
|
|
- //test the constructor.
|
|
|
- if ( x.constructor !== y.constructor ) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- for ( var p in x ) {
|
|
|
- //Inherited properties were tested using x.constructor === y.constructor
|
|
|
- if ( x.hasOwnProperty( p ) ) {
|
|
|
- // Allows comparing x[ p ] and y[ p ] when set to undefined
|
|
|
- if ( ! y.hasOwnProperty( p ) ) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- // If they have the same strict value or identity then they are equal
|
|
|
- if ( x[ p ] === y[ p ] ) {
|
|
|
- continue;
|
|
|
- }
|
|
|
- // Numbers, Strings, Functions, Booleans must be strictly equal
|
|
|
- if ( typeof( x[ p ] ) !== "object" ) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- // Objects and Arrays must be tested recursively
|
|
|
- if ( ! Object.equals( x[ p ], y[ p ] ) ) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- for ( p in y ) {
|
|
|
- // allows x[ p ] to be set to undefined
|
|
|
- if ( y.hasOwnProperty( p ) && ! x.hasOwnProperty( p ) ) {
|
|
|
- return false;
|
|
|
- }
|
|
|
- }
|
|
|
- return true;
|
|
|
- }
|
|
|
+ },
|
|
|
+ isEqual: function(x, y) {
|
|
|
+ // If both x and y are null or undefined and exactly the same
|
|
|
+ if (x === y) {
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ // If they are not strictly equal, they both need to be Objects
|
|
|
+ if (!(x instanceof Object) || !(y instanceof Object)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ //They must have the exact same prototype chain,the closest we can do is
|
|
|
+ //test the constructor.
|
|
|
+ if (x.constructor !== y.constructor) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ for (var p in x) {
|
|
|
+ //Inherited properties were tested using x.constructor === y.constructor
|
|
|
+ if (x.hasOwnProperty(p)) {
|
|
|
+ // Allows comparing x[ p ] and y[ p ] when set to undefined
|
|
|
+ if (!y.hasOwnProperty(p)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // If they have the same strict value or identity then they are equal
|
|
|
+ if (x[p] === y[p]) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ // Numbers, Strings, Functions, Booleans must be strictly equal
|
|
|
+ if (typeof(x[p]) !== "object") {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // Objects and Arrays must be tested recursively
|
|
|
+ if (!Object.equals(x[p], y[p])) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ for (p in y) {
|
|
|
+ // allows x[ p ] to be set to undefined
|
|
|
+ if (y.hasOwnProperty(p) && !x.hasOwnProperty(p)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
}
|