feat: import prodect from file
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 6s
Some checks failed
Spell Check / Spell Check with Typos (push) Failing after 6s
This commit is contained in:
parent
74291c0552
commit
8d8ad40de1
3 changed files with 70 additions and 6 deletions
|
|
@ -1,8 +1,10 @@
|
|||
<script lang="ts" setup>
|
||||
import { ref } from 'vue';
|
||||
import MainButton from './MainButton.vue';
|
||||
|
||||
defineEmits<{
|
||||
const emit = defineEmits<{
|
||||
(e: 'click', v: MouseEvent): void;
|
||||
(e: 'fileSelected', v: File[]): void;
|
||||
}>();
|
||||
defineProps<{
|
||||
iconOnly?: boolean;
|
||||
|
|
@ -10,15 +12,29 @@ defineProps<{
|
|||
outlined?: boolean;
|
||||
disabled?: boolean;
|
||||
dark?: boolean;
|
||||
importFile?: boolean;
|
||||
|
||||
label?: string;
|
||||
icon?: string;
|
||||
}>();
|
||||
|
||||
const inputRef = ref<HTMLInputElement | null>(null);
|
||||
|
||||
function triggerFileInput() {
|
||||
inputRef.value?.click();
|
||||
}
|
||||
|
||||
function handleFileChange(event: Event) {
|
||||
const files = (event.target as HTMLInputElement).files;
|
||||
if (files && files.length > 0) {
|
||||
emit('fileSelected', Array.from(files));
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<MainButton
|
||||
@click="(e) => $emit('click', e)"
|
||||
@click="(e) => (importFile ? triggerFileInput() : $emit('click', e))"
|
||||
v-bind="{ ...$props, ...$attrs }"
|
||||
:icon="icon || 'mdi-import'"
|
||||
color="var(--info-bg)"
|
||||
|
|
@ -26,4 +42,13 @@ defineProps<{
|
|||
>
|
||||
{{ label || $t('general.import') }}
|
||||
</MainButton>
|
||||
|
||||
<input
|
||||
ref="inputRef"
|
||||
type="file"
|
||||
@change="(e) => handleFileChange(e)"
|
||||
hidden
|
||||
accept=".xls, .xlsx , .csv"
|
||||
multiple
|
||||
/>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ import {
|
|||
UndoButton,
|
||||
ToggleButton,
|
||||
PasteButton,
|
||||
ImportButton,
|
||||
} from 'components/button';
|
||||
import TableProduct from 'src/components/04_product-service/TableProduct.vue';
|
||||
import PaginationPageSize from 'src/components/PaginationPageSize.vue';
|
||||
|
|
@ -99,6 +100,8 @@ const {
|
|||
createWork,
|
||||
editWork,
|
||||
deleteWork,
|
||||
|
||||
importProduct,
|
||||
} = productServiceStore;
|
||||
|
||||
const currentCopy = ref<{
|
||||
|
|
@ -107,6 +110,7 @@ const currentCopy = ref<{
|
|||
}>();
|
||||
const { workNameItems } = storeToRefs(productServiceStore);
|
||||
const allStat = ref<{ mode: string; count: number }[]>([]);
|
||||
|
||||
const stat = ref<
|
||||
{
|
||||
icon: string;
|
||||
|
|
@ -2262,7 +2266,6 @@ watch(
|
|||
},
|
||||
]"
|
||||
></q-select>
|
||||
|
||||
<q-select
|
||||
v-if="modeView === false"
|
||||
id="select-field"
|
||||
|
|
@ -2285,7 +2288,6 @@ watch(
|
|||
multiple
|
||||
dense
|
||||
/>
|
||||
|
||||
<q-btn-toggle
|
||||
v-model="modeView"
|
||||
id="btn-mode"
|
||||
|
|
@ -2760,6 +2762,26 @@ watch(
|
|||
</AdvanceSearch>
|
||||
</template>
|
||||
</q-input>
|
||||
<div
|
||||
class="flex q-mr-auto q-pl-sm"
|
||||
v-if="productAndServiceTab === 'product'"
|
||||
>
|
||||
<input ref="fileImport" type="file" hidden />
|
||||
<ImportButton
|
||||
type="file"
|
||||
import-file
|
||||
icon-only
|
||||
@file-selected="
|
||||
(file) => {
|
||||
importProduct(
|
||||
currentIdGroup,
|
||||
file,
|
||||
async () => await fetchListOfProduct(),
|
||||
);
|
||||
}
|
||||
"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="row col-md-6" style="white-space: nowrap">
|
||||
<q-select
|
||||
|
|
@ -2785,7 +2807,6 @@ watch(
|
|||
]"
|
||||
@update:model-value="fetchStatus()"
|
||||
></q-select>
|
||||
|
||||
<q-select
|
||||
v-if="modeView === false"
|
||||
:hide-dropdown-icon="$q.screen.lt.sm"
|
||||
|
|
@ -2820,7 +2841,6 @@ watch(
|
|||
multiple
|
||||
dense
|
||||
/>
|
||||
|
||||
<q-btn-toggle
|
||||
v-model="modeView"
|
||||
id="btn-mode"
|
||||
|
|
|
|||
|
|
@ -194,6 +194,23 @@ const useProductServiceStore = defineStore('api-product-service', () => {
|
|||
return false;
|
||||
}
|
||||
|
||||
async function importProduct(
|
||||
productGroupId: string,
|
||||
files: File[],
|
||||
fetch: (...args: unknown[]) => void,
|
||||
) {
|
||||
const importTasks = files.map((f) => {
|
||||
const formData = new FormData();
|
||||
formData.append('file', f);
|
||||
return api.post('/product/import-product', formData, {
|
||||
params: { productGroupId },
|
||||
});
|
||||
});
|
||||
|
||||
await Promise.all(importTasks);
|
||||
fetch?.();
|
||||
}
|
||||
|
||||
async function fetchListProductById(productId: string) {
|
||||
const res = await api.get<Product>(`/product/${productId}`);
|
||||
|
||||
|
|
@ -549,6 +566,8 @@ const useProductServiceStore = defineStore('api-product-service', () => {
|
|||
fetchImageListById,
|
||||
addImageList,
|
||||
deleteImageByName,
|
||||
|
||||
importProduct,
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue