Commit 5ac50c9e by qinjianhui

feat: 拣胚完成

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