Commit da3010e2 by zhuzhequan

添加生产单查询功能

parent 7a0fd357
...@@ -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 ',
......
...@@ -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>
...@@ -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
......
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