Commit e97691dc by zhuzhequan

删除无用文件

parent 6d854d2d
<template>
<div class="card flex-column h-100 overflow-hidden">
<div class="header-filter-form">
<ElForm :model="searchForm" size="default" inline>
<ElFormItem>
<el-select
v-model="searchForm.timeType"
style="width: 100px; margin-right: 5px"
clearable
placeholder="时间类型"
>
<el-option :value="1" label="创建时间"></el-option>
<el-option :value="2" label="确认时间"></el-option>
<el-option :value="3" label="完成时间"></el-option>
<!-- <el-option :value="4" label="发货时间"></el-option> -->
</el-select>
<el-date-picker
v-model="timeRange"
:default-time="[
new Date(0, 0, 0, 0, 0, 0),
new Date(0, 0, 0, 23, 59, 59),
]"
placeholder="收货人"
value-format="YYYY-MM-DD HH:mm:ss"
type="datetimerange"
style="width: 280px"
:shortcuts="pickerOptions.shortcuts"
start-placeholder="开始时间"
end-placeholder="结束时间"
clearable
>
</el-date-picker>
</ElFormItem>
<ElFormItem label="SKU">
<ElInput
v-model.trim="searchForm.sku"
placeholder=" SKU"
clearable
style="width: 130px"
></ElInput>
</ElFormItem>
<!-- <ElFormItem label="发货单号">
<ElInput
v-model="searchForm.shipmentNumber"
placeholder="发货单号"
clearable
style="width: 130px"
/>
</ElFormItem> -->
<ElFormItem label="生产单号">
<ElInput
v-model="searchForm.factorySubOrderNumber"
placeholder="定制生产单号"
clearable
style="width: 130px"
/>
</ElFormItem>
<ElFormItem label="订单号">
<ElInput
v-model="searchForm.factoryOrderNumber"
placeholder="定制订单号"
clearable
style="width: 130px"
/>
</ElFormItem>
<ElFormItem label="店铺单号">
<ElInput
v-model="searchForm.shopNumber"
placeholder="店铺单号"
clearable
style="width: 130px"
/>
</ElFormItem>
<ElFormItem label="内部标签">
<ElInput
v-model.trim="searchForm.internalMemo"
placeholder="内部标签"
clearable
style="width: 130px"
></ElInput>
</ElFormItem>
<ElFormItem label="排序">
<el-select
v-model="searchForm.order"
clearable
style="width: 100px"
placeholder="排序类型"
>
<el-option value="asc" label="正序"></el-option>
<el-option value="desc" label="倒序"></el-option>
</el-select>
</ElFormItem>
<ElFormItem label="定制类型">
<el-select
v-model="searchForm.customizedQuantity"
clearable
style="width: 100px"
placeholder="定制类型"
>
<el-option value="single" label="单面"></el-option>
<el-option value="multiple" label="多面"></el-option>
</el-select>
</ElFormItem>
<ElFormItem>
<ElButton type="primary" @click="loadDiffList">查询</ElButton>
</ElFormItem>
</ElForm>
</div>
<div class="header-filter-tab">
<div class="tabs">
<div
v-for="item in tabsNav"
:key="item.status"
class="tabs-node"
:class="item.status === status ? 'tabs-node_active' : ''"
@click="changeTab(item)"
>
<span class="tabs-node_label">{{ item.statusName }}</span>
<span class="tabs-node_count">{{ `(${item.quantity})` }}</span>
</div>
</div>
</div>
<div class="order-content flex-1 flex-column overflow-hidden mt-10">
<div style="margin-bottom: 10px">
<span v-if="status === 'TO_BE_CONFIRMED'" class="item">
<ElButton type="success" @click="confirmProduce">确认生产</ElButton>
</span>
<span v-if="status === 'IN_PRODUCTION'" class="item">
<ElButton type="success" dark @click="fastToProduction('快捷生产', 1)"
>快捷生产</ElButton
>
</span>
<span
v-if="
status === 'TO_BE_CONFIRMED' ||
status === 'IN_PRODUCTION' ||
status === 'PART_SHIPPING'
"
class="item"
>
<ElButton type="primary" dark @click="printManuscript"
>打印生产单</ElButton
>
</span>
<span v-if="status === 'TO_BE_CONFIRMED'" class="item">
<ElButton type="success" dark @click="exportManuscript"
>导出生产单</ElButton
>
</span>
<span class="item">
<ElButton type="warning" @click="addInternalTag"
>添加内部标签</ElButton
>
</span>
<span
v-if="
status === 'TO_BE_CONFIRMED' ||
status === 'IN_PRODUCTION' ||
status === 'PART_SHIPPING'
"
class="item"
>
<ElButton type="warning" is-dark @click="downloadMaterial">
下载素材</ElButton
>
</span>
<span
v-if="
[
'TO_BE_CONFIRMED',
'IN_PRODUCTION',
'PART_SHIPPING',
'WAIT_SHIPMENT',
].includes(status)
"
class="item"
>
<ElButton type="primary" @click="refreshProduct"
>刷新商品信息</ElButton
>
</span>
<span
v-if="status === 'WAIT_SHIPMENT' || status === 'PART_SHIPPING'"
class="item"
>
<ElButton type="success" @click="confirmDelivery">发货</ElButton>
</span>
<span v-if="status === 'IN_PRODUCTION'" class="item">
<ElButton type="danger" @click="voidedBtn">作废</ElButton>
</span>
<span v-if="status === 'IN_PRODUCTION'" class="item">
<ElButton type="warning" is-dark @click="applyForReplacement">
申请补胚</ElButton
>
</span>
</div>
<template
v-if="
[
'IN_PRODUCTION',
'WAIT_SHIPMENT',
'TO_BE_REPLENISHMENT',
'INVALID',
].includes(status)
"
>
<div
v-if="CardOrderList.length"
v-loading="loading"
element-loading-text="加载中..."
class="card-mode"
>
<div class="card-list">
<div
v-for="cardItem in CardOrderList"
:key="cardItem.id"
class="card-list_item"
@click="cardClick(cardItem)"
>
<CardWrapper
:card-item="cardItem"
:class="{ active: isSelectStatused(cardItem) }"
@contextmenu.prevent="(v) => rightClick(v, cardItem)"
>
<!-- <template #top_right> 工厂类型 </template> -->
<template #bottom_left>
<span
v-if="cardItem?.factorySubOrderNumber"
title="生产单号"
class="base_sku"
@click.stop="
copy(String(cardItem?.factorySubOrderNumber || ''))
"
>
{{ cardItem?.factorySubOrderNumber }}
</span>
</template>
<template #operations>
<Icon
name="caozuorizhi"
@click.stop="
openLog(Number(cardItem.podOrderId) || undefined)
"
>
<template #title>
<title>操作日志</title>
</template>
</Icon>
<Icon
name="chakanxiangqing"
@click.stop="openDetail(cardItem.id)"
>
<template #title>
<title>查看详情</title>
</template>
</Icon>
</template>
<template #images>
<div class="flex-between">
<div class="images-position">
<div
v-for="(item, index) in getSafeImages(cardItem)"
:key="index"
:title="
item?.ename
? item.ename === 'front'
? '正面图片'
: '反面图片'
: ''
"
:style="
currentImage === item?.image &&
currentId === cardItem.id
? 'border-color: red'
: ''
"
class="item-image"
@click="handleChangeImages(item, cardItem)"
>
<img :src="item?.image" height="28" />
</div>
</div>
<b
v-if="cardItem"
:style="{
color:
(Number(cardItem.customizedQuantity) || 0) > 1
? 'red'
: '#67C23A',
}"
>
{{
(Number(cardItem.customizedQuantity) || 0) > 1
? '多'
: '单'
}}
</b>
</div>
</template>
<template #info>
<div style="font-size: 12px; padding: 14px 5px 0">
<el-row class="el_row">
<el-col :span="14" :offset="0">
<el-tooltip
class="item"
effect="dark"
:content="cardItem?.baseSku"
placement="bottom"
>
<span
title="Base SKU"
style="
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
display: inline-block;
"
>
{{ cardItem?.baseSku }}
</span>
</el-tooltip>
</el-col>
<el-col
v-if="status === 'TO_BE_REPLENISHMENT'"
:span="10"
:offset="0"
style="text-align: right"
>
<el-tooltip
class="item"
effect="dark"
:content="'补胚数量'"
placement="bottom"
>
<span
>补胚数量:{{
cardItem?.replenishmentNum || '--'
}}</span
>
</el-tooltip>
</el-col>
<el-col
v-else
:span="10"
:offset="0"
style="text-align: right"
>
<span v-if="status === 'INVALID'">
数量:{{ cardItem?.num }}
</span>
<template v-else>
<el-tooltip
v-if="status !== 'TO_BE_REPLENISHMENT'"
class="item"
effect="dark"
:content="
['TO_BE_REPLENISHMENT', 'IN_PRODUCTION'].includes(
status,
)
? '未生产数量'
: '已生产数量'
"
placement="bottom"
>
<span
>数量:{{
[
'TO_BE_REPLENISHMENT',
'IN_PRODUCTION',
].includes(status)
? cardItem?.notPassNum
: cardItem?.passNum
}}</span
>
</el-tooltip>
</template>
</el-col>
</el-row>
<el-row style="margin-top: 5px">
<el-col
:span="14"
:offset="0"
style="
white-space: nowrap;
display: flex;
align-items: center;
"
>
<span
title="Variant SKU"
style="
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
"
>
{{ cardItem?.variantSku }}
</span>
</el-col>
<el-col :span="10" :offset="0" style="text-align: right">
<el-tooltip
class="item"
effect="dark"
:content="'货号'"
placement="bottom"
>
<span
>货号:{{ cardItem?.supplierItemNo || '--' }}</span
>
</el-tooltip>
</el-col>
</el-row>
<el-row style="margin-top: 5px">
<el-col
:span="12"
:offset="0"
style="
white-space: nowrap;
display: flex;
align-items: center;
"
>
<span>工艺:</span>
<span
:title="String(cardItem?.process)"
style="
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
"
>
{{ cardItem?.process }}
</span>
</el-col>
<el-col
:span="12"
:offset="0"
style="white-space: nowrap; text-align: right"
>
<span
:title="`店铺单号:${cardItem?.shopNumber}`"
style="
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
"
>
{{ cardItem?.shopNumber }}
</span>
</el-col>
</el-row>
<el-row style="margin-top: 5px">
<el-col
:span="12"
:offset="0"
style="white-space: nowrap"
>
<span
:title="`第三方生产单号:${cardItem?.thirdSubOrderNumber}`"
style="
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
"
@click.stop="
copy(String(cardItem?.thirdSubOrderNumber || ''))
"
>
{{ cardItem?.thirdSubOrderNumber }}
</span>
</el-col>
<el-col :span="12" :offset="0" style="text-align: right">
<span title="期望交货时间">
{{ cardItem?.expectDeliveryTime }}
</span>
</el-col>
</el-row>
<el-row style="margin-top: 5px">
<el-col
:span="12"
:offset="0"
style="white-space: nowrap"
>
<span
:title="`第三方订单号:${cardItem?.thirdOrderNumber}`"
style="
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
"
@click.stop="
copy(String(cardItem?.thirdOrderNumber || ''))
"
>
{{ cardItem?.thirdOrderNumber }}
</span>
</el-col>
</el-row>
</div>
</template>
</CardWrapper>
</div>
</div>
</div>
<div v-else class="empty">暂无数据</div>
</template>
<div
v-else
ref="tableWrapperRef"
v-loading="loading"
element-loading-text="加载中..."
class="order-list flex-1 overflow-hidden"
>
<TableView
:paginated-data="tableData"
:columns="tableColumns"
:selectionable="true"
default-expand-all
:span-method="arraySpanMethod"
@selection-change="handleSelectionChange"
@contextmenu.prevent="handleContextMenu"
>
<template #expand="{ row }">
<div v-if="row.productList" class="table-expand">
<div
class="order-list-expand"
:style="{ width: `${thOrderDetailWidth + 50}px` }"
>
<ProductInfo :row="row" :status="status" :is-pod="true">
<template #operation="{ productItem }">
<div class="operation-item" title="添加备注">
<el-icon
class="icon"
style="color: #e6a23c"
@click="
handleUpdateRemark(
productItem.id,
productItem.remark || '',
)
"
><EditPen
/></el-icon>
</div>
<div
v-if="status === 'TO_BE_RECEIPT'"
class="operation-item"
>
<el-button
size="small"
type="warning"
@click="applyEmbryoReplenishment(productItem)"
>申请补胚</el-button
>
</div>
<div
v-if="
status === 'TO_BE_RECEIPT' ||
status === 'TO_BE_CONFIRMED'
"
class="operation-item"
>
<el-button
size="small"
type="danger"
@click="invalidOrder(productItem)"
>作废</el-button
>
</div>
</template>
</ProductInfo>
<template v-if="row.productList.length > 2">
<div class="order-list-expand_more">
<span @click="openAll(row)">
<template v-if="!row.moreable">
展开全部<strong style="color: red"
>({{ row.productList.length }})</strong
>条商品信息<el-icon style="vertical-align: middle"
><ArrowDown /></el-icon
></template>
<template v-else>
收起商品信息<el-icon style="vertical-align: middle"
><ArrowUp
/></el-icon>
</template>
</span>
</div>
</template>
</div>
<div class="order-actual-payment">
<div class="order-actual-payment_info">
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label">商品价:</span>
<span class="order-list-expand_item_value">{{
row.thirdProductAmount
}}</span>
</div>
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label">小计:</span>
<span class="order-list-expand_item_value">{{
row.totalAmount || '--'
}}</span>
</div>
<div
v-if="row.totolBuyNumber"
class="order-list-expand_item_info_title"
>
<span class="order-list-expand_item_value"
>{{ row.totolBuyNumber }}</span
>
</div>
</div>
</div>
<div class="order-memo">
<div class="order-memo-info">
<div
v-for="memo in row.internalMemoList || []"
:key="memo.id"
class="order-memo-item"
>
<div
v-if="memo.operatorEmployeeName"
class="order-memo-item__name"
>
<span>{{ memo.operatorEmployeeName || '' }}</span>
</div>
<div
v-if="memo.operatorTime"
class="order-memo-item__time"
:title="memo.operatorTime"
>
<span>{{ memo.operatorTime || '' }}</span>
</div>
<div
v-if="memo.content"
class="order-memo-item__content"
:title="memo.content"
>
<span>{{ memo.content || '' }}</span>
</div>
</div>
</div>
</div>
<div class="order-time">
<div class="order-time_info">
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label">创建时间:</span>
<span class="order-list-expand_item_value">{{
row.createTime || '--'
}}</span>
</div>
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label"
>期望交货时间:</span
>
<span class="order-list-expand_item_value">{{
row.expectDeliveryTime || '--'
}}</span>
</div>
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label">确认时间:</span>
<span class="order-list-expand_item_value">{{
row.startStockingTime || '--'
}}</span>
</div>
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label">完成时间:</span>
<span class="order-list-expand_item_value">{{
row.finishTime || '--'
}}</span>
</div>
</div>
</div>
<div class="order-operate">
<div class="order-operate_info">
<div
v-if="status === 'TO_BE_CONFIRMED'"
class="order-list-expand_item_info_title"
>
<ElButton text type="danger" @click="cancelOrder(row.id)"
>取消
</ElButton>
</div>
<div class="order-list-expand_item_info_title">
<ElButton text type="primary" @click="openLog(row.id)"
>操作日志
</ElButton>
</div>
</div>
</div>
</div>
</template>
<template #orderDetail="scope">
<div class="order-detail">
<div
:title="scope.row.factoryOrderNumber"
class="order-detail_item"
>
<span class="label">订单号:</span>
<span class="value">{{ scope.row.factoryOrderNumber }}</span>
</div>
<div
:title="scope.row.thirdOrderNumber"
class="order-detail_item"
>
<span class="label">第三方订单号:</span>
<span class="value" :title="scope.row.thirdOrderNumber">{{
scope.row.thirdOrderNumber || '--'
}}</span>
</div>
<!-- <div
:title="scope.row.manuscriptStatusStr"
class="order-detail_item"
>
<span class="label">稿件状态:</span>
<span class="value" :title="scope.row.manuscriptStatusStr">{{
scope.row.manuscriptStatusStr || '--'
}}</span>
</div> -->
<div :title="scope.row.lanshouName" class="order-detail_item">
<span class="label">收货人:</span>
<span class="value">{{ scope.row.lanshouName }}</span>
</div>
<div :title="scope.row.lanshouPhone" class="order-detail_item">
<span class="label">电话:</span>
<span class="value">{{ scope.row.lanshouPhone }}</span>
</div>
<div :title="scope.row.lanshouAddress" class="order-detail_item">
<span class="label">收货地址:</span>
<span class="value" :title="scope.row.lanshouAddress">{{
scope.row.lanshouRegion + scope.row.lanshouAddress
}}</span>
</div>
<div
v-if="scope.row.shipmentUid"
:title="scope.row.shipmentUid"
class="order-detail_item"
>
<span class="label">提货码:</span>
<span class="value" :title="scope.row.shipmentUid">{{
scope.row.shipmentUid
}}</span>
</div>
<div :title="scope.row.lanshouPost" class="order-detail_item">
<span class="label">邮编:</span>
<span class="value">{{ scope.row.lanshouPost }}</span>
</div>
</div>
</template>
</TableView>
</div>
<div class="pagination">
<div>
<span>已选择 <span style="color: red">{{selection.length}}</span> 条数据</span>
</div>
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:page-sizes="[100, 200, 300, 400]"
background
layout="total, sizes, prev, pager, next, jumper"
:total="total"
style="margin: 10px auto 10px; text-align: right"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
</div>
<el-dialog
v-model="shipmentVisible"
title="发货"
:close-on-click-modal="false"
width="1600PX"
top="6vh"
@opened="onShipmentDialogOpened"
>
<div class="header-search">
<el-input
ref="inputRef"
v-model="productionOrderNumber"
clearable
size="large"
placeholder="请输入生产单号"
@keydown.enter="searchShipmentByOrderNumber"
/>
<el-button
type="primary"
size="large"
@click="searchShipmentByOrderNumber"
>查询
</el-button>
</div>
<Shipment
ref="shipmentOrderRef"
v-loading="shipmentLoading"
:order-list="orderList"
:current-row="currentRow"
:is-pod="true"
@change-current-row="onChangeCurrentRow"
/>
<div class="shipment-logistics-info margin-top-20">
<ElForm ref="shipmentFormRef" :model="shipmentForm" :rules="rules">
<ElRow :gutter="20">
<ElCol :span="6">
<ElFormItem label="发货方式" prop="shippingWay">
<ElSelect
v-model="shipmentForm.shippingWay"
clearable
placeholder="请选择"
style="width: 100%"
>
<ElOption label="送货上门" value="1"></ElOption>
<ElOption label="快递" value="2"></ElOption>
</ElSelect>
</ElFormItem>
</ElCol>
<ElCol v-if="shipmentForm.shippingWay === '2'" :span="6">
<ElFormItem label="物流名称" prop="carriageName">
<ElSelect
v-model="shipmentForm.carriageName"
filterable
placeholder="请输入关键字"
clearable
style="width: 100%"
>
<ElOption
v-for="item in logisticsCompanyList"
:key="item.id"
:value="item.name"
></ElOption>
</ElSelect>
</ElFormItem>
</ElCol>
<ElCol v-if="shipmentForm.shippingWay === '2'" :span="6">
<ElFormItem label="物流跟踪号" prop="logisticsTracking">
<ElInput
v-model="shipmentForm.logisticsTracking"
placeholder="请输入物流跟踪号"
clearable
style="width: 100%"
/>
</ElFormItem>
</ElCol>
<ElCol v-if="shipmentForm.shippingWay === '2'" :span="6">
<ElFormItem label="物流费用" prop="carriageAmount">
<ElInput
v-model="shipmentForm.carriageAmount"
clearable
placeholder="请输入物流费用"
style="width: 100%"
/>
</ElFormItem>
</ElCol>
</ElRow>
</ElForm>
</div>
<template #footer>
<div class="dialog-footer">
<el-button size="large" @click="shipmentVisible = false"
>取消
</el-button>
<el-button size="large" type="primary" @click="saveShipment"
>发货
</el-button>
</div>
</template>
</el-dialog>
<el-dialog
v-model="logVisible"
title="操作日志"
width="1000px"
:close-on-click-modal="false"
>
<LogList :log-list="logList" />
</el-dialog>
<el-dialog
v-model="countVisible"
title="数据统计"
width="400px"
:close-on-click-modal="false"
>
<p>
基版 <b>{{ cardItem?.baseSku }}</b> 的统计数量为:<b> {{ count }}</b>
</p>
</el-dialog>
<right-menu
ref="rightMenuRef"
:show_copy_shop_number="['IN_PRODUCTION', 'WAIT_SHIPMENT'].includes(status)"
@change="rightChange"
/>
<fastProduction
v-model:detailVisible="detailVisible"
:title="fastTitle"
:is-jmpod="'JMPOD'"
:type="fastType"
:detail-data="detailData"
:current-status="status"
@on-success="handleSuccess"
@close="fastClose"
></fastProduction>
<table-right-menu
ref="tableRightMenuRef"
:table-right-menu-visible="tableRightMenuVisible"
@on-copy-change="onCopyChange"
/>
</template>
<script setup lang="tsx">
// refreshJMProductInfo,reasonInvalidationApi,
import RightMenu from './rightMenu.vue'
import {
getOrderTabData,
getOrderList,
confirmProductionOrder,
cancelOrderApi,
downloadMaterialApi,
addInternalTagApi,
printOrder,
exportOrder,
getLogList,
updateRemarkApi,
getCardOrderList,
getOrderDetail,
getInProductionCount,
getWaitShipmentCount,
refreshJMProductInfo,
reasonInvalidationApi,
applyForReplenishmentApi,
} from '@/api/podOrder'
import TableView from '@/components/TableView.vue'
import {
ProductList,
LogisticsData,
OrderData,
ShipmentForm,
} from '@/types/api/order'
import fastProduction from '../fastProduction.vue'
import CardWrapper from '@/components/CardPods.vue'
import { CustomColumn } from '@/types/table'
import { useValue } from '@/utils/hooks/useValue'
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
import dayjs from 'dayjs'
import useElTableColumnWidth from '@/utils/hooks/useElTableColumnWidth'
import ProductInfo from '../ProductInfo.vue'
import { SpanMethodProps } from '@/types/api/order'
import useShipment from '../hook/usePodShipment'
import Shipment from '../Shipment.vue'
import {
SearchForm,
Tab,
LogListData,
PodProductList,
cardImages,
imageAryInter,
CardOrderData,
} from '@/types/api/podOrder'
import { ArrowUp, ArrowDown, EditPen } from '@element-plus/icons-vue'
import { getLogisticsCompanyList } from '@/api/common'
import { ElButton, type FormRules } from 'element-plus'
import { showConfirm } from '@/utils/ui'
import { filePath } from '@/api/axios'
import LogList from '@/components/LogList.vue'
const tableRef = ref()
const loading = ref(false)
const currentPage = ref(1)
const pageSize = ref(100)
const total = ref(0)
const countVisible = ref(false)
const keyCode = ref('')
const cardItem = ref<PodProductList | CardOrderData>()
const rightMenuRef = ref()
const count = ref<number>(0)
const rightClick = (e: MouseEvent, item: PodProductList | CardOrderData) => {
cardItem.value = item
rightMenuRef.value.setPosition({
x: e.clientX,
y: e.clientY,
cardItem: e.clientY,
el: e,
})
}
const handleSizeChange = (size:number)=>{
pageSize.value = size
loadDiffList()
}
const handleCurrentChange = (page:number)=>{
currentPage.value = page
loadDiffList()
}
const rightChange = async (code: string) => {
const flag = ['IN_PRODUCTION', 'WAIT_SHIPMENT'].includes(status.value)
if (code === 'check_all') {
if (flag) {
selection.value = JSON.parse(JSON.stringify(CardOrderList.value))
} else {
if (tableRef.value && tableRef.value?.tableRef) {
tableRef.value?.tableRef.toggleAllSelection()
}
// selection.value = JSON.parse(JSON.stringify(tableData.value))
}
} else if (code === 'clear_check') {
selection.value = []
tableRef.value?.tableRef.toggleAllSelection()
} else if (code === 'copy_code') {
const str = selection.value
.map((item) => item.factorySubOrderNumber || item.factoryOrderNumber)
.join()
navigator.clipboard.writeText(str)
ElMessage.success('复制成功')
} else if (code === 'copy_shopNumber') {
const str = selection.value.map((item) => item.shopNumber).join()
navigator.clipboard.writeText(str)
ElMessage.success('复制成功')
} else if (code === 'count') {
countVisible.value = true
let res
if (status.value === 'WAIT_SHIPMENT') {
res = await getWaitShipmentCount(
cardItem.value?.productionFileId,
cardItem.value?.baseSku,
)
} else if (status.value === 'IN_PRODUCTION') {
res = await getInProductionCount(
cardItem.value?.productionFileId,
cardItem.value?.baseSku,
)
}
count.value = (res?.data || 0) as number
}
}
// 日期工具函数
const getDateRange = (days = 0, type: 'past' | 'future' = 'past') => {
const end = dayjs()
const start =
type === 'past' ? end.subtract(days, 'day') : end.add(days, 'day')
return [start.startOf('day').toDate(), end.endOf('day').toDate()]
}
const getMonthRange = (months = 0, type: 'past' | 'future' = 'past') => {
const now = dayjs()
const start =
type === 'past' ? now.subtract(months, 'month') : now.add(months, 'month')
return [start.startOf('month').toDate(), start.endOf('month').toDate()]
}
const getWeekRange = (weeks = 0, type: 'past' | 'future' = 'past') => {
const now = dayjs()
const start =
type === 'past' ? now.subtract(weeks, 'week') : now.add(weeks, 'week')
return [start.startOf('week').toDate(), start.endOf('week').toDate()]
}
const pickerOptions = {
shortcuts: [
{
text: '今日',
value: () => getDateRange(0),
},
{
text: '昨天',
value: () => getDateRange(1),
},
{
text: '最近7天',
value: () => getDateRange(6),
},
{
text: '最近14天',
value: () => getDateRange(13),
},
{
text: '最近30天',
value: () => getDateRange(29),
},
{
text: '本周',
value: () => getWeekRange(0),
},
{
text: '上周',
value: () => getWeekRange(1),
},
{
text: '本月',
value: () => getMonthRange(0),
},
{
text: '上月',
value: () => getMonthRange(1),
},
{
text: '历史',
value: () => {
const end = dayjs().endOf('day').toDate()
const start = dayjs('2000-01-01').startOf('day').toDate()
return [start, end]
},
},
],
}
const timeRange = ref<string[]>([])
const tabsNav = ref<Tab[]>()
const status = ref('TO_BE_CONFIRMED')
const [tableWrapperRef, thOrderDetailWidth, updateColumnWidth] =
useElTableColumnWidth('table th.th-order-detail')
const loadTabData = async () => {
try {
const res = await getOrderTabData()
tabsNav.value = res.data
} catch (error) {
// showError(error)
}
}
const handleSuccess = () => {
loadTabData()
loadDiffList()
}
// 查看详情
const openDetail = async (id: number) => {
try {
const res = await getOrderDetail(id)
if (res.code == 200) {
if (res.data.imageAry) {
res.data.imageAry = JSON.parse(res.data.imageAry as string)
}
detailData.value = res.data || {}
detailVisible.value = true
fastTitle.value = '查看详情'
fastType.value = 0
}
} catch (e) {
//showError(e)
}
}
const CardOrderList = ref<(PodProductList | CardOrderData)[]>([])
const loadCardList = async () => {
try {
const res = await getCardOrderList(
{
...searchForm.value,
status: status.value,
timeType: searchForm.value.timeType,
startTime:
timeRange.value && timeRange.value.length > 0
? timeRange.value[0]
: null,
endTime:
timeRange.value && timeRange.value.length > 0
? timeRange.value[1]
: null,
},
currentPage.value,
pageSize.value,
)
CardOrderList.value = res.data.records.map((item: PodProductList) => {
if (!item.imageAry) {
const images = []
if (typeof item.variantImage === 'string') {
images.push({
ename: 'front',
cname: '正面',
image: item.variantImage,
})
}
if (typeof item.negativeImage === 'string') {
images.push({
ename: 'back',
cname: '反面',
image: item.negativeImage,
})
}
item.images = images
} else {
if (item.imageAry) {
const images = JSON.parse(item.imageAry as string)
if (Array.isArray(images)) {
item.images = images.map((e: imageAryInter) => {
return {
ename: '',
cname: '',
image: e.url,
}
})
}
}
}
return item
})
total.value = res.data.total
} catch (error) {
// showError(error)
}
}
const loadOrderList = async () => {
try {
const res = await getOrderList({
...searchForm.value,
status: status.value,
timeType: searchForm.value.timeType,
startTime:
timeRange.value && timeRange.value.length > 0
? timeRange.value[0]
: null,
endTime:
timeRange.value && timeRange.value.length > 0
? timeRange.value[1]
: null
},currentPage.value,pageSize.value)
tableData.value = res.data.records
total.value = res.data.total
} catch (error) {
// showError(error)
}
}
const currentImage = ref('')
const currentId = ref(-1)
const changeImages = (
item: cardImages,
data: PodProductList | CardOrderData,
) => {
currentImage.value = item.image
// data.designId = item.designId
currentId.value = data.id
data.variantImage = item.image
// if (data.productList) {
// data.productList[0].variantImage = item.image
// }
}
// 包装函数,用于处理类型转换
const handleChangeImages = (
item: cardImages,
data: PodProductList | CardOrderData,
) => {
changeImages(item as cardImages, data)
}
const fastTitle = ref('')
const detailData = ref({})
const detailVisible = ref(false)
const fastType = ref<number>(-1)
const fastToProduction = (title: string, type: number) => {
detailData.value = {}
detailVisible.value = true
fastTitle.value = title
fastType.value = type
}
const cardClick = (data: PodProductList | CardOrderData) => {
const status = isSelectStatused(data)
if (keyCode.value === 'Shift') {
if (selection.value.length) {
const startIndex = CardOrderList.value.findIndex(
(el) => el.id === selection.value[0].id,
)
const endIndex = CardOrderList.value.findIndex((el) => el.id === data.id)
selection.value = []
for (let k = startIndex; k <= endIndex; k++) {
selection.value.push(JSON.parse(JSON.stringify(CardOrderList.value[k])))
}
}
}
if (status) {
selection.value = selection.value.filter(
(item: CardOrderData | PodProductList) => item.id !== data.id,
)
} else {
selection.value.push(data as CardOrderData)
}
}
const isSelectStatused = (data: PodProductList | CardOrderData) => {
const index = selection.value.findIndex(
(item: CardOrderData | PodProductList) => item.id === data.id,
)
return index !== -1
}
const changeTab = (item: Tab) => {
status.value = item.status ?? ''
currentPage.value = 1
pageSize.value = 100
selection.value = []
searchForm.value.timeType = null
loading.value = false
loadDiffList()
}
const fastClose = () => {
if (fastType.value !== 0) {
loadTabData()
}
detailVisible.value = false
}
// 根据不同状态调用不同接口
const loadDiffList = async () => {
if (
[
'IN_PRODUCTION',
'WAIT_SHIPMENT',
'TO_BE_REPLENISHMENT',
'INVALID',
].includes(status.value)
) {
await loadCardList()
} else {
loadOrderList()
updateColumnWidth()
}
}
const [searchForm] = useValue<SearchForm>({
timeType: null,
shopNumber: '',
customizedQuantity: '',
order: 'desc',
})
const tableColumns = computed<CustomColumn<CardOrderData[]>>(() => {
return [
{
type: 'expand',
align: 'center',
slot: 'expand',
width: 1,
},
{
label: '订单详情',
key: 'id',
minWidth: 800,
slot: 'orderDetail',
className: 'th-order-detail',
showOverflowTooltip: true,
},
{
label: '实付款',
key: '',
width: 280,
},
{
label: '内部便签',
key: 'customerName',
width: 300,
showOverflowTooltip: true,
},
{
label: '时间',
key: 'status',
width: 300,
align: 'center',
},
{
label: '操作',
key: 'status',
width: 100,
align: 'center',
},
]
})
// const {
// loading,
// currentPage,
// pageSize,
// total,
// data: tableData,
// refresh: search,
// onCurrentPageChange: handleCurrentChange,
// onPageSizeChange: handleSizeChange,
// } = usePageList<OrderData | CardOrderData>({
// query: async (page, pageSize) => {
// const commonParams = {
// ...searchForm.value,
// status: status.value,
// timeType: searchForm.value.timeType,
// startTime:
// timeRange.value && timeRange.value.length > 0
// ? timeRange.value[0]
// : null,
// endTime:
// timeRange.value && timeRange.value.length > 0
// ? timeRange.value[1]
// : null,
// }
// // 动态选择接口
// const fetchData =
// status.value === 'IN_PRODUCTION' ? getCardOrderList : getOrderList
// return fetchData(commonParams, page, pageSize).then(
// (res) => {
// if([
// 'IN_PRODUCTION',
// 'WAIT_SHIPMENT',
// 'TO_BE_REPLENISHMENT',
// 'INVALID',
// ].includes(status.value)){
// CardOrderList.value = res.data.records as PodProductList[]
// }else{
// tableData.value = res.data.records
// }
// },
// ) as never
// },
// })
// 发货
const {
shipmentFormRef,
productionOrderNumber,
shipmentVisible,
inputRef,
shipmentForm,
currentRow,
shipmentLoading,
orderList,
shipmentOrderRef,
searchShipmentByOrderNumber,
saveShipment,
confirmDelivery,
onShipmentDialogOpened,
} = useShipment(() => {
loadTabData()
loadDiffList()
})
const rules = reactive<FormRules<ShipmentForm>>({
shippingWay: [
{
required: true,
message: '请选择物流方式',
},
],
carriageName: [
{
required: true,
message: '请选择物流公司',
},
],
carriageAmount: [
{
required: true,
message: '请输入物流费用',
},
],
logisticsTracking: [
{
required: true,
message: '请输入物流跟踪号',
},
],
})
const logisticsCompanyList = ref<LogisticsData[]>([])
const getLogisticsList = async () => {
try {
const res = await getLogisticsCompanyList()
logisticsCompanyList.value = res.data
} catch (error) {
//showError(error)
}
}
const refreshProduct = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
try {
await showConfirm('是否刷新商品信息', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
} catch {
return
}
const ids = []
if (['IN_PRODUCTION', 'WAIT_SHIPMENT'].includes(status.value)) {
ids.push(
...selection.value.map(
(item: CardOrderData | PodProductList) => item.podOrderId as number,
),
)
} else {
ids.push(
...selection.value.map(
(item: CardOrderData | PodProductList) => item.id as number,
),
)
}
try {
const res = await refreshJMProductInfo(ids)
ElMessage({
message: res.message,
type: 'success',
offset: window.innerHeight / 2,
})
loadTabData()
loadDiffList()
} catch (e) {
// showError(e)
}
}
const openAll = (row: CardOrderData) => {
row.moreable = !row.moreable
}
// 表格和卡片的选中值:有两种约束
const selection = ref<(CardOrderData | PodProductList)[]>([])
const tableData = ref<(OrderData)[]>([])
const handleSelectionChange = (s: CardOrderData[]) => {
selection.value = s
}
// 确认生产
const confirmProduce = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
try {
await showConfirm('是否确认生产', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
} catch {
return
}
const ids = selection.value.map(
(item: CardOrderData | PodProductList) => item.id,
)
try {
const res = await confirmProductionOrder(ids)
loadDiffList()
await loadTabData()
ElMessage.success(res.message)
} catch (e) {
// showError(e)
}
}
const applyForReplacement = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
let input = {
value:''
}
try {
input = await ElMessageBox.prompt('', '补胚数量', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputPlaceholder: '请输入补胚数量',
inputPattern: /^\d+$/,
inputErrorMessage: '补胚数量不能为空且只能输入数字',
})
} catch {
return
}
const data = selection.value.map((item: CardOrderData | PodProductList) => {
return {
id: item.podOrderId,
productId: item.id,
factorySubOrderNumber: item.factorySubOrderNumber,
thirdSubOrderNumber: item.thirdSubOrderNumber,
replenishmentNum: Number(input.value),
}
})
try {
const res = await applyForReplenishmentApi(data)
await loadDiffList()
await loadTabData()
ElMessage.success(res.message)
} catch (e) {
// showError(e)
}
}
// 下载稿件
const downloadMaterial = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
const ids = []
if (['IN_PRODUCTION', 'WAIT_SHIPMENT'].includes(status.value)) {
ids.push(
...selection.value.map((item: CardOrderData | PodProductList) => item.id),
)
} else {
ids.push(
...selection.value.flatMap((item: CardOrderData | PodProductList) =>
Array.isArray(item.productList)
? item.productList.map((sub: PodProductList) => sub.id)
: [],
),
)
}
try {
const res = await downloadMaterialApi(ids)
const { data } = res
data.forEach((item: string) => {
const a = document.createElement('a')
a.href = filePath + item
a.download = item
a.target = '_blank'
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
})
} catch (e) {
// showError(e)
console.error(e)
}
}
const arraySpanMethod = ({ columnIndex }: SpanMethodProps) => {
if (columnIndex === 0 || columnIndex === 1) {
return [1, 1]
} else {
return [1, 6]
}
}
const copy = (text: string): void => {
const oInput = document.createElement('input')
oInput.value = text
oInput.style.position = 'absolute'
oInput.style.opacity = '0'
oInput.style.pointerEvents = 'none'
document.body.appendChild(oInput)
oInput.select()
if (document.execCommand('copy')) {
ElMessage.success('复制成功')
} else {
ElMessage.error('复制失败,请手动复制')
}
document.body.removeChild(oInput)
}
const onChangeCurrentRow = (item: ProductList) => {
currentRow.value = item
}
const cancelOrder = async (id: number) => {
try {
await showConfirm('是否确认取消', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
} catch {
return
}
try {
const res = await cancelOrderApi(id)
ElMessage({
message: res.message,
type: 'success',
offset: window.innerHeight / 2,
})
loadTabData()
loadDiffList()
} catch (e) {
// showError(e)
}
}
// 添加内部便签
const addInternalTag = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
ElMessageBox.prompt('', '添加内部便签', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputType: 'textarea',
inputPlaceholder: '请输入内部便签',
inputPattern: /.+/,
inputErrorMessage: '内部便签不能为空',
}).then(async ({ value }: { value: string }) => {
try {
const res = await addInternalTagApi(
selection.value.map((item: CardOrderData | PodProductList) =>
status.value === 'IN_PRODUCTION' || status.value === 'WAIT_SHIPMENT'
? (item.podOrderId as number)
: item.id,
),
value,
)
ElMessage.success(res.message)
loadTabData()
loadDiffList()
} catch (e) {
// showError(e)
}
})
}
const voidedBtn = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
ElMessageBox.prompt('', '作废', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputPlaceholder: '请输入作废原因',
inputPattern: /.+/,
inputErrorMessage: '作废原因不能为空',
}).then(async ({ value }: { value: string }) => {
try {
const res = await reasonInvalidationApi(
selection.value.map((item: CardOrderData | PodProductList) => item.id),
value,
)
ElMessage.success(res.message)
loadTabData()
loadDiffList()
} catch (e) {
// showError(e)
}
})
}
const printManuscript = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
const ids = []
if (['IN_PRODUCTION', 'WAIT_SHIPMENT'].includes(status.value)) {
ids.push(
...selection.value.map((item: CardOrderData | PodProductList) => item.id),
)
} else {
ids.push(
...selection.value.flatMap((item: CardOrderData | PodProductList) =>
Array.isArray(item.productList)
? item.productList.map((sub: PodProductList) => sub.id)
: [],
),
)
}
try {
await showConfirm('是否打印生产单', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
} catch {
return
}
const loading = ElLoading.service({
lock: true,
text: '加载中...',
background: 'rgba(0, 0, 0, 0.7)',
})
try {
const res = await printOrder(ids)
window.open(filePath + res.message)
} catch (e) {
// showError(e)
console.error(e)
} finally {
loading.close()
}
}
const exportManuscript = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
const ids = selection.value.map(
(item: CardOrderData | PodProductList) => item.id,
)
try {
await showConfirm('是否导出生产单', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
} catch {
return
}
const loading = ElLoading.service({
lock: true,
text: '加载中...',
background: 'rgba(0, 0, 0, 0.7)',
})
try {
const res = await exportOrder(ids, status.value)
window.open(filePath + res.message)
} catch (e) {
// showError(e)
console.error(e)
} finally {
loading.close()
}
}
const logVisible = ref(false)
const logList = ref<LogListData[]>([])
// 操作日志
const openLog = async (id?: number) => {
if (!id) return
try {
const res = await getLogList(id)
logList.value = res.data
logVisible.value = true
} catch (e) {
// showError(e)
console.error(e)
}
}
const handleUpdateRemark = (id: number, remark: string) => {
ElMessageBox.prompt('备注', '备注', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /.+/,
inputValue: remark,
inputErrorMessage: '请输入备注',
inputPlaceholder: '备注',
}).then(async ({ value = remark }) => {
try {
await updateRemarkApi(id, value as string)
ElMessage.success('操作成功')
loadDiffList()
} catch (e) {
console.error(e)
}
})
}
// 添加一个函数来安全地获取图片列表
const getSafeImages = (item: PodProductList | CardOrderData): cardImages[] => {
if (!item.images) return []
return item.images as cardImages[]
}
const listenerKeydown = (e: KeyboardEvent) => {
keyCode.value = e?.key
}
const applyEmbryoReplenishment = async (row: ProductList) => {
let res
try {
res = await ElMessageBox.prompt('', '补胚数量', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputPlaceholder: '请输入补胚数量',
inputPattern: /^\d+$/,
inputErrorMessage: '补胚数量不能为空且只能输入数字',
})
} catch {
return
}
const data = [
{
id: row.podOrderId,
productId: row.id,
factorySubOrderNumber: row.factorySubOrderNumber,
thirdSubOrderNumber: row.thirdSubOrderNumber,
replenishmentNum: Number(res.value),
},
]
try {
const res = await applyForReplenishmentApi(data)
loadDiffList()
await loadTabData()
ElMessage.success(res.message)
} catch (e) {
// showError(e)
}
}
const invalidOrder = async (row: ProductList) => {
ElMessageBox.prompt('', '作废', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputPlaceholder: '请输入作废原因',
inputPattern: /.+/,
inputErrorMessage: '作废原因不能为空',
}).then(async ({ value }: { value: string }) => {
try {
const res = await reasonInvalidationApi([row.id as number], value)
ElMessage.success(res.message)
loadTabData()
loadDiffList()
} catch (e) {
// showError(e)
}
})
}
const tableRightMenuVisible = ref(false)
const tableRightMenuRef = ref()
const onCopyChange = (type: string) => {
if (type === 'copy_shop_number') {
const shopNumberList = []
for (const item of tableData.value) {
if (item.productList) {
shopNumberList.push(...item.productList.map((sub) => sub.shopNumber))
}
}
copy(shopNumberList.join(','))
}
}
const handleContextMenu = (e: MouseEvent) => {
tableRightMenuVisible.value = true
tableRightMenuRef.value?.setRightMenuOptions({
contextMenuX: e.clientX,
contextMenuY: e.clientY,
})
}
const listenerClick = () => {
tableRightMenuVisible.value = false
}
onMounted(() => {
document.addEventListener('keydown', listenerKeydown)
document.addEventListener('click', listenerClick)
getLogisticsList()
loadTabData()
})
onBeforeUnmount(() => {
document.removeEventListener('keydown', listenerKeydown)
document.removeEventListener('click', listenerClick)
})
</script>
<style lang="scss" scoped>
.header-filter-form {
:deep(.el-form-item) {
margin-right: 14px;
margin-bottom: 10px;
}
}
.card-mode {
height: 629px;
padding-top: 10px;
overflow: auto;
flex: 1;
.card-list {
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-template-rows: max-content;
gap: 10px;
overflow: hidden;
.card-list_item {
border: 1px solid #eee;
border-top-left-radius: 10px;
background-color: #eee;
overflow: hidden;
cursor: pointer;
.base_sku {
background: rgba(255, 255, 255, 0.699);
font-size: 12px;
display: inline-block;
width: 100%;
box-sizing: border-box;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 3px 5px;
border-radius: 2px;
}
.flex-between {
display: flex;
justify-content: space-between;
align-items: center;
.images-position {
display: flex;
height: 30px;
gap: 10px;
padding: 10px 6px 0;
.item-image {
width: 30px;
height: 30px;
border: 1px solid #909399;
cursor: pointer;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
}
b {
margin-right: 5px;
font-size: 15px;
}
}
}
}
.no-data {
margin-top: 300px;
display: flex;
align-items: center;
justify-content: center;
color: #777;
}
}
.empty {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
color: #777;
overflow: hidden;
}
.tabs {
display: flex;
align-items: center;
gap: 10px;
border-bottom: 1px solid #f0f0f0;
height: 42px;
.tabs-node {
padding: 10px;
font-size: 14px;
color: #000;
cursor: pointer;
height: 40px;
}
.tabs-node:hover {
color: #409eff;
}
.tabs-node.tabs-node_active {
color: #409eff;
border-bottom: 2px solid #409eff;
font-weight: 600;
}
}
.expand-detail {
padding: 10px;
font-size: 14px;
color: #000;
.detail-item {
margin-bottom: 10px;
.label {
font-weight: 600;
}
.value {
color: #666;
}
}
}
.order-list-expand {
border-right: 1px solid #eee;
font-size: 14px;
color: #606266;
overflow: auto;
max-height: 600px;
}
.table-expand {
display: flex;
}
.order-list-expand_more {
text-align: center;
padding: 10px 0;
span {
cursor: pointer;
}
}
.order-list {
margin-top: 10px;
flex: 1;
:deep(.el-table__expand-icon > .el-icon) {
display: none;
}
:deep(.el-table__row) {
background-color: #f5f5f5;
}
:deep(.el-table__expanded-cell) {
padding: 0;
}
}
.order-detail {
display: flex;
font-size: 14px;
}
.order-detail_item {
flex: 1;
display: flex;
align-items: center;
.label {
color: #aaa;
margin-right: 6px;
}
.value {
color: #000;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.order-actual-payment {
width: 280px;
border-right: 1px solid #eee;
}
.order-memo {
width: 300px;
border-right: 1px solid #eee;
}
.order-time_info {
padding: 20px;
font-size: 14px;
}
.order-memo-item__content,
.order-memo-item__time {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.order-memo-info {
padding: 20px;
font-size: 14px;
}
.order-memo-item {
display: flex;
align-items: center;
line-height: 26px;
}
.order-memo-item div:not(:last-child) {
margin-right: 6px;
}
.order-time {
width: 300px;
border-right: 1px solid #eee;
}
.order-operate {
width: 100px;
}
.order-actual-payment_info {
font-size: 14px;
padding: 20px;
}
.order-operate_info {
padding: 20px;
:deep(.el-button) {
padding: 0;
font-size: 14px;
}
}
.header-search {
display: flex;
gap: 10px;
}
.dialog-footer {
text-align: center;
}
.order-detail_goods-info--content {
padding: 10px 0;
font-size: 14px;
:deep(.order-list-expand_item) {
padding: 10px 0;
}
}
.order-list-expand_item_info_title {
line-height: 26px;
display: flex;
align-items: center;
}
.order-list-expand_item_label {
margin-right: 6px;
}
.order-operate_info {
padding: 20px;
:deep(.el-button) {
padding: 0;
font-size: 14px;
}
}
.pagination{
display: flex;
align-items: center;
}
</style>
<template>
<div class="card flex-column h-100 overflow-hidden">
<div class="header-filter-form">
<ElForm :model="searchForm" size="default" inline>
<ElFormItem>
<el-select
v-model="searchForm.timeType"
style="width: 100px; margin-right: 5px"
clearable
placeholder="时间类型"
>
<el-option :value="1" label="创建时间"></el-option>
<el-option :value="2" label="确认时间"></el-option>
<el-option :value="3" label="完成时间"></el-option>
<!-- <el-option :value="4" label="发货时间"></el-option> -->
</el-select>
<el-date-picker
v-model="timeRange"
:default-time="[
new Date(0, 0, 0, 0, 0, 0),
new Date(0, 0, 0, 23, 59, 59),
]"
placeholder="收货人"
value-format="YYYY-MM-DD HH:mm:ss"
type="datetimerange"
style="width: 280px"
:shortcuts="pickerOptions.shortcuts"
start-placeholder="开始时间"
end-placeholder="结束时间"
clearable
>
</el-date-picker>
</ElFormItem>
<ElFormItem label="客户">
<el-select
v-model="searchForm.userMark"
clearable
filterable
style="width: 100px"
placeholder="客户"
>
<el-option v-for="item in userMarkList" :key="item" :value="item" :label="item"></el-option>
</el-select>
</ElFormItem>
<ElFormItem label="SKU">
<ElInput
v-model.trim="searchForm.sku"
placeholder=" SKU"
clearable
style="width: 130px"
></ElInput>
</ElFormItem>
<!-- <ElFormItem label="发货单号">
<ElInput
v-model="searchForm.shipmentNumber"
placeholder="发货单号"
clearable
style="width: 130px"
/>
</ElFormItem> -->
<ElFormItem label="生产单号">
<ElInput
v-model="searchForm.factorySubOrderNumber"
placeholder="定制生产单号"
clearable
style="width: 130px"
/>
</ElFormItem>
<ElFormItem label="订单号">
<ElInput
v-model="searchForm.factoryOrderNumber"
placeholder="定制订单号"
clearable
style="width: 130px"
/>
</ElFormItem>
<ElFormItem label="店铺单号">
<ElInput
v-model="searchForm.shopNumber"
placeholder="店铺单号"
clearable
style="width: 130px"
/>
</ElFormItem>
<ElFormItem label="内部标签">
<ElInput
v-model.trim="searchForm.internalMemo"
placeholder="内部标签"
clearable
style="width: 130px"
></ElInput>
</ElFormItem>
<ElFormItem label="排序">
<el-select
v-model="searchForm.order"
clearable
style="width: 80px"
placeholder="排序类型"
>
<el-option value="asc" label="正序"></el-option>
<el-option value="desc" label="倒序"></el-option>
</el-select>
</ElFormItem>
<ElFormItem label="定制类型">
<el-select
v-model="searchForm.customizedQuantity"
clearable
style="width: 100px"
placeholder="定制类型"
>
<el-option value="single" label="单面"></el-option>
<el-option value="multiple" label="多面"></el-option>
</el-select>
</ElFormItem>
<ElFormItem>
<ElButton type="primary" @click="loadDiffList">查询</ElButton>
</ElFormItem>
</ElForm>
</div>
<div class="header-filter-tab">
<div class="tabs">
<div
v-for="item in tabsNav"
:key="item.status"
class="tabs-node"
:class="item.status === status ? 'tabs-node_active' : ''"
@click="changeTab(item)"
>
<span class="tabs-node_label">{{ item.statusName }}</span>
<span class="tabs-node_count">{{ `(${item.quantity})` }}</span>
</div>
</div>
</div>
<div class="order-content flex-1 flex-column overflow-hidden mt-10">
<div style="margin-bottom: 10px">
<span v-if="status === 'TO_BE_CONFIRMED'" class="item">
<ElButton type="success" @click="confirmProduce">确认生产</ElButton>
</span>
<span v-if="status === 'IN_PRODUCTION'" class="item">
<ElButton type="success" dark @click="fastToProduction('快捷生产', 1)"
>快捷生产</ElButton
>
</span>
<span
v-if="
status === 'IN_PRODUCTION' ||
status === 'PART_SHIPPING'
"
class="item"
>
<ElButton type="primary" dark @click="printManuscript"
>打印生产单</ElButton
>
</span>
<!-- <span v-if="status === 'TO_BE_CONFIRMED'" class="item">-->
<!-- <ElButton type="success" dark @click="exportManuscript"-->
<!-- >导出生产单</ElButton-->
<!-- >-->
<!-- </span>-->
<span class="item">
<ElButton type="warning" @click="addInternalTag"
>添加内部标签</ElButton
>
</span>
<span
v-if="
status === 'TO_BE_CONFIRMED' ||
status === 'IN_PRODUCTION' ||
status === 'PART_SHIPPING'
"
class="item"
>
<ElButton type="warning" is-dark @click="downloadMaterial">
下载素材</ElButton
>
</span>
<span
v-if="
[
'TO_BE_CONFIRMED',
'IN_PRODUCTION',
'PART_SHIPPING',
'WAIT_SHIPMENT',
].includes(status)
"
class="item"
>
<ElButton type="primary" @click="refreshProduct"
>刷新商品信息</ElButton
>
</span>
<span
v-if="status === 'WAIT_SHIPMENT' || status === 'PART_SHIPPING'"
class="item"
>
<ElButton type="success" @click="confirmDelivery">发货</ElButton>
</span>
<span v-if="['TO_BE_CONFIRMED','IN_PRODUCTION'].includes(status)" class="item">
<ElButton type="danger" @click="voidedBtn">作废</ElButton>
</span>
<span v-if="status === 'IN_PRODUCTION'" class="item">
<ElButton type="warning" is-dark @click="applyForReplacement">
申请补胚</ElButton
>
</span>
</div>
<template
v-if="
[
'IN_PRODUCTION',
'TO_BE_CONFIRMED',
'WAIT_SHIPMENT',
'TO_BE_REPLENISHMENT',
'INVALID',
].includes(status)
"
>
<div
v-if="CardOrderList.length"
v-loading="loading"
element-loading-text="加载中..."
class="card-mode"
>
<div class="card-list">
<div
v-for="cardItem in CardOrderList"
:key="cardItem.id"
class="card-list_item"
@click="cardClick(cardItem)"
>
<CardWrapper
:card-item="cardItem"
:class="{ active: isSelectStatused(cardItem) }"
@contextmenu.prevent="(v) => rightClick(v, cardItem)"
>
<!-- <template #top_right> 工厂类型 </template> -->
<template #bottom_left>
<span
v-if="cardItem?.factorySubOrderNumber"
title="生产单号"
class="base_sku"
@click.stop="
copy(String(cardItem?.factorySubOrderNumber || ''))
"
>
{{ cardItem?.factorySubOrderNumber }}
</span>
</template>
<template #operations>
<Icon
name="caozuorizhi"
@click.stop="
openLog(Number(cardItem.podOrderId) || undefined)
"
>
<template #title>
<title>操作日志</title>
</template>
</Icon>
<Icon
name="chakanxiangqing"
@click.stop="openDetail(cardItem.id)"
>
<template #title>
<title>查看详情</title>
</template>
</Icon>
</template>
<template #images>
<div class="flex-between">
<div class="images-position">
<div
v-for="(item, index) in getSafeImages(cardItem)"
:key="index"
:title="
item?.ename
? item.ename === 'front'
? '正面图片'
: '反面图片'
: ''
"
:style="
currentImage === item?.image &&
currentId === cardItem.id
? 'border-color: red'
: ''
"
class="item-image"
@click="handleChangeImages(item, cardItem)"
>
<img :src="item?.image" height="28" />
</div>
</div>
<b
v-if="cardItem"
:style="{
color:
(Number(cardItem.customizedQuantity) || 0) > 1
? 'red'
: '#67C23A',
}"
>
{{
(Number(cardItem.customizedQuantity) || 0) > 1
? '多'
: '单'
}}
</b>
</div>
</template>
<template #info>
<div style="font-size: 12px; padding: 14px 5px 0">
<el-row class="el_row">
<el-col :span="14" :offset="0">
<el-tooltip
class="item"
effect="dark"
:content="cardItem?.baseSku"
placement="bottom"
>
<span
title="Base SKU"
style="
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
display: inline-block;
"
>
{{ cardItem?.baseSku }}
</span>
</el-tooltip>
</el-col>
<el-col
v-if="status === 'TO_BE_REPLENISHMENT'"
:span="10"
:offset="0"
style="text-align: right"
>
<el-tooltip
class="item"
effect="dark"
:content="'补胚数量'"
placement="bottom"
>
<span
>补胚数量:{{
cardItem?.replenishmentNum || '--'
}}</span
>
</el-tooltip>
</el-col>
<el-col
v-else
:span="10"
:offset="0"
style="text-align: right"
>
<span v-if="['INVALID','TO_BE_CONFIRMED'].includes(status)">
数量:{{ cardItem?.num }}
</span>
<template v-else>
<el-tooltip
v-if="status !== 'TO_BE_REPLENISHMENT'"
class="item"
effect="dark"
:content="
['TO_BE_REPLENISHMENT', 'IN_PRODUCTION'].includes(
status,
)
? '未生产数量'
: '已生产数量'
"
placement="bottom"
>
<span
>数量:{{
[
'TO_BE_REPLENISHMENT',
'IN_PRODUCTION',
].includes(status)
? cardItem?.notPassNum
: cardItem?.passNum
}}</span
>
</el-tooltip>
</template>
</el-col>
</el-row>
<el-row style="margin-top: 5px">
<el-col
:span="14"
:offset="0"
style="
white-space: nowrap;
display: flex;
align-items: center;
"
>
<span
title="Variant SKU"
style="
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
"
>
{{ cardItem?.variantSku }}
</span>
</el-col>
<el-col :span="10" :offset="0" style="text-align: right">
<el-tooltip
class="item"
effect="dark"
:content="'货号'"
placement="bottom"
>
<span
>货号:{{ cardItem?.supplierItemNo || '--' }}</span
>
</el-tooltip>
</el-col>
</el-row>
<el-row style="margin-top: 5px">
<el-col
:span="12"
:offset="0"
style="
white-space: nowrap;
display: flex;
align-items: center;
"
>
<span>工艺:</span>
<span
:title="String(cardItem?.process)"
style="
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
"
>
{{ cardItem?.process }}
</span>
</el-col>
<el-col
:span="12"
:offset="0"
style="white-space: nowrap; text-align: right"
>
<span
:title="`店铺单号:${cardItem?.shopNumber}`"
style="
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
"
>
{{ cardItem?.shopNumber }}
</span>
</el-col>
</el-row>
<el-row style="margin-top: 5px">
<el-col
:span="12"
:offset="0"
style="white-space: nowrap"
>
<span
:title="`第三方生产单号:${cardItem?.thirdSubOrderNumber}`"
style="
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
"
@click.stop="
copy(String(cardItem?.thirdSubOrderNumber || ''))
"
>
{{ cardItem?.thirdSubOrderNumber }}
</span>
</el-col>
<el-col :span="12" :offset="0" style="text-align: right">
<span title="期望交货时间">
{{ cardItem?.expectDeliveryTime }}
</span>
</el-col>
</el-row>
<el-row style="margin-top: 5px">
<el-col
:span="12"
:offset="0"
style="white-space: nowrap"
>
<span
:title="`第三方订单号:${cardItem?.thirdOrderNumber}`"
style="
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
"
@click.stop="
copy(String(cardItem?.thirdOrderNumber || ''))
"
>
{{ cardItem?.thirdOrderNumber }}
</span>
</el-col>
</el-row>
</div>
</template>
</CardWrapper>
</div>
</div>
</div>
<div v-else class="empty">暂无数据</div>
</template>
<div
v-else
ref="tableWrapperRef"
v-loading="loading"
element-loading-text="加载中..."
class="order-list flex-1 overflow-hidden"
>
<TableView
:paginated-data="tableData"
:columns="tableColumns"
:selectionable="true"
default-expand-all
:span-method="arraySpanMethod"
@selection-change="handleSelectionChange"
@contextmenu.prevent="handleContextMenu"
>
<template #expand="{ row }">
<div v-if="row.productList" class="table-expand">
<div
class="order-list-expand"
:style="{ width: `${thOrderDetailWidth + 50}px` }"
>
<ProductInfo :row="row" :status="status" :is-pod="true">
<template #operation="{ productItem }">
<div class="operation-item" title="添加备注">
<el-icon
class="icon"
style="color: #e6a23c"
@click="
handleUpdateRemark(
productItem.id,
productItem.remark || '',
)
"
><EditPen
/></el-icon>
</div>
<div
v-if="status === 'TO_BE_RECEIPT'"
class="operation-item"
>
<el-button
size="small"
type="warning"
@click="applyEmbryoReplenishment(productItem)"
>申请补胚</el-button
>
</div>
<div
v-if="
status === 'TO_BE_RECEIPT' ||
status === 'TO_BE_CONFIRMED'
"
class="operation-item"
>
<el-button
size="small"
type="danger"
@click="invalidOrder(productItem)"
>作废</el-button
>
</div>
</template>
</ProductInfo>
<template v-if="row.productList.length > 2">
<div class="order-list-expand_more">
<span @click="openAll(row)">
<template v-if="!row.moreable">
展开全部<strong style="color: red"
>({{ row.productList.length }})</strong
>条商品信息<el-icon style="vertical-align: middle"
><ArrowDown /></el-icon
></template>
<template v-else>
收起商品信息<el-icon style="vertical-align: middle"
><ArrowUp
/></el-icon>
</template>
</span>
</div>
</template>
</div>
<div class="order-actual-payment">
<div class="order-actual-payment_info">
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label">商品价:</span>
<span class="order-list-expand_item_value">{{
row.thirdProductAmount
}}</span>
</div>
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label">小计:</span>
<span class="order-list-expand_item_value">{{
row.totalAmount || '--'
}}</span>
</div>
<div
v-if="row.totolBuyNumber"
class="order-list-expand_item_info_title"
>
<span class="order-list-expand_item_value"
>{{ row.totolBuyNumber }}</span
>
</div>
</div>
</div>
<div class="order-memo">
<div class="order-memo-info">
<div
v-for="memo in row.internalMemoList || []"
:key="memo.id"
class="order-memo-item"
>
<div
v-if="memo.operatorEmployeeName"
class="order-memo-item__name"
>
<span>{{ memo.operatorEmployeeName || '' }}</span>
</div>
<div
v-if="memo.operatorTime"
class="order-memo-item__time"
:title="memo.operatorTime"
>
<span>{{ memo.operatorTime || '' }}</span>
</div>
<div
v-if="memo.content"
class="order-memo-item__content"
:title="memo.content"
>
<span>{{ memo.content || '' }}</span>
</div>
</div>
</div>
</div>
<div class="order-time">
<div class="order-time_info">
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label">创建时间:</span>
<span class="order-list-expand_item_value">{{
row.createTime || '--'
}}</span>
</div>
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label"
>期望交货时间:</span
>
<span class="order-list-expand_item_value">{{
row.expectDeliveryTime || '--'
}}</span>
</div>
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label">确认时间:</span>
<span class="order-list-expand_item_value">{{
row.startStockingTime || '--'
}}</span>
</div>
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label">完成时间:</span>
<span class="order-list-expand_item_value">{{
row.finishTime || '--'
}}</span>
</div>
</div>
</div>
<div class="order-operate">
<div class="order-operate_info">
<div
v-if="status === 'TO_BE_CONFIRMED'"
class="order-list-expand_item_info_title"
>
<ElButton text type="danger" @click="cancelOrder(row.id)"
>取消
</ElButton>
</div>
<div class="order-list-expand_item_info_title">
<ElButton text type="primary" @click="openLog(row.id)"
>操作日志
</ElButton>
</div>
</div>
</div>
</div>
</template>
<template #orderDetail="scope">
<div class="order-detail">
<div
:title="scope.row.factoryOrderNumber"
class="order-detail_item"
>
<span class="label">订单号:</span>
<span class="value">{{ scope.row.factoryOrderNumber }}</span>
</div>
<div
:title="scope.row.thirdOrderNumber"
class="order-detail_item"
>
<span class="label">第三方订单号:</span>
<span class="value" :title="scope.row.thirdOrderNumber">{{
scope.row.thirdOrderNumber || '--'
}}</span>
</div>
<!-- <div
:title="scope.row.manuscriptStatusStr"
class="order-detail_item"
>
<span class="label">稿件状态:</span>
<span class="value" :title="scope.row.manuscriptStatusStr">{{
scope.row.manuscriptStatusStr || '--'
}}</span>
</div> -->
<div :title="scope.row.lanshouName" class="order-detail_item">
<span class="label">收货人:</span>
<span class="value">{{ scope.row.lanshouName }}</span>
</div>
<div :title="scope.row.lanshouPhone" class="order-detail_item">
<span class="label">电话:</span>
<span class="value">{{ scope.row.lanshouPhone }}</span>
</div>
<div :title="scope.row.lanshouAddress" class="order-detail_item">
<span class="label">收货地址:</span>
<span class="value" :title="scope.row.lanshouAddress">{{
scope.row.lanshouRegion + scope.row.lanshouAddress
}}</span>
</div>
<div
v-if="scope.row.shipmentUid"
:title="scope.row.shipmentUid"
class="order-detail_item"
>
<span class="label">提货码:</span>
<span class="value" :title="scope.row.shipmentUid">{{
scope.row.shipmentUid
}}</span>
</div>
<div :title="scope.row.lanshouPost" class="order-detail_item">
<span class="label">邮编:</span>
<span class="value">{{ scope.row.lanshouPost }}</span>
</div>
</div>
</template>
</TableView>
</div>
<div class="pagination">
<div>
<span>已选择 <span style="color: red">{{selection.length}}</span> 条数据</span>
</div>
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:page-sizes="[100, 200, 300, 400]"
background
layout="total, sizes, prev, pager, next, jumper"
:total="total"
style="margin: 10px auto 10px; text-align: right"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
</div>
<el-dialog
v-model="shipmentVisible"
title="发货"
:close-on-click-modal="false"
width="1600PX"
top="6vh"
@opened="onShipmentDialogOpened"
>
<div class="header-search">
<el-input
ref="inputRef"
v-model="productionOrderNumber"
clearable
size="large"
placeholder="请输入生产单号"
@keydown.enter="searchShipmentByOrderNumber"
/>
<el-button
type="primary"
size="large"
@click="searchShipmentByOrderNumber"
>查询
</el-button>
</div>
<Shipment
ref="shipmentOrderRef"
v-loading="shipmentLoading"
:order-list="orderList"
:current-row="currentRow"
:is-pod="true"
@change-current-row="onChangeCurrentRow"
/>
<div class="shipment-logistics-info margin-top-20">
<ElForm ref="shipmentFormRef" :model="shipmentForm" :rules="rules">
<ElRow :gutter="20">
<ElCol :span="6">
<ElFormItem label="发货方式" prop="shippingWay">
<ElSelect
v-model="shipmentForm.shippingWay"
clearable
placeholder="请选择"
style="width: 100%"
>
<ElOption label="送货上门" value="1"></ElOption>
<ElOption label="快递" value="2"></ElOption>
</ElSelect>
</ElFormItem>
</ElCol>
<ElCol v-if="shipmentForm.shippingWay === '2'" :span="6">
<ElFormItem label="物流名称" prop="carriageName">
<ElSelect
v-model="shipmentForm.carriageName"
filterable
placeholder="请输入关键字"
clearable
style="width: 100%"
>
<ElOption
v-for="item in logisticsCompanyList"
:key="item.id"
:value="item.name"
></ElOption>
</ElSelect>
</ElFormItem>
</ElCol>
<ElCol v-if="shipmentForm.shippingWay === '2'" :span="6">
<ElFormItem label="物流跟踪号" prop="logisticsTracking">
<ElInput
v-model="shipmentForm.logisticsTracking"
placeholder="请输入物流跟踪号"
clearable
style="width: 100%"
/>
</ElFormItem>
</ElCol>
<ElCol v-if="shipmentForm.shippingWay === '2'" :span="6">
<ElFormItem label="物流费用" prop="carriageAmount">
<ElInput
v-model="shipmentForm.carriageAmount"
clearable
placeholder="请输入物流费用"
style="width: 100%"
/>
</ElFormItem>
</ElCol>
</ElRow>
</ElForm>
</div>
<template #footer>
<div class="dialog-footer">
<el-button size="large" @click="shipmentVisible = false"
>取消
</el-button>
<el-button size="large" type="primary" @click="saveShipment"
>发货
</el-button>
</div>
</template>
</el-dialog>
<el-dialog
v-model="logVisible"
title="操作日志"
width="1000px"
:close-on-click-modal="false"
>
<LogList :log-list="logList" />
</el-dialog>
<el-dialog
v-model="countVisible"
title="数据统计"
width="400px"
:close-on-click-modal="false"
>
<p>
基版 <b>{{ cardItem?.baseSku }}</b> 的统计数量为:<b> {{ count }}</b>
</p>
</el-dialog>
<right-menu
ref="rightMenuRef"
:show_copy_shop_number="['IN_PRODUCTION', 'WAIT_SHIPMENT'].includes(status)"
@change="rightChange"
/>
<fastProduction
v-model:detailVisible="detailVisible"
:title="fastTitle"
:is-jmpod="'JMPOD'"
:type="fastType"
:detail-data="detailData"
:current-status="status"
@on-success="handleSuccess"
@close="fastClose"
></fastProduction>
<table-right-menu
ref="tableRightMenuRef"
:table-right-menu-visible="tableRightMenuVisible"
@on-copy-change="onCopyChange"
/>
</template>
<script setup lang="tsx">
// refreshJMProductInfo,reasonInvalidationApi,
import RightMenu from './rightMenu.vue'
import {
getOrderTabData,
getOrderList,
confirmProduct,
cancelOrderApi,
downloadMaterialApi,
addInternalTagApi,
printOrder,
getLogList,
updateRemarkApi,
getCardOrderList,
getOrderDetail,
getInProductionCount,
getWaitShipmentCount,
refreshJMProductInfo,
reasonInvalidationApi,
applyForReplenishmentApi,
} from '@/api/podOrder'
import TableView from '@/components/TableView.vue'
import {
ProductList,
LogisticsData,
OrderData,
ShipmentForm,
} from '@/types/api/order'
import fastProduction from '../fastProduction.vue'
import CardWrapper from '@/components/CardPods.vue'
import { CustomColumn } from '@/types/table'
import { useValue } from '@/utils/hooks/useValue'
import { computed, onBeforeUnmount, onMounted, reactive, ref } from 'vue'
import dayjs from 'dayjs'
import useElTableColumnWidth from '@/utils/hooks/useElTableColumnWidth'
import ProductInfo from '../ProductInfo.vue'
import { SpanMethodProps } from '@/types/api/order'
import useShipment from '../hook/usePodShipment'
import Shipment from '../Shipment.vue'
import {
SearchForm,
Tab,
LogListData,
PodProductList,
cardImages,
imageAryInter,
CardOrderData,
} from '@/types/api/podOrder'
import { ArrowUp, ArrowDown, EditPen } from '@element-plus/icons-vue'
import { getLogisticsCompanyList,getUserMarkList } from '@/api/common'
import { ElButton, type FormRules } from 'element-plus'
import { showConfirm } from '@/utils/ui'
import { filePath } from '@/api/axios'
import LogList from '@/components/LogList.vue'
const tableRef = ref()
const loading = ref(false)
const currentPage = ref(1)
const pageSize = ref(100)
const total = ref(0)
const countVisible = ref(false)
const keyCode = ref('')
const cardItem = ref<PodProductList | CardOrderData>()
const rightMenuRef = ref()
const userMarkList = ref<string[]>([])
const count = ref<number>(0)
const rightClick = (e: MouseEvent, item: PodProductList | CardOrderData) => {
cardItem.value = item
rightMenuRef.value.setPosition({
x: e.clientX,
y: e.clientY,
cardItem: e.clientY,
el: e,
})
}
const handleSizeChange = (size:number)=>{
pageSize.value = size
loadDiffList()
}
const handleCurrentChange = (page:number)=>{
currentPage.value = page
loadDiffList()
}
const rightChange = async (code: string) => {
const flag = ['IN_PRODUCTION', 'WAIT_SHIPMENT'].includes(status.value)
if (code === 'check_all') {
if (flag) {
selection.value = JSON.parse(JSON.stringify(CardOrderList.value))
} else {
if (tableRef.value && tableRef.value?.tableRef) {
tableRef.value?.tableRef.toggleAllSelection()
}
// selection.value = JSON.parse(JSON.stringify(tableData.value))
}
} else if (code === 'clear_check') {
selection.value = []
tableRef.value?.tableRef.toggleAllSelection()
} else if (code === 'copy_code') {
const str = selection.value
.map((item) => item.factorySubOrderNumber || item.factoryOrderNumber)
.join()
navigator.clipboard.writeText(str)
ElMessage.success('复制成功')
} else if (code === 'copy_shopNumber') {
const str = selection.value.map((item) => item.shopNumber).join()
navigator.clipboard.writeText(str)
ElMessage.success('复制成功')
} else if (code === 'count') {
countVisible.value = true
let res
if (status.value === 'WAIT_SHIPMENT') {
res = await getWaitShipmentCount(
cardItem.value?.productionFileId,
cardItem.value?.baseSku,
)
} else if (status.value === 'IN_PRODUCTION') {
res = await getInProductionCount(
cardItem.value?.productionFileId,
cardItem.value?.baseSku,
)
}
count.value = (res?.data || 0) as number
}
}
// 日期工具函数
const getDateRange = (days = 0, type: 'past' | 'future' = 'past') => {
const end = dayjs()
const start =
type === 'past' ? end.subtract(days, 'day') : end.add(days, 'day')
return [start.startOf('day').toDate(), end.endOf('day').toDate()]
}
const getMonthRange = (months = 0, type: 'past' | 'future' = 'past') => {
const now = dayjs()
const start =
type === 'past' ? now.subtract(months, 'month') : now.add(months, 'month')
return [start.startOf('month').toDate(), start.endOf('month').toDate()]
}
const getWeekRange = (weeks = 0, type: 'past' | 'future' = 'past') => {
const now = dayjs()
const start =
type === 'past' ? now.subtract(weeks, 'week') : now.add(weeks, 'week')
return [start.startOf('week').toDate(), start.endOf('week').toDate()]
}
const pickerOptions = {
shortcuts: [
{
text: '今日',
value: () => getDateRange(0),
},
{
text: '昨天',
value: () => getDateRange(1),
},
{
text: '最近7天',
value: () => getDateRange(6),
},
{
text: '最近14天',
value: () => getDateRange(13),
},
{
text: '最近30天',
value: () => getDateRange(29),
},
{
text: '本周',
value: () => getWeekRange(0),
},
{
text: '上周',
value: () => getWeekRange(1),
},
{
text: '本月',
value: () => getMonthRange(0),
},
{
text: '上月',
value: () => getMonthRange(1),
},
{
text: '历史',
value: () => {
const end = dayjs().endOf('day').toDate()
const start = dayjs('2000-01-01').startOf('day').toDate()
return [start, end]
},
},
],
}
const timeRange = ref<string[]>([])
const tabsNav = ref<Tab[]>()
const status = ref('TO_BE_CONFIRMED')
const [tableWrapperRef, thOrderDetailWidth, updateColumnWidth] =
useElTableColumnWidth('table th.th-order-detail')
const loadTabData = async () => {
try {
const res = await getOrderTabData()
tabsNav.value = res.data
} catch (error) {
// showError(error)
}
}
const handleSuccess = () => {
loadTabData()
loadDiffList()
}
// 查看详情
const openDetail = async (id: number) => {
try {
const res = await getOrderDetail(id)
if (res.code == 200) {
if (res.data.imageAry) {
res.data.imageAry = JSON.parse(res.data.imageAry as string)
}
detailData.value = res.data || {}
detailVisible.value = true
fastTitle.value = '查看详情'
fastType.value = 0
}
} catch (e) {
//showError(e)
}
}
const CardOrderList = ref<(PodProductList | CardOrderData)[]>([])
const loadCardList = async () => {
try {
const res = await getCardOrderList(
{
...searchForm.value,
status: status.value,
timeType: searchForm.value.timeType,
startTime:
timeRange.value && timeRange.value.length > 0
? timeRange.value[0]
: null,
endTime:
timeRange.value && timeRange.value.length > 0
? timeRange.value[1]
: null,
},
currentPage.value,
pageSize.value,
)
CardOrderList.value = res.data.records.map((item: PodProductList) => {
if (!item.imageAry) {
const images = []
if (typeof item.variantImage === 'string') {
images.push({
ename: 'front',
cname: '正面',
image: item.variantImage,
})
}
if (typeof item.negativeImage === 'string') {
images.push({
ename: 'back',
cname: '反面',
image: item.negativeImage,
})
}
item.images = images
} else {
if (item.imageAry) {
const images = JSON.parse(item.imageAry as string)
if (Array.isArray(images)) {
item.images = images.map((e: imageAryInter) => {
return {
ename: '',
cname: '',
image: e.url,
}
})
}
}
}
return item
})
total.value = res.data.total
} catch (error) {
// showError(error)
}
}
const loadOrderList = async () => {
try {
const res = await getOrderList({
...searchForm.value,
status: status.value,
timeType: searchForm.value.timeType,
startTime:
timeRange.value && timeRange.value.length > 0
? timeRange.value[0]
: null,
endTime:
timeRange.value && timeRange.value.length > 0
? timeRange.value[1]
: null
},currentPage.value,pageSize.value)
tableData.value = res.data.records
total.value = res.data.total
} catch (error) {
// showError(error)
}
}
const currentImage = ref('')
const currentId = ref(-1)
const changeImages = (
item: cardImages,
data: PodProductList | CardOrderData,
) => {
currentImage.value = item.image
// data.designId = item.designId
currentId.value = data.id
data.variantImage = item.image
// if (data.productList) {
// data.productList[0].variantImage = item.image
// }
}
// 包装函数,用于处理类型转换
const handleChangeImages = (
item: cardImages,
data: PodProductList | CardOrderData,
) => {
changeImages(item as cardImages, data)
}
const fastTitle = ref('')
const detailData = ref({})
const detailVisible = ref(false)
const fastType = ref<number>(-1)
const fastToProduction = (title: string, type: number) => {
detailData.value = {}
detailVisible.value = true
fastTitle.value = title
fastType.value = type
}
const cardClick = (data: PodProductList | CardOrderData) => {
const status = isSelectStatused(data)
if (keyCode.value === 'Shift') {
if (selection.value.length) {
const startIndex = CardOrderList.value.findIndex(
(el) => el.id === selection.value[0].id,
)
const endIndex = CardOrderList.value.findIndex((el) => el.id === data.id)
selection.value = []
for (let k = startIndex; k <= endIndex; k++) {
selection.value.push(JSON.parse(JSON.stringify(CardOrderList.value[k])))
}
}
}
if (status) {
selection.value = selection.value.filter(
(item: CardOrderData | PodProductList) => item.id !== data.id,
)
} else {
selection.value.push(data as CardOrderData)
}
}
const isSelectStatused = (data: PodProductList | CardOrderData) => {
const index = selection.value.findIndex(
(item: CardOrderData | PodProductList) => item.id === data.id,
)
return index !== -1
}
const changeTab = (item: Tab) => {
status.value = item.status ?? ''
currentPage.value = 1
pageSize.value = 100
selection.value = []
searchForm.value.timeType = null
loading.value = false
loadDiffList()
}
const fastClose = () => {
if (fastType.value !== 0) {
loadTabData()
}
detailVisible.value = false
}
// 根据不同状态调用不同接口
const loadDiffList = async () => {
if (
[
'IN_PRODUCTION',
'WAIT_SHIPMENT',
'TO_BE_REPLENISHMENT',
'TO_BE_CONFIRMED',
'INVALID',
].includes(status.value)
) {
await loadCardList()
} else {
await loadOrderList()
updateColumnWidth()
}
selection.value = []
}
const [searchForm] = useValue<SearchForm>({
timeType: null,
shopNumber: '',
userMark: '',
customizedQuantity: '',
order: 'desc',
})
const tableColumns = computed<CustomColumn<CardOrderData[]>>(() => {
return [
{
type: 'expand',
align: 'center',
slot: 'expand',
width: 1,
},
{
label: '订单详情',
key: 'id',
minWidth: 800,
slot: 'orderDetail',
className: 'th-order-detail',
showOverflowTooltip: true,
},
{
label: '实付款',
key: '',
width: 280,
},
{
label: '内部便签',
key: 'customerName',
width: 300,
showOverflowTooltip: true,
},
{
label: '时间',
key: 'status',
width: 300,
align: 'center',
},
{
label: '操作',
key: 'status',
width: 100,
align: 'center',
},
]
})
// const {
// loading,
// currentPage,
// pageSize,
// total,
// data: tableData,
// refresh: search,
// onCurrentPageChange: handleCurrentChange,
// onPageSizeChange: handleSizeChange,
// } = usePageList<OrderData | CardOrderData>({
// query: async (page, pageSize) => {
// const commonParams = {
// ...searchForm.value,
// status: status.value,
// timeType: searchForm.value.timeType,
// startTime:
// timeRange.value && timeRange.value.length > 0
// ? timeRange.value[0]
// : null,
// endTime:
// timeRange.value && timeRange.value.length > 0
// ? timeRange.value[1]
// : null,
// }
// // 动态选择接口
// const fetchData =
// status.value === 'IN_PRODUCTION' ? getCardOrderList : getOrderList
// return fetchData(commonParams, page, pageSize).then(
// (res) => {
// if([
// 'IN_PRODUCTION',
// 'WAIT_SHIPMENT',
// 'TO_BE_REPLENISHMENT',
// 'INVALID',
// ].includes(status.value)){
// CardOrderList.value = res.data.records as PodProductList[]
// }else{
// tableData.value = res.data.records
// }
// },
// ) as never
// },
// })
// 发货
const {
shipmentFormRef,
productionOrderNumber,
shipmentVisible,
inputRef,
shipmentForm,
currentRow,
shipmentLoading,
orderList,
shipmentOrderRef,
searchShipmentByOrderNumber,
saveShipment,
confirmDelivery,
onShipmentDialogOpened,
} = useShipment(() => {
loadTabData()
loadDiffList()
})
const rules = reactive<FormRules<ShipmentForm>>({
shippingWay: [
{
required: true,
message: '请选择物流方式',
},
],
carriageName: [
{
required: true,
message: '请选择物流公司',
},
],
carriageAmount: [
{
required: true,
message: '请输入物流费用',
},
],
logisticsTracking: [
{
required: true,
message: '请输入物流跟踪号',
},
],
})
const logisticsCompanyList = ref<LogisticsData[]>([])
const getLogisticsList = async () => {
try {
const res = await getLogisticsCompanyList()
logisticsCompanyList.value = res.data
} catch (error) {
//showError(error)
}
}
const refreshProduct = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
try {
await showConfirm('是否刷新商品信息', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
} catch {
return
}
const ids = []
if (['IN_PRODUCTION','TO_BE_CONFIRMED', 'WAIT_SHIPMENT'].includes(status.value)) {
ids.push(
...selection.value.map(
(item: CardOrderData | PodProductList) => item.podOrderId as number,
),
)
} else {
ids.push(
...selection.value.map(
(item: CardOrderData | PodProductList) => item.id as number,
),
)
}
try {
const res = await refreshJMProductInfo(ids)
ElMessage({
message: res.message,
type: 'success',
offset: window.innerHeight / 2,
})
loadTabData()
loadDiffList()
} catch (e) {
// showError(e)
}
}
const openAll = (row: CardOrderData) => {
row.moreable = !row.moreable
}
// 表格和卡片的选中值:有两种约束
const selection = ref<(CardOrderData | PodProductList)[]>([])
const tableData = ref<(OrderData)[]>([])
const handleSelectionChange = (s: CardOrderData[]) => {
selection.value = s
}
// 确认生产
const confirmProduce = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
try {
await showConfirm('是否确认生产', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
} catch {
return
}
const ids = selection.value.map(
(item: CardOrderData | PodProductList) => item.id,
)
try {
const res = await confirmProduct(ids)
await loadDiffList()
await loadTabData()
ElMessage.success(res.message)
} catch (e) {
// showError(e)
}
}
const applyForReplacement = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
let input = {
value:''
}
try {
input = await ElMessageBox.prompt('', '补胚数量', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputPlaceholder: '请输入补胚数量',
inputPattern: /^\d+$/,
inputErrorMessage: '补胚数量不能为空且只能输入数字',
})
} catch {
return
}
const data = selection.value.map((item: CardOrderData | PodProductList) => {
return {
id: item.podOrderId,
productId: item.id,
factorySubOrderNumber: item.factorySubOrderNumber,
thirdSubOrderNumber: item.thirdSubOrderNumber,
replenishmentNum: Number(input.value),
}
})
try {
const res = await applyForReplenishmentApi(data)
await loadDiffList()
await loadTabData()
ElMessage.success(res.message)
} catch (e) {
// showError(e)
}
}
// 下载稿件
const downloadMaterial = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
const ids = []
if (['IN_PRODUCTION', 'TO_BE_CONFIRMED', 'WAIT_SHIPMENT'].includes(status.value)) {
ids.push(
...selection.value.map((item: CardOrderData | PodProductList) => item.id),
)
} else {
ids.push(
...selection.value.flatMap((item: CardOrderData | PodProductList) =>
Array.isArray(item.productList)
? item.productList.map((sub: PodProductList) => sub.id)
: [],
),
)
}
try {
const res = await downloadMaterialApi(ids)
const { data } = res
data.forEach((item: string) => {
const a = document.createElement('a')
a.href = filePath + item
a.download = item
a.target = '_blank'
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
})
} catch (e) {
// showError(e)
console.error(e)
}
}
const arraySpanMethod = ({ columnIndex }: SpanMethodProps) => {
if (columnIndex === 0 || columnIndex === 1) {
return [1, 1]
} else {
return [1, 6]
}
}
const copy = (text: string): void => {
const oInput = document.createElement('input')
oInput.value = text
oInput.style.position = 'absolute'
oInput.style.opacity = '0'
oInput.style.pointerEvents = 'none'
document.body.appendChild(oInput)
oInput.select()
if (document.execCommand('copy')) {
ElMessage.success('复制成功')
} else {
ElMessage.error('复制失败,请手动复制')
}
document.body.removeChild(oInput)
}
const onChangeCurrentRow = (item: ProductList) => {
currentRow.value = item
}
const cancelOrder = async (id: number) => {
try {
await showConfirm('是否确认取消', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
} catch {
return
}
try {
const res = await cancelOrderApi(id)
ElMessage({
message: res.message,
type: 'success',
offset: window.innerHeight / 2,
})
await loadTabData()
await loadDiffList()
} catch (e) {
// showError(e)
}
}
// 添加内部便签
const addInternalTag = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
ElMessageBox.prompt('', '添加内部便签', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputType: 'textarea',
inputPlaceholder: '请输入内部便签',
inputPattern: /.+/,
inputErrorMessage: '内部便签不能为空',
}).then(async ({ value }: { value: string }) => {
try {
const res = await addInternalTagApi(
selection.value.map((item: CardOrderData | PodProductList) =>
status.value === 'IN_PRODUCTION' || status.value === 'WAIT_SHIPMENT'
? (item.podOrderId as number)
: item.id,
),
value,
)
ElMessage.success(res.message)
loadTabData()
loadDiffList()
} catch (e) {
// showError(e)
}
})
}
const voidedBtn = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
ElMessageBox.prompt('', '作废', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputPlaceholder: '请输入作废原因',
inputPattern: /.+/,
inputErrorMessage: '作废原因不能为空',
}).then(async ({ value }: { value: string }) => {
try {
const res = await reasonInvalidationApi(
selection.value.map((item: CardOrderData | PodProductList) => item.id),
value,
)
ElMessage.success(res.message)
loadTabData()
loadDiffList()
} catch (e) {
// showError(e)
}
})
}
const printManuscript = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
const ids = []
if (['IN_PRODUCTION', 'WAIT_SHIPMENT'].includes(status.value)) {
ids.push(
...selection.value.map((item: CardOrderData | PodProductList) => item.id),
)
} else {
ids.push(
...selection.value.flatMap((item: CardOrderData | PodProductList) =>
Array.isArray(item.productList)
? item.productList.map((sub: PodProductList) => sub.id)
: [],
),
)
}
try {
await showConfirm('是否打印生产单', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
} catch {
return
}
const loading = ElLoading.service({
lock: true,
text: '加载中...',
background: 'rgba(0, 0, 0, 0.7)',
})
try {
const res = await printOrder(ids)
window.open(filePath + res.message)
} catch (e) {
// showError(e)
console.error(e)
} finally {
loading.close()
}
}
// const exportManuscript = async () => {
// if (selection.value.length === 0) {
// return ElMessage({
// message: '请选择订单',
// type: 'warning',
// offset: window.innerHeight / 2,
// })
// }
//
// const ids = selection.value.map(
// (item: CardOrderData | PodProductList) => item.id,
// )
// try {
// await showConfirm('是否导出生产单', {
// confirmButtonText: '确认',
// cancelButtonText: '取消',
// type: 'warning',
// })
// } catch {
// return
// }
// const loading = ElLoading.service({
// lock: true,
// text: '加载中...',
// background: 'rgba(0, 0, 0, 0.7)',
// })
// try {
// const res = await exportOrder(ids, status.value)
// window.open(filePath + res.message)
// } catch (e) {
// // showError(e)
// console.error(e)
// } finally {
// loading.close()
// }
// }
const logVisible = ref(false)
const logList = ref<LogListData[]>([])
// 操作日志
const openLog = async (id?: number) => {
if (!id) return
try {
const res = await getLogList(id)
logList.value = res.data
logVisible.value = true
} catch (e) {
// showError(e)
console.error(e)
}
}
const handleUpdateRemark = (id: number, remark: string) => {
ElMessageBox.prompt('备注', '备注', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /.+/,
inputValue: remark,
inputErrorMessage: '请输入备注',
inputPlaceholder: '备注',
}).then(async ({ value = remark }) => {
try {
await updateRemarkApi(id, value as string)
ElMessage.success('操作成功')
await loadDiffList()
} catch (e) {
console.error(e)
}
})
}
// 添加一个函数来安全地获取图片列表
const getSafeImages = (item: PodProductList | CardOrderData): cardImages[] => {
if (!item.images) return []
return item.images as cardImages[]
}
const listenerKeydown = (e: KeyboardEvent) => {
keyCode.value = e?.key
}
const applyEmbryoReplenishment = async (row: ProductList) => {
let res
try {
res = await ElMessageBox.prompt('', '补胚数量', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputPlaceholder: '请输入补胚数量',
inputPattern: /^\d+$/,
inputErrorMessage: '补胚数量不能为空且只能输入数字',
})
} catch {
return
}
const data = [
{
id: row.podOrderId,
productId: row.id,
factorySubOrderNumber: row.factorySubOrderNumber,
thirdSubOrderNumber: row.thirdSubOrderNumber,
replenishmentNum: Number(res.value),
},
]
try {
const res = await applyForReplenishmentApi(data)
await loadDiffList()
await loadTabData()
ElMessage.success(res.message)
} catch (e) {
// showError(e)
}
}
const invalidOrder = async (row: ProductList) => {
ElMessageBox.prompt('', '作废', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputPlaceholder: '请输入作废原因',
inputPattern: /.+/,
inputErrorMessage: '作废原因不能为空',
}).then(async ({ value }: { value: string }) => {
try {
const res = await reasonInvalidationApi([row.id as number], value)
ElMessage.success(res.message)
loadTabData()
loadDiffList()
} catch (e) {
// showError(e)
}
})
}
const tableRightMenuVisible = ref(false)
const tableRightMenuRef = ref()
const onCopyChange = (type: string) => {
if (type === 'copy_shop_number') {
const shopNumberList = []
for (const item of tableData.value) {
if (item.productList) {
shopNumberList.push(...item.productList.map((sub) => sub.shopNumber))
}
}
copy(shopNumberList.join(','))
}
}
const handleContextMenu = (e: MouseEvent) => {
tableRightMenuVisible.value = true
tableRightMenuRef.value?.setRightMenuOptions({
contextMenuX: e.clientX,
contextMenuY: e.clientY,
})
}
const listenerClick = () => {
tableRightMenuVisible.value = false
}
const getUserMark = async () => {
try {
const res = await getUserMarkList()
userMarkList.value = res.data
} catch (error) {
//showError(error)
}
}
onMounted(async () => {
document.addEventListener('keydown', listenerKeydown)
document.addEventListener('click', listenerClick)
await loadTabData()
getUserMark()
getLogisticsList()
loadDiffList()
})
onBeforeUnmount(() => {
document.removeEventListener('keydown', listenerKeydown)
document.removeEventListener('click', listenerClick)
})
</script>
<style lang="scss" scoped>
.header-filter-form {
:deep(.el-form-item) {
margin-right: 14px;
margin-bottom: 10px;
}
}
.card-mode {
height: 629px;
padding-top: 10px;
overflow: auto;
flex: 1;
.card-list {
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-template-rows: max-content;
gap: 10px;
overflow: hidden;
.card-list_item {
border: 1px solid #eee;
border-top-left-radius: 10px;
background-color: #eee;
overflow: hidden;
cursor: pointer;
.base_sku {
background: rgba(255, 255, 255, 0.699);
font-size: 12px;
display: inline-block;
width: 100%;
box-sizing: border-box;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 3px 5px;
border-radius: 2px;
}
.flex-between {
display: flex;
justify-content: space-between;
align-items: center;
.images-position {
display: flex;
height: 30px;
gap: 10px;
padding: 10px 6px 0;
.item-image {
width: 30px;
height: 30px;
border: 1px solid #909399;
cursor: pointer;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
}
b {
margin-right: 5px;
font-size: 15px;
}
}
}
}
.no-data {
margin-top: 300px;
display: flex;
align-items: center;
justify-content: center;
color: #777;
}
}
.empty {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
color: #777;
overflow: hidden;
}
.tabs {
display: flex;
align-items: center;
gap: 10px;
border-bottom: 1px solid #f0f0f0;
height: 42px;
.tabs-node {
padding: 10px;
font-size: 14px;
color: #000;
cursor: pointer;
height: 40px;
}
.tabs-node:hover {
color: #409eff;
}
.tabs-node.tabs-node_active {
color: #409eff;
border-bottom: 2px solid #409eff;
font-weight: 600;
}
}
.expand-detail {
padding: 10px;
font-size: 14px;
color: #000;
.detail-item {
margin-bottom: 10px;
.label {
font-weight: 600;
}
.value {
color: #666;
}
}
}
.order-list-expand {
border-right: 1px solid #eee;
font-size: 14px;
color: #606266;
overflow: auto;
max-height: 600px;
}
.table-expand {
display: flex;
}
.order-list-expand_more {
text-align: center;
padding: 10px 0;
span {
cursor: pointer;
}
}
.order-list {
margin-top: 10px;
flex: 1;
:deep(.el-table__expand-icon > .el-icon) {
display: none;
}
:deep(.el-table__row) {
background-color: #f5f5f5;
}
:deep(.el-table__expanded-cell) {
padding: 0;
}
}
.order-detail {
display: flex;
font-size: 14px;
}
.order-detail_item {
flex: 1;
display: flex;
align-items: center;
.label {
color: #aaa;
margin-right: 6px;
}
.value {
color: #000;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.order-actual-payment {
width: 280px;
border-right: 1px solid #eee;
}
.order-memo {
width: 300px;
border-right: 1px solid #eee;
}
.order-time_info {
padding: 20px;
font-size: 14px;
}
.order-memo-item__content,
.order-memo-item__time {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.order-memo-info {
padding: 20px;
font-size: 14px;
}
.order-memo-item {
display: flex;
align-items: center;
line-height: 26px;
}
.order-memo-item div:not(:last-child) {
margin-right: 6px;
}
.order-time {
width: 300px;
border-right: 1px solid #eee;
}
.order-operate {
width: 100px;
}
.order-actual-payment_info {
font-size: 14px;
padding: 20px;
}
.order-operate_info {
padding: 20px;
:deep(.el-button) {
padding: 0;
font-size: 14px;
}
}
.header-search {
display: flex;
gap: 10px;
}
.dialog-footer {
text-align: center;
}
.order-detail_goods-info--content {
padding: 10px 0;
font-size: 14px;
:deep(.order-list-expand_item) {
padding: 10px 0;
}
}
.order-list-expand_item_info_title {
line-height: 26px;
display: flex;
align-items: center;
}
.order-list-expand_item_label {
margin-right: 6px;
}
.order-operate_info {
padding: 20px;
:deep(.el-button) {
padding: 0;
font-size: 14px;
}
}
.pagination{
display: flex;
align-items: center;
}
</style>
<template>
<div class="card flex-column h-100 overflow-hidden">
<div class="header-filter-form">
<ElForm :model="searchForm" size="default" inline>
<ElFormItem>
<el-select
v-model="searchForm.timeType"
style="width: 100px; margin-right: 5px"
clearable
placeholder="时间类型"
>
<el-option :value="1" label="创建时间"></el-option>
<el-option :value="2" label="确认时间"></el-option>
<el-option :value="3" label="完成时间"></el-option>
<!-- <el-option :value="4" label="发货时间"></el-option> -->
</el-select>
<el-date-picker
v-model="timeRange"
:default-time="[
new Date(0, 0, 0, 0, 0, 0),
new Date(0, 0, 0, 23, 59, 59),
]"
placeholder="收货人"
value-format="YYYY-MM-DD HH:mm:ss"
type="datetimerange"
style="width: 280px"
:shortcuts="pickerOptions.shortcuts"
start-placeholder="开始时间"
end-placeholder="结束时间"
clearable
>
</el-date-picker>
</ElFormItem>
<ElFormItem label="SKU">
<ElInput
v-model.trim="searchForm.sku"
placeholder=" SKU"
clearable
style="width: 130px"
></ElInput>
</ElFormItem>
<!-- <ElFormItem label="发货单号">
<ElInput
v-model="searchForm.shipmentNumber"
placeholder="发货单号"
clearable
style="width: 130px"
/>
</ElFormItem> -->
<ElFormItem label="生产单号">
<ElInput
v-model="searchForm.factorySubOrderNumber"
placeholder="定制生产单号"
clearable
style="width: 130px"
/>
</ElFormItem>
<ElFormItem label="订单号">
<ElInput
v-model="searchForm.factoryOrderNumber"
placeholder="定制订单号"
clearable
style="width: 130px"
/>
</ElFormItem>
<ElFormItem label="店铺单号">
<ElInput
v-model="searchForm.shopNumber"
placeholder="店铺单号"
clearable
style="width: 130px"
/>
</ElFormItem>
<ElFormItem label="内部标签">
<ElInput
v-model.trim="searchForm.internalMemo"
placeholder="内部标签"
clearable
style="width: 130px"
></ElInput>
</ElFormItem>
<ElFormItem label="排序">
<el-select
v-model="searchForm.order"
clearable
style="width: 100px"
placeholder="排序类型"
>
<el-option value="asc" label="正序"></el-option>
<el-option value="desc" label="倒序"></el-option>
</el-select>
</ElFormItem>
<ElFormItem label="定制类型">
<el-select
v-model="searchForm.customizedQuantity"
clearable
style="width: 100px"
placeholder="定制类型"
>
<el-option value="single" label="单面"></el-option>
<el-option value="multiple" label="多面"></el-option>
</el-select>
</ElFormItem>
<ElFormItem>
<ElButton type="primary" @click="loadDiffList">查询</ElButton>
</ElFormItem>
</ElForm>
</div>
<div class="header-filter-tab">
<div class="tabs">
<div
v-for="item in tabsNav"
:key="item.status"
class="tabs-node"
:class="item.status === status ? 'tabs-node_active' : ''"
@click="changeTab(item)"
>
<span class="tabs-node_label">{{ item.statusName }}</span>
<span class="tabs-node_count">{{ `(${item.quantity})` }}</span>
</div>
</div>
</div>
<div class="order-content flex-1 flex-column overflow-hidden mt-10">
<div style="margin-bottom: 10px">
<span v-if="status === 'TO_BE_CONFIRMED'" class="item">
<ElButton type="success" @click="confirmProduce">确认生产</ElButton>
</span>
<span v-if="status === 'IN_PRODUCTION'" class="item">
<ElButton type="success" dark @click="fastToProduction('快捷生产', 1)"
>快捷生产</ElButton
>
</span>
<span
v-if="
status === 'TO_BE_CONFIRMED' ||
status === 'IN_PRODUCTION' ||
status === 'PART_SHIPPING'
"
class="item"
>
<ElButton type="primary" dark @click="printManuscript"
>打印生产单</ElButton
>
</span>
<span v-if="status === 'TO_BE_CONFIRMED'" class="item">
<ElButton type="success" dark @click="exportManuscript"
>导出生产单</ElButton
>
</span>
<span class="item">
<ElButton type="warning" @click="addInternalTag"
>添加内部标签</ElButton
>
</span>
<span
v-if="
status === 'TO_BE_CONFIRMED' ||
status === 'IN_PRODUCTION' ||
status === 'PART_SHIPPING'
"
class="item"
>
<ElButton type="warning" is-dark @click="downloadMaterial">
下载素材</ElButton
>
</span>
<span
v-if="
[
'TO_BE_CONFIRMED',
'IN_PRODUCTION',
'PART_SHIPPING',
'WAIT_SHIPMENT',
].includes(status)
"
class="item"
>
<ElButton type="primary" @click="refreshProduct"
>刷新商品信息</ElButton
>
</span>
<span
v-if="status === 'WAIT_SHIPMENT' || status === 'PART_SHIPPING'"
class="item"
>
<ElButton type="success" @click="confirmDelivery">发货</ElButton>
</span>
<span v-if="status === 'WAIT_SHIPMENT'" class="item">
<ElButton type="warning" @click="completeDelivery">完成发货</ElButton>
</span>
<span v-if="status === 'IN_PRODUCTION'" class="item">
<ElButton type="danger" @click="voidedBtn">作废</ElButton>
</span>
<span v-if="status === 'IN_PRODUCTION'" class="item">
<ElButton type="warning" is-dark @click="applyForReplacement">
申请补胚</ElButton
>
</span>
</div>
<template
v-if="
[
'IN_PRODUCTION',
'WAIT_SHIPMENT',
'TO_BE_REPLENISHMENT',
'INVALID',
].includes(status)
"
>
<div
v-if="CardOrderList.length"
v-loading="loading"
element-loading-text="加载中..."
class="card-mode"
>
<div class="card-list">
<div
v-for="cardItem in CardOrderList"
:key="cardItem.id"
class="card-list_item"
@click="cardClick(cardItem)"
>
<CardWrapper
:card-item="cardItem"
:class="{ active: isSelectStatused(cardItem) }"
@contextmenu.prevent="(v) => rightClick(v, cardItem)"
>
<!-- <template #top_right> 工厂类型 </template> -->
<template #bottom_left>
<span
v-if="cardItem?.factorySubOrderNumber"
title="生产单号"
class="base_sku"
@click.stop="
copy(String(cardItem?.factorySubOrderNumber || ''))
"
>
{{ cardItem?.factorySubOrderNumber }}
</span>
</template>
<template #operations>
<Icon
name="caozuorizhi"
@click.stop="
openLog(Number(cardItem.podOrderId) || undefined)
"
>
<template #title>
<title>操作日志</title>
</template>
</Icon>
<Icon
name="chakanxiangqing"
@click.stop="openDetail(cardItem.id)"
>
<template #title>
<title>查看详情</title>
</template>
</Icon>
</template>
<template #images>
<div class="flex-between">
<div class="images-position">
<div
v-for="(item, index) in getSafeImages(cardItem)"
:key="index"
:title="
item?.ename
? item.ename === 'front'
? '正面图片'
: '反面图片'
: ''
"
:style="
currentImage === item?.image &&
currentId === cardItem.id
? 'border-color: red'
: ''
"
class="item-image"
@click="handleChangeImages(item, cardItem)"
>
<img :src="item?.image" height="28" />
</div>
</div>
<b
v-if="cardItem"
:style="{
color:
(Number(cardItem.customizedQuantity) || 0) > 1
? 'red'
: '#67C23A',
}"
>
{{
(Number(cardItem.customizedQuantity) || 0) > 1
? '多'
: '单'
}}
</b>
</div>
</template>
<template #info>
<div style="font-size: 12px; padding: 14px 5px 0">
<el-row class="el_row">
<el-col :span="14" :offset="0">
<el-tooltip
class="item"
effect="dark"
:content="cardItem?.baseSku"
placement="bottom"
>
<span
title="Base SKU"
style="
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
width: 100%;
display: inline-block;
"
>
{{ cardItem?.baseSku }}
</span>
</el-tooltip>
</el-col>
<el-col
v-if="status === 'TO_BE_REPLENISHMENT'"
:span="10"
:offset="0"
style="text-align: right"
>
<el-tooltip
class="item"
effect="dark"
:content="'补胚数量'"
placement="bottom"
>
<span
>补胚数量:{{
cardItem?.replenishmentNum || '--'
}}</span
>
</el-tooltip>
</el-col>
<el-col
v-else
:span="10"
:offset="0"
style="text-align: right"
>
<span v-if="status === 'INVALID'">
数量:{{ cardItem?.num }}
</span>
<template v-else>
<el-tooltip
v-if="status !== 'TO_BE_REPLENISHMENT'"
class="item"
effect="dark"
:content="
['TO_BE_REPLENISHMENT', 'IN_PRODUCTION'].includes(
status,
)
? '未生产数量'
: '已生产数量'
"
placement="bottom"
>
<span
>数量:{{
[
'TO_BE_REPLENISHMENT',
'IN_PRODUCTION',
].includes(status)
? cardItem?.notPassNum
: cardItem?.passNum
}}</span
>
</el-tooltip>
</template>
</el-col>
</el-row>
<el-row style="margin-top: 5px">
<el-col
:span="14"
:offset="0"
style="
white-space: nowrap;
display: flex;
align-items: center;
"
>
<span
title="Variant SKU"
style="
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
"
>
{{ cardItem?.variantSku }}
</span>
</el-col>
<el-col :span="10" :offset="0" style="text-align: right">
<el-tooltip
class="item"
effect="dark"
:content="'货号'"
placement="bottom"
>
<span
>货号:{{ cardItem?.supplierItemNo || '--' }}</span
>
</el-tooltip>
</el-col>
</el-row>
<el-row style="margin-top: 5px">
<el-col
:span="12"
:offset="0"
style="
white-space: nowrap;
display: flex;
align-items: center;
"
>
<span>工艺:</span>
<span
:title="String(cardItem?.process)"
style="
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
"
>
{{ cardItem?.process }}
</span>
</el-col>
<el-col
:span="12"
:offset="0"
style="white-space: nowrap; text-align: right"
>
<span
:title="`店铺单号:${cardItem?.shopNumber}`"
style="
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
"
>
{{ cardItem?.shopNumber }}
</span>
</el-col>
</el-row>
<el-row style="margin-top: 5px">
<el-col
:span="12"
:offset="0"
style="white-space: nowrap"
>
<span
:title="`第三方生产单号:${cardItem?.thirdSubOrderNumber}`"
style="
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
"
@click.stop="
copy(String(cardItem?.thirdSubOrderNumber || ''))
"
>
{{ cardItem?.thirdSubOrderNumber }}
</span>
</el-col>
<el-col :span="12" :offset="0" style="text-align: right">
<span title="期望交货时间">
{{ cardItem?.expectDeliveryTime }}
</span>
</el-col>
</el-row>
<el-row style="margin-top: 5px">
<el-col
:span="12"
:offset="0"
style="white-space: nowrap"
>
<span
:title="`第三方订单号:${cardItem?.thirdOrderNumber}`"
style="
display: inline-block;
width: 100%;
overflow: hidden;
text-overflow: ellipsis;
"
@click.stop="
copy(String(cardItem?.thirdOrderNumber || ''))
"
>
{{ cardItem?.thirdOrderNumber }}
</span>
</el-col>
</el-row>
</div>
</template>
</CardWrapper>
</div>
</div>
</div>
<div v-else class="empty">暂无数据</div>
</template>
<div
v-else
ref="tableWrapperRef"
v-loading="loading"
element-loading-text="加载中..."
class="order-list flex-1 overflow-hidden"
>
<TableView
:paginated-data="tableData"
:columns="tableColumns"
:selectionable="true"
default-expand-all
:span-method="arraySpanMethod"
@selection-change="handleSelectionChange"
@contextmenu.prevent="handleContextMenu"
>
<template #expand="{ row }">
<div v-if="row.productList" class="table-expand">
<div
class="order-list-expand"
:style="{ width: `${thOrderDetailWidth + 50}px` }"
>
<ProductInfo :row="row" :status="status" :is-pod="true">
<template #operation="{ productItem }">
<div class="operation-item" title="添加备注">
<el-icon
class="icon"
style="color: #e6a23c"
@click="
handleUpdateRemark(
productItem.id,
productItem.remark || '',
)
"
><EditPen
/></el-icon>
</div>
<div
v-if="status === 'TO_BE_RECEIPT'"
class="operation-item"
>
<el-button
size="small"
type="warning"
@click="applyEmbryoReplenishment(productItem)"
>申请补胚</el-button
>
</div>
<div
v-if="
status === 'TO_BE_RECEIPT' ||
status === 'TO_BE_CONFIRMED'
"
class="operation-item"
>
<el-button
size="small"
type="danger"
@click="invalidOrder(productItem)"
>作废</el-button
>
</div>
</template>
</ProductInfo>
<template v-if="row.productList.length > 2">
<div class="order-list-expand_more">
<span @click="openAll(row)">
<template v-if="!row.moreable">
展开全部<strong style="color: red"
>({{ row.productList.length }})</strong
>条商品信息<el-icon style="vertical-align: middle"
><ArrowDown /></el-icon
></template>
<template v-else>
收起商品信息<el-icon style="vertical-align: middle"
><ArrowUp
/></el-icon>
</template>
</span>
</div>
</template>
</div>
<div class="order-actual-payment">
<div class="order-actual-payment_info">
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label">商品价:</span>
<span class="order-list-expand_item_value">{{
row.thirdProductAmount
}}</span>
</div>
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label">小计:</span>
<span class="order-list-expand_item_value">{{
row.totalAmount || '--'
}}</span>
</div>
<div
v-if="row.totolBuyNumber"
class="order-list-expand_item_info_title"
>
<span class="order-list-expand_item_value"
>{{ row.totolBuyNumber }}</span
>
</div>
</div>
</div>
<div class="order-memo">
<div class="order-memo-info">
<div
v-for="memo in row.internalMemoList || []"
:key="memo.id"
class="order-memo-item"
>
<div
v-if="memo.operatorEmployeeName"
class="order-memo-item__name"
>
<span>{{ memo.operatorEmployeeName || '' }}</span>
</div>
<div
v-if="memo.operatorTime"
class="order-memo-item__time"
:title="memo.operatorTime"
>
<span>{{ memo.operatorTime || '' }}</span>
</div>
<div
v-if="memo.content"
class="order-memo-item__content"
:title="memo.content"
>
<span>{{ memo.content || '' }}</span>
</div>
</div>
</div>
</div>
<div class="order-time">
<div class="order-time_info">
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label">创建时间:</span>
<span class="order-list-expand_item_value">{{
row.createTime || '--'
}}</span>
</div>
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label"
>期望交货时间:</span
>
<span class="order-list-expand_item_value">{{
row.expectDeliveryTime || '--'
}}</span>
</div>
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label">确认时间:</span>
<span class="order-list-expand_item_value">{{
row.startStockingTime || '--'
}}</span>
</div>
<div class="order-list-expand_item_info_title">
<span class="order-list-expand_item_label">完成时间:</span>
<span class="order-list-expand_item_value">{{
row.finishTime || '--'
}}</span>
</div>
</div>
</div>
<div class="order-operate">
<div class="order-operate_info">
<div
v-if="status === 'TO_BE_CONFIRMED'"
class="order-list-expand_item_info_title"
>
<ElButton text type="danger" @click="cancelOrder(row.id)"
>取消
</ElButton>
</div>
<div class="order-list-expand_item_info_title">
<ElButton text type="primary" @click="openLog(row.id)"
>操作日志
</ElButton>
</div>
</div>
</div>
</div>
</template>
<template #orderDetail="scope">
<div class="order-detail">
<div
:title="scope.row.factoryOrderNumber"
class="order-detail_item"
>
<span class="label">订单号:</span>
<span class="value">{{ scope.row.factoryOrderNumber }}</span>
</div>
<div
:title="scope.row.thirdOrderNumber"
class="order-detail_item"
>
<span class="label">第三方订单号:</span>
<span class="value" :title="scope.row.thirdOrderNumber">{{
scope.row.thirdOrderNumber || '--'
}}</span>
</div>
<!-- <div
:title="scope.row.manuscriptStatusStr"
class="order-detail_item"
>
<span class="label">稿件状态:</span>
<span class="value" :title="scope.row.manuscriptStatusStr">{{
scope.row.manuscriptStatusStr || '--'
}}</span>
</div> -->
<div :title="scope.row.lanshouName" class="order-detail_item">
<span class="label">收货人:</span>
<span class="value">{{ scope.row.lanshouName }}</span>
</div>
<div :title="scope.row.lanshouPhone" class="order-detail_item">
<span class="label">电话:</span>
<span class="value">{{ scope.row.lanshouPhone }}</span>
</div>
<div :title="scope.row.lanshouAddress" class="order-detail_item">
<span class="label">收货地址:</span>
<span class="value" :title="scope.row.lanshouAddress">{{
scope.row.lanshouRegion + scope.row.lanshouAddress
}}</span>
</div>
<div
v-if="scope.row.shipmentUid"
:title="scope.row.shipmentUid"
class="order-detail_item"
>
<span class="label">提货码:</span>
<span class="value" :title="scope.row.shipmentUid">{{
scope.row.shipmentUid
}}</span>
</div>
<div :title="scope.row.lanshouPost" class="order-detail_item">
<span class="label">邮编:</span>
<span class="value">{{ scope.row.lanshouPost }}</span>
</div>
</div>
</template>
</TableView>
</div>
<div class="pagination">
<div>
<span>已选择 <span style="color: red">{{selection.length}}</span> 条数据</span>
</div>
<el-pagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:page-sizes="[100, 200, 300, 400]"
background
layout="total, sizes, prev, pager, next, jumper"
:total="total"
style="margin: 10px auto 10px; text-align: right"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
/>
</div>
</div>
</div>
<el-dialog
v-model="shipmentVisible"
title="发货"
:close-on-click-modal="false"
width="1600PX"
top="6vh"
@opened="onShipmentDialogOpened"
>
<div class="header-search">
<el-input
ref="inputRef"
v-model="productionOrderNumber"
clearable
size="large"
placeholder="请输入生产单号"
@keydown.enter="searchShipmentByOrderNumber"
/>
<el-button
type="primary"
size="large"
@click="searchShipmentByOrderNumber"
>查询
</el-button>
</div>
<Shipment
ref="shipmentOrderRef"
v-loading="shipmentLoading"
:order-list="orderList"
:current-row="currentRow"
:is-pod="true"
@change-current-row="onChangeCurrentRow"
/>
<div class="shipment-logistics-info margin-top-20">
<ElForm ref="shipmentFormRef" :model="shipmentForm" :rules="rules">
<ElRow :gutter="20">
<ElCol :span="6">
<ElFormItem label="发货方式" prop="shippingWay">
<ElSelect
v-model="shipmentForm.shippingWay"
clearable
placeholder="请选择"
style="width: 100%"
>
<ElOption label="送货上门" value="1"></ElOption>
<ElOption label="快递" value="2"></ElOption>
</ElSelect>
</ElFormItem>
</ElCol>
<ElCol v-if="shipmentForm.shippingWay === '2'" :span="6">
<ElFormItem label="物流名称" prop="carriageName">
<ElSelect
v-model="shipmentForm.carriageName"
filterable
placeholder="请输入关键字"
clearable
style="width: 100%"
>
<ElOption
v-for="item in logisticsCompanyList"
:key="item.id"
:value="item.name"
></ElOption>
</ElSelect>
</ElFormItem>
</ElCol>
<ElCol v-if="shipmentForm.shippingWay === '2'" :span="6">
<ElFormItem label="物流跟踪号" prop="logisticsTracking">
<ElInput
v-model="shipmentForm.logisticsTracking"
placeholder="请输入物流跟踪号"
clearable
style="width: 100%"
/>
</ElFormItem>
</ElCol>
<ElCol v-if="shipmentForm.shippingWay === '2'" :span="6">
<ElFormItem label="物流费用" prop="carriageAmount">
<ElInput
v-model="shipmentForm.carriageAmount"
clearable
placeholder="请输入物流费用"
style="width: 100%"
/>
</ElFormItem>
</ElCol>
</ElRow>
</ElForm>
</div>
<template #footer>
<div class="dialog-footer">
<el-button size="large" @click="shipmentVisible = false"
>取消
</el-button>
<el-button size="large" type="primary" @click="saveShipment"
>发货
</el-button>
</div>
</template>
</el-dialog>
<el-dialog
v-model="logVisible"
title="操作日志"
width="1000px"
:close-on-click-modal="false"
>
<LogList :log-list="logList" />
</el-dialog>
<el-dialog
v-model="countVisible"
title="数据统计"
width="400px"
:close-on-click-modal="false"
>
<p>
基版 <b>{{ cardItem?.baseSku }}</b> 的统计数量为:<b> {{ count }}</b>
</p>
</el-dialog>
<right-menu
ref="rightMenuRef"
:show_copy_shop_number="['IN_PRODUCTION', 'WAIT_SHIPMENT'].includes(status)"
@change="rightChange"
/>
<fastProduction
v-model:detailVisible="detailVisible"
:title="fastTitle"
:is-jmpod="'JMPOD'"
:type="fastType"
:detail-data="detailData"
:current-status="status"
@on-success="handleSuccess"
@close="fastClose"
></fastProduction>
<table-right-menu
ref="tableRightMenuRef"
:table-right-menu-visible="tableRightMenuVisible"
@on-copy-change="onCopyChange"
/>
<el-dialog
v-model="completeShipmentVisible"
title="完成发货"
width="600px"
:close-on-click-modal="false"
>
<el-form
ref="completeShipmentFormRef"
:model="completeShipmentForm"
:rules="completeShipmentRules"
label-width="100px"
>
<el-form-item label="发货方式" prop="shippingWay">
<el-select
v-model="completeShipmentForm.shippingWay"
placeholder="请选择发货方式"
style="width: 100%"
>
<el-option label="送货上门" value="1" />
<el-option label="快递" value="2" />
</el-select>
</el-form-item>
<template v-if="completeShipmentForm.shippingWay === '2'">
<el-form-item label="物流名称" prop="carriageName">
<el-select
v-model="completeShipmentForm.carriageName"
filterable
placeholder="请选择物流名称"
style="width: 100%"
>
<el-option
v-for="item in logisticsCompanyList"
:key="item.id"
:value="item.name"
/>
</el-select>
</el-form-item>
<el-form-item label="物流跟踪号" prop="logisticsTracking">
<el-input
v-model="completeShipmentForm.logisticsTracking"
placeholder="请输入物流跟踪号"
/>
</el-form-item>
<el-form-item label="物流费用" prop="carriageAmount">
<el-input
v-model="completeShipmentForm.carriageAmount"
placeholder="请输入物流费用"
/>
</el-form-item>
</template>
</el-form>
<template #footer>
<div class="dialog-footer">
<el-button @click="completeShipmentVisible = false">取消</el-button>
<el-button type="primary" @click="saveCompleteShipment">确认</el-button>
</div>
</template>
</el-dialog>
</template>
<script setup lang="tsx">
// refreshJMProductInfo,reasonInvalidationApi,
import RightMenu from './rightMenu.vue'
import {
getOrderTabData,
getOrderList,
confirmProductionOrder,
cancelOrderApi,
downloadMaterialApi,
addInternalTagApi,
printOrder,
exportOrder,
getLogList,
updateRemarkApi,
getCardOrderList,
getOrderDetail,
getInProductionCount,
getWaitShipmentCount,
refreshJMProductInfo,
reasonInvalidationApi,
applyForReplenishmentApi,
completeDeliveryApi,
} from '@/api/podOrder'
import TableView from '@/components/TableView.vue'
import {
ProductList,
LogisticsData,
OrderData,
ShipmentForm,
} from '@/types/api/order'
import fastProduction from '../fastProduction.vue'
import CardWrapper from '@/components/CardPods.vue'
import { CustomColumn } from '@/types/table'
import { useValue } from '@/utils/hooks/useValue'
import {
computed,
nextTick,
onBeforeUnmount,
onMounted,
reactive,
ref,
} from 'vue'
import dayjs from 'dayjs'
import useElTableColumnWidth from '@/utils/hooks/useElTableColumnWidth'
import ProductInfo from '../ProductInfo.vue'
import { SpanMethodProps } from '@/types/api/order'
import useShipment from '../hook/usePodShipment'
import Shipment from '../Shipment.vue'
import {
SearchForm,
Tab,
LogListData,
PodProductList,
cardImages,
imageAryInter,
CardOrderData,
} from '@/types/api/podOrder'
import { ArrowUp, ArrowDown, EditPen } from '@element-plus/icons-vue'
import { getLogisticsCompanyList } from '@/api/common'
import { ElButton, type FormRules } from 'element-plus'
import { showConfirm } from '@/utils/ui'
import { filePath } from '@/api/axios'
import LogList from '@/components/LogList.vue'
const tableRef = ref()
const loading = ref(false)
const currentPage = ref(1)
const pageSize = ref(100)
const total = ref(0)
const countVisible = ref(false)
const keyCode = ref('')
const cardItem = ref<PodProductList | CardOrderData>()
const rightMenuRef = ref()
const count = ref<number>(0)
const rightClick = (e: MouseEvent, item: PodProductList | CardOrderData) => {
cardItem.value = item
rightMenuRef.value.setPosition({
x: e.clientX,
y: e.clientY,
cardItem: e.clientY,
el: e,
})
}
const handleSizeChange = (size:number)=>{
pageSize.value = size
loadDiffList()
}
const handleCurrentChange = (page:number)=>{
currentPage.value = page
loadDiffList()
}
const rightChange = async (code: string) => {
const flag = ['IN_PRODUCTION', 'WAIT_SHIPMENT'].includes(status.value)
if (code === 'check_all') {
if (flag) {
selection.value = JSON.parse(JSON.stringify(CardOrderList.value))
} else {
if (tableRef.value && tableRef.value?.tableRef) {
tableRef.value?.tableRef.toggleAllSelection()
}
// selection.value = JSON.parse(JSON.stringify(tableData.value))
}
} else if (code === 'clear_check') {
selection.value = []
tableRef.value?.tableRef.toggleAllSelection()
} else if (code === 'copy_code') {
const str = selection.value
.map((item) => item.factorySubOrderNumber || item.factoryOrderNumber)
.join()
navigator.clipboard.writeText(str)
ElMessage.success('复制成功')
} else if (code === 'copy_shopNumber') {
const str = selection.value.map((item) => item.shopNumber).join()
navigator.clipboard.writeText(str)
ElMessage.success('复制成功')
} else if (code === 'count') {
countVisible.value = true
let res
if (status.value === 'WAIT_SHIPMENT') {
res = await getWaitShipmentCount(
cardItem.value?.productionFileId,
cardItem.value?.baseSku,
)
} else if (status.value === 'IN_PRODUCTION') {
res = await getInProductionCount(
cardItem.value?.productionFileId,
cardItem.value?.baseSku,
)
}
count.value = (res?.data || 0) as number
}
}
// 日期工具函数
const getDateRange = (days = 0, type: 'past' | 'future' = 'past') => {
const end = dayjs()
const start =
type === 'past' ? end.subtract(days, 'day') : end.add(days, 'day')
return [start.startOf('day').toDate(), end.endOf('day').toDate()]
}
const getMonthRange = (months = 0, type: 'past' | 'future' = 'past') => {
const now = dayjs()
const start =
type === 'past' ? now.subtract(months, 'month') : now.add(months, 'month')
return [start.startOf('month').toDate(), start.endOf('month').toDate()]
}
const getWeekRange = (weeks = 0, type: 'past' | 'future' = 'past') => {
const now = dayjs()
const start =
type === 'past' ? now.subtract(weeks, 'week') : now.add(weeks, 'week')
return [start.startOf('week').toDate(), start.endOf('week').toDate()]
}
const pickerOptions = {
shortcuts: [
{
text: '今日',
value: () => getDateRange(0),
},
{
text: '昨天',
value: () => getDateRange(1),
},
{
text: '最近7天',
value: () => getDateRange(6),
},
{
text: '最近14天',
value: () => getDateRange(13),
},
{
text: '最近30天',
value: () => getDateRange(29),
},
{
text: '本周',
value: () => getWeekRange(0),
},
{
text: '上周',
value: () => getWeekRange(1),
},
{
text: '本月',
value: () => getMonthRange(0),
},
{
text: '上月',
value: () => getMonthRange(1),
},
{
text: '历史',
value: () => {
const end = dayjs().endOf('day').toDate()
const start = dayjs('2000-01-01').startOf('day').toDate()
return [start, end]
},
},
],
}
const timeRange = ref<string[]>([])
const tabsNav = ref<Tab[]>()
const status = ref('TO_BE_CONFIRMED')
const [tableWrapperRef, thOrderDetailWidth, updateColumnWidth] =
useElTableColumnWidth('table th.th-order-detail')
const loadTabData = async () => {
try {
const res = await getOrderTabData()
tabsNav.value = res.data
} catch (error) {
// showError(error)
}
}
const handleSuccess = () => {
loadTabData()
loadDiffList()
}
// 查看详情
const openDetail = async (id: number) => {
try {
const res = await getOrderDetail(id)
if (res.code == 200) {
if (res.data.imageAry) {
res.data.imageAry = JSON.parse(res.data.imageAry as string)
}
detailData.value = res.data || {}
detailVisible.value = true
fastTitle.value = '查看详情'
fastType.value = 0
}
} catch (e) {
//showError(e)
}
}
const CardOrderList = ref<(PodProductList | CardOrderData)[]>([])
const loadCardList = async () => {
try {
const res = await getCardOrderList(
{
...searchForm.value,
status: status.value,
timeType: searchForm.value.timeType,
startTime:
timeRange.value && timeRange.value.length > 0
? timeRange.value[0]
: null,
endTime:
timeRange.value && timeRange.value.length > 0
? timeRange.value[1]
: null,
},
currentPage.value,
pageSize.value,
)
CardOrderList.value = res.data.records.map((item: PodProductList) => {
if (!item.imageAry) {
const images = []
if (typeof item.variantImage === 'string') {
images.push({
ename: 'front',
cname: '正面',
image: item.variantImage,
})
}
if (typeof item.negativeImage === 'string') {
images.push({
ename: 'back',
cname: '反面',
image: item.negativeImage,
})
}
item.images = images
} else {
if (item.imageAry) {
const images = JSON.parse(item.imageAry as string)
if (Array.isArray(images)) {
item.images = images.map((e: imageAryInter) => {
return {
ename: '',
cname: '',
image: e.url,
}
})
}
}
}
return item
})
total.value = res.data.total
} catch (error) {
// showError(error)
}
}
const loadOrderList = async () => {
try {
const res = await getOrderList({
...searchForm.value,
status: status.value,
timeType: searchForm.value.timeType,
startTime:
timeRange.value && timeRange.value.length > 0
? timeRange.value[0]
: null,
endTime:
timeRange.value && timeRange.value.length > 0
? timeRange.value[1]
: null
},currentPage.value,pageSize.value)
tableData.value = res.data.records
total.value = res.data.total
} catch (error) {
// showError(error)
}
}
const currentImage = ref('')
const currentId = ref(-1)
const changeImages = (
item: cardImages,
data: PodProductList | CardOrderData,
) => {
currentImage.value = item.image
// data.designId = item.designId
currentId.value = data.id
data.variantImage = item.image
// if (data.productList) {
// data.productList[0].variantImage = item.image
// }
}
// 包装函数,用于处理类型转换
const handleChangeImages = (
item: cardImages,
data: PodProductList | CardOrderData,
) => {
changeImages(item as cardImages, data)
}
const fastTitle = ref('')
const detailData = ref({})
const detailVisible = ref(false)
const fastType = ref<number>(-1)
const fastToProduction = (title: string, type: number) => {
detailData.value = {}
detailVisible.value = true
fastTitle.value = title
fastType.value = type
}
const cardClick = (data: PodProductList | CardOrderData) => {
const status = isSelectStatused(data)
if (keyCode.value === 'Shift') {
if (selection.value.length) {
const startIndex = CardOrderList.value.findIndex(
(el) => el.id === selection.value[0].id,
)
const endIndex = CardOrderList.value.findIndex((el) => el.id === data.id)
selection.value = []
for (let k = startIndex; k <= endIndex; k++) {
selection.value.push(JSON.parse(JSON.stringify(CardOrderList.value[k])))
}
}
}
if (status) {
selection.value = selection.value.filter(
(item: CardOrderData | PodProductList) => item.id !== data.id,
)
} else {
selection.value.push(data as CardOrderData)
}
}
const isSelectStatused = (data: PodProductList | CardOrderData) => {
const index = selection.value.findIndex(
(item: CardOrderData | PodProductList) => item.id === data.id,
)
return index !== -1
}
const changeTab = (item: Tab) => {
status.value = item.status ?? ''
currentPage.value = 1
pageSize.value = 100
selection.value = []
searchForm.value.timeType = null
loading.value = false
loadDiffList()
}
const fastClose = () => {
if (fastType.value !== 0) {
loadTabData()
}
detailVisible.value = false
}
// 根据不同状态调用不同接口
const loadDiffList = async () => {
if (
[
'IN_PRODUCTION',
'WAIT_SHIPMENT',
'TO_BE_REPLENISHMENT',
'INVALID',
].includes(status.value)
) {
await loadCardList()
} else {
loadOrderList()
updateColumnWidth()
}
}
const [searchForm] = useValue<SearchForm>({
timeType: null,
shopNumber: '',
customizedQuantity: '',
order: 'desc',
})
const tableColumns = computed<CustomColumn<CardOrderData[]>>(() => {
return [
{
type: 'expand',
align: 'center',
slot: 'expand',
width: 1,
},
{
label: '订单详情',
key: 'id',
minWidth: 800,
slot: 'orderDetail',
className: 'th-order-detail',
showOverflowTooltip: true,
},
{
label: '实付款',
key: '',
width: 280,
},
{
label: '内部便签',
key: 'customerName',
width: 300,
showOverflowTooltip: true,
},
{
label: '时间',
key: 'status',
width: 300,
align: 'center',
},
{
label: '操作',
key: 'status',
width: 100,
align: 'center',
},
]
})
// const {
// loading,
// currentPage,
// pageSize,
// total,
// data: tableData,
// refresh: search,
// onCurrentPageChange: handleCurrentChange,
// onPageSizeChange: handleSizeChange,
// } = usePageList<OrderData | CardOrderData>({
// query: async (page, pageSize) => {
// const commonParams = {
// ...searchForm.value,
// status: status.value,
// timeType: searchForm.value.timeType,
// startTime:
// timeRange.value && timeRange.value.length > 0
// ? timeRange.value[0]
// : null,
// endTime:
// timeRange.value && timeRange.value.length > 0
// ? timeRange.value[1]
// : null,
// }
// // 动态选择接口
// const fetchData =
// status.value === 'IN_PRODUCTION' ? getCardOrderList : getOrderList
// return fetchData(commonParams, page, pageSize).then(
// (res) => {
// if([
// 'IN_PRODUCTION',
// 'WAIT_SHIPMENT',
// 'TO_BE_REPLENISHMENT',
// 'INVALID',
// ].includes(status.value)){
// CardOrderList.value = res.data.records as PodProductList[]
// }else{
// tableData.value = res.data.records
// }
// },
// ) as never
// },
// })
// 发货
const {
shipmentFormRef,
productionOrderNumber,
shipmentVisible,
inputRef,
shipmentForm,
currentRow,
shipmentLoading,
orderList,
shipmentOrderRef,
searchShipmentByOrderNumber,
saveShipment,
confirmDelivery,
onShipmentDialogOpened,
} = useShipment(() => {
loadTabData()
loadDiffList()
})
const rules = reactive<FormRules<ShipmentForm>>({
shippingWay: [
{
required: true,
message: '请选择物流方式',
},
],
carriageName: [
{
required: true,
message: '请选择物流公司',
},
],
carriageAmount: [
{
required: true,
message: '请输入物流费用',
},
],
logisticsTracking: [
{
required: true,
message: '请输入物流跟踪号',
},
],
})
const logisticsCompanyList = ref<LogisticsData[]>([])
const getLogisticsList = async () => {
try {
const res = await getLogisticsCompanyList()
logisticsCompanyList.value = res.data
} catch (error) {
//showError(error)
}
}
const refreshProduct = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
try {
await showConfirm('是否刷新商品信息', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
} catch {
return
}
const ids = []
if (['IN_PRODUCTION', 'WAIT_SHIPMENT'].includes(status.value)) {
ids.push(
...selection.value.map(
(item: CardOrderData | PodProductList) => item.podOrderId as number,
),
)
} else {
ids.push(
...selection.value.map(
(item: CardOrderData | PodProductList) => item.id as number,
),
)
}
try {
const res = await refreshJMProductInfo(ids)
ElMessage({
message: res.message,
type: 'success',
offset: window.innerHeight / 2,
})
loadTabData()
loadDiffList()
} catch (e) {
// showError(e)
}
}
const openAll = (row: CardOrderData) => {
row.moreable = !row.moreable
}
// 表格和卡片的选中值:有两种约束
const selection = ref<(CardOrderData | PodProductList)[]>([])
const tableData = ref<(OrderData)[]>([])
const handleSelectionChange = (s: CardOrderData[]) => {
selection.value = s
}
// 确认生产
const confirmProduce = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
try {
await showConfirm('是否确认生产', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
} catch {
return
}
const ids = selection.value.map(
(item: CardOrderData | PodProductList) => item.id,
)
try {
const res = await confirmProductionOrder(ids)
loadDiffList()
await loadTabData()
ElMessage.success(res.message)
} catch (e) {
// showError(e)
}
}
const applyForReplacement = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
let input = {
value:''
}
try {
input = await ElMessageBox.prompt('', '补胚数量', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputPlaceholder: '请输入补胚数量',
inputPattern: /^\d+$/,
inputErrorMessage: '补胚数量不能为空且只能输入数字',
})
} catch {
return
}
const data = selection.value.map((item: CardOrderData | PodProductList) => {
return {
id: item.podOrderId,
productId: item.id,
factorySubOrderNumber: item.factorySubOrderNumber,
thirdSubOrderNumber: item.thirdSubOrderNumber,
replenishmentNum: Number(input.value),
}
})
try {
const res = await applyForReplenishmentApi(data)
await loadDiffList()
await loadTabData()
ElMessage.success(res.message)
} catch (e) {
// showError(e)
}
}
// 下载稿件
const downloadMaterial = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
const ids = []
if (['IN_PRODUCTION', 'WAIT_SHIPMENT'].includes(status.value)) {
ids.push(
...selection.value.map((item: CardOrderData | PodProductList) => item.id),
)
} else {
ids.push(
...selection.value.flatMap((item: CardOrderData | PodProductList) =>
Array.isArray(item.productList)
? item.productList.map((sub: PodProductList) => sub.id)
: [],
),
)
}
try {
const res = await downloadMaterialApi(ids)
const { data } = res
data.forEach((item: string) => {
const a = document.createElement('a')
a.href = filePath + item
a.download = item
a.target = '_blank'
document.body.appendChild(a)
a.click()
document.body.removeChild(a)
})
} catch (e) {
// showError(e)
console.error(e)
}
}
const arraySpanMethod = ({ columnIndex }: SpanMethodProps) => {
if (columnIndex === 0 || columnIndex === 1) {
return [1, 1]
} else {
return [1, 6]
}
}
const copy = (text: string): void => {
const oInput = document.createElement('input')
oInput.value = text
oInput.style.position = 'absolute'
oInput.style.opacity = '0'
oInput.style.pointerEvents = 'none'
document.body.appendChild(oInput)
oInput.select()
if (document.execCommand('copy')) {
ElMessage.success('复制成功')
} else {
ElMessage.error('复制失败,请手动复制')
}
document.body.removeChild(oInput)
}
const onChangeCurrentRow = (item: ProductList) => {
currentRow.value = item
}
const cancelOrder = async (id: number) => {
try {
await showConfirm('是否确认取消', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
} catch {
return
}
try {
const res = await cancelOrderApi(id)
ElMessage({
message: res.message,
type: 'success',
offset: window.innerHeight / 2,
})
loadTabData()
loadDiffList()
} catch (e) {
// showError(e)
}
}
// 添加内部便签
const addInternalTag = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
ElMessageBox.prompt('', '添加内部便签', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputType: 'textarea',
inputPlaceholder: '请输入内部便签',
inputPattern: /.+/,
inputErrorMessage: '内部便签不能为空',
}).then(async ({ value }: { value: string }) => {
try {
const res = await addInternalTagApi(
selection.value.map((item: CardOrderData | PodProductList) =>
status.value === 'IN_PRODUCTION' || status.value === 'WAIT_SHIPMENT'
? (item.podOrderId as number)
: item.id,
),
value,
)
ElMessage.success(res.message)
loadTabData()
loadDiffList()
} catch (e) {
// showError(e)
}
})
}
const voidedBtn = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
ElMessageBox.prompt('', '作废', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputPlaceholder: '请输入作废原因',
inputPattern: /.+/,
inputErrorMessage: '作废原因不能为空',
}).then(async ({ value }: { value: string }) => {
try {
const res = await reasonInvalidationApi(
selection.value.map((item: CardOrderData | PodProductList) => item.id),
value,
)
ElMessage.success(res.message)
loadTabData()
loadDiffList()
} catch (e) {
// showError(e)
}
})
}
const printManuscript = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
const ids = []
if (['IN_PRODUCTION', 'WAIT_SHIPMENT'].includes(status.value)) {
ids.push(
...selection.value.map((item: CardOrderData | PodProductList) => item.id),
)
} else {
ids.push(
...selection.value.flatMap((item: CardOrderData | PodProductList) =>
Array.isArray(item.productList)
? item.productList.map((sub: PodProductList) => sub.id)
: [],
),
)
}
try {
await showConfirm('是否打印生产单', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
} catch {
return
}
const loading = ElLoading.service({
lock: true,
text: '加载中...',
background: 'rgba(0, 0, 0, 0.7)',
})
try {
const res = await printOrder(ids)
window.open(filePath + res.message)
} catch (e) {
// showError(e)
console.error(e)
} finally {
loading.close()
}
}
const exportManuscript = async () => {
if (selection.value.length === 0) {
return ElMessage({
message: '请选择订单',
type: 'warning',
offset: window.innerHeight / 2,
})
}
const ids = selection.value.map(
(item: CardOrderData | PodProductList) => item.id,
)
try {
await showConfirm('是否导出生产单', {
confirmButtonText: '确认',
cancelButtonText: '取消',
type: 'warning',
})
} catch {
return
}
const loading = ElLoading.service({
lock: true,
text: '加载中...',
background: 'rgba(0, 0, 0, 0.7)',
})
try {
const res = await exportOrder(ids, status.value)
window.open(filePath + res.message)
} catch (e) {
// showError(e)
console.error(e)
} finally {
loading.close()
}
}
const logVisible = ref(false)
const logList = ref<LogListData[]>([])
// 操作日志
const openLog = async (id?: number) => {
if (!id) return
try {
const res = await getLogList(id)
logList.value = res.data
logVisible.value = true
} catch (e) {
// showError(e)
console.error(e)
}
}
const handleUpdateRemark = (id: number, remark: string) => {
ElMessageBox.prompt('备注', '备注', {
confirmButtonText: '确定',
cancelButtonText: '取消',
inputPattern: /.+/,
inputValue: remark,
inputErrorMessage: '请输入备注',
inputPlaceholder: '备注',
}).then(async ({ value = remark }) => {
try {
await updateRemarkApi(id, value as string)
ElMessage.success('操作成功')
loadDiffList()
} catch (e) {
console.error(e)
}
})
}
// 添加一个函数来安全地获取图片列表
const getSafeImages = (item: PodProductList | CardOrderData): cardImages[] => {
if (!item.images) return []
return item.images as cardImages[]
}
const listenerKeydown = (e: KeyboardEvent) => {
keyCode.value = e?.key
}
const applyEmbryoReplenishment = async (row: ProductList) => {
let res
try {
res = await ElMessageBox.prompt('', '补胚数量', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputPlaceholder: '请输入补胚数量',
inputPattern: /^\d+$/,
inputErrorMessage: '补胚数量不能为空且只能输入数字',
})
} catch {
return
}
const data = [
{
id: row.podOrderId,
productId: row.id,
factorySubOrderNumber: row.factorySubOrderNumber,
thirdSubOrderNumber: row.thirdSubOrderNumber,
replenishmentNum: Number(res.value),
},
]
try {
const res = await applyForReplenishmentApi(data)
loadDiffList()
await loadTabData()
ElMessage.success(res.message)
} catch (e) {
// showError(e)
}
}
const invalidOrder = async (row: ProductList) => {
ElMessageBox.prompt('', '作废', {
confirmButtonText: '确认',
cancelButtonText: '取消',
inputPlaceholder: '请输入作废原因',
inputPattern: /.+/,
inputErrorMessage: '作废原因不能为空',
}).then(async ({ value }: { value: string }) => {
try {
const res = await reasonInvalidationApi([row.id as number], value)
ElMessage.success(res.message)
loadTabData()
loadDiffList()
} catch (e) {
// showError(e)
}
})
}
const tableRightMenuVisible = ref(false)
const tableRightMenuRef = ref()
const onCopyChange = (type: string) => {
if (type === 'copy_shop_number') {
const shopNumberList = []
for (const item of tableData.value) {
if (item.productList) {
shopNumberList.push(...item.productList.map((sub) => sub.shopNumber))
}
}
copy(shopNumberList.join(','))
}
}
const handleContextMenu = (e: MouseEvent) => {
tableRightMenuVisible.value = true
tableRightMenuRef.value?.setRightMenuOptions({
contextMenuX: e.clientX,
contextMenuY: e.clientY,
})
}
const listenerClick = () => {
tableRightMenuVisible.value = false
}
const completeShipmentVisible = ref(false)
const completeShipmentForm = ref({
shippingWay: '', // 发货方式:1-送货上门,2-快递
carriageName: '', // 物流名称
logisticsTracking: '', // 物流跟踪号
carriageAmount: '', // 物流费用
})
// 表单校验规则
const completeShipmentRules = {
shippingWay: [
{ required: true, message: '请选择发货方式', trigger: 'change' },
],
carriageName: [
{ required: true, message: '请选择物流名称', trigger: 'change' },
],
logisticsTracking: [
{ required: true, message: '请输入物流跟踪号', trigger: 'blur' },
],
carriageAmount: [
{ required: true, message: '请输入物流费用', trigger: 'blur' },
],
}
const completeShipmentFormRef = ref()
const completeDelivery = async () => {
if (selection.value.length === 0) {
ElMessage.warning('请选择要完成发货的订单')
return
}
completeShipmentForm.value = {
shippingWay: '1',
carriageName: '',
logisticsTracking: '',
carriageAmount: '',
}
completeShipmentVisible.value = true
await nextTick()
completeShipmentFormRef.value && completeShipmentFormRef.value.clearValidate()
}
const saveCompleteShipment = async () => {
try {
await completeShipmentFormRef.value.validate()
} catch (e) {
return
}
const productIdList = selection.value.map(
(item: CardOrderData | PodProductList) => item.id,
)
try {
const res = await completeDeliveryApi(productIdList, {
...completeShipmentForm.value,
})
ElMessage.success(res.message)
completeShipmentVisible.value = false
loadTabData()
loadDiffList()
} catch (e) {
console.error(e)
}
}
onMounted(() => {
document.addEventListener('keydown', listenerKeydown)
document.addEventListener('click', listenerClick)
getLogisticsList()
loadTabData()
})
onBeforeUnmount(() => {
document.removeEventListener('keydown', listenerKeydown)
document.removeEventListener('click', listenerClick)
})
</script>
<style lang="scss" scoped>
.header-filter-form {
:deep(.el-form-item) {
margin-right: 14px;
margin-bottom: 10px;
}
}
.card-mode {
height: 629px;
padding-top: 10px;
overflow: auto;
flex: 1;
.card-list {
display: grid;
grid-template-columns: repeat(6, 1fr);
grid-template-rows: max-content;
gap: 10px;
overflow: hidden;
.card-list_item {
border: 1px solid #eee;
border-top-left-radius: 10px;
background-color: #eee;
overflow: hidden;
cursor: pointer;
.base_sku {
background: rgba(255, 255, 255, 0.699);
font-size: 12px;
display: inline-block;
width: 100%;
box-sizing: border-box;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
padding: 3px 5px;
border-radius: 2px;
}
.flex-between {
display: flex;
justify-content: space-between;
align-items: center;
.images-position {
display: flex;
height: 30px;
gap: 10px;
padding: 10px 6px 0;
.item-image {
width: 30px;
height: 30px;
border: 1px solid #909399;
cursor: pointer;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
}
b {
margin-right: 5px;
font-size: 15px;
}
}
}
}
.no-data {
margin-top: 300px;
display: flex;
align-items: center;
justify-content: center;
color: #777;
}
}
.empty {
flex: 1;
display: flex;
justify-content: center;
align-items: center;
color: #777;
overflow: hidden;
}
.tabs {
display: flex;
align-items: center;
gap: 10px;
border-bottom: 1px solid #f0f0f0;
height: 42px;
.tabs-node {
padding: 10px;
font-size: 14px;
color: #000;
cursor: pointer;
height: 40px;
}
.tabs-node:hover {
color: #409eff;
}
.tabs-node.tabs-node_active {
color: #409eff;
border-bottom: 2px solid #409eff;
font-weight: 600;
}
}
.expand-detail {
padding: 10px;
font-size: 14px;
color: #000;
.detail-item {
margin-bottom: 10px;
.label {
font-weight: 600;
}
.value {
color: #666;
}
}
}
.order-list-expand {
border-right: 1px solid #eee;
font-size: 14px;
color: #606266;
overflow: auto;
max-height: 600px;
}
.table-expand {
display: flex;
}
.order-list-expand_more {
text-align: center;
padding: 10px 0;
span {
cursor: pointer;
}
}
.order-list {
margin-top: 10px;
flex: 1;
:deep(.el-table__expand-icon > .el-icon) {
display: none;
}
:deep(.el-table__row) {
background-color: #f5f5f5;
}
:deep(.el-table__expanded-cell) {
padding: 0;
}
}
.order-detail {
display: flex;
font-size: 14px;
}
.order-detail_item {
flex: 1;
display: flex;
align-items: center;
.label {
color: #aaa;
margin-right: 6px;
}
.value {
color: #000;
flex: 1;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
.order-actual-payment {
width: 280px;
border-right: 1px solid #eee;
}
.order-memo {
width: 300px;
border-right: 1px solid #eee;
}
.order-time_info {
padding: 20px;
font-size: 14px;
}
.order-memo-item__content,
.order-memo-item__time {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.order-memo-info {
padding: 20px;
font-size: 14px;
}
.order-memo-item {
display: flex;
align-items: center;
line-height: 26px;
}
.order-memo-item div:not(:last-child) {
margin-right: 6px;
}
.order-time {
width: 300px;
border-right: 1px solid #eee;
}
.order-operate {
width: 100px;
}
.order-actual-payment_info {
font-size: 14px;
padding: 20px;
}
.order-operate_info {
padding: 20px;
:deep(.el-button) {
padding: 0;
font-size: 14px;
}
}
.header-search {
display: flex;
gap: 10px;
}
.dialog-footer {
text-align: center;
}
.order-detail_goods-info--content {
padding: 10px 0;
font-size: 14px;
:deep(.order-list-expand_item) {
padding: 10px 0;
}
}
.order-list-expand_item_info_title {
line-height: 26px;
display: flex;
align-items: center;
}
.order-list-expand_item_label {
margin-right: 6px;
}
.order-operate_info {
padding: 20px;
:deep(.el-button) {
padding: 0;
font-size: 14px;
}
}
.pagination{
display: flex;
align-items: center;
}
</style>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment