diff --git a/public/mitm.html b/public/mitm.html new file mode 100644 index 00000000..508a9c3b --- /dev/null +++ b/public/mitm.html @@ -0,0 +1,167 @@ + + diff --git a/public/sw.js b/public/sw.js new file mode 100644 index 00000000..dd75c1a5 --- /dev/null +++ b/public/sw.js @@ -0,0 +1,130 @@ +/* global self ReadableStream Response */ + +self.addEventListener('install', () => { + self.skipWaiting() +}) + +self.addEventListener('activate', event => { + event.waitUntil(self.clients.claim()) +}) + +const map = new Map() + +// This should be called once per download +// Each event has a dataChannel that the data will be piped through +self.onmessage = event => { + // We send a heartbeat every x second to keep the + // service worker alive if a transferable stream is not sent + if (event.data === 'ping') { + return + } + + const data = event.data + const downloadUrl = data.url || self.registration.scope + Math.random() + '/' + (typeof data === 'string' ? data : data.filename) + const port = event.ports[0] + const metadata = new Array(3) // [stream, data, port] + + metadata[1] = data + metadata[2] = port + + // Note to self: + // old streamsaver v1.2.0 might still use `readableStream`... + // but v2.0.0 will always transfer the stream through MessageChannel #94 + if (event.data.readableStream) { + metadata[0] = event.data.readableStream + } else if (event.data.transferringReadable) { + port.onmessage = evt => { + port.onmessage = null + metadata[0] = evt.data.readableStream + } + } else { + metadata[0] = createStream(port) + } + + map.set(downloadUrl, metadata) + port.postMessage({ download: downloadUrl }) +} + +function createStream (port) { + // ReadableStream is only supported by chrome 52 + return new ReadableStream({ + start (controller) { + // When we receive data on the messageChannel, we write + port.onmessage = ({ data }) => { + if (data === 'end') { + return controller.close() + } + + if (data === 'abort') { + controller.error('Aborted the download') + return + } + + controller.enqueue(data) + } + }, + cancel (reason) { + console.log('user aborted', reason) + port.postMessage({ abort: true }) + } + }) +} + +self.onfetch = event => { + const url = event.request.url + + // this only works for Firefox + if (url.endsWith('/ping')) { + return event.respondWith(new Response('pong')) + } + + const hijacke = map.get(url) + + if (!hijacke) return null + + const [ stream, data, port ] = hijacke + + map.delete(url) + + // Not comfortable letting any user control all headers + // so we only copy over the length & disposition + const responseHeaders = new Headers({ + 'Content-Type': 'application/octet-stream; charset=utf-8', + + // To be on the safe side, The link can be opened in a iframe. + // but octet-stream should stop it. + 'Content-Security-Policy': "default-src 'none'", + 'X-Content-Security-Policy': "default-src 'none'", + 'X-WebKit-CSP': "default-src 'none'", + 'X-XSS-Protection': '1; mode=block', + 'Cross-Origin-Embedder-Policy': 'require-corp' + }) + + let headers = new Headers(data.headers || {}) + + if (headers.has('Content-Length')) { + responseHeaders.set('Content-Length', headers.get('Content-Length')) + } + + if (headers.has('Content-Disposition')) { + responseHeaders.set('Content-Disposition', headers.get('Content-Disposition')) + } + + // data, data.filename and size should not be used anymore + if (data.size) { + console.warn('Depricated') + responseHeaders.set('Content-Length', data.size) + } + + let fileName = typeof data === 'string' ? data : data.filename + if (fileName) { + console.warn('Depricated') + // Make filename RFC5987 compatible + fileName = encodeURIComponent(fileName).replace(/['()]/g, escape).replace(/\*/g, '%2A') + responseHeaders.set('Content-Disposition', "attachment; filename*=UTF-8''" + fileName) + } + + event.respondWith(new Response(stream, { headers: responseHeaders })) + + port.postMessage({ debug: 'Download started' }) +} diff --git a/src/utils/stream.js b/src/utils/stream.js index eef180e7..7f745ed2 100644 --- a/src/utils/stream.js +++ b/src/utils/stream.js @@ -1,10 +1,12 @@ import streamSaver from "streamsaver"; import "streamsaver/examples/zip-stream.js"; import store from '@/store' +streamSaver.mitm = `${window.location.origin}/mitm.html?version=2.0.0` // 下载文件并压缩 function zipFiles(zipName, files) { console.log("同步下载打包开始时间:" + new Date()); store.dispatch('trials/setUnLock', true) + files = formatFiles(files) // 创建压缩文件输出流 const zipFileOutputStream = streamSaver.createWriteStream(zipName); // 创建下载文件流 @@ -50,6 +52,23 @@ async function updateFile(file, name) { console.log(err) } } +// 同名文件修改名称 +function formatFiles(files) { + let fileObj = {}; + files.forEach(file => { + let arr = Object.keys(fileObj); + if (!~arr.indexOf(file.name)) { + fileObj[file.name] = 1; + } else { + let name = file.name; + file.name = name.split(".")[0] + `(${fileObj[name]})` + name + .substring(name.lastIndexOf('.')) + .toLocaleLowerCase() + fileObj[name]++; + } + }) + return files; +} function decodeUtf8(bytes) { let str = bytes.split('?'); let str2 = str[0].split('/'); diff --git a/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRules.vue b/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRules.vue index 1289e411..e8766187 100644 --- a/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRules.vue +++ b/src/views/trials/trials-panel/setting/reading-unit/components/ArbitrationRules.vue @@ -41,7 +41,7 @@ type="primary" :disabled="OtherInfo.IsSign" @click="apply(item.ReadingQuestionTrialId, index)" - >{{ $t("common:button:save") }}{{ $t('common:button:save') }} {{ $t("common:button:reset") }}{{ $t('common:button:reset') }} {{ $t("trials:adRules:button:addRule") }}{{ $t('trials:adRules:button:addRule') }}
- {{ $t("trials:adRules:title:selectAnswerGroup") }} + {{ $t('trials:adRules:title:selectAnswerGroup') }} {{ - QuestionList[index].grouping.toString().replaceAll(",", "|") + QuestionList[index].grouping.toString().replaceAll(',', '|') }} - {{ $t("trials:adRules:title:addGroup") }} + {{ $t('trials:adRules:title:addGroup') }}
@@ -253,7 +256,7 @@ v-if="QuestionList[index].QuestionGenre !== 3" style="margin-top: 20px" > - {{ $t("trials:adRules:title:group") }} + {{ $t('trials:adRules:title:group') }} {{ itemA }} - {{ $t("trials:adRules:title:group") }} + {{ $t('trials:adRules:title:group') }} {{ itemA - .split("|") + .split('|') .map((v) => $fd(QuestionList[index].DictionaryCode, parseInt(v)) ) - .join("|") + .join('|') }} @@ -457,12 +460,12 @@ size="small" type="primary" @click=" - QuestionVisible = false; - $set(QuestionList[selectIndex], 'groupingA', []); - $set(QuestionList[selectIndex], 'groupingB', []); + QuestionVisible = false + $set(QuestionList[selectIndex], 'groupingA', []) + $set(QuestionList[selectIndex], 'groupingB', []) " > - {{ $t("common:button:cancel") }} + {{ $t('common:button:cancel') }} - {{ $t("common:button:save") }} + {{ $t('common:button:save') }} @@ -482,13 +485,13 @@ import { getTrialConfirmCriterionList, getTrialCriterionJudgeQuestionList, setTrialCriterionJudgeQuestionAnswerGroup, -} from "@/api/trials/reading"; -import { setTrialJudgyInfo, getTrialJudgyInfo } from "@/api/trials/setting"; +} from '@/api/trials/reading' +import { setTrialJudgyInfo, getTrialJudgyInfo } from '@/api/trials/setting' export default { props: { trialReadingCriterionId: { type: String, - default: "", + default: '', }, }, data() { @@ -512,23 +515,23 @@ export default { { required: true, message: this.$t( - "trials:trials-list:setitng:JudgeDifferenceTypeRequired" + 'trials:trials-list:setitng:JudgeDifferenceTypeRequired' ), - trigger: "blur", + trigger: 'blur', }, ], JudgeDifferenceValue: [ { required: true, message: this.$t( - "trials:trials-list:setitng:JudgeDifferenceValueRequired" + 'trials:trials-list:setitng:JudgeDifferenceValueRequired' ), - trigger: "blur", + trigger: 'blur', }, { pattern: /^[0-9]+(.[0-9]{2})?$/, - message: this.$t("trials:trials-list:setitng:JudgeDifferenceValue"), - trigger: "blur", + message: this.$t('trials:trials-list:setitng:JudgeDifferenceValue'), + trigger: 'blur', }, { validator: (rule, value, callback) => { @@ -536,115 +539,115 @@ export default { callback( new Error( this.$t( - "trials:trials-list:setitng:JudgeDifferenceValueMin" + 'trials:trials-list:setitng:JudgeDifferenceValueMin' ) ) - ); + ) } else { - callback(); + callback() } }, - trigger: "blur", + trigger: 'blur', }, ], }, - }; + } }, watch: { TrialReadingCriterionId(v) { - if (v === null) return; - this.loading = true; + if (v === null) return + this.loading = true getTrialCriterionJudgeQuestionList({ TrialId: this.$route.query.trialId, // ReadingQuestionCriterionTrialId: v, TrialReadingCriterionId: this.trialReadingCriterionId, }) .then((res) => { - this.loading = false; - this.QuestionList = res.Result; - this.OtherInfo = res.OtherInfo; + this.loading = false + this.QuestionList = res.Result + this.OtherInfo = res.OtherInfo this.activeNames = this.QuestionList.map( (v) => v.ReadingQuestionTrialId - ); + ) this.QuestionList.forEach((v) => { - this.$set(v, "grouping", []); - this.$set(v, "groupingA", []); - this.$set(v, "groupingB", []); + this.$set(v, 'grouping', []) + this.$set(v, 'groupingA', []) + this.$set(v, 'groupingB', []) this.$set( v, - "AnswerGroupList", + 'AnswerGroupList', Object.assign([], v.AnswerCombination) - ); - this.$set(v, "AnswerGroup2List", Object.assign([], v.AnswerGroup)); - }); + ) + this.$set(v, 'AnswerGroup2List', Object.assign([], v.AnswerGroup)) + }) }) .catch(() => { - this.btnLoading = false; - this.loading = false; - }); + this.btnLoading = false + this.loading = false + }) }, }, mounted() { - this.getList(); - this.getTrialJudgyInfo(); + this.getList() + this.getTrialJudgyInfo() }, methods: { // 修改仲裁规则 changeArbitrationRule(value) { if (value !== 1) { this.QuestionList.forEach((item) => { - item.JudgeDifferenceValue = 0; - item.JudgeDifferenceType = 0; - }); + item.JudgeDifferenceValue = 0 + item.JudgeDifferenceType = 0 + }) } }, JudgeTypeChange(value, index) { this.$nextTick(() => { if (value === 4 || value === 5) { - if (this.$refs["JudgeDifferenceValue" + value + index][0]) { - this.$refs["JudgeDifferenceValue" + value + index][0].resetFields(); + if (this.$refs['JudgeDifferenceValue' + value + index][0]) { + this.$refs['JudgeDifferenceValue' + value + index][0].resetFields() // this.QuestionList[index].JudgeDifferenceValue = 0; } } - }); + }) }, saveAllSync() { return new Promise((resolve, reject) => { - var arr = []; + var arr = [] this.QuestionList.forEach((v, i) => { - arr.push(this.applySync(v.ReadingQuestionTrialId, i)); - }); + arr.push(this.applySync(v.ReadingQuestionTrialId, i)) + }) Promise.all(arr) .then((res) => { - console.log(res); - resolve(true); + console.log(res) + resolve(true) }) .catch((res) => { - console.log("进入catch"); - resolve(false); - }); - }); + console.log('进入catch') + resolve(false) + }) + }) }, applySync(ReadingQuestionTrialId, index) { return new Promise(async (resolve, reject) => { - console.log(this.QuestionList[index].JudgeType); + console.log(this.QuestionList[index].JudgeType) if (this.QuestionList[index].JudgeType === 0) { - reject(false); - return; + reject(false) + return } if ( this.QuestionList[index].JudgeType === 2 && this.QuestionList[index].AnswerGroup2List.length === 0 ) { - reject(false); - return; + reject(false) + return } if ( this.QuestionList[index].JudgeType === 3 && this.QuestionList[index].AnswerGroupList.length === 0 ) { - reject(false); - return; + reject(false) + return } if ( this.QuestionList[index].JudgeType === 4 || @@ -652,17 +655,17 @@ export default { ) { try { let validate = await this.$refs[ - "JudgeDifferenceValue" + + 'JudgeDifferenceValue' + this.QuestionList[index].JudgeType + index - ][0].validate(); - if (!validate) return reject(false); + ][0].validate() + if (!validate) return reject(false) } catch (err) { - return reject(false); + return reject(false) } } - this.btnLoading = true; - this.loading = true; + this.btnLoading = true + this.loading = true setTrialCriterionJudgeQuestionAnswerGroup({ ReadingQuestionTrialId: ReadingQuestionTrialId, AnswerGroup: this.QuestionList[index].AnswerGroup2List, @@ -676,126 +679,126 @@ export default { ), }) .then((res) => { - resolve(); - this.btnLoading = false; - this.loading = false; + resolve() + this.btnLoading = false + this.loading = false }) .catch(() => { - reject(false); - this.btnLoading = false; - this.loading = false; - }); - }); + reject(false) + this.btnLoading = false + this.loading = false + }) + }) }, setTrialJudgyInfo() { - this.loading = true; + this.loading = true setTrialJudgyInfo({ TrialId: this.$route.query.trialId, ArbitrationRule: this.JudgyInfo.ArbitrationRule, TrialReadingCriterionId: this.trialReadingCriterionId, }) .then((res) => { - this.loading = false; - this.$message.success(this.$t("common:message:savedSuccessfully")); // '保存成功' + this.loading = false + this.$message.success(this.$t('common:message:savedSuccessfully')) // '保存成功' }) .catch(() => { - this.loading = false; - }); + this.loading = false + }) }, getTrialJudgyInfo() { - this.loading = true; + this.loading = true getTrialJudgyInfo({ TrialId: this.$route.query.trialId, TrialReadingCriterionId: this.trialReadingCriterionId, }) .then((res) => { - this.JudgyInfo = res.Result; - this.loading = false; + this.JudgyInfo = res.Result + this.loading = false }) .catch((v) => { - this.loading = false; - }); + this.loading = false + }) }, tagClose2(index, indexA) { // '删除该规则组?' - this.$confirm(this.$t("trials:adRules:message:msg1")).then(() => { - this.QuestionList[index].AnswerGroup2List.splice(indexA, 1); - }); + this.$confirm(this.$t('trials:adRules:message:msg1')).then(() => { + this.QuestionList[index].AnswerGroup2List.splice(indexA, 1) + }) }, tagClose(index, indexA) { // '删除该规则组?' - this.$confirm(this.$t("trials:adRules:message:msg1")).then(() => { - this.QuestionList[index].AnswerGroupList.splice(indexA, 1); - }); + this.$confirm(this.$t('trials:adRules:message:msg1')).then(() => { + this.QuestionList[index].AnswerGroupList.splice(indexA, 1) + }) }, save() { - var index = this.selectIndex; - var indexA = this.indexA; + var index = this.selectIndex + var indexA = this.indexA if (this.QuestionList[index].groupingA.length === 0) { - this.$alert(this.$t("trials:adRules:message:msg2")); // '请先选择答案A' - return; + this.$alert(this.$t('trials:adRules:message:msg2')) // '请先选择答案A' + return } if (this.QuestionList[index].groupingB.length === 0) { - this.$alert(this.$t("trials:adRules:message:msg3")); // '请先选择答案B' - return; + this.$alert(this.$t('trials:adRules:message:msg3')) // '请先选择答案B' + return } - if (this.type === "add") { + if (this.type === 'add') { this.QuestionList[index].AnswerGroupList.push({ AnswerGroupA: this.QuestionList[index].groupingA, AnswerGroupB: this.QuestionList[index].groupingB, - }); + }) } else { this.$set( this.QuestionList[index].AnswerGroupList[indexA], - "AnswerGroupA", + 'AnswerGroupA', this.QuestionList[index].groupingA - ); + ) this.$set( this.QuestionList[index].AnswerGroupList[indexA], - "AnswerGroupB", + 'AnswerGroupB', this.QuestionList[index].groupingB - ); + ) } - this.$set(this.QuestionList[index], "groupingA", []); - this.$set(this.QuestionList[index], "groupingB", []); - this.$message.success(this.$t("trials:adRules:message:msg4")); // '成功新增答案规则' - this.QuestionVisible = false; + this.$set(this.QuestionList[index], 'groupingA', []) + this.$set(this.QuestionList[index], 'groupingB', []) + this.$message.success(this.$t('trials:adRules:message:msg4')) // '成功新增答案规则' + this.QuestionVisible = false }, addGroup2(index) { if (this.QuestionList[index].grouping.length === 0) { - this.$alert(this.$t("trials:adRules:message:msg5")); // '请先选择答案,再添加分组' - return; + this.$alert(this.$t('trials:adRules:message:msg5')) // '请先选择答案,再添加分组' + return } var grouping = this.QuestionList[index].grouping .toString() - .replaceAll(",", "|"); - this.QuestionList[index].AnswerGroup2List.push(`|${grouping}|`); - this.$set(this.QuestionList[index], "grouping", []); + .replaceAll(',', '|') + this.QuestionList[index].AnswerGroup2List.push(`|${grouping}|`) + this.$set(this.QuestionList[index], 'grouping', []) }, addGroup(index, indexA) { - this.selectIndex = index; - this.type = "add"; + this.selectIndex = index + this.type = 'add' if (indexA !== null) { - this.indexA = indexA; - this.type = "edit"; + this.indexA = indexA + this.type = 'edit' this.$set( this.QuestionList[index], - "groupingA", + 'groupingA', this.QuestionList[index].AnswerGroupList[indexA].AnswerGroupA - ); + ) this.$set( this.QuestionList[index], - "groupingB", + 'groupingB', this.QuestionList[index].AnswerGroupList[indexA].AnswerGroupB - ); + ) } - this.QuestionVisible = true; + this.QuestionVisible = true }, reset(ReadingQuestionTrialId, index) { // '确定重置当前设置的裁判任务生成规则吗?' - this.$confirm(this.$t("trials:adRules:message:msg6")).then(() => { - this.btnLoading = true; - this.loading = true; + this.$confirm(this.$t('trials:adRules:message:msg6')).then(() => { + this.btnLoading = true + this.loading = true setTrialCriterionJudgeQuestionAnswerGroup({ ReadingQuestionTrialId: ReadingQuestionTrialId, AnswerGroup: [], @@ -805,39 +808,39 @@ export default { JudgeDifferenceType: 0, }) .then((res) => { - this.$set(this.QuestionList[index], "AnswerGroup2List", []); - this.$set(this.QuestionList[index], "AnswerGroupList", []); - this.$set(this.QuestionList[index], "JudgeType", 0); - this.$set(this.QuestionList[index], "JudgeDifferenceValue", 0); - this.$set(this.QuestionList[index], "JudgeDifferenceType", 0); - this.$message.success(this.$t("trials:adRules:message:msg7")); // '重置成功' - this.btnLoading = false; - this.loading = false; + this.$set(this.QuestionList[index], 'AnswerGroup2List', []) + this.$set(this.QuestionList[index], 'AnswerGroupList', []) + this.$set(this.QuestionList[index], 'JudgeType', 0) + this.$set(this.QuestionList[index], 'JudgeDifferenceValue', 0) + this.$set(this.QuestionList[index], 'JudgeDifferenceType', 0) + this.$message.success(this.$t('trials:adRules:message:msg7')) // '重置成功' + this.btnLoading = false + this.loading = false }) .catch(() => { - this.btnLoading = false; - this.loading = false; - }); - }); + this.btnLoading = false + this.loading = false + }) + }) }, async apply(ReadingQuestionTrialId, index) { if (this.QuestionList[index].JudgeType === 0) { - this.$alert(this.$t("trials:adRules:message:msg8")); // '请先配置规则才能应用' - return; + this.$alert(this.$t('trials:adRules:message:msg8')) // '请先配置规则才能应用' + return } if ( this.QuestionList[index].JudgeType === 2 && this.QuestionList[index].AnswerGroup2List.length === 0 ) { - this.$alert(this.$t("trials:adRules:message:msg8")); // '请先配置规则才能应用' - return; + this.$alert(this.$t('trials:adRules:message:msg8')) // '请先配置规则才能应用' + return } if ( this.QuestionList[index].JudgeType === 3 && this.QuestionList[index].AnswerGroupList.length === 0 ) { - this.$alert(this.$t("trials:adRules:message:msg8")); - return; + this.$alert(this.$t('trials:adRules:message:msg8')) + return } if ( this.QuestionList[index].JudgeType === 4 || @@ -845,15 +848,15 @@ export default { ) { try { let validate = await this.$refs[ - "JudgeDifferenceValue" + this.QuestionList[index].JudgeType + index - ][0].validate(); - if (!validate) return; + 'JudgeDifferenceValue' + this.QuestionList[index].JudgeType + index + ][0].validate() + if (!validate) return } catch (err) { - return; + return } } - this.btnLoading = true; - this.loading = true; + this.btnLoading = true + this.loading = true setTrialCriterionJudgeQuestionAnswerGroup({ ReadingQuestionTrialId: ReadingQuestionTrialId, AnswerGroup: this.QuestionList[index].AnswerGroup2List, @@ -867,49 +870,49 @@ export default { ), }) .then((res) => { - this.$message.success(this.$t("trials:adRules:message:msg9")); // '应用成功' - this.btnLoading = false; - this.loading = false; + this.$message.success(this.$t('trials:adRules:message:msg9')) // '应用成功' + this.btnLoading = false + this.loading = false }) .catch(() => { - this.btnLoading = false; - this.loading = false; - }); + this.btnLoading = false + this.loading = false + }) }, tabClick(v) { this.ReadingQuestionCriterionTrialId = - this.CriterionList[this.index].ReadingQuestionCriterionTrialId; + this.CriterionList[this.index].ReadingQuestionCriterionTrialId }, getList() { - this.loading = true; + this.loading = true getTrialCriterionJudgeQuestionList({ TrialId: this.$route.query.trialId, TrialReadingCriterionId: this.trialReadingCriterionId, }) .then((res) => { - this.loading = false; - this.QuestionList = res.Result; - this.OtherInfo = res.OtherInfo; + this.loading = false + this.QuestionList = res.Result + this.OtherInfo = res.OtherInfo this.activeNames = this.QuestionList.map( (v) => v.ReadingQuestionTrialId - ); + ) this.QuestionList.forEach((v) => { - this.$set(v, "grouping", []); - this.$set(v, "groupingA", []); - this.$set(v, "groupingB", []); + this.$set(v, 'grouping', []) + this.$set(v, 'groupingA', []) + this.$set(v, 'groupingB', []) this.$set( v, - "AnswerGroupList", + 'AnswerGroupList', Object.assign([], v.AnswerCombination) - ); - this.$set(v, "AnswerGroup2List", Object.assign([], v.AnswerGroup)); - }); + ) + this.$set(v, 'AnswerGroup2List', Object.assign([], v.AnswerGroup)) + }) }) .catch(() => { - this.btnLoading = false; - this.loading = false; - }); + this.btnLoading = false + this.loading = false + }) }, }, -}; +} diff --git a/vue.config.js b/vue.config.js index f7fb01e5..ea3e8bf9 100644 --- a/vue.config.js +++ b/vue.config.js @@ -24,10 +24,10 @@ module.exports = { productionSourceMap: false, devServer: { port: '8080', - // headers: { - // 'Cross-Origin-Opener-Policy': 'same-origin', - // 'Cross-Origin-Embedder-Policy': 'require-corp' - // }, + headers: { + 'Cross-Origin-Opener-Policy': 'same-origin', + 'Cross-Origin-Embedder-Policy': 'require-corp' + }, // open: true, overlay: { warnings: false,