Commit 4a4ca76c by linjinhong

Merge remote-tracking branch 'origin/master' into lin-task

parents b722b152 de688cbf
import { BasePaginationData, BaseRespData } from '@/types/api'
import {
ProductList,
PodCnOrderListData,
SearchForm,
Tab,
LogListData,
WarehouseListData,
LogisticsData,
ExportParams,
IconfirmSubmit
} from '@/types/api/podCnOrder'
import { InterceptStateGroupData } from '@/types/api/podUsOrder'
import axios from './axios'
import { PodMakeOrderData } from '@/types/api/podMakeOrder'
export function exportPodCnInfo(data: ExportParams) {
return axios.post<never, BasePaginationData<never>>(
'factory/podJomallOrderCn/exportPodCnOrder',
data,
)
}
// 拦截状态数量
export function getgetInterceptStateGroupList() {
return axios.get<never, BaseRespData<InterceptStateGroupData>>(
'factory/podJomallOrderCn/findInterceptStateGroupList',
)
}
// 同步收货地址
export function syncReceiverAddress(data: number[]) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderCn/syncReceiverAddress',
data,
)
}
export function getPackingCnDataApi(
code: string,
factoryNo: number,
box: number | null,
warehouseId: number | string,
) {
return axios.get<never, BaseRespData<PodMakeOrderData>>(
'/factory/podJomallOrderCn/getPodBoxDetailsBySkuOrNo',
{
params: {
podJomallCnNo: code,
box,
factoryNo,
warehouseId,
},
},
)
}
export function refreshAddressApi(idList: number[]) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderCn/syncReceiverAddress',
idList,
)
}
export function updateAddressApi(data: PodCnOrderListData) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderCn/updateReceiverAddress',
data,
)
}
export function getOrderTabData() {
return axios.get<never, BaseRespData<Tab[]>>(
'/factory/podJomallOrderCn/findStateGroupList',
)
}
export function getOrderList(
params: SearchForm,
currentPage: number,
pageSize: number,
) {
return axios.post<never, BasePaginationData<PodCnOrderListData[]>>(
'/factory/podJomallOrderCn/list_page',
{
...params,
currentPage,
pageSize,
},
)
}
export function getCardOrderList(
params: SearchForm,
currentPage: number,
pageSize: number,
) {
return axios.post<never, BasePaginationData<ProductList[]>>(
'/factory/podJomallOrderProductCn/list_page',
{
...params,
currentPage,
pageSize,
},
)
}
export function confirmOrderApi(
data: number[],
productionClient: string,
type: string,
logisticsTrialCalculation?: LogisticsData | null,
) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderCn/confirmOrders',
{
ids: data.join(','),
type,
logisticsTrialCalculation,
productionClient,
},
)
}
export function updateExceptionOrderApi(data: number[]) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderCn/updateExceptionOrders',
{
orderIds: data,
},
)
}
export function changeExceptionOrderApi(
url: string,
ids: number[],
type: string,
value: string,
) {
return axios.post<never, BaseRespData<never>>(url, {
orderIds: ids,
exceptionType: type,
exceptionReason: value,
})
}
export function cancelOrderApi(ids: number[], value: string) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderCn/cancelOrders',
{
orderIds: ids,
cancelReason: value,
},
)
}
export function getOperationLogApi(id: number) {
return axios.get<never, BaseRespData<LogListData[]>>(
`factory/podJomallOrderCnLog/getPodJomallOrderCnLog?id=${id}`,
)
}
export function getSubOrderBySubOrderNumber(factorySubOrderNumber: string) {
return axios.get<never, BaseRespData<ProductList>>(
'factory/podJomallOrderProductCn/getProductCnByFactorySubOrderNumber',
{
params: {
factorySubOrderNumber,
},
},
)
}
export function downloadMaterialApi(id: number[]) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderProductCn/downloadDesignImages',
id,
)
}
export function productionQueryApi(id: number, podJomallOrderCnId: number) {
return axios.post<never, BasePaginationData<never>>(
'factory/podJomallOrderProductCn/completeDelivery',
{
id,
podJomallOrderCnId,
},
)
}
export function printProductionOrderApi(orderIds: number[]) {
return axios.post<never, BaseRespData<string>>(
'factory/podJomallOrderProductCn/printProducePdf',
orderIds,
)
}
export function printPrintOrderApi(orderIds: number[]) {
return axios.post<never, BaseRespData<string>>(
'factory/podJomallOrderProductCn/printPickPdf',
{
ids: orderIds.join(','),
},
)
}
export function printPickingOrderApi(orderIds: number[]) {
return axios.post<never, BaseRespData<string>>(
'factory/podJomallOrderProductCn/pickingComplete',
{
ids: orderIds.join(','),
},
)
}
export function stockOutCheckApi(orderIds: number[]) {
return axios.get<
never,
BaseRespData<
{
id: number
status: boolean
message?: string
factoryOrderNumber?: string
}[]
>
>(`factory/podJomallOrderCn/replenishVerify?ids=${orderIds.join(',')}`)
}
export function toBePickingApi(orderIds: number[]) {
return axios.get<never, BaseRespData<never>>(
`factory/podJomallOrderCn/updateStockOutOrderToPicking?ids=${orderIds.join(
',',
)}`,
)
}
export function getOrderDetailById(id: number) {
return axios.get<never, BaseRespData<ProductList>>(
`factory/podJomallOrderProductCn/getProductCnById?id=${id}`,
)
}
export function getPackingDataApi(
code: string,
factoryNo: number,
box: number | null,
warehouseId: number | string,
) {
return axios.get<never, BaseRespData<PodMakeOrderData>>(
'/factory/podJomallOrderCn/getPodBoxDetailsBySkuOrNo',
{
params: {
podJomallCnNo: code,
box,
factoryNo,
warehouseId,
},
},
)
}
export function getPodBoxListApi(
factoryNo: number | string,
warehouseId: number | string,
) {
return axios.get<never, BaseRespData<PodMakeOrderData[]>>(
'factory/podJomallOrderCn/getPodBoxOrderDetails',
{
params: { factoryNo, warehouseId },
},
)
}
export function submitInspectionApi(
data: { id: number; version?: number }[],
boxIndex: number | null,
warehouseId: number | string,
) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderCn/podPrintOrderComplete?box=${boxIndex}&warehouseId=${warehouseId}`,
{
orderParamList: data,
},
)
}
export function clearBoxApi(
factoryNo: number,
box: number | null,
warehouseId: number | string,
) {
return axios.get<never, BaseRespData<never>>(
'factory/podJomallOrderCn/delPodBoxOrderDetailsByBox',
{
params: { factoryNo, box, warehouseId },
},
)
}
export function clearAllBoxApi() {
return axios.get<never, BaseRespData<never>>(
'factory/podJomallOrderCn/delPodBoxOrderDetails',
)
}
export function updateRemarkApi(id: number, content: string) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderCn/addRemark',
{ id, content },
)
}
export function getLogisticsCalculation(id: number) {
return axios.get<never, BaseRespData<never>>(
'factory/podJomallOrderCn/getLogisticsCalculation',
{ params: { id } },
)
}
export function loadWarehouseListApi() {
return axios.get<never, BaseRespData<WarehouseListData[]>>(
'factoryWarehouseInfo/getAll',
)
}
export function refreshMaterialApi(data: {
orderIds?: string
productIds?: string
}) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderProductCn/refreshDesignImages ',
data,
)
}
// 拦截状态改变
export function interceptUpdateApi(params: {
orderIds: (string | number)[]
interceptStatus: number
}) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderCn/updateInterceptStatus`,
params,
)
}
// 驳回
export function rejectToApi(params: {
orderStatus: string
productList: ProductList[]
reasonStr: string
}) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderCn/rejectTo`,
params,
)
}
// 状态推送
export function statusPushApi(params: (string | number)[]) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderCn/statusPush`,
params,
)
}
// 完成发货
export function completeDeliveryApi(params: {
orderIdList: (string | number)[]
}) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderCn/completeDelivery`,
params,
)
}
export function refreshProductInformationApi(data: {
orderIds?: string
productIds?: string
}) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderProductCn/refreshProductInfo',
data,
)
}
// 设计图排版
export function composingDesignImages(data: number[], type: string) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderCn/composingDesignImages?type=${type}`,
data,
)
}
// 转至待拣胚
export function updateLogisticsToPickingApi(params: { ids: string }) {
return axios.get<never, BaseRespData<never>>(
`factory/podJomallOrderCn/updateLogisticsToPicking`,
{
params,
},
)
}
// 转至待排单
export function updateLogisticsToArrangeApi(params: { ids: string }) {
return axios.get<never, BaseRespData<never>>(
`factory/podJomallOrderCn/updateLogisticsToArrange`,
{
params,
},
)
}
export function applyForReplenishmentApi(
data: {
id: number
productId: number
factorySubOrderNumber: string
replenishmentNum: string
podJomallOrderCnStatus: string
}[],
) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderProductCn/applyForReplenishment`,
data,
)
}
export function replenishmentSuccessApi(data: number[]) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderProductCn/replenishmentComplete`,
data,
)
}
//确认生产
export function confirmProductApi(data:IconfirmSubmit) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderCn/confirmProduct`,
data,
)
}
export function toOutOfStockApi(ids: number[]) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderCn/pickingToStockOut`,
ids,
)
}
// 排单完成
export function arrangeFinishApi(ids: number[]) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderProductCn/arrangeFinish`,
ids,
)
}
// 获取工艺
export function getListCraftApi() {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderProductCn/listCraft`,
)
}
// 批量下载 列表
export function batchDownloadApi(currentPage: number, pageSize: number) {
return axios.post<never, BaseRespData<never>>(
`factory/podBatchDownload/cn/list_page`,
{
currentPage,
pageSize,
},
)
}
// 批量下载 下载
export function batchDownloadDownloadApi(params: { id: number; type: string }) {
return axios.get<never, BaseRespData<never>>(
`factory/podBatchDownload/download`,
{
params,
},
)
}
// 批量下载 删除
export function batchDownloadDeleteApi(params: { ids: string }) {
return axios.get<never, BaseRespData<never>>(
`factory/podBatchDownload/delete`,
{
params,
},
)
}
// 批量下载 重新排版
export function batchDownloadRecomposingApi(params: { id: number }) {
return axios.get<never, BaseRespData<never>>(
`factory/podBatchDownload/reComposingDesignImages`,
{
params,
},
)
}
export function batchDownloadCnRecomposingApi(params: { id: number }) {
return axios.get<never, BaseRespData<never>>(
`factory/podBatchDownload/reCnComposingDesignImages`,
{
params,
},
)
}
// 生产完成
export function updateToWaitShipmentApi(params: {
cnUpdateParams: Array<{
id: number | string
podJomallOrderCnId: number | string
factorySubOrderNumber: number | string
version: number | string
}>
}) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderCn/updateToWaitShipment`,
params,
)
}
//创建物流订单
export function createLogisticsOrdersApi(orderIds: (string | number)[]) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderCn/createLogisticsOrders`,
orderIds,
)
}
// 获取跟踪号
export function getTrackingNumberApi(orderIds: (string | number)[]) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderCn/getTrackingNumber',
orderIds,
)
}
// 获取打印面单
export function getfaceSimplexFileApi(orderIds: (string | number)[]) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderCn/getfaceSimplexFile',
orderIds,
)
}
// 取消物流订单
export function cancelLogisticsOrderApi(orderIds: (string | number)[]) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderCn/cancelLogisticsOrder',
orderIds,
)
}
// 更改物流
export function changeLogisticsApi(params: {
updateByIdParam: {
id: string | number
dataVersion: number
}
logisticsTrialCalculation: LogisticsData
}) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderCn/changeLogistics',
params,
)
}
// 修改自有物流信息
export function updateSelfLogistics(params: {
trackingNumber: string
expressSheet: string
processNumber: string
id?: string
}) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderCn/updateSelfLogistics',
params,
)
}
// 上传物流面单
export function uploadExpressSheet(params: {
trackingNumber: string
file: File
}) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderCn/uploadExpressSheet',
params,
)
}
......@@ -294,7 +294,7 @@ export function refreshMaterialApi(data: {
productIds?: string
}) {
return axios.post<never, BaseRespData<never>>(
'factory/podJomallOrderProductUs/refreshDesignImages ',
'factory/podJomallOrderProductUs/refreshDesignImages',
data,
)
}
......@@ -380,15 +380,6 @@ export function composingDesignImages(
data,
)
}
// 转至待拣胚
export function updateLogisticsToPickingApi(params: { ids: string }) {
return axios.get<never, BaseRespData<never>>(
`factory/podJomallOrderUs/updateLogisticsToPicking`,
{
params,
},
)
}
// 转至待排单
export function updateLogisticsToArrangeApi(params: { ids: string }) {
return axios.get<never, BaseRespData<never>>(
......@@ -470,7 +461,7 @@ export function getListCraftApi() {
// 批量下载 列表
export function batchDownloadApi(currentPage: number, pageSize: number) {
return axios.post<never, BaseRespData<never>>(
`factory/podUsBatchDownload/list_page`,
`factory/podBatchDownload/us/list_page`,
{
currentPage,
pageSize,
......@@ -481,7 +472,7 @@ export function batchDownloadApi(currentPage: number, pageSize: number) {
// 批量下载 下载
export function batchDownloadDownloadApi(params: { id: number; type: string }) {
return axios.get<never, BaseRespData<never>>(
`factory/podUsBatchDownload/download`,
`factory/podBatchDownload/download`,
{
params,
},
......@@ -491,7 +482,7 @@ export function batchDownloadDownloadApi(params: { id: number; type: string }) {
// 批量下载 删除
export function batchDownloadDeleteApi(params: { ids?: string }) {
return axios.get<never, BaseRespData<never>>(
`factory/podUsBatchDownload/delete`,
`factory/podBatchDownload/delete`,
{
params,
},
......@@ -505,7 +496,7 @@ export function batchDownloadRecomposingApi(params: {
templateWidth?: number
}) {
return axios.get<never, BaseRespData<never>>(
`factory/podUsBatchDownload/reComposingDesignImages`,
`factory/podBatchDownload/reComposingDesignImages`,
{
params,
},
......
......@@ -67,6 +67,13 @@ const router = createRouter({
component: PodOrderList,
},
{
path: '/pod-cn-order/list',
meta: {
title: 'POD订单(CN)',
},
component: () => import('@/views/order/podCN/index.vue'),
},
{
path: '/pod-us-order/list',
meta: {
title: 'POD订单(US)',
......
......@@ -113,13 +113,19 @@ const menu: MenuItem[] = [
label: 'POD订单',
},
{
index: '/pod-cn-order/list',
id: 6,
label: 'POD订单(CN)',
},
{
index: '/pod-us-order/list',
id: 8,
label: 'POD订单(US)',
},
{
index: '/pod-us-order/orderTracking',
id: 8,
id: 9,
label: 'POD(US)订单跟踪',
},
],
......
import { defineStore } from 'pinia'
import {
OrderData,
PodMakeOrderData,
ProductList,
} from '@/types/api/podMakeOrder'
import { getPodBoxListApi } from '@/api/podCnOrder'
export interface OrderStoreState {
podBoxList?: PodMakeOrderData[]
podBoxIndex?: number | null
socketConnect?: string
}
const useOrderStore = defineStore('order', {
state: () => {
return {
podBoxList: [],
podBoxIndex: null,
socketConnect: '',
} as OrderStoreState
},
actions: {
async setPodBoxList(content: {
boxList: PodMakeOrderData[] | OrderData | null
factoryNo: number | string
warehouseId: number | string
box?: number
data?: OrderData
}) {
const { factoryNo, warehouseId, boxList, box, data } = content
if (Array.isArray(boxList)) {
this.podBoxList = boxList
} else {
const index = this.podBoxList?.findIndex((item) => item.box === box)
if (index === -1) {
try {
const res = await getPodBoxListApi(factoryNo, warehouseId)
const boxList = res.data.map((item) => {
if (res.data) {
const productList = item?.data?.productList || []
const pickingNumber = productList.reduce(
(prev: number, item1: ProductList) => {
if (item1.count) {
return prev + item1.count
}
return prev
},
0,
)
if (item.data) {
item.data.pickingNumber = pickingNumber
}
}
return item
})
this.podBoxList = boxList
this.podBoxIndex = box
} catch (error) {
console.error(error)
}
} else if (box !== 0 && box !== undefined) {
const arr = this.podBoxList
if (arr) {
arr[box - 1] = {
box,
data: data || boxList || null,
}
}
this.podBoxList = arr
this.podBoxIndex = box
}
}
},
// 清空所有箱子
clearPodBoxList() {
this.podBoxList = []
},
// 设置当前箱子
setPodBox(box: number) {
this.podBoxIndex = box
},
// 清空当前箱子
clearPodBox() {
this.podBoxIndex = null
},
setSocketConnect(connect: string) {
this.socketConnect = connect
},
},
})
export default useOrderStore
......@@ -66,7 +66,6 @@ const useOrderStore = defineStore('order', {
data: data || boxList || null,
}
}
console.log('222arr1111', arr)
this.podBoxList = arr
this.podBoxIndex = box
}
......
export interface Tab {
status?: string
statusName?: string
quantity?: number
}
export interface IconfirmSubmit {
ids: string
warehouseId: number | null
warehouseName: string
}
export interface ExportParams extends SearchForm {
idList?: number[]
exportAll: boolean
}
export interface SearchForm {
timeType?: number | null
shopNumber?: string
shipmentType?: string
userMark?: string
processNumber?: string
trackingNumber?: string
baseSku?: string
factoryOrderNumber?: string
sku?: string
factorySubOrderNumber?: string
status?: string
customizedQuantity?: string
multi?: boolean | null
startTime?: string | null
endTime?: string | null
shipmentArea?: number | undefined
platform?: string
productionClient?: string
warehouseId?: string | number
thirdSkuCode?: string
supplierProductNo?: string
batchArrangeNumber?: string
craftCode?: string
thirdStockSku?: string
exceptionHandling?: number | undefined
interceptStatus?: number | string
}
export interface PodCnOrderListData {
id: number
thirdOrderNumber?: string
factoryOrderNumber?: string
shopNumber?: string
factoryOnlineId?: number | null
factoryNo?: number | null
factoryCode?: string | null
status?: string
weight?: number | null
totalProductAmount?: number | null
productAmount?: number
carriageAmount?: number | null
totalAmount?: number | null
productNum?: number | null
trackStatus?: string | null
receiverName?: string
receiverPhone?: string
receiverCountry?: string
receiverProvince?: string
receiverCity?: string
receiverDistrict?: string
receiverAddress1?: string
receiverAddress2?: string
receiverPostCode?: string
paymentType?: string
paymentTime?: string
startStockingTime?: string
finishTime?: string
shipmentType?: number
expressSheet?: string
trackingNumber?: string
processNumber?: string
createTime?: string
updateTime?: string
remark?: string | null
userMark?: string
serviceAmount?: number | null
prepaidAmount?: number | null
actualAmount?: number | null
version?: number
productList?: ProductList[]
orderNumber?: string
logisticsWayId?: number | null
logisticsWayName?: string
url?: string | null
tiffUrl?: string | null
}
export interface ProductList {
id: number
podJomallOrderCnId: number
thirdSubOrderNumber?: string
thirdStockSku?: string
factorySubOrderNumber?: string
factoryCode?: string
productName?: string
baseSku?: string
variantSku?: string
productPrice?: number
templatePrice?: number
variantImage?: string
craftPrice?: number
craftCode?: string
previewImgs?: []
platform?: string
imageAry?: string
designImages?: string
categoryId?: number
categoryName?: string
num?: number
passNum?: number
notPassNum?: number
payAmount?: number
status?: number
weight?: number | null
diyId?: string
endProductId?: string
customizedQuantity?: number
tagIds?: string
isProduction?: boolean
createTime?: string
updateTime?: string
remark?: string | null
version?: number
subOrderNumber?: string
craftName?: string | null
lanshouAddress?: string | null
shopNumber?: string | null
factoryOrderNumber?: string | null
replenishmentNum?: number | null
isReplenishment?: boolean
thirdSkuCode?: string | null
supplierProductNo?: string | null
userMark?: string | null
replenishmentSumNum?: number | null
interceptStatus?: number | null
batchArrangeNumber?: string | null
}
export interface cardImages {
title: string
url: string
sort: number
id?: number
}
export interface LogListData {
id: number
bizId: number
userId: number
employeeName: string
description: string
deleteContent: string
createTime: string
}
export interface ProductionClient {
code?: string
remark?: string
}
export interface PodOrderRes extends ProductList {
expectDeliveryTime?: string | null
thirdOrderNumber?: string | null
startStockingTime?: string | null
factoryOrderNumber?: string | null
userMark?: string | null
craftName?: string | null
craftId?: string | null
shopNumber?: string | null
color?: string | null
size?: string | null
note?: Array<{ prop: string | number; value: string | number }>
imgList: cardImages[]
}
export interface WarehouseListData {
code?: string
defaulted?: number
factoryCode?: string
factoryId?: number
id: number
name?: string
remarks?: string
sort?: number
}
export interface LogisticsData {
logisticsWayName: string // 物流名称
warehouseName: string // 发货仓库
status: boolean
logisticsWayCode: string // 物流编码
partition: string // 所在分区
logisticsWayId?: number | null
}
export interface AddressInfo {
id?: string
receiverName: string
receiverPhone: string
receiverCountry: string
receiverProvince: string
receiverCity: string
receiverDistrict: string
receiverAddress1: string
receiverAddress2: string
receiverPostCode: string
}
export interface LogisticsFormData {
processNumber: string
trackingNumber: string
expressSheetUrl: string
expressSheet: File | null
}
export interface CraftListData {
craftName: string
craftCode: string
}
......@@ -45,6 +45,7 @@ export interface ProductList {
power?: boolean
variantImage?: string
podJomallUsNo?: string
podJomallCnNo?: string
previewImgs?: { sort: string | number; title: string; url: string }[]
}
......
import { getWsUrl } from '../api/axios'
import useOrderStore from '../store/cnOrder'
interface NotificationOptions {
body: string
icon: string
data: string
requireInteraction: boolean
}
export interface WebSocketMessage {
code?: string
content?: string
type?: string
data?: unknown
[key: string]: string | unknown | undefined
}
interface InitOptions {
account: string
factoryNo: string
}
type MessageCallback = (
data: WebSocketMessage,
sendSystemMessage: (msg: string) => void,
) => void
type OpenCallback = () => void
function sendSystemMessage(msg: string): void {
if (window.Notification && Notification.permission === 'granted') {
const notificationOptions: NotificationOptions = {
body: msg,
icon: './favicon.ico',
data: 'I like peas.',
requireInteraction: true,
}
const n = new Notification('消息通知', notificationOptions)
n.onclick = (event: Event) => {
event.preventDefault()
window.open('/home', '_blank')
}
setTimeout(() => {
n.close()
}, 10000)
}
}
const showReconnectingMsg = (): void => {
ElMessageBox.alert('消息服务已断开,正在重新连接,请稍候', {
showClose: true,
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
}
class Im {
private socket: WebSocket | null = null
private _wsUrl: string = ''
// private userId: string = ''
private _onMessageCallback?: MessageCallback
private _onOpenCallback?: OpenCallback
private _heartbeatTimer: number | null = null
private _heartbeatTimeoutTimer: number | null = null
private _reconnectingTimer: number | null = null
private num: number = 0
constructor() {
this._onWsOpen = this._onWsOpen.bind(this)
this._onWsMessage = this._onWsMessage.bind(this)
this._onWsClose = this._onWsClose.bind(this)
this._onWsError = this._onWsError.bind(this)
}
private _onWsOpen(): void {
console.log('服务器连接成功')
localStorage.setItem('socket_connect', 'online')
this._onOpenCallback?.()
this._startHeartbeat()
}
private _onWsMessage(event: MessageEvent): void {
let data: WebSocketMessage = {}
if (typeof event.data === 'string') {
try {
data = JSON.parse(event.data)
} catch (error) {
data = {}
}
}
this._onHeartbeatMessage()
this._onMessageCallback?.(data, sendSystemMessage)
}
private _onWsClose(): void {
console.log('服务器关闭')
this._destroyWebSocket(true)
}
private _onWsError(): void {
console.log('连接出错')
this._destroyWebSocket(true)
}
private _sendHeartbeat(): void {
if (!this.socket) return
this.send({ code: 'HEALTH' })
if (this._heartbeatTimeoutTimer) {
window.clearTimeout(this._heartbeatTimeoutTimer)
}
this._heartbeatTimeoutTimer = window.setTimeout(() => {
this._destroyWebSocket(true)
}, 5 * 1000)
}
private _onHeartbeatMessage(): void {
console.log('心跳')
useOrderStore().setSocketConnect('online')
if (this._heartbeatTimeoutTimer) {
window.clearTimeout(this._heartbeatTimeoutTimer)
}
}
private _startHeartbeat(): void {
this._stopHeartbeat()
this._sendHeartbeat()
this._heartbeatTimer = window.setInterval(
() => this._sendHeartbeat(),
10 * 1000,
)
}
private _stopHeartbeat(): void {
if (this._heartbeatTimer) {
window.clearInterval(this._heartbeatTimer)
}
if (this._heartbeatTimeoutTimer) {
window.clearTimeout(this._heartbeatTimeoutTimer)
}
}
private _scheduleReconnect(): void {
if (!this.num) this.num = 0
this.num++
if (this.num > 5) {
ElMessageBox.alert('尝试重连消息服务失败,请刷新重试')
return
}
showReconnectingMsg()
this._reconnectingTimer = window.setTimeout(() => {
this._createWebSocket()
}, 2000)
}
private _destroyWebSocket(reconnect?: boolean): void {
if (!this.socket) return
this._stopHeartbeat()
if (this._reconnectingTimer) {
window.clearTimeout(this._reconnectingTimer)
}
this.socket.removeEventListener('open', this._onWsOpen)
this.socket.removeEventListener('message', this._onWsMessage)
this.socket.removeEventListener('close', this._onWsClose)
this.socket.removeEventListener('error', this._onWsError)
this.socket.close(1000)
this.socket = null
localStorage.removeItem('socket_connect')
useOrderStore().setSocketConnect('offline')
if (reconnect) this._scheduleReconnect()
}
private _createWebSocket(): void {
if (!this._wsUrl) return
const socket = new WebSocket(this._wsUrl)
socket.addEventListener('open', this._onWsOpen)
socket.addEventListener('message', this._onWsMessage)
socket.addEventListener('close', this._onWsClose)
socket.addEventListener('error', this._onWsError)
this.socket = socket
}
init(
options: InitOptions,
msgfunc?: MessageCallback,
openfunc?: OpenCallback,
): Promise<void> {
return new Promise((resolve, reject) => {
const { account, factoryNo } = options
const socket_connect = localStorage.getItem('socket_connect')
if (socket_connect === 'online') {
resolve()
return
}
if (!window.WebSocket) {
reject(new Error('WebSocket is not supported'))
return
}
this._onMessageCallback = msgfunc
this._onOpenCallback = () => {
openfunc?.()
resolve()
}
this._destroyWebSocket()
this._wsUrl = `${getWsUrl()}/ws/websocket/${factoryNo}/${account}`
this._createWebSocket()
})
}
send(options: WebSocketMessage): void {
this.socket?.send(JSON.stringify(options))
}
close(): void {
this._destroyWebSocket()
}
}
export default new Im()
<template>
<el-dialog
v-model="dialogVisible"
:title="fastKey === 'detail' ? '查看详情' : '快捷生产'"
top="140px"
:fullscreen="true"
:close-on-click-modal="false"
@opened="onOpened"
@close="emit('close')"
>
<div class="detail-div">
<div class="detail-content">
<div class="left">
<div class="left-images">
<el-carousel
v-if="detail?.imgList.length > 0"
style="height: 100%"
:autoplay="false"
indicator-position="none"
>
<el-carousel-item
v-for="(item, index) in detail?.imgList"
:key="index"
style="height: 100%"
>
<div class="left-image">
<b v-show="item?.title && item?.url">
{{ item?.title }}
<span
v-if="item?.id"
style="
text-decoration: underline;
cursor: pointer;
color: blue;
"
>
(DID:{{ item?.id }}
</span>
</b>
<img :src="item.url" alt="" />
</div>
</el-carousel-item>
</el-carousel>
</div>
</div>
<div class="right">
<div v-if="fastKey === 'fastProduction'" class="input">
<el-input
ref="trackingNumberRef"
v-model="TrackingNumber"
:placeholder="placeholderText"
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">
<div class="div-content">
<div :title="String(detail?.userMark)" class="div-item">
<span style="font-size: 18px">客户</span>
<p style="color: red; font-size: 30px">
{{ detail?.userMark }}
</p>
</div>
<div
:title="String(detail?.factoryOrderNumber)"
class="div-item"
style="margin-top: 14px"
>
<span style="font-size: 18px">订单号</span>
<p style="color: red; font-size: 22px">
{{ detail?.factoryOrderNumber }}
</p>
</div>
</div>
</div>
<div class="div-text">
<b>生产单信息</b>
<div class="div-content">
<div :title="detail?.factorySubOrderNumber" class="div-item">
<span>生产单号</span>
<p>
{{ detail?.factorySubOrderNumber }}
</p>
</div>
<div :title="detail?.thirdSubOrderNumber || ''" class="div-item">
<span>第三方生产单号</span>
<p>
{{ detail?.thirdSubOrderNumber }}
</p>
</div>
<div :title="String(detail?.craftName)" class="div-item">
<span>生产工艺</span>
<p>
{{ detail?.craftName }}
</p>
</div>
<div :title="detail?.baseSku" class="div-item">
<span>基版</span>
<p>{{ detail?.baseSku }}</p>
</div>
<div :title="detail?.variantSku" class="div-item">
<span>变体SKU</span>
<p>{{ detail?.variantSku }}</p>
</div>
<div :title="String(detail?.num)" class="div-item">
<span>数量</span>
<p>{{ detail?.num }}</p>
</div>
<div :title="String(detail?.size)" class="div-item">
<span>尺寸</span>
<p>{{ detail?.size }}</p>
</div>
<div :title="detail?.shopNumber ?? ''" class="div-item">
<span>店铺单号</span>
<p>{{ detail?.shopNumber ?? '' }}</p>
</div>
<div :title="detail?.createTime" class="div-item">
<span>创建时间</span>
<p>{{ detail?.createTime }}</p>
</div>
</div>
</div>
<div class="btn">
<div
:style="{
visibility: fastKey === 'fastProduction' ? 'visible' : 'hidden',
}"
class="btn-sure"
>
<el-button
style="width: 100%; height: 100%; font-size: 18px"
size="large"
type="success"
@click="changeStatus"
>
生产完成
</el-button>
<div class="check">
<el-checkbox v-model="isAutoSure"> 自动完成上一单 </el-checkbox>
</div>
</div>
<div class="btn-down">
<div class="check">
<el-checkbox v-model="isDownloadImage" size="large">
扫码下载素材
</el-checkbox>
</div>
<el-button
style="width: 100%; height: 100%; font-size: 18px"
type="primary"
size="large"
@click="handleDownload"
>
下载素材
</el-button>
</div>
</div>
<div
class="div-text"
style="
flex: 1;
flex-shrink: 0;
display: flex;
flex-direction: column;
"
>
<div v-if="detail?.note" 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>
</el-dialog>
</template>
<script setup lang="tsx">
import {
productionQueryApi,
getSubOrderBySubOrderNumber,
downloadMaterialApi,
} from '@/api/podCnOrder'
import { cardImages, PodOrderRes } from '@/types/api/podCnOrder'
import { showConfirm } from '@/utils/ui'
import { filePath } from '@/api/axios'
import { ref, watch, defineProps, defineEmits } from 'vue'
interface HistoryDataItem {
orderNumber: string
finished: boolean
}
const trackingNumberRef = ref()
const historyData = ref<HistoryDataItem[]>([])
const placeholderText = ref('')
const sendNum = ref(0)
const isDownloadImage = ref(false)
const isAutoSure = ref(false)
const detail = ref<PodOrderRes>({
id: -1,
podJomallOrderCnId: -1,
imgList: [] as cardImages[],
})
const dialogVisible = ref(false)
// 通过import动态导入音频文件
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 TrackingNumber = ref('')
const props = defineProps({
type: {
default: 0,
type: Number,
},
detailVisible: {
default: false,
type: Boolean,
},
detailData: {
default: null,
type: Object,
},
fastKey: {
default: '',
type: String,
},
})
const emit = defineEmits(['update:detailVisible', 'close', 'onSuccess'])
watch(
() => props.detailVisible,
(newVal: boolean) => {
dialogVisible.value = newVal
detail.value = { id: -1, podJomallOrderCnId: -1, imgList: [] }
if (newVal) {
const history = localStorage.getItem('historyCnData')
historyData.value = history ? JSON.parse(history) : []
const len = historyData.value
if (len.length > 0 && props.fastKey === 'fastProduction') {
confirmQuery(len, 0)
}
placeholderText.value =
'扫描枪输入生产单号,录入下一单本单自动生产完成,最后一单扫两次完成生产'
trackingNumberRef.value && trackingNumberRef.value.focus()
TrackingNumber.value = ''
isAutoSure.value = false
sendNum.value = 0
}
},
)
watch(
() => props.detailData,
(newVal) => {
detail.value = {
id: -1,
podJomallOrderCnId: -1,
imgList: [],
}
if (newVal && Object.keys(newVal).length > 0) {
const d = JSON.parse(JSON.stringify(newVal))
if (d.note) {
d.note = JSON.parse(d.note)
} else {
d.note = []
}
if (d.imageAry) {
d.imgList = d.imageAry
} else {
d.imgList = []
}
detail.value = d
}
},
{ deep: true },
)
const confirmQuery = (len: HistoryDataItem[], i: number) => {
const el = len[i]
showConfirm(`生产单号 ${el.orderNumber} 未生产完成,取消则不提醒?`, {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(async () => {
TrackingNumber.value = el.orderNumber
await trackCodeInput()
await setData(el.orderNumber)
ElMessage.success('生产完成')
if (len[i + 1]) {
confirmQuery(len, i + 1)
}
})
.catch(() => {
const index = historyData.value.findIndex(
(item: HistoryDataItem) => item.orderNumber === el.orderNumber,
)
if (index >= 0) {
historyData.value.splice(index, 1)
localStorage.setItem('historyCnData', JSON.stringify(historyData.value))
}
if (len[i + 1]) {
confirmQuery(len, i + 1)
}
trackingNumberRef.value && trackingNumberRef.value.focus()
})
}
const changeStatus = async () => {
if (!detail.value || Object.keys(detail.value).length <= 1) {
return ElMessage.warning('请扫码生产单号')
}
showConfirm('确定生产完成?', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
setData(detail.value.factorySubOrderNumber || '')
})
}
const setData = async (orderNumber: string) => {
if (!detail.value || detail.value?.id === -1) return
try {
const id = detail.value.id
const podJomallOrderCnId = detail.value.podJomallOrderCnId
await productionQueryApi(id, podJomallOrderCnId)
if (orderNumber) {
const index = historyData.value.findIndex(
(el: HistoryDataItem) => el.orderNumber === orderNumber,
)
if (index >= 0) {
// 扫单完成删除
historyData.value.splice(index, 1)
localStorage.setItem('historCnData', JSON.stringify(historyData.value))
}
}
emit('onSuccess')
playAudio('weight_success')
detail.value = {
id: -1,
podJomallOrderCnId: -1,
imgList: [] as cardImages[],
}
TrackingNumber.value = ''
isDownloadImage.value = false
trackingNumberRef.value && trackingNumberRef.value.focus()
} catch (e) {
console.error(e)
detail.value = {
id: -1,
podJomallOrderCnId: -1,
imgList: [] as cardImages[],
}
trackingNumberRef.value && trackingNumberRef.value.focus()
playAudio('weight_search_error')
}
}
const handleDownload = () => {
if (
!detail.value ||
Object.keys(detail.value).length <= 1 ||
detail.value.id == -1
) {
return ElMessage.warning('请扫码生产单号')
}
download()
}
const download = async () => {
if (detail.value && detail.value?.id != -1) {
try {
const id = detail.value.id
if (id !== undefined) {
try {
const res = await downloadMaterialApi([id])
if (res.code !== 200) return
window.open(filePath + res.message)
} catch (e) {
console.error(e)
}
}
} catch (e) {
// showError(e)
console.error(e)
}
}
}
type AudioKey = keyof typeof audios // 创建一个类型,确保 key 只能是 audios 对象的键之一
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')
trackingNumberRef.value && trackingNumberRef.value.focus()
return
}
const item = historyData.value.find(
(el: HistoryDataItem) => el.orderNumber === TrackingNumber.value,
)
if (!item) {
// 记录扫单
historyData.value.push({
orderNumber: TrackingNumber.value,
finished: false,
})
localStorage.setItem('historyCnData', JSON.stringify(historyData.value))
}
const orderNumber = TrackingNumber.value
if (isAutoSure.value) {
await setData(
historyData.value[historyData.value.length - 1].orderNumber || '',
)
}
try {
const res = await getSubOrderBySubOrderNumber(orderNumber)
if (!res.data) {
return ElMessage.error('生产单不存在')
}
const d = JSON.parse(JSON.stringify(res.data))
if (d.note) {
d.note = JSON.parse(d.note)
} else {
d.note = []
}
if (d.imageAry) {
d.imgList = JSON.parse(d.imageAry)
} else {
d.imgList = []
}
detail.value = d
if (isDownloadImage.value) {
download()
}
playAudio('weight_search_success')
trackingNumberRef.value && trackingNumberRef.value.focus()
TrackingNumber.value = ''
} catch (e) {
console.error(e)
trackingNumberRef.value && trackingNumberRef.value.focus()
TrackingNumber.value = ''
}
}
const onOpened = () => {
trackingNumberRef.value && trackingNumberRef.value.focus()
}
</script>
<style lang="scss" scoped>
.sure-btn {
position: absolute;
right: 62px;
top: 14px;
}
.detail-div {
display: flex;
height: 100%;
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%;
}
.right {
width: 730px;
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;
.div-item {
width: 50%;
margin-bottom: 10px;
display: flex;
align-items: center;
p {
font-weight: 400;
color: black;
}
span {
display: inline-block;
text-align: right;
width: 120px;
}
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%;
object-fit: contain;
}
b {
color: black;
font-size: 18px;
margin-bottom: 15px;
}
}
.left-images {
display: flex;
width: 95%;
height: 100%;
flex-direction: column;
b {
color: black;
text-align: center;
margin-bottom: 15px;
}
}
}
}
.left-images {
:deep(.el-carousel__container) {
height: 100%;
}
:deep(.el-dialog__title) {
font-weight: bold;
font-size: 37px;
color: black;
position: relative;
left: 47%;
top: 13px;
}
}
.btn {
position: relative;
:deep(.el-button) {
span {
position: relative;
left: -30px;
}
}
.check {
:deep(.el-checkbox__inner) {
background-color: transparent !important;
border-color: white !important;
width: 12px;
height: 12px;
}
:deep(.el-checkbox__inner::after) {
left: 3px;
}
: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>
<template>
<ElDialog
v-model="visible"
title="播种墙配货"
fullscreen
:close-on-click-modal="false"
:close-on-press-escape="false"
:before-close="handleClose"
style="top: 60px"
modal-class="pod-make-order-dialog"
@opened="handleOpened"
@close="onClose"
>
<template #header>
<div class="title">
<span>播种墙配货</span>
<span v-if="socketConnect === 'online'" class="online">[在线]</span>
<span v-else class="offline">[离线]</span>
</div>
</template>
<div class="pod-make-order-content">
<div class="left-content">
<div class="head-form">
<div class="form-item">
<ElSelect
v-model="sheetPrinter"
placeholder="请选择打印机"
style="width: 200px"
@change="handlePrinterChange"
>
<ElOption
v-for="item in printDeviceList"
:key="item"
:label="item"
:value="item"
/>
</ElSelect>
</div>
<div class="form-item">
<ElSelect
v-model="warehouseId"
placeholder="请选择仓库"
style="width: 200px"
@change="handleWarehouseChange"
>
<ElOption
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</ElSelect>
</div>
<div class="form-item" style="flex: 1">
<ElInput
ref="productionOrderRef"
v-model="productionOrder"
placeholder="请输入生产单号"
clearable
style="width: 100%"
@keyup.enter="handleSearch"
/>
</div>
<div class="form-item">
<ElButton type="primary" @click="handleSearch">查询</ElButton>
</div>
<div class="form-item">
<ElButton type="danger" @click="clearAllBox">清空所有箱子</ElButton>
</div>
</div>
<div class="basic-info">
<div class="basic-info-item">
<span>物流跟踪号:</span>
<span>{{ podOrderDetailsData?.trackingNumber }}</span>
</div>
<div class="basic-info-item">
<span>店铺单号:</span>
<span>{{ podOrderDetailsData?.shopNumber }}</span>
</div>
<div class="basic-info-item">
<span>商品总数量:</span>
<span>{{ podOrderDetailsData?.purchaseNumber }}</span>
</div>
<div class="basic-info-item">
<span>拣货数量:</span>
<span>{{ podOrderDetailsData?.pickingNumber }}</span>
</div>
<!-- <div class="basic-info-item">
<span>物流公司:</span>
<span></span>
</div>
<div class="basic-info-item">
<span>物流方式:</span>
<span></span>
</div> -->
<div class="basic-info-item">
<span>发货备注:</span>
<span>{{ podOrderDetailsData?.remark }}</span>
</div>
<div class="basic-info-item">
<span>订单号:</span>
<span>{{ podOrderDetailsData?.factoryOrderNumber }}</span>
</div>
</div>
<div class="table-content">
<TableView
ref="tableRef"
:paginated-data="podOrderDetailsData?.productList || []"
:columns="podOrderDetailsColumns"
highlight-current-row
@row-click="handleRowClick"
>
<template #image="{ row }">
<div
style="display: flex; flex-wrap: nowrap"
v-if="row.previewImgs?.length"
>
<div
v-for="img in row.previewImgs"
:key="img"
@click.stop="handleCurrentChange(img.url)"
style="cursor: pointer; margin-right: 5px; flex: 1"
>
<img v-if="img.url" :src="img.url" alt="" />
</div>
</div>
</template>
<template #verifyResult="{ row }">
<el-icon
v-if="row.power"
style="color: #00cc00; font-size: 24px; font-weight: 900"
><Check
/></el-icon>
</template>
</TableView>
</div>
</div>
<div class="middle-content">
<div class="box-top">
<div class="box-top-item">
<span class="box-top-item-box-index">
{{ boxIndex }}
</span>
<span class="box-top-item-box-index-text">号箱</span>
<span style="font-size: 30px">放入第</span>
<div class="box-top-item-box-index-number">
{{ podOrderDetailsData?.pickingNumber }}
</div>
<span style="font-size: 30px">件商品</span>
</div>
<div class="box-top-item-status">
<span
v-if="
podOrderDetailsData?.pickingNumber &&
podOrderDetailsData?.purchaseNumber &&
podOrderDetailsData?.pickingNumber ===
podOrderDetailsData?.purchaseNumber
"
>
<span v-if="podOrderDetailsData?.printResult">
面单{{ renderPrintResult(podOrderDetailsData?.printResult) }}
</span>
<span v-else>面单打印中。。。</span>
</span>
<span v-else>验货中。。。</span>
</div>
<div class="box-top-item-btn">
<ElButton
type="primary"
@click="podOrderDetailsData && print(podOrderDetailsData, true)"
>手动打印</ElButton
>
<ElButton type="success" @click="handlePrintFinish"
>打单完成</ElButton
>
<ElButton type="danger" @click="handleClearBox">清空箱子</ElButton>
</div>
<div
v-if="
podOrderDetailsData?.productList?.length &&
podOrderDetailsData?.productList?.length > 1
"
class="multiple-title"
>
<span class="multiple-title-text"></span>
</div>
</div>
<div class="order-image">
<img :src="coverImage" alt="" />
</div>
</div>
<div class="right-content">
<div class="box-list">
<div
v-for="(item, index) in podBoxList"
:key="item.box"
class="box-list-item"
:class="{
active: item.box && boxIndex == item.box,
isNull: !item.data,
badge: handleProduct(item.data || {}),
}"
@click="handleBoxClick(item)"
>
<span style="font-weight: bold" :title="index + 1 + '号箱'">
{{ index + 1 }}
</span>
<span v-if="item.data" class="number">
{{ item.data.pickingNumber }}/{{ item.data.purchaseNumber }}
</span>
</div>
</div>
</div>
</div>
</ElDialog>
</template>
<script setup lang="ts">
import { computed, nextTick, ref, watch } from 'vue'
import useLodop from '@/utils/hooks/useLodop'
import TableView from '@/components/TableView.vue'
import type { WebSocketMessage } from '@/utils/websocket'
import {
OrderData,
PodMakeOrderData,
ProductList,
} from '@/types/api/podMakeOrder'
import useOrderStore from '@/store/cnOrder'
import {
getPackingCnDataApi,
clearBoxApi,
clearAllBoxApi,
getPodBoxListApi,
submitInspectionApi,
} from '@/api/podCnOrder'
import useUserStore from '@/store/user'
import { Check } from '@element-plus/icons-vue'
import socket from '@/utils/cnWebsocket'
import { WarehouseListData } from '@/types/api/podUsOrder'
const { getCLodop } = useLodop()
const props = defineProps<{
modelValue: boolean
printOrder: (data: OrderData, callback: (status: boolean) => void) => void
warehouseList: WarehouseListData[]
}>()
const emit = defineEmits(['update:modelValue', 'set-printer', 'refresh'])
const visible = computed({
get() {
return props.modelValue
},
set(value) {
emit('update:modelValue', value)
},
})
const printDeviceList = ref<string[]>([])
const sheetPrinter = ref<string>('')
const productionOrder = ref<string>('')
const podOrderDetailsData = ref<OrderData>()
const podOrderDetailsColumns = computed(() => [
{
label: '图片',
prop: 'image',
width: 250,
slot: 'image',
align: 'center',
fixed: 'left',
},
{
label: '生产单号',
prop: 'podJomallCnNo',
width: 150,
align: 'center',
},
// {
// label: 'base SKU',
// prop: 'baseSku',
// width: 140,
// align: 'center',
// },
{
label: 'variant SKU',
prop: 'variantSku',
width: 140,
align: 'center',
},
{
label: '商品名称',
prop: 'productName',
},
{
label: '购买数量',
prop: 'purchaseNumber',
width: 90,
align: 'center',
},
{
label: '拣货数量',
prop: 'count',
width: 90,
align: 'center',
},
{
label: '验证结果',
slot: 'verifyResult',
width: 90,
align: 'center',
},
])
const boxChange = ref<boolean>(false)
const boxIndex = ref<number | null>(null)
const orderStore = useOrderStore()
const isLock = ref<boolean>(false)
const productionOrderRef = ref()
const socketConnect = computed(() => orderStore.socketConnect)
const podBoxList = computed(() => orderStore.podBoxList)
const coverImage = ref<string>('')
let currentCode = ''
const tableRef = ref()
watch(visible, async (value: boolean) => {
if (value) {
podOrderDetailsData.value = {}
currentCode = ''
// warehouseId.value = props.warehouseList[0].id
// _warehouseId.value = props.warehouseList[0].id
const locaclWarehouseId = sessionStorage.getItem('locaclCnWarehouseId')
// 设置仓库ID,优先使用本地存储的值,否则使用列表中的第一个仓库
warehouseId.value = locaclWarehouseId
? JSON.parse(locaclWarehouseId)
: props.warehouseList[0].id
_warehouseId.value = locaclWarehouseId
? JSON.parse(locaclWarehouseId)
: props.warehouseList[0].id
if (userStore.user?.factory.id) {
try {
await socket.init(
{
account: userStore.user?.account.toString(),
factoryNo: userStore.user?.factory.id.toString(),
},
messageChange,
)
socket.send({
code: 'STARTORDER',
factoryNo: userStore.user?.factory.id,
warehouseId: warehouseId.value,
})
} catch (error) {
console.error(error)
}
}
initOrderDetailBox()
initPrintDevice()
const locaclPrinter = localStorage.getItem('sheetPrinter')
if (locaclPrinter) sheetPrinter.value = JSON.parse(locaclPrinter)
} else {
if (userStore.user?.factory.id) {
socket.send({
code: 'ENDORDER',
factoryNo: userStore.user?.factory.id,
warehouseId: warehouseId.value,
})
socket.close()
}
}
})
watch(boxIndex, (value: number | null) => {
if (value) {
const bool = !boxChange.value
boxChange.value = false
console.log('boxChange', bool, value)
renderItemBox(bool)
}
})
watch(
podBoxList,
(value) => {
if (value) {
const item = value.find((item) => item.box === podBoxIndex.value)
console.log('podBoxList', value, podBoxIndex.value, item)
if (item?.data) {
renderItemBox(true)
} else {
if (boxIndex.value === podBoxIndex.value) {
podOrderDetailsData.value = {}
boxIndex.value = null
}
}
}
},
{ deep: true },
)
watch(
() => podOrderDetailsData.value,
(val) => {
if (val && val.productList?.length)
val.productList.forEach((el) => {
if (!el.previewImgs) el.previewImgs = JSON.parse(el.imageAry)
})
},
{ deep: true },
)
const podBoxIndex = computed(() => orderStore.podBoxIndex)
let renderLock = false
const renderItemBox = (bool: boolean) => {
if (
!podBoxList.value ||
podBoxList.value.length === 0 ||
!boxIndex.value ||
(bool && boxIndex.value !== podBoxIndex.value)
)
return
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) => {
if (!el.previewImgs) el.previewImgs = JSON.parse(el.imageAry)
})
if (!data) {
renderLock = false
currentCode = ''
podOrderDetailsData.value = {}
return
}
const { productList = [] } = data
const pickingNumber = productList.reduce((prev, product) => {
return prev + (product.count || 0)
}, 0)
data.pickingNumber = pickingNumber
// coverImage.value = productList[0].previewImgs?.[0]?.url || ''
for (const product of productList) {
if (product.count === product.purchaseNumber) {
product.power = true
}
}
if (currentCode) {
const parts = currentCode.split('_')
currentCode =
parts.length > 3 && parts[3].startsWith('CNPSC')
? parts[3]
: parts.length > 1
? parts[1]
: parts[0]
for (const product of productList) {
if (product.podJomallCnNo === currentCode) {
coverImage.value = product.previewImgs?.[0]?.url || ''
nextTick(() => {
tableRef.value?.setCurrentRow(product)
})
break
}
}
currentCode = ''
}
podOrderDetailsData.value = data
if (productList.every((item) => item.power)) {
print(data, false, () => {
renderLock = false
})
} else {
renderLock = false
}
}
const messageChange = (data: WebSocketMessage) => {
if (!data) return
const { code, ...more } = data
if (code === 'FACTORY_POD_CN_PRINT_ORDER') {
try {
if (typeof more.txt === 'string') {
console.log(
'%conWebSocketMessage',
'font-size: 20px; color: red;',
JSON.parse(more.txt),
)
}
} catch (e) {
console.error(e)
}
setPodBoxList(more)
}
}
const setPodBoxList = (data: WebSocketMessage) => {
const obj = data.txt
if (obj && typeof obj === 'string') {
const parsedData = JSON.parse(obj)
orderStore.setPodBoxList(parsedData)
}
}
const initPrintDevice = () => {
const lodop = getCLodop(null, null)
if (!lodop) return
const arr = []
// 获取打印机数量
const length = lodop.GET_PRINTER_COUNT()
for (let i = 0; i < length; i++) {
// 根据设备序号获取设备名
const name = lodop.GET_PRINTER_NAME(i)
arr.push(name)
}
console.log('arr', arr, lodop.GET_PRINTER_NAME(1))
// 获取默认打印机
sheetPrinter.value = lodop.GET_PRINTER_NAME(0)
printDeviceList.value = arr
}
const handleProduct = (val: OrderData) => {
if (val && val.productList && val.productList.length > 0) {
return val.productList?.some((item) => {
return item.productMark == 'normal'
})
} else {
return false
}
}
const handleSearch = () => {
const code = productionOrder.value
if (!code) {
ElMessage.warning('请输入生产单号')
productionOrderRef.value.focus()
return
}
if (isLock.value) {
ElMessage.warning('请稍后再试')
productionOrderRef.value.focus()
return
}
productionOrder.value = ''
isLock.value = true
const everyPower = podOrderDetailsData.value?.productList?.every(
(item) => item.power,
)
if (everyPower) {
/**
* printSuccess 打印成功
* printFail 打印失败
* printIng 打印中
* notPrintSuccess 未能获取打印状态
*/
if (podOrderDetailsData.value?.printResult === 'printSuccess') {
submitInspection(() => {
getPackingData(code)
})
} else {
ElMessage.warning('未获取到打印结果')
isLock.value = false
}
} else {
getPackingData(code)
}
}
const userStore = useUserStore()
const getPackingData = async (code: string) => {
const loading = ElLoading.service({
fullscreen: true,
text: '加载中...',
background: 'rgba(0, 0, 0, 0.3)',
})
currentCode = code
try {
const factoryNo = userStore.user?.factory.id
if (!factoryNo) {
isLock.value = false
productionOrder.value = ''
return
}
const res = await getPackingCnDataApi(
code,
factoryNo,
boxIndex.value,
warehouseId.value,
)
if (res.code !== 200) {
ElMessage.warning(res.message)
isLock.value = false
productionOrder.value = ''
return
}
const { box } = res.data
if (box) {
boxIndex.value = box
}
} catch (error) {
console.log(error)
} finally {
isLock.value = false
productionOrder.value = ''
loading.close()
productionOrderRef.value.focus()
}
}
// 提交打单
const submitInspection = async (callback: () => void) => {
const factoryNo = userStore.user?.factory.id
if (!factoryNo) {
return
}
const data = podOrderDetailsData.value?.id
? [
{
id: podOrderDetailsData.value.id,
version: podOrderDetailsData.value?.version,
},
]
: []
try {
const res = await submitInspectionApi(
data,
boxIndex.value,
warehouseId.value,
)
if (res.code !== 200) return
ElMessage.warning(res.message)
isLock.value = false
coverImage.value = ''
podOrderDetailsData.value = {}
productionOrderRef.value.focus()
callback && callback()
} catch (error) {
isLock.value = false
productionOrderRef.value.focus()
console.error(error)
}
}
const isBillLading = ref<boolean>(false)
const initOrderDetailBox = async () => {
const factoryNo = userStore.user?.factory.id
if (!factoryNo) {
return
}
const loading = ElLoading.service({
fullscreen: true,
text: '加载中...',
background: 'rgba(0, 0, 0, 0.3)',
})
try {
const res = await getPodBoxListApi(factoryNo, warehouseId.value)
if (res.code !== 200) {
ElMessage.warning(res.message)
return
}
orderStore.setPodBoxList({
boxList: res.data,
factoryNo,
warehouseId: warehouseId.value,
})
const boxList = res.data.map((item) => {
if (item.data) {
if (!item.data.filePath) {
isBillLading.value = true
} else {
isBillLading.value = false
}
const productList = item?.data?.productList || []
const pickingNumber = productList.reduce((prev, product) => {
if (product.count === product.purchaseNumber) {
product.power = true
}
if (product.count) {
return prev + product.count
}
return prev
}, 0)
item.data.pickingNumber = pickingNumber
}
return item
})
podOrderDetailsData.value =
boxList.find((item) => item.data)?.data || undefined
boxIndex.value = boxList.find((item) => item.data)?.box || null
podOrderDetailsData.value?.productList?.forEach((el) => {
if (!el.previewImgs) el.previewImgs = JSON.parse(el.imageAry)
})
coverImage.value =
podOrderDetailsData.value?.productList?.[0]?.previewImgs?.[0].url || ''
if (
podOrderDetailsData.value &&
podOrderDetailsData.value.pickingNumber ===
podOrderDetailsData.value.purchaseNumber
) {
podOrderDetailsData.value.printResult = 'notPrintSuccess'
}
const pickFinished = boxList.filter((item) => {
return item.data?.productList?.every((product) => product.power)
})
const boxs = pickFinished.map((item) => item.box)
if (boxs.length > 0) {
nextTick(async () => {
try {
await ElMessageBox.alert(
`检测到${boxs.join(',')}号箱验货完成,请及时处理`,
'提示',
{
confirmButtonText: '确定',
},
)
productionOrderRef.value.focus()
} catch (error) {
productionOrderRef.value.focus()
console.error(error)
}
})
}
renderLock = false
productionOrder.value = ''
isLock.value = false
productionOrderRef.value.focus()
} catch (error) {
console.error(error)
} finally {
loading.close()
}
}
const renderPrintResult = (printResult: string) => {
switch (printResult) {
case 'printSuccess':
return '打印成功'
case 'printFail':
return '打印失败'
case 'printIng':
return '打印中'
case 'notPrintSuccess':
return '未能获取打印状态'
default:
return '未知'
}
}
const handleOpened = () => {
productionOrderRef.value.focus()
}
const handleClose = (done: () => void) => {
nextStep(() => {
done()
})
}
const onClose = () => {
// orderStore.clearPodBox()
emit('refresh')
}
// 下一步
const nextStep = async (callback: () => void) => {
const everyPicked = podOrderDetailsData.value?.productList?.every(
(item) => item.count === item.purchaseNumber,
)
if (
everyPicked &&
(podOrderDetailsData.value?.printResult === 'printSuccess' ||
podOrderDetailsData.value?.printResult === 'notPrintSuccess')
) {
try {
await ElMessageBox.alert(
'当前订单验货完成并打印面单成功,是否转至已完成',
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
},
)
submitInspection(() => {
callback && callback()
})
} catch (error) {
productionOrderRef.value.focus()
console.error(error)
}
} else {
callback && callback()
}
}
const handleBoxClick = (item: PodMakeOrderData) => {
const { box, data } = item
isBillLading.value = !data?.filePath
nextStep(() => {
if (!data) {
ElMessage.warning('暂无数据')
return
}
boxIndex.value = box || null
boxChange.value = true
productionOrderRef.value.focus()
})
}
const handleClearBox = async () => {
try {
await ElMessageBox.alert('确定清空当前箱子吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
})
} catch {
return
}
const factoryNo = userStore.user?.factory.id
if (!factoryNo) {
return
}
try {
const res = await clearBoxApi(
factoryNo,
boxIndex.value || null,
warehouseId.value,
)
if (res.code !== 200) {
ElMessage.warning(res.message)
return
}
ElMessage.success('清空成功')
orderStore.setPodBoxList({
boxList: null,
factoryNo,
box: boxIndex.value || undefined,
warehouseId: warehouseId.value,
})
boxIndex.value = null
podOrderDetailsData.value = {}
coverImage.value = ''
productionOrderRef.value.focus()
} catch (error) {
productionOrderRef.value.focus()
console.error(error)
}
}
const handlePrintFinish = async () => {
try {
await ElMessageBox.alert('确定打单完成吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
})
submitInspection(() => {
productionOrderRef.value.focus()
})
} catch {
productionOrderRef.value.focus()
return
}
}
const handlePrinterChange = (value: string) => {
emit('set-printer', value)
}
const print = (data: OrderData, forcePrint = false, callback?: () => void) => {
const _boxIndex = boxIndex.value
if (!forcePrint && data.printResult) {
callback && callback()
return
}
props.printOrder(data, (status: boolean) => {
callback && callback()
const item = podBoxList.value?.find((item) => item.box === _boxIndex)
if (item && item.data) {
if (status) {
item.data.printResult = 'printSuccess'
} else {
item.data.printResult = 'printFail'
}
}
const factoryNo = userStore.user?.factory.id
if (!factoryNo) return
orderStore.setPodBoxList({
boxList: item ? item.data : null,
factoryNo,
box: _boxIndex || undefined,
warehouseId: warehouseId.value,
})
})
}
const clearAllBox = async () => {
try {
await ElMessageBox.alert('确定清空所有箱子吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
})
} catch {
productionOrderRef.value.focus()
return
}
try {
const res = await clearAllBoxApi()
if (res.code !== 200) return
orderStore.setPodBoxList({
boxList: res.data,
factoryNo: userStore.user?.factory.id || '',
warehouseId: warehouseId.value,
})
productionOrderRef.value.focus()
podOrderDetailsData.value = {}
coverImage.value = ''
boxIndex.value = null
} catch (error) {
productionOrderRef.value.focus()
console.error(error)
}
}
const handleRowClick = (row: ProductList) => {
console.log(907, row)
coverImage.value = row.previewImgs?.[0]?.url || ''
productionOrderRef.value.focus()
}
const handleCurrentChange = (url: string) => {
if (url) {
coverImage.value = url || ''
}
}
const warehouseId = ref<string | number>('')
const _warehouseId = ref<string | number>('')
const handleWarehouseChange = (value: string | number) => {
if (!value) return
if (_warehouseId.value !== warehouseId.value) {
socket.send({
code: 'ENDORDER',
factoryNo: userStore.user?.factory.id,
warehouseId: _warehouseId.value,
})
}
warehouseId.value = value
socket.send({
code: 'STARTORDER',
factoryNo: userStore.user?.factory.id,
warehouseId: warehouseId.value,
})
_warehouseId.value = value
initOrderDetailBox()
}
</script>
<style scoped lang="scss">
.title {
display: flex;
align-items: center;
gap: 10px;
}
.online {
color: green;
font-size: 14px;
font-weight: 600;
}
.offline {
color: red;
font-size: 14px;
font-weight: 600;
}
.pod-make-order-content {
display: flex;
height: 100%;
overflow: hidden;
gap: 10px;
}
.left-content {
display: flex;
flex-direction: column;
gap: 10px;
width: calc(100% - 900px - 20px);
}
.head-form {
display: flex;
align-items: center;
gap: 10px;
}
.table-content {
flex: 1;
overflow: hidden;
}
.middle-content {
width: 500px;
display: flex;
flex-direction: column;
gap: 5px;
}
.right-content {
width: 400px;
}
.basic-info {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
.basic-info-item {
display: flex;
align-items: center;
span:last-child {
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
.box-top {
position: relative;
border: 1px solid #ddd;
background: rgb(50 50 50);
border-radius: 5px;
padding: 10px 15px;
box-sizing: border-box;
font-size: 16px;
color: #fff;
overflow: hidden;
}
.multiple-title {
position: absolute;
top: 0;
right: 0;
&::after {
position: absolute;
top: -31px;
right: -30px;
content: '';
border-width: 30px;
border-style: solid;
border-color: transparent transparent red transparent;
transform: rotate(45deg);
}
.multiple-title-text {
position: absolute;
z-index: 2;
color: #fff;
left: -20px;
}
}
.box-top-item {
display: flex;
height: 80px;
align-items: center;
margin-bottom: 10px;
}
.box-top-item-box-index {
font-size: 60px;
color: red;
text-align: center;
width: 120px;
font-weight: 600;
}
.box-top-item-box-index-text {
margin-right: 15px;
font-size: 30px;
}
.box-top-item-box-index-number {
font-size: 60px;
color: red;
display: inline-block;
text-align: center;
width: 90px;
font-weight: 600;
}
.box-top-item-status {
margin-bottom: 15px;
}
.order-image {
flex: 1;
overflow: hidden;
border: 1px solid #ddd;
background: #eee;
}
.box-list {
display: grid;
grid-template-columns: repeat(7, 50px);
gap: 8px;
position: relative;
}
.box-list-item {
position: relative;
border: 1px solid #ddd;
cursor: pointer;
font-size: 18px;
line-height: 30px;
height: 46px;
text-align: center;
box-sizing: border-box;
border-radius: 5px;
&:not(.isNull) {
background: #819aff;
color: #fff;
}
&.active {
background: #ff9900;
color: #fff;
}
&.badge::after {
position: absolute;
content: '';
right: 4px;
top: 4px;
width: 7px;
height: 7px;
border-radius: 50%;
background-color: red;
}
.number {
position: absolute;
bottom: 3px;
right: 0;
left: 0;
text-align: center;
font-size: 12px;
line-height: 14px;
color: #ddd;
}
}
</style>
<style lang="scss">
.pod-make-order-dialog {
.el-dialog {
display: flex;
flex-direction: column;
height: calc(100% - 60px);
}
.el-dialog__body {
flex: 1;
overflow: hidden;
}
}
</style>
<template>
<el-dialog
title="处理结果"
v-model="resultDialog"
width="60%"
:close-on-click-modal="false"
@closed="closedFn"
>
<div style="display: flex">
<el-checkbox
:indeterminate="isIndeterminate"
v-model="checkAll"
@change="checkAllChange"
>
{{ '全选' }}
</el-checkbox>
<el-button
type="success"
style="margin-left: 20px"
@click="resultfilter(true)"
>
{{ '选择正常' }}
</el-button>
<el-button type="danger" @click="resultfilter(false)">
{{ '选择异常' }}
</el-button>
<el-button type="success" @click="copyAllCode('factoryOrderNumber')">
{{ '复制工厂订单号' }}
</el-button>
</div>
<div style="height: 50vh; overflow: auto">
<div style="margin: 15px 0"></div>
<el-checkbox-group v-model="selectedList" @change="checkChange">
<div style="display: block" v-for="(item, index) in list" :key="index">
<el-checkbox :value="item">
{{ '工厂订单号:' + item.factoryOrderNumber + ' ' + item.message }}
</el-checkbox>
</div>
</el-checkbox-group>
</div>
<template #footer>
<div style="display: flex; justify-content: flex-end">
<!-- <el-button @click="resultDialog = false"> 取 消 </el-button>
<div style="width: 50px; display: inline-block"></div> -->
<el-button type="primary" @click="confirm"> 确 定 </el-button>
</div>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, watch } from 'vue'
import { copyText } from '@/utils/index'
interface IList {
id: string | number
shopNumber?: string
factoryOrderNumber?: string
message: string
status: boolean
}
const props = withDefaults(
defineProps<{
list: IList[]
}>(),
{
list: () => [],
},
)
// 响应式数据
const resultDialog = ref(false)
const isIndeterminate = ref(false)
const checkAll = ref(false)
const selectedList = ref<IList[]>([])
let key = ''
// 显示弹窗
const showDialog = (type?: string) => {
key = type || ''
resultDialog.value = true
selectedList.value = []
checkAll.value = false
}
// 全选状态改变
const checkAllChange = (value: boolean) => {
selectedList.value = value ? props.list : []
isIndeterminate.value = false
}
// 单个选择改变
const checkChange = () => {
const checkedCount = selectedList.value.length
checkAll.value = checkedCount === props.list.length
isIndeterminate.value = checkedCount > 0 && checkedCount < props.list.length
}
// 确认选择
const confirm = () => {
resultDialog.value = false
// emits('confirm', selectedList.value)
}
// 结果过滤
const resultfilter = (bool: boolean) => {
const arr = props.list.filter((item) => item.status === bool)
selectedList.value = arr
const checkedCount = arr.length
console.log(112, checkedCount)
console.log(113, props.list)
checkAll.value = checkedCount === props.list.length
isIndeterminate.value = checkedCount > 0 && checkedCount < props.list.length
}
// 复制店铺单号
const copyAllCode = (field: string) => {
if (!selectedList.value.length) {
return ElMessage.warning('请先选择数据')
}
const str = selectedList.value.map((el) => el[field as keyof IList]).join(',')
console.log('复制店铺单号', str)
copyText(str)
}
function closedFn() {
if (key === 'stockOut') return
emits('confirm', selectedList.value)
}
// 监听弹窗状态
watch(
() => resultDialog.value,
(v) => {
console.log(v)
},
)
watch(
() => props.list,
(v) => {
if (v.length) {
console.log(127, v)
resultfilter(true)
}
},
)
defineExpose({
showDialog,
})
const emits = defineEmits<{
(e: 'confirm', data: IList[]): void
}>()
</script>
<style lang="scss" scoped></style>
<script setup lang="ts">
import { defineModel } from 'vue'
import { updateAddressApi } from '@/api/podCnOrder.ts'
import {AddressInfo} from '@/types/api/podCnOrder.ts'
const emits = defineEmits(['success'])
defineProps<{
countryList: { countryCode: string }[]
}>()
const visible = defineModel<boolean>('visible')
const form = defineModel<AddressInfo>('form', {
default: {
receiverName: '',
receiverPhone: '',
receiverCountry: '',
receiverProvince: '',
receiverCity: '',
receiverDistrict: '',
receiverAddress1: '',
receiverAddress2: '',
receiverPostCode: '',
},
})
const formRef = ref()
const rules = {
receiverName: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
receiverPhone: [{ required: true, message: '请输入电话', trigger: 'blur' }],
receiverCountry: [{ required: true, message: '请输入国家', trigger: 'blur' }],
receiverProvince: [
{ required: true, message: '请输入省/州', trigger: 'blur' },
],
receiverCity: [{ required: true, message: '请输入市', trigger: 'blur' }],
receiverAddress1: [
{ required: true, message: '请输入地址1', trigger: 'blur' },
],
receiverPostCode: [
{ required: true, message: '请输入邮政编码', trigger: 'blur' },
],
}
const submitForm = async () => {
formRef?.value.validate(async (valid: boolean) => {
if (valid) {
await updateAddressApi(form.value as never)
visible.value = false
emits('success')
await ElMessageBox.alert(
'请修改/刷新地址后取消物流或者更换物流在重新创建物流订单、获取跟踪号、获取打印面单',
'提示',
{
type: 'warning',
confirmButtonText: '确定',
cancelButtonText: '取消',
showCancelButton: true,
},
)
}
})
}
</script>
<template>
<el-dialog
v-model="visible"
:close-on-click-modal="false"
title="修改揽收信息"
width="50%"
>
<el-form ref="formRef" :model="form" :rules="rules" label-width="120px">
<el-form-item label="姓名" prop="receiverName">
<el-input
v-model="form.receiverName"
clearable
placeholder="请输入姓名"
/>
</el-form-item>
<el-form-item label="电话" prop="receiverPhone">
<el-input
v-model="form.receiverPhone"
clearable
placeholder="请输入电话"
/>
</el-form-item>
<el-form-item label="国家" prop="receiverCountry">
<el-select v-model="form.receiverCountry" clearable filterable>
<el-option
v-for="it in countryList"
:key="it.countryCode"
:label="it.countryCode"
:value="it.countryCode"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="省/州" prop="receiverProvince">
<el-input
v-model="form.receiverProvince"
clearable
placeholder="请输入省/州"
/>
</el-form-item>
<el-form-item label="市" prop="receiverCity">
<el-input
v-model="form.receiverCity"
clearable
placeholder="请输入市"
/>
</el-form-item>
<el-form-item label="区/县" prop="receiverDistrict">
<el-input
v-model="form.receiverDistrict"
clearable
placeholder="请输入区/县"
/>
</el-form-item>
<el-form-item label="地址1" prop="receiverAddress1">
<el-input
v-model="form.receiverAddress1"
clearable
placeholder="请输入地址1"
/>
</el-form-item>
<el-form-item label="地址2" prop="receiverAddress2">
<el-input
v-model="form.receiverAddress2"
clearable
placeholder="请输入地址2"
/>
</el-form-item>
<el-form-item label="邮政编码" prop="receiverPostCode">
<el-input
v-model="form.receiverPostCode"
clearable
placeholder="请输入邮政编码"
/>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="visible = false">取消</el-button>
<el-button type="primary" @click="submitForm">提交</el-button>
</template>
</el-dialog>
</template>
<style scoped lang="scss"></style>
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -365,7 +365,6 @@ watch(visible, async (value: boolean) => {
warehouseId.value = locaclWarehouseId
? JSON.parse(locaclWarehouseId)
: props.warehouseList[0].id
_warehouseId.value = locaclWarehouseId
? JSON.parse(locaclWarehouseId)
: props.warehouseList[0].id
......
......@@ -560,7 +560,6 @@
<ElButton type="warning" @click="showArrange(2)">排单完成</ElButton>
</span>
</ElFormItem>
<ElFormItem
v-if="status !== 'BATCH_DOWNLOAD' && status !== 'WAIT_SHIPMENT'"
>
......@@ -3060,7 +3059,7 @@ const tableColumns = computed(() => {
align: 'center',
},
{
label: '发货时间',
label: '完成时间',
width: 180,
prop: 'finishTime',
slot: 'finishTime',
......
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