Commit ecb13036 by sunyang
parents 93225d1b 5489caaa
......@@ -9,6 +9,7 @@ import {
WarehouseListData,
LogisticsData,
ExportParams,
InterceptStateGroupData,
} from '@/types/api/podUsOrder'
import axios from './axios'
import { PodMakeOrderData } from '@/types/api/podMakeOrder'
......@@ -43,12 +44,19 @@ export function getOrderTabData() {
'/factory/podJomallOrderUs/findStateGroupList',
)
}
// 拦截状态数量
export function getgetInterceptStateGroupList() {
return axios.get<never, BaseRespData<InterceptStateGroupData>>(
'factory/podJomallOrderUs/findInterceptStateGroupList',
)
}
export function getOrderList(
params: SearchForm,
currentPage: number,
pageSize: number,
) {
return axios.post<never, BasePaginationData<PodUsOrderListData[]>>(
return axios.post<never, BasePaginationData<PodUsOrderListData>>(
'/factory/podJomallOrderUs/list_page',
{
...params,
......@@ -496,3 +504,25 @@ export function updateToWaitShipmentApi(params: {
params,
)
}
// 拦截状态改变
export function interceptUpdateApi(params: {
orderIds: (string | number)[]
interceptStatus: number
}) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderUs/updateInterceptStatus`,
params,
)
}
// 驳回
export function rejectToApi(params: {
orderStatus: string
productList: ProductList[]
reasonStr: string
}) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderUs/rejectTo`,
params,
)
}
......@@ -12,7 +12,7 @@
<ElTableColumn
v-if="selectionable"
type="selection"
width="50"
width="40"
fixed="left"
header-align="center"
align="center"
......@@ -21,7 +21,7 @@
v-if="serialNumberable"
label="序号"
type="index"
width="60"
width="55"
fixed="left"
header-align="center"
align="center"
......
......@@ -6,7 +6,9 @@ export interface Tab {
export interface ExportParams extends SearchForm {
idList?: number[]
exportAll: boolean
status?: string
}
export interface SearchForm {
timeType?: number | null
shopNumber?: string
......@@ -32,6 +34,7 @@ export interface SearchForm {
batchArrangeNumber?: string
craftCode?: string
thirdStockSku?: string
interceptStatus?: number | string
}
export interface PodUsOrderListData {
id: number
......@@ -95,6 +98,7 @@ export interface ProductList {
craftCode?: string
platform?: string
imageAry?: string
previewImgs?: []
designImages?: string
categoryId?: number
categoryName?: string
......@@ -124,6 +128,7 @@ export interface ProductList {
supplierProductNo?: string | null
replenishmentSumNum?: number | null
batchArrangeNumber?: string | null
interceptStatus?: number | null
}
export interface cardImages {
title: string
......@@ -198,3 +203,12 @@ export interface CraftListData {
craftName: string
craftCode: string
}
export interface InterceptStateGroupData {
shipment: {
[key: string]: number
}
production: {
[key: string]: number
}
}
......@@ -14,6 +14,7 @@ import {
getOperationLogApi,
getOrderTabData,
getfaceSimplexFileApi,
exportPodUSInfo,
} from '@/api/podUsOrder'
import {
SearchForm,
......@@ -23,6 +24,7 @@ import {
PodUsOrderListData,
LogListData,
Tab,
ExportParams,
} from '@/types/api/podUsOrder'
import platformJson from '../../../json/platform.json'
import dayjs from 'dayjs'
......@@ -284,7 +286,7 @@ const goodsColumns = computed(() => {
},
]
})
const tableData = ref<PodUsOrderListData[][]>([])
const tableData = ref<PodUsOrderListData[]>([])
const goodsData = ref<ProductList[]>([])
const searchVisible = ref(false)
const goodsLoading = ref(false)
......@@ -371,7 +373,55 @@ const getWeekRange = (weeks = 0, type: 'past' | 'future' = 'past') => {
type === 'past' ? now.subtract(weeks, 'week') : now.add(weeks, 'week')
return [start.startOf('week').toDate(), start.endOf('week').toDate()]
}
const exportLoading = ref(false)
const exportVisible = ref(false)
const exportForm = ref({
resource: '',
})
const exportData = () => {
exportVisible.value = true
}
const submitExportForm = async () => {
if (exportForm.value.resource === '') {
return ElMessage.error('请选择导出类型')
}
exportLoading.value = true
const resourceType = Number(exportForm.value.resource)
const params: ExportParams = {
exportAll: false,
idList: [],
}
// 使用函数封装映射逻辑
const mapIds = (items: PodUsOrderListData[]) =>
items.map((el) => Number(el.id))
switch (resourceType) {
case 0:
params.idList = mapIds(tableData.value as PodUsOrderListData[])
break
case 1:
params.idList = mapIds(selection.value)
break
case 2:
params.exportAll = true
params.idList = undefined
break
default:
console.error('未知的资源类型:', resourceType)
}
try {
const res = await exportPodUSInfo({
...params,
...(resourceType === 2 ? searchForm.value : {}),
})
window.open(filePath + res.message, '_blank')
exportVisible.value = false
exportLoading.value = false
} catch (e) {
exportVisible.value = false
exportLoading.value = false
}
}
const handleSizeChange = (pageSize: number) => {
pagination.value.pageSize = pageSize
getOrderListFn()
......@@ -886,6 +936,9 @@ onMounted(() => {
>
</span>
</ElFormItem>
<ElFormItem>
<ElButton type="success" @click="exportData">导出</ElButton>
</ElFormItem>
</ElForm>
</el-card>
</template>
......@@ -957,6 +1010,33 @@ onMounted(() => {
</div>
</template>
</split-div>
<ElDialog
v-model="exportVisible"
title="导出选项"
width="500px"
:close-on-click-modal="false"
>
<el-form :model="exportForm" label-width="80px">
<el-form-item label="" prop="resource">
<el-radio-group v-model="exportForm.resource">
<el-radio :label="0">导出本页</el-radio>
<el-radio :label="1">导出选中</el-radio>
<el-radio :label="2">全部</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="exportVisible = false">取消</el-button>
<el-button
:loading="exportLoading"
type="primary"
@click="submitExportForm"
>确认</el-button
>
</span>
</template>
</ElDialog>
<ResultInfo
ref="resultRefs"
:list="resultInfo"
......
......@@ -392,8 +392,20 @@ watch(
{ url: d.negativeImage, title: '反面', id: d.negativeDesignId },
].filter((el) => el.url)
} else {
arr =
typeof d.imageAry == 'string' ? JSON.parse(d.imageAry) : d.imageAry
arr = Array.isArray(d.imageAry)
? d.imageAry
: typeof d.imageAry === 'string'
? (() => {
try {
const parsed = JSON.parse(d.imageAry)
return parsed
} catch {
return [{ url: d.imageAry }]
}
})()
: [d.imageAry]?.filter?.((v) => v != null) || []
// arr =
// typeof d.imageAry == 'string' ? JSON.parse(d.imageAry) : d.imageAry
arr = arr.concat([
{ url: d.negativeImage, title: '反面', id: d.negativeDesignId },
])
......@@ -591,7 +603,10 @@ const trackcodeInput = async () => {
// AAAB_60527128-9_1_JMSC250121017 新版示例
const regex = /^[A-Z]{4}_/ //是否以四个大写字母加下划线开头
if (regex.test(orderNumber)) {
orderNumber = orderNumber.split('_')[0] + "-"+ orderNumber.split('_')[orderNumber.split('_').length - 1]
orderNumber =
orderNumber.split('_')[0] +
'-' +
orderNumber.split('_')[orderNumber.split('_').length - 1]
}
try {
const res = await getSubOrderBySubOrderNumber(orderNumber)
......@@ -612,7 +627,20 @@ const trackcodeInput = async () => {
{ url: d.negativeImage, title: '反面', id: d.negativeDesignId },
].filter((el) => el.url)
} else {
arr = typeof d.imageAry == 'string' ? JSON.parse(d.imageAry) : d.imageAry
arr = Array.isArray(d.imageAry)
? d.imageAry
: typeof d.imageAry === 'string'
? (() => {
try {
const parsed = JSON.parse(d.imageAry)
return parsed
} catch {
return [{ url: d.imageAry }]
}
})()
: [d.imageAry]?.filter?.((v) => v != null) || []
// arr = typeof d.imageAry == 'string' ? JSON.parse(d.imageAry) : d.imageAry
arr = arr.concat([
{ url: d.negativeImage, title: '反面', id: d.negativeDesignId },
])
......
......@@ -220,7 +220,7 @@
'TO_BE_CONFIRMED',
'IN_PRODUCTION',
'PART_SHIPPING',
'WAIT_SHIPMENT',
'WAIT_SHIPMENT'
].includes(status)
"
class="item"
......@@ -1449,7 +1449,20 @@ const openDetail = async (id: number) => {
const res = await getOrderDetail(id)
if (res.code == 200) {
if (res.data.imageAry) {
res.data.imageAry = JSON.parse(res.data.imageAry as string)
const newarr = res.data.imageAry
res.data.imageAry = Array.isArray(newarr)
? newarr
: typeof newarr === 'string'
? (() => {
try {
const parsed = JSON.parse(newarr)
return parsed
} catch {
return [{ url: newarr }]
}
})()
: [newarr]?.filter?.((v) => v != null) || []
// res.data.imageAry = JSON.parse(res.data.imageAry as string)
}
detailData.value = res.data || {}
detailVisible.value = true
......@@ -1457,6 +1470,8 @@ const openDetail = async (id: number) => {
fastType.value = 0
}
} catch (e) {
console.log(e)
//showError(e)
}
}
......@@ -1691,7 +1706,7 @@ const [searchForm] = useValue<SearchForm>({
userMark: '',
customizedQuantity: '',
order: 'desc',
platform:''
platform: '',
})
const tableColumns = computed<CustomColumn<CardOrderData[]>>(() => {
return [
......
......@@ -247,7 +247,12 @@ const props = defineProps<{
printOrder: (data: OrderData, callback: (status: boolean) => void) => void
warehouseList: WarehouseListData[]
}>()
const emit = defineEmits(['update:modelValue', 'set-printer', 'refresh'])
const emit = defineEmits([
'update:modelValue',
'set-printer',
'refresh',
'set-warehouseId',
])
const visible = computed({
get() {
return props.modelValue
......@@ -259,6 +264,7 @@ const visible = computed({
const printDeviceList = ref<string[]>([])
const sheetPrinter = ref<string>('')
const productionOrder = ref<string>('')
const podOrderDetailsData = ref<OrderData>()
const podOrderDetailsColumns = computed(() => [
......@@ -351,7 +357,9 @@ watch(visible, async (value: boolean) => {
initOrderDetailBox()
initPrintDevice()
const locaclPrinter = localStorage.getItem('sheetPrinter')
const locaclWarehouseId = localStorage.getItem('locaclWarehouseId')
if (locaclPrinter) sheetPrinter.value = JSON.parse(locaclPrinter)
if (locaclWarehouseId) warehouseId.value = JSON.parse(locaclWarehouseId)
} else {
if (userStore.user?.factory.id) {
socket.send({
......@@ -414,6 +422,7 @@ const renderItemBox = (bool: boolean) => {
if (renderLock) return
renderLock = true
let boxItem = podBoxList.value.find((item) => item.box === boxIndex.value)
if (!boxItem) boxItem = { data: { productList: [] } }
const { data } = boxItem
data?.productList?.forEach((el) => {
......@@ -927,6 +936,7 @@ const handleWarehouseChange = (value: string | number) => {
})
}
warehouseId.value = value
emit('set-warehouseId', value)
socket.send({
code: 'STARTORDER',
factoryNo: userStore.user?.factory.id,
......
......@@ -329,7 +329,11 @@
</ElButton>
</span> -->
<span
v-if="status === 'PICKING' || status === 'TO_BE_REPLENISHMENT'"
v-if="
status === 'PICKING' ||
status === 'TO_BE_REPLENISHMENT' ||
status === 'IN_PRODUCTION'
"
class="item"
>
<ElButton type="primary" @click="printProductionOrder">
......@@ -412,7 +416,7 @@
<ElDropdownMenu>
<ElDropdownItem
:disabled="
selection.length === 0 ||
(selection.length === 0 && cardSelection.length === 0) ||
selection.some((item) => item.shipmentType !== 1)
"
@click="getOrderByIdApi('createLogisticsOrder')"
......@@ -420,7 +424,7 @@
>
<ElDropdownItem
:disabled="
selection.length === 0 ||
(selection.length === 0 && cardSelection.length === 0) ||
selection.some((item) => item.shipmentType !== 1)
"
@click="getOrderByIdApi('getTrackingNumber')"
......@@ -428,7 +432,7 @@
>
<ElDropdownItem
:disabled="
selection.length === 0 ||
(selection.length === 0 && cardSelection.length === 0) ||
selection.some((item) => item.shipmentType !== 1)
"
@click="getOrderByIdApi('getPrintOrder')"
......@@ -436,7 +440,7 @@
>
<ElDropdownItem
:disabled="
selection.length === 0 ||
(selection.length === 0 && cardSelection.length === 0) ||
selection.some((item) => item.shipmentType !== 1)
"
@click="getOrderByIdApi('cancelLogisticsOrder')"
......@@ -465,13 +469,39 @@
<span v-if="status === 'TO_BE_ARRANGE'" class="item">
<ElButton type="warning" @click="arrangeFinish">排单完成</ElButton>
</span>
<span v-if="status !== 'BATCH_DOWNLOAD'" class="item">
<span
v-if="status !== 'BATCH_DOWNLOAD' && status !== 'WAIT_SHIPMENT'"
class="item"
>
<ElButton type="primary" @click="downloadMaterial"
>下载素材</ElButton
>
</span>
<span
v-if="
status === 'INTERCEPTED' &&
(interceptCurrent === 1 || interceptCurrent === 4)
"
class="item"
>
<ElButton type="success" @click="interceptChange(true)">
拦截成功
</ElButton>
</span>
<span
v-if="
status === 'INTERCEPTED' &&
(interceptCurrent === 1 || interceptCurrent === 4)
"
class="item"
>
<ElButton type="danger" @click="interceptChange(false)">
拦截失败
</ElButton>
</span>
<span
v-if="
status === 'TO_BE_CONFIRMED' ||
status === 'PICKING' ||
status === 'STOCK_OUT' ||
......@@ -482,16 +512,66 @@
class="item"
>
<ElButton type="success" @click="refreshMaterial">
刷新素材
刷新商品信息
</ElButton>
</span>
<span
v-if="
status === 'STOCK_OUT' ||
status === 'CREATE_LOGISTICS' ||
status === 'TO_BE_ARRANGE' ||
status === 'PICKING' ||
status === 'IN_PRODUCTION'
"
class="item"
>
<ElDropdown>
<el-button type="warning">
驳回至<el-icon class="el-icon--right"><ArrowDown /></el-icon>
</el-button>
<template #dropdown>
<ElDropdownMenu>
<ElDropdownItem
:disabled="
selection.length === 0 && cardSelection.length === 0
"
@click="rejectOrder('TO_BE_CONFIRMED')"
>待确认</ElDropdownItem
>
<ElDropdownItem
v-if="
status === 'IN_PRODUCTION' ||
status === 'TO_BE_ARRANGE' ||
status === 'PICKING'
"
:disabled="
selection.length === 0 && cardSelection.length === 0
"
@click="rejectOrder('CREATE_LOGISTICS')"
>待创建物流</ElDropdownItem
>
<ElDropdownItem
v-if="status === 'PICKING' || status === 'IN_PRODUCTION'"
:disabled="
selection.length === 0 && cardSelection.length === 0
"
@click="rejectOrder('TO_BE_ARRANGE')"
>待排单</ElDropdownItem
>
<ElDropdownItem
v-if="status === 'IN_PRODUCTION'"
:disabled="
selection.length === 0 && cardSelection.length === 0
"
@click="rejectOrder('PICKING')"
>待拣胚</ElDropdownItem
>
</ElDropdownMenu>
</template>
</ElDropdown>
</span>
<span v-if="status === 'COMPLETE'" class="item">
<ElButton
:loading="exportLoading"
type="success"
@click="exportData"
>导出</ElButton
>
<ElButton type="success" @click="exportData">导出</ElButton>
</span>
</ElFormItem>
</ElForm>
......@@ -575,6 +655,80 @@
<span class="sub-status-item-label">待同步</span>
</div>
</div>
<div v-if="status === 'INTERCEPTED'" class="sub-status mb-10">
<div
class="sub-status-item"
:class="interceptCurrent === 1 ? 'sub-active' : ''"
@click="handleInterceptionCommand(1, 0)"
>
<span class="sub-status-item-label">生产拦截申请</span>
<span
v-if="interceptionStatus.production['0']"
class="tabs-node_count blue"
>{{ interceptionStatus.production['0'] }}</span
>
</div>
<div
class="sub-status-item"
:class="interceptCurrent === 2 ? 'sub-active' : ''"
@click="handleInterceptionCommand(2, 1)"
>
<span class="sub-status-item-label">生产拦截成功</span>
<span
v-if="interceptionStatus.production['1']"
class="tabs-node_count blue"
>{{ interceptionStatus.production['1'] }}</span
>
</div>
<div
class="sub-status-item"
:class="interceptCurrent === 3 ? 'sub-active' : ''"
@click="handleInterceptionCommand(3, 2)"
>
<span class="sub-status-item-label">生产拦截失败</span>
<span
v-if="interceptionStatus.production['2']"
class="tabs-node_count red"
>{{ interceptionStatus.production['2'] }}</span
>
</div>
<div
class="sub-status-item"
:class="interceptCurrent === 4 ? 'sub-active' : ''"
@click="handleInterceptionCommand(4, 2)"
>
<span class="sub-status-item-label">发货拦截申请</span>
<span
v-if="interceptionStatus.shipment['0']"
class="tabs-node_count blue"
>{{ interceptionStatus.shipment['0'] }}</span
>
</div>
<div
class="sub-status-item"
:class="interceptCurrent === 5 ? 'sub-active' : ''"
@click="handleInterceptionCommand(5, 3)"
>
<span class="sub-status-item-label">发货拦截成功</span>
<span
v-if="interceptionStatus.shipment['1']"
class="tabs-node_count blue"
>{{ interceptionStatus.shipment['1'] }}</span
>
</div>
<div
class="sub-status-item"
:class="interceptCurrent === 6 ? 'sub-active' : ''"
@click="handleInterceptionCommand(6, 4)"
>
<span class="sub-status-item-label">发货拦截失败</span>
<span
v-if="interceptionStatus.shipment['2']"
class="tabs-node_count red"
>{{ interceptionStatus.shipment['2'] }}</span
>
</div>
</div>
<div
v-if="
status !== 'IN_PRODUCTION' &&
......@@ -590,7 +744,6 @@
<TableView
ref="tableRef"
:columns="tableColumns"
:serial-numberable="true"
:selectionable="true"
:paginated-data="tableData"
:cell-style="onCellStyle"
......@@ -598,6 +751,26 @@
:row-style="getRowStyle"
@selection-change="handleSelectionChange"
>
<template #serialNumber="{ row, index }">
<div>
<el-tooltip
v-if="
status !== 'INTERCEPTED' &&
(row.interceptStatus == 0 || row.interceptStatus == 2)
"
effect="light"
:content="
row.interceptStatus == 0
? '订单已提交至生产拦截申请'
: '订单已提交至发货拦截申请'
"
placement="bottom"
>
<el-icon color="#E6A23C"><InfoFilled /></el-icon>
</el-tooltip>
<span class="serial-number">{{ index + 1 }}</span>
</div>
</template>
<template #goods="{ row }">
<div class="goods-info-box">
<div class="goods-list">
......@@ -606,17 +779,31 @@
:key="item"
class="goods-item"
>
<div class="goods-item-img">
<img :src="item.variantImage" alt="商品图片" />
<div
class="goods-item-img"
style="display: flex; flex-direction: column"
>
<div
v-if="item.customizedQuantity"
class="triangle-box"
:title="`类型:${getQuantityText(
item.customizedQuantity,
)}面`"
v-for="img in item.previewImgs"
:key="img"
style="text-align: center"
>
<div class="multi-text">
{{ getQuantityText(item.customizedQuantity) }}
<img
:src="img.url"
alt="商品图片"
style="cursor: pointer"
@click="handlePictureCardPreview(img.url)"
/>
<div
v-if="item.customizedQuantity"
class="triangle-box"
:title="`类型:${getQuantityText(
item.customizedQuantity,
)}面`"
>
<div class="multi-text">
{{ getQuantityText(item.customizedQuantity) }}
</div>
</div>
</div>
</div>
......@@ -707,7 +894,7 @@
</span>
<el-icon
class="icon"
@click="copy(item.factorySubOrderNumber || '')"
@click.stop="copy(item.factorySubOrderNumber || '')"
>
<DocumentCopy />
</el-icon>
......@@ -724,7 +911,7 @@
</span>
<el-icon
class="icon"
@click="copy(item.thirdSubOrderNumber || '')"
@click.stop="copy(item.thirdSubOrderNumber || '')"
>
<DocumentCopy />
</el-icon>
......@@ -741,7 +928,15 @@
{{ item.supplierProductNo }}
</span>
</div>
<div class="goods-item-info-item">
<span class="goods-item-info-item-label">克重:</span>
<span
v-if="item.weight"
class="goods-item-info-item-value"
>
{{ item.weight }}g
</span>
</div>
<div
v-if="item.isReplenishment"
class="goods-item-info-item"
......@@ -754,12 +949,14 @@
</div>
<div class="goods-item-info">
<div class="goods-item-info-item">
<span class="goods-item-info-item-label">价格:</span>
<span class="goods-item-info-item-label"
>商品单价($):</span
>
<span class="goods-item-info-item-value">
{{ item.productPrice }}($)
{{ item.productPrice }}
</span>
</div>
<div class="goods-item-info-item">
<!-- <div class="goods-item-info-item">
<span class="goods-item-info-item-label">模板金额:</span>
<span class="goods-item-info-item-value">
{{ item.templatePrice }}($)
......@@ -776,7 +973,7 @@
<span class="goods-item-info-item-value">
{{ item.payAmount }}($)
</span>
</div>
</div> -->
<div class="goods-item-info-item">
<span class="goods-item-info-item-label">{{
......@@ -803,6 +1000,7 @@
<div
v-if="status === 'WAIT_SHIPMENT' || status === 'COMPLETE'"
class="goods-item-info-item"
style="align-items: start"
>
<span class="goods-item-info-item-label">补胚数量:</span>
<span
......@@ -811,24 +1009,83 @@
>
{{ item.replenishmentSumNum || 0 }}
</span>
<el-button
<!-- <ElDropdown
v-if="status === 'WAIT_SHIPMENT'"
link
style="height: 23px"
size="small"
type="success"
@click="applyForReplenishment(item)"
>申请补胚
</el-button>
>
<span class="el-dropdown-link"
>素材接口<el-icon class="el-icon--right"
><ArrowDown /></el-icon
></span>
<template #dropdown>
<ElDropdownMenu>
<ElDropdownItem @click="applyForReplenishment(item)"
>申请补胚</ElDropdownItem
>
<ElDropdownItem @click="downloadMaterialItem(item)"
>下载素材</ElDropdownItem
>
<ElDropdownItem
@click="downloadTifItem('tiff', item.id)"
>TIF排版</ElDropdownItem
>
<ElDropdownItem
@click="downloadTifItem('png', item.id)"
>PNG排版</ElDropdownItem
>
</ElDropdownMenu>
</template>
</ElDropdown> -->
<div
v-if="status === 'WAIT_SHIPMENT'"
style="
display: flex;
flex-direction: column;
align-items: center;
"
>
<el-button
link
size="small"
type="success"
style="height: 23px"
@click="applyForReplenishment(item)"
>申请补胚
</el-button>
</div>
<!-- f -->
</div>
<div class="goods-item-info-item">
<span class="goods-item-info-item-label">克重:</span>
<span
v-if="item.weight"
class="goods-item-info-item-value"
>
{{ item.weight }}g
</span>
<div
v-if="status === 'WAIT_SHIPMENT'"
style="display: flex; justify-content: space-between"
>
<el-button
link
size="small"
type="primary"
style="height: 23px; padding: 0"
@click="downloadMaterialItem(item)"
>下载素材
</el-button>
<el-button
link
size="small"
type="warning"
style="height: 23px; margin: 0"
@click="downloadTifItem('tiff', item.id)"
>TIF排版
</el-button>
<el-button
link
size="small"
type="warning"
style="height: 23px; margin: 0"
@click="downloadTifItem('png', item.id)"
>PNG排版
</el-button>
</div>
</div>
</div>
......@@ -985,10 +1242,10 @@
<template #price="{ row }">
<div class="order-price-box">
<div class="order-price-item">
<span class="order-price-item-label">商品总价:</span>
<span class="order-price-item-value">
{{ row.totalAmount }}($)
</span>
<div class="order-price-item-label">商品总价</div>
<div class="order-price-item-value">
{{ row.totalAmount }}
</div>
</div>
<div
......@@ -998,15 +1255,15 @@
"
class="order-price-item"
>
<span class="order-price-item-label">物流运费:</span>
<span class="order-price-item-value">
{{ row.payFreight }}($)
</span>
<div class="order-price-item-label">物流运费</div>
<div class="order-price-item-value">
{{ row.payFreight }}
</div>
</div>
</div>
</template>
<template #time="{ row }">
<el-timeline style="max-width: 600px">
<el-timeline>
<el-timeline-item
:color="row.createTime ? '#409EFF' : ''"
:timestamp="row.createTime"
......@@ -1155,7 +1412,7 @@
class="operate-item"
>
<ElButton link type="primary" @click="showLogistics(row)">
更新物流信息
更新物流
</ElButton>
</span>
<span
......@@ -1222,6 +1479,23 @@
:image-field="'variantImage'"
@contextmenu.prevent="(v: MouseEvent) => rightClick(v)"
>
<template #top_left>
<el-tooltip
v-if="
cardItem.interceptStatus == 0 ||
cardItem.interceptStatus == 2
"
effect="light"
:content="
cardItem.interceptStatus == 0
? '订单已提交至生产拦截申请'
: '订单已提交至发货拦截申请'
"
placement="bottom"
>
<el-icon color="#E6A23C"><InfoFilled /></el-icon>
</el-tooltip>
</template>
<template
#top_right
v-if="['ZPZY', 'CXZY', 'THZY'].includes(cardItem.craftCode as string)"
......@@ -1291,9 +1565,7 @@
<div class="flex-between">
<div v-if="cardItem.imageAry" class="images-position">
<div
v-for="(item, index) in JSON.parse(
cardItem.imageAry || '',
)"
v-for="(item, index) in filteredImages(cardItem.imageAry)"
:key="index"
:title="item.title"
class="item-image"
......@@ -1438,7 +1710,7 @@
<div class="grid-item">
<div
:title="`第三方生产单号:${cardItem?.thirdSubOrderNumber}`"
:title="`单号:${cardItem?.thirdSubOrderNumber}`"
class="grid-item-value orderNumber"
>
{{ cardItem?.thirdSubOrderNumber }}
......@@ -1631,6 +1903,7 @@
:print-order="printOrder"
:warehouse-list="warehouseList"
@set-printer="handlePrinterChange"
@set-warehouseId="handleWarehouseIdChange"
@refresh="onFastRefresh"
/>
<ElDialog
......@@ -1879,7 +2152,12 @@
<template #footer>
<span class="dialog-footer">
<el-button @click="exportVisible = false">取消</el-button>
<el-button type="primary" @click="submitExportForm">确认</el-button>
<el-button
:loading="exportLoading"
type="primary"
@click="submitExportForm"
>确认</el-button
>
</span>
</template>
</ElDialog>
......@@ -1891,6 +2169,7 @@
import { getUserMarkList } from '@/api/common'
// import { AnyObject } from '@/types/api/warehouse'
import {
InfoFilled,
ArrowDown,
CaretBottom,
CaretTop,
......@@ -1946,6 +2225,9 @@ import {
batchDownloadRecomposingApi,
updateToWaitShipmentApi,
exportPodUSInfo,
getgetInterceptStateGroupList,
interceptUpdateApi,
rejectToApi,
} from '@/api/podUsOrder'
import { BaseRespData } from '@/types/api'
......@@ -1972,7 +2254,7 @@ import {
import usePageList from '@/utils/hooks/usePageList'
import { useValue } from '@/utils/hooks/useValue'
import { showConfirm } from '@/utils/ui'
import { DocumentCopy, EditPen } from '@element-plus/icons-vue'
// import { DocumentCopy, EditPen } from '@element-plus/icons-vue'
import { Column, ElFormItem } from 'element-plus'
import { computed, onMounted, ref, nextTick, reactive } from 'vue'
import FastProduction from './FastProduction.vue'
......@@ -2036,6 +2318,7 @@ const submitExportForm = async () => {
const params: ExportParams = {
exportAll: false,
idList: [],
status: status.value,
}
// 使用函数封装映射逻辑
const mapIds = (items: PodUsOrderListData[]) =>
......@@ -2089,6 +2372,13 @@ const searchVisible = ref(false)
const confirmSelectionData = ref<LogisticsData[]>([])
const confirmRowData = ref<ProductList | null>(null)
const status = ref(localStorage.getItem('podUsStatus') || 'TO_BE_CONFIRMED')
const interceptionStatus = ref<{
shipment: Record<string, number>
production: Record<string, number>
}>({
shipment: {},
production: {},
})
const detailData = ref({})
const [searchForm, resetSearchForm] = useValue<SearchForm>({
......@@ -2117,6 +2407,8 @@ const [searchForm, resetSearchForm] = useValue<SearchForm>({
thirdStockSku: '',
})
const exceptionStatus = ref(1)
const interceptCurrent = ref(1)
const interceptStatus = ref(0)
const userMarkList = ref<string[]>([])
const selection = ref<PodUsOrderListData[]>([])
const pickerOptions = {
......@@ -2167,6 +2459,17 @@ const pickerOptions = {
},
],
}
const filteredImages = (imageAry: string | null) => {
if (!imageAry) return []
try {
const parsed = JSON.parse(imageAry)
return Array.isArray(parsed)
? parsed.filter((el: { title: string }) => el.title)
: []
} catch {
return []
}
}
const timeRange = ref<string[]>([])
const getDateRange = (days = 0, type: 'past' | 'future' = 'past') => {
const end = dayjs()
......@@ -2390,10 +2693,17 @@ const tableColumns = computed(() => {
}
return [
{
label: '序号',
prop: 'serialNumber',
slot: 'serialNumber',
width: 60,
align: 'center',
},
{
label: '商品',
prop: 'goods',
slot: 'goods',
minWidth: 920,
minWidth: 800,
},
{
label: '订单详情',
......@@ -2402,16 +2712,16 @@ const tableColumns = computed(() => {
width: 300,
},
{
label: '单价',
label: '订单金额($)',
slot: 'price',
width: 160,
width: 110,
prop: 'price',
align: 'left',
},
{
label: '时间',
slot: 'time',
width: 180,
width: 170,
prop: 'time',
align: 'left',
},
......@@ -2423,7 +2733,7 @@ const tableColumns = computed(() => {
// },
{
label: '异常原因',
width: 300,
width: 250,
prop: 'exceptionReason',
slot: 'exceptionReason',
align: 'left',
......@@ -2431,7 +2741,7 @@ const tableColumns = computed(() => {
{
label: '操作',
slot: 'operate',
width: 180,
width: 80,
align: 'center',
fixed: 'right',
prop: 'operate',
......@@ -2494,6 +2804,12 @@ const asyncOrderAddress = async () => {
const changeTab = (item: Tab) => {
status.value = item.status || ''
localStorage.setItem('podUsStatus', item.status as string)
// 如果切换到INTERCEPTED状态,设置默认的exceptionStatus
if (item.status === 'INTERCEPTED' && !interceptCurrent.value) {
interceptCurrent.value = 1
}
selection.value = []
cardSelection.value = []
stockOutSuccessIds.value = []
......@@ -2516,10 +2832,46 @@ const onCellClassName = ({ column }: { column: Column }) => {
return 'exception-reason'
}
}
// 获取Tab信息
const loadTabData = async () => {
try {
const res = await getOrderTabData()
tabsNav.value = res.data
// 获取拦截数量
const statusRes = await getgetInterceptStateGroupList()
interceptionStatus.value = statusRes.data as {
shipment: Record<string, number>
production: Record<string, number>
}
// 在 已完成 后面添加 拦截 标签页
const completeIndex = tabsNav.value.findIndex(
(item) => item.status === 'COMPLETE',
)
// 发货拦截数量
const shipmentCount = (statusRes.data as any)?.shipment
? Object.values((statusRes.data as any).shipment).reduce(
(sum: number, value: any) => sum + (Number(value) || 0),
0,
)
: 0
// 生产拦截数量
const productionCount = (statusRes.data as any)?.production
? Object.values((statusRes.data as any).production).reduce(
(sum: number, value: any) => sum + (Number(value) || 0),
0,
)
: 0
tabsNav.value.splice(completeIndex + 1, 0, {
status: 'INTERCEPTED',
statusName: '拦截',
quantity: shipmentCount + productionCount,
})
} catch (error) {
// showError(error)
}
......@@ -2567,11 +2919,13 @@ const {
timeRange.value && timeRange.value.length > 0
? timeRange.value[1]
: null,
status: status.value,
status: status.value === 'INTERCEPTED' ? '' : status.value,
exceptionHandling:
status.value === 'EXCEPTION_ORDER'
? exceptionStatus.value || undefined
: undefined,
interceptStatus:
status.value === 'INTERCEPTED' ? interceptStatus.value : '',
},
page,
pageSize,
......@@ -2589,6 +2943,7 @@ const {
? timeRange.value[1]
: null,
status: status.value,
interceptStatus: '',
},
page,
pageSize,
......@@ -2597,6 +2952,31 @@ const {
},
})
watch(
() => [...(tableData.value as PodUsOrderListData[])], // 创建新数组避免直接修改原始数据
(newData) => {
if (!newData?.length) return
newData.forEach((order) => {
// 使用可选链和空值合并简化判断
order.productList?.forEach((product) => {
if (!product.previewImgs && product.imageAry) {
try {
product.previewImgs =
JSON.parse(product.imageAry)?.filter(
(el: { title: string }) => el.title,
) || []
} catch (error) {
console.error('JSON解析失败:', error)
product.previewImgs = []
}
}
})
})
},
{ deep: true, immediate: true }, // 添加immediate确保初始化时执行
)
const search = () => {
selection.value = []
cardSelection.value = []
......@@ -2732,8 +3112,12 @@ const handleConfirm = async () => {
await loadTabData()
}
const copy = (text: string) => {
navigator.clipboard.writeText(text)
ElMessage.success('复制成功')
try {
navigator.clipboard.writeText(text)
ElMessage.success('复制成功')
} catch (err) {
console.error('复制失败:', err)
}
}
const handleUpdateRemark = async (item: ProductList) => {
ElMessageBox.prompt('请输入备注', '提示', {
......@@ -2825,7 +3209,51 @@ const downloadTif = async (type: string) => {
}
}
}
const downloadTifItem = async (type: string, id: number) => {
const loading = ElLoading.service({
fullscreen: true,
text: '操作中...',
background: 'rgba(0, 0, 0, 0.3)',
})
try {
const res = await composingDesignImages([id], type)
const url =
type === 'tiff'
? `https://ps.jomalls.com/tiff/` + res.message
: filePath + res.message
if (type === 'tiff') {
window.open(url, '_blank')
} else {
fetch(url)
.then((response) => {
// 确保响应是 OK
if (!response.ok) {
throw new Error('网络响应错误')
}
// 返回图片的二进制数据(Blob)
return response.blob()
})
.then((blob) => {
const a = document.createElement('a')
a.href = window.URL.createObjectURL(blob)
a.target = '_blank'
a.download = (res.message as string).split('/')[
(res.message as string).split('/').length - 1
]
a.click()
pngDownloadLoading.value = false
})
.catch((error) => {
console.error('下载图片时出错:', error)
pngDownloadLoading.value = false
})
}
} catch (e) {
console.log(e)
} finally {
loading.close()
}
}
const loadProductionClient = async () => {
try {
const res = await getProductionClientApi()
......@@ -3227,6 +3655,24 @@ const downloadMaterial = async () => {
loading.close()
}
}
// 下载单个素材
const downloadMaterialItem = async (data: PodUsOrderListData) => {
const loading = ElLoading.service({
fullscreen: true,
text: '操作中...',
background: 'rgba(0, 0, 0, 0.3)',
})
try {
const res = await downloadMaterialApi([data.id])
if (res.code !== 200) return
window.open(filePath + res.message)
} catch (e) {
// showError(e)
console.error(e)
} finally {
loading.close()
}
}
// 排单完成
const arrangeFinish = async () => {
......@@ -3367,6 +3813,55 @@ const getOrderByIdApi = async (type: string) => {
ElMessage.warning('未知操作类型')
}
}
// 驳回
const rejectOrder = async (type: string) => {
if (selection.value.length === 0 && cardSelection.value.length === 0) {
return ElMessage.warning('请选择数据')
}
const loading = ElLoading.service({
fullscreen: true,
text: '操作中...',
background: 'rgba(0, 0, 0, 0.3)',
})
try {
const { value } = await ElMessageBox.prompt('驳回确认', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputType: 'textarea',
inputPlaceholder: '驳回原因',
inputPattern: /\S+/, // 非空验证,至少一个非空白字符
inputErrorMessage: '内容不能为空',
})
const res = await rejectToApi({
orderStatus: type,
productList: selection.value.length
? selection.value.flatMap(
(item: PodUsOrderListData) => item.productList || [],
)
: cardSelection.value,
reasonStr: value,
})
if (res.code !== 200) return
resultInfo.value = res.data
resultInfo.value = resultInfo.value.filter((item) => !item.status)
if (!resultInfo.value.length) {
ElMessage.success('操作成功')
search()
loadTabData()
} else {
resultRefs.value?.showDialog()
}
} catch (e) {
console.log(e)
} finally {
loading.close()
}
}
const handleStockOut = async (row: PodUsOrderListData) => {
wayDialogTitle.value = `切换物流(当前物流方式:${row.logisticsWayName})`
......@@ -3653,6 +4148,9 @@ const handlePrinterChange = (value: string) => {
sheetPrinter.value = value
localStorage.setItem('sheetPrinter', JSON.stringify(value))
}
const handleWarehouseIdChange = (value: string) => {
localStorage.setItem('locaclWarehouseId', JSON.stringify(value))
}
const { getCLodop } = useLodop()
const printOrder = async (
data: OrderData,
......@@ -3873,7 +4371,9 @@ const loadCraftList = async () => {
}
}
const refreshMaterial = async () => {
if (status.value === 'PICKING' || status.value === 'TO_BE_REPLENISHMENT') {
if (
['PICKING', 'TO_BE_REPLENISHMENT', 'IN_PRODUCTION'].includes(status.value)
) {
if (cardSelection.value.length === 0) {
return ElMessage.warning('请选择数据')
}
......@@ -3889,14 +4389,16 @@ const refreshMaterial = async () => {
})
try {
const res = await refreshMaterialApi({
orderIds:
status.value !== 'PICKING' && status.value !== 'TO_BE_REPLENISHMENT'
? selection.value.map((item) => item.id).join(',')
: undefined,
productIds:
status.value === 'PICKING' || status.value === 'TO_BE_REPLENISHMENT'
? cardSelection.value.map((item) => item.id).join(',')
: undefined,
orderIds: !['PICKING', 'TO_BE_REPLENISHMENT', 'IN_PRODUCTION'].includes(
status.value,
)
? selection.value.map((item) => item.id).join(',')
: undefined,
productIds: ['PICKING', 'TO_BE_REPLENISHMENT', 'IN_PRODUCTION'].includes(
status.value,
)
? cardSelection.value.map((item) => item.id).join(',')
: undefined,
})
if (res.code !== 200) return
ElMessage.success('刷新成功')
......@@ -3968,6 +4470,14 @@ const handleExceptionCommand = (command: number) => {
exceptionStatus.value = command
search()
}
// 拦截分页
const handleInterceptionCommand = (current: number, command: number) => {
interceptCurrent.value = current
interceptStatus.value = command
search()
loadTabData()
}
const applyForReplenishment = async (row: ProductList | undefined) => {
if (!row) {
if (cardSelection.value.length === 0) {
......@@ -4150,6 +4660,54 @@ const handleBeforeRouteLeave = (
next()
}
// 拦截状态改变
const interceptChange = async (status: boolean) => {
if (selection.value.length === 0) {
return ElMessage.warning('请选择数据')
}
try {
await ElMessageBox.confirm(
`确定${status ? '拦截成功' : '拦截失败'}吗?`,
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
},
)
} catch (e) {
return
}
const loading = ElLoading.service({
fullscreen: true,
text: '操作中...',
background: 'rgba(0, 0, 0, 0.3)',
})
const interceptStatus = status
? interceptCurrent.value === 1
? 1
: 3
: interceptCurrent.value === 1
? 2
: 4
try {
const res = await interceptUpdateApi({
orderIds: selection.value.map((item) => item.id),
interceptStatus,
})
if (res.code !== 200) return
ElMessage.success('操作成功')
search()
loadTabData()
} catch (e) {
resultInfo.value = []
console.error(e)
} finally {
loading.close()
}
}
useRouter().beforeEach((to, from, next) => {
handleBeforeRouteLeave(to, from, next)
})
......@@ -4203,15 +4761,15 @@ useRouter().beforeEach((to, from, next) => {
.goods-item {
display: grid;
grid-template-columns: 100px 1fr minmax(180px, 1fr) 180px;
gap: 20px;
grid-template-columns: 100px 1fr minmax(150px, 1fr) 150px;
gap: 15px;
.goods-item-img {
width: 100px;
height: 100px;
// width: 100px;
// height: 65px;
position: relative;
img {
width: 100%;
width: 65%;
}
}
......@@ -4484,4 +5042,15 @@ useRouter().beforeEach((to, from, next) => {
flex-wrap: wrap;
}
}
.el-dropdown-link {
cursor: pointer;
color: var(--el-color-success);
display: flex;
align-items: center;
outline: none;
}
.el-timeline-item__wrapper {
padding-left: 15px;
top: -6px;
}
</style>
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