code refactor

This commit is contained in:
MaysWind
2025-06-22 22:27:45 +08:00
parent a69db9d299
commit dfa573b49b
2 changed files with 64 additions and 29 deletions
+36
View File
@@ -1,3 +1,39 @@
export class KnownFileType {
private static readonly allInstancesByExtension: Record<string, KnownFileType> = {};
public static readonly CSV = new KnownFileType('csv', 'text/csv');
public static readonly TSV = new KnownFileType('tsv', 'text/tab-separated-values');
public static readonly MARKDOWN = new KnownFileType('md', 'text/markdown');
public readonly extension: string;
public readonly contentType: string;
private constructor(extension: string, contentType: string) {
this.extension = extension;
this.contentType = contentType;
KnownFileType.allInstancesByExtension[extension] = this;
}
public formatFileName(fileName: string): string {
if (fileName.endsWith(`.${this.extension}`)) {
return fileName;
}
return `${fileName}.${this.extension}`;
}
public createBlob(content: string): Blob {
return new Blob([content], {
type: this.contentType,
});
}
public static parse(extension: string): KnownFileType | undefined {
return KnownFileType.allInstancesByExtension[extension];
}
}
export interface ImportFileTypeAndExtensions {
readonly type: string;
readonly extensions?: string;
@@ -12,17 +12,17 @@
<v-list>
<v-list-subheader :title="tt('File Format')"/>
<v-list-item :prepend-icon="mdiComma"
:append-icon="fileFormat === 'csv' ? mdiCheck : undefined"
:append-icon="fileFormat === KnownFileType.CSV.extension ? mdiCheck : undefined"
:title="tt('CSV (Comma-separated values) File')"
@click="fileFormat = 'csv'"></v-list-item>
@click="fileFormat = KnownFileType.CSV.extension"></v-list-item>
<v-list-item :prepend-icon="mdiKeyboardTab"
:append-icon="fileFormat === 'tsv' ? mdiCheck : undefined"
:append-icon="fileFormat === KnownFileType.TSV.extension ? mdiCheck : undefined"
:title="tt('TSV (Tab-separated values) File')"
@click="fileFormat = 'tsv'"></v-list-item>
@click="fileFormat = KnownFileType.TSV.extension"></v-list-item>
<v-list-item :prepend-icon="mdiLanguageMarkdownOutline"
:append-icon="fileFormat === 'md' ? mdiCheck : undefined"
:append-icon="fileFormat === KnownFileType.MARKDOWN.extension ? mdiCheck : undefined"
:title="tt('Markdown File')"
@click="fileFormat = 'md'"></v-list-item>
@click="fileFormat = KnownFileType.MARKDOWN.extension"></v-list-item>
</v-list>
</v-menu>
</v-btn>
@@ -91,6 +91,7 @@ import { useI18n } from '@/locales/helpers.ts';
import { useUserStore } from '@/stores/user.ts';
import { KnownFileType } from '@/core/file.ts';
import { replaceAll } from '@/lib/common.ts';
import { copyTextToClipboard, startDownloadFile } from '@/lib/ui/common.ts';
@@ -115,9 +116,21 @@ const snackbar = useTemplateRef<SnackBarType>('snackbar');
const showState = ref<boolean>(false);
const headers = ref<string[]>([]);
const data = ref<string[][]>([]);
const fileFormat = ref<string>('csv');
const fileFormat = ref<string>(KnownFileType.CSV.extension);
const showRawData = ref<boolean>(false);
const fileName = computed<string>(() => {
const nickname = userStore.currentUserNickname;
if (nickname) {
return tt('dataExport.exportStatisticsFileName', {
nickname: nickname
});
}
return tt('dataExport.defaultExportStatisticsFileName');
});
const dataTableHeaders = computed<object[]>(() => {
return headers.value.map((header, index) => ({
key: index.toString(),
@@ -143,10 +156,10 @@ const dataTableItems = computed<object[]>(() => {
const exportedData = computed<string>(() => {
let ret = '';
if (fileFormat.value === 'csv' || fileFormat.value === 'tsv') {
if (fileFormat.value === KnownFileType.CSV.extension || fileFormat.value === KnownFileType.TSV.extension) {
let separator = ',';
if (fileFormat.value === 'tsv') {
if (fileFormat.value === KnownFileType.TSV.extension) {
separator = '\t';
}
@@ -158,7 +171,7 @@ const exportedData = computed<string>(() => {
ret += '\n';
ret += row.map(item => replaceAll(item, separator, ' ')).join(separator);
}
} else if (fileFormat.value === 'md') {
} else if (fileFormat.value === KnownFileType.MARKDOWN.extension) {
ret += '| ' + headers.value.map(item => replaceAll(item, '|', ' ')).join(' | ') + ' |';
ret += '\n';
ret += '| ' + headers.value.map(() => '---').join(' | ') + ' |';
@@ -173,22 +186,10 @@ const exportedData = computed<string>(() => {
return ret;
});
function getExportFileName(fileExtension: string): string {
const nickname = userStore.currentUserNickname;
if (nickname) {
return tt('dataExport.exportStatisticsFileName', {
nickname: nickname
}) + '.' + fileExtension;
}
return tt('dataExport.defaultExportStatisticsFileName') + '.' + fileExtension;
}
function open(options: { headers: string[], data: string[][] }): void {
headers.value = options.headers || [];
data.value = options.data || [];
fileFormat.value = 'csv';
fileFormat.value = KnownFileType.CSV.extension;
showRawData.value = false;
showState.value = true;
}
@@ -199,15 +200,13 @@ function copy(): void {
}
function save(): void {
let contentType = 'text/csv';
let fileType = KnownFileType.parse(fileFormat.value);
if (fileFormat.value === 'tsv') {
contentType = 'text/tab-separated-values';
} else if (fileFormat.value === 'md') {
contentType = 'text/markdown';
if (!fileType) {
fileType = KnownFileType.CSV;
}
startDownloadFile(getExportFileName(fileFormat.value), new Blob([exportedData.value], { type: contentType }));
startDownloadFile(fileType.formatFileName(fileName.value), fileType.createBlob(exportedData.value));
}
function cancel(): void {