Commit d48d0919 by qinjianhui

feat: 入库单修改

parent e25dfaf4
......@@ -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>>(
`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 {
currentPage: number
endDate?: string
pageSize: number
shippingStatus?: string
shippingStatusList?: string[]
startDate?: string
status?: string
stockingUpManageNo?: string
stockingUpUserId?: string
supplierId?: string
stockingUpUserId?: string[]
supplierId?: string[]
warehouseId?: string | number[]
warehouseSku?: string | number[]
warehouseSkuName?: string
......@@ -130,7 +130,15 @@ export interface RelatedDocumentList {
updateTime?: string
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 {
id: number
manageId?: number
......
......@@ -56,6 +56,7 @@ export interface StockingApplyOrderDetailList {
locationId?: number
locationCode?: string | undefined
finallyShipmentQuantity?: number
storedPending?: number
}
export interface RelatedDocumentList {
......
......@@ -682,6 +682,7 @@ const getStockingOrderDetailById = async (id: number) => {
}
const open = (row: TableData | null, type: string) => {
if (row) {
productSku.value = ''
editId.value = row.id
editOrderType.value = type
getStockingOrderDetailById(row.id)
......
......@@ -24,8 +24,32 @@
</div>
</ElTabPane>
<ElTabPane name="internalMemo" label="内部便签">
<div class="detail-table-content">
<div class="empty-content">暂无数据</div>
<div class="detail-table-content memo-content">
<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>
</ElTabPane>
<ElTabPane name="operationLog" label="操作日志">
......@@ -42,6 +66,7 @@ import { ref } from 'vue'
import type { TabsPaneContext } from 'element-plus'
import TableView from '@/components/TableView.vue'
import {
InternalMemoList,
LogListData,
RelatedDocumentList,
StockingOrderProduct,
......@@ -49,11 +74,13 @@ import {
} from '@/types/api/supply/stockingOrder'
import ImageView from '@/components/ImageView.vue'
import {
addStockingOrderInternalTagApi,
getStockingOrderDetailListByIdApi,
getStockingOrderInternalMemoListByIdApi,
getStockingOrderLogListByIdApi,
getStockingOrderRelatedDocumentListByIdApi,
} from '@/api/supplier/stockingOrder'
import { ElMessage } from 'element-plus'
import LogList from '@/components/LogList.vue'
const relatedDocumentsColumns = computed(() => {
return [
......@@ -76,7 +103,7 @@ const relatedDocumentsColumns = computed(() => {
{
label: '制单时间',
width: 160,
prop:'createTime',
prop: 'createTime',
align: 'center',
},
{
......@@ -89,7 +116,7 @@ const relatedDocumentsColumns = computed(() => {
label: '入库数量',
width: 120,
align: 'right',
prop:'buyStored'
prop: 'buyStored',
},
{
label: '申请数量',
......@@ -101,13 +128,13 @@ const relatedDocumentsColumns = computed(() => {
label: '预计到货日期',
width: 160,
align: 'center',
prop:'expectDeliveryTime'
prop: 'expectDeliveryTime',
},
{
label: '实际到货日期',
width: 160,
align: 'center',
prop:'deliveryTime'
prop: 'deliveryTime',
},
]
})
......@@ -184,10 +211,37 @@ const props = defineProps<{
const stockProductsData = ref<StockingOrderProduct[]>([])
const relatedDocumentsData = ref<RelatedDocumentList[]>([])
const internalMemoData = ref<StockingOrderProduct[]>([])
const internalMemoData = ref<InternalMemoList[]>([])
const operationLogData = ref<LogListData[]>([])
const activeTab = ref('stockProducts')
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(
() => props.selectedRow,
(newVal) => {
......@@ -259,6 +313,7 @@ const loadOperationLog = async (row: TableData) => {
}
const handleTabClick = (tab: TabsPaneContext) => {
activeTab.value = tab.paneName as string
if (!props.selectedRow) return
if (activeTab.value === 'stockProducts') {
loadStockProducts(props.selectedRow as TableData)
} else if (activeTab.value === 'relatedDocuments') {
......@@ -294,4 +349,49 @@ const handleTabClick = (tab: TabsPaneContext) => {
color: #909399;
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>
......@@ -330,7 +330,7 @@ const handleDispatch = async () => {
const open = async (row: TableData) => {
if (!row?.id) return
selectedProducts.value = []
const loading = ElLoading.service({
lock: true,
text: '加载中...',
......
......@@ -87,9 +87,9 @@
/>
</ElSelect>
</ElFormItem>
<ElFormItem label="发货状态" prop="shippingStatus">
<ElFormItem label="发货状态" prop="shippingStatusList">
<ElSelect
v-model="searchForm.shippingStatus"
v-model="searchForm.shippingStatusList"
placeholder="请选择"
filterable
multiple
......@@ -163,7 +163,9 @@
</span>
<span class="item">
<ElButton type="success">添加内部便签</ElButton>
<ElButton type="success" @click="addInternalTag"
>添加内部便签</ElButton
>
</span>
<span
v-if="['PENDING_SUBMIT', 'STOCKING_UP'].includes(status)"
......@@ -233,6 +235,7 @@ import {
submitStockingOrderAuditApi,
deleteStockingOrderApi,
cancelStockingOrderApi,
addStockingOrderInternalTagApi,
} from '@/api/supplier/stockingOrder'
import TableView from '@/components/TableView.vue'
import StockingOrderDetailTabs from './StockingOrderDetailTabs.vue'
......@@ -256,9 +259,9 @@ import { getStockingOrderStatusTreeApi } from '@/api/supplier/stockingOrder'
import { userData } from '@/types/api/user'
import { ElButton, ElTag } from 'element-plus'
const deliveryStatusList = ref([
{ label: '待发货', value: 0 },
{ label: '部分发货', value: 1 },
{ label: '全部发货', value: 2 },
{ label: '待发货', value: '0' },
{ label: '部分发货', value: '1' },
{ label: '全部发货', value: '2' },
])
const tableColumns = computed(() => {
return [
......@@ -563,7 +566,7 @@ const nodeClick = (data: TreeData) => {
const getDeliveryStatusName = (shippingStatus: number) => {
if (!shippingStatus) return ''
return deliveryStatusList.value.find(
(item) => item.value === Number(shippingStatus),
(item) => item.value === shippingStatus.toString(),
)?.label
}
......@@ -580,12 +583,6 @@ const {
getStockingOrderListApi(
{
...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],
endDate: rangeTime.value?.[1],
status: status.value === '-1' ? undefined : status.value,
......@@ -705,23 +702,51 @@ const handleCancelOrder = async () => {
if (selection.value.length !== 1) {
return ElMessage.warning('请选择一条数据')
}
try {
await ElMessageBox.confirm('确定要取消选中的数据吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
ElMessageBox.prompt('', '取消原因', {
confirmButtonText: '确认',
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',
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 = () => {
search()
......
......@@ -125,7 +125,7 @@
提交审核
</el-button>
</ElFormItem>
<ElFormItem v-if="nodeCode === 'PENDING_AUDIT'">
<ElFormItem v-if="nodeCode === 'PENDING_SUBMIT'">
<el-button type="danger" @click="auditOrder('invalid')">
作废
</el-button>
......@@ -184,7 +184,7 @@
align="center"
></ElTableColumn>
<ElTableColumn
label="备货单号"
label="来源单号"
show-overflow-tooltip
prop="sourceOn"
width="130"
......@@ -278,7 +278,16 @@
label="操作"
>
<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>
</template>
......
......@@ -100,9 +100,7 @@
<template #footer>
<div class="dialog-footer">
<ElButton @click="handleCancel">取消</ElButton>
<ElButton type="primary" @click="handleSubmit">
入库
</ElButton>
<ElButton type="primary" @click="handleSubmit"> 入库 </ElButton>
</div>
</template>
</ElDialog>
......@@ -251,6 +249,19 @@ const loadDetailList = async (id: number) => {
res.data.warehouseId as string | number,
)
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 || []
if (locationList.value.length > 0) {
res.data.detailsList.forEach((item) => {
......@@ -291,6 +302,7 @@ const open = async (row: {
id: number
warehouseId: string | number | undefined
}) => {
selectedRows.value = []
loadUserList()
await loadAllLocationList(row.warehouseId)
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