Commit d48d0919 by qinjianhui

feat: 入库单修改

parent e25dfaf4
...@@ -124,11 +124,24 @@ export function deleteStockingOrderApi(id: string | number) { ...@@ -124,11 +124,24 @@ export function deleteStockingOrderApi(id: string | number) {
) )
} }
export function cancelStockingOrderApi(id: string | number) { export function cancelStockingOrderApi(
id: string | number,
cancelReason: string,
) {
return axios.get<never, BaseRespData<void>>( return axios.get<never, BaseRespData<void>>(
`factory/supply/stockingUpManage/cancel`, `factory/supply/stockingUpManage/cancel`,
{ {
params: { id }, params: { id, cancelReason },
},
)
}
export function addStockingOrderInternalTagApi(memo: string, idList: number[]) {
return axios.post<never, BaseRespData<void>>(
`factory/supply/stockingUpManage/batchAddInternalMemo`,
{
content: memo,
idList,
}, },
) )
} }
...@@ -9,12 +9,12 @@ export interface SearchForm { ...@@ -9,12 +9,12 @@ export interface SearchForm {
currentPage: number currentPage: number
endDate?: string endDate?: string
pageSize: number pageSize: number
shippingStatus?: string shippingStatusList?: string[]
startDate?: string startDate?: string
status?: string status?: string
stockingUpManageNo?: string stockingUpManageNo?: string
stockingUpUserId?: string stockingUpUserId?: string[]
supplierId?: string supplierId?: string[]
warehouseId?: string | number[] warehouseId?: string | number[]
warehouseSku?: string | number[] warehouseSku?: string | number[]
warehouseSkuName?: string warehouseSkuName?: string
...@@ -130,7 +130,15 @@ export interface RelatedDocumentList { ...@@ -130,7 +130,15 @@ export interface RelatedDocumentList {
updateTime?: string updateTime?: string
dataVersion?: number dataVersion?: number
} }
export interface InternalMemoList {} export interface InternalMemoList {
id: number
outId?: number
operatorEmployeeName?: string
operatorTime?: string
content?: string
remark?: string
type?: number
}
export interface LogListData { export interface LogListData {
id: number id: number
manageId?: number manageId?: number
......
...@@ -56,6 +56,7 @@ export interface StockingApplyOrderDetailList { ...@@ -56,6 +56,7 @@ export interface StockingApplyOrderDetailList {
locationId?: number locationId?: number
locationCode?: string | undefined locationCode?: string | undefined
finallyShipmentQuantity?: number finallyShipmentQuantity?: number
storedPending?: number
} }
export interface RelatedDocumentList { export interface RelatedDocumentList {
......
...@@ -682,6 +682,7 @@ const getStockingOrderDetailById = async (id: number) => { ...@@ -682,6 +682,7 @@ const getStockingOrderDetailById = async (id: number) => {
} }
const open = (row: TableData | null, type: string) => { const open = (row: TableData | null, type: string) => {
if (row) { if (row) {
productSku.value = ''
editId.value = row.id editId.value = row.id
editOrderType.value = type editOrderType.value = type
getStockingOrderDetailById(row.id) getStockingOrderDetailById(row.id)
......
...@@ -24,8 +24,32 @@ ...@@ -24,8 +24,32 @@
</div> </div>
</ElTabPane> </ElTabPane>
<ElTabPane name="internalMemo" label="内部便签"> <ElTabPane name="internalMemo" label="内部便签">
<div class="detail-table-content"> <div class="detail-table-content memo-content">
<div class="empty-content">暂无数据</div> <div class="memo-input-wrapper">
<ElInput
v-model="memoInputValue"
placeholder="请输入内容"
clearable
class="memo-input"
/>
<ElButton type="primary" :loading="addingMemo" @click="handleAddMemo">
添加
</ElButton>
</div>
<div class="memo-list">
<template v-if="internalMemoData.length > 0">
<div
v-for="item in internalMemoData"
:key="item.id"
class="memo-item"
>
<span class="memo-user">{{ item.operatorEmployeeName }}</span>
<span class="memo-text">{{ item.content }}</span>
<span class="memo-time">({{ item.operatorTime }})</span>
</div>
</template>
<div v-else class="empty-content">暂无数据</div>
</div>
</div> </div>
</ElTabPane> </ElTabPane>
<ElTabPane name="operationLog" label="操作日志"> <ElTabPane name="operationLog" label="操作日志">
...@@ -42,6 +66,7 @@ import { ref } from 'vue' ...@@ -42,6 +66,7 @@ import { ref } from 'vue'
import type { TabsPaneContext } from 'element-plus' import type { TabsPaneContext } from 'element-plus'
import TableView from '@/components/TableView.vue' import TableView from '@/components/TableView.vue'
import { import {
InternalMemoList,
LogListData, LogListData,
RelatedDocumentList, RelatedDocumentList,
StockingOrderProduct, StockingOrderProduct,
...@@ -49,11 +74,13 @@ import { ...@@ -49,11 +74,13 @@ import {
} from '@/types/api/supply/stockingOrder' } from '@/types/api/supply/stockingOrder'
import ImageView from '@/components/ImageView.vue' import ImageView from '@/components/ImageView.vue'
import { import {
addStockingOrderInternalTagApi,
getStockingOrderDetailListByIdApi, getStockingOrderDetailListByIdApi,
getStockingOrderInternalMemoListByIdApi, getStockingOrderInternalMemoListByIdApi,
getStockingOrderLogListByIdApi, getStockingOrderLogListByIdApi,
getStockingOrderRelatedDocumentListByIdApi, getStockingOrderRelatedDocumentListByIdApi,
} from '@/api/supplier/stockingOrder' } from '@/api/supplier/stockingOrder'
import { ElMessage } from 'element-plus'
import LogList from '@/components/LogList.vue' import LogList from '@/components/LogList.vue'
const relatedDocumentsColumns = computed(() => { const relatedDocumentsColumns = computed(() => {
return [ return [
...@@ -76,7 +103,7 @@ const relatedDocumentsColumns = computed(() => { ...@@ -76,7 +103,7 @@ const relatedDocumentsColumns = computed(() => {
{ {
label: '制单时间', label: '制单时间',
width: 160, width: 160,
prop:'createTime', prop: 'createTime',
align: 'center', align: 'center',
}, },
{ {
...@@ -89,7 +116,7 @@ const relatedDocumentsColumns = computed(() => { ...@@ -89,7 +116,7 @@ const relatedDocumentsColumns = computed(() => {
label: '入库数量', label: '入库数量',
width: 120, width: 120,
align: 'right', align: 'right',
prop:'buyStored' prop: 'buyStored',
}, },
{ {
label: '申请数量', label: '申请数量',
...@@ -101,13 +128,13 @@ const relatedDocumentsColumns = computed(() => { ...@@ -101,13 +128,13 @@ const relatedDocumentsColumns = computed(() => {
label: '预计到货日期', label: '预计到货日期',
width: 160, width: 160,
align: 'center', align: 'center',
prop:'expectDeliveryTime' prop: 'expectDeliveryTime',
}, },
{ {
label: '实际到货日期', label: '实际到货日期',
width: 160, width: 160,
align: 'center', align: 'center',
prop:'deliveryTime' prop: 'deliveryTime',
}, },
] ]
}) })
...@@ -184,10 +211,37 @@ const props = defineProps<{ ...@@ -184,10 +211,37 @@ const props = defineProps<{
const stockProductsData = ref<StockingOrderProduct[]>([]) const stockProductsData = ref<StockingOrderProduct[]>([])
const relatedDocumentsData = ref<RelatedDocumentList[]>([]) const relatedDocumentsData = ref<RelatedDocumentList[]>([])
const internalMemoData = ref<StockingOrderProduct[]>([]) const internalMemoData = ref<InternalMemoList[]>([])
const operationLogData = ref<LogListData[]>([]) const operationLogData = ref<LogListData[]>([])
const activeTab = ref('stockProducts') const activeTab = ref('stockProducts')
const loading = ref(false) const loading = ref(false)
const memoInputValue = ref('')
const addingMemo = ref(false)
const handleAddMemo = async () => {
if (!memoInputValue.value.trim()) {
ElMessage.warning('请输入内容')
return
}
if (!props.selectedRow) return
addingMemo.value = true
try {
const res = await addStockingOrderInternalTagApi(
memoInputValue.value.trim(),
[props.selectedRow.id],
)
if (res.code === 200) {
ElMessage.success('添加成功')
memoInputValue.value = ''
loadInternalMemo(props.selectedRow)
}
} catch (e) {
console.error(e)
} finally {
addingMemo.value = false
}
}
watch( watch(
() => props.selectedRow, () => props.selectedRow,
(newVal) => { (newVal) => {
...@@ -259,6 +313,7 @@ const loadOperationLog = async (row: TableData) => { ...@@ -259,6 +313,7 @@ const loadOperationLog = async (row: TableData) => {
} }
const handleTabClick = (tab: TabsPaneContext) => { const handleTabClick = (tab: TabsPaneContext) => {
activeTab.value = tab.paneName as string activeTab.value = tab.paneName as string
if (!props.selectedRow) return
if (activeTab.value === 'stockProducts') { if (activeTab.value === 'stockProducts') {
loadStockProducts(props.selectedRow as TableData) loadStockProducts(props.selectedRow as TableData)
} else if (activeTab.value === 'relatedDocuments') { } else if (activeTab.value === 'relatedDocuments') {
...@@ -294,4 +349,49 @@ const handleTabClick = (tab: TabsPaneContext) => { ...@@ -294,4 +349,49 @@ const handleTabClick = (tab: TabsPaneContext) => {
color: #909399; color: #909399;
font-size: 14px; font-size: 14px;
} }
.memo-content {
display: flex;
flex-direction: column;
}
.memo-input-wrapper {
display: flex;
align-items: center;
gap: 12px;
.memo-input {
flex: 1;
max-width: 300px;
}
}
.memo-list {
flex: 1;
overflow-y: auto;
}
.memo-item {
padding: 8px 0;
font-size: 14px;
line-height: 1.5;
border-bottom: 1px solid #f0f0f0;
&:last-child {
border-bottom: none;
}
.memo-user {
color: #409eff;
}
.memo-text {
color: #303133;
}
.memo-time {
color: #909399;
margin-left: 8px;
}
}
</style> </style>
...@@ -330,7 +330,7 @@ const handleDispatch = async () => { ...@@ -330,7 +330,7 @@ const handleDispatch = async () => {
const open = async (row: TableData) => { const open = async (row: TableData) => {
if (!row?.id) return if (!row?.id) return
selectedProducts.value = []
const loading = ElLoading.service({ const loading = ElLoading.service({
lock: true, lock: true,
text: '加载中...', text: '加载中...',
......
...@@ -87,9 +87,9 @@ ...@@ -87,9 +87,9 @@
/> />
</ElSelect> </ElSelect>
</ElFormItem> </ElFormItem>
<ElFormItem label="发货状态" prop="shippingStatus"> <ElFormItem label="发货状态" prop="shippingStatusList">
<ElSelect <ElSelect
v-model="searchForm.shippingStatus" v-model="searchForm.shippingStatusList"
placeholder="请选择" placeholder="请选择"
filterable filterable
multiple multiple
...@@ -163,7 +163,9 @@ ...@@ -163,7 +163,9 @@
</span> </span>
<span class="item"> <span class="item">
<ElButton type="success">添加内部便签</ElButton> <ElButton type="success" @click="addInternalTag"
>添加内部便签</ElButton
>
</span> </span>
<span <span
v-if="['PENDING_SUBMIT', 'STOCKING_UP'].includes(status)" v-if="['PENDING_SUBMIT', 'STOCKING_UP'].includes(status)"
...@@ -233,6 +235,7 @@ import { ...@@ -233,6 +235,7 @@ import {
submitStockingOrderAuditApi, submitStockingOrderAuditApi,
deleteStockingOrderApi, deleteStockingOrderApi,
cancelStockingOrderApi, cancelStockingOrderApi,
addStockingOrderInternalTagApi,
} from '@/api/supplier/stockingOrder' } from '@/api/supplier/stockingOrder'
import TableView from '@/components/TableView.vue' import TableView from '@/components/TableView.vue'
import StockingOrderDetailTabs from './StockingOrderDetailTabs.vue' import StockingOrderDetailTabs from './StockingOrderDetailTabs.vue'
...@@ -256,9 +259,9 @@ import { getStockingOrderStatusTreeApi } from '@/api/supplier/stockingOrder' ...@@ -256,9 +259,9 @@ import { getStockingOrderStatusTreeApi } from '@/api/supplier/stockingOrder'
import { userData } from '@/types/api/user' import { userData } from '@/types/api/user'
import { ElButton, ElTag } from 'element-plus' import { ElButton, ElTag } from 'element-plus'
const deliveryStatusList = ref([ const deliveryStatusList = ref([
{ label: '待发货', value: 0 }, { label: '待发货', value: '0' },
{ label: '部分发货', value: 1 }, { label: '部分发货', value: '1' },
{ label: '全部发货', value: 2 }, { label: '全部发货', value: '2' },
]) ])
const tableColumns = computed(() => { const tableColumns = computed(() => {
return [ return [
...@@ -563,7 +566,7 @@ const nodeClick = (data: TreeData) => { ...@@ -563,7 +566,7 @@ const nodeClick = (data: TreeData) => {
const getDeliveryStatusName = (shippingStatus: number) => { const getDeliveryStatusName = (shippingStatus: number) => {
if (!shippingStatus) return '' if (!shippingStatus) return ''
return deliveryStatusList.value.find( return deliveryStatusList.value.find(
(item) => item.value === Number(shippingStatus), (item) => item.value === shippingStatus.toString(),
)?.label )?.label
} }
...@@ -580,12 +583,6 @@ const { ...@@ -580,12 +583,6 @@ const {
getStockingOrderListApi( getStockingOrderListApi(
{ {
...searchForm.value, ...searchForm.value,
warehouseId: Array.isArray(searchForm.value.warehouseId)
? searchForm.value.warehouseId.join(',')
: (searchForm.value.warehouseId as string | undefined),
supplierId: Array.isArray(searchForm.value.supplierId)
? searchForm.value.supplierId.join(',')
: (searchForm.value.supplierId as string | undefined),
startDate: rangeTime.value?.[0], startDate: rangeTime.value?.[0],
endDate: rangeTime.value?.[1], endDate: rangeTime.value?.[1],
status: status.value === '-1' ? undefined : status.value, status: status.value === '-1' ? undefined : status.value,
...@@ -705,23 +702,51 @@ const handleCancelOrder = async () => { ...@@ -705,23 +702,51 @@ const handleCancelOrder = async () => {
if (selection.value.length !== 1) { if (selection.value.length !== 1) {
return ElMessage.warning('请选择一条数据') return ElMessage.warning('请选择一条数据')
} }
try { ElMessageBox.prompt('', '取消原因', {
await ElMessageBox.confirm('确定要取消选中的数据吗?', '提示', { confirmButtonText: '确认',
confirmButtonText: '确定', cancelButtonText: '取消',
cancelButtonText: '取消', inputType: 'textarea',
inputPlaceholder: '请输入取消原因',
inputPattern: /.+/,
inputErrorMessage: '取消原因不能为空',
}).then(async ({ value }: { value: string }) => {
try {
const res = await cancelStockingOrderApi(selection.value[0].id, value)
if (res.code !== 200) return
ElMessage.success('取消成功')
onRefresh()
} catch (e) {
console.error(e)
}
})
}
const addInternalTag = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning', type: 'warning',
offset: window.innerHeight / 2,
}) })
} catch {
return
}
try {
const res = await cancelStockingOrderApi(selection.value[0].id)
if (res.code !== 200) return
ElMessage.success('取消成功')
onRefresh()
} catch (e) {
console.error(e)
} }
ElMessageBox.prompt('', '添加内部便签', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputType: 'textarea',
inputPlaceholder: '请输入内部便签',
inputPattern: /.+/,
inputErrorMessage: '内部便签不能为空',
}).then(async ({ value }: { value: string }) => {
try {
const res = await addStockingOrderInternalTagApi(
value,
selection.value.map((item) => item.id),
)
ElMessage.success(res.message)
search()
} catch (e) {
// showError(e)
}
})
} }
const onRefresh = () => { const onRefresh = () => {
search() search()
......
...@@ -125,7 +125,7 @@ ...@@ -125,7 +125,7 @@
提交审核 提交审核
</el-button> </el-button>
</ElFormItem> </ElFormItem>
<ElFormItem v-if="nodeCode === 'PENDING_AUDIT'"> <ElFormItem v-if="nodeCode === 'PENDING_SUBMIT'">
<el-button type="danger" @click="auditOrder('invalid')"> <el-button type="danger" @click="auditOrder('invalid')">
作废 作废
</el-button> </el-button>
...@@ -184,7 +184,7 @@ ...@@ -184,7 +184,7 @@
align="center" align="center"
></ElTableColumn> ></ElTableColumn>
<ElTableColumn <ElTableColumn
label="备货单号" label="来源单号"
show-overflow-tooltip show-overflow-tooltip
prop="sourceOn" prop="sourceOn"
width="130" width="130"
...@@ -278,7 +278,16 @@ ...@@ -278,7 +278,16 @@
label="操作" label="操作"
> >
<template #default="{ row }"> <template #default="{ row }">
<ElButton type="primary" link @click="addDialog(2, row)" <ElButton
:disabled="row.source === 'StockingUpWarehouseApply'"
:title="
row.source === 'StockingUpWarehouseApply'
? '来源为入库申请单,不允许编辑!请先操作取消,再重新提交入库单'
: ''
"
type="primary"
link
@click="addDialog(2, row)"
>编辑 >编辑
</ElButton> </ElButton>
</template> </template>
......
...@@ -100,9 +100,7 @@ ...@@ -100,9 +100,7 @@
<template #footer> <template #footer>
<div class="dialog-footer"> <div class="dialog-footer">
<ElButton @click="handleCancel">取消</ElButton> <ElButton @click="handleCancel">取消</ElButton>
<ElButton type="primary" @click="handleSubmit"> <ElButton type="primary" @click="handleSubmit"> 入库 </ElButton>
入库
</ElButton>
</div> </div>
</template> </template>
</ElDialog> </ElDialog>
...@@ -251,6 +249,19 @@ const loadDetailList = async (id: number) => { ...@@ -251,6 +249,19 @@ const loadDetailList = async (id: number) => {
res.data.warehouseId as string | number, res.data.warehouseId as string | number,
) )
if (locationRes.code !== 200) return if (locationRes.code !== 200) return
const { detailsList } = res.data
if (detailsList && detailsList.length > 0) {
if (detailsList.some((e) => (e.storedPending as number) > 0)) {
return ElMessageBox.alert(
'已存在待审核的入库单,请勿重复操作!',
'提示',
{
confirmButtonText: '确定',
type: 'warning',
},
)
}
}
locationList.value = locationRes.data || [] locationList.value = locationRes.data || []
if (locationList.value.length > 0) { if (locationList.value.length > 0) {
res.data.detailsList.forEach((item) => { res.data.detailsList.forEach((item) => {
...@@ -291,6 +302,7 @@ const open = async (row: { ...@@ -291,6 +302,7 @@ const open = async (row: {
id: number id: number
warehouseId: string | number | undefined warehouseId: string | number | undefined
}) => { }) => {
selectedRows.value = []
loadUserList() loadUserList()
await loadAllLocationList(row.warehouseId) await loadAllLocationList(row.warehouseId)
loadDetailList(row.id) loadDetailList(row.id)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment