增加出库单模块

main
郭强 2024-11-07 23:22:44 +08:00
parent d3e251f3e4
commit e77c661274
7 changed files with 471 additions and 2 deletions

View File

@ -1,7 +1,6 @@
import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/inventory/inbound/` + url, ...arg)
const produceRequest = (url, ...arg) => baseRequest(`/produce/inbound/` + url, ...arg)
/**
* 入库单Api接口管理器
*
@ -19,7 +18,7 @@ export default {
},
// 获取入库单 条码列表
inventoryInboundBarcodeTree(data) {
return produceRequest('barcode/tree/list', data, 'get')
return request('barcode/tree/list', data, 'get')
},
// 获取入库单 条码(子级)列表
inventoryInboundBarcodeTreeChildren(data) {

View File

@ -0,0 +1,36 @@
import { baseRequest } from '@/utils/request'
const request = (url, ...arg) => baseRequest(`/inventory/outbound/` + url, ...arg)
/**
* 出库单Api接口管理器
*
* @author Luck
* @date 2024/10/18 22:35
**/
export default {
// 获取出库单分页
inventoryOutboundPage(data) {
return request('page', data, 'get')
},
// 获取出库单明细信息列表
inventoryOutboundDetailList(data) {
return request('detail/list', data, 'get')
},
// 获取出库单 条码列表
inventoryOutboundBarcodeTree(data) {
return request('barcode/tree/list', data, 'get')
},
// 获取出库单 条码(子级)列表
inventoryOutboundBarcodeTreeChildren(data) {
return request('barcode/tree/childrenList', data, 'get')
},
// 删除出库单
inventoryOutboundDelete(data) {
return request('delete', data)
},
// 获取出库单详情
inventoryOutboundDetail(data) {
return request('detail', data, 'get')
}
}

View File

@ -0,0 +1,95 @@
export const tableColumns = [
{
title: '单号',
dataIndex: 'billNumber',
align: 'center',
resizable: true,
width: 200,
ellipsis: true
},
{
title: '业务日期',
dataIndex: 'businessDate',
align: 'center',
sorter: true,
sortDirections: ['descend', 'ascend'],
resizable: true,
width: 200,
ellipsis: true
},
{
title: '类型',
dataIndex: 'type',
align: 'center',
resizable: true,
width: 100,
ellipsis: true
},
{
title: '客户名称',
dataIndex: 'customerName',
align: 'center',
resizable: true,
width: 200,
ellipsis: true
},
{
title: '客户编码',
dataIndex: 'customerNumber',
align: 'center',
resizable: true,
width: 200,
ellipsis: true
},
{
title: '仓库',
dataIndex: 'storeName',
align: 'center',
resizable: true,
width: 200,
ellipsis: true
},
{
title: '仓库编码',
dataIndex: 'storeNumber',
align: 'center',
resizable: true,
width: 250,
ellipsis: true
},
{
title: '车牌号',
dataIndex: 'carNumber',
align: 'center',
resizable: true,
width: 200,
ellipsis: true
},
{
title: '备注',
dataIndex: 'remarks',
align: 'center',
resizable: true,
width: 200,
ellipsis: true
},
{
title: '创建人',
dataIndex: 'createUserName',
align: 'center',
resizable: true,
width: 200,
ellipsis: true
},
{
title: '创建时间',
dataIndex: 'createTime',
sorter: true,
sortDirections: ['descend', 'ascend'],
align: 'center',
resizable: true,
width: 200,
ellipsis: true
}
]

View File

@ -0,0 +1,148 @@
<template>
<a-page-header style="padding: 10px; font-size: 20px" @back="handleBack">
<template #extra>
<!-- <a-button v-if="route.query.type !== 'SEARCH'" key="1" type="primary" @click="onSubmitForm"></a-button>-->
</template>
</a-page-header>
<a-card :bordered="false" title="出库单">
<DynamicForm
:allDisabled="route.query.type === 'SEARCH'"
:formItems="unitFormItems"
:model="formData"
:rules="formRules"
ref="formRef1"
/>
</a-card>
<a-card :bordered="false" class="mt-4" style="height: 100%">
<a-tabs v-model:activeKey="activeKey">
<a-tab-pane key="1" tab="出库明细" forceRender>
<a-table
:columns="detailColumns"
:data-source="detailDataSource"
:scroll="{
x: 100
}"
>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'action'">
<a type="primary" @click="handleOpenViewScan(record)"></a>
</template>
</template>
</a-table>
</a-tab-pane>
<a-tab-pane key="2" tab="操作信息" v-if="route.query.type !== 'ADD'">
<OperationalInformation :detailData="inform" :colSpan="6"></OperationalInformation>
</a-tab-pane>
</a-tabs>
</a-card>
<!-- 产看条码 -->
<a-modal v-model:open="visible" title="查看条码" width="80%">
<a-table
style="height: 500px"
:columns="modalColumns"
:data-source="scanTableList"
:pagination="false"
:scroll="{ x: 100, y: 420 }"
:row-key="(record) => record.id"
@expand="columnsExpand"
bordered
/>
</a-modal>
</template>
<script setup>
import produceReportApi from '@/api/production/produceTask/produceReportApi'
import useFormHandler from '@/hook/useFormHandler'
import { useRoute } from 'vue-router'
import { unitFormItems, formRules } from '@/views/productionBusiness/productionCenter/report/formFields/detailFields'
import { detailColumns, modalColumns } from '@/views/productionBusiness/productionCenter/report/columns/detailColumns'
import { cloneDeep } from 'lodash-es'
import produceReportDetailApi from '@/api/production/produceTask/produceReportDetailApi'
import inventoryOutboundApi from '@/api/inventory/inventoryOutboundApi'
const route = useRoute()
const formRef1 = ref(null)
const tableRef = ref(null)
let extendData = ref([])
let searchFormState = ref({})
let { formData, formRefs, inform, handleBack, fetchData, getExtendField } = useFormHandler(unitFormItems, {
getDetail: inventoryOutboundApi.inventoryOutboundDetail
})
let detailDataSource = ref([])
const options = {
alert: {
show: true,
clear: () => {
selectedRowKeys.value = []
}
},
rowSelection: {
onChange: (selectedRowKey, selectedRows) => {
selectedRowKeys.value = selectedRowKey
}
},
toolConfig: { refresh: true, height: true, columnSetting: true, striped: false }
}
onMounted(async () => {
formRefs.value = [formRef1.value]
const detailData = await fetchData(route.query.type)
searchFormState.value.inboundId = detailData.id
// tableRef.value.refresh(true)
await loadData()
extendData.value = await getExtendField('MATERIAL')
})
//
const loadData = async () => {
const searchFormParam = cloneDeep(searchFormState.value)
return inventoryOutboundApi.inventoryOutboundDetailList(Object.assign(searchFormParam)).then((data) => {
detailDataSource.value = data
})
}
let activeKey = ref('1')
//
let visible = ref(false)
let scanTableList = ref([])
let recordTable = {}
const handleOpenViewScan = (record) => {
recordTable = record
visible.value = true
inventoryOutboundApi.inventoryOutboundBarcodeTree({
docsDetailId: record.id,
docsId: record.inboundId
})
.then((res) => {
scanTableList.value = res
scanTableList.value.forEach((item) => {
if (item.subAmount && item.subAmount > 0) item.children = []
})
})
}
const columnsExpand = (expanded, record) => {
if (expanded) {
produceReportApi
.produceReportTreeChildrenList({
docsDetailId: recordTable.id,
docsId: record.docsId,
parentBarcode: record.barcode
})
.then((res) => {
record.children = res
record.children &&
record.children.forEach((item) => {
if (item.subAmount && item.subAmount > 0) item.children = []
})
})
}
}
</script>

View File

@ -0,0 +1,69 @@
import { required } from '@/utils/formRules'
import tool from '@/utils/tool'
export const unitFormItems = reactive([
{
label: '单号:',
name: 'billNumber',
type: 'a-input-number',
span: 6,
attrs: {
placeholder: '请输入编码',
allowClear: true
}
},
{
label: '业务日期:',
name: 'businessDate',
type: 'a-date-picker',
span: 6,
attrs: {
placeholder: '请输入业务日期',
allowClear: true,
valueFormat: 'YYYY-MM-DD HH:mm:ss'
}
},
{
label: '状态:',
name: 'state',
type: 'a-select',
span: 6,
attrs: {
placeholder: '请选择可用状态',
options: tool.dictList('PRODUCE_REPORT_STATE')
},
defaultValue: ''
},
{
label: '类型:',
name: 'produceType',
type: 'a-select',
span: 6,
attrs: {
options: tool.dictList('PRODUCE_TYPE')
}
},
{
label: '生产线:',
name: 'productionLineName',
type: 'a-select',
span: 6,
attrs: {
placeholder: '请选择是否基本单位',
options: tool.dictList('YES_NO')
},
defaultValue: 'NO'
},
{
label: '备注:',
name: 'remarks',
type: 'a-textarea',
span: 24,
attrs: {
placeholder: '请输入备注',
allowClear: true
}
}
])
export const formRules = {}

View File

@ -0,0 +1,31 @@
import tool from '@/utils/tool'
export const searchFields = [
{ name: 'billNumber', label: '单号', component: 'a-input', props: { placeholder: '请输入单号' } },
{
label: '类型:',
name: 'type',
component: 'a-select',
props: {
placeholder: '请选择类型',
allowClear: true,
options: tool.dictList('OUTBOUND_TYPE')
}
},
{
label: '仓库:',
name: 'storeId',
component: 'a-tree-select',
props: {
placeholder: '请选择仓库',
treeData: [],
fieldNames: {
children: 'children',
label: 'name',
value: 'id'
}
}
},
{ name: 'customerName', label: '客户名称', component: 'a-input', props: { placeholder: '请输入客户名称' } },
{ name: 'customerNumber', label: '客户编码', component: 'a-input', props: { placeholder: '请输入客户编码' } }
]

View File

@ -0,0 +1,91 @@
<template>
<AdvancedSearchForm
:formState="searchFormState"
:formFields="searchFieldsRef"
@search="tableRef.refresh()"
@reset="tableRef.refresh()"
/>
<a-card :bordered="false" class="mt-4" style="height: 100%">
<a-row :gutter="24">
<a-col :span="24">
<s-table
ref="tableRef"
:columns="columns"
:data="loadData"
:alert="options.alert.show"
bordered
:row-key="(record) => record.id"
:tool-config="options.toolConfig"
:scroll="{
x: 100
}"
>
<template #bodyCell="{ column, record }">
<template v-if="column.dataIndex === 'billNumber'">
<span style="color: #0d84ff">{{ record.billNumber }}</span>
</template>
<template v-if="column.dataIndex === 'type'">
<a-tag :color="tagColorList[record.type - 1]">{{
$TOOL.dictTypeData('OUTBOUND_TYPE', record.type || '')
}}</a-tag>
</template>
<template v-if="column.dataIndex === 'action'">
<a-space>
<a
@click="
navigateTo('/inventory/outbound/detail', {
type: 'SEARCH',
id: record.id
})
"
>
<EyeOutlined />
查看
</a>
</a-space>
</template>
</template>
</s-table>
</a-col>
</a-row>
</a-card>
</template>
<script setup name="inventoryInbound">
import inventoryOutboundApi from '@/api/inventory/inventoryOutboundApi'
import { useTableManagement } from '@/hook/useTableManagement'
import { searchFields } from '@/views/productionBusiness/inventory/outbound/formFields/searchFields'
import { tableColumns } from '@/views/productionBusiness/inventory/outbound/columns/tableColumn'
import sysStoreApi from '@/api/base/store/sysStoreApi'
const searchFieldsRef = ref(searchFields)
const tagColorList = ['warning', 'success', 'error', 'purple']
const {
searchFormState,
tableRef,
columns,
loadData,
options,
navigateTo
} = useTableManagement(
{
page: inventoryOutboundApi.inventoryOutboundPage
},
tableColumns,
['inventoryOutbound:view']
)
//
const exportBatchVerify = () => {}
onMounted(async () => {
const list = await sysStoreApi.sysStoreTree()
searchFieldsRef.value.forEach((item) => {
if (item.name === 'storeId') {
item.props.treeData = list
}
})
})
</script>