优化
This commit is contained in:
@@ -21,6 +21,19 @@ export interface MaterialTypeQuery {
|
||||
}
|
||||
export interface MaterialTypePageQuery extends MaterialTypeQuery, PageQuery {}
|
||||
|
||||
export interface MaterialTypeImportResp {
|
||||
importKey: string
|
||||
totalRows: number
|
||||
validRows: number
|
||||
duplicateNameRows: number
|
||||
}
|
||||
|
||||
export interface MaterialTypeImportResult {
|
||||
insertRows: number
|
||||
updateRows: number
|
||||
totalRows: number
|
||||
}
|
||||
|
||||
/** @desc 查询物料品类列表 */
|
||||
export function listMaterialType(query: MaterialTypePageQuery) {
|
||||
return http.get<PageRes<MaterialTypeResp[]>>(`${BASE_URL}`, query)
|
||||
@@ -50,3 +63,18 @@ export function deleteMaterialType(id: string) {
|
||||
export function exportMaterialType(query: MaterialTypeQuery) {
|
||||
return http.download(`${BASE_URL}/export`, query)
|
||||
}
|
||||
|
||||
/** @desc 下载物料品类导入模板 */
|
||||
export function downloadMaterialTypeImportTemplate() {
|
||||
return http.download(`${BASE_URL}/importTemplate`)
|
||||
}
|
||||
|
||||
/** @desc 解析物料品类导入数据 */
|
||||
export function parseImportMaterialType(data: FormData) {
|
||||
return http.post<MaterialTypeImportResp>(`${BASE_URL}/parseImport`, data)
|
||||
}
|
||||
|
||||
/** @desc 导入物料品类 */
|
||||
export function importMaterialType(data: any) {
|
||||
return http.post<MaterialTypeImportResult>(`${BASE_URL}/import`, data)
|
||||
}
|
||||
|
||||
179
src/views/materialType/MaterialTypeImportDrawer.vue
Normal file
179
src/views/materialType/MaterialTypeImportDrawer.vue
Normal file
@@ -0,0 +1,179 @@
|
||||
<template>
|
||||
<a-drawer
|
||||
v-model:visible="visible"
|
||||
title="导入物料品类"
|
||||
:mask-closable="false"
|
||||
:esc-to-close="false"
|
||||
:width="width >= 600 ? 600 : '100%'"
|
||||
ok-text="确认导入"
|
||||
cancel-text="取消导入"
|
||||
@before-ok="save"
|
||||
@close="reset"
|
||||
>
|
||||
<a-form ref="formRef" :model="form" size="large" auto-label-width>
|
||||
<a-alert v-if="!form.disabled" style="margin-bottom: 15px">
|
||||
请按照模板要求填写数据,填写完毕后,请先上传并进行解析。
|
||||
<template #action>
|
||||
<a-link @click="downloadTemplate">
|
||||
<template #icon><GiSvgIcon name="file-excel" :size="16" /></template>
|
||||
<template #default>下载模板</template>
|
||||
</a-link>
|
||||
</template>
|
||||
</a-alert>
|
||||
<fieldset>
|
||||
<legend>1.解析数据</legend>
|
||||
<div class="file-box">
|
||||
<a-upload
|
||||
draggable
|
||||
:custom-request="handleUpload"
|
||||
:limit="1"
|
||||
:show-retry-butto="false"
|
||||
:show-cancel-button="false" tip="仅支持xls、xlsx格式"
|
||||
:file-list="uploadFile"
|
||||
accept=".xls, .xlsx, application/vnd.ms-excel, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
||||
/>
|
||||
</div>
|
||||
<div v-if="dataResult.importKey">
|
||||
<div class="file-box">
|
||||
<a-space size="large">
|
||||
<a-statistic title="总计行数" :value="dataResult.totalRows" />
|
||||
<a-statistic title="正常行数" :value="dataResult.validRows" />
|
||||
</a-space>
|
||||
</div>
|
||||
<div class="file-box">
|
||||
<a-space size="large">
|
||||
<a-statistic title="已存在品类名" :value="dataResult.duplicateNameRows" />
|
||||
</a-space>
|
||||
</div>
|
||||
</div>
|
||||
</fieldset>
|
||||
<fieldset>
|
||||
<legend>2.导入策略</legend>
|
||||
<a-form-item label="品类名已存在" field="duplicateTypeName">
|
||||
<a-radio-group v-model="form.duplicateTypeName" type="button">
|
||||
<a-radio :value="1">跳过该行</a-radio>
|
||||
<a-radio :value="2">修改数据</a-radio>
|
||||
<a-radio :value="3">停止导入</a-radio>
|
||||
</a-radio-group>
|
||||
</a-form-item>
|
||||
</fieldset>
|
||||
</a-form>
|
||||
</a-drawer>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { type FormInstance, Message, type RequestOption } from '@arco-design/web-vue'
|
||||
import { useWindowSize } from '@vueuse/core'
|
||||
import {
|
||||
type MaterialTypeImportResp,
|
||||
downloadMaterialTypeImportTemplate,
|
||||
importMaterialType,
|
||||
parseImportMaterialType,
|
||||
} from '@/apis/materialType/materialType'
|
||||
import { useDownload, useResetReactive } from '@/hooks'
|
||||
|
||||
const emit = defineEmits<{
|
||||
(e: 'save-success'): void
|
||||
}>()
|
||||
|
||||
const { width } = useWindowSize()
|
||||
|
||||
const visible = ref(false)
|
||||
const formRef = ref<FormInstance>()
|
||||
const uploadFile = ref([])
|
||||
|
||||
const [form, resetForm] = useResetReactive({
|
||||
importKey: '',
|
||||
duplicateTypeName: 1,
|
||||
})
|
||||
|
||||
const dataResult = ref<MaterialTypeImportResp>({
|
||||
importKey: '',
|
||||
totalRows: 0,
|
||||
validRows: 0,
|
||||
duplicateNameRows: 0,
|
||||
})
|
||||
|
||||
// 重置
|
||||
const reset = () => {
|
||||
formRef.value?.resetFields()
|
||||
dataResult.value.importKey = ''
|
||||
uploadFile.value = []
|
||||
resetForm()
|
||||
}
|
||||
|
||||
// 下载模板
|
||||
const downloadTemplate = () => {
|
||||
useDownload(() => downloadMaterialTypeImportTemplate())
|
||||
}
|
||||
|
||||
// 上传解析导入数据
|
||||
const handleUpload = (options: RequestOption) => {
|
||||
const controller = new AbortController();
|
||||
(async function requestWrap() {
|
||||
const { onProgress, onError, onSuccess, fileItem, name = 'file' } = options
|
||||
onProgress(20)
|
||||
const formData = new FormData()
|
||||
formData.append(name as string, fileItem.file as Blob)
|
||||
try {
|
||||
const res = await parseImportMaterialType(formData)
|
||||
dataResult.value = res.data
|
||||
Message.success('上传解析成功')
|
||||
onSuccess(res)
|
||||
} catch (error) {
|
||||
onError(error)
|
||||
}
|
||||
})()
|
||||
return {
|
||||
abort() {
|
||||
controller.abort()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// 执行导入
|
||||
const save = async () => {
|
||||
try {
|
||||
if (!dataResult.value.importKey) {
|
||||
Message.warning('请先上传文件,解析导入数据')
|
||||
return false
|
||||
}
|
||||
form.importKey = dataResult.value.importKey
|
||||
const res = await importMaterialType(form)
|
||||
Message.success(`导入成功! 新增${res.data.insertRows}, 修改${res.data.updateRows},总计处理${res.data.totalRows}`)
|
||||
emit('save-success')
|
||||
return true
|
||||
} catch (error) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// 打开
|
||||
const onOpen = () => {
|
||||
reset()
|
||||
visible.value = true
|
||||
}
|
||||
|
||||
defineExpose({ onOpen })
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
fieldset {
|
||||
padding: 15px 15px 0 15px;
|
||||
margin-bottom: 15px;
|
||||
border: 1px solid var(--color-neutral-3);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
fieldset legend {
|
||||
color: rgb(var(--gray-10));
|
||||
padding: 2px 5px 2px 5px;
|
||||
border: 1px solid var(--color-neutral-3);
|
||||
border-radius: 3px;
|
||||
}
|
||||
|
||||
.file-box {
|
||||
margin-bottom: 20px;
|
||||
margin-left: 10px;
|
||||
}
|
||||
</style>
|
||||
@@ -28,6 +28,10 @@
|
||||
<template #icon><icon-plus /></template>
|
||||
<template #default>新增</template>
|
||||
</a-button>
|
||||
<a-button v-permission="['materialType:materialType:import']" @click="onImport">
|
||||
<template #icon><icon-upload /></template>
|
||||
<template #default>导入</template>
|
||||
</a-button>
|
||||
<a-button v-permission="['materialType:materialType:export']" @click="onExport">
|
||||
<template #icon><icon-download /></template>
|
||||
<template #default>导出</template>
|
||||
@@ -53,12 +57,14 @@
|
||||
</GiTable>
|
||||
|
||||
<MaterialTypeAddModal ref="MaterialTypeAddModalRef" @save-success="search" />
|
||||
<MaterialTypeImportDrawer ref="MaterialTypeImportDrawerRef" @save-success="search" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { h } from 'vue'
|
||||
import MaterialTypeAddModal from './MaterialTypeAddModal.vue'
|
||||
import MaterialTypeImportDrawer from './MaterialTypeImportDrawer.vue'
|
||||
import { type MaterialTypeResp, type MaterialTypeQuery, deleteMaterialType, exportMaterialType, listMaterialType } from '@/apis/materialType/materialType'
|
||||
import type { TableInstanceColumns } from '@/components/GiTable/type'
|
||||
import { useDownload, useTable } from '@/hooks'
|
||||
@@ -138,6 +144,8 @@ const onExport = () => {
|
||||
}
|
||||
|
||||
const MaterialTypeAddModalRef = ref<InstanceType<typeof MaterialTypeAddModal>>()
|
||||
const MaterialTypeImportDrawerRef = ref<InstanceType<typeof MaterialTypeImportDrawer>>()
|
||||
|
||||
// 新增
|
||||
const onAdd = () => {
|
||||
MaterialTypeAddModalRef.value?.onAdd()
|
||||
@@ -148,6 +156,11 @@ const onUpdate = (record: MaterialTypeResp) => {
|
||||
MaterialTypeAddModalRef.value?.onUpdate(record)
|
||||
}
|
||||
|
||||
// 导入
|
||||
const onImport = () => {
|
||||
MaterialTypeImportDrawerRef.value?.onOpen()
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
Reference in New Issue
Block a user