// import store from '@/store' import { app } from '@/main.js' import _tools from "./public.js" // import _editorTools from "./editorTools.js" /* * 根据某个属性进行分组 */ function groupBy(array, key) { const groups = {} array.forEach(function (item) { const group = JSON.stringify(item[key]) groups[group] = groups[group] || [] groups[group].push(item) }) return Object.keys(groups).map(function (group) { return groups[group] }) } /* * 判断两个对象是否相等 */ function isObjEqual(o1, o2) { var props1 = Object.keys(o1) var props2 = Object.keys(o2) if (props1.length != props2.length) { return false } for (var i = 0, max = props1.length; i < max; i++) { var propName = props1[i] if (o1[propName] !== o2[propName]) { return false } } return true } /* * 获取对象在对象数组的index */ function getIndex(_arr, _obj) { var len = _arr.length for (let i = 0; i < len; i++) { if (isObjEqual(_arr[i], _obj)) { return parseInt(i) } } return -1 } /* * 产生某个范围的随机数 */ function getBtwRandom(start, end) { return Math.floor(Math.random() * (end - start)) + start } /* *根据图片链接压缩图片得到缩略图 * @params url: 文件url */ function compressImgByUrl(url, name, quality) { return new Promise((r, j) => { try { let img = new Image() img.setAttribute('crossOrigin', 'Anonymous') img.src = url img.onload = function () { let canvas = document.createElement('canvas') canvas.width = 200 canvas.height = 200 * img.height / img.width let ctx = canvas.getContext('2d') ctx.drawImage(img, 0, 0, img.width, img.height, 0, 0, canvas.width, canvas.height) let newImgData = canvas.toDataURL('image/png', quality) //let resultFile = dataURLtoFile(newImgData, name) //r(resultFile) r(newImgData) } img.onerror = function (e) { console.error('图片Error', e) j('Format Error') } } catch (err) { j(err) } }) } /* *根据视频链接创建封面图 * @params url: 文件url */ function createVideoPoster(url, name, quality) { return new Promise( (r, j) => { try { let video = document.createElement('video') video.setAttribute('crossOrigin', 'Anonymous') video.setAttribute('width', '300') video.setAttribute('controls', 'controls') video.setAttribute('crossOrigin', 'Anonymous') video.setAttribute('src', url) video.currentTime = 1 console.log(url) video.addEventListener('loadeddata', () => { let canvas = document.createElement('canvas') canvas.width = 300 canvas.height = 300 * video.videoHeight / video.videoWidth let ctx = canvas.getContext('2d') ctx.drawImage(video, 0, 0, video.videoWidth, video.videoHeight, 0, 0, canvas.width, canvas.height) let newVideoData = canvas.toDataURL('image/png', quality) //let resultFile = dataURLtoFile(newVideoData, name) r(newVideoData) }) video.addEventListener('error', (e) => { console.error(e) j('Format Error') }) } catch (err) { j(err) } } ) } /* *dataUrl转文件 */ function dataURLtoFile(dataurl, filename) { console.log(...arguments); let arr = dataurl.split(',') let mime = arr[0].match(/:(.*?);/)[1] let bstr = atob(arr[1]) let n = bstr.length let u8arr = new Uint8Array(n) while (n--) { u8arr[n] = bstr.charCodeAt(n) } return new File([u8arr], filename, { type: mime }) } /* *文件转dataUrl */ function fileToURL(file) { return new Promise((r, j) => { try { var reader = new FileReader() reader.onloadend = function (e) { r(e.target.result) } reader.readAsDataURL(file) } catch (e) { j(e) } }) } /* * 函数防抖 */ function debounce(func, delay) { return function () { window.clearTimeout(window.timeout) window.timeout = setTimeout(() => { clearTimeout(window.timeout) func.apply(this, arguments) }, delay) } } /* * 函数节流 */ function throttle(func, delay) { let run = true return function () { if (!run) { return // 如果开关关闭了,那就直接不执行下边的代码 } run = false // 持续触发的话,run一直是false,就会停在上边的判断那里 setTimeout(() => { func.apply(this, arguments) run = true // 定时器到时间之后,会把开关打开,我们的函数就会被执行 }, delay) } } //转换bytes function formatBytes(bytes) { bytes = bytes || 0 return bytes / 1024 < 1024 ? (bytes / 1024).toFixed(1) + 'KB' : bytes / 1024 / 1024 < 1024 ? (bytes / 1024 / 1024).toFixed(1) + 'M' : (bytes / 1024 / 1024 / 1024).toFixed(1) + 'G' } //生成uuid function uuid() { function S4() { return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1) } return (S4() + S4() + '-' + S4() + '-' + S4() + '-' + S4() + '-' + S4() + S4() + S4()) } // 获取某个字符在字符串中第num次出现的index function findChartIndex(str, cha, num) { var x = str.indexOf(cha); for (var i = 0; i < num; i++) { x = str.indexOf(cha, x + 1); } return x; } function secondTimeFormat(timestamp) { timestamp = timestamp < 10000000000 ? timestamp * 1000 : timestamp let date = new Date(timestamp) let Y = date.getFullYear() let M = date.getMonth() let D = date.getDate() let H = date.getHours() let MIN = date.getMinutes() let SEC = date.getSeconds() return `${Y}/${M < 9 ? '0' + (M + 1) : M + 1}/${D < 10 ? '0' + D : D} ${H < 10 ? '0' + H : H}:${MIN < 10 ? '0' + MIN : MIN}:${SEC < 10 ? '0' + SEC : SEC}` } function timeFormat(timestamp) { timestamp = timestamp < 10000000000 ? timestamp * 1000 : timestamp let date = new Date(timestamp) let Y = date.getFullYear() let M = date.getMonth() let D = date.getDate() let H = date.getHours() let MIN = date.getMinutes() return `${Y}/${M < 9 ? '0' + (M + 1) : M + 1}/${D < 9 ? '0' + D : D} ${H < 10 ? '0' + H : H}:${MIN < 10 ? '0' + MIN : MIN}` } //時間戳轉換 function dateFormat(timestamp) { if (timestamp <= 0) return '' timestamp = timestamp < 10000000000 ? timestamp * 1000 : timestamp let date = new Date(timestamp) let Y = date.getFullYear() let M = date.getMonth() let D = date.getDate() return `${Y}/${M < 9 ? '0' + (M + 1) : M + 1}/${D < 9 ? '0' + D : D}` } /** * 根据学年获取年级名称 * @param year 学年 */ function getGradeNameByYear(year) { if (year && year > 0) { let curPeriod = store.state.user?.curPeriod if (curPeriod) { let date = new Date() let curYear = date.getFullYear() let month = date.getMonth() + 1 let start = curPeriod.semesters.find(item => { return item.start == 1 }) // 根据入学月份确定当前年级和学级的关系 if (start && month < start.month) { curYear-- } let res = curPeriod.grades[curYear - year] if (curYear - year >= curPeriod.grades.length) { return app.$t('schoolBaseInfo.graduated') } return res ? res : app.$t('schoolBaseInfo.untimed') } else { return '--' } } else { return '--' } } /** * 根据学年获取年级信息 * @param year 学年 * @param periodId 学段id(非必填) */ function getGradeInfoByYear(year, periodId) { if (year && year > 0) { let curPeriod if (periodId) { curPeriod = store.state.user?.schoolProfile?.school_base?.period?.find(item => item.id == periodId) } else { curPeriod = store.state.user?.curPeriod } if (curPeriod) { let date = new Date() let curYear = date.getFullYear() let month = date.getMonth() + 1 let start = curPeriod.semesters.find(item => { return item.start == 1 }) // 根据入学月份确定当前年级和学级的关系 if (start && month < start.month) { curYear-- } let res = curPeriod.grades[curYear - year] let gradeName if (curYear - year >= curPeriod.grades.length) { gradeName = app.$t('schoolBaseInfo.graduated') } gradeName = res ? res : app.$t('schoolBaseInfo.untimed') return { id: curYear - year, name: gradeName } } else { return undefined } } else { return undefined } } /** * 根据班级学年年级名称 * @param data 学校基础数据 schoolProfile.school_base * @param curPd 当前学段id * @param grade 年级index */ function getYearByGrade(grade) { let date = new Date() let curYear = date.getFullYear() let month = date.getMonth() + 1 grade = parseInt(grade) let curPeriod = store.state.user?.curPeriod if (grade > -1 && curPeriod) { let start = curPeriod.semesters.find(item => { return item.start == 1 }) // 根据入学月份确定当前年级和学级的关系 if (start && month < start.month) { curYear-- } return curYear - grade } else { return curYear } } /** * 根据教师绑定的学科id获取学科和学段名称 * @param ids 学科ids * @returns * [ * { * periodId:'ddd' * periodName:'小学', * subjectId:'wwww', * subjectName:'语文' * } * ] */ function getTeacherSubjects(ids) { let schoolPeriod = store.state.user?.schoolProfile?.school_base?.period if (ids && ids.length && schoolPeriod) { let data = [] ids.forEach(sid => { for (let i = 0; i < schoolPeriod.length; i++) { let subjectInfo = schoolPeriod[i].subjects.find(subject => subject.id === sid) if (subjectInfo) { data.push({ periodId: schoolPeriod[i].id, periodName: schoolPeriod[i].name, subjectId: subjectInfo.id, subjectName: subjectInfo.name }) break } } }) return data } else { return [] } } //根据域名判断菜单是否显示 function checkJinNiu() { let host = window.location.host return host == 'jinniu.teammodel.cn' } //根据域名判断菜单是否显示 知音 function checkZhiYin() { let host = window.location.host // return host == 'zhiyin.teammodel.cn' return host=='zhiyin-test.teammodel.cn' } //根据域名判断菜单是否显示 function checkTrain() { let host = window.location.host return host == 'scyx.teammodel.cn' } /** * 统一处理学生作答数据 * @param {string} fullUrl ans.json完成路径含授权 * @param {string} richPrefix 富文本前缀(到stuId) * @param {string} sas 授权(不需要“?”) */ function handleStudentAnswer(fullUrl, richPrefix, sas) { return new Promise(async (r, j) => { try { let ansStr = await _tools.getFile(fullUrl) if (ansStr) { let ans = JSON.parse(ansStr) ans.forEach((item, index) => { // 数据异常 if (!item) { ans[index] = [app.$t('learnActivity.score.ansErr')] } // 未作答 // 2024.4.7 题型增加问答题,保存字段为blob地址,需判断是否作答,因此返回[] else if (!item.length) { // ans[index] = [app.$t('learnActivity.score.noStuAns')] ans[index] = [] } // 处理富文本中多媒体 else { item.forEach((as, ai) => { item[ai] = _editorTools.getMideaFullPath(as, richPrefix + '/', '?' + sas) }) ans[index] = item } }) r(ans) } else { r([]) } } catch (e) { r([]) } }) } function getBlobInfo(scope) { console.log(store) let blobProfile if (scope == 'school') { blobProfile = store.state.user.schoolProfile } else if (scope == 'private') { blobProfile = store.state.user.userProfile } if (blobProfile) { let blobUrl = blobProfile.blob_uri let blobName = blobUrl.substring(blobUrl.lastIndexOf('/') + 1) let blobHost = blobUrl.substring(0, blobUrl.lastIndexOf('/')) let blobSas = blobProfile.blob_sas return { blobUrl, blobName, blobHost, blobSas } } else { return {} } } function setLocalLang() { // 自动根据浏览器系统语言设置语言(优先判断本地设置的语言,如果有则使用本地设置的语言,如果没有则使用浏览器系统语言) const curLang = localStorage.getItem('cloudSetting') ? JSON.parse(localStorage.getItem('cloudSetting')).curLang : null const navLang = curLang || navigator.language.toLowerCase() const localLang = (navLang === 'zh' || navLang === 'zh-tw' || navLang === 'zh-cn' || navLang === 'zh-hk') ? navLang : false let lang = localLang || 'en-us' localStorage.setItem('local', lang) return lang } export default { groupBy, isObjEqual, getIndex, getBtwRandom, compressImgByUrl, createVideoPoster, dataURLtoFile, fileToURL, debounce, throttle, formatBytes, uuid, findChartIndex, getGradeNameByYear, getGradeInfoByYear, getYearByGrade, dateFormat, timeFormat, secondTimeFormat, getTeacherSubjects, checkJinNiu, checkZhiYin, checkTrain, handleStudentAnswer, getBlobInfo, setLocalLang }