Commit 5ac50c9e by qinjianhui

feat: 拣胚完成

parent 71f385c2
...@@ -55,6 +55,12 @@ ...@@ -55,6 +55,12 @@
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib"> <li class="dib">
<span class="icon iconfont">&#xe605;</span>
<div class="name">提示</div>
<div class="code-name">&amp;#xe605;</div>
</li>
<li class="dib">
<span class="icon iconfont">&#xe62e;</span> <span class="icon iconfont">&#xe62e;</span>
<div class="name">查看详情</div> <div class="name">查看详情</div>
<div class="code-name">&amp;#xe62e;</div> <div class="code-name">&amp;#xe62e;</div>
...@@ -132,9 +138,9 @@ ...@@ -132,9 +138,9 @@
<pre><code class="language-css" <pre><code class="language-css"
>@font-face { >@font-face {
font-family: 'iconfont'; font-family: 'iconfont';
src: url('iconfont.woff2?t=1729077025378') format('woff2'), src: url('iconfont.woff2?t=1774496872018') format('woff2'),
url('iconfont.woff?t=1729077025378') format('woff'), url('iconfont.woff?t=1774496872018') format('woff'),
url('iconfont.ttf?t=1729077025378') format('truetype'); url('iconfont.ttf?t=1774496872018') format('truetype');
} }
</code></pre> </code></pre>
<h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3> <h3 id="-iconfont-">第二步:定义使用 iconfont 的样式</h3>
...@@ -161,6 +167,15 @@ ...@@ -161,6 +167,15 @@
<ul class="icon_lists dib-box"> <ul class="icon_lists dib-box">
<li class="dib"> <li class="dib">
<span class="icon iconfont icon-tishi"></span>
<div class="name">
提示
</div>
<div class="code-name">.icon-tishi
</div>
</li>
<li class="dib">
<span class="icon iconfont icon-chakanxiangqing"></span> <span class="icon iconfont icon-chakanxiangqing"></span>
<div class="name"> <div class="name">
查看详情 查看详情
...@@ -279,6 +294,14 @@ ...@@ -279,6 +294,14 @@
<li class="dib"> <li class="dib">
<svg class="icon svg-icon" aria-hidden="true"> <svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-tishi"></use>
</svg>
<div class="name">提示</div>
<div class="code-name">#icon-tishi</div>
</li>
<li class="dib">
<svg class="icon svg-icon" aria-hidden="true">
<use xlink:href="#icon-chakanxiangqing"></use> <use xlink:href="#icon-chakanxiangqing"></use>
</svg> </svg>
<div class="name">查看详情</div> <div class="name">查看详情</div>
......
@font-face { @font-face {
font-family: "iconfont"; /* Project id 4462827 */ font-family: "iconfont"; /* Project id 4462827 */
src: url('iconfont.woff2?t=1729077025378') format('woff2'), src: url('iconfont.woff2?t=1774496872018') format('woff2'),
url('iconfont.woff?t=1729077025378') format('woff'), url('iconfont.woff?t=1774496872018') format('woff'),
url('iconfont.ttf?t=1729077025378') format('truetype'); url('iconfont.ttf?t=1774496872018') format('truetype');
} }
.iconfont { .iconfont {
...@@ -13,6 +13,10 @@ ...@@ -13,6 +13,10 @@
-moz-osx-font-smoothing: grayscale; -moz-osx-font-smoothing: grayscale;
} }
.icon-tishi:before {
content: "\e605";
}
.icon-chakanxiangqing:before { .icon-chakanxiangqing:before {
content: "\e62e"; content: "\e62e";
} }
......
...@@ -6,6 +6,13 @@ ...@@ -6,6 +6,13 @@
"description": "", "description": "",
"glyphs": [ "glyphs": [
{ {
"icon_id": "3833188",
"name": "提示",
"font_class": "tishi",
"unicode": "e605",
"unicode_decimal": 58885
},
{
"icon_id": "22718987", "icon_id": "22718987",
"name": "查看详情", "name": "查看详情",
"font_class": "chakanxiangqing", "font_class": "chakanxiangqing",
......
...@@ -107,6 +107,7 @@ export function transferOldFlowApi(ids: (number | string)[]) { ...@@ -107,6 +107,7 @@ export function transferOldFlowApi(ids: (number | string)[]) {
export function confirmOrderWithWarehouseApi( export function confirmOrderWithWarehouseApi(
ids: (number | string)[], ids: (number | string)[],
warehouseId: number | string, warehouseId: number | string,
warehouseName: string,
) { ) {
return axios.post< return axios.post<
never, never,
...@@ -118,7 +119,11 @@ export function confirmOrderWithWarehouseApi( ...@@ -118,7 +119,11 @@ export function confirmOrderWithWarehouseApi(
status?: boolean status?: boolean
}[] }[]
> >
>('factory/podOrder/ordersAccepted', { podOrderIds: ids, warehouseId }) >('factory/podOrder/ordersAccepted', {
podOrderIds: ids,
warehouseId,
warehouseName,
})
} }
export function cancelOrderWithReasonApi( export function cancelOrderWithReasonApi(
...@@ -188,9 +193,23 @@ export function restockCheckApi(id: number | string) { ...@@ -188,9 +193,23 @@ export function restockCheckApi(id: number | string) {
) )
} }
export function pickCompleteByIdsDataApi(ids: (number | string)[]) {
return axios.post<
never,
BaseRespData<{
overallMessage?: string
pickingSituationList?: PickCompleteData[]
allAvailableOrderIds?: number[]
partialAvailableOrderIds?: number[]
unavailableOrderIds?: number[]
}>
>('factory/podOrderOperation/getPickingSituation', ids)
}
export function pickCompleteApi(ids: (number | string)[]) { export function pickCompleteApi(ids: (number | string)[]) {
return axios.post<never, BaseRespData<PickCompleteData[]>>( return axios.post<never, BaseRespData<void>>(
'factory/podOrderOperation/listByIds', 'factory/podOrderOperation/pickingComplete',
ids, ids,
) )
} }
......
<template> <template>
<i <i
v-if="unicodeIcon" v-if="unicodeIcon"
class="erpIconfont erp unicode-icon" class="iconfont factory unicode-icon"
v-html="unicodeIcon" v-html="unicodeIcon"
></i> ></i>
<svg v-else class="svg-icon erp" aria-hidden="true"> <svg v-else class="svg-icon factory" aria-hidden="true">
<slot name="title"></slot> <slot name="title"></slot>
<use :xlink:href="svgIcon"></use> <use :xlink:href="svgIcon"></use>
</svg> </svg>
...@@ -19,7 +19,7 @@ const props = defineProps({ ...@@ -19,7 +19,7 @@ const props = defineProps({
} }
}) })
const unicodeIcon = computed(() => { const unicodeIcon = computed(() => {
if (props.name.match(/^x[a-f0-9]{4}$/)) { if (props.name.match(/^x[a-f0-9]{4,}$/)) {
return `&#${props.name};` return `&#${props.name};`
} }
return undefined return undefined
......
...@@ -210,14 +210,16 @@ export interface PickCompleteData { ...@@ -210,14 +210,16 @@ export interface PickCompleteData {
warehouseName?: string warehouseName?: string
skuImage?: string skuImage?: string
productName?: string productName?: string
styleNo?: string supplierProductNo?: string
stockSku?: string thirdSkuCode?: string
pickQuantity?: number selectedQuantity?: number
availableStock?: number availableInventory?: number
stockQuantity?: number inventory?: number
producingQuantity?: number producingQuantity?: number
occupiedQuantity?: number occupyInventory?: number
pickStatus?: 'success' | 'partial' | 'fail' pickingStatus?: string
availableOrderIds?: number[]
allOrderIds?: number[]
} }
export interface PickFailData { export interface PickFailData {
......
...@@ -42,12 +42,14 @@ import { confirmOrderWithWarehouseApi } from '@/api/factoryOrderNew' ...@@ -42,12 +42,14 @@ import { confirmOrderWithWarehouseApi } from '@/api/factoryOrderNew'
import type { WarehouseListData } from '@/types' import type { WarehouseListData } from '@/types'
const emit = defineEmits<{ const emit = defineEmits<{
success: [data: { success: [
data: {
factoryOrderNumber?: string factoryOrderNumber?: string
message?: string message?: string
id: number | string id: number | string
status?: boolean status?: boolean
}[]] }[],
]
}>() }>()
const visible = ref(false) const visible = ref(false)
...@@ -89,11 +91,15 @@ const handleClose = () => { ...@@ -89,11 +91,15 @@ const handleClose = () => {
const handleSubmit = async () => { const handleSubmit = async () => {
if (!formRef.value) return if (!formRef.value) return
await formRef.value.validate() await formRef.value.validate()
const warehouseName = warehouseList.value.find(
(item) => item.id === form.warehouseId,
)?.name
submitLoading.value = true submitLoading.value = true
try { try {
const res = await confirmOrderWithWarehouseApi( const res = await confirmOrderWithWarehouseApi(
orderIds.value, orderIds.value,
form.warehouseId, form.warehouseId,
warehouseName || '',
) )
if (res.code !== 200) return if (res.code !== 200) return
visible.value = false visible.value = false
......
...@@ -2,10 +2,15 @@ ...@@ -2,10 +2,15 @@
<ElDialog <ElDialog
v-model="visible" v-model="visible"
title="拣胚完成" title="拣胚完成"
width="1200px" width="1400px"
:close-on-click-modal="false" :close-on-click-modal="false"
@close="handleClose" @close="handleClose"
> >
<div v-if="pickData" class="pick-order-data">
<div class="pick-order-data-message">
<Icon style="width: 24px; height: 24px" name="tishi" />
<span> {{ pickData.overallMessage }}! </span>
</div>
<div class="pick-complete-actions" style="margin-bottom: 10px"> <div class="pick-complete-actions" style="margin-bottom: 10px">
<span class="item"> <span class="item">
<ElButton type="success" @click="handleCreateInbound"> <ElButton type="success" @click="handleCreateInbound">
...@@ -15,51 +20,55 @@ ...@@ -15,51 +20,55 @@
</div> </div>
<div class="table-view"> <div class="table-view">
<TableView <TableView
:paginated-data="tableData" :paginated-data="pickData.pickingSituationList"
:columns="columns" :columns="columns"
serial-numberable serial-numberable
selectionable selectionable
@selection-change="handleSelectionChange"
> >
<template #skuImage="{ row }"> <template #skuImage="{ row }">
<el-image <el-image
v-if="row.variantImage" v-if="row.skuImage"
:src="row.variantImage" :src="row.skuImage"
style="width: 50px; height: 50px" style="width: 50px; height: 50px"
fit="contain" fit="contain"
:preview-src-list="[row.variantImage]" :preview-src-list="[row.skuImage]"
preview-teleported preview-teleported
/> />
</template> </template>
<template #pickQuantity="{ row }"> <template #pickQuantity="{ row }">
<span style="color: #e6a23c; font-weight: bold">{{ <span style="color: #e6a23c; font-weight: bold">{{
row.pickQuantity row.selectedQuantity
}}</span> }}</span>
</template> </template>
<template #pickStatus="{ row }"> <template #pickStatus="{ row }">
<span v-if="row.pickStatus === 'fail'" style="color: #f56c6c"> <span
v-if="row.pickingStatus === 'fail'"
style="color: #f56c6c; font-weight: 500"
>
✕ 无法拣胚 ✕ 无法拣胚
</span> </span>
<span v-else-if="row.pickStatus === 'partial'" class="item"> <span v-else-if="row.pickingStatus === 'partial'" class="item">
<ElButton type="warning" size="small">调整拣胚顺序</ElButton> <ElButton type="warning" size="small">调整拣胚顺序</ElButton>
</span> </span>
<span v-else style="color: #67c23a"> ✓ 直接拣胚 </span> <span
v-else-if="row.pickingStatus === 'success'"
style="color: #67c23a; font-weight: 500"
>
✓ 直接拣胚
</span>
<span v-else style="color: #999; font-weight: 500">未知状态</span>
</template> </template>
</TableView> </TableView>
</div> </div>
</div>
<template #footer> <template #footer>
<div class="dialog-footer" style="text-align: center"> <div class="dialog-footer" style="text-align: center">
<span class="item"> <span class="item">
<ElButton @click="visible = false">取消</ElButton> <ElButton @click="visible = false">取消</ElButton>
</span> </span>
<span class="item"> <span class="item">
<ElButton <ElButton type="primary" @click="handleSubmit"> 确定 </ElButton>
type="primary"
:loading="submitLoading"
@click="handleSubmit"
>
确定
</ElButton>
</span> </span>
</div> </div>
</template> </template>
...@@ -69,26 +78,33 @@ ...@@ -69,26 +78,33 @@
<script setup lang="ts"> <script setup lang="ts">
import { ref } from 'vue' import { ref } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
import { pickCompleteApi } from '@/api/factoryOrderNew' import {
pickCompleteByIdsDataApi,
pickCompleteApi,
} from '@/api/factoryOrderNew'
import type { PickCompleteData } from '@/types/api/factoryOrderNew' import type { PickCompleteData } from '@/types/api/factoryOrderNew'
import TableView from '@/components/TableView.vue' import TableView from '@/components/TableView.vue'
import type { CustomColumn } from '@/types/table' import Icon from '@/components/Icon.vue'
interface PickData {
overallMessage?: string
pickingSituationList?: PickCompleteData[]
allAvailableOrderIds?: number[]
partialAvailableOrderIds?: number[]
unavailableOrderIds?: number[]
}
const emit = defineEmits<{ const emit = defineEmits<{
success: [] success: []
}>() }>()
const visible = ref(false) const visible = ref(false)
const submitLoading = ref(false) const pickData = ref<PickData | null>(null)
const tableData = ref<PickCompleteData[]>([]) const selections = ref<PickCompleteData[]>([])
const orderIds = ref<(number | string)[]>([])
const columns: CustomColumn<PickCompleteData>[] = [ const columns = [
{ {
key: 'warehouseName',
prop: 'warehouseName', prop: 'warehouseName',
label: '仓库名称', label: '仓库名称',
minWidth: 100, minWidth: 120,
}, },
{ {
key: 'skuImage', key: 'skuImage',
...@@ -104,48 +120,55 @@ const columns: CustomColumn<PickCompleteData>[] = [ ...@@ -104,48 +120,55 @@ const columns: CustomColumn<PickCompleteData>[] = [
minWidth: 120, minWidth: 120,
showOverflowTooltip: true, showOverflowTooltip: true,
}, },
{ key: 'styleNo', prop: 'styleNo', label: '款号', minWidth: 80 },
{ key: 'stockSku', prop: 'stockSku', label: '库存SKU', minWidth: 120 },
{ {
key: 'pickQuantity', prop: 'supplierProductNo',
prop: 'pickQuantity', label: '款号',
label: '本次拣胚数量', width: 100,
minWidth: 110, align: 'center',
},
{
key: 'thirdSkuCode',
prop: 'thirdSkuCode',
label: '库存SKU',
align: 'center', align: 'center',
width: 180,
},
{
key: 'selectedQuantity',
prop: 'selectedQuantity',
label: '本次拣胚数量',
width: 110,
align: 'right',
slot: 'pickQuantity', slot: 'pickQuantity',
}, },
{ {
key: 'availableStock', prop: 'availableInventory',
prop: 'availableStock',
label: '可调配库存', label: '可调配库存',
minWidth: 100, width: 100,
align: 'center', align: 'right',
}, },
{ {
key: 'stockQuantity', prop: 'inventory',
prop: 'stockQuantity',
label: '库存数量', label: '库存数量',
minWidth: 90, width: 90,
align: 'center', align: 'right',
}, },
{ {
key: 'producingQuantity',
prop: 'producingQuantity', prop: 'producingQuantity',
label: '生产中数量', label: '生产中数量',
minWidth: 100, width: 100,
align: 'center', align: 'right',
}, },
{ {
key: 'occupiedQuantity', prop: 'occupyInventory',
prop: 'occupiedQuantity',
label: '占用数量', label: '占用数量',
minWidth: 90, width: 90,
align: 'center', align: 'right',
}, },
{ {
key: 'pickStatus', key: 'pickStatus',
label: '拣胚情况', label: '拣胚情况',
minWidth: 130, width: 130,
align: 'center', align: 'center',
fixed: 'right', fixed: 'right',
slot: 'pickStatus', slot: 'pickStatus',
...@@ -153,34 +176,54 @@ const columns: CustomColumn<PickCompleteData>[] = [ ...@@ -153,34 +176,54 @@ const columns: CustomColumn<PickCompleteData>[] = [
] ]
const open = async (ids: (number | string)[]) => { const open = async (ids: (number | string)[]) => {
orderIds.value = ids selections.value = []
visible.value = true pickData.value = null
const loading = ElLoading.service({
text: '操作中...',
background: 'rgba(0, 0, 0, 0.3)',
})
try { try {
const res = await pickCompleteApi(ids) const res = await pickCompleteByIdsDataApi(ids)
tableData.value = res.data || [] if (res.code !== 200) return
} catch (_e) { pickData.value = res.data || null
tableData.value = [] visible.value = true
} catch (e) {
console.error(e)
} finally {
loading.close()
} }
} }
const handleClose = () => { const handleClose = () => {
tableData.value = [] pickData.value = null
} }
const handleCreateInbound = () => { const handleCreateInbound = () => {
ElMessage.info('创建入库单功能待实现') ElMessage.info('创建入库单功能待实现')
} }
const handleSelectionChange = (selection: PickCompleteData[]) => {
selections.value = selection
}
const handleSubmit = async () => { const handleSubmit = async () => {
submitLoading.value = true const loading = ElLoading.service({
text: '操作中...',
background: 'rgba(0, 0, 0, 0.3)',
})
const orderIds = pickData.value?.pickingSituationList
?.map((item) => item.availableOrderIds)
.flat()
try { try {
const res = await pickCompleteApi(orderIds as (number | string)[])
if (res.code !== 200) return
ElMessage.success('拣胚完成') ElMessage.success('拣胚完成')
visible.value = false visible.value = false
emit('success') emit('success')
} catch (_e) { } catch (e) {
ElMessage.error('操作失败') console.error(e)
} finally { } finally {
submitLoading.value = false loading.close()
} }
} }
...@@ -191,4 +234,12 @@ defineExpose({ open }) ...@@ -191,4 +234,12 @@ defineExpose({ open })
.table-view { .table-view {
height: 600px; height: 600px;
} }
.pick-order-data-message {
font-size: 14px;
color: #f56c6c;
margin-bottom: 10px;
font-weight: bold;
display: flex;
align-items: center;
}
</style> </style>
...@@ -714,9 +714,9 @@ ...@@ -714,9 +714,9 @@
<!-- 表格布局 --> <!-- 表格布局 -->
<div v-if="isTableLayout" class="table-content"> <div v-if="isTableLayout" class="table-content">
<splitDiv v-loading="loading" size="55"> <splitDiv size="55">
<template #top> <template #top>
<div class="table-list flex-1 overflow-hidden"> <div v-loading="loading" class="table-list flex-1 overflow-hidden">
<TableView <TableView
ref="tableRef" ref="tableRef"
highlight-current-row highlight-current-row
...@@ -763,7 +763,7 @@ ...@@ -763,7 +763,7 @@
@tab-click="handleTabClick" @tab-click="handleTabClick"
> >
<el-tab-pane name="product" label="包含商品"> <el-tab-pane name="product" label="包含商品">
<div class="sub-table-wrapper"> <div v-loading="subLoading" class="sub-table-wrapper">
<TableView <TableView
:paginated-data="productList" :paginated-data="productList"
:columns="productColumns" :columns="productColumns"
...@@ -772,7 +772,7 @@ ...@@ -772,7 +772,7 @@
</div> </div>
</el-tab-pane> </el-tab-pane>
<el-tab-pane name="log" label="操作日志"> <el-tab-pane name="log" label="操作日志">
<div class="detail-table-content"> <div v-loading="subLoading" class="detail-table-content">
<LogList :log-list="logList" /> <LogList :log-list="logList" />
<div v-if="!logList.length" class="empty-content"> <div v-if="!logList.length" class="empty-content">
暂无数据 暂无数据
...@@ -935,6 +935,7 @@ const cardLayoutStatuses = [ ...@@ -935,6 +935,7 @@ const cardLayoutStatuses = [
'PENDING_PACKING', 'PENDING_PACKING',
] ]
const specialLayoutStatuses = ['BATCH_MANAGE', 'AWAITING_RESTOCK'] const specialLayoutStatuses = ['BATCH_MANAGE', 'AWAITING_RESTOCK']
const subLoading = ref(false)
const isCardLayout = computed(() => cardLayoutStatuses.includes(status.value)) const isCardLayout = computed(() => cardLayoutStatuses.includes(status.value))
const isSpecialLayout = computed(() => const isSpecialLayout = computed(() =>
specialLayoutStatuses.includes(status.value), specialLayoutStatuses.includes(status.value),
...@@ -1578,6 +1579,7 @@ const getOrderDetailsById = async (tabName?: 'product' | 'log') => { ...@@ -1578,6 +1579,7 @@ const getOrderDetailsById = async (tabName?: 'product' | 'log') => {
const id = currentRow.value.id const id = currentRow.value.id
const isSuspend = status.value === 'SUSPEND' const isSuspend = status.value === 'SUSPEND'
const effectiveTab = tabName ?? activeTab.value const effectiveTab = tabName ?? activeTab.value
subLoading.value = true
try { try {
if (effectiveTab === 'product') { if (effectiveTab === 'product') {
productList.value = [] productList.value = []
...@@ -1594,6 +1596,8 @@ const getOrderDetailsById = async (tabName?: 'product' | 'log') => { ...@@ -1594,6 +1596,8 @@ const getOrderDetailsById = async (tabName?: 'product' | 'log') => {
} }
} catch (e) { } catch (e) {
console.error(e) console.error(e)
} finally{
subLoading.value = false
} }
} }
watch(currentRow, (row) => { watch(currentRow, (row) => {
...@@ -2031,7 +2035,7 @@ const handlePrintPickOrder = async () => { ...@@ -2031,7 +2035,7 @@ const handlePrintPickOrder = async () => {
} }
} }
const handlePickComplete = () => { const handlePickComplete = () => {
// if (!ensureSelection()) return if (!ensureSelection()) return
pickCompleteDialogRef.value?.open(getSelectedIds()) pickCompleteDialogRef.value?.open(getSelectedIds())
} }
const handlePickFail = () => { const handlePickFail = () => {
......
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