feat(wms):新增出库管理
parent
765c8ea94f
commit
b3b35e147b
|
|
@ -0,0 +1,25 @@
|
|||
// WMS 出库单明细 VO
|
||||
export interface ShipmentOrderDetailVO {
|
||||
id?: number
|
||||
orderId?: number
|
||||
itemId?: number
|
||||
itemCode?: string
|
||||
itemName?: string
|
||||
unit?: string
|
||||
skuId?: number
|
||||
skuCode?: string
|
||||
skuName?: string
|
||||
inventoryDetailId?: number
|
||||
warehouseId?: number
|
||||
warehouseName?: string
|
||||
areaId?: number
|
||||
areaName?: string
|
||||
batchNo?: string
|
||||
productionDate?: Date
|
||||
expirationDate?: Date
|
||||
quantity?: number
|
||||
availableQuantity?: number
|
||||
amount?: number
|
||||
remark?: string
|
||||
createTime?: Date
|
||||
}
|
||||
|
|
@ -0,0 +1,77 @@
|
|||
import request from '@/config/axios'
|
||||
import { ShipmentOrderDetailVO } from './detail'
|
||||
|
||||
// WMS 出库单 VO
|
||||
export interface ShipmentOrderVO {
|
||||
id?: number
|
||||
no?: string
|
||||
type?: number
|
||||
status?: number
|
||||
bizOrderNo?: string
|
||||
merchantId?: number
|
||||
merchantName?: string
|
||||
remark?: string
|
||||
warehouseId?: number
|
||||
warehouseName?: string
|
||||
areaId?: number
|
||||
areaName?: string
|
||||
totalQuantity?: number
|
||||
totalAmount?: number
|
||||
details?: ShipmentOrderDetailVO[]
|
||||
createTime?: Date
|
||||
creator?: string
|
||||
creatorName?: string
|
||||
updateTime?: Date
|
||||
updater?: string
|
||||
updaterName?: string
|
||||
}
|
||||
|
||||
// WMS 出库单 API
|
||||
export const ShipmentOrderApi = {
|
||||
// 查询出库单分页
|
||||
getShipmentOrderPage: async (params: any) => {
|
||||
return await request.get({ url: '/wms/shipment-order/page', params })
|
||||
},
|
||||
|
||||
// 查询出库单详情
|
||||
getShipmentOrder: async (id: number) => {
|
||||
return await request.get({ url: '/wms/shipment-order/get?id=' + id })
|
||||
},
|
||||
|
||||
// 查询出库单明细
|
||||
getShipmentOrderDetailListByOrderId: async (orderId: number) => {
|
||||
return await request.get({
|
||||
url: '/wms/shipment-order-detail/list-by-order-id?orderId=' + orderId
|
||||
})
|
||||
},
|
||||
|
||||
// 新增出库单
|
||||
createShipmentOrder: async (data: ShipmentOrderVO) => {
|
||||
return await request.post({ url: '/wms/shipment-order/create', data })
|
||||
},
|
||||
|
||||
// 修改出库单
|
||||
updateShipmentOrder: async (data: ShipmentOrderVO) => {
|
||||
return await request.put({ url: '/wms/shipment-order/update', data })
|
||||
},
|
||||
|
||||
// 完成出库
|
||||
completeShipmentOrder: async (id: number) => {
|
||||
return await request.put({ url: '/wms/shipment-order/complete?id=' + id })
|
||||
},
|
||||
|
||||
// 作废出库单
|
||||
cancelShipmentOrder: async (id: number) => {
|
||||
return await request.put({ url: '/wms/shipment-order/cancel?id=' + id })
|
||||
},
|
||||
|
||||
// 删除出库单
|
||||
deleteShipmentOrder: async (id: number) => {
|
||||
return await request.delete({ url: '/wms/shipment-order/delete?id=' + id })
|
||||
},
|
||||
|
||||
// 导出出库单
|
||||
exportShipmentOrder: async (params: any) => {
|
||||
return await request.download({ url: '/wms/shipment-order/export-excel', params })
|
||||
}
|
||||
}
|
||||
|
|
@ -221,6 +221,7 @@ export enum DICT_TYPE {
|
|||
WMS_INVENTORY_HISTORY_TYPE = 'wms_inventory_history_type', // WMS 库存记录类型
|
||||
WMS_ORDER_STATUS = 'wms_order_status', // WMS 单据状态
|
||||
WMS_RECEIPT_ORDER_TYPE = 'wms_receipt_order_type', // WMS 入库单类型
|
||||
WMS_SHIPMENT_ORDER_TYPE = 'wms_shipment_order_type', // WMS 出库单类型
|
||||
|
||||
// ========== AI - 人工智能模块 ==========
|
||||
AI_PLATFORM = 'ai_platform', // AI 平台
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
|
||||
<script lang="ts" setup>
|
||||
import { MerchantApi, MerchantVO } from '@/api/wms/md/merchant'
|
||||
import { SupplierMerchantTypeList } from '@/views/wms/utils/constants'
|
||||
import { CustomerMerchantTypeList, SupplierMerchantTypeList } from '@/views/wms/utils/constants'
|
||||
|
||||
/** WMS 往来企业选择器 */
|
||||
defineOptions({ name: 'WmsMerchantSelect', inheritAttrs: false })
|
||||
|
|
@ -31,6 +31,7 @@ const props = withDefaults(
|
|||
defineProps<{
|
||||
modelValue?: number
|
||||
supplier?: boolean
|
||||
customer?: boolean
|
||||
disabled?: boolean
|
||||
clearable?: boolean
|
||||
placeholder?: string
|
||||
|
|
@ -57,9 +58,12 @@ const selectValue = computed({
|
|||
|
||||
/** 获得可选往来企业列表 */
|
||||
const loadSelectableList = async () => {
|
||||
merchantList.value = await MerchantApi.getMerchantSimpleList(
|
||||
props.supplier ? { types: SupplierMerchantTypeList } : undefined
|
||||
)
|
||||
const types = props.supplier
|
||||
? SupplierMerchantTypeList
|
||||
: props.customer
|
||||
? CustomerMerchantTypeList
|
||||
: undefined
|
||||
merchantList.value = await MerchantApi.getMerchantSimpleList(types ? { types } : undefined)
|
||||
handleFilter('')
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +89,7 @@ const handleChange = (value: number | undefined) => {
|
|||
|
||||
/** 供应商开关变化时,重新加载可选列表 */
|
||||
watch(
|
||||
() => props.supplier,
|
||||
() => [props.supplier, props.customer],
|
||||
() => loadSelectableList()
|
||||
)
|
||||
|
||||
|
|
|
|||
|
|
@ -73,17 +73,31 @@
|
|||
</el-col>
|
||||
<el-col :span="AREA_ENABLE ? 8 : 16">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input v-model="formData.remark" maxlength="255" placeholder="请输入备注" />
|
||||
<el-input
|
||||
v-model="formData.remark"
|
||||
maxlength="255"
|
||||
placeholder="请输入备注"
|
||||
:rows="3"
|
||||
type="textarea"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="mb-12px flex items-center justify-between">
|
||||
<span class="text-14px font-bold">入库明细</span>
|
||||
<el-button :disabled="!formData.warehouseId" plain type="primary" @click="handleAddDetail">
|
||||
<Icon class="mr-5px" icon="ep:plus" />
|
||||
添加商品
|
||||
</el-button>
|
||||
<el-tooltip
|
||||
content="请先选择仓库"
|
||||
:disabled="!!formData.warehouseId"
|
||||
placement="top"
|
||||
>
|
||||
<span>
|
||||
<el-button :disabled="!formData.warehouseId" plain type="primary" @click="handleAddDetail">
|
||||
<Icon class="mr-5px" icon="ep:plus" />
|
||||
添加商品
|
||||
</el-button>
|
||||
</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<el-table :data="formData.details" border empty-text="暂无商品明细">
|
||||
<el-table-column label="商品信息" min-width="220">
|
||||
|
|
@ -221,7 +235,7 @@ import MerchantSelect from '@/views/wms/md/merchant/components/MerchantSelect.vu
|
|||
import WarehouseAreaSelect from '@/views/wms/md/warehouse/components/WarehouseAreaSelect.vue'
|
||||
import WarehouseSelect from '@/views/wms/md/warehouse/components/WarehouseSelect.vue'
|
||||
import { AREA_ENABLE, BATCH_ENABLE } from '@/views/wms/utils/config'
|
||||
import { OrderStatusEnum } from '@/views/wms/utils/constants'
|
||||
import { OrderStatusEnum, OrderUpdateStatusList } from '@/views/wms/utils/constants'
|
||||
import {
|
||||
formatQuantity,
|
||||
PRICE_PRECISION,
|
||||
|
|
@ -267,10 +281,15 @@ const skuSelectRef = ref() // 商品 SKU 选择弹窗 Ref
|
|||
const totalQuantity = computed(() => sumQuantity(formData.value.details || [], (detail) => detail.quantity))
|
||||
const detailTotalAmount = computed(() => sumPrice(formData.value.details || [], (detail) => detail.amount))
|
||||
const isPrepareOrder = computed(
|
||||
() => !formData.value.id || formData.value.status === OrderStatusEnum.PREPARE
|
||||
() =>
|
||||
!formData.value.id ||
|
||||
(formData.value.status !== undefined && OrderUpdateStatusList.includes(formData.value.status))
|
||||
)
|
||||
const isSavedPrepareOrder = computed(
|
||||
() => !!formData.value.id && formData.value.status === OrderStatusEnum.PREPARE
|
||||
() =>
|
||||
!!formData.value.id &&
|
||||
formData.value.status !== undefined &&
|
||||
OrderUpdateStatusList.includes(formData.value.status)
|
||||
)
|
||||
|
||||
/** 打开弹窗 */
|
||||
|
|
|
|||
|
|
@ -275,7 +275,7 @@
|
|||
</el-table>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="isTableColumnVisible('no')" fixed="left" label="单号/业务单号" width="210">
|
||||
<el-table-column v-if="isTableColumnVisible('no')" fixed="left" label="单号/业务单号" width="290">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
单号:
|
||||
|
|
@ -346,34 +346,55 @@
|
|||
min-width="160"
|
||||
prop="merchantName"
|
||||
/>
|
||||
<el-table-column
|
||||
v-if="isTableColumnVisible('operateTime')"
|
||||
label="操作时间"
|
||||
min-width="160"
|
||||
>
|
||||
<el-table-column v-if="isTableColumnVisible('operateInfo')" label="操作信息" min-width="280">
|
||||
<template #default="scope">
|
||||
<div>创建:{{ formatNullableDate(scope.row.createTime, 'MM-DD HH:mm') }}</div>
|
||||
<div>更新:{{ formatNullableDate(scope.row.updateTime, 'MM-DD HH:mm') }}</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="isTableColumnVisible('operator')" label="操作人" min-width="120">
|
||||
<template #default="scope">
|
||||
<div>创建:{{ scope.row.creatorName || scope.row.creator || '-' }}</div>
|
||||
<div>更新:{{ scope.row.updaterName || scope.row.updater || '-' }}</div>
|
||||
<div>
|
||||
创建:{{ formatNullableDate(scope.row.createTime) }} /
|
||||
{{ scope.row.creatorName || scope.row.creator || '-' }}
|
||||
</div>
|
||||
<div>
|
||||
更新:{{ formatNullableDate(scope.row.updateTime) }} /
|
||||
{{ scope.row.updaterName || scope.row.updater || '-' }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="isTableColumnVisible('remark')" label="备注" min-width="160" prop="remark" />
|
||||
<el-table-column align="center" fixed="right" label="操作" width="180">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
v-if="scope.row.status === OrderStatusEnum.PREPARE"
|
||||
v-hasPermi="['wms:receipt-order:update']"
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
<el-tooltip
|
||||
:content="getReceiptOrderUpdateTip(scope.row.status)"
|
||||
:disabled="canUpdateReceiptOrder(scope.row.status)"
|
||||
placement="top"
|
||||
>
|
||||
修改
|
||||
</el-button>
|
||||
<span>
|
||||
<el-button
|
||||
v-hasPermi="['wms:receipt-order:update']"
|
||||
:disabled="!canUpdateReceiptOrder(scope.row.status)"
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
>
|
||||
修改
|
||||
</el-button>
|
||||
</span>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
:content="getReceiptOrderDeleteTip(scope.row.status)"
|
||||
:disabled="canDeleteReceiptOrder(scope.row.status)"
|
||||
placement="top"
|
||||
>
|
||||
<span>
|
||||
<el-button
|
||||
v-hasPermi="['wms:receipt-order:delete']"
|
||||
:disabled="!canDeleteReceiptOrder(scope.row.status)"
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</span>
|
||||
</el-tooltip>
|
||||
<el-button
|
||||
v-hasPermi="['wms:receipt-order:query']"
|
||||
link
|
||||
|
|
@ -382,15 +403,6 @@
|
|||
>
|
||||
打印
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="canDeleteReceiptOrder(scope.row.status)"
|
||||
v-hasPermi="['wms:receipt-order:delete']"
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
|
@ -417,7 +429,11 @@ import { ReceiptOrderDetailVO } from '@/api/wms/order/receipt/detail'
|
|||
import MerchantSelect from '@/views/wms/md/merchant/components/MerchantSelect.vue'
|
||||
import WarehouseSelect from '@/views/wms/md/warehouse/components/WarehouseSelect.vue'
|
||||
import { AREA_ENABLE, BATCH_ENABLE } from '@/views/wms/utils/config'
|
||||
import { OrderStatusEnum } from '@/views/wms/utils/constants'
|
||||
import {
|
||||
OrderDeleteStatusList,
|
||||
OrderStatusEnum,
|
||||
OrderUpdateStatusList
|
||||
} from '@/views/wms/utils/constants'
|
||||
import { formatPrice, formatQuantity, PRICE_PRECISION, QUANTITY_PRECISION } from '@/views/wms/utils/format'
|
||||
import UserSelectV2 from '@/views/system/user/components/UserSelectV2.vue'
|
||||
import ReceiptOrderDetail from './ReceiptOrderDetail.vue'
|
||||
|
|
@ -438,8 +454,7 @@ type TableColumnKey =
|
|||
| 'warehouse'
|
||||
| 'quantityAmount'
|
||||
| 'merchant'
|
||||
| 'operateTime'
|
||||
| 'operator'
|
||||
| 'operateInfo'
|
||||
| 'remark'
|
||||
|
||||
const tableColumnOptions: Array<{ label: string; value: TableColumnKey }> = [
|
||||
|
|
@ -449,8 +464,7 @@ const tableColumnOptions: Array<{ label: string; value: TableColumnKey }> = [
|
|||
{ label: '仓库', value: 'warehouse' },
|
||||
{ label: '数量/金额(元)', value: 'quantityAmount' },
|
||||
{ label: '供应商', value: 'merchant' },
|
||||
{ label: '操作时间', value: 'operateTime' },
|
||||
{ label: '操作人', value: 'operator' },
|
||||
{ label: '操作信息', value: 'operateInfo' },
|
||||
{ label: '备注', value: 'remark' }
|
||||
]
|
||||
const checkedTableColumns = ref<TableColumnKey[]>([
|
||||
|
|
@ -460,8 +474,7 @@ const checkedTableColumns = ref<TableColumnKey[]>([
|
|||
'warehouse',
|
||||
'quantityAmount',
|
||||
'merchant',
|
||||
'operateTime',
|
||||
'operator',
|
||||
'operateInfo',
|
||||
'remark'
|
||||
])
|
||||
const isTableColumnVisible = (column: TableColumnKey) => checkedTableColumns.value.includes(column)
|
||||
|
|
@ -493,9 +506,33 @@ const queryFormRef = ref() // 搜索的表单
|
|||
const exportLoading = ref(false) // 导出的加载中
|
||||
const detailMap = reactive<Record<number, ReceiptOrderDetailVO[]>>({}) // 入库单明细缓存
|
||||
|
||||
/** 是否允许修改入库单 */
|
||||
const canUpdateReceiptOrder = (status?: number) => {
|
||||
return status !== undefined && OrderUpdateStatusList.includes(status)
|
||||
}
|
||||
|
||||
/** 是否允许删除入库单 */
|
||||
const canDeleteReceiptOrder = (status?: number) => {
|
||||
return status !== undefined && [OrderStatusEnum.PREPARE, OrderStatusEnum.CANCELED].includes(status)
|
||||
return status !== undefined && OrderDeleteStatusList.includes(status)
|
||||
}
|
||||
|
||||
/** 获得入库单修改禁用提示 */
|
||||
const getReceiptOrderUpdateTip = (status?: number) => {
|
||||
if (status === OrderStatusEnum.FINISHED) {
|
||||
return '已入库,无法修改'
|
||||
}
|
||||
if (status === OrderStatusEnum.CANCELED) {
|
||||
return '已作废,无法修改'
|
||||
}
|
||||
return '当前状态无法修改'
|
||||
}
|
||||
|
||||
/** 获得入库单删除禁用提示 */
|
||||
const getReceiptOrderDeleteTip = (status?: number) => {
|
||||
if (status === OrderStatusEnum.FINISHED) {
|
||||
return '已入库,无法删除'
|
||||
}
|
||||
return '当前状态无法删除'
|
||||
}
|
||||
|
||||
/** 查询入库单列表 */
|
||||
|
|
|
|||
|
|
@ -0,0 +1,168 @@
|
|||
<!-- WMS 出库单详情 -->
|
||||
<template>
|
||||
<Dialog v-model="dialogVisible" title="出库单详情" width="1200px">
|
||||
<div v-loading="loading">
|
||||
<div class="mb-16px text-18px font-bold">单据信息</div>
|
||||
<el-descriptions :column="2" border>
|
||||
<el-descriptions-item label="出库单号">{{ detailData.no || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="单据状态">
|
||||
<dict-tag
|
||||
v-if="detailData.status !== undefined"
|
||||
:type="DICT_TYPE.WMS_ORDER_STATUS"
|
||||
:value="detailData.status"
|
||||
/>
|
||||
<span v-else>-</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="出库类型">
|
||||
<dict-tag
|
||||
v-if="detailData.type !== undefined"
|
||||
:type="DICT_TYPE.WMS_SHIPMENT_ORDER_TYPE"
|
||||
:value="detailData.type"
|
||||
/>
|
||||
<span v-else>-</span>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="仓库">
|
||||
{{ detailData.warehouseName || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="客户">
|
||||
{{ detailData.merchantName || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="业务单号">
|
||||
{{ detailData.bizOrderNo || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item v-if="AREA_ENABLE" label="库区">
|
||||
{{ detailData.areaName || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="总数量">
|
||||
{{ formatQuantity(detailData.totalQuantity) || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="总金额">
|
||||
{{ formatPrice(detailData.totalAmount) || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="创建时间">
|
||||
{{ formatNullableDate(detailData.createTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="创建人">
|
||||
{{ detailData.creatorName || detailData.creator || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="更新时间">
|
||||
{{ formatNullableDate(detailData.updateTime) }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="更新人">
|
||||
{{ detailData.updaterName || detailData.updater || '-' }}
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item :span="2" label="备注">
|
||||
{{ detailData.remark || '-' }}
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
|
||||
<div class="mb-16px mt-24px text-18px font-bold">商品明细</div>
|
||||
<el-table :data="detailRows" :summary-method="getSummaries" border show-summary>
|
||||
<el-table-column label="商品名称" min-width="180" prop="itemName">
|
||||
<template #default="scope">
|
||||
<div>{{ scope.row.itemName || '-' }}</div>
|
||||
<div v-if="scope.row.itemCode" class="text-12px text-gray-500">
|
||||
商品编号:{{ scope.row.itemCode }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="规格名称" min-width="180" prop="skuName">
|
||||
<template #default="scope">
|
||||
<div>{{ scope.row.skuName || '-' }}</div>
|
||||
<div v-if="scope.row.skuCode" class="text-12px text-gray-500">
|
||||
规格编号:{{ scope.row.skuCode }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="AREA_ENABLE" label="库区" min-width="140" prop="areaName" />
|
||||
<el-table-column v-if="BATCH_ENABLE" label="批号" min-width="140" prop="batchNo" />
|
||||
<el-table-column v-if="BATCH_ENABLE" label="生产日期" width="140">
|
||||
<template #default="scope">
|
||||
{{ formatNullableDate(scope.row.productionDate, 'YYYY-MM-DD') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="BATCH_ENABLE" label="过期日期" width="140">
|
||||
<template #default="scope">
|
||||
{{ formatNullableDate(scope.row.expirationDate, 'YYYY-MM-DD') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="right" label="数量" prop="quantity" width="120">
|
||||
<template #default="scope">
|
||||
{{ formatQuantity(scope.row.quantity) || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="单位" prop="unit" width="100" />
|
||||
<el-table-column align="right" label="单价" prop="unitPrice" width="140">
|
||||
<template #default="scope">
|
||||
{{ formatPrice(scope.row.unitPrice) || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="right" label="总价" prop="amount" width="140">
|
||||
<template #default="scope">
|
||||
{{ formatPrice(scope.row.amount) || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { formatNullableDate } from '@/utils/formatTime'
|
||||
import { DICT_TYPE } from '@/utils/dict'
|
||||
import { ShipmentOrderApi, ShipmentOrderVO } from '@/api/wms/order/shipment'
|
||||
import { ShipmentOrderDetailVO } from '@/api/wms/order/shipment/detail'
|
||||
import { AREA_ENABLE, BATCH_ENABLE } from '@/views/wms/utils/config'
|
||||
import {
|
||||
formatPrice,
|
||||
formatQuantity,
|
||||
formatSumPrice,
|
||||
formatSumQuantity
|
||||
} from '@/views/wms/utils/format'
|
||||
|
||||
/** WMS 出库单详情 */
|
||||
defineOptions({ name: 'WmsShipmentOrderDetail' })
|
||||
|
||||
interface DetailRow extends ShipmentOrderDetailVO {
|
||||
unitPrice?: number
|
||||
}
|
||||
|
||||
const loading = ref(false) // 加载中
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const detailData = ref<ShipmentOrderVO>({}) // 详情数据
|
||||
const detailRows = computed<DetailRow[]>(() =>
|
||||
(detailData.value.details || []).map((detail) => ({
|
||||
...detail,
|
||||
unitPrice:
|
||||
detail.amount != null && detail.quantity
|
||||
? Number(detail.amount) / Number(detail.quantity)
|
||||
: undefined
|
||||
}))
|
||||
)
|
||||
|
||||
const getSummaries = ({ columns, data }: { columns: any[]; data: DetailRow[] }) =>
|
||||
columns.map((column, index) => {
|
||||
if (index === 0) {
|
||||
return '合计'
|
||||
}
|
||||
if (column.property === 'quantity') {
|
||||
return formatSumQuantity(data, (detail) => detail.quantity)
|
||||
}
|
||||
if (column.property === 'amount') {
|
||||
return formatSumPrice(data, (detail) => detail.amount)
|
||||
}
|
||||
return ''
|
||||
})
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (id: number) => {
|
||||
dialogVisible.value = true
|
||||
loading.value = true
|
||||
try {
|
||||
detailData.value = await ShipmentOrderApi.getShipmentOrder(id)
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
defineExpose({ open })
|
||||
</script>
|
||||
|
|
@ -0,0 +1,524 @@
|
|||
<!-- WMS 出库单表单 -->
|
||||
<template>
|
||||
<Dialog v-model="dialogVisible" :title="dialogTitle" width="1280px">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
v-loading="formLoading"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="92px"
|
||||
>
|
||||
<el-row :gutter="20">
|
||||
<el-col :span="8">
|
||||
<el-form-item label="出库单号" prop="no">
|
||||
<el-input v-model="formData.no" maxlength="64" placeholder="请输入出库单号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="出库类型" prop="type">
|
||||
<el-select v-model="formData.type" class="w-1/1" placeholder="请选择出库类型">
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.WMS_SHIPMENT_ORDER_TYPE)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="客户" prop="merchantId">
|
||||
<MerchantSelect
|
||||
v-model="formData.merchantId"
|
||||
placeholder="请选择客户"
|
||||
customer
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="业务单号" prop="bizOrderNo">
|
||||
<el-input v-model="formData.bizOrderNo" maxlength="64" placeholder="请输入业务单号" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="仓库" prop="warehouseId">
|
||||
<WarehouseSelect v-model="formData.warehouseId" @change="handleWarehouseChange" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-if="AREA_ENABLE" :span="8">
|
||||
<el-form-item label="库区" prop="areaId">
|
||||
<WarehouseAreaSelect
|
||||
v-model="formData.areaId"
|
||||
:warehouse-id="formData.warehouseId"
|
||||
@change="handleAreaChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="总数量">
|
||||
<el-input :model-value="formatQuantity(totalQuantity)" disabled />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="8">
|
||||
<el-form-item label="总金额">
|
||||
<el-input-number
|
||||
v-model="formData.totalAmount"
|
||||
:controls="false"
|
||||
:min="0"
|
||||
:precision="PRICE_PRECISION"
|
||||
class="!w-1/1"
|
||||
placeholder="请输入总金额"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col :span="AREA_ENABLE ? 8 : 16">
|
||||
<el-form-item label="备注" prop="remark">
|
||||
<el-input
|
||||
v-model="formData.remark"
|
||||
maxlength="255"
|
||||
placeholder="请输入备注"
|
||||
:rows="3"
|
||||
type="textarea"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
||||
<div class="mb-12px flex items-center justify-between">
|
||||
<span class="text-14px font-bold">出库明细</span>
|
||||
<el-tooltip
|
||||
content="请先选择仓库"
|
||||
:disabled="!!formData.warehouseId"
|
||||
placement="top"
|
||||
>
|
||||
<span>
|
||||
<el-button :disabled="!formData.warehouseId" plain type="primary" @click="handleAddDetail">
|
||||
<Icon class="mr-5px" icon="ep:plus" />
|
||||
添加商品
|
||||
</el-button>
|
||||
</span>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<el-table :data="formData.details" border empty-text="暂无商品明细">
|
||||
<el-table-column label="商品信息" min-width="220">
|
||||
<template #default="scope">
|
||||
<div>{{ scope.row.itemName || '-' }}</div>
|
||||
<div v-if="scope.row.itemCode" class="text-12px text-gray-500">
|
||||
商品编号:{{ scope.row.itemCode }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="规格信息" min-width="220">
|
||||
<template #default="scope">
|
||||
<div>{{ scope.row.skuName || '-' }}</div>
|
||||
<div v-if="scope.row.skuCode" class="text-12px text-gray-500">
|
||||
规格编号:{{ scope.row.skuCode }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="AREA_ENABLE" label="库区" min-width="140">
|
||||
<template #default="scope">
|
||||
{{ scope.row.areaName || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="BATCH_ENABLE" label="批号" min-width="160">
|
||||
<template #default="scope">
|
||||
{{ scope.row.batchNo || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="BATCH_ENABLE" label="生产日期" width="180">
|
||||
<template #default="scope">
|
||||
{{ formatNullableDate(scope.row.productionDate, 'YYYY-MM-DD') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="BATCH_ENABLE" label="过期日期" width="180">
|
||||
<template #default="scope">
|
||||
{{ formatNullableDate(scope.row.expirationDate, 'YYYY-MM-DD') }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="right" label="可用库存" width="120">
|
||||
<template #default="scope">
|
||||
{{ formatQuantity(scope.row.availableQuantity) || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="出库数量" width="160">
|
||||
<template #default="scope">
|
||||
<el-input-number
|
||||
v-model="scope.row.quantity"
|
||||
:controls="false"
|
||||
:min="0"
|
||||
:precision="QUANTITY_PRECISION"
|
||||
class="!w-1/1"
|
||||
placeholder="数量"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="金额(元)" width="160">
|
||||
<template #default="scope">
|
||||
<el-input-number
|
||||
v-model="scope.row.amount"
|
||||
:controls="false"
|
||||
:min="0"
|
||||
:precision="PRICE_PRECISION"
|
||||
class="!w-1/1"
|
||||
placeholder="金额"
|
||||
@change="handleDetailAmountChange"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" min-width="180">
|
||||
<template #default="scope">
|
||||
<el-input v-model="scope.row.remark" maxlength="255" placeholder="请输入备注" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="center" label="操作" width="80">
|
||||
<template #default="scope">
|
||||
<el-button link type="danger" @click="handleDeleteDetail(scope.$index)">删除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<InventorySelect
|
||||
ref="inventorySelectRef"
|
||||
:area-id="formData.areaId"
|
||||
:warehouse-id="formData.warehouseId"
|
||||
@change="handleSelectInventory"
|
||||
/>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<div class="flex items-center justify-between">
|
||||
<div>
|
||||
<el-button
|
||||
v-if="isSavedPrepareOrder"
|
||||
v-hasPermi="['wms:shipment-order:complete']"
|
||||
:disabled="formLoading"
|
||||
type="success"
|
||||
@click="handleComplete"
|
||||
>
|
||||
完成出库
|
||||
</el-button>
|
||||
<el-button
|
||||
v-if="isSavedPrepareOrder"
|
||||
v-hasPermi="['wms:shipment-order:cancel']"
|
||||
:disabled="formLoading"
|
||||
type="danger"
|
||||
@click="handleCancel"
|
||||
>
|
||||
作废
|
||||
</el-button>
|
||||
</div>
|
||||
<div>
|
||||
<el-button v-if="isPrepareOrder" :disabled="formLoading" type="primary" @click="submitForm">
|
||||
保存
|
||||
</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { FormRules } from 'element-plus'
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import { ShipmentOrderApi, ShipmentOrderVO } from '@/api/wms/order/shipment'
|
||||
import { ShipmentOrderDetailVO } from '@/api/wms/order/shipment/detail'
|
||||
import InventorySelect, {
|
||||
InventorySelectRow
|
||||
} from '@/views/wms/inventory/components/InventorySelect.vue'
|
||||
import MerchantSelect from '@/views/wms/md/merchant/components/MerchantSelect.vue'
|
||||
import WarehouseAreaSelect from '@/views/wms/md/warehouse/components/WarehouseAreaSelect.vue'
|
||||
import WarehouseSelect from '@/views/wms/md/warehouse/components/WarehouseSelect.vue'
|
||||
import { formatNullableDate } from '@/utils/formatTime'
|
||||
import { AREA_ENABLE, BATCH_ENABLE } from '@/views/wms/utils/config'
|
||||
import { OrderStatusEnum, OrderUpdateStatusList } from '@/views/wms/utils/constants'
|
||||
import {
|
||||
formatQuantity,
|
||||
PRICE_PRECISION,
|
||||
QUANTITY_PRECISION,
|
||||
sumPrice,
|
||||
sumQuantity
|
||||
} from '@/views/wms/utils/format'
|
||||
import { generateOrderNo } from '@/views/wms/utils/order'
|
||||
|
||||
/** WMS 出库单表单 */
|
||||
defineOptions({ name: 'WmsShipmentOrderForm' })
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const originalFormData = ref('') // 表单原始数据快照
|
||||
const formData = ref<ShipmentOrderVO>({
|
||||
id: undefined,
|
||||
no: undefined,
|
||||
type: undefined,
|
||||
status: OrderStatusEnum.PREPARE,
|
||||
bizOrderNo: undefined,
|
||||
merchantId: undefined,
|
||||
warehouseId: undefined,
|
||||
areaId: undefined,
|
||||
totalQuantity: 0,
|
||||
totalAmount: 0,
|
||||
remark: undefined,
|
||||
details: []
|
||||
})
|
||||
const formRules = reactive<FormRules>({
|
||||
no: [{ required: true, message: '出库单号不能为空', trigger: 'blur' }],
|
||||
type: [{ required: true, message: '出库类型不能为空', trigger: 'change' }],
|
||||
warehouseId: [{ required: true, message: '仓库不能为空', trigger: 'change' }]
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
const inventorySelectRef = ref() // 库存选择弹窗 Ref
|
||||
|
||||
const totalQuantity = computed(() => sumQuantity(formData.value.details || [], (detail) => detail.quantity))
|
||||
const detailTotalAmount = computed(() => sumPrice(formData.value.details || [], (detail) => detail.amount))
|
||||
const isPrepareOrder = computed(
|
||||
() =>
|
||||
!formData.value.id ||
|
||||
(formData.value.status !== undefined && OrderUpdateStatusList.includes(formData.value.status))
|
||||
)
|
||||
const isSavedPrepareOrder = computed(
|
||||
() =>
|
||||
!!formData.value.id &&
|
||||
formData.value.status !== undefined &&
|
||||
OrderUpdateStatusList.includes(formData.value.status)
|
||||
)
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
const order = await ShipmentOrderApi.getShipmentOrder(id)
|
||||
formData.value = {
|
||||
...order,
|
||||
details: order.details || []
|
||||
}
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
originalFormData.value = JSON.stringify(buildSubmitData())
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 构建出库明细 */
|
||||
const buildDetail = (inventory: InventorySelectRow): ShipmentOrderDetailVO => ({
|
||||
id: undefined,
|
||||
itemId: inventory.itemId,
|
||||
itemCode: inventory.itemCode,
|
||||
itemName: inventory.itemName,
|
||||
unit: inventory.unit,
|
||||
skuId: inventory.skuId,
|
||||
skuCode: inventory.skuCode,
|
||||
skuName: inventory.skuName,
|
||||
inventoryDetailId: inventory.inventoryDetailId,
|
||||
warehouseId: inventory.warehouseId,
|
||||
warehouseName: inventory.warehouseName,
|
||||
areaId: inventory.areaId,
|
||||
areaName: inventory.areaName,
|
||||
batchNo: inventory.batchNo,
|
||||
productionDate: inventory.productionDate,
|
||||
expirationDate: inventory.expirationDate,
|
||||
quantity: undefined,
|
||||
availableQuantity: inventory.availableQuantity,
|
||||
amount: undefined,
|
||||
remark: undefined
|
||||
})
|
||||
|
||||
/** 添加商品 */
|
||||
const handleAddDetail = () => {
|
||||
inventorySelectRef.value?.open()
|
||||
}
|
||||
|
||||
/** 选择库存 */
|
||||
const handleSelectInventory = (inventories: InventorySelectRow[]) => {
|
||||
if (!inventories.length) {
|
||||
return
|
||||
}
|
||||
formData.value.details = formData.value.details || []
|
||||
inventories.forEach((inventory) => {
|
||||
if (isInventorySelected(inventory)) {
|
||||
return
|
||||
}
|
||||
formData.value.details!.push(buildDetail(inventory))
|
||||
})
|
||||
refreshTotalAmount()
|
||||
}
|
||||
|
||||
/** 判断库存是否已选择 */
|
||||
const isInventorySelected = (inventory: InventorySelectRow) => {
|
||||
return (formData.value.details || []).some((detail) => {
|
||||
if (BATCH_ENABLE) {
|
||||
return detail.inventoryDetailId === inventory.inventoryDetailId
|
||||
}
|
||||
return (
|
||||
detail.skuId === inventory.skuId &&
|
||||
detail.warehouseId === inventory.warehouseId &&
|
||||
detail.areaId === inventory.areaId
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
/** 删除明细 */
|
||||
const handleDeleteDetail = (index: number) => {
|
||||
formData.value.details?.splice(index, 1)
|
||||
refreshTotalAmount()
|
||||
}
|
||||
|
||||
/** 仓库变化 */
|
||||
const handleWarehouseChange = () => {
|
||||
formData.value.areaId = undefined
|
||||
formData.value.details = []
|
||||
refreshTotalAmount()
|
||||
}
|
||||
|
||||
/** 库区变化 */
|
||||
const handleAreaChange = () => {
|
||||
formData.value.details = []
|
||||
refreshTotalAmount()
|
||||
}
|
||||
|
||||
/** 明细金额变化 */
|
||||
const handleDetailAmountChange = () => {
|
||||
refreshTotalAmount()
|
||||
}
|
||||
|
||||
/** 汇总明细金额 */
|
||||
const refreshTotalAmount = () => {
|
||||
formData.value.totalAmount = detailTotalAmount.value
|
||||
}
|
||||
|
||||
/** 校验明细 */
|
||||
const validateDetails = (required: boolean) => {
|
||||
if (!formData.value.details?.length) {
|
||||
if (required) {
|
||||
message.error('至少包含一条出库明细')
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
for (let i = 0; i < formData.value.details.length; i++) {
|
||||
const detail = formData.value.details[i]
|
||||
if (!detail.skuId) {
|
||||
message.error(`第 ${i + 1} 行明细请选择商品规格`)
|
||||
return false
|
||||
}
|
||||
if (AREA_ENABLE && !detail.areaId) {
|
||||
message.error(`第 ${i + 1} 行明细请选择库区`)
|
||||
return false
|
||||
}
|
||||
if (!detail.quantity || detail.quantity <= 0) {
|
||||
message.error(`第 ${i + 1} 行明细出库数量必须大于 0`)
|
||||
return false
|
||||
}
|
||||
if (detail.availableQuantity !== undefined && detail.quantity > detail.availableQuantity) {
|
||||
message.error(`第 ${i + 1} 行明细出库数量不能大于可用库存`)
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/** 构建提交数据 */
|
||||
const buildSubmitData = () =>
|
||||
({
|
||||
...formData.value,
|
||||
totalQuantity: totalQuantity.value,
|
||||
totalAmount: formData.value.totalAmount,
|
||||
details: formData.value.details || []
|
||||
}) as ShipmentOrderVO
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
await formRef.value.validate()
|
||||
if (!validateDetails(false)) {
|
||||
return
|
||||
}
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = buildSubmitData()
|
||||
if (formType.value === 'create') {
|
||||
await ShipmentOrderApi.createShipmentOrder(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await ShipmentOrderApi.updateShipmentOrder(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 完成出库:表单修改过则先保存,再完成 */
|
||||
const handleComplete = async () => {
|
||||
await formRef.value.validate()
|
||||
if (!validateDetails(true)) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
await message.confirm('确认完成出库?完成后将更新库存。')
|
||||
formLoading.value = true
|
||||
const data = buildSubmitData()
|
||||
if (JSON.stringify(data) !== originalFormData.value) {
|
||||
await ShipmentOrderApi.updateShipmentOrder(data)
|
||||
}
|
||||
await ShipmentOrderApi.completeShipmentOrder(formData.value.id!)
|
||||
message.success('出库成功')
|
||||
dialogVisible.value = false
|
||||
emit('success')
|
||||
} catch {
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 作废出库单 */
|
||||
const handleCancel = async () => {
|
||||
try {
|
||||
await message.confirm('确认作废该出库单?作废后不可恢复。')
|
||||
formLoading.value = true
|
||||
await ShipmentOrderApi.cancelShipmentOrder(formData.value.id!)
|
||||
message.success('作废成功')
|
||||
dialogVisible.value = false
|
||||
emit('success')
|
||||
} catch {
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
no: generateOrderNo('CK'),
|
||||
type: undefined,
|
||||
status: OrderStatusEnum.PREPARE,
|
||||
bizOrderNo: undefined,
|
||||
merchantId: undefined,
|
||||
warehouseId: undefined,
|
||||
areaId: undefined,
|
||||
totalQuantity: 0,
|
||||
totalAmount: 0,
|
||||
remark: undefined,
|
||||
details: []
|
||||
}
|
||||
originalFormData.value = ''
|
||||
nextTick(() => formRef.value?.clearValidate())
|
||||
}
|
||||
</script>
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
<!-- WMS 出库单打印 -->
|
||||
<template>
|
||||
<div class="hidden">
|
||||
<button ref="printButtonRef" v-print="printObj" type="button"></button>
|
||||
<div id="wmsShipmentOrderPrint" class="color-#303133">
|
||||
<h2 class="text-center">出库单</h2>
|
||||
<div class="mb-12px grid grid-cols-3 gap-x-24px gap-y-8px text-14px">
|
||||
<div>出库单号:{{ printData.no || '-' }}</div>
|
||||
<div>
|
||||
出库类型:{{ getDictLabel(DICT_TYPE.WMS_SHIPMENT_ORDER_TYPE, printData.type) || '-' }}
|
||||
</div>
|
||||
<div>出库状态:{{ getDictLabel(DICT_TYPE.WMS_ORDER_STATUS, printData.status) || '-' }}</div>
|
||||
<div>客户:{{ printData.merchantName || '-' }}</div>
|
||||
<div>业务单号:{{ printData.bizOrderNo || '-' }}</div>
|
||||
<div>仓库:{{ printData.warehouseName || '-' }}</div>
|
||||
<div v-if="AREA_ENABLE">库区:{{ printData.areaName || '-' }}</div>
|
||||
<div>总数量:{{ formatQuantity(printData.totalQuantity) || '-' }}</div>
|
||||
<div>总金额:{{ formatPrice(printData.totalAmount) || '-' }}</div>
|
||||
<div>创建时间:{{ formatNullableDate(printData.createTime) }}</div>
|
||||
<div class="col-span-3">备注:{{ printData.remark || '-' }}</div>
|
||||
</div>
|
||||
<table class="w-full border-collapse text-13px">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="border border-solid border-#dcdfe6 bg-#f5f7fa p-8px text-left">商品信息</th>
|
||||
<th class="border border-solid border-#dcdfe6 bg-#f5f7fa p-8px text-left">规格信息</th>
|
||||
<th
|
||||
v-if="AREA_ENABLE"
|
||||
class="border border-solid border-#dcdfe6 bg-#f5f7fa p-8px text-left"
|
||||
>
|
||||
库区
|
||||
</th>
|
||||
<th
|
||||
v-if="BATCH_ENABLE"
|
||||
class="border border-solid border-#dcdfe6 bg-#f5f7fa p-8px text-left"
|
||||
>
|
||||
批号
|
||||
</th>
|
||||
<th
|
||||
v-if="BATCH_ENABLE"
|
||||
class="border border-solid border-#dcdfe6 bg-#f5f7fa p-8px text-left"
|
||||
>
|
||||
生产日期
|
||||
</th>
|
||||
<th
|
||||
v-if="BATCH_ENABLE"
|
||||
class="border border-solid border-#dcdfe6 bg-#f5f7fa p-8px text-left"
|
||||
>
|
||||
过期日期
|
||||
</th>
|
||||
<th class="border border-solid border-#dcdfe6 bg-#f5f7fa p-8px text-left">数量</th>
|
||||
<th class="border border-solid border-#dcdfe6 bg-#f5f7fa p-8px text-left">金额(元)</th>
|
||||
<th class="border border-solid border-#dcdfe6 bg-#f5f7fa p-8px text-left">备注</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="detail in printData.details || []" :key="detail.id">
|
||||
<td class="border border-solid border-#dcdfe6 p-8px">
|
||||
<div>{{ detail.itemName || '-' }}</div>
|
||||
<div v-if="detail.itemCode" class="text-12px">编号:{{ detail.itemCode }}</div>
|
||||
</td>
|
||||
<td class="border border-solid border-#dcdfe6 p-8px">
|
||||
<div>{{ detail.skuName || '-' }}</div>
|
||||
<div v-if="detail.skuCode" class="text-12px">编号:{{ detail.skuCode }}</div>
|
||||
</td>
|
||||
<td v-if="AREA_ENABLE" class="border border-solid border-#dcdfe6 p-8px">
|
||||
{{ detail.areaName || '-' }}
|
||||
</td>
|
||||
<td v-if="BATCH_ENABLE" class="border border-solid border-#dcdfe6 p-8px">
|
||||
{{ detail.batchNo || '-' }}
|
||||
</td>
|
||||
<td v-if="BATCH_ENABLE" class="border border-solid border-#dcdfe6 p-8px">
|
||||
{{ formatNullableDate(detail.productionDate, 'YYYY-MM-DD') }}
|
||||
</td>
|
||||
<td v-if="BATCH_ENABLE" class="border border-solid border-#dcdfe6 p-8px">
|
||||
{{ formatNullableDate(detail.expirationDate, 'YYYY-MM-DD') }}
|
||||
</td>
|
||||
<td class="border border-solid border-#dcdfe6 p-8px text-right">
|
||||
{{ formatQuantity(detail.quantity) || '-' }}
|
||||
</td>
|
||||
<td class="border border-solid border-#dcdfe6 p-8px text-right">
|
||||
{{ formatPrice(detail.amount) || '-' }}
|
||||
</td>
|
||||
<td class="border border-solid border-#dcdfe6 p-8px">{{ detail.remark || '-' }}</td>
|
||||
</tr>
|
||||
<tr v-if="!printData.details?.length">
|
||||
<td
|
||||
class="border border-solid border-#dcdfe6 p-8px text-center"
|
||||
:colspan="tableColumnCount"
|
||||
>
|
||||
暂无明细
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { formatNullableDate } from '@/utils/formatTime'
|
||||
import { DICT_TYPE, getDictLabel } from '@/utils/dict'
|
||||
import { ShipmentOrderApi, ShipmentOrderVO } from '@/api/wms/order/shipment'
|
||||
import { AREA_ENABLE, BATCH_ENABLE } from '@/views/wms/utils/config'
|
||||
import { formatPrice, formatQuantity } from '@/views/wms/utils/format'
|
||||
|
||||
/** WMS 出库单打印 */
|
||||
defineOptions({ name: 'WmsShipmentOrderPrint' })
|
||||
|
||||
const printData = ref<ShipmentOrderVO>({}) // 打印数据
|
||||
const printButtonRef = ref<HTMLButtonElement>() // 打印按钮
|
||||
const tableColumnCount = computed(() => 5 + (AREA_ENABLE ? 1 : 0) + (BATCH_ENABLE ? 3 : 0))
|
||||
const printObj = ref({
|
||||
id: 'wmsShipmentOrderPrint',
|
||||
popTitle: ' ',
|
||||
extraCss: '/print.css',
|
||||
extraHead: '',
|
||||
zIndex: 20003
|
||||
})
|
||||
|
||||
/** 打印出库单 */
|
||||
const print = async (id: number) => {
|
||||
printData.value = await ShipmentOrderApi.getShipmentOrder(id)
|
||||
await nextTick()
|
||||
printButtonRef.value?.click()
|
||||
}
|
||||
defineExpose({ print })
|
||||
</script>
|
||||
|
|
@ -0,0 +1,649 @@
|
|||
<!-- WMS 出库单 -->
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
:model="queryParams"
|
||||
class="-mb-15px"
|
||||
label-width="80px"
|
||||
>
|
||||
<el-form-item label="出库单号" prop="no">
|
||||
<el-input
|
||||
v-model="queryParams.no"
|
||||
class="!w-240px"
|
||||
clearable
|
||||
placeholder="请输入出库单号"
|
||||
@keyup.enter="handleQuery"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="单据状态" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
class="!w-240px"
|
||||
clearable
|
||||
placeholder="请选择单据状态"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.WMS_ORDER_STATUS)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="仓库" prop="warehouseId">
|
||||
<WarehouseSelect
|
||||
v-model="queryParams.warehouseId"
|
||||
class="!w-240px"
|
||||
@change="handleWarehouseChange"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="客户" prop="merchantId">
|
||||
<MerchantSelect
|
||||
v-model="queryParams.merchantId"
|
||||
class="!w-240px"
|
||||
placeholder="请选择客户"
|
||||
customer
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="单据日期" prop="orderDate">
|
||||
<el-date-picker
|
||||
v-model="queryParams.orderDate"
|
||||
:shortcuts="defaultShortcuts"
|
||||
class="!w-240px"
|
||||
end-placeholder="结束时间"
|
||||
start-placeholder="开始时间"
|
||||
type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="数量" prop="totalQuantityMin">
|
||||
<div class="flex w-240px items-center gap-8px">
|
||||
<el-input-number
|
||||
v-model="queryParams.totalQuantityMin"
|
||||
:controls="false"
|
||||
:min="0"
|
||||
:precision="QUANTITY_PRECISION"
|
||||
class="!w-105px"
|
||||
placeholder="最小值"
|
||||
/>
|
||||
<span>至</span>
|
||||
<el-input-number
|
||||
v-model="queryParams.totalQuantityMax"
|
||||
:controls="false"
|
||||
:min="0"
|
||||
:precision="QUANTITY_PRECISION"
|
||||
class="!w-105px"
|
||||
placeholder="最大值"
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="总金额" prop="totalAmountMin">
|
||||
<div class="flex w-240px items-center gap-8px">
|
||||
<el-input-number
|
||||
v-model="queryParams.totalAmountMin"
|
||||
:controls="false"
|
||||
:min="0"
|
||||
:precision="PRICE_PRECISION"
|
||||
class="!w-105px"
|
||||
placeholder="最小值"
|
||||
/>
|
||||
<span>至</span>
|
||||
<el-input-number
|
||||
v-model="queryParams.totalAmountMax"
|
||||
:controls="false"
|
||||
:min="0"
|
||||
:precision="PRICE_PRECISION"
|
||||
class="!w-105px"
|
||||
placeholder="最大值"
|
||||
/>
|
||||
</div>
|
||||
</el-form-item>
|
||||
<el-form-item label="出库类型" prop="type">
|
||||
<el-select
|
||||
v-model="queryParams.type"
|
||||
class="!w-240px"
|
||||
clearable
|
||||
placeholder="请选择出库类型"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.WMS_SHIPMENT_ORDER_TYPE)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建用户" prop="creator">
|
||||
<UserSelectV2
|
||||
v-model="queryParams.creator"
|
||||
class="!w-240px"
|
||||
placeholder="请选择创建用户"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="更新用户" prop="updater">
|
||||
<UserSelectV2
|
||||
v-model="queryParams.updater"
|
||||
class="!w-240px"
|
||||
placeholder="请选择更新用户"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.createTime"
|
||||
:shortcuts="defaultShortcuts"
|
||||
class="!w-240px"
|
||||
end-placeholder="结束时间"
|
||||
start-placeholder="开始时间"
|
||||
type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="更新时间" prop="updateTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.updateTime"
|
||||
:shortcuts="defaultShortcuts"
|
||||
class="!w-240px"
|
||||
end-placeholder="结束时间"
|
||||
start-placeholder="开始时间"
|
||||
type="datetimerange"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery">
|
||||
<Icon class="mr-5px" icon="ep:search" />
|
||||
搜索
|
||||
</el-button>
|
||||
<el-button @click="resetQuery">
|
||||
<Icon class="mr-5px" icon="ep:refresh" />
|
||||
重置
|
||||
</el-button>
|
||||
<el-popover
|
||||
popper-class="wms-shipment-order-table-setting-popover"
|
||||
trigger="click"
|
||||
width="520"
|
||||
>
|
||||
<template #reference>
|
||||
<el-button>
|
||||
<Icon class="mr-5px" icon="ep:setting" />
|
||||
表格设置
|
||||
</el-button>
|
||||
</template>
|
||||
<el-checkbox-group
|
||||
v-model="checkedTableColumns"
|
||||
class="wms-shipment-order-table-setting grid grid-cols-3 gap-y-14px rounded p-16px"
|
||||
>
|
||||
<el-checkbox
|
||||
v-for="column in tableColumnOptions"
|
||||
:key="column.value"
|
||||
:label="column.value"
|
||||
>
|
||||
{{ column.label }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-popover>
|
||||
<el-button
|
||||
v-hasPermi="['wms:shipment-order:create']"
|
||||
plain
|
||||
type="primary"
|
||||
@click="openForm('create')"
|
||||
>
|
||||
<Icon class="mr-5px" icon="ep:plus" />
|
||||
新增
|
||||
</el-button>
|
||||
<el-button
|
||||
v-hasPermi="['wms:shipment-order:export']"
|
||||
:loading="exportLoading"
|
||||
plain
|
||||
type="success"
|
||||
@click="handleExport"
|
||||
>
|
||||
<Icon class="mr-5px" icon="ep:download" />
|
||||
导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 出库单列表 -->
|
||||
<ContentWrap>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
:cell-class-name="'wms-shipment-order-cell'"
|
||||
:data="list"
|
||||
:show-overflow-tooltip="true"
|
||||
border
|
||||
@expand-change="handleExpandChange"
|
||||
>
|
||||
<el-table-column type="expand" width="48">
|
||||
<template #default="scope">
|
||||
<el-table :data="detailMap[scope.row.id] || []" border>
|
||||
<el-table-column label="商品信息" min-width="220">
|
||||
<template #default="detailScope">
|
||||
<div>{{ detailScope.row.itemName || '-' }}</div>
|
||||
<div v-if="detailScope.row.itemCode" class="text-12px text-gray-500">
|
||||
商品编号:{{ detailScope.row.itemCode }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="规格信息" min-width="220">
|
||||
<template #default="detailScope">
|
||||
<div>{{ detailScope.row.skuName || '-' }}</div>
|
||||
<div v-if="detailScope.row.skuCode" class="text-12px text-gray-500">
|
||||
规格编号:{{ detailScope.row.skuCode }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="AREA_ENABLE"
|
||||
align="center"
|
||||
label="库区"
|
||||
min-width="140"
|
||||
prop="areaName"
|
||||
/>
|
||||
<el-table-column
|
||||
v-if="BATCH_ENABLE"
|
||||
align="center"
|
||||
label="批号"
|
||||
min-width="140"
|
||||
prop="batchNo"
|
||||
/>
|
||||
<el-table-column v-if="BATCH_ENABLE" label="生产日期/过期日期" min-width="180">
|
||||
<template #default="detailScope">
|
||||
<div v-if="detailScope.row.productionDate">
|
||||
生产日期:{{ formatNullableDate(detailScope.row.productionDate, 'YYYY-MM-DD') }}
|
||||
</div>
|
||||
<div v-if="detailScope.row.expirationDate">
|
||||
过期日期:{{ formatNullableDate(detailScope.row.expirationDate, 'YYYY-MM-DD') }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="right" label="出库数量" width="120">
|
||||
<template #default="detailScope">
|
||||
{{ formatQuantity(detailScope.row.quantity) }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column align="right" label="金额(元)" width="120">
|
||||
<template #default="detailScope">
|
||||
{{ formatPrice(detailScope.row.amount) || '-' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="备注" min-width="160" prop="remark" />
|
||||
</el-table>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="isTableColumnVisible('no')" fixed="left" label="单号/业务单号" width="290">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
单号:
|
||||
<el-button link type="primary" @click="openDetail(scope.row.id)">
|
||||
{{ scope.row.no }}
|
||||
</el-button>
|
||||
</div>
|
||||
<div v-if="scope.row.bizOrderNo" class="text-12px text-gray-500">
|
||||
业务:{{ scope.row.bizOrderNo }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isTableColumnVisible('status')"
|
||||
align="center"
|
||||
fixed="left"
|
||||
label="出库状态"
|
||||
width="110"
|
||||
>
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.WMS_ORDER_STATUS" :value="scope.row.status" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isTableColumnVisible('type')"
|
||||
align="center"
|
||||
label="出库类型"
|
||||
width="120"
|
||||
>
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.WMS_SHIPMENT_ORDER_TYPE" :value="scope.row.type" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isTableColumnVisible('warehouse')"
|
||||
:label="AREA_ENABLE ? '仓库/库区' : '仓库'"
|
||||
min-width="160"
|
||||
>
|
||||
<template #default="scope">
|
||||
<template v-if="AREA_ENABLE">
|
||||
<div>仓库:{{ scope.row.warehouseName || '-' }}</div>
|
||||
<div>库区:{{ scope.row.areaName || '-' }}</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ scope.row.warehouseName || '-' }}
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isTableColumnVisible('quantityAmount')"
|
||||
label="总数量/总金额(元)"
|
||||
min-width="180"
|
||||
>
|
||||
<template #default="scope">
|
||||
<div class="flex items-center justify-between">
|
||||
<span>数量:</span>
|
||||
<span>{{ formatQuantity(scope.row.totalQuantity) }}</span>
|
||||
</div>
|
||||
<div class="flex items-center justify-between">
|
||||
<span>金额:</span>
|
||||
<span>{{ formatPrice(scope.row.totalAmount) }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="isTableColumnVisible('merchant')"
|
||||
label="客户"
|
||||
min-width="160"
|
||||
prop="merchantName"
|
||||
/>
|
||||
<el-table-column v-if="isTableColumnVisible('operateInfo')" label="操作信息" min-width="280">
|
||||
<template #default="scope">
|
||||
<div>
|
||||
创建:{{ formatNullableDate(scope.row.createTime) }} /
|
||||
{{ scope.row.creatorName || scope.row.creator || '-' }}
|
||||
</div>
|
||||
<div>
|
||||
更新:{{ formatNullableDate(scope.row.updateTime) }} /
|
||||
{{ scope.row.updaterName || scope.row.updater || '-' }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column v-if="isTableColumnVisible('remark')" label="备注" min-width="160" prop="remark" />
|
||||
<el-table-column align="center" fixed="right" label="操作" width="180">
|
||||
<template #default="scope">
|
||||
<el-tooltip
|
||||
:content="getShipmentOrderUpdateTip(scope.row.status)"
|
||||
:disabled="canUpdateShipmentOrder(scope.row.status)"
|
||||
placement="top"
|
||||
>
|
||||
<span>
|
||||
<el-button
|
||||
v-hasPermi="['wms:shipment-order:update']"
|
||||
:disabled="!canUpdateShipmentOrder(scope.row.status)"
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
>
|
||||
修改
|
||||
</el-button>
|
||||
</span>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
:content="getShipmentOrderDeleteTip(scope.row.status)"
|
||||
:disabled="canDeleteShipmentOrder(scope.row.status)"
|
||||
placement="top"
|
||||
>
|
||||
<span>
|
||||
<el-button
|
||||
v-hasPermi="['wms:shipment-order:delete']"
|
||||
:disabled="!canDeleteShipmentOrder(scope.row.status)"
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</span>
|
||||
</el-tooltip>
|
||||
<el-button
|
||||
v-hasPermi="['wms:shipment-order:query']"
|
||||
link
|
||||
type="primary"
|
||||
@click="handlePrint(scope.row.id)"
|
||||
>
|
||||
打印
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
v-model:limit="queryParams.pageSize"
|
||||
v-model:page="queryParams.pageNo"
|
||||
:total="total"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<ShipmentOrderForm ref="formRef" @success="getList" />
|
||||
<ShipmentOrderDetail ref="detailRef" />
|
||||
<ShipmentOrderPrint ref="printRef" />
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { defaultShortcuts, formatNullableDate } from '@/utils/formatTime'
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import { ShipmentOrderApi, ShipmentOrderVO } from '@/api/wms/order/shipment'
|
||||
import { ShipmentOrderDetailVO } from '@/api/wms/order/shipment/detail'
|
||||
import MerchantSelect from '@/views/wms/md/merchant/components/MerchantSelect.vue'
|
||||
import WarehouseSelect from '@/views/wms/md/warehouse/components/WarehouseSelect.vue'
|
||||
import { AREA_ENABLE, BATCH_ENABLE } from '@/views/wms/utils/config'
|
||||
import {
|
||||
OrderDeleteStatusList,
|
||||
OrderStatusEnum,
|
||||
OrderUpdateStatusList
|
||||
} from '@/views/wms/utils/constants'
|
||||
import { formatPrice, formatQuantity, PRICE_PRECISION, QUANTITY_PRECISION } from '@/views/wms/utils/format'
|
||||
import UserSelectV2 from '@/views/system/user/components/UserSelectV2.vue'
|
||||
import ShipmentOrderDetail from './ShipmentOrderDetail.vue'
|
||||
import ShipmentOrderForm from './ShipmentOrderForm.vue'
|
||||
import ShipmentOrderPrint from './ShipmentOrderPrint.vue'
|
||||
import download from '@/utils/download'
|
||||
|
||||
/** WMS 出库单 */
|
||||
defineOptions({ name: 'WmsShipmentOrder' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
type TableColumnKey =
|
||||
| 'no'
|
||||
| 'status'
|
||||
| 'type'
|
||||
| 'warehouse'
|
||||
| 'quantityAmount'
|
||||
| 'merchant'
|
||||
| 'operateInfo'
|
||||
| 'remark'
|
||||
|
||||
const tableColumnOptions: Array<{ label: string; value: TableColumnKey }> = [
|
||||
{ label: '单号/业务单号', value: 'no' },
|
||||
{ label: '出库状态', value: 'status' },
|
||||
{ label: '出库类型', value: 'type' },
|
||||
{ label: '仓库', value: 'warehouse' },
|
||||
{ label: '数量/金额(元)', value: 'quantityAmount' },
|
||||
{ label: '客户', value: 'merchant' },
|
||||
{ label: '操作信息', value: 'operateInfo' },
|
||||
{ label: '备注', value: 'remark' }
|
||||
]
|
||||
const checkedTableColumns = ref<TableColumnKey[]>([
|
||||
'no',
|
||||
'status',
|
||||
'type',
|
||||
'warehouse',
|
||||
'quantityAmount',
|
||||
'merchant',
|
||||
'operateInfo',
|
||||
'remark'
|
||||
])
|
||||
const isTableColumnVisible = (column: TableColumnKey) => checkedTableColumns.value.includes(column)
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const list = ref<ShipmentOrderVO[]>([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const getDefaultQueryParams = () => ({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
no: undefined as string | undefined,
|
||||
status: undefined as number | undefined,
|
||||
warehouseId: undefined as number | undefined,
|
||||
merchantId: undefined as number | undefined,
|
||||
orderDate: undefined as string[] | undefined,
|
||||
totalQuantityMin: undefined as number | undefined,
|
||||
totalQuantityMax: undefined as number | undefined,
|
||||
totalAmountMin: undefined as number | undefined,
|
||||
totalAmountMax: undefined as number | undefined,
|
||||
type: undefined as number | undefined,
|
||||
bizOrderNo: undefined as string | undefined,
|
||||
creator: undefined as number | undefined,
|
||||
updater: undefined as number | undefined,
|
||||
createTime: undefined as string[] | undefined,
|
||||
updateTime: undefined as string[] | undefined
|
||||
})
|
||||
const queryParams = reactive(getDefaultQueryParams())
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
const detailMap = reactive<Record<number, ShipmentOrderDetailVO[]>>({}) // 出库单明细缓存
|
||||
|
||||
/** 是否允许修改出库单 */
|
||||
const canUpdateShipmentOrder = (status?: number) => {
|
||||
return status !== undefined && OrderUpdateStatusList.includes(status)
|
||||
}
|
||||
|
||||
/** 是否允许删除出库单 */
|
||||
const canDeleteShipmentOrder = (status?: number) => {
|
||||
return status !== undefined && OrderDeleteStatusList.includes(status)
|
||||
}
|
||||
|
||||
/** 获得出库单修改禁用提示 */
|
||||
const getShipmentOrderUpdateTip = (status?: number) => {
|
||||
if (status === OrderStatusEnum.FINISHED) {
|
||||
return '已出库,无法修改'
|
||||
}
|
||||
if (status === OrderStatusEnum.CANCELED) {
|
||||
return '已作废,无法修改'
|
||||
}
|
||||
return '当前状态无法修改'
|
||||
}
|
||||
|
||||
/** 获得出库单删除禁用提示 */
|
||||
const getShipmentOrderDeleteTip = (status?: number) => {
|
||||
if (status === OrderStatusEnum.FINISHED) {
|
||||
return '已出库,无法删除'
|
||||
}
|
||||
return '当前状态无法删除'
|
||||
}
|
||||
|
||||
/** 查询出库单列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await ShipmentOrderApi.getShipmentOrderPage(queryParams)
|
||||
list.value = data.list
|
||||
total.value = data.total
|
||||
} finally {
|
||||
loading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
queryParams.pageNo = 1
|
||||
getList()
|
||||
}
|
||||
|
||||
/** 重置按钮操作 */
|
||||
const resetQuery = () => {
|
||||
Object.assign(queryParams, getDefaultQueryParams())
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 仓库变化 */
|
||||
const handleWarehouseChange = () => {
|
||||
handleQuery()
|
||||
}
|
||||
|
||||
/** 展开明细 */
|
||||
const handleExpandChange = async (row: ShipmentOrderVO) => {
|
||||
if (!row.id || detailMap[row.id]) {
|
||||
return
|
||||
}
|
||||
detailMap[row.id] = await ShipmentOrderApi.getShipmentOrderDetailListByOrderId(row.id)
|
||||
}
|
||||
|
||||
/** 添加/修改操作 */
|
||||
const formRef = ref()
|
||||
const openForm = (type: string, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 查看出库单详情 */
|
||||
const detailRef = ref()
|
||||
const openDetail = (id: number) => {
|
||||
detailRef.value.open(id)
|
||||
}
|
||||
|
||||
/** 打印出库单 */
|
||||
const printRef = ref()
|
||||
const handlePrint = (id: number) => {
|
||||
printRef.value.print(id)
|
||||
}
|
||||
|
||||
/** 删除出库单 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await ShipmentOrderApi.deleteShipmentOrder(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await ShipmentOrderApi.exportShipmentOrder(queryParams)
|
||||
download.excel(data, '出库单.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(async () => {
|
||||
await getList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
:deep(.wms-shipment-order-cell) {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
:global(.wms-shipment-order-table-setting-popover) {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
:global(.wms-shipment-order-table-setting) {
|
||||
background-color: var(--el-fill-color-light);
|
||||
}
|
||||
|
||||
:global(.wms-shipment-order-table-setting .el-checkbox) {
|
||||
height: 28px;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
:global(.wms-shipment-order-table-setting .el-checkbox__label) {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
}
|
||||
</style>
|
||||
|
|
@ -5,6 +5,12 @@ export const OrderStatusEnum = {
|
|||
CANCELED: 5 // 已作废
|
||||
} as const
|
||||
|
||||
/** 可修改的单据状态 */
|
||||
export const OrderUpdateStatusList: number[] = [OrderStatusEnum.PREPARE]
|
||||
|
||||
/** 可删除的单据状态 */
|
||||
export const OrderDeleteStatusList: number[] = [OrderStatusEnum.PREPARE, OrderStatusEnum.CANCELED]
|
||||
|
||||
/** 往来企业类型枚举 */
|
||||
export const MerchantTypeEnum = {
|
||||
CUSTOMER: 1, // 客户
|
||||
|
|
@ -17,3 +23,9 @@ export const SupplierMerchantTypeList = [
|
|||
MerchantTypeEnum.SUPPLIER,
|
||||
MerchantTypeEnum.CUSTOMER_SUPPLIER
|
||||
]
|
||||
|
||||
/** 客户类型的往来企业 */
|
||||
export const CustomerMerchantTypeList = [
|
||||
MerchantTypeEnum.CUSTOMER,
|
||||
MerchantTypeEnum.CUSTOMER_SUPPLIER
|
||||
]
|
||||
|
|
|
|||
Loading…
Reference in New Issue