refactor: 重写PHD解析方法以适配内容各异的文件

This commit is contained in:
Xu Zhimeng 2023-10-09 19:10:06 +08:00
parent a06362f23d
commit 36ba4a8167
3 changed files with 169 additions and 86 deletions

View File

@ -37,6 +37,7 @@ export const showSaveFileModal = (data, ext) => {
* 读文件
* @param {File} file
* @param { 'arrayBuffer' | 'text' | 'dataURL' | 'binaryString'} fileType
* @returns {Promise<string | ArrayBuffer}
*/
export const readFile = (file, fileType = 'text') => {
return new Promise((resolve, reject) => {
@ -59,15 +60,23 @@ export const readFile = (file, fileType = 'text') => {
/**
* 压缩文件
* @param {Array<File>} fileList
* @param {string} zipName
* @returns
* @param {Array<File>} fileList
* @param {string} zipName
* @returns
*/
export const zipFile = async (fileList, zipName) => {
const zip = new JSZip()
const promises = []
const readFileWithName = async file => {
const data = await readFile(file, 'arrayBuffer')
return {
fileName: file.name,
data
}
}
fileList.forEach(file => {
promises.push(readFile(file, 'arrayBuffer'))
promises.push(readFileWithName(file))
})
const result = await Promise.all(promises)
result.forEach(res => {

View File

@ -1,4 +1,30 @@
/**
* PHD 类型
*/
export const PHD_DATA_TYPE = {
QCPHD: 'QCPHD',
DETBKPHD: 'DETBKPHD',
SAMPLEPHD: 'SAMPLEPHD',
GASBKPHD: 'GASBKPHD'
}
/**
* 判断是不是sample
* @param {*} dataType
* @returns
*/
export const isSample = dataType => {
return ['SAMPLEPHD', 'SPHDP', 'SPHDF'].includes(dataType)
}
export class PHDParser {
/**
* 根据Block解析出的结果集
*/
blocks = {
baseInfo: []
}
/**
* 数据类型
*/
@ -30,47 +56,97 @@ export class PHDParser {
*/
otherFilePrefixes = []
/**
* 该文件是不是sample
*/
isSample = false
/**
* 构造函数
* @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.splitByBlock(text)
this.dataType = this.getBaseInfoByTag('DATA_TYPE')[0]
this.isSample = isSample(this.dataType)
this.dataType = this.getOnymousData(dataTypeLine)[0]
const fileType = this.splitLineText(fileTypeLine)
this.fileType = fileType[2]
this.qualify = fileType[4]
const headerInfo = this.getBlockInfo('Header')
const headerInfoLine1 = this.splitLineText(headerInfo[0])
this.fileType = headerInfoLine1[2]
this.qualify = headerInfoLine1[4]
const liveTime = parseFloat(this.splitLineText(liveTimeLine)[3]).toFixed(1)
const liveTime = parseFloat(this.getBlockStr('Acquisition', 0, 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
}
// 如果解析的是sample 文件,则解析相关联的文件
if (this.isSample) {
const filePrefixes = this.getFilePrefixes(headerInfo[2])
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]
splitByBlock(text) {
const lines = (text = text.replace(/\r{0,1}\n/g, '\n').split('\n'))
let blockType = 'baseInfo'
for (const line of lines) {
// 如果以#开头
if (line.startsWith('#')) {
blockType = line.slice(1)
if (blockType.startsWith('Header')) {
blockType = 'Header'
}
this.blocks[blockType] = []
continue
}
this.blocks[blockType].push(line.trim())
}
}
/**
* 根据块名拿到块内容
* @param {string} blockName
* @returns {Array<string>}
*/
getBlockInfo(blockName) {
return this.blocks[blockName]
}
/**
* 在baseInfo中根据tag查找值
* @param {*} tag
* @returns {Array<string>}
*/
getBaseInfoByTag(tag) {
const baseInfo = this.getBlockInfo('baseInfo')
const map = new Map()
baseInfo.forEach(line => {
if (line.startsWith(tag)) {
map.set(tag, this.getOnymousData(line))
}
})
return map.get(tag)
}
/**
* 根据行号和位置在block中查找字符
* @param {string} blockName
* @param {number} lineNum
* @param {number} index
* @returns {string}
*/
getBlockStr(blockName, lineNum, index) {
const blockInfo = this.getBlockInfo(blockName)
const lineText = blockInfo[lineNum]
const splited = this.splitLineText(lineText)
return splited[index]
}
/**
* 获取 具名 行的数据
* @param {string} text
@ -98,19 +174,9 @@ export class PHDParser {
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')
filePrefix = filePrefix.replace(/(\d{4})\/(\d{2})\/(\d{2})-(\d{2}):(\d{2})(:\d{2}\.\d)?/, '$1$2$3_$4$5')
return filePrefix + '_'
})
return filePrefixes
}
}
/**
* PHD 类型
*/
export const PHD_DATA_TYPE = {
QCPHD: 'QCPHD',
DETBKPHD: 'DETBKPHD',
SAMPLEPHD: 'SAMPLEPHD',
GASBKPHD: 'GASBKPHD'
}

View File

@ -205,7 +205,7 @@
import { getAction, postAction } from '../../../../api/manage'
import { FilePicker } from '@/utils/FilePicker'
import { readFile, zipFile } from '@/utils/file'
import { PHDParser, PHD_DATA_TYPE } from '@/utils/phdHelper'
import { isSample, PHDParser, PHD_DATA_TYPE } from '@/utils/phdHelper'
import ModalMixin from '@/mixins/ModalMixin'
const columns = [
@ -417,57 +417,66 @@ export default {
fileName: `${sampleFilePrefix}S_${qualify}_${liveTime}.PHD`,
}
const iter = await this.directoryHanlder.values()
const fileList = []
// Beta Gamma
if (phdParser.fileType == 'B') {
const iter = await this.directoryHanlder.values()
const fileList = []
let result = await iter.next()
while (!result.done) {
const fileHandle = result.value
const file = await fileHandle.getFile()
fileList.push(file)
result = await iter.next()
}
let result = await iter.next()
while (!result.done) {
const fileHandle = result.value
const file = await fileHandle.getFile()
fileList.push(file)
result = await iter.next()
}
const nameKeys = ['detFileName', 'gasFileName']
const fileTypes = ['D', 'G']
const nameKeys = ['detFileName', 'gasFileName']
const fileTypes = ['D', 'G']
otherFilePrefixes.forEach((otherFilePrefix, index) => {
const fileType = fileTypes[index]
// sample
const findFile = fileList.find((file) => {
return file.name.includes(`${otherFilePrefix}${fileType}_${qualify}`)
otherFilePrefixes.forEach((otherFilePrefix, index) => {
const fileType = fileTypes[index]
// sample
const findFile = fileList.find((file) => {
return file.name.includes(`${otherFilePrefix}${fileType}_${qualify}`)
})
if (findFile) {
record[nameKeys[index]] = {
file: findFile,
fileName: findFile.name,
}
} else {
record[nameKeys[index]] = {
file: undefined,
fileName: `${otherFilePrefix}${fileType}.PHD`,
}
}
})
if (findFile) {
record[nameKeys[index]] = {
file: findFile,
fileName: findFile.name,
}
} else {
record[nameKeys[index]] = {
file: undefined,
fileName: `${otherFilePrefix}${fileType}.PHD`,
// QC
let qcFileInfo = {
file: undefined,
fileName: `${sampleFilePrefix}Q.PHD`,
}
const qcFileList = fileList.filter((file) => file.name.includes('_Q_'))
for (const qcFile of qcFileList) {
if (qcFile.name.slice(0, 23) <= sampleFilePrefix) {
qcFileInfo = {
file: qcFile,
fileName: qcFile.name,
}
} else {
break
}
}
})
// QC
let qcFileInfo = {
file: undefined,
fileName: `${sampleFilePrefix}Q.PHD`,
record.qcFileName = qcFileInfo
} else {
Object.assign(record, {
gasFileName: undefined,
detFileName: undefined,
qcFileName: undefined,
})
}
const qcFileList = fileList.filter((file) => file.name.includes('_Q_'))
for (const qcFile of qcFileList) {
if (qcFile.name.slice(0, 23) <= sampleFilePrefix) {
qcFileInfo = {
file: qcFile,
fileName: qcFile.name,
}
} else {
break
}
}
record.qcFileName = qcFileInfo
}
// sample
else {
@ -491,8 +500,7 @@ export default {
let currDataType = ''
switch (column) {
case 'sampleFileName':
currDataType = PHD_DATA_TYPE.SAMPLEPHD
break
return isSample(dataType)
case 'gasFileName':
currDataType = PHD_DATA_TYPE.GASBKPHD
break
@ -628,7 +636,7 @@ export default {
}
})
}
if(!files.length) {
if (!files.length) {
this.$message.warn('File is Empty ')
return
}