| | |
| | | <ArtTableHeader v-model:columns="columnChecks" :loading="loading" @refresh="refreshData"> |
| | | <template #left> |
| | | <ElSpace wrap> |
| | | <ElButton v-if="canCreate" type="primary" @click="showDialog('add')" v-ripple>{{ t('pages.orders.transfer.actions.add') }}</ElButton> |
| | | <ElButton v-if="canCreate" type="primary" @click="showDialog('add')" v-ripple>{{ |
| | | t('pages.orders.transfer.actions.add') |
| | | }}</ElButton> |
| | | <ElButton |
| | | v-if="canDelete" |
| | | type="danger" |
| | |
| | | :transfer-data="currentTransferData" |
| | | :type-options="typeOptions" |
| | | :area-options="areaOptions" |
| | | :field-definitions="fieldDefinitions" |
| | | :submit-loading="dialogSubmitting" |
| | | @submit="handleDialogSubmit" |
| | | /> |
| | |
| | | :detail="detailData" |
| | | :order-rows="detailOrderRows" |
| | | :order-pagination="detailOrderPagination" |
| | | :on-order-view="handleViewRelatedOrder" |
| | | @size-change="handleDetailSizeChange" |
| | | @current-change="handleDetailCurrentChange" |
| | | /> |
| | |
| | | import { guardRequestWithMessage } from '@/utils/sys/requestGuard' |
| | | import { fetchDictDataPage } from '@/api/system-manage' |
| | | import { fetchWarehouseAreasList } from '@/api/warehouse-areas' |
| | | import { fetchTransferItemList } from '@/api/transfer-item' |
| | | import { |
| | | fetchDeleteTransfer, |
| | | fetchEnabledTransferFields, |
| | | fetchExportTransferReport, |
| | | fetchTransferDetail, |
| | | fetchTransferMany, |
| | | fetchSaveTransferItems, |
| | | fetchTransferOrdersPage, |
| | | fetchTransferPage, |
| | | fetchTransferPubOutStock, |
| | | fetchSaveTransfer, |
| | | fetchUpdateTransfer |
| | | fetchUpdateTransferItems |
| | | } from '@/api/transfer' |
| | | import TransferDialog from './modules/transfer-dialog.vue' |
| | | import TransferDetailDrawer from './modules/transfer-detail-drawer.vue' |
| | |
| | | import { |
| | | TRANSFER_REPORT_STYLE, |
| | | buildTransferDetailOrderQueryParams, |
| | | buildTransferDialogModel, |
| | | buildTransferItemsSavePayload, |
| | | buildTransferManageDialogModel, |
| | | buildTransferPageQueryParams, |
| | | buildTransferPrintRows, |
| | | buildTransferReportMeta, |
| | | buildTransferSavePayload, |
| | | buildTransferSearchParams, |
| | | createTransferFormState, |
| | | createTransferSearchState, |
| | |
| | | const searchForm = ref(createTransferSearchState()) |
| | | const typeOptions = ref([]) |
| | | const areaOptions = ref([]) |
| | | const fieldDefinitions = ref([]) |
| | | const selectedRows = ref([]) |
| | | const detailDrawerVisible = ref(false) |
| | | const detailLoading = ref(false) |
| | |
| | | |
| | | const reportQueryParams = computed(() => buildTransferSearchParams(searchForm.value)) |
| | | const searchItems = computed(() => [ |
| | | { label: t('pages.orders.transfer.search.condition'), key: 'condition', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.condition') } }, |
| | | { label: t('pages.orders.transfer.search.code'), key: 'code', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.code') } }, |
| | | { |
| | | label: t('pages.orders.transfer.search.condition'), |
| | | key: 'condition', |
| | | type: 'input', |
| | | props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.condition') } |
| | | }, |
| | | { |
| | | label: t('pages.orders.transfer.search.code'), |
| | | key: 'code', |
| | | type: 'input', |
| | | props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.code') } |
| | | }, |
| | | { |
| | | label: t('pages.orders.transfer.search.type'), |
| | | key: 'type', |
| | |
| | | type: 'select', |
| | | props: { clearable: true, options: getTransferExceStatusOptions(t) } |
| | | }, |
| | | { label: t('pages.orders.transfer.search.orgWareName'), key: 'orgWareName', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.orgWareName') } }, |
| | | { label: t('pages.orders.transfer.search.tarWareName'), key: 'tarWareName', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.tarWareName') } }, |
| | | { label: t('pages.orders.transfer.search.orgAreaName'), key: 'orgAreaName', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.orgAreaName') } }, |
| | | { label: t('pages.orders.transfer.search.tarAreaName'), key: 'tarAreaName', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.tarAreaName') } }, |
| | | { |
| | | label: t('pages.orders.transfer.search.timeStart'), |
| | | key: 'timeStart', |
| | | type: 'date', |
| | | props: { clearable: true, type: 'date', valueFormat: 'YYYY-MM-DD' } |
| | | }, |
| | | { |
| | | label: t('pages.orders.transfer.search.timeEnd'), |
| | | key: 'timeEnd', |
| | | type: 'date', |
| | | props: { clearable: true, type: 'date', valueFormat: 'YYYY-MM-DD' } |
| | | }, |
| | | { |
| | | label: t('pages.orders.transfer.search.orgWareId'), |
| | | key: 'orgWareId', |
| | | type: 'inputNumber', |
| | | props: { |
| | | clearable: true, |
| | | controlsPosition: 'right', |
| | | placeholder: t('pages.orders.transfer.placeholder.orgWareId') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.orders.transfer.search.orgWareName'), |
| | | key: 'orgWareName', |
| | | type: 'input', |
| | | props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.orgWareName') } |
| | | }, |
| | | { |
| | | label: t('pages.orders.transfer.search.tarWareId'), |
| | | key: 'tarWareId', |
| | | type: 'inputNumber', |
| | | props: { |
| | | clearable: true, |
| | | controlsPosition: 'right', |
| | | placeholder: t('pages.orders.transfer.placeholder.tarWareId') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.orders.transfer.search.tarWareName'), |
| | | key: 'tarWareName', |
| | | type: 'input', |
| | | props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.tarWareName') } |
| | | }, |
| | | { |
| | | label: t('pages.orders.transfer.search.orgAreaId'), |
| | | key: 'orgAreaId', |
| | | type: 'inputNumber', |
| | | props: { |
| | | clearable: true, |
| | | controlsPosition: 'right', |
| | | placeholder: t('pages.orders.transfer.placeholder.orgAreaId') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.orders.transfer.search.orgAreaName'), |
| | | key: 'orgAreaName', |
| | | type: 'input', |
| | | props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.orgAreaName') } |
| | | }, |
| | | { |
| | | label: t('pages.orders.transfer.search.tarAreaId'), |
| | | key: 'tarAreaId', |
| | | type: 'inputNumber', |
| | | props: { |
| | | clearable: true, |
| | | controlsPosition: 'right', |
| | | placeholder: t('pages.orders.transfer.placeholder.tarAreaId') |
| | | } |
| | | }, |
| | | { |
| | | label: t('pages.orders.transfer.search.tarAreaName'), |
| | | key: 'tarAreaName', |
| | | type: 'input', |
| | | props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.tarAreaName') } |
| | | }, |
| | | { |
| | | label: t('pages.orders.transfer.search.status'), |
| | | key: 'status', |
| | | type: 'select', |
| | | props: { clearable: true, options: getTransferStatusOptions(t) } |
| | | }, |
| | | { label: t('pages.orders.transfer.search.memo'), key: 'memo', type: 'input', props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.memo') } } |
| | | { |
| | | label: t('pages.orders.transfer.search.memo'), |
| | | key: 'memo', |
| | | type: 'input', |
| | | props: { clearable: true, placeholder: t('pages.orders.transfer.placeholder.memo') } |
| | | } |
| | | ]) |
| | | |
| | | function handleSelectionChange(rows) { |
| | |
| | | } |
| | | } |
| | | |
| | | async function loadTransferOrders(code) { |
| | | async function loadTransferOrders(transferId, code) { |
| | | detailOrdersLoading.value = true |
| | | try { |
| | | const response = await guardRequestWithMessage( |
| | | fetchTransferOrdersPage( |
| | | buildTransferDetailOrderQueryParams({ |
| | | id: transferId, |
| | | code, |
| | | current: detailOrderPagination.current, |
| | | pageSize: detailOrderPagination.size |
| | | }) |
| | | ), |
| | | { records: [], total: 0, current: detailOrderPagination.current, size: detailOrderPagination.size }, |
| | | { |
| | | records: [], |
| | | total: 0, |
| | | current: detailOrderPagination.current, |
| | | size: detailOrderPagination.size |
| | | }, |
| | | { timeoutMessage: t('pages.orders.transfer.messages.ordersTimeout') } |
| | | ) |
| | | const normalized = defaultResponseAdapter(response) |
| | | detailOrderRows.value = normalized.records.map((item) => normalizeTransferOrderRow(item, t)) |
| | | detailOrderPagination.total = Number(normalized.total || 0) |
| | | detailOrderPagination.current = Number(normalized.current || detailOrderPagination.current || 1) |
| | | detailOrderPagination.current = Number( |
| | | normalized.current || detailOrderPagination.current || 1 |
| | | ) |
| | | detailOrderPagination.size = Number(normalized.size || detailOrderPagination.size || 20) |
| | | } catch (error) { |
| | | detailOrderRows.value = [] |
| | |
| | | try { |
| | | await loadTransferDetail(row.id) |
| | | activeTransferCode.value = detailData.value.code || row.code || activeTransferCode.value |
| | | await loadTransferOrders(activeTransferCode.value) |
| | | await loadTransferOrders(row.id, activeTransferCode.value) |
| | | } catch (error) { |
| | | detailDrawerVisible.value = false |
| | | detailData.value = {} |
| | |
| | | |
| | | async function openEditDialog(row) { |
| | | try { |
| | | const detail = await guardRequestWithMessage( |
| | | fetchTransferDetail(row.id), |
| | | {}, |
| | | { timeoutMessage: t('pages.orders.transfer.messages.detailTimeout') } |
| | | ) |
| | | showDialog('edit', detail) |
| | | const [detail, itemResponse] = await Promise.all([ |
| | | guardRequestWithMessage( |
| | | fetchTransferDetail(row.id), |
| | | {}, |
| | | { timeoutMessage: t('pages.orders.transfer.messages.detailTimeout') } |
| | | ), |
| | | guardRequestWithMessage(fetchTransferItemList({ transferId: row.id }), [], { |
| | | timeoutMessage: t('pages.orders.transfer.messages.itemsTimeout') |
| | | }) |
| | | ]) |
| | | const itemRecords = Array.isArray(itemResponse) |
| | | ? itemResponse |
| | | : defaultResponseAdapter(itemResponse).records |
| | | showDialog('edit', { |
| | | transfer: detail, |
| | | items: itemRecords |
| | | }) |
| | | } catch (error) { |
| | | ElMessage.error(error?.message || t('pages.orders.transfer.messages.detailLoadFailed')) |
| | | } |
| | |
| | | |
| | | async function handlePublish(row) { |
| | | try { |
| | | await ElMessageBox.confirm(t('pages.orders.transfer.messages.publishConfirm', { code: row.code || row.id }), t('pages.orders.transfer.messages.publishTitle'), { |
| | | confirmButtonText: t('common.confirm'), |
| | | cancelButtonText: t('common.cancel'), |
| | | type: 'warning' |
| | | }) |
| | | const response = await fetchTransferPubOutStock({ id: row.id }) |
| | | if (response?.code !== 200 && response?.success !== true) { |
| | | throw new Error(response?.message || t('pages.orders.transfer.messages.publishFailed')) |
| | | } |
| | | ElMessage.success(response?.message || t('pages.orders.transfer.messages.publishSuccess')) |
| | | await ElMessageBox.confirm( |
| | | t('pages.orders.transfer.messages.publishConfirm', { code: row.code || row.id }), |
| | | t('pages.orders.transfer.messages.publishTitle'), |
| | | { |
| | | confirmButtonText: t('common.confirm'), |
| | | cancelButtonText: t('common.cancel'), |
| | | type: 'warning' |
| | | } |
| | | ) |
| | | await fetchTransferPubOutStock({ id: row.id }) |
| | | ElMessage.success(t('pages.orders.transfer.messages.publishSuccess')) |
| | | await refreshData() |
| | | if (detailDrawerVisible.value && activeTransferId.value === row.id) { |
| | | await loadTransferDetail(row.id) |
| | | await loadTransferOrders(row.code || activeTransferCode.value) |
| | | await loadTransferOrders(row.id, row.code || activeTransferCode.value) |
| | | } |
| | | router.push('/orders/out-stock') |
| | | } catch (error) { |
| | | if (error === 'cancel' || error?.message === 'cancel') return |
| | | ElMessage.error(error?.message || t('pages.orders.transfer.messages.publishFailed')) |
| | |
| | | apiFn: fetchTransferPage, |
| | | apiParams: buildTransferPageQueryParams(searchForm.value), |
| | | paginationKey: getTransferPaginationKey(), |
| | | columnsFactory: () => createTransferTableColumns({ handleActionClick }) |
| | | columnsFactory: () => |
| | | createTransferTableColumns({ |
| | | handleActionClick, |
| | | handleViewOrder: handleViewRelatedOrder |
| | | }) |
| | | }, |
| | | transform: { |
| | | dataTransformer: (records) => (Array.isArray(records) ? records.map((item) => normalizeTransferRow(item, t)) : []) |
| | | dataTransformer: (records) => |
| | | Array.isArray(records) ? records.map((item) => normalizeTransferRow(item, t)) : [] |
| | | } |
| | | }) |
| | | |
| | |
| | | dialogVisible, |
| | | dialogType, |
| | | currentRecord: currentTransferData, |
| | | selectedRows: crudSelectedRows, |
| | | handleSelectionChange: handleCrudSelectionChange, |
| | | showDialog, |
| | | handleDialogSubmit: handleCrudDialogSubmit, |
| | | handleDelete, |
| | | handleBatchDelete |
| | | } = useCrudPage({ |
| | | createEmptyModel: () => createTransferFormState(), |
| | | buildEditModel: (record) => buildTransferDialogModel(record), |
| | | buildSavePayload: (formData) => buildTransferSavePayload(formData, areaOptions.value), |
| | | saveRequest: fetchSaveTransfer, |
| | | updateRequest: fetchUpdateTransfer, |
| | | createEmptyModel: () => ({ |
| | | transfer: createTransferFormState(), |
| | | items: [] |
| | | }), |
| | | buildEditModel: (record) => buildTransferManageDialogModel(record, fieldDefinitions.value), |
| | | buildSavePayload: (formData) => |
| | | buildTransferItemsSavePayload(formData, areaOptions.value, fieldDefinitions.value), |
| | | saveRequest: fetchSaveTransferItems, |
| | | updateRequest: fetchUpdateTransferItems, |
| | | deleteRequest: fetchDeleteTransfer, |
| | | entityName: t('pages.orders.transfer.entity'), |
| | | resolveRecordLabel: (record) => record?.code || record?.id, |
| | |
| | | |
| | | async function loadTypeOptions() { |
| | | const response = await guardRequestWithMessage( |
| | | fetchDictDataPage({ current: 1, pageSize: 200, dictTypeCode: 'sys_transfer_type', status: 1 }), |
| | | fetchDictDataPage({ |
| | | current: 1, |
| | | pageSize: 200, |
| | | dictTypeCode: 'sys_transfer_type', |
| | | status: 1 |
| | | }), |
| | | { records: [] }, |
| | | { timeoutMessage: t('pages.orders.transfer.messages.typeOptionsTimeout') } |
| | | ) |
| | |
| | | areaOptions.value = resolveTransferAreaOptions(defaultResponseAdapter(response).records) |
| | | } |
| | | |
| | | async function loadFieldDefinitions() { |
| | | const records = await guardRequestWithMessage(fetchEnabledTransferFields(), [], { |
| | | timeoutMessage: t('pages.orders.transfer.messages.fieldTimeout') |
| | | }) |
| | | fieldDefinitions.value = Array.isArray(records) ? records : [] |
| | | } |
| | | |
| | | function handleViewRelatedOrder(row) { |
| | | if (row?.type === 'out') { |
| | | router.push('/orders/out-stock') |
| | | return |
| | | } |
| | | if (row?.type === 'in') { |
| | | router.push('/orders/asn-order') |
| | | } |
| | | } |
| | | |
| | | function handleSearch(params) { |
| | | searchForm.value = { ...searchForm.value, ...params } |
| | | replaceSearchParams(buildTransferSearchParams(searchForm.value)) |
| | |
| | | |
| | | async function handleDetailCurrentChange(current) { |
| | | detailOrderPagination.current = current |
| | | await loadTransferOrders(activeTransferCode.value) |
| | | await loadTransferOrders(activeTransferId.value, activeTransferCode.value) |
| | | } |
| | | |
| | | async function handleDetailSizeChange(size) { |
| | | detailOrderPagination.size = size |
| | | detailOrderPagination.current = 1 |
| | | await loadTransferOrders(activeTransferCode.value) |
| | | await loadTransferOrders(activeTransferId.value, activeTransferCode.value) |
| | | } |
| | | |
| | | const resolvePrintRecords = async (payload) => { |
| | |
| | | await fetchTransferPage({ |
| | | ...reportQueryParams.value, |
| | | current: 1, |
| | | pageSize: Number(pagination.total) > 0 ? Number(pagination.total) : Number(payload?.pageSize) || 20 |
| | | pageSize: |
| | | Number(pagination.total) > 0 ? Number(pagination.total) : Number(payload?.pageSize) || 20 |
| | | }) |
| | | ).records |
| | | } |
| | |
| | | } = usePrintExportPage({ |
| | | downloadFileName: 'transfer.xlsx', |
| | | requestExport: (payload) => |
| | | fetchExportTransferReport(Array.isArray(payload?.ids) && payload.ids.length > 0 ? reportQueryParams.value : payload, { |
| | | headers: { |
| | | Authorization: userStore.accessToken || '' |
| | | fetchExportTransferReport( |
| | | Array.isArray(payload?.ids) && payload.ids.length > 0 ? reportQueryParams.value : payload, |
| | | { |
| | | headers: { |
| | | Authorization: userStore.accessToken || '' |
| | | } |
| | | } |
| | | }), |
| | | ), |
| | | resolvePrintRecords, |
| | | buildPreviewRows: (records) => buildTransferPrintRows(records, t), |
| | | buildPreviewMeta: (rows) => { |
| | |
| | | buildTransferReportMeta({ |
| | | previewMeta: rawPreviewMeta.value, |
| | | count: previewRows.value.length, |
| | | orientation: rawPreviewMeta.value?.reportStyle?.orientation || TRANSFER_REPORT_STYLE.orientation, |
| | | orientation: |
| | | rawPreviewMeta.value?.reportStyle?.orientation || TRANSFER_REPORT_STYLE.orientation, |
| | | t |
| | | }) |
| | | ) |
| | | |
| | | onMounted(async () => { |
| | | await Promise.allSettled([loadTypeOptions(), loadAreaOptions()]) |
| | | await Promise.allSettled([loadTypeOptions(), loadAreaOptions(), loadFieldDefinitions()]) |
| | | }) |
| | | </script> |