Commit 888af742 by qinjianhui

Merge branch 'dev' into 'master'

Dev

See merge request !212
parents acdec884 3bbd5f32
...@@ -54,7 +54,6 @@ declare module 'vue' { ...@@ -54,7 +54,6 @@ declare module 'vue' {
ElTag: typeof import('element-plus/es')['ElTag'] ElTag: typeof import('element-plus/es')['ElTag']
ElTimeline: typeof import('element-plus/es')['ElTimeline'] ElTimeline: typeof import('element-plus/es')['ElTimeline']
ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem'] ElTimelineItem: typeof import('element-plus/es')['ElTimelineItem']
ElTimePicker: typeof import('element-plus/es')['ElTimePicker']
ElTooltip: typeof import('element-plus/es')['ElTooltip'] ElTooltip: typeof import('element-plus/es')['ElTooltip']
ElTree: typeof import('element-plus/es')['ElTree'] ElTree: typeof import('element-plus/es')['ElTree']
ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect'] ElTreeSelect: typeof import('element-plus/es')['ElTreeSelect']
......
...@@ -2,6 +2,7 @@ import axios from './axios' ...@@ -2,6 +2,7 @@ import axios from './axios'
import type { BasePaginationData, BaseRespData } from '@/types/api' import type { BasePaginationData, BaseRespData } from '@/types/api'
import type { CancelOrderProcessStateGroupMap } from '@/types/api/cancelOrderProcess' import type { CancelOrderProcessStateGroupMap } from '@/types/api/cancelOrderProcess'
import type { operateOrderListData } from '@/types/api/factoryOrderNew' import type { operateOrderListData } from '@/types/api/factoryOrderNew'
import { InterskuList } from '@/types/api/warehouse'
function normalizePodOrderQueryPayload( function normalizePodOrderQueryPayload(
data: Record<string, unknown>, data: Record<string, unknown>,
...@@ -20,7 +21,7 @@ function normalizePodOrderQueryPayload( ...@@ -20,7 +21,7 @@ function normalizePodOrderQueryPayload(
export function getCancelOrderProcessStateGroupMapApi() { export function getCancelOrderProcessStateGroupMapApi() {
return axios.get<never, BaseRespData<CancelOrderProcessStateGroupMap>>( return axios.get<never, BaseRespData<CancelOrderProcessStateGroupMap>>(
'factory/podOrderOperationForReclaim/findStateGroupMap', 'factory/podOrderOperation/find-state-group-map',
) )
} }
...@@ -32,13 +33,13 @@ export function getCancelOrderProcessListApi( ...@@ -32,13 +33,13 @@ export function getCancelOrderProcessListApi(
) { ) {
const body = normalizePodOrderQueryPayload({ ...data }) const body = normalizePodOrderQueryPayload({ ...data })
return axios.post<never, BasePaginationData<operateOrderListData>>( return axios.post<never, BasePaginationData<operateOrderListData>>(
'factory/podOrderOperationForReclaim/list_page', 'factory/podOrderOperation/list-page',
{ ...body, currentPage, pageSize, alreadyInStock }, { ...body, currentPage, pageSize, alreadyInStock },
) )
} }
export function getOperationInfoByNoApi(operationNo: string) { export function getOperationInfoByNoApi(operationNo: string) {
return axios.get<never, BaseRespData<operateOrderListData>>( return axios.get<never, BaseRespData<operateOrderListData>>(
`factory/podOrderOperationForReclaim/getByOperationNo?operationNo=${operationNo}`, `factory/podOrderOperation/get-by-operation-no?operationNo=${operationNo}`,
) )
} }
export function completeDeliveryByCancelOrderProcessApi(data: { export function completeDeliveryByCancelOrderProcessApi(data: {
...@@ -47,7 +48,14 @@ export function completeDeliveryByCancelOrderProcessApi(data: { ...@@ -47,7 +48,14 @@ export function completeDeliveryByCancelOrderProcessApi(data: {
warehouseId: number warehouseId: number
}) { }) {
return axios.post<never, BaseRespData<never>>( return axios.post<never, BaseRespData<never>>(
'factory/podOrderOperationForReclaim/storeAfterScan', 'factory/podOrderOperation/store-after-scan',
data, data,
) )
} }
export function getBySkuAndUserMarkAndInboundTypeApi(operationNo: string[]) {
return axios.post<never, BaseRespData<InterskuList[]>>(
'factory/podOrderOperation/get-product-by-operation-no',
operationNo,
)
}
...@@ -535,6 +535,14 @@ export function completeDeliveryApi(ids: (number | string)[]) { ...@@ -535,6 +535,14 @@ export function completeDeliveryApi(ids: (number | string)[]) {
) )
} }
// 生产扫码
export function productionScanApi(id: number | string, status: string) {
return axios.get<never, BaseRespData<never>>(
'factory/podOrderOperation/scan-produce',
{ params: { id, status } },
)
}
export function applyForProductByIdApi(id: string, url: string) { export function applyForProductByIdApi(id: string, url: string) {
return axios.get<never, BaseRespData<operateOrderListData[]>>(url, { return axios.get<never, BaseRespData<operateOrderListData[]>>(url, {
params: { podProductId: id }, params: { podProductId: id },
...@@ -550,6 +558,13 @@ export function getByOperationNoLogApi(operationNo: string) { ...@@ -550,6 +558,13 @@ export function getByOperationNoLogApi(operationNo: string) {
) )
} }
// 校验库存
export function checkInventoryApi(id: number | string, status: string) {
return axios.get<never, BaseRespData<never>>(
'factory/podOrderOperation/check-inventory',
{ params: { id, status } },
)
}
export function listByNoPodOrderApi(params: { export function listByNoPodOrderApi(params: {
type: string type: string
no: string no: string
......
...@@ -394,7 +394,7 @@ export function rejectInRecordApi({ ...@@ -394,7 +394,7 @@ export function rejectInRecordApi({
) )
} }
export function addInRecordApi(form: InterWarehouseDetail) { export function addInRecordApi(form: InterWarehouseDetail) {
return axios.post<never, BaseRespData<never>>( return axios.post<never, BaseRespData<unknown>>(
'factory/warehouseInRecord/add', 'factory/warehouseInRecord/add',
{ {
...form, ...form,
......
...@@ -151,11 +151,11 @@ const menu: MenuItem[] = [ ...@@ -151,11 +151,11 @@ const menu: MenuItem[] = [
id: 12, id: 12,
label: '工厂订单(NEW)', label: '工厂订单(NEW)',
}, },
// { {
// index: '/order/cancel-order-process', index: '/order/cancel-order-process',
// id: 13, id: 13,
// label: '取消后订单处理', label: '取消后订单处理',
// }, },
], ],
}, },
{ {
......
...@@ -123,6 +123,8 @@ export interface InterskuList { ...@@ -123,6 +123,8 @@ export interface InterskuList {
remark?: string | null remark?: string | null
currencyName?: string | null currencyName?: string | null
currencyCode?: string | null currencyCode?: string | null
buyStored?: number | null
totalPrice?: number | null
} }
export interface ILocation { export interface ILocation {
id?: number id?: number
......
...@@ -327,6 +327,7 @@ ...@@ -327,6 +327,7 @@
</div> </div>
<FastProduction <FastProduction
v-model:detail-visible="detailVisible" v-model:detail-visible="detailVisible"
:dialog-title="dialogTitle"
:is-new-order="true" :is-new-order="true"
:detail-data="detailData" :detail-data="detailData"
:fast-key="fastKey" :fast-key="fastKey"
...@@ -385,6 +386,7 @@ import { ...@@ -385,6 +386,7 @@ import {
getCancelOrderProcessStateGroupMapApi, getCancelOrderProcessStateGroupMapApi,
getOperationInfoByNoApi, getOperationInfoByNoApi,
completeDeliveryByCancelOrderProcessApi, completeDeliveryByCancelOrderProcessApi,
getBySkuAndUserMarkAndInboundTypeApi,
} from '@/api/cancelOrderProcess' } from '@/api/cancelOrderProcess'
import type { CardLayoutListFetcher } from '@/types/api/factoryOrderNew' import type { CardLayoutListFetcher } from '@/types/api/factoryOrderNew'
import LogisticsWaySelect from '@/views/logistics/components/LogisticsWaySelect' import LogisticsWaySelect from '@/views/logistics/components/LogisticsWaySelect'
...@@ -393,7 +395,6 @@ import ProductTypeFilter from '../factoryOrderNew/component/ProductTypeFilter.vu ...@@ -393,7 +395,6 @@ import ProductTypeFilter from '../factoryOrderNew/component/ProductTypeFilter.vu
import { CaretBottom, CaretTop } from '@element-plus/icons-vue' import { CaretBottom, CaretTop } from '@element-plus/icons-vue'
import { normalizeProductMarkListForQuery } from '../factoryOrderNew/utils/productMarkQuery' import { normalizeProductMarkListForQuery } from '../factoryOrderNew/utils/productMarkQuery'
import FastProduction from '../components/FastProduction.vue' import FastProduction from '../components/FastProduction.vue'
import { ResultInfoDataItem } from '@/types/api/order/common'
import { ElButton } from 'element-plus' import { ElButton } from 'element-plus'
import ReceiptProductDialog from '@/views/warehouse/components/ReceiptProductDialog.vue' import ReceiptProductDialog from '@/views/warehouse/components/ReceiptProductDialog.vue'
import { useValue } from '@/utils/hooks/useValue' import { useValue } from '@/utils/hooks/useValue'
...@@ -412,6 +413,7 @@ import { ...@@ -412,6 +413,7 @@ import {
warehouseInfoGetAll, warehouseInfoGetAll,
} from '@/api/warehouse' } from '@/api/warehouse'
import type { CancelOrderProcessStateGroupMap } from '@/types/api/cancelOrderProcess' import type { CancelOrderProcessStateGroupMap } from '@/types/api/cancelOrderProcess'
import BigNumber from 'bignumber.js'
const cardLayoutRef = ref() const cardLayoutRef = ref()
...@@ -545,23 +547,14 @@ const completeOperationById = (_: number[], detail: Record<string, unknown>) => ...@@ -545,23 +547,14 @@ const completeOperationById = (_: number[], detail: Record<string, unknown>) =>
warehouseId: detail.warehouseId as number, warehouseId: detail.warehouseId as number,
inboundType: fastInboundType.value, inboundType: fastInboundType.value,
}) })
const handleFastProductionSuccess = (data: ResultInfoDataItem[]) => { const handleFastProductionSuccess = () => {
const result = data[0] ElMessage.success('入库成功')
if (!result.status) {
ElMessageBox.alert(
`操作单号 ${result.factoryOrderNumber} ${result.message}`,
'提示',
{
type: 'error',
},
)
return
}
} }
const fastClose = () => { const fastClose = () => {
detailVisible.value = false detailVisible.value = false
if (fastKey.value === 'detail') return if (fastKey.value === 'detail') return
search() search()
loadOrderStatusCounts()
} }
const { const {
userMarkList, userMarkList,
...@@ -614,7 +607,10 @@ const { skuData, setCostPrice, filterSkuData } = useReceiptProductDialog({ ...@@ -614,7 +607,10 @@ const { skuData, setCostPrice, filterSkuData } = useReceiptProductDialog({
selectSku: receiptSelectSku, selectSku: receiptSelectSku,
userMarkList: receiptUserMarkList, userMarkList: receiptUserMarkList,
}) })
function mapInterskuToProduct(val: InterskuList): InterProductList { function mapInterskuToProduct(
val: InterskuList,
type: 'completeProduction' | 'embryoInStock',
): InterProductList {
const warehouseSku = val.warehouseSku || val.sku || '' const warehouseSku = val.warehouseSku || val.sku || ''
const skuNameVal = val.skuName || val.productName || '' const skuNameVal = val.skuName || val.productName || ''
let customerId: number | null = null let customerId: number | null = null
...@@ -622,6 +618,16 @@ function mapInterskuToProduct(val: InterskuList): InterProductList { ...@@ -622,6 +618,16 @@ function mapInterskuToProduct(val: InterskuList): InterProductList {
const n = Number(val.customerId) const n = Number(val.customerId)
if (!Number.isNaN(n)) customerId = n if (!Number.isNaN(n)) customerId = n
} }
if (type === 'embryoInStock') {
const operationList = cardSelectList.value.filter(
(r) => r.thirdSkuCode === val.warehouseSku,
)
val.buyStored = operationList ? operationList.length : 0
}
const amount = new BigNumber(val.buyStored ?? 0)
.multipliedBy(val.costPrice ?? 0)
.toFixed(2)
val.totalPrice = Number(amount) as number
return { return {
skuImage: val.skuImage || val.image || '', skuImage: val.skuImage || val.image || '',
warehouseSku, warehouseSku,
...@@ -630,8 +636,8 @@ function mapInterskuToProduct(val: InterskuList): InterProductList { ...@@ -630,8 +636,8 @@ function mapInterskuToProduct(val: InterskuList): InterProductList {
locationCode: val.locationCode ?? '', locationCode: val.locationCode ?? '',
locationId: val.locationId ?? null, locationId: val.locationId ?? null,
costPrice: val.costPrice ?? null, costPrice: val.costPrice ?? null,
buyStored: null, buyStored: val.buyStored ?? null,
totalPrice: null, totalPrice: val.totalPrice ?? null,
currencyName: val.currencyName ?? null, currencyName: val.currencyName ?? null,
currencyCode: val.currencyCode ?? null, currencyCode: val.currencyCode ?? null,
customerId, customerId,
...@@ -641,20 +647,40 @@ function mapInterskuToProduct(val: InterskuList): InterProductList { ...@@ -641,20 +647,40 @@ function mapInterskuToProduct(val: InterskuList): InterProductList {
} }
const handleEmbryoInStock = async () => { const handleEmbryoInStock = async () => {
if (cardSelectList.value.length !== 0) { if (cardSelectList.value.length !== 0) {
handleEmbryoInStockByCard() handleEmbryoInStockByCard('embryoInStock')
} else { } else {
handleEmbryoInFastStock(0) handleEmbryoInFastStock(0)
} }
} }
const dialogTitle = computed(() => {
return fastKey.value === 'fastReceipt'
? fastInboundType.value === 1
? '生产完成-快捷入库'
: '胚衣-快捷入库'
: '查看详情'
})
const handleEmbryoInFastStock = (inboundType: number) => { const handleEmbryoInFastStock = (inboundType: number) => {
fastInboundType.value = inboundType fastInboundType.value = inboundType
fastKey.value = 'fastReceipt' fastKey.value = 'fastReceipt'
detailVisible.value = true detailVisible.value = true
detailData.value = {} detailData.value = {}
} }
const handleEmbryoInStockByCard = async () => { const handleEmbryoInStockByCard = async (
const firstWid = cardSelectList.value[0].warehouseId type: 'completeProduction' | 'embryoInStock',
if (cardSelectList.value.some((r) => r.warehouseId !== firstWid)) { ) => {
let operationList
if (type === 'completeProduction') {
operationList = cardSelectList.value.filter((r) => r.inboundType !== 2)
if (operationList.length === 0) {
ElMessage.error('客户定制商品,不能入库!')
return
}
} else {
operationList = cardSelectList.value
}
fastInboundType.value = type === 'completeProduction' ? 1 : 0
const firstWid = operationList[0].warehouseId
if (operationList.some((r) => r.warehouseId !== firstWid)) {
return ElMessage.error('请选择相同仓库的库存SKU!') return ElMessage.error('请选择相同仓库的库存SKU!')
} }
resetReceiptEditForm() resetReceiptEditForm()
...@@ -674,8 +700,7 @@ const handleEmbryoInStockByCard = async () => { ...@@ -674,8 +700,7 @@ const handleEmbryoInStockByCard = async () => {
} }
} }
receiptEditForm.value.warehouseId = firstWid receiptEditForm.value.warehouseId = firstWid
receiptEditForm.value.warehouseName = cardSelectList.value[0] receiptEditForm.value.warehouseName = operationList[0].warehouseName as string
.warehouseName as string
const wh = warehouseList.value.find((w) => w.id == firstWid) const wh = warehouseList.value.find((w) => w.id == firstWid)
if (wh) { if (wh) {
receiptEditForm.value.warehouseName = wh.name receiptEditForm.value.warehouseName = wh.name
...@@ -685,11 +710,16 @@ const handleEmbryoInStockByCard = async () => { ...@@ -685,11 +710,16 @@ const handleEmbryoInStockByCard = async () => {
background: 'rgba(0, 0, 0, 0.3)', background: 'rgba(0, 0, 0, 0.3)',
}) })
try { try {
const skus = cardSelectList.value.map((r) => r.thirdSkuCode as string) const skus = operationList.map((r) => r.thirdSkuCode as string)
const res = await getBySkuAndUserMarkApi(firstWid, skus.join(','), null) const res =
type === 'embryoInStock'
? await getBySkuAndUserMarkApi(firstWid, skus.join(','), null)
: await getBySkuAndUserMarkAndInboundTypeApi(
operationList.map((r) => r.operationNo as string),
)
if (res.code !== 200) return if (res.code !== 200) return
otherPurchaseData.value = res.data.map((item: InterskuList) => otherPurchaseData.value = res.data.map((item: InterskuList) =>
mapInterskuToProduct(item), mapInterskuToProduct(item, type),
) )
await fetchReceiptLocationList('') await fetchReceiptLocationList('')
const listRes = await warehouseInfoGetAll() const listRes = await warehouseInfoGetAll()
...@@ -758,7 +788,17 @@ const handleReceiptSave = async () => { ...@@ -758,7 +788,17 @@ const handleReceiptSave = async () => {
} catch { } catch {
return return
} }
const arr = otherPurchaseData.value const arr = otherPurchaseData.value.map((item) => {
const operationForReclaimList = cardSelectList.value.filter((r) =>
fastInboundType.value === 1
? `${r.userMark}${r.variantSku}` === item.warehouseSku
: r.thirdSkuCode === item.warehouseSku,
)
return {
...item,
operationForReclaimList: operationForReclaimList,
}
})
if (arr.length === 0) { if (arr.length === 0) {
ElMessage.error('请至少选择一条数据') ElMessage.error('请至少选择一条数据')
return return
...@@ -780,17 +820,31 @@ const handleReceiptSave = async () => { ...@@ -780,17 +820,31 @@ const handleReceiptSave = async () => {
} }
} }
const params = { const params = {
forNewProduct: fastInboundType.value === 1,
...receiptEditForm.value, ...receiptEditForm.value,
productList: otherPurchaseData.value, productList: arr,
} }
const loading = ElLoading.service({ const loading = ElLoading.service({
text: '保存中...', text: '保存中...',
background: 'rgba(0, 0, 0, 0.3)', background: 'rgba(0, 0, 0, 0.3)',
}) })
try { try {
await addInRecordApi(params) const res = await addInRecordApi(params)
ElMessage.success('保存成功') if (res.code !== 200) return
if (res.data && Array.isArray(res.data) && res.data.length > 0) {
ElMessageBox.alert(
`操作单号: ${res.data.map((e: number) => e).join(',')}入库失败`,
'提示',
{
type: 'error',
},
)
} else {
ElMessage.success('保存成功')
}
receiptDialogVisible.value = false receiptDialogVisible.value = false
search()
loadOrderStatusCounts()
} catch (e) { } catch (e) {
console.error(e) console.error(e)
} finally { } finally {
...@@ -800,11 +854,7 @@ const handleReceiptSave = async () => { ...@@ -800,11 +854,7 @@ const handleReceiptSave = async () => {
const handleProductionCompleteInStock = () => { const handleProductionCompleteInStock = () => {
// 客户定制的单子不能操作生产完成入库,提示:客户定制商品,不能入库! // 客户定制的单子不能操作生产完成入库,提示:客户定制商品,不能入库!
if (cardSelectList.value.length !== 0) { if (cardSelectList.value.length !== 0) {
if (cardSelectList.value.some((r) => r.inboundType === 2)) { handleEmbryoInStockByCard('completeProduction')
ElMessage.error('客户定制商品,不能入库!')
return
}
handleEmbryoInStockByCard()
} else { } else {
handleEmbryoInFastStock(1) handleEmbryoInFastStock(1)
} }
......
...@@ -45,7 +45,11 @@ ...@@ -45,7 +45,11 @@
</div> </div>
<div class="right"> <div class="right">
<div <div
v-if="['fastProduction', 'fastReceipt'].includes(fastKey)" v-if="
['fastProduction', 'fastReceipt', 'productionScan'].includes(
fastKey,
)
"
class="input" class="input"
> >
<el-input <el-input
...@@ -70,10 +74,7 @@ ...@@ -70,10 +74,7 @@
{{ detail?.userMark }} {{ detail?.userMark }}
</div> </div>
</div> </div>
<div <div :title="String(detail?.factoryOrderNumber)" class="div-item">
:title="String(detail?.factoryOrderNumber)"
class="div-item"
>
<span class="div-item-label" style="font-size: 18px" <span class="div-item-label" style="font-size: 18px"
>订单号:</span >订单号:</span
> >
...@@ -145,8 +146,9 @@ ...@@ -145,8 +146,9 @@
> >
<span class="div-item-label">挂起前状态:</span> <span class="div-item-label">挂起前状态:</span>
<div class="div-item-value"> <div class="div-item-value">
<ElTag v-if="detail.statusName" type="primary">{{ detail.statusName || '' }}</ElTag <ElTag v-if="detail.statusName" type="primary">{{
> detail.statusName || ''
}}</ElTag>
</div> </div>
</div> </div>
<div <div
...@@ -237,10 +239,13 @@ ...@@ -237,10 +239,13 @@
<div class="btn"> <div class="btn">
<div <div
:style="{ :style="{
visibility: visibility: [
fastKey === 'fastProduction' || fastKey === 'fastReceipt' 'fastProduction',
? 'visible' 'fastReceipt',
: 'hidden', 'productionScan',
].includes(fastKey)
? 'visible'
: 'hidden',
}" }"
class="btn-sure" class="btn-sure"
> >
...@@ -250,10 +255,19 @@ ...@@ -250,10 +255,19 @@
type="success" type="success"
@click="changeStatus" @click="changeStatus"
> >
{{ fastKey === 'fastProduction' ? '生产完成' : '快捷入库' }} {{
['fastProduction', 'productionScan'].includes(fastKey)
? '生产完成'
: '快捷入库'
}}
</el-button> </el-button>
<div class="check"> <div class="check">
<el-checkbox v-model="isAutoSure"> 自动完成上一单 </el-checkbox> <el-checkbox
v-if="fastKey !== 'productionScan'"
v-model="isAutoSure"
>
自动完成上一单
</el-checkbox>
</div> </div>
</div> </div>
<div v-if="fastKey !== 'fastReceipt'" class="btn-down"> <div v-if="fastKey !== 'fastReceipt'" class="btn-down">
...@@ -311,6 +325,7 @@ import { ...@@ -311,6 +325,7 @@ import {
downloadMaterialApi, downloadMaterialApi,
} from '@/api/podCnOrder' } from '@/api/podCnOrder'
import { cardImages, PodOrderRes } from '@/types/api/podCnOrder' import { cardImages, PodOrderRes } from '@/types/api/podCnOrder'
import { checkInventoryApi } from '@/api/factoryOrderNew'
import { showConfirm } from '@/utils/ui' import { showConfirm } from '@/utils/ui'
import { filePath } from '@/api/axios' import { filePath } from '@/api/axios'
import { computed, ref, watch } from 'vue' import { computed, ref, watch } from 'vue'
...@@ -320,10 +335,10 @@ interface HistoryDataItem { ...@@ -320,10 +335,10 @@ interface HistoryDataItem {
finished: boolean finished: boolean
} }
const title = computed(() => { const title = computed(() => {
if (props.fastKey === 'fastProduction') { if (['fastProduction', 'productionScan'].includes(props.fastKey)) {
return '快捷生产' return '快捷生产'
} else if (props.fastKey === 'fastReceipt') { } else if (props.fastKey === 'fastReceipt') {
return '快捷入库' return props.dialogTitle
} else { } else {
return '查看详情' return '查看详情'
} }
...@@ -334,6 +349,7 @@ export type FastProductionDetail = PodOrderRes & { ...@@ -334,6 +349,7 @@ export type FastProductionDetail = PodOrderRes & {
podOrderNo?: string | null podOrderNo?: string | null
podOrderProductId?: number | null podOrderProductId?: number | null
statusName?: string | null statusName?: string | null
productMark?: string | null
} }
const trackingNumberRef = ref() const trackingNumberRef = ref()
const historyData = ref<HistoryDataItem[]>([]) const historyData = ref<HistoryDataItem[]>([])
...@@ -384,22 +400,22 @@ const props = withDefaults( ...@@ -384,22 +400,22 @@ const props = withDefaults(
completeApi?: ( completeApi?: (
ids: number[], ids: number[],
detail: Record<string, unknown>, detail: Record<string, unknown>,
trigger?: 'manual' | 'auto',
) => Promise<unknown> ) => Promise<unknown>
downloadApi?: ( downloadApi?: (
ids: number[], ids: number[],
) => Promise<{ code?: number; message?: string }> ) => Promise<{ code?: number; message?: string }>
/** 打开弹框时「自动完成上一单」的初始勾选;默认 false,与原有 podCN 快捷生产一致 */
defaultAutoSure?: boolean defaultAutoSure?: boolean
/** 为 true 时展示「操作单号」一行,数据字段为 `operationNo`(不影响 podCN 默认) */
showOperationNoRow?: boolean showOperationNoRow?: boolean
/** 查询无数据时的提示 */
notFoundMessage?: string notFoundMessage?: string
/** 未生产完成提醒里对单号的称呼,如「生产单号」「操作单号」 */
pendingOrderLabel?: string pendingOrderLabel?: string
/** 未扫码时的提示 */
pleaseScanTip?: string pleaseScanTip?: string
/** 扫码输入为空时音频/提示文案 */
searchInputAudioTip?: string searchInputAudioTip?: string
/** 是否限制扫码 */
isLimitScan?: boolean
/** 限制扫码的提示 */
limitScanMessage?: string
dialogTitle?: string
}>(), }>(),
{ {
type: 0, type: 0,
...@@ -415,11 +431,13 @@ const props = withDefaults( ...@@ -415,11 +431,13 @@ const props = withDefaults(
notFoundMessage: '生产单不存在', notFoundMessage: '生产单不存在',
pendingOrderLabel: '生产单号', pendingOrderLabel: '生产单号',
pleaseScanTip: '请扫码生产单号', pleaseScanTip: '请扫码生产单号',
searchInputAudioTip: '请录入生产单号', searchInputAudioTip: '请录入生产单号???',
isLimitScan: false,
queryApi: (orderNumber: string) => getSubOrderBySubOrderNumber(orderNumber), queryApi: (orderNumber: string) => getSubOrderBySubOrderNumber(orderNumber),
completeApi: (ids: number[], detailData: Record<string, unknown>) => completeApi: (ids: number[], detailData: Record<string, unknown>) =>
productionQueryApi(ids[0], Number(detailData.podJomallOrderCnId || -1)), productionQueryApi(ids[0], Number(detailData.podJomallOrderCnId || -1)),
downloadApi: (ids: number[]) => downloadMaterialApi(ids), downloadApi: (ids: number[]) => downloadMaterialApi(ids),
dialogTitle: '',
}, },
) )
const emit = defineEmits(['update:detailVisible', 'close', 'onSuccess']) const emit = defineEmits(['update:detailVisible', 'close', 'onSuccess'])
...@@ -509,7 +527,9 @@ watch( ...@@ -509,7 +527,9 @@ watch(
const len = historyData.value const len = historyData.value
if ( if (
len.length > 0 && len.length > 0 &&
(props.fastKey === 'fastProduction' || props.fastKey === 'fastReceipt') ['fastProduction', 'fastReceipt', 'productionScan'].includes(
props.fastKey,
)
) { ) {
confirmQuery(len, 0) confirmQuery(len, 0)
} }
...@@ -541,7 +561,9 @@ const confirmQuery = (len: HistoryDataItem[], i: number) => { ...@@ -541,7 +561,9 @@ const confirmQuery = (len: HistoryDataItem[], i: number) => {
const el = len[i] const el = len[i]
showConfirm( showConfirm(
`${props.pendingOrderLabel} ${el.orderNumber} ${ `${props.pendingOrderLabel} ${el.orderNumber} ${
props.fastKey === 'fastProduction' ? '未生产' : '未入库' ['fastProduction', 'productionScan'].includes(props.fastKey)
? '未生产'
: '未入库'
}完成,取消则不提醒?`, }完成,取消则不提醒?`,
{ {
confirmButtonText: '确定', confirmButtonText: '确定',
...@@ -553,7 +575,13 @@ const confirmQuery = (len: HistoryDataItem[], i: number) => { ...@@ -553,7 +575,13 @@ const confirmQuery = (len: HistoryDataItem[], i: number) => {
TrackingNumber.value = el.orderNumber TrackingNumber.value = el.orderNumber
await trackCodeInput() await trackCodeInput()
await setData(el.orderNumber) await setData(el.orderNumber)
ElMessage.success('生产完成') ElMessage.success(
`${
['fastProduction', 'productionScan'].includes(props.fastKey)
? '生产完成'
: '入库完成'
}`,
)
if (len[i + 1]) { if (len[i + 1]) {
confirmQuery(len, i + 1) confirmQuery(len, i + 1)
} }
...@@ -580,21 +608,32 @@ const changeStatus = async () => { ...@@ -580,21 +608,32 @@ const changeStatus = async () => {
if (!detail.value || Object.keys(detail.value).length <= 1) { if (!detail.value || Object.keys(detail.value).length <= 1) {
return ElMessage.warning(props.pleaseScanTip) return ElMessage.warning(props.pleaseScanTip)
} }
showConfirm('确定生产完成?', { showConfirm(
confirmButtonText: '确定', `确定${
cancelButtonText: '取消', ['fastProduction', 'productionScan'].includes(props.fastKey)
type: 'warning', ? '生产完成'
}).then(() => { : '入库完成'
}?`,
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
},
).then(() => {
setData(historyKeyFromDetail(detail.value)) setData(historyKeyFromDetail(detail.value))
}) })
} }
const setData = async (orderNumber: string) => { const setData = async (
orderNumber: string,
trigger: 'manual' | 'auto' = 'manual',
) => {
if (!detail.value || detail.value?.id === -1) return if (!detail.value || detail.value?.id === -1) return
try { try {
const id = detail.value.id const id = detail.value.id
const res = (await props.completeApi( const res = (await props.completeApi(
[id], [id],
detail.value as unknown as Record<string, unknown>, detail.value as unknown as Record<string, unknown>,
trigger,
)) as unknown as BaseRespData< )) as unknown as BaseRespData<
{ {
factoryOrderNumber?: number factoryOrderNumber?: number
...@@ -618,16 +657,43 @@ const setData = async (orderNumber: string) => { ...@@ -618,16 +657,43 @@ const setData = async (orderNumber: string) => {
} }
emit('onSuccess', res.data) emit('onSuccess', res.data)
playAudio('weight_success') playAudio('weight_success')
detail.value = {
id: -1, if (trigger === 'auto') {
podJomallOrderCnId: -1, // new 快捷生产:扫码后直接将订单流转至生产中
imgList: [] as cardImages[], localStorage.setItem(props.historyStorageKey, JSON.stringify([]))
} else {
detail.value = {
id: -1,
podJomallOrderCnId: -1,
imgList: [] as cardImages[],
}
} }
TrackingNumber.value = '' TrackingNumber.value = ''
isDownloadImage.value = false isDownloadImage.value = false
trackingNumberRef.value && trackingNumberRef.value.focus() trackingNumberRef.value && trackingNumberRef.value.focus()
} catch (e) { } catch (e) {
console.error(e) console.error(e)
const err = e as BaseRespData<{
inventory: number
producingQuantity: number
availableInventory: number
thirdSkuCode?: string
}>
if (err?.code === 301) {
await ElMessageBox.alert(
`${err.data?.thirdSkuCode}库存不足,无法进入生产!请联系仓库管理人员核对库存。<br/>
库存数量:${err.data?.inventory},生产中的数量:${err.data?.producingQuantity}
<span style="color: red">可调配库存:${err.data?.availableInventory}</span>`,
'提示',
{
type: 'warning',
dangerouslyUseHTMLString: true,
},
).then(() => {
localStorage.setItem(props.historyStorageKey, JSON.stringify([]))
})
}
detail.value = { detail.value = {
id: -1, id: -1,
podJomallOrderCnId: -1, podJomallOrderCnId: -1,
...@@ -729,9 +795,10 @@ const trackCodeInput = async () => { ...@@ -729,9 +795,10 @@ const trackCodeInput = async () => {
const orderNumber = TrackingNumber.value const orderNumber = TrackingNumber.value
if (isAutoSure.value) { if (!['productionScan'].includes(props.fastKey) && isAutoSure.value) {
await setData( await setData(
historyData.value[historyData.value.length - 1].orderNumber || '', historyData.value[historyData.value.length - 1].orderNumber || '',
'auto',
) )
} }
...@@ -742,9 +809,67 @@ const trackCodeInput = async () => { ...@@ -742,9 +809,67 @@ const trackCodeInput = async () => {
} }
detail.value = normalizeDetail(res.data) detail.value = normalizeDetail(res.data)
// 扫码后限制
if (props.isLimitScan) {
if (
detail.value.productMark &&
['custom_normal', 'normal'].includes(detail.value.productMark)
) {
detail.value = { id: -1, podJomallOrderCnId: -1, imgList: [] }
localStorage.setItem(props.historyStorageKey, JSON.stringify([]))
trackingNumberRef.value && trackingNumberRef.value.focus()
TrackingNumber.value = ''
return showConfirm(props.limitScanMessage || '', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
}
}
if (isDownloadImage.value) { if (isDownloadImage.value) {
download() download()
} }
// 工厂订单new 校验库存 生产扫码
if (props.fastKey === 'productionScan') {
try {
await checkInventoryApi(
detail.value.id,
String(detail.value.status ?? ''),
)
} catch (inventoryErr) {
const err = inventoryErr as BaseRespData<{
inventory: number
producingQuantity: number
availableInventory: number
thirdSkuCode?: string
}>
if (err?.code === 301) {
historyData.value = []
localStorage.setItem(props.historyStorageKey, JSON.stringify([]))
detail.value = emptyDetail()
playAudio('weight_search_error', props.searchInputAudioTip)
trackingNumberRef.value && trackingNumberRef.value.focus()
TrackingNumber.value = ''
await ElMessageBox.alert(
`${err.data?.thirdSkuCode}库存不足,无法进入生产!请联系仓库管理人员核对库存。<br/>
库存数量:${err.data?.inventory},生产中的数量:${err.data?.producingQuantity}
<span style="color: red">可调配库存:${err.data?.availableInventory}</span>`,
'提示',
{
type: 'warning',
dangerouslyUseHTMLString: true,
},
)
return
}
throw inventoryErr
}
await setData(detail.value.id.toString(), 'auto')
}
playAudio('weight_search_success') playAudio('weight_search_success')
trackingNumberRef.value && trackingNumberRef.value.focus() trackingNumberRef.value && trackingNumberRef.value.focus()
......
<template> <template>
<div class="page card h-100 flex-gap-10 overflow-hidden flex"> <div class="page card h-100 flex-gap-10 overflow-hidden flex">
<div class="order-status"> <div
<ElTree class="order-status-wrapper"
ref="treeRef" :class="{ 'is-collapsed': statusSidebarCollapsed }"
default-expand-all >
:expand-on-click-node="false" <div class="order-status">
:default-expanded-keys="['ALL']" <ElTree
:highlight-current="true" ref="treeRef"
node-key="status" default-expand-all
:data="statusTree" :expand-on-click-node="false"
:props="{ children: 'children', label: 'statusName' }" :default-expanded-keys="['ALL']"
class="status-tree" :highlight-current="true"
@node-click="handleStatusNodeClick" node-key="status"
> :data="statusTree"
<template #default="{ node, data }"> :props="{ children: 'children', label: 'statusName' }"
<div class="tree-node"> class="status-tree"
<div class="tree-node-label-wrapper"> @node-click="handleStatusNodeClick"
<span class="tree-node-label">{{ data.statusName }}</span> >
<template #default="{ node, data }">
<div class="tree-node">
<div class="tree-node-label-wrapper">
<span class="tree-node-label">{{ data.statusName }}</span>
<span
v-if="
data.status !== 'ALL' &&
(data.quantity || data.quantity === 0)
"
class="tree-node-count"
>
{{ `(${data.quantity})` }}
</span>
</div>
<span <span
v-if=" v-if="data.children && data.children.length"
data.status !== 'ALL' && class="tree-node-expand"
(data.quantity || data.quantity === 0) @click.stop="toggleExpand(node)"
"
class="tree-node-count"
> >
{{ `(${data.quantity})` }} <el-icon
><ArrowUp v-if="node.expanded" /><ArrowDown v-else
/></el-icon>
</span> </span>
</div> </div>
<span </template>
v-if="data.children && data.children.length" </ElTree>
class="tree-node-expand" </div>
@click.stop="toggleExpand(node)" <div
> class="sidebar-toggle"
<el-icon title="收起/展开"
><ArrowUp v-if="node.expanded" /><ArrowDown v-else @click="toggleStatusSidebar"
/></el-icon> >
</span> <span
</div> class="sidebar-toggle-icon"
</template> :class="{ 'is-collapsed': statusSidebarCollapsed }"
</ElTree> />
</div>
</div> </div>
<div class="order-content flex-1 flex-column overflow-hidden"> <div class="order-content flex-1 flex-column overflow-hidden">
<div v-if="!isSpecialLayout" class="header"> <div v-if="!isSpecialLayout" class="header">
...@@ -294,6 +309,26 @@ ...@@ -294,6 +309,26 @@
></ElOption> ></ElOption>
</ElSelect> </ElSelect>
</ElFormItem> </ElFormItem>
<ElFormItem label="尺码筛选">
<ElSelect
v-model="searchForm.size"
multiple
collapse-tags
collapse-tags-tooltip
placeholder="请选择"
clearable
filterable
:teleported="false"
style="width: 150px"
>
<ElOption
v-for="(item, index) in sizes"
:key="index"
:value="item"
:label="item"
></ElOption>
</ElSelect>
</ElFormItem>
<ElFormItem label="客户标签"> <ElFormItem label="客户标签">
<ElSelect <ElSelect
v-model="searchForm.tagsIdArr" v-model="searchForm.tagsIdArr"
...@@ -531,6 +566,7 @@ ...@@ -531,6 +566,7 @@
>拣胚完成</ElButton >拣胚完成</ElButton
> >
</span> </span>
<span v-if="status === 'PENDING_PICK'" class="item"> <span v-if="status === 'PENDING_PICK'" class="item">
<ElButton type="danger" @click="handlePickFail">拣胚失败</ElButton> <ElButton type="danger" @click="handlePickFail">拣胚失败</ElButton>
</span> </span>
...@@ -546,7 +582,7 @@ ...@@ -546,7 +582,7 @@
</span> </span>
<span v-if="status === 'PENDING_PACKING'" class="item"> <span v-if="status === 'PENDING_PACKING'" class="item">
<ElButton type="success" @click="handleSeedingWall" <ElButton type="success" @click="handleSeedingWall"
>播种墙配货</ElButton >配货打单</ElButton
> >
</span> </span>
<span v-if="status === 'PENDING_PACKING'" class="item"> <span v-if="status === 'PENDING_PACKING'" class="item">
...@@ -563,8 +599,8 @@ ...@@ -563,8 +599,8 @@
>申请补胚</ElButton >申请补胚</ElButton
> >
</span> </span>
<span v-if="status === 'IN_PRODUCTION'" class="item"> <span v-if="['IN_PRODUCTION'].includes(status)" class="item">
<ElButton type="success" @click="handleQuickProduction" <ElButton type="success" @click="handleQuickProduction()"
>快捷生产</ElButton >快捷生产</ElButton
> >
</span> </span>
...@@ -756,79 +792,100 @@ ...@@ -756,79 +792,100 @@
> >
<template #operation="{ row }"> <template #operation="{ row }">
<div class="main-table-operation"> <div class="main-table-operation">
<ElButton <span v-if="status === 'PENDING_RECEIVE'" class="item">
v-if="status === 'PENDING_RECEIVE'" <ElButton
type="primary" type="primary"
link link
size="small" size="small"
@click.stop="handleSingleConfirmOrder(row)" @click.stop="handleSingleConfirmOrder(row)"
> >
{{ {{
pendingAcceptSubTab === 'ACCEPT_FAIL_OUT_OF_STOCK' pendingAcceptSubTab === 'ACCEPT_FAIL_OUT_OF_STOCK'
? '重新接单' ? '重新接单'
: '接单' : '接单'
}} }}
</ElButton> </ElButton>
<ElButton </span>
<span
v-if=" v-if="
showPendingLogisticsUpdateAddress() && showPendingLogisticsUpdateAddress() &&
row.shipmentType === 1 row.shipmentType === 1
" "
type="primary" class="item"
link
size="small"
@click.stop="openUpdateReceiverAddress(row)"
> >
修改地址 <ElButton
</ElButton> type="primary"
<ElButton link
v-if="showChangeLogistics(row)" size="small"
type="warning" @click.stop="openUpdateReceiverAddress(row)"
link >
size="small" 修改地址
@click.stop="handleChangeLogistics(row)" </ElButton>
> </span>
更换物流方式 <span v-if="showChangeLogistics(row)" class="item">
</ElButton> <ElButton
<ElButton type="warning"
link
size="small"
@click.stop="handleChangeLogistics(row)"
>
更换物流方式
</ElButton>
</span>
<span
v-if="showPendingLogisticsUpdateAddress()" v-if="showPendingLogisticsUpdateAddress()"
type="success" class="item"
link
size="small"
@click.stop="handleRefreshReceiverAddress(row)"
> >
{{ <ElButton
row.shipmentType === 0 ? '同步物流/地址' : '同步地址' type="success"
}} link
</ElButton> size="small"
@click.stop="handleRefreshReceiverAddress(row)"
<ElButton >
{{
row.shipmentType === 0 ? '同步物流/地址' : '同步地址'
}}
</ElButton>
</span>
<span
v-if="status === 'SUSPEND' && suspendedSubTab !== 1" v-if="status === 'SUSPEND' && suspendedSubTab !== 1"
type="primary" class="item"
link
size="small"
@click.stop="handleCancelSuspend(row)"
> >
取消挂起 <ElButton
</ElButton> type="warning"
<ElButton link
size="small"
@click.stop="handleCancelSuspend(row)"
>
取消挂起
</ElButton>
</span>
<span
v-if="status === 'SUSPEND' && suspendedSubTab === 1" v-if="status === 'SUSPEND' && suspendedSubTab === 1"
type="primary" class="item"
link
size="small"
@click.stop="handleInterceptionSuccess(row)"
> >
拦截成功 <ElButton
</ElButton> type="success"
<ElButton link
size="small"
@click.stop="handleInterceptionSuccess(row)"
>
拦截成功
</ElButton>
</span>
<span
v-if="status === 'SUSPEND' && suspendedSubTab === 1" v-if="status === 'SUSPEND' && suspendedSubTab === 1"
type="primary" class="item"
link
size="small"
@click.stop="handleInterceptionFail(row)"
> >
拦截失败 <ElButton
</ElButton> type="danger"
link
size="small"
@click.stop="handleInterceptionFail(row)"
>
拦截失败
</ElButton>
</span>
</div> </div>
</template> </template>
</TableView> </TableView>
...@@ -951,12 +1008,14 @@ ...@@ -951,12 +1008,14 @@
:fast-key="fastKey" :fast-key="fastKey"
:default-auto-sure="true" :default-auto-sure="true"
:show-operation-no-row="true" :show-operation-no-row="true"
:is-limit-scan="isLimitScan"
limit-scan-message="G和CB类的操作单无效操作"
not-found-message="操作单不存在" not-found-message="操作单不存在"
pending-order-label="操作单号" pending-order-label="操作单号"
please-scan-tip="请扫码操作单号" please-scan-tip="请扫码操作单号"
search-input-audio-tip="请录入操作单号" search-input-audio-tip="请录入操作单号"
history-storage-key="historyFactoryOrderNewData" history-storage-key="historyFactoryOrderNewData"
tracking-placeholder="扫描枪输入操作单号,录入下一单本单自动生产完成,最后一单扫两次完成生产" tracking-placeholder="扫描枪输入操作单号"
:query-api="getOperationByNo" :query-api="getOperationByNo"
:complete-api="completeOperationById" :complete-api="completeOperationById"
:download-api="downloadOperationById" :download-api="downloadOperationById"
...@@ -1136,6 +1195,7 @@ import { ...@@ -1136,6 +1195,7 @@ import {
updateReceiverAddressApi, updateReceiverAddressApi,
updateRemarkApi, updateRemarkApi,
completeDeliveryApi, completeDeliveryApi,
productionScanApi,
getByOperationNoLogApi, getByOperationNoLogApi,
listByNoPodOrderApi, listByNoPodOrderApi,
orderWeighingPodOrderApi, orderWeighingPodOrderApi,
...@@ -1187,6 +1247,11 @@ import { ElTag } from 'element-plus' ...@@ -1187,6 +1247,11 @@ import { ElTag } from 'element-plus'
const resultInfo = ref<ResultInfoDataItem[]>([]) const resultInfo = ref<ResultInfoDataItem[]>([])
const resultRefs = ref() const resultRefs = ref()
const statusSidebarCollapsed = ref(false)
const toggleStatusSidebar = () => {
statusSidebarCollapsed.value = !statusSidebarCollapsed.value
}
const batchManageRef = ref<InstanceType<typeof BatchManageTable>>() const batchManageRef = ref<InstanceType<typeof BatchManageTable>>()
const waitingRestockRef = ref<InstanceType<typeof WaitingRestockTable>>() const waitingRestockRef = ref<InstanceType<typeof WaitingRestockTable>>()
const cardLayoutRef = ref<InstanceType<typeof CardLayout>>() const cardLayoutRef = ref<InstanceType<typeof CardLayout>>()
...@@ -1205,7 +1270,7 @@ const interceptSuccessForm = ref<{ suspendSussessType: number | undefined }>({ ...@@ -1205,7 +1270,7 @@ const interceptSuccessForm = ref<{ suspendSussessType: number | undefined }>({
suspendSussessType: undefined, suspendSussessType: undefined,
}) })
const interceptSuccessRows = ref<FactoryOrderNewListData[]>([]) const interceptSuccessRows = ref<FactoryOrderNewListData[]>([])
const sizes = ['FS', 'XS', 'S', 'M', 'L', 'XL', 'XXL', '3XL', '4XL', '5XL']
const { const {
userMarkList, userMarkList,
receiverCountryList, receiverCountryList,
...@@ -1708,7 +1773,7 @@ const mainColumns = computed(() => [ ...@@ -1708,7 +1773,7 @@ const mainColumns = computed(() => [
{ {
prop: 'operation', prop: 'operation',
label: '操作', label: '操作',
minWidth: 300, minWidth: 100,
align: 'center', align: 'center',
slot: 'operation', slot: 'operation',
fixed: 'right', fixed: 'right',
...@@ -1755,13 +1820,13 @@ const operationOrderColumns = [ ...@@ -1755,13 +1820,13 @@ const operationOrderColumns = [
key: 'imageAry', key: 'imageAry',
prop: 'imageAry', prop: 'imageAry',
label: '商品图片', label: '商品图片',
minWidth: 100, minWidth: 180,
align: 'center', align: 'center',
render: (row: operateOrderListData) => { render: (row: operateOrderListData) => {
const list = parseOperationOrderImageAry(row.imageAry) const list = parseOperationOrderImageAry(row.imageAry)
if (!list.length) { if (!list.length) {
return ( return (
<div> <div style="display:flex;gap:4px;">
<el-image <el-image
src={row.variantImage} src={row.variantImage}
style="width:50px;height:50px" style="width:50px;height:50px"
...@@ -2816,10 +2881,25 @@ const handleReplenishFail = () => { ...@@ -2816,10 +2881,25 @@ const handleReplenishFail = () => {
} }
const getOperationByNo = (operationNo: string) => const getOperationByNo = (operationNo: string) =>
getByOperationNoLogApi(operationNo) as Promise<{ data?: unknown }> getByOperationNoLogApi(operationNo) as Promise<{ data?: unknown }>
const completeOperationById = (ids: number[]) => completeDeliveryApi(ids) const completeOperationById = (
ids: number[],
detailData?: Record<string, unknown>,
trigger: 'manual' | 'auto' = 'manual',
) => {
if (trigger === 'auto') {
const detailStatus = String(detailData?.status ?? '')
return productionScanApi(ids[0], detailStatus)
}
return completeDeliveryApi(ids)
}
const downloadOperationById = (ids: number[]) => const downloadOperationById = (ids: number[]) =>
downloadOperationMaterialApi(ids) downloadOperationMaterialApi(ids)
const handleFastProductionSuccess = (data: ResultInfoDataItem[]) => { const handleFastProductionSuccess = (data: ResultInfoDataItem[]) => {
if (fastKey.value === 'productionScan') {
ElMessage.success('操作成功')
return
}
const result = data[0] const result = data[0]
if (!result.status) { if (!result.status) {
ElMessageBox.alert( ElMessageBox.alert(
...@@ -2830,6 +2910,8 @@ const handleFastProductionSuccess = (data: ResultInfoDataItem[]) => { ...@@ -2830,6 +2910,8 @@ const handleFastProductionSuccess = (data: ResultInfoDataItem[]) => {
}, },
) )
return return
} else {
ElMessage.success('操作成功')
} }
} }
const createLogisticsSuccess = (data: ResultInfoDataItem[]) => { const createLogisticsSuccess = (data: ResultInfoDataItem[]) => {
...@@ -2848,6 +2930,7 @@ const fastClose = () => { ...@@ -2848,6 +2930,7 @@ const fastClose = () => {
refreshCurrentView({ isRefreshTree: true }) refreshCurrentView({ isRefreshTree: true })
} }
const handleViewDetail = async (item: operateOrderListData) => { const handleViewDetail = async (item: operateOrderListData) => {
isLimitScan.value = false
const loading = ElLoading.service({ const loading = ElLoading.service({
fullscreen: true, fullscreen: true,
text: '加载中...', text: '加载中...',
...@@ -2865,9 +2948,11 @@ const handleViewDetail = async (item: operateOrderListData) => { ...@@ -2865,9 +2948,11 @@ const handleViewDetail = async (item: operateOrderListData) => {
loading.close() loading.close()
} }
} }
const isLimitScan = ref(false)
const handleQuickProduction = () => { const handleQuickProduction = () => {
detailVisible.value = true detailVisible.value = true
fastKey.value = 'fastProduction' fastKey.value = 'productionScan'
isLimitScan.value = true
detailData.value = {} detailData.value = {}
} }
const handleSinglePrint = () => { const handleSinglePrint = () => {
...@@ -2987,9 +3072,145 @@ onMounted(() => { ...@@ -2987,9 +3072,145 @@ onMounted(() => {
.page { .page {
display: flex; display: flex;
} }
.main-table-operation {
display: flex;
flex-direction: column;
gap: 2px;
}
.order-status-wrapper {
position: relative;
flex-shrink: 0;
width: 180px;
transition: width 0.3s ease;
&.is-collapsed {
width: 0;
.order-status {
opacity: 0;
visibility: hidden;
}
}
}
.sidebar-toggle {
position: absolute;
top: 50%;
right: -12px;
transform: translateY(-50%);
z-index: 10;
width: 12px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
background: #fff;
border: 1px solid #dcdfe6;
border-left: none;
border-radius: 0 4px 4px 0;
cursor: pointer;
box-shadow: 1px 0 4px rgba(0, 0, 0, 0.06);
user-select: none;
&:hover {
background: #f5f7fa;
.sidebar-toggle-icon {
border-right-color: #409eff;
&.is-collapsed {
border-right-color: transparent;
border-left-color: #409eff;
}
}
}
}
.sidebar-toggle-icon {
display: block;
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-right: 6px solid #909399;
transition: border-color 0.2s;
&.is-collapsed {
border-right: none;
border-left: 6px solid #909399;
}
}
.order-status-wrapper {
position: relative;
flex-shrink: 0;
width: 180px;
transition: width 0.3s ease;
&.is-collapsed {
width: 0;
.order-status {
opacity: 0;
visibility: hidden;
}
}
}
.sidebar-toggle {
position: absolute;
top: 50%;
right: -12px;
transform: translateY(-50%);
z-index: 10;
width: 12px;
height: 48px;
display: flex;
align-items: center;
justify-content: center;
background: #fff;
border: 1px solid #dcdfe6;
border-left: none;
border-radius: 0 4px 4px 0;
cursor: pointer;
box-shadow: 1px 0 4px rgba(0, 0, 0, 0.06);
user-select: none;
&:hover {
background: #f5f7fa;
.sidebar-toggle-icon {
border-right-color: #409eff;
&.is-collapsed {
border-right-color: transparent;
border-left-color: #409eff;
}
}
}
}
.sidebar-toggle-icon {
display: block;
width: 0;
height: 0;
border-top: 5px solid transparent;
border-bottom: 5px solid transparent;
border-right: 6px solid #909399;
transition: border-color 0.2s;
&.is-collapsed {
border-right: none;
border-left: 6px solid #909399;
}
}
.order-status { .order-status {
width: 180px; width: 180px;
height: 100%;
overflow: auto;
transition: opacity 0.3s ease;
:deep(.el-tree-node__content) { :deep(.el-tree-node__content) {
height: 30px; height: 30px;
......
...@@ -13,7 +13,7 @@ ...@@ -13,7 +13,7 @@
> >
<template #header> <template #header>
<div class="title"> <div class="title">
<span>播种墙配货</span> <span>{{ isNewOrder ? '配货打单' : '播种墙配货' }}</span>
<span v-if="socketConnect === 'online'" class="online">[在线]</span> <span v-if="socketConnect === 'online'" class="online">[在线]</span>
<span v-else class="offline">[离线]</span> <span v-else class="offline">[离线]</span>
<ElButton <ElButton
...@@ -169,7 +169,17 @@ ...@@ -169,7 +169,17 @@
> >
{{ podOrderDetailsData?.pickingNumber }} {{ podOrderDetailsData?.pickingNumber }}
</div> </div>
<span style="font-size: 30px">件商品</span> <span
v-if="
podOrderDetailsData?.pickingNumber != null &&
podOrderDetailsData?.purchaseNumber != null &&
podOrderDetailsData.pickingNumber ===
podOrderDetailsData.purchaseNumber
"
style="font-size: 30px"
>件已配齐</span
>
<span v-else style="font-size: 30px">件商品</span>
</div> </div>
<div v-else class="box-top-item-box-index-text"> <div v-else class="box-top-item-box-index-text">
单件商品<span style="color: rgb(0, 255, 0)">(配齐)</span 单件商品<span style="color: rgb(0, 255, 0)">(配齐)</span
...@@ -288,6 +298,7 @@ import socket from '@/utils/websocket' ...@@ -288,6 +298,7 @@ import socket from '@/utils/websocket'
import { WarehouseListData } from '@/types/index' import { WarehouseListData } from '@/types/index'
import { filePath } from '@/api/axios.ts' import { filePath } from '@/api/axios.ts'
import { ElButton, ElIcon, ElTag } from 'element-plus' import { ElButton, ElIcon, ElTag } from 'element-plus'
import { BaseRespData } from '@/types/api'
const { getCLodop } = useLodop() const { getCLodop } = useLodop()
...@@ -793,6 +804,7 @@ const getPackingData = async (code: string) => { ...@@ -793,6 +804,7 @@ const getPackingData = async (code: string) => {
} }
} }
const res = await getPackingDataApi(url, params) const res = await getPackingDataApi(url, params)
if (res.code !== 200) { if (res.code !== 200) {
ElMessage.warning(res.message) ElMessage.warning(res.message)
isLock.value = false isLock.value = false
...@@ -829,7 +841,24 @@ const getPackingData = async (code: string) => { ...@@ -829,7 +841,24 @@ const getPackingData = async (code: string) => {
// } // }
} catch (error) { } catch (error) {
console.log(error) const err = error as BaseRespData<{
inventory: number
producingQuantity: number
availableInventory: number
thirdSkuCode?: string
}>
if (props.isNewOrder && err?.code === 301) {
loading.close()
await ElMessageBox.alert(
`${err.data?.thirdSkuCode}库存不足,无法进入生产!请联系仓库管理人员核对库存。<br/>
库存数量:${err.data?.inventory},生产中的数量:${err.data?.producingQuantity}<span style="color: red">可调配库存:${err.data?.availableInventory}</span>`,
'提示',
{
type: 'warning',
dangerouslyUseHTMLString: true,
},
)
}
} finally { } finally {
isLock.value = false isLock.value = false
productionOrder.value = '' productionOrder.value = ''
...@@ -1394,7 +1423,7 @@ const reconnectWebSocket = async () => { ...@@ -1394,7 +1423,7 @@ const reconnectWebSocket = async () => {
font-size: 60px; font-size: 60px;
color: red; color: red;
text-align: center; text-align: center;
width: 120px; width: 80px;
font-weight: 600; font-weight: 600;
} }
.box-top-item-box-index-text { .box-top-item-box-index-text {
...@@ -1406,7 +1435,7 @@ const reconnectWebSocket = async () => { ...@@ -1406,7 +1435,7 @@ const reconnectWebSocket = async () => {
color: red; color: red;
display: inline-block; display: inline-block;
text-align: center; text-align: center;
width: 90px; width: 80px;
font-weight: 600; font-weight: 600;
} }
.box-top-item-status { .box-top-item-status {
......
...@@ -7,13 +7,6 @@ import vueJsx from '@vitejs/plugin-vue-jsx' ...@@ -7,13 +7,6 @@ import vueJsx from '@vitejs/plugin-vue-jsx'
import compression from 'vite-plugin-compression' import compression from 'vite-plugin-compression'
export default defineConfig({ export default defineConfig({
base: '/', base: '/',
server:{
proxy: {
'/api/': {
target: 'http://172.16.17.244:8060',
},
},
},
plugins: [ plugins: [
vue(), vue(),
......
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