Commit d3309db6 by qinjianhui

fix: 操作列功能-申请补胚

parent 8ba23b17
......@@ -22,6 +22,7 @@ export function getFactoryOrderNewListApi(
currentPage: number,
pageSize: number,
status?: string,
subStatus?: string,
) {
return axios.post<never, BasePaginationData<FactoryOrderNewListData>>(
'factory/podOrder/list_page',
......@@ -30,6 +31,7 @@ export function getFactoryOrderNewListApi(
currentPage,
pageSize,
status,
subStatus,
},
)
}
......@@ -304,3 +306,17 @@ export function syncReceiverAddress(data: number[]) {
data,
)
}
export function updateRemarkApi(id: number | string, remark: string) {
return axios.post<never, BaseRespData<void>>(
'factory/podOrder/updateRemark',
{ id, remark },
)
}
export function applyForReplenishByIdApi(id: number | string) {
return axios.post<never, BaseRespData<unknown>>(
'factory/podOrder/applyForReplenish',
{ id },
)
}
<template>
<ElDialog
v-model="visible"
title="申请补胚"
width="900px"
:close-on-click-modal="false"
>
<div class="replenish-tip">请选择具体的操作单,申请补胚</div>
<div v-loading="loading" class="replenish-card-grid">
<div
v-for="item in cardList"
:key="item.id"
class="replenish-card-item"
@click="toggleSelect(item)"
>
<CommonCard
:card-item="item"
:active="isSelected(item)"
:show-sku="false"
:show-product-info="false"
:image-field="'variantImage'"
>
<template #bottom_left>
<span
v-if="item.factorySubOrderNumber"
class="operation-number"
:title="`操作单号:${item.factorySubOrderNumber}`"
>
{{ item.factorySubOrderNumber }}
</span>
</template>
<template #info>
<div class="card-info-grid">
<div class="card-info-row full">
<span
class="info-value ellipsis"
:title="(item.productName as string) || ''"
>
{{ item.productName }}
</span>
</div>
<div class="card-info-row">
<span class="info-label">工艺:</span>
<span class="info-value">{{ item.craftName }}</span>
</div>
<div class="card-info-row">
<span class="info-label">店铺单号:</span>
<span class="info-value">{{ item.shopNumber }}</span>
</div>
<div class="card-info-row">
<span class="info-label">客户号:</span>
<span class="info-value">{{ item.userMark }}</span>
</div>
<div class="card-info-row">
<span class="info-label">变体SKU</span>
<span class="info-value ellipsis" :title="(item.variantSku as string) || ''">
{{ item.variantSku }}
</span>
</div>
<div class="card-info-row">
<span class="info-label">库存SKU</span>
<span class="info-value ellipsis" :title="(item.thirdSkuCode as string) || ''">
{{ item.thirdSkuCode }}
</span>
</div>
<div class="card-info-row">
<span class="info-label">款号:</span>
<span class="info-value">{{ item.supplierProductNo }}</span>
</div>
<div v-if="item.batchArrangeNumber" class="card-info-row">
<span class="info-label">批次号:</span>
<span class="info-value">{{ item.batchArrangeNumber }}</span>
</div>
<div class="card-info-row">
<span class="info-label">状态:</span>
<span class="info-value">{{ item.statusName }}</span>
</div>
</div>
</template>
</CommonCard>
</div>
<div v-if="!loading && cardList.length === 0" class="replenish-empty">
暂无数据
</div>
</div>
<template #footer>
<div style="text-align: center">
<ElButton @click="visible = false">取消</ElButton>
<ElButton type="primary" :loading="submitting" @click="handleConfirm">
确定
</ElButton>
</div>
</template>
</ElDialog>
</template>
<script setup lang="ts">
import { ref } from 'vue'
import { ElMessage } from 'element-plus'
import CommonCard from '@/components/CommonCard.vue'
import { applyForReplenishByIdApi } from '@/api/factoryOrderNew'
interface CardItem {
id: number | string
[key: string]: unknown
}
const emit = defineEmits<{
success: []
}>()
const visible = ref(false)
const loading = ref(false)
const submitting = ref(false)
const cardList = ref<CardItem[]>([])
const selectedItems = ref<CardItem[]>([])
const productId = ref<number | string>()
const isSelected = (item: CardItem) =>
selectedItems.value.some((s) => s.id === item.id)
const toggleSelect = (item: CardItem) => {
const idx = selectedItems.value.findIndex((s) => s.id === item.id)
if (idx >= 0) {
selectedItems.value.splice(idx, 1)
} else {
selectedItems.value.push(item)
}
}
const open = async (id: number | string) => {
productId.value = id
selectedItems.value = []
cardList.value = []
visible.value = true
loading.value = true
try {
const res = await applyForReplenishByIdApi(id)
cardList.value = Array.isArray(res.data) ? res.data : []
} catch (e) {
console.error(e)
} finally {
loading.value = false
}
}
const handleConfirm = async () => {
if (!selectedItems.value.length) {
return ElMessage.warning('请选择操作单')
}
submitting.value = true
try {
await applyForReplenishByIdApi(productId.value!)
ElMessage.success('申请补胚成功')
visible.value = false
emit('success')
} catch (e) {
console.error(e)
} finally {
submitting.value = false
}
}
defineExpose({ open })
</script>
<style scoped lang="scss">
.replenish-tip {
font-size: 14px;
color: #606266;
margin-bottom: 12px;
}
.replenish-card-grid {
display: grid;
grid-template-columns: repeat(3, 1fr);
gap: 12px;
max-height: 500px;
overflow-y: auto;
min-height: 200px;
}
.replenish-card-item {
cursor: pointer;
}
.replenish-empty {
grid-column: 1 / -1;
display: flex;
align-items: center;
justify-content: center;
color: #909399;
font-size: 14px;
min-height: 200px;
}
.operation-number {
font-size: 12px;
color: #409eff;
}
.card-info-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 4px;
font-size: 12px;
margin-top: 6px;
.full {
grid-column: 1 / -1;
}
}
.card-info-row {
display: flex;
overflow: hidden;
}
.info-label {
flex-shrink: 0;
color: #909399;
}
.info-value {
flex: 1;
min-width: 0;
&.ellipsis {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
</style>
......@@ -132,8 +132,8 @@
<ElFormItem label="数量">
<el-radio-group v-model="searchForm.multi">
<el-radio-button :value="false">单件</el-radio-button>
<el-radio-button :value="true">多件</el-radio-button>
<el-radio-button :value="false" @click="toggleMulti(false)">单件</el-radio-button>
<el-radio-button :value="true" @click="toggleMulti(true)">多件</el-radio-button>
</el-radio-group>
</ElFormItem>
......@@ -415,7 +415,7 @@
</ElFormItem>
<ElFormItem>
<ElButton type="primary" @click="refreshCurrentView">
<ElButton type="primary" @click="() => refreshCurrentView()">
查询
</ElButton>
<ElButton @click="reset"> 重置 </ElButton>
......@@ -426,9 +426,9 @@
<!-- ====== 操作按钮栏 ====== -->
<div v-if="!isSpecialLayout" class="operation-list">
<span v-if="status === 'PENDING_RECEIVE'" class="item">
<ElButton type="success" @click="handleConfirmOrder"
>确认接单</ElButton
>
<ElButton type="success" @click="handleConfirmOrder">
{{ pendingAcceptSubTab === 'ACCEPT_FAIL_OUT_OF_STOCK' ? '重新接单' : '确认接单' }}
</ElButton>
</span>
<span
v-if="status === 'PENDING_RECEIVE' || status === 'SUSPEND'"
......@@ -669,16 +669,18 @@
<div
class="status-subtab"
:class="{ active: pendingAcceptSubTab === 'PENDING_RECEIVE' }"
@click="handlePendingAcceptTabClick('PENDING_RECEIVE')"
>
待接单<span> ({{ 0 }}) </span>
待接单<span> ({{ pendingAcceptCounts.pendingCount }}) </span>
</div>
<div
class="status-subtab"
:class="{
active: pendingAcceptSubTab === 'ACCEPT_FAIL_OUT_OF_STOCK',
}"
@click="handlePendingAcceptTabClick('ACCEPT_FAIL_OUT_OF_STOCK')"
>
接单失败-缺货<span> ({{ 0 }}) </span>
接单失败-缺货<span> ({{ pendingAcceptCounts.acceptFailOutOfStockCount }}) </span>
</div>
</div>
<!-- 批次管理 -->
......@@ -714,7 +716,19 @@
selectionable
@selection-change="handleMainSelectionChange"
@row-click="handleRowClick"
/>
>
<template #operation="{ row }">
<ElButton
v-if="status === 'PENDING_RECEIVE'"
type="primary"
link
size="small"
@click.stop="handleSingleArrange(row)"
>
排单
</ElButton>
</template>
</TableView>
</div>
<ElPagination
v-model:current-page="currentPage"
......@@ -795,6 +809,11 @@
@success="() => refreshCurrentView({ isRefreshTree: true })"
/>
<ApplyReplenishDialog
ref="applyReplenishDialogRef"
@success="() => refreshCurrentView({ isRefreshTree: true })"
/>
<PodMakeOrder
v-model="podOrderVisible"
:print-order="printOrder"
......@@ -817,9 +836,11 @@ import {
ArrowUp,
CaretTop,
CaretBottom,
Edit,
} from '@element-plus/icons-vue'
import { computed, onMounted, ref, watch } from 'vue'
import {
ElButton,
ElForm,
ElFormItem,
ElMessage,
......@@ -859,7 +880,8 @@ import {
downloadMaterialApi,
composingNewPodOrderDesignImages,
printNewPodOrderProductionOrderApi,
syncReceiverAddress
syncReceiverAddress,
updateRemarkApi,
} from '@/api/factoryOrderNew'
import {
getListCraftApi,
......@@ -888,6 +910,7 @@ import CardLayout from './component/CardLayout.vue'
import BatchManageTable from './component/BatchManageTable.vue'
import WaitingRestockTable from './component/WaitingRestockTable.vue'
import ArrangeDialog from './component/ArrangeDialog.vue'
import ApplyReplenishDialog from './component/ApplyReplenishDialog.vue'
import CreateLogisticDialog from '@/views/order/podCN/components/CreateLogisticDialog.vue'
import UpdateCustomDeclarationInfoDialog from '@/views/order/podCN/components/UpdateCustomDeclarationInfoDialog.vue'
......@@ -915,6 +938,7 @@ const status = ref<string>('PENDING_RECEIVE')
const pendingAcceptSubTab = ref<'PENDING_RECEIVE' | 'ACCEPT_FAIL_OUT_OF_STOCK'>(
'PENDING_RECEIVE',
)
const pendingAcceptCounts = ref({ pendingCount: 0, acceptFailOutOfStockCount: 0 })
const suspendedTabs = [
{ label: '客户拦截', value: 'CUSTOMER_INTERCEPT', count: 0 },
{ label: '地址异常', value: 'ADDRESS_EXCEPTION', count: 0 },
......@@ -981,6 +1005,15 @@ const productTypeGroups = ref<ProductTypeGroup[]>([
},
])
const toggleMulti = (val: boolean) => {
if (searchForm.value.multi === val) {
setTimeout(() => {
if (searchForm.value.multi === val) {
searchForm.value.multi = undefined
}
}, 0)
}
}
const changeReplaceShipment = () => {
searchForm.value.shipmentType = ''
}
......@@ -1191,7 +1224,7 @@ const mainColumns = [
},
]
const productColumns = [
const baseProductColumns = [
{
key: 'productImage',
prop: 'productImage',
......@@ -1256,9 +1289,61 @@ const productColumns = [
label: '申报价值($)',
width: 100,
},
{ key: 'remark', prop: 'remark', label: '备注', width: 160 },
{
key: 'remark',
prop: 'remark',
label: '备注',
width: 160,
render: ({ row }: { row: ProductListData }) => {
return (
<div style="display:flex;align-items:center;gap:4px">
<span>{row?.remark || ''}</span>
<el-icon
style="cursor:pointer;color:#409eff;flex-shrink:0"
onClick={(e: Event) => {
e.stopPropagation()
handleEditRemark(row)
}}
>
<Edit />
</el-icon>
</div>
)
},
},
]
const productColumns = computed(() => {
if (status.value === 'PENDING_DELIVERY') {
return [
...baseProductColumns,
{
key: 'operation',
prop: 'operation',
label: '操作',
width: 120,
fixed: 'right',
render: ({ row }: { row: ProductListData }) => {
return (
<ElButton
type="warning"
link
size="small"
onClick={(e: Event) => {
e.stopPropagation()
handleSubApplyReplenish(row)
}}
>
申请补胚
</ElButton>
)
},
},
]
}
return baseProductColumns
})
const getQueryPayload = () => ({
...searchForm.value,
startTime: dateRange.value?.[0] || null,
......@@ -1291,13 +1376,23 @@ const {
return res.data
})
}
const currentSubStatus =
status.value === 'PENDING_RECEIVE' ? pendingAcceptSubTab.value : undefined
return getFactoryOrderNewListApi(
getQueryPayload(),
page,
size,
status.value === 'ALL' ? undefined : status.value,
currentSubStatus,
).then(async (res) => {
const { records } = res.data
const extra = res.data as unknown as Record<string, unknown>
if (status.value === 'PENDING_RECEIVE') {
pendingAcceptCounts.value = {
pendingCount: (extra.pendingCount as number) ?? 0,
acceptFailOutOfStockCount: (extra.acceptFailOutOfStockCount as number) ?? 0,
}
}
await nextTick(() => {
tableRef.value.setCurrentRow(records[0])
currentRow.value = (records as never)[0]
......@@ -1322,6 +1417,7 @@ const cardLayoutRef = ref<InstanceType<typeof CardLayout>>()
const batchManageRef = ref<InstanceType<typeof BatchManageTable>>()
const waitingRestockRef = ref<InstanceType<typeof WaitingRestockTable>>()
const arrangeDialogRef = ref<InstanceType<typeof ArrangeDialog>>()
const applyReplenishDialogRef = ref<InstanceType<typeof ApplyReplenishDialog>>()
const createLogisticDialogRef = ref()
const updateCustomsDialogVisible = ref(false)
const weightDialogRef = ref()
......@@ -1370,6 +1466,11 @@ const handleStatusNodeClick = (node: StatusTreeNode) => {
refreshCurrentView()
}
}
const handlePendingAcceptTabClick = (tab: 'PENDING_RECEIVE' | 'ACCEPT_FAIL_OUT_OF_STOCK') => {
if (pendingAcceptSubTab.value === tab) return
pendingAcceptSubTab.value = tab
refreshTableList()
}
const toggleExpand = (node: { expanded?: boolean }) => {
node.expanded = !node.expanded
}
......@@ -1440,6 +1541,25 @@ const handleTabClick = (tab: TabsPaneContext) => {
void getOrderDetailsById(name)
}
const handleEditRemark = async (row: ProductListData) => {
try {
const { value } = await ElMessageBox.prompt('请输入备注', '提示', {
inputValue: row.remark || '',
confirmButtonText: '确认',
cancelButtonText: '取消',
})
await updateRemarkApi(row.id, value)
ElMessage.success('备注修改成功')
void getOrderDetailsById('product')
} catch {
// cancelled
}
}
const handleSubApplyReplenish = (row: ProductListData) => {
applyReplenishDialogRef.value?.open(row.id)
}
const handleConfirmOrder = () => {
if (!ensureSelection()) return
confirmOrderDialogRef.value?.open(getSelectedIds())
......@@ -1546,6 +1666,13 @@ const handleArrange = async () => {
showAutoSwitch: true,
})
}
const handleSingleArrange = (row: FactoryOrderNewListData) => {
arrangeDialogRef.value?.open({
productIdList: [row.id],
requestUrl: 'factory/podOrder/updateLogisticsToArrange',
showAutoSwitch: true,
})
}
const podOrderVisible = ref(false)
const warehouseList = ref<WarehouseListData[]>([])
const loadWarehouseList = async () => {
......
# 每个状态调用接口及字段说明
# 新订单
## 待接单、待创建物流、配货中、待发货、已完成、已取消、已归档
- 主表格分页查询接口: `factory/podOrder/list_page` post 请求
- 请求参数:
- 平台: `platform`,筛选时传平台 type
- 状态: `status`
- 工艺:`craftCode`
- 库存 SKU:`thirdSkuCode`
- 款号:`supplierProductNo`
- 批次号:`batchArrangeNumber`
- 操作单号: `orderNumber`
- 商品类型: `productMark`
- 数量: `multi`
- 时间类型: `timeType`
- 开始时间: `startTime`
- 结束时间: `endTime`
- 订单号: `factoryOrderNumber`
- 客户: `userMark`
- Variant SKU: `sku`
- 物流跟踪号: `trackingNumber`
- 收件国家: `receiverCountry`
- 是否代发: `replaceShipment` 筛选时传 0 和 1,0:不代发,1:代发
- ERP 标签: `tagsIdArr` 筛选时传数组,数组中传 ERP 标签 id
- 订单来源: `source` 筛选时传订单来源 id
- 尺码筛选: `size` 筛选时传尺码
- 自有物流公司: `logisticsCompanyCode` 筛选时传自有物流公司 id
- 拦截订单: `interceptStatus` 筛选传拦截订单 id
- 规范素材: `standardDesignImage` 筛选传 0 和 1,0:不规范,1:规范
- 页码: `currentPage`
- 每页条数: `pageSize`
- 点击主表格每行后会加载子表格下数据
- 子表格包含商品Tab接口 `factory/podOrder/get` get 请求,
- 参数: `id` 主表格每行 id
- 子表格包含操作日志Tab接口 `factory/podOrder/getLog` get 请求,
- 参数: `id` 主表格每行 id
- 字段说明:
-- 平台: `platform`
-- 状态: `status`
-- 工艺:`craftCode`
-- 库存 SKU:`thirdSkuCode`
-- 款号:`supplierProductNo`
-- 批次号:`batchArrangeNumber`
-- 操作单号: `orderNumber`
-- 商品类型: `productMark`
-- 数量: `multi`
-- 时间类型: `timeType`
-- 开始时间: `startTime`
-- 结束时间: `endTime`
-- 订单号: `factoryOrderNumber`
-- 客户: `userMark`
-- Variant SKU: `sku`
-- 物流跟踪号: `trackingNumber`
-- 收件国家: `receiverCountry`
-- 是否代发: `replaceShipment`
-- ERP 标签: `tagsIdArr`
-- 订单来源: `source`
-- 尺码筛选: `size`
-- 自有物流公司: `logisticsCompanyCode`
-- 拦截订单: `interceptStatus`
-- 规范素材: `standardDesignImage`
-- 店铺单号: `shopNumber`
-- 订单状态: `statusName`
-- 物流方式: `logisticsWayName`
-- 总克重: `weight`
-- 商品总数量: `productNum`
-- 收货人: `receiverName`
-- 收货人电话: `receiverPhone`
-- 收货人邮编: `receiverCode`
-- 收货地址: `receiverAddress`
-- 创建时间: `createTime`
-- 接单时间: `acceptTime`
-- 完成时间: `finishTime`
-- 客户标签: `customerTags`
## 待排单、待补胚、生产中、待配货
- 接口: `factory/podOrderBatchDownload/list_page` post 请求
- 请求参数:
- 页码: `currentPage`
- 每页条数: `pageSize`
## 批次管理
- 接口: `factory/podOrderBatchDownload/list_page` post 请求
- 请求参数:
- 页码: `currentPage`
- 每页条数: `pageSize`
- 开始时间: `startTime`
- 结束时间: `endTime`
- 创建人: `employeeId` 筛选时创建人 id
- 列表创建人: `employeeAccount`
- 工艺类型: `craftType` 传工艺类型 value
- 下载状态: `downloadStatus` 传 0 和 1,0:未下载,1:已下载
- 排版状态: `syntheticStatus` 传 0 和 1,0:否,1:是
- 自动排版: `automaticComposing` 传 0 和 1,0:否,1:是
- 批次号: `batchArrangeNumber`
- 字段:
- 开始时间: `startTime`
- 结束时间: `endTime`
- 创建人: `employeeId`
- 列表创建人: `employeeAccount`
- 工艺类型: `craftType`
- 下载状态: `downloadStatus`
- 排版状态: `syntheticStatus`
- 自动排版: `automaticComposing`
- 批次号: `batchArrangeNumber`
- 订单数量: `productNum`
- 素材数量: `materialNum`
- 规范素材: `standardDesignImage`
- 失败原因: `failReason`
- 创建时间: `createTime`
- 完成时间: `finishTime`
- 自动排版: `automaticComposing`
- 排版参数: `composingParam`
## 等待补货
- 接口: `factory/podOrderBatchDownload/list_page`
- 请求参数:
- 页码: `currentPage`
- 每页条数: `pageSize`
- 字段: 暂时还不清楚,只需空出位置,以便后续开发
## 挂起
- 主表格分页查询接口: `factory/podOrderPauseControl/list_page` post 请求
- 点击主表格每行后会加载子表格下数据
- 子表格包含商品Tab接口 `factory/podOrderPauseControl/get` get 请求,
- 参数: `id` 主表格每行 id
- 子表格包含操作日志Tab接口 `factory/podOrderPauseControl/getLog` get 请求,
- 参数: `id` 主表格每行 id
- 请求参数:
- 页码: `currentPage`
- 每页条数: `pageSize`
- 字段: 暂时还不清楚,只需空出位置,以便后续开发
- 注意:挂起状态和待接单、待接单、待创建物流、配货中、待发货、已完成、已取消、已归档页面一致,只是接口不一样,返回的返回的数据结构暂时还不清楚是否一样,所以先按照不一样处理,到挂起状态时,调用不一样的接口
- 查询条件
- 数量: 当点击同一个字段时,取消选中状态,**例如: 当前状态在多件,再点击一次多件,取消选中状态**
- 主表格操作列
- 待接单状态下添加`排单按钮`,和批量排单的接口一致,区别是这里只能操作一条数据
- 子表格备注列
- 可修改备注,在值的后面加一个编辑图标,如图一所示
- 点击编辑图标后,弹出一个`prompt` 输入框,提示,请输入备注
- 点击确定后,调用`factory/podOrder/updateRemark` 接口,参数为 `id``remark`
- 接口返回成功后,刷新当前行数据
- 待派单状态下的两个tab可以点击
- 点击待接单后,给接口`factory/podOrder/list_page`传入`subStatus``PENDING_RECEIVE`
- 点击接单失败-缺货后,给接口`factory/podOrder/list_page`传入`subStatus``ACCEPT_FAIL_OUT_OF_STOCK`
- `factory/podOrder/list_page`会返回对应状态下的数据,其中`pendingCount`为待接单tab下的数量,`acceptFailOutOfStockCount`为接单失败-缺货tab下的数量
- 点击接单失败-缺货tab后,将`确认接单`按钮修改为`重新接单`,注意:只修改文字,操作列也同步修改
- 待发货子表格加一个操作列
- 操作列添加`申请补胚`按钮
- 点击“申请补胚”按钮后,会调用接口`factory/podOrder/applyForReplenish`,参数为 `id`
- 调用接口成功后,会返回和卡片布局一样的数据结构(这里暂时还不清楚,可占位),然后弹出和待排单、待补胚、生产中、待配货状态下布局一样的卡片布局弹框,如图二所示(页面中紫色字体无需处理)
- 点击确定后,调用接口`factory/podOrder/applyForReplenish`,参数为 `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