123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506 |
- import $api from '@/api'
- import store from '@/store'
- import SparkMD5 from "spark-md5";
- import FileSaver from "file-saver";
- import JSZip from "jszip";
- import QRCode from 'qrcodejs2'
- import JsPDF from 'jspdf'
- import 'jspdf-autotable'
- import domtoimage from '@/utils/dom_to_image';
- import excel from '@/utils/excel.js'
- import {
- app
- } from '@/boot-app.js'
- import {
- Message
- } from 'view-design'
- /**
- * 校验blob授权是否过期
- * */
- function checkSas(sasTs) {
- 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(197, 197, 197)',
- /** 滚动条透明度, 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', // 插入链接
- 'video', //插入视频
- 'justify', // 对齐方式
- 'image', // 插入图片
- 'table', // 表格
- 'undo', // 撤销
- ],
- /* 简易版菜单 */
- wangEditorMenuSimple: [
- 'head', // 标题
- 'bold', // 粗体
- 'fontSize', // 字号
- 'fontName', // 字体
- 'italic', // 斜体
- 'underline', // 下划线
- 'strikeThrough', // 删除线
- 'foreColor', // 文字颜色
- 'justify', // 对齐方式
- 'table', // 表格
- ],
- /* 全屏 */
- fullScreen(element) {
- // var element = document.documentElement;
- if (element.requestFullscreen) {
- element.requestFullscreen();
- } else if (element.msRequestFullscreen) {
- element.msRequestFullscreen();
- } else if (element.mozRequestFullScreen) {
- element.mozRequestFullScreen();
- } else if (element.webkitRequestFullscreen) {
- element.webkitRequestFullscreen();
- }
- },
- /* 退出全屏 */
- exitFullscreen() {
- if (document.exitFullscreen) {
- document.exitFullscreen();
- } else if (document.msExitFullscreen) {
- document.msExitFullscreen();
- } else if (document.mozCancelFullScreen) {
- document.mozCancelFullScreen();
- } else if (document.webkitExitFullscreen) {
- document.webkitExitFullscreen();
- }
- },
- getFileThum(type, fileName) {
- const docType = ['doc', 'docx']
- const excelType = ['xls', 'csv', 'xlsx']
- const pptType = ['ppt', 'pptx']
- let thumPath = ''
- if (type === 'doc' && docType.includes(this.getSuffix(fileName))) {
- thumPath = require('@/assets/source/word.png')
- } else if (type === 'doc' && excelType.includes(this.getSuffix(fileName))) {
- thumPath = require('@/assets/source/excel.png')
- } else if (type === 'doc' && pptType.includes(this.getSuffix(fileName))) {
- thumPath = require('@/assets/source/ppt.png')
- } else if (type === 'image') {
- thumPath = require('@/assets/source/image.png')
- } else if (type === 'video') {
- thumPath = require('@/assets/source/video.png')
- } else if (type === 'audio') {
- thumPath = require('@/assets/source/audio.png')
- } else if (type === 'link') {
- thumPath = require('@/assets/source/link.png')
- } else if (type === 'res') {
- thumPath = require('@/assets/source/zip.png')
- } else if (type === 'thum') {
- thumPath = require('@/assets/source/image.png')
- } else {
- thumPath = require('@/assets/source/link.png')
- }
- return thumPath
- },
- /* 获取文件后缀名 */
- getSuffix(name) {
- return name.substr(name.lastIndexOf(".") + 1)
- },
- /* 导出表格 */
- exportTable(params) {
- excel.export_array_to_excel(params)
- },
- /* 检查音视频格式是否符合格式要求 */
- checkMediaFile(file) {
- return new Promise((r, j) => {
- const getSize = () => file.size
- const readChunk = (chunkSize, offset) =>
- new Promise((resolve, reject) => {
- const reader = new FileReader()
- reader.onload = (event) => {
- if (event.target.error) {
- reject(event.target.error)
- }
- resolve(new Uint8Array(event.target.result))
- }
- reader.readAsArrayBuffer(file.slice(offset, offset + chunkSize))
- })
- window.MediaInfo().then((media) => {
- media.analyzeData(getSize, readChunk).then((result) => {
- console.log(result)
- if (result['media']) {
- let tracks = result['media']['track']
- // 判断是否是视频
- let videoTrack = tracks.find(track => track['@type'] === 'Video')
- let audioTrack = tracks.find(track => track['@type'] === 'Audio')
- // 如果视频文件满足MP4(H264+AAC),WAV('vp8','vp9') 则代表是可以正常播放的视频文件,返回视频的编码级别
- if (videoTrack && audioTrack) {
- let videoFormat = videoTrack.Format.toLowerCase()
- let audioFormat = audioTrack.Format.toLowerCase()
- if((videoFormat === 'avc' && audioFormat === 'aac') || (['vp8','vp9'].includes(videoFormat) && audioFormat === 'vorbis')) {
- r(videoTrack.Format_Profile || true)
- }else{
- r(false)
- }
- }
- // 如果是音频文件则需要满足 mp3(MPEG Audio),ogg(Vorbis),wav(PCM) 任意一种编码格式
- else if (!videoTrack && audioTrack && ['mpeg audio','vorbis','pcm'].includes(audioTrack.Format.toLowerCase())) {
- r(true)
- } else {
- r(false)
- }
- } else {
- r(false)
- }
- }).catch((error) => {
- j(error)
- })
- }).catch((error) => {
- j(error)
- })
- })
- },
- /* 根据最新服务器时间获取当前所在学期的起止时间戳 */
- getSemesterTimeRange() {
- let curServerTime = localStorage.getItem('serverTime') // 服务器时间
- let curPeriod = store.state.user.curPeriod
- // 如果没有记录到服务器时间或者学期数据,则默认查全部
- if (!curServerTime || !curPeriod || !curPeriod.semesterCount) {
- return {
- st: 0,
- et: 0
- }
- } else {
- let settingSemesters = curPeriod.semesters // 基础设置的学期数据
- let settingRange = this.getSettingTermRange(settingSemesters) // 获取设置学期对应的月和日
- let serverTimeArr = this.formatTime(curServerTime, 'MM-dd').split('-') // 获取当前服务器时间的月和日
- let curSemeterIndex = settingSemesters.length > 1 ? this.getCurSemesterIndex(settingSemesters, settingRange,
- serverTimeArr) : 0 // 获取当前学期的序号
- let curYear = new Date(Number(curServerTime)).getFullYear() // 获取服务器时间的年份
- let curMonth = new Date(Number(curServerTime)).getMonth() + 1 // 获取服务器时间的月份
- let startMonth = settingSemesters[curSemeterIndex].month // 当前所在学期的开始月
- let startDay = settingSemesters[curSemeterIndex].day // 当前所在学期的开始日
- let endMonth = settingSemesters[curSemeterIndex === settingSemesters.length - 1 ? 0 : (curSemeterIndex + 1)]
- .month
- let endDay = settingSemesters[curSemeterIndex === settingSemesters.length - 1 ? 0 : (curSemeterIndex + 1)]
- .day
- let startTime = ''
- let endTime = ''
- // 如果当前学校只设置了一个学期
- if (settingSemesters.length === 1) {
- startMonth = settingSemesters[0].month
- startDay = settingSemesters[0].day
- startTime = new Date(
- `${curYear}-${startMonth > 9 ? startMonth : '0' + startMonth}-${startDay > 9 ? startDay : '0' + startDay} 00:00:00`
- ).getTime()
- endTime = new Date(
- `${curYear + 1}-${startMonth > 9 ? startMonth : '0' + startMonth}-${startDay > 9 ? startDay : '0' + startDay} 00:00:00`
- ).getTime()
- } else {
- // 如果当前月份小于开始月份 则代表开始时间是在去年
- if (curMonth >= startMonth && curMonth <= 12) {
- startTime = new Date(
- `${curYear}-${startMonth > 9 ? startMonth : '0' + startMonth}-${startDay > 9 ? startDay : '0' + startDay} 00:00:00`
- ).getTime()
- } else {
- startTime = new Date(
- `${curYear - 1}-${startMonth > 9 ? startMonth : '0' + startMonth}-${startDay > 9 ? startDay : '0' + startDay} 00:00:00`
- ).getTime()
- }
- // 如果当前月份比结束月份大 则代表是明年结束 Year要加1
- if (curMonth > endMonth) {
- endTime = new Date(
- `${curYear + 1}-${endMonth > 9 ? endMonth : '0' + endMonth}-${endDay > 9 ? endDay : '0' + endDay} 00:00:00`
- ).getTime()
- } else {
- endTime = new Date(
- `${curYear}-${endMonth > 9 ? endMonth : '0' + endMonth}-${endDay > 9 ? endDay : '0' + endDay} 00:00:00`
- ).getTime()
- }
- }
- return {
- st: startTime,
- et: endTime,
- name: settingSemesters[curSemeterIndex].name
- }
- }
- },
- /* 获取当前学段学期时间范围 */
- getSettingTermRange(semesters) {
- let range = []
- for (var i = 0; i < semesters.length; i++) {
- range.push([
- this.tranNum([+semesters[i].month, +semesters[i].day]),
- i === semesters.length - 1 ? this.tranNum([+semesters[0].month, +semesters[0].day]) : this
- .tranNum([+semesters[i + 1].month, +semesters[i + 1].day])
- ])
- }
- return range
- },
- /* 对比评测时间和学期分界点时间 */
- getCurSemesterIndex(semesters, range, val) {
- console.log(...arguments);
- let rangeArr = []
- let s = this.tranNum(val)
- for (let i = 0; i < range.length; i++) {
- let item = range[i]
- if (item[0] === s) {
- return i
- } else {
- // 代表跨年了
- if (item[0] > item[1]) {
- rangeArr = [...this.getNumsArr([item[0], 1231]), ...this.getNumsArr([0, item[1]])]
- } else {
- rangeArr = this.getNumsArr(item)
- }
- if (rangeArr.includes(s)) {
- return i
- }
- }
- }
- },
- /* 获取范围内数字数组 */
- getNumsArr(range) {
- let diff = range[1] - range[0]
- let arr = []
- for (let i = 0; i < diff; i++) {
- arr.push(range[0] + i)
- }
- return arr
- },
- /* 数字转换 */
- tranNum(val) {
- let month = +val[0]
- let day = +val[1]
- return Number(month + '' + (day > 9 ? day : ('0' + day)))
- },
- /* 数字与中文转换 */
- getChineseByNum(num) {
- num = Number(num)
- var upperCaseNumber = [
- app.$t('learnActivity.score.zero'),
- app.$t('learnActivity.score.one'),
- app.$t('learnActivity.score.two'),
- app.$t('learnActivity.score.three'),
- app.$t('learnActivity.score.four'),
- app.$t('learnActivity.score.five'),
- app.$t('learnActivity.score.six'),
- app.$t('learnActivity.score.seven'),
- app.$t('learnActivity.score.eight'),
- app.$t('learnActivity.score.nine'),
- app.$t('learnActivity.score.ten'),
- app.$t('learnActivity.score.hundred'),
- app.$t('learnActivity.score.thousand'),
- app.$t('learnActivity.score.tenThd'),
- app.$t('learnActivity.score.hMillion')
- ]
- var length = String(num).length
- if (length === 1) {
- return upperCaseNumber[num]
- } else if (length === 2) {
- if (num === 10) {
- return upperCaseNumber[num]
- } else if (num > 10 && num < 20) {
- return app.$t('learnActivity.score.ten') + upperCaseNumber[String(num).charAt(1)]
- } else {
- return upperCaseNumber[String(num).charAt(0)] + app.$t('learnActivity.score.ten') + upperCaseNumber[
- String(num).charAt(1)].replace(app.$t('learnActivity.score.zero'), '')
- }
- }
- },
- /* 生成随机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())
- },
- /* 生成从minNum到maxNum的随机数 */
- randomNum(minNum, maxNum) {
- switch (arguments.length) {
- case 1:
- return parseInt(Math.random() * minNum + 1, 10);
- break;
- case 2:
- return parseInt(Math.random() * (maxNum - minNum + 1) + minNum, 10);
- break;
- default:
- return 0;
- break;
- }
- },
- /* 获取mm与px的转换 */
- getOneMmsPx() {
- // 创建一个1mm宽的元素插入到页面,然后坐等出结果
- let div = document.createElement("div");
- div.id = "mm";
- div.style.width = "1mm";
- document.querySelector("body").appendChild(div);
- // 原生方法获取浏览器对元素的计算值
- let mm1 = document.getElementById("mm").getBoundingClientRect();
- console.log(mm1);
- return mm1.width;
- },
- // 根据总分和数量求平均结果
- doAverage(total, count, step) {
- let oneMaxScore = (Math.floor((total / (count * step))) * step);
- let maxIndex = Math.floor((total - oneMaxScore * count) / step);
- let tempArr = new Array(count).fill(oneMaxScore).map((item, index) => index < maxIndex ? (item + step) : item);
- return tempArr
- },
- /* 根据x,y,w,h获取四点坐标 */
- getBoxPos(x, y, w, h) {
- return [{
- x: x,
- y: y
- },
- {
- x: x + w,
- y: y
- },
- {
- x: x + w,
- y: y + h
- },
- {
- x: x,
- y: y + h
- }
- ]
- },
- /* 匹配URL里面的HOST */
- matchHost(url) {
- var pattern = /[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?/
- return 'https://' + url.match(pattern)[0]
- },
- /* 正则判断是否为标准的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;
- },
- /* 数据结构转换工具 */
- jsonTransform(obj) {
- let arr = []
- console.log(obj)
- 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
- },
- /* 时间格式化 */
- 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
- },
- /* 字节格式转换 */
- 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, type) {
- return new Promise((resolve, reject) => {
- var xhr = new XMLHttpRequest();
- var formData = new FormData();
- xhr.open('get', url); //url填写后台的接口地址,如果是post,在formData append参数(参考原文地址)
- if (type) xhr.responseType = 'arraybuffer';
- xhr.onload = function (e) {
- switch (e.currentTarget.status) {
- case 200:
- resolve(e.currentTarget.response)
- break;
- case 404:
- // Message.error('有资源丢失')
- reject(404)
- break;
- case 403:
- Message.error(app.$t('http.error403'))
- reject(403)
- break;
- default:
- break;
- }
- };
- xhr.send(formData);
- })
- },
- /* 获取授权码 */
- getSas(param) {
- return new Promise((r, j) => {
- switch (param.type) {
- case 'file': //单文件授权
- if (!store.state.fileSas || checkSas(store.state.fileSas.timeout)) {
- $api.blob.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.blob.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.blob.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')
- }
- })
- },
- /* 根据登录后的用户信息获取blobHOST域名 */
- getBlobHost() {
- let s = store.state.user.userProfile.blob_uri || store.state.user.studentProfile.blob_uri
- let pattern = /[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+\.?/
- return s.split('//')[0] + '//' + s.match(pattern)[0]
- },
- /* 获取个人容器授权 */
- getPrivateSas(code) {
- return new Promise((r, j) => {
- let ts = new Date().getTime()
- if (!store.state.user.userProfile.blob_sas) {
- $api.blob.blobSasRCW({
- name: store.state.userInfo.TEAMModelId,
- role: 'teacher'
- }).then(
- (res) => {
- if (res.error == null) {
- res.sas = '?' + res.sas
- r(res)
- } else {
- j(500)
- }
- },
- (err) => {
- j(500)
- }
- )
- } else {
- r({
- sas: '?' + store.state.user.userProfile.blob_sas + '×tamp=' + ts,
- name: code || store.state.userInfo.TEAMModelId,
- url: this.getBlobHost()
- })
- }
- })
- },
- /* 获取学校容器授权 */
- getSchoolSas(code) {
- return new Promise((r, j) => {
- let ts = new Date().getTime()
- if (!store.state.user.schoolProfile.blob_sas) {
- $api.blob.blobSasRCW({
- name: code || store.state.userInfo.schoolCode,
- role: 'school'
- }).then(
- (res) => {
- if (res.error == null) {
- res.sas = '?' + res.sas
- r(res)
- } else {
- j(500)
- }
- },
- (err) => {
- j(500)
- }
- )
- } else {
- r({
- sas: '?' + store.state.user.schoolProfile.blob_sas + '×tamp=' + ts,
- name: code || store.state.userInfo.schoolCode,
- url: this.getBlobHost()
- })
- }
- })
- },
- /* 获取单个文件授权 */
- getFileSas(param) {
- console.log('获取单个文件授权', param)
- return new Promise((r, j) => {
- $api.blob.urlSasR({
- url: param
- }).then(
- (res) => {
- if (res.error == null) {
- //store.commit('setBlobRW', res.result.data)
- r(res)
- } else {
- j(500)
- }
- },
- (err) => {
- j(500)
- }
- )
- })
- },
- /* 根据容器名称获取完整授权码 */
- getBlobSas(code) {
- return new Promise((r, j) => {
- $api.blob.blobSasR({
- name: code,
- role: 'teacher'
- }).then(res => {
- if (!res.error) {
- r(res)
- }
- })
- })
- },
- /* 批量生成二维码 */
- batchQrcodes(arr, pdfName) {
- return new Promise((resolve, reject) => {
- if (!arr.length) {
- app.$Message.warning('未获取到学生数据')
- resolve(200)
- return
- }
- let promiseArr = []
- arr.forEach((i, index) => {
- promiseArr.push(new Promise((r, j) => {
- let dom = document.createElement('div')
- let qrcode = new QRCode(dom, {
- width: 320, // 设置宽度,单位像素
- height: 320, // 设置高度,单位像素
- text: arr[index], // 设置二维码内容或跳转地址
- })
- setTimeout(() => {
- let base64 = dom.getElementsByTagName('img')[0].currentSrc
- dom.remove()
- r(base64)
- }, 500)
- }))
- })
- Promise.all(promiseArr).then(result => {
- var PDF = new JsPDF({
- orientation: 'p',
- unit: 'mm',
- format: 'a4',
- putOnlyUsedFonts: true
- })
- PDF.setFontSize(12);
- result.forEach((img, imgIndex) => {
- let whichRow = parseInt((imgIndex % 30) / 5)
- let xArr = [10, 50, 90, 130, 170]
- let yArr = [10, 55, 100, 145, 190, 235]
- let x = xArr[imgIndex % 5]
- let y = yArr[whichRow]
- let xMarginLeft = ((13 - arr[imgIndex].length) / 2) * (30 / 13)
- PDF.addImage(img, 'JPEG', x, y, 30, 30)
- PDF.text(arr[imgIndex], x + xMarginLeft, y + 38);
- if ((imgIndex + 1) % 30 === 0 && imgIndex !== result.length - 1) {
- PDF.addPage()
- }
- })
- PDF.save(app.$t('stuAccount.qrcode') + '(' + pdfName + ').pdf')
- resolve(200)
- })
- })
- },
- /* 生成学生清单PDF */
- batchStuList(datas, pdfName) {
- return new Promise(async (resolve, reject) => {
- try {
- let namesArr = await this.getNamesBase64(datas.map(i => i.name))
- let classNameBase64 = await this.getClassNameBase64(pdfName)
- let pageCount = 1
- let PDF = new JsPDF({
- orientation: 'p',
- unit: 'mm',
- format: 'a4',
- putOnlyUsedFonts: true
- })
- const a4Height = 297
- const a4Width = 210
- // 生成学生清单表格
- PDF.autoTable({
- theme: 'plain',
- styles: {
- valign: 'middle'
- },
- margin: {
- top: 15,
- left: 15,
- },
- headStyles: {
- cellPadding: {
- top: 3,
- bottom: 3,
- left: 5
- },
- valign: 'middle',
- },
- bodyStyles: {
- cellPadding: 5,
- },
- columnStyles: {
- 0: {
- cellWidth: 20,
- valign: 'middle',
- halign: 'center'
- }
- },
- head: [
- ['', 'Name', 'ID', 'IRS', '']
- ],
- body: datas.map(i => ['', '', i.id, i.irs]),
- didDrawPage: (data) => {
- PDF.addImage(classNameBase64, 'JPEG', 15, 5, 200, 10);
- PDF.setFontSize(12);
- PDF.setFont('Times New Roman')
- // PDF.text(`${data.pageNumber} / ${data.doc.internal.pages.length}`, a4Width / 2 - 5, a4Height - 4,'center')
- },
- didDrawCell: (cell) => {
- if (cell.column.dataKey === 0 && cell.section === 'body') {
- let defaultImg = require('@/assets/image/tmd_logo.png')
- let url = datas[cell.row.index].picture || defaultImg
- var img = new Image();
- img.src = url;
- PDF.addImage(img, 'JPEG', cell.cursor.x + 5, cell.cursor.y + 2, 10, 10);
- }
- if (cell.column.dataKey === 1 && cell.section === 'body') {
- let nameBase64 = namesArr[cell.row.index]
- PDF.addImage(nameBase64, 'JPEG', cell.cursor.x + 5, cell.cursor.y + 4, 20, 8);
- }
- if (cell.column.dataKey === 4 && cell.section === 'body') {
- PDF.setDrawColor(0);
- PDF.setLineWidth(0.6);
- PDF.rect(cell.cursor.x + 5, cell.cursor.y + 4, 5, 5);
- }
- }
- })
- PDF.save(pdfName + '.pdf')
- resolve(200)
- } catch (e) {
- reject(500)
- }
- })
- },
- /* 根据图片生成PDF */
- generatePdfByImgs(urls, pdfName) {
- return new Promise(async (resolve, reject) => {
- try {
- const a4Height = 297
- const a4Width = 210
- let PDF = new JsPDF({
- orientation: 'l',
- unit: 'mm',
- format: 'a4',
- putOnlyUsedFonts: true
- })
- urls.forEach((url, index) => {
- var img = new Image();
- img.src = url;
- PDF.addImage(img, 'JPEG', 0, 0, a4Height, a4Width);
- if (index !== urls.length - 1) {
- PDF.addPage()
- }
- })
- PDF.save(pdfName + '.pdf')
- resolve(200)
- } catch (e) {
- reject(500)
- console.log(e)
- }
- })
- },
- /* 生成名字图片 */
- getImgsBase64ByUrls(urls) {
- return new Promise((resolve, reject) => {
- let promiseArr = []
- urls.forEach(url => {
- promiseArr.push(new Promise((r, j) => {
- console.error(url)
- var img = new Image();
- img.src = url
- img.onload = function () {
- var canvas = document.createElement("canvas");
- canvas.width = img.width;
- canvas.height = img.height;
- var ctx = canvas.getContext("2d");
- ctx.drawImage(img, 0, 0, img.width, img.height);
- var dataURL = canvas.toDataURL("image/png");
- r(dataURL)
- }
- }))
- })
- Promise.all(promiseArr).then(result => {
- resolve(result)
- }).catch(e => {
- reject(e)
- })
- })
- },
- /* 生成班级名称图片 */
- getClassNameBase64(name) {
- return new Promise((resolve, reject) => {
- let dom = document.createElement('div')
- dom.style.width = '200mm'
- dom.style.height = '10mm'
- dom.style.fontSize = '20px'
- dom.style.fontWeight = 'bold'
- dom.innerHTML = name
- document.body.appendChild(dom)
- setTimeout(() => {
- domtoimage.toPng(dom).then((pageData) => {
- dom.remove()
- resolve(pageData)
- })
- }, 100)
- })
- },
- /* 生成名字图片 */
- getNamesBase64(arr) {
- return new Promise((resolve, reject) => {
- let promiseArr = []
- arr.forEach(name => {
- promiseArr.push(new Promise((r, j) => {
- let dom = document.createElement('div')
- dom.style.width = '20mm'
- dom.style.height = '8mm'
- dom.style.fontSize = '14px'
- dom.style.fontWeight = 'bold'
- dom.innerHTML = name
- document.body.appendChild(dom)
- setTimeout(() => {
- domtoimage.toPng(dom).then((pageData) => {
- dom.remove()
- r(pageData)
- })
- }, 100)
- }))
- })
- Promise.all(promiseArr).then(result => {
- resolve(result)
- })
- })
- },
- /* 弹窗下载文件操作 */
- doDownloadByUrl(url, fileName) {
- let a = document.createElement('a');
- a.href = url;
- a.download = fileName;
- a.target = '_blank'
- a.click()
- a.remove();
- },
- /* 获取视频第一帧 */
- getVideoBase64(url) {
- return new Promise(function (resolve, reject) {
- let dataURL = '';
- let video = document.createElement("video");
- video.setAttribute('crossOrigin', 'anonymous'); //处理跨域
- video.setAttribute('src', url);
- video.setAttribute('preload', 'auto');
- video.setAttribute('width', 150);
- video.setAttribute('height', 90);
- video.addEventListener('loadeddata', function () {
- let canvas = document.createElement("canvas"),
- width = video.width, //canvas的尺寸和图片一样
- height = video.height;
- canvas.width = width;
- canvas.height = height;
- canvas.getContext("2d").drawImage(video, 0, 0, width, height); //绘制canvas
- dataURL = canvas.toDataURL('image/jpeg'); //转换为base64
- // 画播放按钮
- var img = new Image()
- img.src = require('@/assets/icon/icon_play.png')
- img.setAttribute('crossOrigin', 'anonymous');
- img.onload = function () {
- //画图
- canvas.getContext("2d").drawImage(img, 55, 25, 40, 40);
- var data = canvas.toDataURL('image/jpeg');
- resolve(data);
- }
- });
- })
- },
- /* 获取视频文件的持续时长 */
- getVideoDuration(file, url) {
- return new Promise((resolve, reject) => {
- var vid = document.createElement('video');
- var fileURL = url || URL.createObjectURL(file);
- vid.src = fileURL;
- vid.addEventListener('loadedmetadata', function () {
- resolve(vid.duration);
- });
- vid.remove()
- })
- },
- /* 将文件MD5 Uint8Array格式转换成字符串 */
- convertFileMD5ToString(fileData) {
- var dataString = "";
- for (var i = 0; i < fileData.length; i++) {
- dataString += fileData[i].toString(16);
- }
- return dataString
- },
- /* 将二进制流字符串转换成Uint8Array */
- stringToUint8Array(str) {
- var arr = [];
- for (var i = 0, j = str.length; i < j; ++i) {
- arr.push(str.charCodeAt(i));
- }
- var tmpUint8Array = new Uint8Array(arr);
- return tmpUint8Array
- },
- /* 批量打包下载 */
- async doBatchDownloadZip(urls, zipName) {
- const zip = new JSZip();
- const cache = {};
- const promises = [];
- /* 循环下载所有文件后 加入promise队列 */
- await urls.forEach(item => {
- const promiseItem = this.getFile(item).then(dta => {
- const arr_name = item.split("/"); //处理名称
- var file_name = arr_name[arr_name.length - 1].split('?')[0];
- zip.file(file_name, dta, {
- binary: true
- }); // 逐个添加文件
- cache[file_name] = dta;
- });
- promises.push(promiseItem);
- });
- Promise.all(promises).then(() => {
- zip.generateAsync({
- type: "blob"
- }).then(content => {
- // 生成二进制流
- FileSaver.saveAs(content, zipName + ".zip"); // 利用file-saver保存文件
- })
- .catch(err => {
- console.log(err);
- });
- });
- },
- /* 获取字符串的MD5 */
- getStringMd5(str) {
- let spark = new SparkMD5();
- spark.append(str)
- var md5 = spark.end();
- return md5
- },
- /* 获取文件的MD5 */
- getFileMD5(file) {
- return new Promise((r, j) => {
- console.log(file)
- const CHUNK_SIZE = 4194304; // 大文件获取数前4M大小
- const fileReader = new FileReader();
- const chunkFile = file.slice(0, CHUNK_SIZE);
- fileReader.readAsBinaryString(chunkFile);
- let spark = new SparkMD5();
- console.time('getMd5')
- fileReader.onload = e => {
- spark.appendBinary(e.target.result);
- var md5 = spark.end(true);
- console.log(md5)
- r(this.stringToUint8Array(md5))
- };
- })
- },
- /* 获取时间差异 */
- getDateDiff(dateTimeStamp) {
- var result = ''
- var minute = 1000 * 60;
- var hour = minute * 60;
- var day = hour * 24;
- var halfamonth = day * 15;
- var month = day * 30;
- var now = new Date().getTime();
- var diffValue = now - dateTimeStamp;
- if (diffValue < 0) {
- return;
- }
- var monthC = diffValue / month;
- var weekC = diffValue / (7 * day);
- var dayC = diffValue / day;
- var hourC = diffValue / hour;
- var minC = diffValue / minute;
- if (monthC >= 1) {
- result = "" + parseInt(monthC) + app.$t('unit.diffTip1');
- } else if (weekC >= 1) {
- result = "" + parseInt(weekC) + app.$t('unit.diffTip2');
- } else if (dayC >= 1) {
- result = "" + parseInt(dayC) + app.$t('unit.diffTip3');
- } else if (hourC >= 1) {
- result = "" + parseInt(hourC) + app.$t('unit.diffTip4');
- } else if (minC >= 1) {
- result = "" + parseInt(minC) + app.$t('unit.diffTip5');
- } else
- result = app.$t('unit.diffTip6');
- return result;
- },
- /* 上传视频到BLob */
- async doUploadVideo(vm, file, editor) {
- // 判断试卷编辑试题环境下 则直接取scope
- let editorEnv = sessionStorage.getItem('editorEnv')
- let inPaperEnv = editorEnv && editorEnv !== 'normal'
- let paperName = inPaperEnv ? sessionStorage.getItem('paper_name') : null
- vm.$Spin.show({
- render: (h) => {
- return h('div', {
- 'class': 'my-spin',
- style: {
- background: '#000',
- padding: '20px',
- borderRadius: '5px',
- color: '#fff'
- }
- }, [
- h('Icon', {
- 'class': 'demo-spin-icon-load',
- props: {
- type: 'ios-loading',
- size: 18
- }
- }),
- h('div', app.$t('utils.uploadLoading'))
- ])
- }
- });
- const blobTool = require('./blobTool.js')
- const isSchool = vm.$parent.exerciseScope ? vm.$parent.exerciseScope === 1 : vm.exerciseScope === 1
- const scope = inPaperEnv ? editorEnv : (isSchool ? 'school' : 'private')
- const sasData = scope === 'school' ? await this.getSchoolSas() : await this.getPrivateSas()
- const blobToolClass = blobTool.default
- //初始化Blob
- let containerClient = new blobToolClass(sasData.url, sasData.name, sasData.sas, scope)
- try {
- let id = vm.curId || vm.$parent.curId
- // 上传文件
- let blobFile = await containerClient.upload(file, {
- path: inPaperEnv && paperName ? ('paper/' + paperName) : ('item/' + id)
- })
- // 获取blob链接以及视频封面截图
- const fileSas = await this.getFileSas(blobFile.url)
- // const fileBlobUrl = encodeURI(blobFile.url) + '?' + fileSas.sas
- const fileBlobUrl = encodeURI(blobFile.url) + '?' + fileSas.sas
- // const posterBase64 = await this.getVideoBase64(fileBlobUrl)
- editor.selection.getSelectionStartElem().elems[0].innerHTML += '<span><span> </span><video src=' +
- fileBlobUrl +
- ' class="richText-video" width="300" preload controls="controls"></video><span> </span></span>'
- editor.change.emit()
- // 如果是在试卷环境下上传多媒体 则需要先保留以下 试题的数据 如果同步到题库 再进行上传
- if (inPaperEnv && paperName) {
- let needSaveToItem = sessionStorage.getItem('syncItemBlob') ? JSON.parse(sessionStorage.getItem(
- 'syncItemBlob')) : []
- needSaveToItem.push({
- paperName: paperName,
- target: 'item/' + id + '/' + file.name,
- path: blobFile.blob,
- scope: scope
- })
- sessionStorage.setItem('syncItemBlob', JSON.stringify(needSaveToItem))
- }
- vm.$EventBus.$emit('noSave', {
- path: blobFile.blob,
- size: blobFile.size,
- scope: scope
- })
- vm.$Spin.hide();
- } catch (e) {
- vm.$Message.error(e.spaceError)
- vm.$Spin.hide();
- }
- },
- /* 上传视频到BLob */
- async doUploadAudio(vm, file, editor) {
- console.log(vm)
- // 判断试卷编辑试题环境下 则直接取scope
- let editorEnv = sessionStorage.getItem('editorEnv')
- let inPaperEnv = editorEnv && editorEnv !== 'normal'
- let paperName = inPaperEnv ? sessionStorage.getItem('paper_name') : null
- vm.$Spin.show({
- render: (h) => {
- return h('div', {
- 'class': 'my-spin',
- style: {
- background: '#000',
- padding: '20px',
- borderRadius: '5px',
- color: '#fff'
- }
- }, [
- h('Icon', {
- 'class': 'demo-spin-icon-load',
- props: {
- type: 'ios-loading',
- size: 18
- }
- }),
- h('div', app.$t('utils.uploadLoading'))
- ])
- }
- });
- const blobTool = require('./blobTool.js')
- const isSchool = vm.$parent.exerciseScope ? vm.$parent.exerciseScope === 1 : vm.exerciseScope === 1
- const scope = inPaperEnv ? editorEnv : (isSchool ? 'school' : 'private')
- const sasData = scope === 'school' ? await this.getSchoolSas() : await this.getPrivateSas()
- const blobToolClass = blobTool.default
- console.log(isSchool)
- //初始化Blob
- let containerClient = new blobToolClass(sasData.url, sasData.name, sasData.sas, scope)
- try {
- let id = vm.curId || vm.$parent.curId
- // 上传文件
- let blobFile = await containerClient.upload(file, {
- path: inPaperEnv && paperName ? ('paper/' + paperName) : ('item/' + id)
- })
- console.log(blobFile)
- // 获取blob链接以及视频封面截图
- const fileSas = await this.getFileSas(blobFile.url)
- const fileBlobUrl = fileSas.url
- editor.selection.getSelectionStartElem().elems[0].innerHTML += `<span><span> </span><span class="richText-audio" contenteditable="false" >
- <span class="audio-info">
- <i class="ivu-icon ivu-icon-ios-musical-notes" style="font-size: 24px;margin:0 10px"></i>
- <span class="audio-name">${file.name}</span>
- </span>
- <audio src="${fileBlobUrl}" id="audio" controls="controls" controlsList="nodownload"></audio>
- </span><span> </span></span>`
- editor.change.emit()
- // 如果是在试卷环境下上传多媒体 则需要先保留以下 试题的数据 如果同步到题库 再进行上传
- if (inPaperEnv && paperName) {
- let needSaveToItem = sessionStorage.getItem('syncItemBlob') ? JSON.parse(sessionStorage.getItem(
- 'syncItemBlob')) : []
- needSaveToItem.push({
- paperName: paperName,
- target: 'item/' + id + '/' + file.name,
- path: blobFile.blob,
- scope: scope
- })
- sessionStorage.setItem('syncItemBlob', JSON.stringify(needSaveToItem))
- }
- vm.$EventBus.$emit('noSave', {
- path: blobFile.blob,
- size: blobFile.size,
- scope: scope
- })
- vm.$Spin.hide();
- } catch (e) {
- vm.$Message.error(e.spaceError)
- vm.$Spin.hide();
- }
- },
- /* 删除未保存的BLOB多媒体文件 */
- async deleteNoSave(noSaveArr) {
- const blobTool = require('./blobTool.js')
- const schoolSas = await this.getSchoolSas()
- const privateSas = await this.getPrivateSas()
- const blobToolClass = blobTool.default
- let schoolBlobClient = new blobToolClass(schoolSas.url, schoolSas.name, schoolSas.sas, 'school')
- let privateBlobClient = new blobToolClass(privateSas.url, privateSas.name, privateSas.sas, 'private')
- let promiseArr = []
- for (let i = 0; i < noSaveArr.length; i++) {
- let item = noSaveArr[i]
- promiseArr.push(new Promise((r, j) => {
- let myClient = item.scope === 'school' ? schoolBlobClient : privateBlobClient
- myClient.deleteBlob(item.path, item.size).then(res => {
- r(200)
- }).catch(err => {
- j(err)
- })
- }))
- }
- Promise.all(promiseArr).then(result => {
- localStorage.setItem('noSave', '[]')
- }).catch(err => {
- console.log(err)
- })
- },
- /* 判断是否相等 */
- 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;
- },
- /* 学情认知层次模块数据转换 */
- getLevelStuPercent(val, subjectIndex, index) {
- let result = []
- val.students.forEach(stu => {
- result.push([
- stu.name,
- stu.className,
- stu.no || '-',
- val.fScores[subjectIndex].value[index],
- stu.subjects[subjectIndex].fieldPoint[index],
- val.fScores[subjectIndex].value[index] == 0 ? 0 : (stu.subjects[subjectIndex]
- .fieldPoint[index] / val.fScores[subjectIndex].value[index])
- .toFixed(2)
- ])
- })
- return result
- },
- /* 学情认知层次年级班级得分率数据转换 */
- getLevelClassPercent(val, subjectIndex, index) {
- let result = []
- val.classes.forEach(classItem => {
- result.push(classItem.subjects[subjectIndex].field.map((score, index) => val.fieldwrong[
- subjectIndex].value[index][1] == 0 ? 0 : Number(score / val.fieldwrong[subjectIndex]
- .value[index][1]) * 100)[index])
- })
- return result
- },
- /* 学情认知层次年级班级得分率数据转换 */
- getLevelPercent(val, subjectIndex) {
- let stuResult = {}
- let classResult = {}
- val.fieldName[subjectIndex].value.forEach((item, index) => {
- stuResult[item] = this.getLevelStuPercent(val, subjectIndex, index)
- classResult[item] = this.getLevelClassPercent(val, subjectIndex, index)
- })
- stuResult.grade = val.fieldAllPer[subjectIndex].value.map((score, index) => (val.fieldwrong[subjectIndex].value[
- index][1] == 0 ? 0 : Number(score / val.fieldwrong[subjectIndex].value[index][1]).toFixed(2)) * 100)
- stuResult.keys = val.knowKey
- classResult.keys = val.knowkey
- classResult.className = val.classes.map(i => i.className)
- let obj = {
- stuResult: stuResult,
- classResult: classResult
- }
- return obj
- },
- /* 学情知识点模块数据转换 */
- getKnowStuPercent(val, subjectIndex, index) {
- let result = []
- val.students.forEach(stu => {
- result.push([
- stu.name,
- stu.className,
- stu.no || '-',
- val.kScores[subjectIndex].value[index],
- stu.subjects[subjectIndex].point[index],
- val.kScores[subjectIndex].value[index] == 0 ? 0 : (stu.subjects[subjectIndex].point[
- index] / val.kScores[subjectIndex].value[index])
- .toFixed(2)
- ])
- })
- return result
- },
- /* 学情知识点班级得分率数据转换 */
- getKnowClassPercent(val, subjectIndex, index) {
- let result = []
- val.classes.forEach(classItem => {
- // 取当前班级在每个知识点的得分 除以知识点的总分 得到每个班在该知识点的得分率 index=>知识点下标
- result.push(classItem.subjects[subjectIndex].point.map((score, pointIndex) => val.wrong[
- subjectIndex].value[pointIndex][1] == 0 ? 0 : Number(score / val.wrong[subjectIndex]
- .value[pointIndex][1]) * 100)[index])
- })
- return result
- },
- /* 学情知识点年级班级得分率数据转换 */
- getKnowPercent(val, subjectIndex) {
- let stuResult = {}
- let classResult = {}
- val.knowName[subjectIndex].value.forEach((item, index) => {
- stuResult[item] = this.getKnowStuPercent(val, subjectIndex, index)
- classResult[item] = this.getKnowClassPercent(val, subjectIndex, index)
- })
- // 取当前年级在每个知识点的得分 除以知识点的总分 得到年级在该知识点的得分率
- stuResult.grade = val.knowAllper[subjectIndex].value.map((score, index) => val.wrong[subjectIndex].value[index][
- 1
- ] == 0 ? 0 : Number(score / val.wrong[subjectIndex].value[index][1]) * 100)
- stuResult.keys = val.knowKey
- classResult.keys = val.knowkey
- classResult.className = val.classes.map(i => i.className)
- let obj = {
- stuResult: stuResult,
- classResult: classResult
- }
- return obj
- },
- /* 罗马数字转换 */
- getRomanByNum(number) {
- var Roman = [
- ["", "I", "II", "III", "IV", "V", "VI", "VII", "VIII", "IX"],
- ["", "X", "XX", "XXX", "XL", "L", "LX", "LXX", "LXXX", "XC"],
- ["", "C", "CC", "CCC", "CD", "D", "DC", "DCC", "DCCC", "CM"],
- ["", "M", "MM", "MMM", " ", " ", " ", " ", " ", " "]
- ];
- // 只能转换 4000 以下的正整数阿拉伯数字
- function convert(num) {
- if (isNaN(num)) return num;
- var ReverseArr = num.toString().split("").reverse();
- var CorrectArr = [];
- for (var i = 0; i < ReverseArr.length; i++) {
- CorrectArr.unshift(Roman[i][ReverseArr[i]]);
- }
- return CorrectArr.join("");
- }
- return convert(number)
- }
- }
|