From 85f4ccb9959b0959c96c8991e2b1b31a790a9a14 Mon Sep 17 00:00:00 2001 From: Xu Zhimeng Date: Sat, 7 Oct 2023 19:12:42 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat:=20=E5=A2=9E=E5=8A=A0Load=20From=20Fil?= =?UTF-8?q?e=E8=B0=83=E7=94=A8File=20System=20Access=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/FilePicker.js | 56 +++++ src/utils/file.js | 24 ++ src/utils/phdHelper.js | 117 +++++++++ .../components/Modals/LoadFromFileModal.vue | 226 ++++++++++++++++-- 4 files changed, 408 insertions(+), 15 deletions(-) create mode 100644 src/utils/FilePicker.js create mode 100644 src/utils/phdHelper.js diff --git a/src/utils/FilePicker.js b/src/utils/FilePicker.js new file mode 100644 index 0000000..46b2b15 --- /dev/null +++ b/src/utils/FilePicker.js @@ -0,0 +1,56 @@ +/** + * 本地文件选择 + */ +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) { + return false + } else { + return true + } + } +} diff --git a/src/utils/file.js b/src/utils/file.js index 60c4ac9..ce06fef 100644 --- a/src/utils/file.js +++ b/src/utils/file.js @@ -31,3 +31,27 @@ 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) + } + }) +} diff --git a/src/utils/phdHelper.js b/src/utils/phdHelper.js new file mode 100644 index 0000000..e5629a4 --- /dev/null +++ b/src/utils/phdHelper.js @@ -0,0 +1,117 @@ +export class PHDParser { + /** + * 数据类型 + */ + dataType = '' + + /** + * 类型 B G 等 + */ + fileType = '' + + /** + * 质量 FULL 等 + */ + qualify = '' + + /** + * 生存时间 + */ + + liveTime = '' + + /** + * sample 谱的文件名 + */ + sampleFileName = '' + + /** + * 其他文件名 + */ + otherFileNames = [] + + /** + * 构造函数 + * @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 fileNames = this.getFileNames(fileNameLine) + this.sampleFileName = fileNames.splice(0, 1)[0] + this.otherFileNames = fileNames + } + } + } + /** + * 将文本按行分割 + * @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 + */ + getFileNames(text) { + const unHandledfileNames = this.splitLineText(text) + const fileTypes = ['S', 'D', 'G'] + const fileNames = unHandledfileNames + .filter(fileName => fileName) + .map((fileName, index) => { + fileName = fileName.replace(/(\d{4})\/(\d{2})\/(\d{2})-(\d{2}):(\d{2})/, '$1$2$3_$4$5') + return `${fileName}_${fileTypes[index]}_${this.qualify}` + }) + return fileNames + } +} + +/** + * 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..766dbe1 100644 --- a/src/views/spectrumAnalysis/components/Modals/LoadFromFileModal.vue +++ b/src/views/spectrumAnalysis/components/Modals/LoadFromFileModal.vue @@ -1,7 +1,67 @@ @@ -141,9 +201,12 @@