diff --git a/src/utils/FilePicker.js b/src/utils/FilePicker.js new file mode 100644 index 0000000..08a6706 --- /dev/null +++ b/src/utils/FilePicker.js @@ -0,0 +1,55 @@ +/** + * 本地文件选择 + */ +export class FilePicker { + /** + * 接口是否可用 + * @returns { Boolean } + */ + static canUse() { + return !!(window.showDirectoryPicker && window.showOpenFilePicker) + } + + /** + * 选择一个目录 + * @returns { Promise } + */ + static chooseDirectory() { + if (!this.canUse()) { + throw new Error('Not Support showDirectoryPicker') + } + return window.showDirectoryPicker() + } + + /** + * 选择一个文件 + * @param { Boolean } multiple + * @param { { description?: string; accept?: { [key: string]: string[]; } } } types + * @returns { Promise } + */ + static chooseFile(multiple, types) { + if (!this.canUse()) { + throw new Error('Not Support showOpenFilePicker') + } + const pickerOpts = { + multiple, + types, + excludeAcceptAllOption: true + } + return window.showOpenFilePicker(pickerOpts) + } + + /** + * 判断一个文件是否在某个目录下 + * @param {FileSystemDirectoryHandle} directoryHandle + * @param {FileSystemFileHandle} fileHandle + */ + static async isFileInDirectory(directoryHandle, fileHandle) { + const relativePaths = await directoryHandle.resolve(fileHandle) + if (relativePaths === null || relativePaths.length > 1) { + return false + } else { + return true + } + } +} diff --git a/src/utils/file.js b/src/utils/file.js index 60c4ac9..4c1830c 100644 --- a/src/utils/file.js +++ b/src/utils/file.js @@ -1,5 +1,6 @@ import { Modal } from 'ant-design-vue' import { saveAs } from 'file-saver' +import JSZip from 'jszip' /** * 弹窗填入文件名保存文件 @@ -31,3 +32,47 @@ export const showSaveFileModal = (data, ext) => { } }) } + +/** + * 读文件 + * @param {File} file + * @param { 'arrayBuffer' | 'text' | 'dataURL' | 'binaryString'} fileType + */ +export const readFile = (file, fileType = 'text') => { + return new Promise((resolve, reject) => { + const fileReader = new FileReader() + const category = { + arrayBuffer: 'readAsArrayBuffer', + text: 'readAsText', + dataURL: 'readAsDataURL', + binaryString: 'readAsBinaryString' + } + fileReader[category[fileType]](file) + fileReader.onload = event => { + resolve(event.target.result) + } + fileReader.onerror = error => { + reject(error) + } + }) +} + +/** + * 压缩文件 + * @param {Array} fileList + * @param {string} zipName + * @returns + */ +export const zipFile = async (fileList, zipName) => { + const zip = new JSZip() + const promises = [] + fileList.forEach(file => { + promises.push(readFile(file, 'arrayBuffer')) + }) + const result = await Promise.all(promises) + result.forEach(res => { + zip.file(res.fileName, res.data) + }) + const content = await zip.generateAsync({ type: 'blob' }) + return new File([content], zipName, { type: content.type }) +} diff --git a/src/utils/phdHelper.js b/src/utils/phdHelper.js new file mode 100644 index 0000000..04ef354 --- /dev/null +++ b/src/utils/phdHelper.js @@ -0,0 +1,116 @@ +export class PHDParser { + /** + * 数据类型 + */ + dataType = '' + + /** + * 类型 B G 等 + */ + fileType = '' + + /** + * 质量 FULL 等 + */ + qualify = '' + + /** + * 生存时间 + */ + + liveTime = '' + + /** + * sample 谱的文件名 + */ + sampleFilePrefix = '' + + /** + * 其他文件名 + */ + otherFilePrefixes = [] + + /** + * 构造函数 + * @param {string} text + */ + constructor(text) { + const getLine = this.readTextLine(text) + const dataTypeLine = getLine(4) + const fileTypeLine = getLine(6) + const fileNameLine = getLine(8) + const liveTimeLine = getLine(18) + + this.dataType = this.getOnymousData(dataTypeLine)[0] + const fileType = this.splitLineText(fileTypeLine) + this.fileType = fileType[2] + this.qualify = fileType[4] + + const liveTime = parseFloat(this.splitLineText(liveTimeLine)[3]).toFixed(1) + this.liveTime = liveTime.indexOf('.0') == -1 ? liveTime : liveTime.slice(0, -2) + + // 如果是 Beta 谱 + if (this.fileType == 'B') { + // 如果解析的是sample 文件,则获取其他三个文件 + if (this.dataType == PHD_DATA_TYPE.SAMPLEPHD) { + const filePrefixes = this.getFilePrefixes(fileNameLine) + this.sampleFilePrefix = filePrefixes.splice(0, 1)[0] + this.otherFilePrefixes = filePrefixes + } + } + } + /** + * 将文本按行分割 + * @param {string} text + * @returns { (line: number) => string } + */ + readTextLine(text) { + const splited = text.split('\n') + return line => { + return splited[line - 1] + } + } + + /** + * 获取 具名 行的数据 + * @param {string} text + * @example DATA_TYPE SAMPLEPHD 返回['SAMPLEPHD'] + * @returns {string[]} + */ + getOnymousData(text) { + return text.split(' ').slice(1) + } + + /** + * 将一行中的文本按空格切割 + * @param {string} text + */ + splitLineText(text) { + return text.replace(/\s+/g, ',').split(',') + } + + /** + * 获取全部文件名 + * @param {string} text + */ + getFilePrefixes(text) { + const unHandledfilePrefixes = this.splitLineText(text) + const filePrefixes = unHandledfilePrefixes + .filter(filePrefix => filePrefix) + .map(filePrefix => { + filePrefix = filePrefix.replace(/(\d{4})\/(\d{2})\/(\d{2})-(\d{2}):(\d{2})/, '$1$2$3_$4$5') + return filePrefix + '_' + }) + return filePrefixes + } +} + +/** + * PHD 类型 + */ +export const PHD_DATA_TYPE = { + QCPHD: 'QCPHD', + DETBKPHD: 'DETBKPHD', + SAMPLEPHD: 'SAMPLEPHD', + GASBKPHD: 'GASBKPHD' +} diff --git a/src/views/spectrumAnalysis/components/Modals/LoadFromFileModal.vue b/src/views/spectrumAnalysis/components/Modals/LoadFromFileModal.vue index 8221959..9c28bdc 100644 --- a/src/views/spectrumAnalysis/components/Modals/LoadFromFileModal.vue +++ b/src/views/spectrumAnalysis/components/Modals/LoadFromFileModal.vue @@ -1,7 +1,68 @@ @@ -61,6 +122,7 @@ @@ -140,10 +202,12 @@