Commit 72626d4d by wuqian

Merge branch 'dev' of 47.122.114.111:qinjianhui/factory_front into new-pod-cn

parents a5e986f4 3365ea7f
......@@ -32,6 +32,7 @@ declare module 'vue' {
ElImage: typeof import('element-plus/es')['ElImage']
ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElLink: typeof import('element-plus/es')['ElLink']
ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import('element-plus/es')['ElOption']
......@@ -62,6 +63,7 @@ declare module 'vue' {
RightClickMenu: typeof import('./src/components/RightClickMenu.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView']
SearchProdOrder: typeof import('./src/components/searchProdOrder.vue')['default']
Select: typeof import('./src/components/Form/Select.vue')['default']
ShipmentOrderDetail: typeof import('./src/components/ShipmentOrderDetail.vue')['default']
SideBar: typeof import('./src/components/SideBar.vue')['default']
......
......@@ -36,6 +36,18 @@ export function getSubOrderBySubOrderNumber(thirdSubOrderNumber: string) {
},
)
}
export function getSubOrderBySubOrder(factorySubOrderNumber: string,orderFrom:string) {
return axios.get<never, BaseRespData<PodProductList>>(
'factory/podJomallOrderProductCnUs/getSubOrderBySubOrderNumber',
{
params: {
factorySubOrderNumber,
orderFrom,
},
},
)
}
export function refreshJMProductInfo(data: number[]) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrder/refreshJomallPodProduct ',
......
......@@ -535,6 +535,25 @@ export function statusPushApi(params: (string | number)[]) {
)
}
// 转至已完成
export function changeToFinished(ids: string) {
return axios.get<never, BaseRespData<never>>(
`factory/podJomallOrderUs/updateToComplete`,
{ params: { ids } },
)
}
// 转至已完成
export function updateTrackingNumberAndRegister(
id: number,
trackingNumber: string,
) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderUs/updateTrackingNumberAndRegister`,
{ id, trackingNumber },
)
}
// 完成发货
export function completeDeliveryApi(params: {
orderIdList: (string | number)[]
......@@ -576,3 +595,10 @@ export function printProductionPdfByBatchNumberApi(params: {
},
)
}
// 待跟踪 注册列表统计接口
export function countTrackRegisterApi() {
return axios.get<never, BaseRespData<never>>(
`factory/podJomallOrderUs/countTrackRegister`,
)
}
......@@ -11,6 +11,13 @@
>
<img src="../assets/images/printer.png" width="24" height="24" />
</div>
<div
title="生产单查询"
class="tool-item"
@click="searchVisible = true"
>
<img src="../assets/images/saoma.png" width="24" height="24" />
</div>
</div>
<!-- 格式工具 -->
......@@ -130,13 +137,16 @@
</TableView>
</el-dialog>
</span>
<el-dialog v-model="searchVisible" title="生产单查询" width="100%" fullscreen>
<SearchProductOrder v-if="searchVisible" />
</el-dialog>
<!-- 预览图片 -->
<el-dialog v-model="dialogVisible" width="35%">
<img :src="dialogImageUrl" alt="商品预览图片" />
</el-dialog>
</template>
<script lang="ts" setup>
import SearchProductOrder from './searchProdOrder.vue'
import { ref, watch, computed } from 'vue'
import { ElMessage } from 'element-plus'
......@@ -148,6 +158,7 @@ import { LogisticBill } from '@/types/api/podMakeOrder'
import TableView from '@/components/TableView.vue'
const formatDrawer = ref(false)
const searchVisible = ref(false)
const getLogisticDrawer = ref(false)
const textareaT = ref('')
......
<script setup lang="ts">
import { getSubOrderBySubOrder } from '@/api/podOrder.ts'
import { SearchOrderRes } from '@/types/api/podOrder.ts'
import { nextTick, ref } from 'vue'
import { DocumentCopy } from '@element-plus/icons-vue'
import { copyText } from '@/utils'
defineProps({
detailData: {
default: null,
type: Object,
},
})
const type = {
'A': '正面',
'B': '反面',
'C': '左边',
'D': '右边',
}
const imageList = ref<{
sort: number
title?: 'A' | 'B' | 'C' | 'D'
url?: string
}[]>([])
const detail = ref<SearchOrderRes>({
imgList: [], id: 0,
})
type AudioKey = keyof typeof audios // 创建一个类型,确保 key 只能是 audios 对象的键之一
const TrackingNumber = ref('')
const trackingNumberRef = ref(null)
const audios = {
weight_warning: new URL('@/assets/audio/weight_warning.mp3', import.meta.url)
.href,
weight_success: new URL('@/assets/audio/weight_success.mp3', import.meta.url)
.href,
weight_repeat: new URL('@/assets/audio/weight_repeat.mp3', import.meta.url)
.href,
weight_search_error: new URL(
'@/assets/audio/weight_search_error.mp3',
import.meta.url,
).href,
weight_search_success: new URL(
'@/assets/audio/weight_search_success.mp3',
import.meta.url,
).href,
}
const playAudio = (key: AudioKey, message?: string) => {
let text = ''
switch (key) {
case 'weight_search_success':
text = ''
break
case 'weight_search_error':
text = '请录入生产单号'
break
case 'weight_success':
text = ''
break
case 'weight_repeat':
text = '称重复录入'
break
default:
text = '请录入跟踪号或重量'
break
}
if (message || text) ElMessage.warning(message || text)
const audio = new Audio()
if (audios[key]) {
audio.src = audios[key] // 获取对应 key 的音频路径
audio.play().catch((err) => console.error('Audio play failed:', err)) // 捕获音频播放失败的错误
} else {
console.error(`No audio found for key: ${key}`)
}
}
const trackcodeInput = async () => {
if (!TrackingNumber.value) {
// ElMessage.warning('请扫描生产单号')
playAudio('weight_search_error')
return
}
const user = JSON.parse(localStorage.getItem('user') || '{}')
const orderNumber = TrackingNumber.value
// if (user.factory?.countryCode.toLowerCase() !== 'us') {
// const regex = /^[A-Z]{4}_/ //是否以四个大写字母加下划线开头
// if (regex.test(orderNumber)) {
// orderNumber =
// orderNumber.split('_')[0] +
// '-' +
// orderNumber.split('_')[orderNumber.split('_').length - 1]
// }
// }
try {
const res = await getSubOrderBySubOrder(orderNumber, user.factory?.countryCode.toLowerCase())
if (!res.data) {
return ElMessage.error('生产单不存在')
}
res.data.inputNum = TrackingNumber.value
TrackingNumber.value = ''
if (typeof res.data.imageAry === 'string') {
imageList.value = JSON.parse(res.data.imageAry)
} else {
imageList.value = []
}
const d = JSON.parse(JSON.stringify(res.data))
if (d.note) {
d.note = JSON.parse(d.note)
} else {
d.note = []
}
detail.value = d
playAudio('weight_search_success')
nextTick(() => {
if (trackingNumberRef.value) {
;(trackingNumberRef.value as HTMLInputElement).focus()
}
})
} catch (e) {
console.error(e)
nextTick(() => {
if (trackingNumberRef.value) {
;(trackingNumberRef.value as HTMLInputElement).focus()
}
})
}
}
</script>
<template>
<div class="detail-div">
<div class="detail-content">
<div class="left">
<div v-if="imageList.length > 0" class="left-images">
<div v-for="(item, index) in imageList" :key="index" class="img-box">
<b v-if="item.title">{{ item.title }}({{ type[item.title] }})</b>
<img :src="item.url" alt="">
</div>
</div>
</div>
<div class="right">
<div
v-if="!detailData || Object.keys(detailData).length === 0"
class="input"
>
<el-input
ref="trackingNumberRef"
v-model="TrackingNumber"
placeholder="扫描枪输入第三方订单号"
style="width: 660px; margin-right: 10px"
clearable
@keydown.enter="trackcodeInput()"
></el-input>
<el-button type="primary" @click="trackcodeInput()">
查询
</el-button>
</div>
<div class="div-text">
<b>生产单信息</b>
<div class="div-content">
<h2 style="text-align: center;color: black;font-size: 16px;width: 100%;">{{ detail.inputNum }}</h2>
<div :title="detail?.factorySubOrderNumber" class="div-item">
<span>生产单号</span>
<p>
{{ detail?.factorySubOrderNumber }}
</p>
<el-icon
v-if="detail?.factorySubOrderNumber" class="copy" style="cursor:pointer;"
@click="copyText(detail.factorySubOrderNumber)">
<DocumentCopy />
</el-icon>
</div>
<div :title="detail?.shopNumber" class="div-item">
<span>店铺单号</span>
<p>{{ detail?.shopNumber }}</p>
<el-icon
v-if="detail?.shopNumber" class="copy" style="cursor:pointer;"
@click="copyText(detail.shopNumber)">
<DocumentCopy />
</el-icon>
</div>
<div :title="detail?.thirdSubOrderNumber || ''" class="div-item">
<span>第三方生产单号</span>
<p>
{{ detail?.thirdSubOrderNumber }}
</p>
<el-icon
v-if="detail?.thirdSubOrderNumber"
class="copy" style="cursor:pointer;"
@click="copyText(detail.thirdSubOrderNumber)">
<DocumentCopy />
</el-icon>
</div>
<div :title="String(detail?.process)" class="div-item">
<span>生产工艺</span>
<p>
{{ detail?.craftName }}
</p>
</div>
<div :title="detail?.createTime" class="div-item">
<span>创建时间</span>
<p>{{ detail?.createTime }}</p>
</div>
<div :title="detail?.baseSku" class="div-item">
<span>基版</span>
<p>{{ detail?.baseSku }}</p>
</div>
<div :title="String(detail?.supplierItemNo)" class="div-item">
<span>货号</span>
<p>{{ detail?.supplierItemNo }}</p>
</div>
<div :title="String(detail?.size)" class="div-item">
<span>尺寸</span>
<p>{{ detail?.size }}</p>
</div>
<!-- <div :title="detail?.variantSku" class="div-item">-->
<!-- <span>变体SKU</span>-->
<!-- <p>{{ detail?.variantSku }}</p>-->
<!-- </div>-->
<div :title="String(detail?.faceCount)" class="div-item">
<span>打印面数</span>
<p v-if="detail?.num || imageList.length" style="color: red">{{ detail?.faceCount
}}({{ imageList.map(el => el.title).join('+') }})</p>
</div>
</div>
</div>
<div
class="div-text"
style="
flex: 1;
margin-top: 15px;
flex-shrink: 0;
display: flex;
flex-direction: column;
"
>
<div style="height: 100%" class="div-content">
<b style="position: absolute; top: -12px">客户留言信息</b>
<div
v-for="(item, index) in detail?.note"
:key="index"
class="div-item"
>
<span>{{ item.prop }}:</span>
<p>
{{ item.value }}
</p>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<style lang="scss" scoped>
.copy {
font-weight: bold;
margin-left: 5px;
}
::v-deep .el-dialog__body {
box-sizing: border-box;
flex: 1;
flex-shrink: 0;
overflow: hidden;
}
::v-deep .el-dialog {
display: flex;
height: calc(100% - 50px);
margin-top: 50px;
flex-direction: column;
}
.sure-btn {
position: absolute;
right: 62px;
top: 14px;
}
.detail-div {
display: flex;
height: 92vh;
flex-direction: column;
justify-content: space-between;
.detail-images {
.scroll-list {
background: #ececec;
display: flex;
height: 100px;
width: 100%;
padding: 5px;
.scroll-content {
margin-left: 10px;
overflow-x: auto;
overflow-y: hidden;
flex: 1;
display: flex;
flex-wrap: nowrap;
flex-shrink: 0;
.scroll-item {
height: 100%;
min-width: 100px;
background: white;
margin-right: 5px;
}
}
.img-title {
display: flex;
flex-direction: column;
justify-content: center;
background: white;
padding: 10px;
b {
text-align: center;
color: black;
font-weight: bold;
font-size: 16px;
margin-bottom: 15px;
}
.id {
display: flex;
align-items: center;
padding: 3px 5px;
background: #ececec;
justify-content: center;
img {
width: 15px;
margin-right: 8px;
}
}
}
}
}
.detail-content {
display: flex;
width: 100%;
flex: 1;
margin-bottom: 10px;
flex-shrink: 0;
justify-content: space-between;
}
.right {
width: 500px;
height: 100%;
display: flex;
flex-direction: column;
.btn {
margin: 20px 0;
display: flex;
align-items: center;
justify-content: space-between;
height: 50px;
width: 100%;
.btn-sure,
.btn-down {
width: 49%;
position: relative;
.check {
position: absolute;
width: 144px;
height: 100%;
background: transparent;
display: flex;
align-items: center;
justify-content: center;
right: 0;
top: 1px;
}
}
}
.div-text {
.div-content {
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: flex-start;
padding: 15px 10px;
box-sizing: border-box;
text-align: center;
.div-item {
width: 100%;
margin-bottom: 10px;
display: flex;
align-items: center;
font-size: 16px !important;
p {
font-weight: 400;
color: black;
}
span {
display: inline-block;
text-align: right;
width: 140px;
}
span::after {
content: ':';
margin: 0 3px;
}
}
}
b {
position: relative;
background: white;
top: 9px;
left: 13px;
padding: 0 10px;
font-size: 18px;
color: black;
z-index: 3;
}
.div-content {
position: relative;
border: 1px solid #ececec;
}
}
.input {
display: flex;
align-items: center;
margin: 30px 0;
}
}
.left {
flex: 1;
flex-shrink: 0;
margin-right: 20px;
overflow: hidden;
display: flex;
justify-content: center;
align-items: center;
.left-image {
display: flex;
height: 100%;
flex-direction: column;
justify-content: center;
img {
height: auto;
width: 100%;
max-height: 90%;
}
b {
color: black;
font-size: 18px;
margin-bottom: 15px;
}
}
.left-images {
display: flex;
width: 95%;
height: 100%;
gap: 10px;
justify-content: center;
.img-box {
display: flex;
flex-direction: column;
gap: 10px;
width: 50%;
height: 100%;
b {
font-size: 26px;
font-weight: normal;
}
img {
flex: 1;
flex-shrink: 0;
object-fit: cover;
overflow: hidden;
}
}
b {
color: black;
text-align: center;
margin-bottom: 15px;
}
}
}
}
::v-deep .el-carousel__container {
height: 100%;
}
::v-deep .el-form-item__label {
font-weight: bold;
color: white;
}
::v-deep .el-dialog__title {
font-weight: bold;
font-size: 37px;
color: black;
position: relative;
left: 47%;
top: 13px;
}
.btn {
position: relative;
::v-deep .el-button {
span {
position: relative;
left: -30px;
}
}
.check {
::v-deep .el-checkbox__inner {
background-color: transparent !important;
border-color: white !important;
width: 12px;
height: 12px;
}
::v-deep .el-checkbox__inner::after {
left: 3px;
}
::v-deep .el-checkbox__label {
padding-left: 5px;
font-size: 12px;
color: white !important;
}
}
}
.warning {
font-size: 18px;
font-weight: bold;
color: #ff9900;
margin-left: 10px;
cursor: pointer;
}
</style>
......@@ -187,11 +187,6 @@ const menu: MenuItem[] = [
label: '下载生产客户端',
},
{
index: '/system/external-authorisation',
id: 5,
label: '外部授权',
},
{
index: '/system/customers',
id: 6,
label: '客户管理',
......
......@@ -123,6 +123,20 @@ export interface PodOrderRes extends PodProductList {
note?: Array<{ prop: string | number; value: string | number }>
imgList: ImgList
}
export interface SearchOrderRes extends PodProductList {
expectDeliveryTime?: string | null
thirdOrderNumber?: string | null
startStockingTime?: string | null
userMark?: string | null
color?: string | null
size?: string | null
note?: Array<{ prop: string | number; value: string | number }>
imgList: {
url:string
title?: string
}[]
}
export interface ShipmentOrderRes {
factoryOrderNumber?: string
thirdSubOrderNumber?: string
......
......@@ -35,6 +35,7 @@ export interface SearchForm {
craftCode?: string
thirdStockSku?: string
interceptStatus?: number | string
trackRegisterSelect?: string | number
}
export interface PodUsOrderListData {
id: number
......@@ -80,6 +81,7 @@ export interface PodUsOrderListData {
logisticsWayName?: string
url?: string | null
tiffUrl?: string | null
lanshouAddress?: string | null
}
export interface ProductList {
id: number
......
......@@ -133,7 +133,7 @@
>
<el-option :value="1" label="创建时间"></el-option>
<el-option :value="2" label="确认时间"></el-option>
<el-option :value="3" label="完成时间"></el-option>
<el-option :value="3" label="发货时间"></el-option>
</el-select>
<el-date-picker
v-model="timeRange"
......@@ -252,7 +252,7 @@
</ElFormItem>
<ElFormItem>
<span>
<ElButton link @click="resetSearchForm" style="font-size: 12px"
<ElButton link style="font-size: 12px" @click="resetSearchForm"
><span title="重置查询条件">重置</span></ElButton
>
</span>
......@@ -665,6 +665,12 @@
<ElButton type="warning" @click="statusPush">状态推送</ElButton>
</span>
</ElFormItem>
<ElFormItem v-if="['WAIT_TRACK'].includes(status)">
<span class="item">
<ElButton type="success" @click="setFinish">转至已完成</ElButton>
</span>
</ElFormItem>
<ElFormItem v-if="status === 'COMPLETE'">
<span class="item">
<ElButton type="success" @click="exportData">导出</ElButton>
......@@ -758,6 +764,68 @@
<span class="sub-status-item-label">待同步</span>
</div>
</div>
<div v-if="status === 'WAIT_TRACK'" class="sub-status mb-10">
<div
class="sub-status-item"
:class="waitTrackStatus === 1 ? 'sub-active' : ''"
@click="handleWaitTrackCommand(1)"
>
<span class="sub-status-item-label">{{
trackRegisterCount[0]?.name
}}</span>
<span class="tabs-node_count">{{
trackRegisterCount[0]?.count || 0
}}</span>
</div>
<div
class="sub-status-item"
:class="waitTrackStatus === 2 ? 'sub-active' : ''"
@click="handleWaitTrackCommand(2)"
>
<span class="sub-status-item-label">{{
trackRegisterCount[1]?.name
}}</span>
<span class="tabs-node_count blue">{{
trackRegisterCount[1]?.count || 0
}}</span>
</div>
<div
class="sub-status-item"
:class="waitTrackStatus === 3 ? 'sub-active' : ''"
@click="handleWaitTrackCommand(3)"
>
<span class="sub-status-item-label">{{
trackRegisterCount[2]?.name
}}</span>
<span class="tabs-node_count green">{{
trackRegisterCount[2]?.count || 0
}}</span>
</div>
<div
class="sub-status-item"
:class="waitTrackStatus === 4 ? 'sub-active' : ''"
@click="handleWaitTrackCommand(4)"
>
<span class="sub-status-item-label">{{
trackRegisterCount[3]?.name
}}</span>
<span class="tabs-node_count yellow">{{
trackRegisterCount[3]?.count || 0
}}</span>
</div>
<div
class="sub-status-item"
:class="waitTrackStatus === 5 ? 'sub-active' : ''"
@click="handleWaitTrackCommand(5)"
>
<span class="sub-status-item-label">{{
trackRegisterCount[4]?.name
}}</span>
<span class="tabs-node_count red">{{
trackRegisterCount[4]?.count || 0
}}</span>
</div>
</div>
<div v-if="status === 'INTERCEPTED'" class="sub-status mb-10">
<div
class="sub-status-item"
......@@ -869,7 +937,9 @@
"
placement="bottom"
>
<el-icon color="#E6A23C"><InfoFilled /></el-icon>
<el-icon color="#E6A23C">
<InfoFilled />
</el-icon>
</el-tooltip>
<span class="serial-number">{{ index + 1 }}</span>
</div>
......@@ -1331,7 +1401,7 @@
{{ row.receiverPostCode }}
</span>
</div>
<div class="order-detail-item">
<!-- <div class="order-detail-item">
<span class="order-detail-item-label">收货地址:</span>
<span
class="order-detail-item-value"
......@@ -1339,7 +1409,7 @@
>
{{ row.lanshouAddress }}
</span>
</div>
</div> -->
</div>
</template>
<template #price="{ row }">
......@@ -1380,9 +1450,29 @@
<el-timeline-item
:color="row.finishTime ? '#67C23A' : ''"
:timestamp="row.finishTime"
>完成时间
>发货时间
</el-timeline-item>
<el-timeline-item
v-if="status === 'IN_TRANSIT'"
:color="row.finishTime ? '#F56C6C' : ''"
>
{{
`延迟${(() => {
if (!row.finishTime) return ''
const finishDate = new Date(row.finishTime)
const today = new Date()
const diffTime = today.getTime() - finishDate.getTime()
const diffDays = Math.floor(
diffTime / (1000 * 60 * 60 * 24),
)
return diffDays
})()}
天`
}}
</el-timeline-item>
</el-timeline>
<div v-if="status === 'IN_TRANSIT'" style="color: #f56c6c"></div>
<!-- <div class="order-time-box">
<div class="order-time-item">
<span class="order-time-item-label">创建时间:</span>
......@@ -1445,7 +1535,7 @@
</div>
</template>
<template #failReason="{ row }">
<span v-html="row.failReason" style="white-space: pre-line"></span>
<span style="white-space: pre-line" v-html="row.failReason"></span>
</template>
<template #operate="{ row }">
<div
......@@ -1515,12 +1605,17 @@
<ElButton
link
type="primary"
@click="operationLog(row.id, null)"
@click="operationLog(row.id, null, row)"
>
操作日志
</ElButton>
</span>
<span v-if="['WAIT_TRACK'].includes(status)" class="operate-item">
<ElButton link type="warning" @click="updateTrackingNumber(row)"
>修改跟踪号</ElButton
>
</span>
<!-- <span
v-if="!row.expressSheet && row.status === 'TO_BE_CONFIRMED'"
class="operate-item"
......@@ -1591,6 +1686,11 @@
</span>
</div>
</template>
<template #trackRegisterFailContent="{ row }">
<div style="white-space: pre-line">
{{ JSON.parse(row.trackRegisterFailContent)?.error || '' }}
</div>
</template>
</TableView>
</div>
<div
......@@ -1629,7 +1729,9 @@
"
placement="bottom"
>
<el-icon color="#E6A23C"><InfoFilled /></el-icon>
<el-icon color="#E6A23C">
<InfoFilled />
</el-icon>
</el-tooltip>
</template>
<template
......@@ -1667,8 +1769,8 @@
</div>
<Icon
name="caozuorizhi"
@click="(e: MouseEvent) => operationLog(cardItem.podJomallOrderUsId, e)"
style="width: 28px; height: 28px"
@click="(e: MouseEvent) => operationLog(cardItem.podJomallOrderUsId, e)"
>
<template #title>
<title>操作日志</title>
......@@ -1992,26 +2094,33 @@
link
style="margin-left: 10px"
@click="changeChinaTime('Asia/Shanghai')"
>北京时间</el-button
>
>北京时间
</el-button>
<el-button
:type="timeType === 'America/New_York' ? 'primary' : ''"
size="small"
link
style="margin-left: 10px"
@click="changeChinaTime('America/New_York')"
>新泽西时间</el-button
>
>新泽西时间
</el-button>
<el-button
:type="timeType === 'America/Los_Angeles' ? 'primary' : ''"
size="small"
link
style="margin-left: 10px"
@click="changeChinaTime('America/Los_Angeles')"
>洛杉矶时间</el-button
>
>洛杉矶时间
</el-button>
</div>
</div>
<div
v-if="currentItem?.lanshouAddress"
style="margin-top: 10px; color: #606266"
>
<span>地址:</span>
<span>{{ currentItem?.lanshouAddress }}</span>
</div>
</template>
<LogList :log-list="logList" />
</el-dialog>
......@@ -2029,7 +2138,7 @@
:warehouse-list="warehouseList"
:is-cn="false"
@set-printer="handlePrinterChange"
@set-warehouseId="handleWarehouseIdChange"
@set-warehouse-id="handleWarehouseIdChange"
@refresh="onFastRefresh"
/>
<InspPackagOrder
......@@ -2294,7 +2403,7 @@
<el-dialog v-model="dialogVisible" width="35%">
<img :src="dialogImageUrl" alt="商品预览图片" />
</el-dialog>
<el-dialog title="物流轨迹" v-model="timeLineVisible" width="1000px">
<el-dialog v-model="timeLineVisible" title="物流轨迹" width="1000px">
<el-timeline>
<el-timeline-item
v-for="(item, index) in timeLine"
......@@ -2380,6 +2489,9 @@ import {
getAccountCodeByFactoryIdApi,
printPickPdfByBatchNumberApi,
printProductionPdfByBatchNumberApi,
changeToFinished,
updateTrackingNumberAndRegister,
countTrackRegisterApi,
} from '@/api/podUsOrder'
import { BaseRespData } from '@/types/api'
......@@ -2423,12 +2535,14 @@ import { isArray, isString } from '@/utils/validate'
import platformJson from '../../../json/platform.json'
import { getToken } from '@/api/axios'
import usePermissionBtnStore from '@/store/permission'
const permissionBtns = usePermissionBtnStore()
import {
useRouter,
type NavigationGuardNext,
type RouteLocationNormalized,
} from 'vue-router'
declare global {
interface Window {
ActiveXObject: {
......@@ -2457,12 +2571,41 @@ const currentRow = ref<AddressInfo>({
receiverAddress2: '',
receiverPostCode: '',
})
const currentItem = ref<PodUsOrderListData | null>(null)
const exportLoading = ref(false)
const exportVisible = ref(false)
const exportForm = ref({
resource: '',
})
// 修改物流跟踪号
const updateTrackingNumber = async (row: PodUsOrderListData) => {
const { value } = await ElMessageBox.prompt('请输入物流跟踪号', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /.+/,
inputErrorMessage: '请输入物流跟踪号',
inputPlaceholder: '物流跟踪号',
inputValue: row.trackingNumber,
})
const loading = ElLoading.service({
fullscreen: true,
text: '操作中...',
background: 'rgba(0, 0, 0, 0.3)',
})
try {
const res = await updateTrackingNumberAndRegister(row.id, value)
if (res.code !== 200) return
ElMessage.success('操作成功')
search()
await loadTabData()
} catch (e) {
console.error(e)
} finally {
loading.close()
}
}
const exportData = () => {
exportVisible.value = true
}
......@@ -2566,9 +2709,16 @@ const [searchForm, resetSearchForm] = useValue<SearchForm>({
const exceptionStatus = ref(1)
const interceptCurrent = ref(1)
const interceptStatus = ref(0)
const waitTrackStatus = ref(1)
const trackRegisterCount = ref<
{
count: number
trackRegisterSelect: number
name: string
}[]
>([])
const userMarkList = ref<string[]>([])
const selection = ref<PodUsOrderListData[]>([])
const currentItem = ref<PodUsOrderListData | null>(null)
const pickerOptions = {
shortcuts: [
{
......@@ -2800,8 +2950,9 @@ const handleReComposingDesign = async (row: PodUsOrderListData) => {
}
}
const tableColumns = computed(() => {
let arr = []
if (status.value === 'BATCH_DOWNLOAD') {
return [
arr = [
{
label: '批次号',
prop: 'batchArrangeNum',
......@@ -2848,7 +2999,7 @@ const tableColumns = computed(() => {
align: 'center',
},
{
label: '完成时间',
label: '发货时间',
width: 180,
prop: 'finishTime',
slot: 'finishTime',
......@@ -2870,8 +3021,9 @@ const tableColumns = computed(() => {
prop: 'operate',
},
]
return arr
}
return [
arr = [
{
label: '序号',
prop: 'serialNumber',
......@@ -2919,14 +3071,53 @@ const tableColumns = computed(() => {
align: 'left',
},
{
label: '物流跟踪状态',
width: 220,
prop: 'track17Status',
align: 'left',
},
{
label: '注册失败信息',
width: 220,
prop: 'trackRegisterFailContent',
slot: 'trackRegisterFailContent',
align: 'left',
},
{
label: '操作',
slot: 'operate',
width: 80,
width: 120,
align: 'center',
fixed: 'right',
prop: 'operate',
},
]
// 根据状态动态调整列显示
if (!['WAIT_TRACK'].includes(status.value)) {
const trackRegisterIndex = arr.findIndex(
(item) => item.prop === 'trackRegisterFailContent',
)
if (trackRegisterIndex >= 0) {
arr.splice(trackRegisterIndex, 1)
}
} else {
if (waitTrackStatus.value !== 1) {
const trackRegisterIndex = arr.findIndex(
(item) => item.prop === 'trackRegisterFailContent',
)
if (trackRegisterIndex >= 0) {
arr.splice(trackRegisterIndex, 1)
}
}
}
if (!['WAIT_TRACK', 'IN_TRANSIT'].includes(status.value)) {
const index = arr.findIndex((item) => item.prop === 'track17Status')
if (index >= 0) {
arr.splice(index, 1)
}
}
return arr
})
const rightMenuRef = ref()
const rightClick = (e: MouseEvent) => {
......@@ -2981,7 +3172,7 @@ const asyncOrderAddress = async () => {
}
}
const changeTab = (item: Tab) => {
const changeTab = async (item: Tab) => {
status.value = item.status || ''
localStorage.setItem('podUsStatus', item.status as string)
......@@ -2989,6 +3180,12 @@ const changeTab = (item: Tab) => {
if (item.status === 'INTERCEPTED' && !interceptCurrent.value) {
interceptCurrent.value = 1
}
if (item.status === 'WAIT_TRACK') {
await getRegistData()
}
if (item.status === 'INTERCEPTED') {
await loadTabData()
}
selection.value = []
cardSelection.value = []
......@@ -3013,11 +3210,20 @@ const onCellClassName = ({ column }: { column: Column }) => {
}
}
// 获取注册列表tab信息
const getRegistData = async () => {
const res = await countTrackRegisterApi()
trackRegisterCount.value = res.data
}
// 获取Tab信息
const loadTabData = async () => {
try {
const res = await getOrderTabData()
tabsNav.value = res.data
if (status.value === 'WAIT_TRACK') {
await getRegistData()
}
// 获取拦截数量
const statusRes = await getgetInterceptStateGroupList()
......@@ -3106,6 +3312,8 @@ const {
: undefined,
interceptStatus:
status.value === 'INTERCEPTED' ? interceptStatus.value : '',
trackRegisterSelect:
status.value === 'WAIT_TRACK' ? waitTrackStatus.value : '',
},
page,
pageSize,
......@@ -3924,11 +4132,13 @@ const arrangeFinish = async () => {
loading.close()
}
}
interface timeLineType {
time_iso?: string
time_utc?: string
description?: string
}
const timeLineVisible = ref(false)
const timeLine = ref<timeLineType[]>([])
const logTrajectory = async (row: { id: string }) => {
......@@ -3944,7 +4154,15 @@ const logTrajectory = async (row: { id: string }) => {
const logList = ref<LogListData[]>([])
const logVisible = ref(false)
const operationLog = async (id: number, e: MouseEvent | null) => {
const operationLog = async (
id: number,
e: MouseEvent | null,
row?: PodUsOrderListData,
) => {
if (row) {
currentItem.value = row
}
e && e.stopPropagation()
try {
const res = await getOperationLogApi(id)
......@@ -4723,6 +4941,7 @@ const logisticsSubmit = () => {
})
}
// 异常单分页
const handleExceptionCommand = (command: number) => {
exceptionStatus.value = command
search()
......@@ -4735,6 +4954,13 @@ const handleInterceptionCommand = (current: number, command: number) => {
loadTabData()
}
// 待跟踪分页
const handleWaitTrackCommand = (command: number) => {
waitTrackStatus.value = command
search()
loadTabData()
}
const applyForReplenishment = async (row: ProductList | undefined) => {
if (!row) {
if (cardSelection.value.length === 0) {
......@@ -4998,6 +5224,36 @@ const statusPush = async () => {
}
}
// 转至已完成
const setFinish = async () => {
if (selection.value.length === 0) {
return ElMessage.warning('请选择数据')
}
await ElMessageBox.confirm('是否转至已完成?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
const loading = ElLoading.service({
fullscreen: true,
text: '操作中...',
background: 'rgba(0, 0, 0, 0.3)',
})
try {
const res = await changeToFinished(
selection.value.map((item) => item.id).join(','),
)
if (res.code !== 200) return
ElMessage.success('操作成功')
search()
await loadTabData()
} catch (e) {
console.error(e)
} finally {
loading.close()
}
}
// 完成发货
const completeDelivery = async () => {
if (selection.value.length === 0) {
......@@ -5052,6 +5308,7 @@ const completeDelivery = async () => {
const tempChinaLogs = ref<LogListData[]>([])
const timeType = ref<string>('Asia/Shanghai')
function changeChinaTime(zone: string) {
timeType.value = zone
logList.value = tempChinaLogs.value.map((el) => {
......@@ -5064,11 +5321,13 @@ function changeChinaTime(zone: string) {
}
const token = getToken() as string
async function getPermission() {
const res = await getAccountCodeByFactoryIdApi({ token })
permissionBtns.setBtn(res.data)
console.log(res)
}
getPermission()
const globalProperties =
getCurrentInstance()?.appContext.config.globalProperties // 获取全局挂载
......@@ -5134,6 +5393,7 @@ useRouter().beforeEach((to, from, next) => {
// width: 100px;
// height: 65px;
position: relative;
img {
width: 65%;
}
......@@ -5205,6 +5465,15 @@ useRouter().beforeEach((to, from, next) => {
color: rgb(153 27 27);
}
.tabs-node_count.green {
background: rgb(223 240 216);
color: rgb(39 174 96);
}
.tabs-node_count.yellow {
background: rgb(255 243 205);
color: rgb(91, 99, 18);
}
.empty {
height: 100%;
display: flex;
......@@ -5240,6 +5509,7 @@ useRouter().beforeEach((to, from, next) => {
display: flex;
overflow: hidden;
width: 100%;
.grid-item-value {
display: flex;
flex: 1;
......@@ -5367,6 +5637,7 @@ useRouter().beforeEach((to, from, next) => {
font-size: 15px;
}
}
.orderNumber {
white-space: nowrap;
overflow: hidden;
......@@ -5374,6 +5645,7 @@ useRouter().beforeEach((to, from, next) => {
flex: 1;
min-width: 0; /* 关键属性 */
}
.customizedQuantity {
height: 28px;
width: 28px;
......@@ -5387,6 +5659,7 @@ useRouter().beforeEach((to, from, next) => {
font-weight: 700;
box-sizing: border-box;
}
.triangle-box {
position: absolute;
top: 0;
......@@ -5413,6 +5686,7 @@ useRouter().beforeEach((to, from, next) => {
flex-wrap: wrap;
}
}
.el-dropdown-link {
cursor: pointer;
color: var(--el-color-success);
......@@ -5420,15 +5694,18 @@ useRouter().beforeEach((to, from, next) => {
align-items: center;
outline: none;
}
.el-timeline-item__wrapper {
padding-left: 15px;
top: -4px;
}
.el-timeline
> .el-timeline-item:first-child
.el-timeline-item__timestamp.is-top {
color: #409eff;
}
.flex-between {
display: flex;
justify-content: space-between;
......
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