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' { ...@@ -32,6 +32,7 @@ declare module 'vue' {
ElImage: typeof import('element-plus/es')['ElImage'] ElImage: typeof import('element-plus/es')['ElImage']
ElInput: typeof import('element-plus/es')['ElInput'] ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElLink: typeof import('element-plus/es')['ElLink']
ElMenu: typeof import('element-plus/es')['ElMenu'] ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import('element-plus/es')['ElOption'] ElOption: typeof import('element-plus/es')['ElOption']
...@@ -62,6 +63,7 @@ declare module 'vue' { ...@@ -62,6 +63,7 @@ declare module 'vue' {
RightClickMenu: typeof import('./src/components/RightClickMenu.vue')['default'] RightClickMenu: typeof import('./src/components/RightClickMenu.vue')['default']
RouterLink: typeof import('vue-router')['RouterLink'] RouterLink: typeof import('vue-router')['RouterLink']
RouterView: typeof import('vue-router')['RouterView'] RouterView: typeof import('vue-router')['RouterView']
SearchProdOrder: typeof import('./src/components/searchProdOrder.vue')['default']
Select: typeof import('./src/components/Form/Select.vue')['default'] Select: typeof import('./src/components/Form/Select.vue')['default']
ShipmentOrderDetail: typeof import('./src/components/ShipmentOrderDetail.vue')['default'] ShipmentOrderDetail: typeof import('./src/components/ShipmentOrderDetail.vue')['default']
SideBar: typeof import('./src/components/SideBar.vue')['default'] SideBar: typeof import('./src/components/SideBar.vue')['default']
......
...@@ -36,6 +36,18 @@ export function getSubOrderBySubOrderNumber(thirdSubOrderNumber: string) { ...@@ -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[]) { export function refreshJMProductInfo(data: number[]) {
return axios.post<never, BaseRespData<never>>( return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrder/refreshJomallPodProduct ', 'factory/podJomallOrder/refreshJomallPodProduct ',
......
...@@ -535,6 +535,25 @@ export function statusPushApi(params: (string | number)[]) { ...@@ -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: { export function completeDeliveryApi(params: {
orderIdList: (string | number)[] orderIdList: (string | number)[]
...@@ -576,3 +595,10 @@ export function printProductionPdfByBatchNumberApi(params: { ...@@ -576,3 +595,10 @@ export function printProductionPdfByBatchNumberApi(params: {
}, },
) )
} }
// 待跟踪 注册列表统计接口
export function countTrackRegisterApi() {
return axios.get<never, BaseRespData<never>>(
`factory/podJomallOrderUs/countTrackRegister`,
)
}
...@@ -11,6 +11,13 @@ ...@@ -11,6 +11,13 @@
> >
<img src="../assets/images/printer.png" width="24" height="24" /> <img src="../assets/images/printer.png" width="24" height="24" />
</div> </div>
<div
title="生产单查询"
class="tool-item"
@click="searchVisible = true"
>
<img src="../assets/images/saoma.png" width="24" height="24" />
</div>
</div> </div>
<!-- 格式工具 --> <!-- 格式工具 -->
...@@ -130,13 +137,16 @@ ...@@ -130,13 +137,16 @@
</TableView> </TableView>
</el-dialog> </el-dialog>
</span> </span>
<el-dialog v-model="searchVisible" title="生产单查询" width="100%" fullscreen>
<SearchProductOrder v-if="searchVisible" />
</el-dialog>
<!-- 预览图片 --> <!-- 预览图片 -->
<el-dialog v-model="dialogVisible" width="35%"> <el-dialog v-model="dialogVisible" width="35%">
<img :src="dialogImageUrl" alt="商品预览图片" /> <img :src="dialogImageUrl" alt="商品预览图片" />
</el-dialog> </el-dialog>
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import SearchProductOrder from './searchProdOrder.vue'
import { ref, watch, computed } from 'vue' import { ref, watch, computed } from 'vue'
import { ElMessage } from 'element-plus' import { ElMessage } from 'element-plus'
...@@ -148,6 +158,7 @@ import { LogisticBill } from '@/types/api/podMakeOrder' ...@@ -148,6 +158,7 @@ import { LogisticBill } from '@/types/api/podMakeOrder'
import TableView from '@/components/TableView.vue' import TableView from '@/components/TableView.vue'
const formatDrawer = ref(false) const formatDrawer = ref(false)
const searchVisible = ref(false)
const getLogisticDrawer = ref(false) const getLogisticDrawer = ref(false)
const textareaT = ref('') 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[] = [ ...@@ -187,11 +187,6 @@ const menu: MenuItem[] = [
label: '下载生产客户端', label: '下载生产客户端',
}, },
{ {
index: '/system/external-authorisation',
id: 5,
label: '外部授权',
},
{
index: '/system/customers', index: '/system/customers',
id: 6, id: 6,
label: '客户管理', label: '客户管理',
......
...@@ -123,6 +123,20 @@ export interface PodOrderRes extends PodProductList { ...@@ -123,6 +123,20 @@ export interface PodOrderRes extends PodProductList {
note?: Array<{ prop: string | number; value: string | number }> note?: Array<{ prop: string | number; value: string | number }>
imgList: ImgList 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 { export interface ShipmentOrderRes {
factoryOrderNumber?: string factoryOrderNumber?: string
thirdSubOrderNumber?: string thirdSubOrderNumber?: string
......
...@@ -35,6 +35,7 @@ export interface SearchForm { ...@@ -35,6 +35,7 @@ export interface SearchForm {
craftCode?: string craftCode?: string
thirdStockSku?: string thirdStockSku?: string
interceptStatus?: number | string interceptStatus?: number | string
trackRegisterSelect?: string | number
} }
export interface PodUsOrderListData { export interface PodUsOrderListData {
id: number id: number
...@@ -80,6 +81,7 @@ export interface PodUsOrderListData { ...@@ -80,6 +81,7 @@ export interface PodUsOrderListData {
logisticsWayName?: string logisticsWayName?: string
url?: string | null url?: string | null
tiffUrl?: string | null tiffUrl?: string | null
lanshouAddress?: string | null
} }
export interface ProductList { export interface ProductList {
id: number id: number
......
...@@ -133,7 +133,7 @@ ...@@ -133,7 +133,7 @@
> >
<el-option :value="1" label="创建时间"></el-option> <el-option :value="1" label="创建时间"></el-option>
<el-option :value="2" 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-select>
<el-date-picker <el-date-picker
v-model="timeRange" v-model="timeRange"
...@@ -252,7 +252,7 @@ ...@@ -252,7 +252,7 @@
</ElFormItem> </ElFormItem>
<ElFormItem> <ElFormItem>
<span> <span>
<ElButton link @click="resetSearchForm" style="font-size: 12px" <ElButton link style="font-size: 12px" @click="resetSearchForm"
><span title="重置查询条件">重置</span></ElButton ><span title="重置查询条件">重置</span></ElButton
> >
</span> </span>
...@@ -665,6 +665,12 @@ ...@@ -665,6 +665,12 @@
<ElButton type="warning" @click="statusPush">状态推送</ElButton> <ElButton type="warning" @click="statusPush">状态推送</ElButton>
</span> </span>
</ElFormItem> </ElFormItem>
<ElFormItem v-if="['WAIT_TRACK'].includes(status)">
<span class="item">
<ElButton type="success" @click="setFinish">转至已完成</ElButton>
</span>
</ElFormItem>
<ElFormItem v-if="status === 'COMPLETE'"> <ElFormItem v-if="status === 'COMPLETE'">
<span class="item"> <span class="item">
<ElButton type="success" @click="exportData">导出</ElButton> <ElButton type="success" @click="exportData">导出</ElButton>
...@@ -758,6 +764,68 @@ ...@@ -758,6 +764,68 @@
<span class="sub-status-item-label">待同步</span> <span class="sub-status-item-label">待同步</span>
</div> </div>
</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 v-if="status === 'INTERCEPTED'" class="sub-status mb-10">
<div <div
class="sub-status-item" class="sub-status-item"
...@@ -869,7 +937,9 @@ ...@@ -869,7 +937,9 @@
" "
placement="bottom" placement="bottom"
> >
<el-icon color="#E6A23C"><InfoFilled /></el-icon> <el-icon color="#E6A23C">
<InfoFilled />
</el-icon>
</el-tooltip> </el-tooltip>
<span class="serial-number">{{ index + 1 }}</span> <span class="serial-number">{{ index + 1 }}</span>
</div> </div>
...@@ -1331,7 +1401,7 @@ ...@@ -1331,7 +1401,7 @@
{{ row.receiverPostCode }} {{ row.receiverPostCode }}
</span> </span>
</div> </div>
<div class="order-detail-item"> <!-- <div class="order-detail-item">
<span class="order-detail-item-label">收货地址:</span> <span class="order-detail-item-label">收货地址:</span>
<span <span
class="order-detail-item-value" class="order-detail-item-value"
...@@ -1339,7 +1409,7 @@ ...@@ -1339,7 +1409,7 @@
> >
{{ row.lanshouAddress }} {{ row.lanshouAddress }}
</span> </span>
</div> </div> -->
</div> </div>
</template> </template>
<template #price="{ row }"> <template #price="{ row }">
...@@ -1380,9 +1450,29 @@ ...@@ -1380,9 +1450,29 @@
<el-timeline-item <el-timeline-item
:color="row.finishTime ? '#67C23A' : ''" :color="row.finishTime ? '#67C23A' : ''"
:timestamp="row.finishTime" :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-item>
</el-timeline> </el-timeline>
<div v-if="status === 'IN_TRANSIT'" style="color: #f56c6c"></div>
<!-- <div class="order-time-box"> <!-- <div class="order-time-box">
<div class="order-time-item"> <div class="order-time-item">
<span class="order-time-item-label">创建时间:</span> <span class="order-time-item-label">创建时间:</span>
...@@ -1445,7 +1535,7 @@ ...@@ -1445,7 +1535,7 @@
</div> </div>
</template> </template>
<template #failReason="{ row }"> <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>
<template #operate="{ row }"> <template #operate="{ row }">
<div <div
...@@ -1515,12 +1605,17 @@ ...@@ -1515,12 +1605,17 @@
<ElButton <ElButton
link link
type="primary" type="primary"
@click="operationLog(row.id, null)" @click="operationLog(row.id, null, row)"
> >
操作日志 操作日志
</ElButton> </ElButton>
</span> </span>
<span v-if="['WAIT_TRACK'].includes(status)" class="operate-item">
<ElButton link type="warning" @click="updateTrackingNumber(row)"
>修改跟踪号</ElButton
>
</span>
<!-- <span <!-- <span
v-if="!row.expressSheet && row.status === 'TO_BE_CONFIRMED'" v-if="!row.expressSheet && row.status === 'TO_BE_CONFIRMED'"
class="operate-item" class="operate-item"
...@@ -1591,6 +1686,11 @@ ...@@ -1591,6 +1686,11 @@
</span> </span>
</div> </div>
</template> </template>
<template #trackRegisterFailContent="{ row }">
<div style="white-space: pre-line">
{{ JSON.parse(row.trackRegisterFailContent)?.error || '' }}
</div>
</template>
</TableView> </TableView>
</div> </div>
<div <div
...@@ -1629,7 +1729,9 @@ ...@@ -1629,7 +1729,9 @@
" "
placement="bottom" placement="bottom"
> >
<el-icon color="#E6A23C"><InfoFilled /></el-icon> <el-icon color="#E6A23C">
<InfoFilled />
</el-icon>
</el-tooltip> </el-tooltip>
</template> </template>
<template <template
...@@ -1667,8 +1769,8 @@ ...@@ -1667,8 +1769,8 @@
</div> </div>
<Icon <Icon
name="caozuorizhi" name="caozuorizhi"
@click="(e: MouseEvent) => operationLog(cardItem.podJomallOrderUsId, e)"
style="width: 28px; height: 28px" style="width: 28px; height: 28px"
@click="(e: MouseEvent) => operationLog(cardItem.podJomallOrderUsId, e)"
> >
<template #title> <template #title>
<title>操作日志</title> <title>操作日志</title>
...@@ -1992,26 +2094,33 @@ ...@@ -1992,26 +2094,33 @@
link link
style="margin-left: 10px" style="margin-left: 10px"
@click="changeChinaTime('Asia/Shanghai')" @click="changeChinaTime('Asia/Shanghai')"
>北京时间</el-button >北京时间
> </el-button>
<el-button <el-button
:type="timeType === 'America/New_York' ? 'primary' : ''" :type="timeType === 'America/New_York' ? 'primary' : ''"
size="small" size="small"
link link
style="margin-left: 10px" style="margin-left: 10px"
@click="changeChinaTime('America/New_York')" @click="changeChinaTime('America/New_York')"
>新泽西时间</el-button >新泽西时间
> </el-button>
<el-button <el-button
:type="timeType === 'America/Los_Angeles' ? 'primary' : ''" :type="timeType === 'America/Los_Angeles' ? 'primary' : ''"
size="small" size="small"
link link
style="margin-left: 10px" style="margin-left: 10px"
@click="changeChinaTime('America/Los_Angeles')" @click="changeChinaTime('America/Los_Angeles')"
>洛杉矶时间</el-button >洛杉矶时间
> </el-button>
</div> </div>
</div> </div>
<div
v-if="currentItem?.lanshouAddress"
style="margin-top: 10px; color: #606266"
>
<span>地址:</span>
<span>{{ currentItem?.lanshouAddress }}</span>
</div>
</template> </template>
<LogList :log-list="logList" /> <LogList :log-list="logList" />
</el-dialog> </el-dialog>
...@@ -2029,7 +2138,7 @@ ...@@ -2029,7 +2138,7 @@
:warehouse-list="warehouseList" :warehouse-list="warehouseList"
:is-cn="false" :is-cn="false"
@set-printer="handlePrinterChange" @set-printer="handlePrinterChange"
@set-warehouseId="handleWarehouseIdChange" @set-warehouse-id="handleWarehouseIdChange"
@refresh="onFastRefresh" @refresh="onFastRefresh"
/> />
<InspPackagOrder <InspPackagOrder
...@@ -2294,7 +2403,7 @@ ...@@ -2294,7 +2403,7 @@
<el-dialog v-model="dialogVisible" width="35%"> <el-dialog v-model="dialogVisible" width="35%">
<img :src="dialogImageUrl" alt="商品预览图片" /> <img :src="dialogImageUrl" alt="商品预览图片" />
</el-dialog> </el-dialog>
<el-dialog title="物流轨迹" v-model="timeLineVisible" width="1000px"> <el-dialog v-model="timeLineVisible" title="物流轨迹" width="1000px">
<el-timeline> <el-timeline>
<el-timeline-item <el-timeline-item
v-for="(item, index) in timeLine" v-for="(item, index) in timeLine"
...@@ -2380,6 +2489,9 @@ import { ...@@ -2380,6 +2489,9 @@ import {
getAccountCodeByFactoryIdApi, getAccountCodeByFactoryIdApi,
printPickPdfByBatchNumberApi, printPickPdfByBatchNumberApi,
printProductionPdfByBatchNumberApi, printProductionPdfByBatchNumberApi,
changeToFinished,
updateTrackingNumberAndRegister,
countTrackRegisterApi,
} from '@/api/podUsOrder' } from '@/api/podUsOrder'
import { BaseRespData } from '@/types/api' import { BaseRespData } from '@/types/api'
...@@ -2423,12 +2535,14 @@ import { isArray, isString } from '@/utils/validate' ...@@ -2423,12 +2535,14 @@ import { isArray, isString } from '@/utils/validate'
import platformJson from '../../../json/platform.json' import platformJson from '../../../json/platform.json'
import { getToken } from '@/api/axios' import { getToken } from '@/api/axios'
import usePermissionBtnStore from '@/store/permission' import usePermissionBtnStore from '@/store/permission'
const permissionBtns = usePermissionBtnStore() const permissionBtns = usePermissionBtnStore()
import { import {
useRouter, useRouter,
type NavigationGuardNext, type NavigationGuardNext,
type RouteLocationNormalized, type RouteLocationNormalized,
} from 'vue-router' } from 'vue-router'
declare global { declare global {
interface Window { interface Window {
ActiveXObject: { ActiveXObject: {
...@@ -2457,12 +2571,41 @@ const currentRow = ref<AddressInfo>({ ...@@ -2457,12 +2571,41 @@ const currentRow = ref<AddressInfo>({
receiverAddress2: '', receiverAddress2: '',
receiverPostCode: '', receiverPostCode: '',
}) })
const currentItem = ref<PodUsOrderListData | null>(null)
const exportLoading = ref(false) const exportLoading = ref(false)
const exportVisible = ref(false) const exportVisible = ref(false)
const exportForm = ref({ const exportForm = ref({
resource: '', 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 = () => { const exportData = () => {
exportVisible.value = true exportVisible.value = true
} }
...@@ -2566,9 +2709,16 @@ const [searchForm, resetSearchForm] = useValue<SearchForm>({ ...@@ -2566,9 +2709,16 @@ const [searchForm, resetSearchForm] = useValue<SearchForm>({
const exceptionStatus = ref(1) const exceptionStatus = ref(1)
const interceptCurrent = ref(1) const interceptCurrent = ref(1)
const interceptStatus = ref(0) const interceptStatus = ref(0)
const waitTrackStatus = ref(1)
const trackRegisterCount = ref<
{
count: number
trackRegisterSelect: number
name: string
}[]
>([])
const userMarkList = ref<string[]>([]) const userMarkList = ref<string[]>([])
const selection = ref<PodUsOrderListData[]>([]) const selection = ref<PodUsOrderListData[]>([])
const currentItem = ref<PodUsOrderListData | null>(null)
const pickerOptions = { const pickerOptions = {
shortcuts: [ shortcuts: [
{ {
...@@ -2800,8 +2950,9 @@ const handleReComposingDesign = async (row: PodUsOrderListData) => { ...@@ -2800,8 +2950,9 @@ const handleReComposingDesign = async (row: PodUsOrderListData) => {
} }
} }
const tableColumns = computed(() => { const tableColumns = computed(() => {
let arr = []
if (status.value === 'BATCH_DOWNLOAD') { if (status.value === 'BATCH_DOWNLOAD') {
return [ arr = [
{ {
label: '批次号', label: '批次号',
prop: 'batchArrangeNum', prop: 'batchArrangeNum',
...@@ -2848,7 +2999,7 @@ const tableColumns = computed(() => { ...@@ -2848,7 +2999,7 @@ const tableColumns = computed(() => {
align: 'center', align: 'center',
}, },
{ {
label: '完成时间', label: '发货时间',
width: 180, width: 180,
prop: 'finishTime', prop: 'finishTime',
slot: 'finishTime', slot: 'finishTime',
...@@ -2870,8 +3021,9 @@ const tableColumns = computed(() => { ...@@ -2870,8 +3021,9 @@ const tableColumns = computed(() => {
prop: 'operate', prop: 'operate',
}, },
] ]
return arr
} }
return [ arr = [
{ {
label: '序号', label: '序号',
prop: 'serialNumber', prop: 'serialNumber',
...@@ -2919,14 +3071,53 @@ const tableColumns = computed(() => { ...@@ -2919,14 +3071,53 @@ const tableColumns = computed(() => {
align: 'left', align: 'left',
}, },
{ {
label: '物流跟踪状态',
width: 220,
prop: 'track17Status',
align: 'left',
},
{
label: '注册失败信息',
width: 220,
prop: 'trackRegisterFailContent',
slot: 'trackRegisterFailContent',
align: 'left',
},
{
label: '操作', label: '操作',
slot: 'operate', slot: 'operate',
width: 80, width: 120,
align: 'center', align: 'center',
fixed: 'right', fixed: 'right',
prop: 'operate', 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 rightMenuRef = ref()
const rightClick = (e: MouseEvent) => { const rightClick = (e: MouseEvent) => {
...@@ -2981,7 +3172,7 @@ const asyncOrderAddress = async () => { ...@@ -2981,7 +3172,7 @@ const asyncOrderAddress = async () => {
} }
} }
const changeTab = (item: Tab) => { const changeTab = async (item: Tab) => {
status.value = item.status || '' status.value = item.status || ''
localStorage.setItem('podUsStatus', item.status as string) localStorage.setItem('podUsStatus', item.status as string)
...@@ -2989,6 +3180,12 @@ const changeTab = (item: Tab) => { ...@@ -2989,6 +3180,12 @@ const changeTab = (item: Tab) => {
if (item.status === 'INTERCEPTED' && !interceptCurrent.value) { if (item.status === 'INTERCEPTED' && !interceptCurrent.value) {
interceptCurrent.value = 1 interceptCurrent.value = 1
} }
if (item.status === 'WAIT_TRACK') {
await getRegistData()
}
if (item.status === 'INTERCEPTED') {
await loadTabData()
}
selection.value = [] selection.value = []
cardSelection.value = [] cardSelection.value = []
...@@ -3013,11 +3210,20 @@ const onCellClassName = ({ column }: { column: Column }) => { ...@@ -3013,11 +3210,20 @@ const onCellClassName = ({ column }: { column: Column }) => {
} }
} }
// 获取注册列表tab信息
const getRegistData = async () => {
const res = await countTrackRegisterApi()
trackRegisterCount.value = res.data
}
// 获取Tab信息 // 获取Tab信息
const loadTabData = async () => { const loadTabData = async () => {
try { try {
const res = await getOrderTabData() const res = await getOrderTabData()
tabsNav.value = res.data tabsNav.value = res.data
if (status.value === 'WAIT_TRACK') {
await getRegistData()
}
// 获取拦截数量 // 获取拦截数量
const statusRes = await getgetInterceptStateGroupList() const statusRes = await getgetInterceptStateGroupList()
...@@ -3106,6 +3312,8 @@ const { ...@@ -3106,6 +3312,8 @@ const {
: undefined, : undefined,
interceptStatus: interceptStatus:
status.value === 'INTERCEPTED' ? interceptStatus.value : '', status.value === 'INTERCEPTED' ? interceptStatus.value : '',
trackRegisterSelect:
status.value === 'WAIT_TRACK' ? waitTrackStatus.value : '',
}, },
page, page,
pageSize, pageSize,
...@@ -3924,11 +4132,13 @@ const arrangeFinish = async () => { ...@@ -3924,11 +4132,13 @@ const arrangeFinish = async () => {
loading.close() loading.close()
} }
} }
interface timeLineType { interface timeLineType {
time_iso?: string time_iso?: string
time_utc?: string time_utc?: string
description?: string description?: string
} }
const timeLineVisible = ref(false) const timeLineVisible = ref(false)
const timeLine = ref<timeLineType[]>([]) const timeLine = ref<timeLineType[]>([])
const logTrajectory = async (row: { id: string }) => { const logTrajectory = async (row: { id: string }) => {
...@@ -3944,7 +4154,15 @@ const logTrajectory = async (row: { id: string }) => { ...@@ -3944,7 +4154,15 @@ const logTrajectory = async (row: { id: string }) => {
const logList = ref<LogListData[]>([]) const logList = ref<LogListData[]>([])
const logVisible = ref(false) 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() e && e.stopPropagation()
try { try {
const res = await getOperationLogApi(id) const res = await getOperationLogApi(id)
...@@ -4723,6 +4941,7 @@ const logisticsSubmit = () => { ...@@ -4723,6 +4941,7 @@ const logisticsSubmit = () => {
}) })
} }
// 异常单分页
const handleExceptionCommand = (command: number) => { const handleExceptionCommand = (command: number) => {
exceptionStatus.value = command exceptionStatus.value = command
search() search()
...@@ -4735,6 +4954,13 @@ const handleInterceptionCommand = (current: number, command: number) => { ...@@ -4735,6 +4954,13 @@ const handleInterceptionCommand = (current: number, command: number) => {
loadTabData() loadTabData()
} }
// 待跟踪分页
const handleWaitTrackCommand = (command: number) => {
waitTrackStatus.value = command
search()
loadTabData()
}
const applyForReplenishment = async (row: ProductList | undefined) => { const applyForReplenishment = async (row: ProductList | undefined) => {
if (!row) { if (!row) {
if (cardSelection.value.length === 0) { if (cardSelection.value.length === 0) {
...@@ -4998,6 +5224,36 @@ const statusPush = async () => { ...@@ -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 () => { const completeDelivery = async () => {
if (selection.value.length === 0) { if (selection.value.length === 0) {
...@@ -5052,6 +5308,7 @@ const completeDelivery = async () => { ...@@ -5052,6 +5308,7 @@ const completeDelivery = async () => {
const tempChinaLogs = ref<LogListData[]>([]) const tempChinaLogs = ref<LogListData[]>([])
const timeType = ref<string>('Asia/Shanghai') const timeType = ref<string>('Asia/Shanghai')
function changeChinaTime(zone: string) { function changeChinaTime(zone: string) {
timeType.value = zone timeType.value = zone
logList.value = tempChinaLogs.value.map((el) => { logList.value = tempChinaLogs.value.map((el) => {
...@@ -5064,11 +5321,13 @@ function changeChinaTime(zone: string) { ...@@ -5064,11 +5321,13 @@ function changeChinaTime(zone: string) {
} }
const token = getToken() as string const token = getToken() as string
async function getPermission() { async function getPermission() {
const res = await getAccountCodeByFactoryIdApi({ token }) const res = await getAccountCodeByFactoryIdApi({ token })
permissionBtns.setBtn(res.data) permissionBtns.setBtn(res.data)
console.log(res) console.log(res)
} }
getPermission() getPermission()
const globalProperties = const globalProperties =
getCurrentInstance()?.appContext.config.globalProperties // 获取全局挂载 getCurrentInstance()?.appContext.config.globalProperties // 获取全局挂载
...@@ -5134,6 +5393,7 @@ useRouter().beforeEach((to, from, next) => { ...@@ -5134,6 +5393,7 @@ useRouter().beforeEach((to, from, next) => {
// width: 100px; // width: 100px;
// height: 65px; // height: 65px;
position: relative; position: relative;
img { img {
width: 65%; width: 65%;
} }
...@@ -5205,6 +5465,15 @@ useRouter().beforeEach((to, from, next) => { ...@@ -5205,6 +5465,15 @@ useRouter().beforeEach((to, from, next) => {
color: rgb(153 27 27); 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 { .empty {
height: 100%; height: 100%;
display: flex; display: flex;
...@@ -5240,6 +5509,7 @@ useRouter().beforeEach((to, from, next) => { ...@@ -5240,6 +5509,7 @@ useRouter().beforeEach((to, from, next) => {
display: flex; display: flex;
overflow: hidden; overflow: hidden;
width: 100%; width: 100%;
.grid-item-value { .grid-item-value {
display: flex; display: flex;
flex: 1; flex: 1;
...@@ -5367,6 +5637,7 @@ useRouter().beforeEach((to, from, next) => { ...@@ -5367,6 +5637,7 @@ useRouter().beforeEach((to, from, next) => {
font-size: 15px; font-size: 15px;
} }
} }
.orderNumber { .orderNumber {
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
...@@ -5374,6 +5645,7 @@ useRouter().beforeEach((to, from, next) => { ...@@ -5374,6 +5645,7 @@ useRouter().beforeEach((to, from, next) => {
flex: 1; flex: 1;
min-width: 0; /* 关键属性 */ min-width: 0; /* 关键属性 */
} }
.customizedQuantity { .customizedQuantity {
height: 28px; height: 28px;
width: 28px; width: 28px;
...@@ -5387,6 +5659,7 @@ useRouter().beforeEach((to, from, next) => { ...@@ -5387,6 +5659,7 @@ useRouter().beforeEach((to, from, next) => {
font-weight: 700; font-weight: 700;
box-sizing: border-box; box-sizing: border-box;
} }
.triangle-box { .triangle-box {
position: absolute; position: absolute;
top: 0; top: 0;
...@@ -5413,6 +5686,7 @@ useRouter().beforeEach((to, from, next) => { ...@@ -5413,6 +5686,7 @@ useRouter().beforeEach((to, from, next) => {
flex-wrap: wrap; flex-wrap: wrap;
} }
} }
.el-dropdown-link { .el-dropdown-link {
cursor: pointer; cursor: pointer;
color: var(--el-color-success); color: var(--el-color-success);
...@@ -5420,15 +5694,18 @@ useRouter().beforeEach((to, from, next) => { ...@@ -5420,15 +5694,18 @@ useRouter().beforeEach((to, from, next) => {
align-items: center; align-items: center;
outline: none; outline: none;
} }
.el-timeline-item__wrapper { .el-timeline-item__wrapper {
padding-left: 15px; padding-left: 15px;
top: -4px; top: -4px;
} }
.el-timeline .el-timeline
> .el-timeline-item:first-child > .el-timeline-item:first-child
.el-timeline-item__timestamp.is-top { .el-timeline-item__timestamp.is-top {
color: #409eff; color: #409eff;
} }
.flex-between { .flex-between {
display: flex; display: flex;
justify-content: space-between; 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