Commit ee1e96d4 by linjinhong

Merge branch 'dev_product_supply' of…

Merge branch 'dev_product_supply' of http://47.122.114.111:9999/qinjianhui/factory_front into dev_product_supply
parents 441b6295 71bc2511
...@@ -34,7 +34,6 @@ declare module 'vue' { ...@@ -34,7 +34,6 @@ declare module 'vue' {
ElImage: typeof import('element-plus/es')['ElImage'] ElImage: typeof import('element-plus/es')['ElImage']
ElInput: typeof import('element-plus/es')['ElInput'] ElInput: typeof import('element-plus/es')['ElInput']
ElInputNumber: typeof import('element-plus/es')['ElInputNumber'] ElInputNumber: typeof import('element-plus/es')['ElInputNumber']
ElLink: typeof import('element-plus/es')['ElLink']
ElMenu: typeof import('element-plus/es')['ElMenu'] ElMenu: typeof import('element-plus/es')['ElMenu']
ElMenuItem: typeof import('element-plus/es')['ElMenuItem'] ElMenuItem: typeof import('element-plus/es')['ElMenuItem']
ElOption: typeof import('element-plus/es')['ElOption'] ElOption: typeof import('element-plus/es')['ElOption']
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
"version": "0.0.0", "version": "0.0.0",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite --host",
"build": "npm run lint && vue-tsc && vite build", "build": "npm run lint && vue-tsc && vite build",
"preview": "vite preview", "preview": "vite preview",
"lint": "vue-tsc --noEmit && eslint" "lint": "vue-tsc --noEmit && eslint"
......
...@@ -4,7 +4,7 @@ import { showError } from '@/utils/ui.ts' ...@@ -4,7 +4,7 @@ import { showError } from '@/utils/ui.ts'
const axios = Axios.create({ const axios = Axios.create({
baseURL: import.meta.env.VITE_API_BASE, baseURL: import.meta.env.VITE_API_BASE,
timeout: 300000, //凯哥让改的超时时间 timeout: 30 * 60 * 1000, //半小时
}) })
const TOKEN_KEY = 'token' const TOKEN_KEY = 'token'
......
...@@ -48,3 +48,14 @@ export function addExternalAuthorisationApi( ...@@ -48,3 +48,14 @@ export function addExternalAuthorisationApi(
) { ) {
return axios.post<never, BaseRespData<never>>(url, data) return axios.post<never, BaseRespData<never>>(url, data)
} }
export function saveInventoryLowerLimitApi(inventoryLowerLimit: number) {
return axios.get<never, BaseRespData<never>>(
'factory/baseExternalAccount/setInventoryWarningFloor',
{ params: { inventoryWarningFloor: inventoryLowerLimit } },
)
}
export function getInventoryLowerLimitApi() {
return axios.get<never, BaseRespData<number>>(
'factory/baseExternalAccount/getInventoryWarningFloor',
)
}
import axios from './axios'
import { BasePaginationData, BaseRespData } from '@/types/api'
import { SearchForm, OutOfStockItem } from '@/types/api/outOfStockStatistics'
export function getOutOfStockStatisticsListApi(
data: SearchForm,
currentPage: number,
pageSize: number,
) {
return axios.post<never, BasePaginationData<OutOfStockItem>>(
'stockOutStatistics/getStockOutStatistics',
{ ...data, currentPage, pageSize },
)
}
export function exportOutOfStockStatisticsListApi(data: {
exportAll: boolean
indexes?: number[]
}) {
return axios.post<never, BaseRespData<never>>(
'stockOutStatistics/exportStockOutStatistics',
data,
)
}
...@@ -85,6 +85,23 @@ export function getCardOrderList( ...@@ -85,6 +85,23 @@ export function getCardOrderList(
}, },
) )
} }
export function uploadPRNFile(
id: number,
data: FormData,
) {
return axios.post<never, BaseRespData<string>>(
`/factory/podBatchDownload/uploadPRNFile?id=${id}`,
data
)
}
export function updatePRNDownloadStatus(
id: number
) {
return axios.get<never, BaseRespData<string>>(
`/factory/podBatchDownload/updatePRNDownloadStatus?id=${id}`
)
}
export function confirmOrderApi( export function confirmOrderApi(
data: number[], data: number[],
productionClient: string, productionClient: string,
...@@ -556,10 +573,15 @@ export function changeToFinished(ids: string) { ...@@ -556,10 +573,15 @@ export function changeToFinished(ids: string) {
) )
} }
export function reissueOrderApi(ids: string) { export function reissueOrderApi(data: {
return axios.get<never, BaseRespData<never>>( ids:string
reissueType:number
trackingNumber?:string
expressSheet:string
}) {
return axios.post<never, BaseRespData<never>>(
`factory/podJomallOrderUs/reissueOrder`, `factory/podJomallOrderUs/reissueOrder`,
{ params: { ids } }, data,
) )
} }
export function OrderCnReceiverAddress(idList: number[]) { export function OrderCnReceiverAddress(idList: number[]) {
......
...@@ -163,6 +163,13 @@ const router = createRouter({ ...@@ -163,6 +163,13 @@ const router = createRouter({
component: CustomersPage, component: CustomersPage,
}, },
{ {
path: '/supply/out-of-stock-statistics',
meta: {
title: '缺货统计',
},
component: () => import('@/views/supply/OutOfStockStatistics.vue')
},
{
path: '/system/delivery-note', path: '/system/delivery-note',
meta: { meta: {
title: '定制发货单', title: '定制发货单',
......
...@@ -148,19 +148,24 @@ const menu: MenuItem[] = [ ...@@ -148,19 +148,24 @@ const menu: MenuItem[] = [
}, },
], ],
}, },
{ {
index: '12', index: '14',
id: 4, id: 14,
label: '供应', label: '供应',
children: [ children: [
{ {
index: '/supply/supplierManagement', label: '缺货统计',
index: '/supply/out-of-stock-statistics',
id: 1, id: 1,
},
{
index: '/supply/supplierManagement',
id: 2,
label: '供应商管理', label: '供应商管理',
}, },
], ],
}, },
{ {
index: '11', index: '11',
id: 3, id: 3,
......
export interface OutOfStockItem {
id?: number
variantImage?: string
warehouseName?: string
locationCode?: string
warehouseSku?: string
productNo?: string
skuName?: string
currency?: string
costPrice?: number
stockOutNum?: number
salesNum?: number
warehouseSpu?: string
inventory?: number
occupyInventory?: number
freezeInventory?: number
purchaseNotInQuantity?: number
longestDelayDays?: number
sort?: number
}
export interface SearchForm {
warehouseId?: string | number
warehouseSku?: string
productNo?: string
skuName?: string
}
\ No newline at end of file
...@@ -48,8 +48,11 @@ export interface SearchForm { ...@@ -48,8 +48,11 @@ export interface SearchForm {
export interface PodUsOrderListData { export interface PodUsOrderListData {
id: number id: number
thirdOrderNumber?: string thirdOrderNumber?: string
prnUrl?: string
factoryOrderNumber?: string factoryOrderNumber?: string
prnDownloadStatus?: boolean
shopNumber?: string shopNumber?: string
isUpload?: boolean
factoryOnlineId?: number | null factoryOnlineId?: number | null
factoryNo?: number | null factoryNo?: number | null
factoryCode?: string | null factoryCode?: string | null
......
<script setup lang="ts">
import { ref } from 'vue'
import { Plus, Close } from '@element-plus/icons-vue'
import { reissueOrderApi, uploadExpressSheet } from '@/api/podUsOrder.ts'
import { PodUsOrderListData } from '@/types/api/podUsOrder.ts'
const dialogShow = ref(false)
const formRef = ref()
const open = () => {
form.value = {
reissueType: 1,
trackingNumber: '',
expressSheet: '',
file: null,
}
dialogShow.value = true
}
const emit = defineEmits(['success'])
const props = defineProps({
selection: {
type: Array,
default: () => [],
},
})
const formRules = {
reissueType: {
required: true,
message: '请选择补发方式',
trigger: 'change',
},
trackingNumber: {
required: true,
message: '请输入跟踪号',
trigger: 'blur',
},
file: {
required: true,
message: '请上传物流面单',
trigger: 'change',
},
}
interface Iform {
reissueType: number
trackingNumber: string
expressSheet: string
file: File | null
}
const form = ref<Iform>({
reissueType: 1,
trackingNumber: '',
expressSheet: '',
file: null,
})
defineExpose({ open })
const submit = async () => {
await formRef.value.validate()
if((props.selection as PodUsOrderListData[])[0].shipmentType===0 && form.value.reissueType!==1){
if(!form.value.expressSheet){
return ElMessage.warning('请上传物流面单')
}
}
await reissueOrderApi({
ids: (props.selection as PodUsOrderListData[]).map(e => e.id).join(),
reissueType: form.value.reissueType,
trackingNumber: form.value.trackingNumber,
expressSheet: form.value.expressSheet,
})
ElMessage.success('操作成功')
dialogShow.value = false
emit('success')
}
const radioChange = () => {
form.value.trackingNumber = ''
form.value.expressSheet = ''
form.value.file = null
}
const clearFile = () => {
form.value.file = null
form.value.expressSheet = ''
}
const createFormToUpload = () => {
const input = document.createElement('input')
input.type = 'file'
input.style.display = 'none'
input.accept = '.pdf'
input.name = 'file'
document.body.appendChild(input)
input.click()
input.onchange = async function() {
console.log(input.files)
if (input.files?.length !== 1) {
return ElMessage.warning('请上传一个面单')
}
form.value.file = input.files[0]
const fm = new FormData()
fm.append('file', input.files[0])
fm.append('trackingNumber', form.value.trackingNumber)
const res = await uploadExpressSheet(fm as never)
form.value.expressSheet = res.message || ''
}
}
</script>
<template>
<el-dialog v-model="dialogShow" title="补发" :close-on-click-modal="false">
<el-form v-if="selection.length" ref="formRef" :rules="formRules" :model="form">
<el-form-item required label="补发方式" prop="reissueType">
<el-radio-group
v-model="form.reissueType"
style="display: flex;flex-direction: column;align-items: flex-start;"
@change="radioChange">
<el-radio :label="1">原单补发</el-radio>
<el-radio
:disabled="(selection as PodUsOrderListData[])[0].shipmentType===0 && selection.length>1"
:label="2">换单补发,取消原单物流
</el-radio>
<el-radio
:disabled="(selection as PodUsOrderListData[])[0].shipmentType===0 && selection.length>1"
:label="3">换单补发,不取消原单物流
</el-radio>
</el-radio-group>
</el-form-item>
<span v-if="(selection as PodUsOrderListData[])[0].shipmentType===0 && selection.length>1" class="tip">自有物流选择选项2和选项3请单个操作,不支持批量操作;</span>
<el-form-item
v-if="(selection as PodUsOrderListData[])[0].shipmentType===0 && form.reissueType!==1" required
label="物流信息" prop="trackingNumber">
<div class="form-content">
<div class="content-item">
<div class="label">跟踪号</div>
<el-input v-model="form.trackingNumber" style="height: 40px" placeholder="请输入跟踪号"></el-input>
</div>
<div v-if="form.trackingNumber" class="content-item">
<div class="label">物流面单</div>
<div class="upload" @click="createFormToUpload">
<el-icon>
<Plus></Plus>
</el-icon>
</div>
<div v-if="form.file" class="file">
<div class="name">{{ form.file.name }}</div>
<div class="close" @click="clearFile">
<el-icon>
<Close></Close>
</el-icon>
</div>
</div>
</div>
</div>
</el-form-item>
<el-form-item v-if="(selection as PodUsOrderListData[])[0].shipmentType===0 && form.reissueType!==1">
<div class="tip-2">自有物流请联系客户提供新跟踪号和面单</div>
</el-form-item>
</el-form>
<template #footer>
<el-button @click="dialogShow=false">取消</el-button>
<el-button type="primary" @click="submit">确定</el-button>
</template>
</el-dialog>
</template>
<style scoped lang="scss">
.tip {
color: red;
position: relative;
top: -14px;
left: 79px;
}
.form-content, .content-item {
display: flex;
margin-right: 25px;
.upload {
border: 1px darkgray solid;
width: 50px;
cursor: pointer;
height: 50px;
display: flex;
align-items: center;
justify-content: center;
border-radius: 3px;
}
.file {
display: flex;
margin-left: 25px;
align-items: center;
gap: 6px;
.close {
cursor: pointer;
color: red;
}
}
.label {
width: 70px;
}
}
.tip-2{
color: red;
margin-left: 13px;
position: relative;
top: -9px;
}
</style>
...@@ -379,14 +379,14 @@ ...@@ -379,14 +379,14 @@
<ElFormItem> <ElFormItem>
<span> <span>
<ElButton link style="font-size: 12px" @click="resetSearchForm" <ElButton link style="font-size: 12px" @click="resetSearchForm"
><span title="重置查询条件">重置</span></ElButton ><span title="重置查询条件">重置</span></ElButton
> >
</span> </span>
</ElFormItem> </ElFormItem>
<ElFormItem> <ElFormItem>
<span> <span>
<ElButton ref="searchBtnRef" type="primary" @click="search" <ElButton ref="searchBtnRef" type="primary" @click="search"
>查询</ElButton >查询</ElButton
> >
</span> </span>
</ElFormItem> </ElFormItem>
...@@ -399,33 +399,43 @@ ...@@ -399,33 +399,43 @@
> >
<ElDropdown> <ElDropdown>
<el-button type="primary"> <el-button type="primary">
DTF排版<el-icon class="el-icon--right"><ArrowDown /></el-icon> DTF排版
<el-icon class="el-icon--right">
<ArrowDown />
</el-icon>
</el-button> </el-button>
<template #dropdown> <template #dropdown>
<ElDropdownMenu> <ElDropdownMenu>
<ElDropdownItem <ElDropdownItem
:loading="tifDownloadLoading" :loading="tifDownloadLoading"
@click="downloadTif('tiff', 42)" @click="downloadTif('tiff', 42)"
>TIF(40+2cm)</ElDropdownItem >TIF(40+2cm)
</ElDropdownItem
> >
<ElDropdownItem <ElDropdownItem
:loading="tifDownloadLoading" :loading="tifDownloadLoading"
@click="downloadTif('tiff', 60)" @click="downloadTif('tiff', 60)"
>TIF(60cm)</ElDropdownItem >TIF(60cm)
</ElDropdownItem
> >
<ElDropdownItem <ElDropdownItem
:loading="pngDownloadLoading" :loading="pngDownloadLoading"
@click="downloadTif('png', 42)" @click="downloadTif('png', 42)"
>PNG(40+2cm)</ElDropdownItem >PNG(40+2cm)
</ElDropdownItem
> >
<ElDropdownItem <ElDropdownItem
:loading="pngDownloadLoading" :loading="pngDownloadLoading"
@click="downloadTif('png', 60)" @click="downloadTif('png', 60)"
>PNG(60cm)</ElDropdownItem >PNG(60cm)
</ElDropdownItem
> >
</ElDropdownMenu></template </ElDropdownMenu>
></ElDropdown </template
></ElFormItem >
</ElDropdown
>
</ElFormItem
> >
<!-- <ElFormItem <!-- <ElFormItem
v-if=" v-if="
...@@ -609,7 +619,7 @@ ...@@ -609,7 +619,7 @@
<ElFormItem v-if="status === 'WAIT_SHIPMENT'"> <ElFormItem v-if="status === 'WAIT_SHIPMENT'">
<span class="item"> <span class="item">
<ElButton type="primary" @click="completeDelivery()" <ElButton type="primary" @click="completeDelivery()"
>完成发货</ElButton >完成发货</ElButton
> >
</span> </span>
</ElFormItem> </ElFormItem>
...@@ -629,7 +639,7 @@ ...@@ -629,7 +639,7 @@
selection.some((item) => item.shipmentType !== 1) selection.some((item) => item.shipmentType !== 1)
" "
@click="getOrderByIdApi('createLogisticsOrder')" @click="getOrderByIdApi('createLogisticsOrder')"
>创建物流订单</ElDropdownItem >创建物流订单</ElDropdownItem
> >
<ElDropdownItem <ElDropdownItem
:disabled=" :disabled="
...@@ -637,7 +647,7 @@ ...@@ -637,7 +647,7 @@
selection.some((item) => item.shipmentType !== 1) selection.some((item) => item.shipmentType !== 1)
" "
@click="getOrderByIdApi('getTrackingNumber')" @click="getOrderByIdApi('getTrackingNumber')"
>获取跟踪号</ElDropdownItem >获取跟踪号</ElDropdownItem
> >
<ElDropdownItem <ElDropdownItem
:disabled=" :disabled="
...@@ -645,7 +655,7 @@ ...@@ -645,7 +655,7 @@
selection.some((item) => item.shipmentType !== 1) selection.some((item) => item.shipmentType !== 1)
" "
@click="getOrderByIdApi('getPrintOrder')" @click="getOrderByIdApi('getPrintOrder')"
>获取打印面单</ElDropdownItem >获取打印面单</ElDropdownItem
> >
<ElDropdownItem <ElDropdownItem
:disabled=" :disabled="
...@@ -653,7 +663,7 @@ ...@@ -653,7 +663,7 @@
selection.some((item) => item.shipmentType !== 1) selection.some((item) => item.shipmentType !== 1)
" "
@click="getOrderByIdApi('cancelLogisticsOrder')" @click="getOrderByIdApi('cancelLogisticsOrder')"
>取消物流订单</ElDropdownItem >取消物流订单</ElDropdownItem
> >
<!-- <ElDropdownItem <!-- <ElDropdownItem
:disabled=" :disabled="
...@@ -690,7 +700,7 @@ ...@@ -690,7 +700,7 @@
> >
<span class="item"> <span class="item">
<ElButton type="primary" @click="downloadMaterial" <ElButton type="primary" @click="downloadMaterial"
>下载素材</ElButton >下载素材</ElButton
> >
</span> </span>
</ElFormItem> </ElFormItem>
...@@ -766,7 +776,7 @@ ...@@ -766,7 +776,7 @@
selection.length === 0 && cardSelection.length === 0 selection.length === 0 && cardSelection.length === 0
" "
@click="rejectOrder('TO_BE_CONFIRMED')" @click="rejectOrder('TO_BE_CONFIRMED')"
>待确认</ElDropdownItem >待确认</ElDropdownItem
> >
<ElDropdownItem <ElDropdownItem
v-if=" v-if="
...@@ -778,7 +788,7 @@ ...@@ -778,7 +788,7 @@
selection.length === 0 && cardSelection.length === 0 selection.length === 0 && cardSelection.length === 0
" "
@click="rejectOrder('CREATE_LOGISTICS')" @click="rejectOrder('CREATE_LOGISTICS')"
>待创建物流</ElDropdownItem >待创建物流</ElDropdownItem
> >
<ElDropdownItem <ElDropdownItem
v-if="status === 'PICKING' || status === 'IN_PRODUCTION'" v-if="status === 'PICKING' || status === 'IN_PRODUCTION'"
...@@ -786,7 +796,7 @@ ...@@ -786,7 +796,7 @@
selection.length === 0 && cardSelection.length === 0 selection.length === 0 && cardSelection.length === 0
" "
@click="rejectOrder('TO_BE_ARRANGE')" @click="rejectOrder('TO_BE_ARRANGE')"
>待排单</ElDropdownItem >待排单</ElDropdownItem
> >
<ElDropdownItem <ElDropdownItem
v-if="status === 'IN_PRODUCTION'" v-if="status === 'IN_PRODUCTION'"
...@@ -794,7 +804,7 @@ ...@@ -794,7 +804,7 @@
selection.length === 0 && cardSelection.length === 0 selection.length === 0 && cardSelection.length === 0
" "
@click="rejectOrder('PICKING')" @click="rejectOrder('PICKING')"
>待拣胚</ElDropdownItem >待拣胚</ElDropdownItem
> >
</ElDropdownMenu> </ElDropdownMenu>
</template> </template>
...@@ -822,7 +832,7 @@ ...@@ -822,7 +832,7 @@
<ElFormItem v-if="status === 'BATCH_DOWNLOAD'"> <ElFormItem v-if="status === 'BATCH_DOWNLOAD'">
<span class="item"> <span class="item">
<ElButton type="danger" @click="handleBatchDelete('batch')" <ElButton type="danger" @click="handleBatchDelete('batch')"
>批量删除</ElButton >批量删除</ElButton
> >
</span> </span>
</ElFormItem> </ElFormItem>
...@@ -850,7 +860,7 @@ ...@@ -850,7 +860,7 @@
blue: item.quantity && item.quantity > 0, blue: item.quantity && item.quantity > 0,
red: item.status === 'EXCEPTION_ORDER', red: item.status === 'EXCEPTION_ORDER',
}" }"
>{{ item.quantity }}</span >{{ item.quantity }}</span
> >
<span <span
v-if=" v-if="
...@@ -859,45 +869,12 @@ ...@@ -859,45 +869,12 @@
interceptionStatus.shipment['0']) interceptionStatus.shipment['0'])
" "
class="tabs-node-quantity" class="tabs-node-quantity"
>+{{ >+{{
(interceptionStatus.production['0'] || 0) + (interceptionStatus.production['0'] || 0) +
(interceptionStatus.shipment['0'] || 0) || '' (interceptionStatus.shipment['0'] || 0) || ''
}}</span }}</span
> >
</div> </div>
<!-- <div
v-if="item.status === 'EXCEPTION_ORDER'"
:key="item.status"
class="tabs-node"
>
<el-dropdown @command="handleExceptionCommand">
<div>
<span
class="tabs-node_label"
style="color: #000; font-weight: 500"
>
异常单
</span>
<span
class="tabs-node_count"
:class="{
blue: item.quantity && item.quantity > 0,
red: item.status === 'EXCEPTION_ORDER',
}"
>{{ item.quantity }}</span
>
<el-icon class="el-icon--right"><arrow-down /></el-icon>
</div>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item command="1">待分派</el-dropdown-item>
<el-dropdown-item command="2">待处理</el-dropdown-item>
<el-dropdown-item command="3">已处理</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div> -->
</div> </div>
</div> </div>
<div class="order-content flex-1 flex-column overflow-hidden mt-10"> <div class="order-content flex-1 flex-column overflow-hidden mt-10">
...@@ -931,11 +908,11 @@ ...@@ -931,11 +908,11 @@
@click="handleWaitTrackCommand(1)" @click="handleWaitTrackCommand(1)"
> >
<span class="sub-status-item-label">{{ <span class="sub-status-item-label">{{
trackRegisterCount[0]?.name trackRegisterCount[0]?.name
}}</span> }}</span>
<span class="tabs-node_count">{{ <span class="tabs-node_count">{{
trackRegisterCount[0]?.count || 0 trackRegisterCount[0]?.count || 0
}}</span> }}</span>
</div> </div>
<div <div
class="sub-status-item" class="sub-status-item"
...@@ -943,11 +920,11 @@ ...@@ -943,11 +920,11 @@
@click="handleWaitTrackCommand(2)" @click="handleWaitTrackCommand(2)"
> >
<span class="sub-status-item-label">{{ <span class="sub-status-item-label">{{
trackRegisterCount[1]?.name trackRegisterCount[1]?.name
}}</span> }}</span>
<span class="tabs-node_count blue">{{ <span class="tabs-node_count blue">{{
trackRegisterCount[1]?.count || 0 trackRegisterCount[1]?.count || 0
}}</span> }}</span>
</div> </div>
<div <div
class="sub-status-item" class="sub-status-item"
...@@ -955,11 +932,11 @@ ...@@ -955,11 +932,11 @@
@click="handleWaitTrackCommand(3)" @click="handleWaitTrackCommand(3)"
> >
<span class="sub-status-item-label">{{ <span class="sub-status-item-label">{{
trackRegisterCount[2]?.name trackRegisterCount[2]?.name
}}</span> }}</span>
<span class="tabs-node_count green">{{ <span class="tabs-node_count green">{{
trackRegisterCount[2]?.count || 0 trackRegisterCount[2]?.count || 0
}}</span> }}</span>
</div> </div>
<div <div
class="sub-status-item" class="sub-status-item"
...@@ -967,11 +944,11 @@ ...@@ -967,11 +944,11 @@
@click="handleWaitTrackCommand(4)" @click="handleWaitTrackCommand(4)"
> >
<span class="sub-status-item-label">{{ <span class="sub-status-item-label">{{
trackRegisterCount[3]?.name trackRegisterCount[3]?.name
}}</span> }}</span>
<span class="tabs-node_count yellow">{{ <span class="tabs-node_count yellow">{{
trackRegisterCount[3]?.count || 0 trackRegisterCount[3]?.count || 0
}}</span> }}</span>
</div> </div>
<div <div
class="sub-status-item" class="sub-status-item"
...@@ -979,11 +956,11 @@ ...@@ -979,11 +956,11 @@
@click="handleWaitTrackCommand(5)" @click="handleWaitTrackCommand(5)"
> >
<span class="sub-status-item-label">{{ <span class="sub-status-item-label">{{
trackRegisterCount[4]?.name trackRegisterCount[4]?.name
}}</span> }}</span>
<span class="tabs-node_count red">{{ <span class="tabs-node_count red">{{
trackRegisterCount[4]?.count || 0 trackRegisterCount[4]?.count || 0
}}</span> }}</span>
</div> </div>
</div> </div>
<div v-if="status === 'INTERCEPTED'" class="sub-status mb-10"> <div v-if="status === 'INTERCEPTED'" class="sub-status mb-10">
...@@ -996,7 +973,7 @@ ...@@ -996,7 +973,7 @@
<span <span
v-if="interceptionStatus.production['0']" v-if="interceptionStatus.production['0']"
class="tabs-node_count blue" class="tabs-node_count blue"
>{{ interceptionStatus.production['0'] }}</span >{{ interceptionStatus.production['0'] }}</span
> >
</div> </div>
<div <div
...@@ -1008,7 +985,7 @@ ...@@ -1008,7 +985,7 @@
<span <span
v-if="interceptionStatus.production['1']" v-if="interceptionStatus.production['1']"
class="tabs-node_count blue" class="tabs-node_count blue"
>{{ interceptionStatus.production['1'] }}</span >{{ interceptionStatus.production['1'] }}</span
> >
</div> </div>
<div <div
...@@ -1020,7 +997,7 @@ ...@@ -1020,7 +997,7 @@
<span <span
v-if="interceptionStatus.production['2']" v-if="interceptionStatus.production['2']"
class="tabs-node_count red" class="tabs-node_count red"
>{{ interceptionStatus.production['2'] }}</span >{{ interceptionStatus.production['2'] }}</span
> >
</div> </div>
<div <div
...@@ -1032,7 +1009,7 @@ ...@@ -1032,7 +1009,7 @@
<span <span
v-if="interceptionStatus.shipment['0']" v-if="interceptionStatus.shipment['0']"
class="tabs-node_count blue" class="tabs-node_count blue"
>{{ interceptionStatus.shipment['0'] }}</span >{{ interceptionStatus.shipment['0'] }}</span
> >
</div> </div>
<div <div
...@@ -1044,7 +1021,7 @@ ...@@ -1044,7 +1021,7 @@
<span <span
v-if="interceptionStatus.shipment['1']" v-if="interceptionStatus.shipment['1']"
class="tabs-node_count blue" class="tabs-node_count blue"
>{{ interceptionStatus.shipment['1'] }}</span >{{ interceptionStatus.shipment['1'] }}</span
> >
</div> </div>
<div <div
...@@ -1056,7 +1033,7 @@ ...@@ -1056,7 +1033,7 @@
<span <span
v-if="interceptionStatus.shipment['2']" v-if="interceptionStatus.shipment['2']"
class="tabs-node_count red" class="tabs-node_count red"
>{{ interceptionStatus.shipment['2'] }}</span >{{ interceptionStatus.shipment['2'] }}</span
> >
</div> </div>
</div> </div>
...@@ -1255,7 +1232,7 @@ ...@@ -1255,7 +1232,7 @@
</div> </div>
<div class="goods-item-info-item"> <div class="goods-item-info-item">
<span class="goods-item-info-item-label" <span class="goods-item-info-item-label"
>第三方生产单号:</span >第三方生产单号:</span
> >
<span <span
class="goods-item-info-item-value" class="goods-item-info-item-value"
...@@ -1305,14 +1282,14 @@ ...@@ -1305,14 +1282,14 @@
> >
<!-- <span class="goods-item-info-item-label">补胚状态:</span> --> <!-- <span class="goods-item-info-item-label">补胚状态:</span> -->
<el-tag size="small" effect="dark" type="danger" <el-tag size="small" effect="dark" type="danger"
>补胚中 >补胚中
</el-tag> </el-tag>
</div> </div>
</div> </div>
<div class="goods-item-info"> <div class="goods-item-info">
<div class="goods-item-info-item"> <div class="goods-item-info-item">
<span class="goods-item-info-item-label" <span class="goods-item-info-item-label"
>商品单价($):</span >商品单价($):</span
> >
<span class="goods-item-info-item-value"> <span class="goods-item-info-item-value">
{{ item.productPrice }} {{ item.productPrice }}
...@@ -1339,14 +1316,14 @@ ...@@ -1339,14 +1316,14 @@
<div class="goods-item-info-item"> <div class="goods-item-info-item">
<span class="goods-item-info-item-label">{{ <span class="goods-item-info-item-label">{{
status === 'EXCEPTION_ORDER' || status === 'EXCEPTION_ORDER' ||
status === 'PICKING' || status === 'PICKING' ||
status === 'TO_BE_CONFIRMED' || status === 'TO_BE_CONFIRMED' ||
status === 'STOCK_OUT' || status === 'STOCK_OUT' ||
status === 'CREATE_LOGISTICS' status === 'CREATE_LOGISTICS'
? '数量:' ? '数量:'
: '已生产数量:' : '已生产数量:'
}}</span> }}</span>
<span class="goods-item-info-item-value"> <span class="goods-item-info-item-value">
{{ {{
status === 'EXCEPTION_ORDER' || status === 'EXCEPTION_ORDER' ||
...@@ -1417,7 +1394,7 @@ ...@@ -1417,7 +1394,7 @@
type="success" type="success"
style="height: 23px" style="height: 23px"
@click="applyForReplenishment(item)" @click="applyForReplenishment(item)"
>申请补胚 >申请补胚
</el-button> </el-button>
</div> </div>
...@@ -1436,7 +1413,7 @@ ...@@ -1436,7 +1413,7 @@
type="primary" type="primary"
style="height: 23px; padding: 0" style="height: 23px; padding: 0"
@click="downloadMaterialItem(item)" @click="downloadMaterialItem(item)"
>下载素材 >下载素材
</el-button> </el-button>
<el-button <el-button
...@@ -1445,7 +1422,7 @@ ...@@ -1445,7 +1422,7 @@
type="warning" type="warning"
style="height: 23px; margin: 0" style="height: 23px; margin: 0"
@click="showArrange(3, item)" @click="showArrange(3, item)"
>排版 >排版
</el-button> </el-button>
</div> </div>
<div <div
...@@ -1465,7 +1442,7 @@ ...@@ -1465,7 +1442,7 @@
type="success" type="success"
style="height: 23px" style="height: 23px"
@click="printProductionOrder(1, item)" @click="printProductionOrder(1, item)"
>打印生产单 >打印生产单
</el-button> </el-button>
</div> </div>
</div> </div>
...@@ -1565,13 +1542,14 @@ ...@@ -1565,13 +1542,14 @@
</div> </div>
<div class="order-detail-item"> <div class="order-detail-item">
<span class="order-detail-item-label">订单来源:</span> <span class="order-detail-item-label">订单来源:</span>
<span class="order-detail-item-value"> <span :class="{'red-big':row.source==='factory-reissue'}" class="order-detail-item-value">
{{ {{
row.source row.source
? { ? {
'jomall-erp': 'erp推送', 'jomall-erp': 'erp推送',
'third-party': '第三方推送', 'third-party': '第三方推送',
}[row.source as 'jomall-erp' | 'third-party'] 'factory-reissue': '补发订单',
}[row.source as 'jomall-erp' | 'third-party' | 'factory-reissue']
: '' : ''
}} }}
</span> </span>
...@@ -1687,17 +1665,17 @@ ...@@ -1687,17 +1665,17 @@
<el-timeline-item <el-timeline-item
:color="row.createTime ? '#409EFF' : ''" :color="row.createTime ? '#409EFF' : ''"
:timestamp="row.createTime" :timestamp="row.createTime"
>创建时间 >创建时间
</el-timeline-item> </el-timeline-item>
<el-timeline-item <el-timeline-item
:color="row.startStockingTime ? '#E6A23C' : ''" :color="row.startStockingTime ? '#E6A23C' : ''"
:timestamp="row.startStockingTime" :timestamp="row.startStockingTime"
>确认时间 >确认时间
</el-timeline-item> </el-timeline-item>
<el-timeline-item <el-timeline-item
:color="row.finishTime ? '#67C23A' : ''" :color="row.finishTime ? '#67C23A' : ''"
:timestamp="row.finishTime" :timestamp="row.finishTime"
>发货时间 >发货时间
</el-timeline-item> </el-timeline-item>
<el-timeline-item <el-timeline-item
v-if="status === 'IN_TRANSIT'" v-if="status === 'IN_TRANSIT'"
...@@ -1781,6 +1759,26 @@ ...@@ -1781,6 +1759,26 @@
{{ row.automaticComposing ? '是' : '否' }} {{ row.automaticComposing ? '是' : '否' }}
</div> </div>
</template> </template>
<template #prn="{ row }">
<div style="display: flex">
<span :title="fileName(row)" class="flex-1">{{ fileName(row) }}</span>
<el-link :disabled="row.isUpload" underline="never" type="success" @click="uploadFile(row)">上传</el-link>
<el-icon v-if="row.isUpload" style="right: 0;top:5px;" class="is-loading"
>
<Loading
/>
</el-icon>
<el-link
:disabled="!row.prnUrl" style="margin-left: 8px" underline="never" type="primary"
@click="downloadRowProFile(row)">下载
</el-link>
<el-icon v-if="row.prnDownloadStatus" style="right: -2px" class="check-icon"
>
<CircleCheckFilled
/>
</el-icon>
</div>
</template>
<template #composingParam="{ row }"> <template #composingParam="{ row }">
<div style="white-space: pre-line"> <div style="white-space: pre-line">
{{ row.composingParam?.split(';').join('\n') }} {{ row.composingParam?.split(';').join('\n') }}
...@@ -1809,7 +1807,7 @@ ...@@ -1809,7 +1807,7 @@
下载 下载
</ElButton> </ElButton>
<el-icon v-if="row.downloadStatus" class="check-icon" <el-icon v-if="row.downloadStatus" class="check-icon"
><CircleCheckFilled ><CircleCheckFilled
/></el-icon> /></el-icon>
</span> </span>
<!-- <span class="operate-item"> <!-- <span class="operate-item">
...@@ -1825,36 +1823,39 @@ ...@@ -1825,36 +1823,39 @@
<span class="operate-item"> <span class="operate-item">
<ElButton <ElButton
link link
title="打印拣货单"
type="primary" type="primary"
@click="printPickingOrderItem(row, 1)" @click="printPickingOrderItem(row, 1)"
> >
打印拣货单 拣货单
</ElButton> </ElButton>
<el-icon v-if="row.printPickOrder" class="check-icon" <el-icon v-if="row.printPickOrder" class="check-icon"
><CircleCheckFilled ><CircleCheckFilled
/></el-icon> /></el-icon>
</span> </span>
<span class="operate-item"> <span class="operate-item">
<ElButton <ElButton
link link
title="打印生产单"
type="primary" type="primary"
@click="printPickingOrderItem(row, 2)" @click="printPickingOrderItem(row, 2)"
> >
打印生产单 生产单
</ElButton> </ElButton>
<el-icon v-if="row.printProductOrder" class="check-icon" <el-icon v-if="row.printProductOrder" class="check-icon"
><CircleCheckFilled ><CircleCheckFilled
/></el-icon> /></el-icon>
</span> </span>
<span class="operate-item"> <span class="operate-item">
<ElButton <ElButton
:disabled="row.productNum > 50" :disabled="row.productNum > 50"
link link
title="重新排版"
type="warning" type="warning"
:loading="reComposingLoadingMap[row.id]" :loading="reComposingLoadingMap[row.id]"
@click="showArrange(1, row)" @click="showArrange(1, row)"
> >
新排版
</ElButton> </ElButton>
</span> </span>
<span class="operate-item"> <span class="operate-item">
...@@ -1896,7 +1897,7 @@ ...@@ -1896,7 +1897,7 @@
class="operate-item" class="operate-item"
> >
<ElButton link type="warning" @click="updateTrackingNumber(row)" <ElButton link type="warning" @click="updateTrackingNumber(row)"
>修改跟踪号</ElButton >修改跟踪号</ElButton
> >
</span> </span>
<!-- <span <!-- <span
...@@ -1972,7 +1973,7 @@ ...@@ -1972,7 +1973,7 @@
class="operate-item" class="operate-item"
> >
<ElButton link type="primary" @click="logTrajectory(row)" <ElButton link type="primary" @click="logTrajectory(row)"
>物流轨迹</ElButton >物流轨迹</ElButton
> >
</span> </span>
</div> </div>
...@@ -1994,8 +1995,8 @@ ...@@ -1994,8 +1995,8 @@
<div <div
v-for="(cardItem) in tableData as ProductList[]" v-for="(cardItem) in tableData as ProductList[]"
:key="cardItem.id" :key="cardItem.id"
class="card-list-item"
ref="cardRefs" ref="cardRefs"
class="card-list-item"
@click="cardClick(cardItem)" @click="cardClick(cardItem)"
@mouseleave="handleChangeImages(null, cardItem)" @mouseleave="handleChangeImages(null, cardItem)"
> >
...@@ -2043,26 +2044,27 @@ ...@@ -2043,26 +2044,27 @@
type="primary" type="primary"
:title="item.name || ''" :title="item.name || ''"
style="margin-bottom: 2px" style="margin-bottom: 2px"
>{{ item.name || '' }}</el-tag >{{ item.name || '' }}
</el-tag
> >
</div> </div>
</template> </template>
<div <div
class="flex" v-if="cardItem.customTagList?.length"
ref="tagRefs" ref="tagRefs"
class="flex"
style="gap: 5px; overflow: hidden" style="gap: 5px; overflow: hidden"
v-if="cardItem.customTagList?.length"
> >
<el-tag <el-tag
size="small"
type="primary"
v-for="(item, index) in cardItem.customTagList.slice( v-for="(item, index) in cardItem.customTagList.slice(
0, 0,
3, 3,
)" )"
:key="index" :key="index"
><span size="small"
style=" type="primary"
><span
style="
width: 50px; width: 50px;
text-align: center; text-align: center;
overflow: hidden; overflow: hidden;
...@@ -2070,15 +2072,16 @@ ...@@ -2070,15 +2072,16 @@
text-overflow: ellipsis; text-overflow: ellipsis;
display: inline-block; display: inline-block;
" "
:title="item.name || ''" :title="item.name || ''"
>{{ item.name || '' }}</span >{{ item.name || '' }}</span
></el-tag ></el-tag
> >
<el-tag <el-tag
v-if="cardItem.customTagList?.slice(3)?.length"
size="small" size="small"
type="primary" type="primary"
v-if="cardItem.customTagList?.slice(3)?.length" >+{{ cardItem.customTagList.slice(3).length }}
>+{{ cardItem.customTagList.slice(3).length }}</el-tag </el-tag
> >
</div> </div>
</el-tooltip> </el-tooltip>
...@@ -2163,7 +2166,7 @@ ...@@ -2163,7 +2166,7 @@
:title="`商品名称:${cardItem?.productName || ''}`" :title="`商品名称:${cardItem?.productName || ''}`"
> >
<span class="grid-item-value" <span class="grid-item-value"
>{{ cardItem?.productName }} >{{ cardItem?.productName }}
</span> </span>
</div> </div>
<div <div
...@@ -2306,7 +2309,7 @@ ...@@ -2306,7 +2309,7 @@
</div> </div>
<div v-if="cardItem.isReplenishment" class="grid-item"> <div v-if="cardItem.isReplenishment" class="grid-item">
<el-tag size="small" type="danger" effect="dark" <el-tag size="small" type="danger" effect="dark"
>补胚中 >补胚中
</el-tag> </el-tag>
</div> </div>
</div> </div>
...@@ -2319,10 +2322,10 @@ ...@@ -2319,10 +2322,10 @@
<div class="pagination"> <div class="pagination">
<div class="total"> <div class="total">
<span <span
>已选择 >已选择
<span style="color: red">{{ <span style="color: red">{{
selection.length || cardSelection.length selection.length || cardSelection.length
}}</span> }}</span>
条数据</span 条数据</span
> >
</div> </div>
...@@ -2339,15 +2342,15 @@ ...@@ -2339,15 +2342,15 @@
></ElPagination> ></ElPagination>
<div class="pageSize"> <div class="pageSize">
<span <span
>自定义条数 >自定义条数
<span <span
><el-input ><el-input
v-model="pageSize" v-model="pageSize"
type="number" type="number"
style="width: 100px" style="width: 100px"
clearable clearable
@blur="inputBlur" @blur="inputBlur"
></el-input ></el-input
></span> ></span>
/</span /</span
> >
...@@ -2459,7 +2462,7 @@ ...@@ -2459,7 +2462,7 @@
link link
style="margin-left: 10px" style="margin-left: 10px"
@click="changeChinaTime('Asia/Shanghai')" @click="changeChinaTime('Asia/Shanghai')"
>北京时间 >北京时间
</el-button> </el-button>
<el-button <el-button
:type="timeType === 'America/New_York' ? 'primary' : ''" :type="timeType === 'America/New_York' ? 'primary' : ''"
...@@ -2467,7 +2470,7 @@ ...@@ -2467,7 +2470,7 @@
link link
style="margin-left: 10px" style="margin-left: 10px"
@click="changeChinaTime('America/New_York')" @click="changeChinaTime('America/New_York')"
>新泽西时间 >新泽西时间
</el-button> </el-button>
<el-button <el-button
:type="timeType === 'America/Los_Angeles' ? 'primary' : ''" :type="timeType === 'America/Los_Angeles' ? 'primary' : ''"
...@@ -2475,7 +2478,7 @@ ...@@ -2475,7 +2478,7 @@
link link
style="margin-left: 10px" style="margin-left: 10px"
@click="changeChinaTime('America/Los_Angeles')" @click="changeChinaTime('America/Los_Angeles')"
>洛杉矶时间 >洛杉矶时间
</el-button> </el-button>
</div> </div>
</div> </div>
...@@ -2639,8 +2642,8 @@ ...@@ -2639,8 +2642,8 @@
v-model:form="currentRow" v-model:form="currentRow"
v-model:visible="updateAddVisible" v-model:visible="updateAddVisible"
:country-list="countryList" :country-list="countryList"
@success="search"
:type="updateAddressType" :type="updateAddressType"
@success="search"
></UpdateAddress> ></UpdateAddress>
<ElDialog <ElDialog
v-model="exceptionDialogVisible" v-model="exceptionDialogVisible"
...@@ -2774,7 +2777,7 @@ ...@@ -2774,7 +2777,7 @@
:loading="exportLoading" :loading="exportLoading"
type="primary" type="primary"
@click="submitExportForm" @click="submitExportForm"
>确认</el-button >确认</el-button
> >
</span> </span>
</template> </template>
...@@ -2842,7 +2845,8 @@ ...@@ -2842,7 +2845,8 @@
typesettingVisible = false typesettingVisible = false
} }
" "
>取消</el-button >取消
</el-button
> >
<el-button type="primary" @click="submitTypesetting">确认</el-button> <el-button type="primary" @click="submitTypesetting">确认</el-button>
</template> </template>
...@@ -2886,6 +2890,7 @@ ...@@ -2886,6 +2890,7 @@
<ElButton type="primary" @click="confirmReplenishment">确定</ElButton> <ElButton type="primary" @click="confirmReplenishment">确定</ElButton>
</template> </template>
</ElDialog> </ElDialog>
<ReissueOrderComponent ref="reissueOrderRef" :selection="selection" @success="handleSuccess"></ReissueOrderComponent>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import LogisticsWaySelect from '../../logistics/components/LogisticsWaySelect.tsx' import LogisticsWaySelect from '../../logistics/components/LogisticsWaySelect.tsx'
...@@ -2903,6 +2908,7 @@ import { ...@@ -2903,6 +2908,7 @@ import {
} from '@element-plus/icons-vue' } from '@element-plus/icons-vue'
import { import {
getCardOrderList, getCardOrderList,
uploadPRNFile,
getOrderList, getOrderList,
getOrderTabData, getOrderTabData,
confirmOrderApi, confirmOrderApi,
...@@ -2964,7 +2970,7 @@ import { ...@@ -2964,7 +2970,7 @@ import {
getCustomTagListApi, getCustomTagListApi,
getLogisticsWayApi, getLogisticsWayApi,
printNormalPickPdfApi, printNormalPickPdfApi,
reissueOrderApi updatePRNDownloadStatus,
} from '@/api/podUsOrder' } from '@/api/podUsOrder'
import { BaseRespData } from '@/types/api' import { BaseRespData } from '@/types/api'
...@@ -2997,6 +3003,7 @@ import { showConfirm } from '@/utils/ui' ...@@ -2997,6 +3003,7 @@ import { showConfirm } from '@/utils/ui'
import { import {
DocumentCopy, DocumentCopy,
EditPen, EditPen,
Loading,
CircleCheckFilled, CircleCheckFilled,
} from '@element-plus/icons-vue' } from '@element-plus/icons-vue'
import { Column, ElFormItem } from 'element-plus' import { Column, ElFormItem } from 'element-plus'
...@@ -3014,8 +3021,10 @@ import { isArray, isString } from '@/utils/validate' ...@@ -3014,8 +3021,10 @@ import { isArray, isString } from '@/utils/validate'
import platformJson from '../../../json/platform.json' import platformJson from '../../../json/platform.json'
import { getToken } from '@/api/axios' import { getToken } from '@/api/axios'
import usePermissionBtnStore from '@/store/permission' import usePermissionBtnStore from '@/store/permission'
import ReissueOrderComponent from './components/ReissueOrder.vue'
const permissionBtns = usePermissionBtnStore() const permissionBtns = usePermissionBtnStore()
import { import {
useRouter, useRouter,
type NavigationGuardNext, type NavigationGuardNext,
...@@ -3025,7 +3034,7 @@ import { ...@@ -3025,7 +3034,7 @@ import {
declare global { declare global {
interface Window { interface Window {
ActiveXObject: { ActiveXObject: {
new (type: string): XMLHttpRequest new(type: string): XMLHttpRequest
} }
VBS_BinaryToArray: { VBS_BinaryToArray: {
(data: unknown): { toArray(): number[] } (data: unknown): { toArray(): number[] }
...@@ -3045,10 +3054,14 @@ const sourceList = [ ...@@ -3045,10 +3054,14 @@ const sourceList = [
{ {
name: '第三方推送', name: '第三方推送',
id: 'third-party', id: 'third-party',
},{
name: '补发订单',
id: 'factory-reissue',
}, },
] ]
const sizes = ['FS', 'XS', 'S', 'M', 'L', 'XL', 'XXL', '3XL', '4XL', '5XL'] const sizes = ['FS', 'XS', 'S', 'M', 'L', 'XL', 'XXL', '3XL', '4XL', '5XL']
const tabsNav = ref<Tab[]>() const tabsNav = ref<Tab[]>()
const reissueOrderRef = ref()
const isAuto = ref(true) const isAuto = ref(true)
const countryList = ref([]) const countryList = ref([])
const logisticsWayList = ref<{ name: string; id: number }[]>([]) const logisticsWayList = ref<{ name: string; id: number }[]>([])
...@@ -3134,10 +3147,10 @@ const submitExportForm = async () => { ...@@ -3134,10 +3147,10 @@ const submitExportForm = async () => {
...params, ...params,
...(resourceType === 2 ...(resourceType === 2
? { ? {
...searchForm.value, ...searchForm.value,
startTime: timeRange.value?.[0] || null, startTime: timeRange.value?.[0] || null,
endTime: timeRange.value?.[1] || null, endTime: timeRange.value?.[1] || null,
} }
: {}), : {}),
}) })
ElMessage.success('请求成功,请稍后到右上角[我的下载]中查看') ElMessage.success('请求成功,请稍后到右上角[我的下载]中查看')
...@@ -3552,6 +3565,12 @@ const tableColumns = computed(() => { ...@@ -3552,6 +3565,12 @@ const tableColumns = computed(() => {
prop: 'automaticComposing', prop: 'automaticComposing',
slot: 'automaticComposing', slot: 'automaticComposing',
align: 'center', align: 'center',
}, {
label: 'PRN文件',
width: 300,
prop: 'automaticComposing',
slot: 'prn',
align: 'right',
}, },
{ {
label: '排版参数', label: '排版参数',
...@@ -3563,7 +3582,7 @@ const tableColumns = computed(() => { ...@@ -3563,7 +3582,7 @@ const tableColumns = computed(() => {
{ {
label: '操作', label: '操作',
slot: 'operate', slot: 'operate',
width: 350, width: 300,
align: 'center', align: 'center',
fixed: 'right', fixed: 'right',
prop: 'operate', prop: 'operate',
...@@ -3789,16 +3808,16 @@ const loadTabData = async () => { ...@@ -3789,16 +3808,16 @@ const loadTabData = async () => {
// 发货拦截数量 // 发货拦截数量
const shipmentCount = (statusRes.data as InterceptStateGroupData)?.shipment const shipmentCount = (statusRes.data as InterceptStateGroupData)?.shipment
? Object.values( ? Object.values(
(statusRes.data as InterceptStateGroupData).shipment, (statusRes.data as InterceptStateGroupData).shipment,
).reduce((sum: number, value: unknown) => sum + (Number(value) || 0), 0) ).reduce((sum: number, value: unknown) => sum + (Number(value) || 0), 0)
: 0 : 0
// 生产拦截数量 // 生产拦截数量
const productionCount = (statusRes.data as InterceptStateGroupData) const productionCount = (statusRes.data as InterceptStateGroupData)
?.production ?.production
? Object.values( ? Object.values(
(statusRes.data as InterceptStateGroupData).production, (statusRes.data as InterceptStateGroupData).production,
).reduce((sum: number, value: unknown) => sum + (Number(value) || 0), 0) ).reduce((sum: number, value: unknown) => sum + (Number(value) || 0), 0)
: 0 : 0
tabsNav.value.splice(completeIndex + 1, 0, { tabsNav.value.splice(completeIndex + 1, 0, {
...@@ -3967,7 +3986,10 @@ watch( ...@@ -3967,7 +3986,10 @@ watch(
}, },
{ deep: true, immediate: true }, // 添加immediate确保初始化时执行 { deep: true, immediate: true }, // 添加immediate确保初始化时执行
) )
const fileName = (row: PodUsOrderListData) => {
if (!row.prnUrl) return ''
return row.prnUrl.split('/')[row.prnUrl.split('/').length - 1]
}
const search = () => { const search = () => {
selection.value = [] selection.value = []
cardSelection.value = [] cardSelection.value = []
...@@ -4145,6 +4167,37 @@ const productionClientVisible = ref(false) ...@@ -4145,6 +4167,37 @@ const productionClientVisible = ref(false)
// productionClientVisible.value = true // productionClientVisible.value = true
// } // }
const downloadRowProFile = async (row: PodUsOrderListData) => {
const url =
`https://factory.jomalls.com/upload/factory` + row.prnUrl
window.open(url, '_blank')
await updatePRNDownloadStatus(
row.id,
)
search()
}
const uploadFile = (row: PodUsOrderListData) => {
const input = document.createElement('input')
input.style.display = 'none'
input.type = 'file'
input.multiple = false
input?.click()
row.isUpload = true
input.onchange = async function() {
try {
if (input.files && input.files.length) {
const fm = new FormData()
fm.append('file', input.files?.[0])
const res = await uploadPRNFile(row.id, fm)
row.prnUrl = res.message
}
} finally {
row.isUpload = false
}
}
}
const downloadTif = async (type: string, templateWidth: number) => { const downloadTif = async (type: string, templateWidth: number) => {
if (!cardSelection.value.length) { if (!cardSelection.value.length) {
return ElMessage.warning('请选择数据') return ElMessage.warning('请选择数据')
...@@ -4189,8 +4242,8 @@ const downloadTif = async (type: string, templateWidth: number) => { ...@@ -4189,8 +4242,8 @@ const downloadTif = async (type: string, templateWidth: number) => {
a.href = window.URL.createObjectURL(blob) a.href = window.URL.createObjectURL(blob)
a.target = '_blank' a.target = '_blank'
a.download = (res.message as string).split('/')[ a.download = (res.message as string).split('/')[
(res.message as string).split('/').length - 1 (res.message as string).split('/').length - 1
] ]
a.click() a.click()
pngDownloadLoading.value = false pngDownloadLoading.value = false
}) })
...@@ -5200,8 +5253,8 @@ const rejectOrder = async (type: string) => { ...@@ -5200,8 +5253,8 @@ const rejectOrder = async (type: string) => {
orderStatus: type, orderStatus: type,
productList: selection.value.length productList: selection.value.length
? selection.value.flatMap( ? selection.value.flatMap(
(item: PodUsOrderListData) => item.productList || [], (item: PodUsOrderListData) => item.productList || [],
) )
: cardSelection.value, : cardSelection.value,
reasonStr: value, reasonStr: value,
}) })
...@@ -6188,8 +6241,8 @@ const interceptChange = async (status: boolean) => { ...@@ -6188,8 +6241,8 @@ const interceptChange = async (status: boolean) => {
? 1 ? 1
: 3 : 3
: interceptCurrent.value === 1 : interceptCurrent.value === 1
? 2 ? 2
: 4 : 4
try { try {
const res = await interceptUpdateApi({ const res = await interceptUpdateApi({
orderIds: selection.value.map((item) => item.id), orderIds: selection.value.map((item) => item.id),
...@@ -6273,29 +6326,11 @@ const reissueOrder = async () => { ...@@ -6273,29 +6326,11 @@ const reissueOrder = async () => {
if (selection.value.length === 0) { if (selection.value.length === 0) {
return ElMessage.warning('请选择数据') return ElMessage.warning('请选择数据')
} }
await ElMessageBox.confirm('是否补发?', '提示', { const isSameShipmentType = Array.from(new Set(selection.value.map(s=>s.shipmentType))).length===1
confirmButtonText: '确定', if(!isSameShipmentType){
cancelButtonText: '取消', return ElMessage.warning('请选择相同物流类型的数据')
type: 'warning',
})
const loading = ElLoading.service({
fullscreen: true,
text: '操作中...',
background: 'rgba(0, 0, 0, 0.3)',
})
try {
const res = await reissueOrderApi(
selection.value.map((item) => item.id).join(','),
)
if (res.code !== 200) return
ElMessage.success('操作成功')
search()
await loadTabData()
} catch (e) {
console.error(e)
} finally {
loading.close()
} }
reissueOrderRef.value.open()
} }
// 完成发货 // 完成发货
...@@ -6412,11 +6447,11 @@ const printNormal = async () => { ...@@ -6412,11 +6447,11 @@ const printNormal = async () => {
selection.value.forEach((s) => { selection.value.forEach((s) => {
s.productList && s.productList &&
s.productList.forEach((p) => { s.productList.forEach((p) => {
if (p.productMark === 'normal' || p.productMark === 'custom_normal') { if (p.productMark === 'normal' || p.productMark === 'custom_normal') {
arr.push(p.id) arr.push(p.id)
} }
}) })
}) })
console.log(3661, arr) console.log(3661, arr)
...@@ -6562,6 +6597,7 @@ const printNormal = async () => { ...@@ -6562,6 +6597,7 @@ const printNormal = async () => {
background: rgb(255 243 205); background: rgb(255 243 205);
color: rgb(91, 99, 18); color: rgb(91, 99, 18);
} }
.empty { .empty {
height: 100%; height: 100%;
display: flex; display: flex;
...@@ -6765,13 +6801,16 @@ const printNormal = async () => { ...@@ -6765,13 +6801,16 @@ const printNormal = async () => {
color: white; color: white;
font-weight: bold; font-weight: bold;
} }
.triangle-container-wrap { .triangle-container-wrap {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
} }
.triangle-container { .triangle-container {
position: relative; position: relative;
.triangle-marker { .triangle-marker {
width: 0; width: 0;
height: 0; height: 0;
...@@ -6779,6 +6818,7 @@ const printNormal = async () => { ...@@ -6779,6 +6818,7 @@ const printNormal = async () => {
border-right: 18px solid #e74c3c; border-right: 18px solid #e74c3c;
border-top: 18px solid #e74c3c; border-top: 18px solid #e74c3c;
} }
.content { .content {
position: absolute; position: absolute;
top: 0; top: 0;
...@@ -6790,13 +6830,16 @@ const printNormal = async () => { ...@@ -6790,13 +6830,16 @@ const printNormal = async () => {
font-size: 12px; font-size: 12px;
} }
} }
.triangle-container-wrap { .triangle-container-wrap {
position: absolute; position: absolute;
top: 0; top: 0;
right: 0; right: 0;
} }
.triangle-container { .triangle-container {
position: relative; position: relative;
.triangle-marker { .triangle-marker {
width: 0; width: 0;
height: 0; height: 0;
...@@ -6804,6 +6847,7 @@ const printNormal = async () => { ...@@ -6804,6 +6847,7 @@ const printNormal = async () => {
border-right: 18px solid #e74c3c; border-right: 18px solid #e74c3c;
border-top: 18px solid #e74c3c; border-top: 18px solid #e74c3c;
} }
.content { .content {
position: absolute; position: absolute;
top: 0; top: 0;
...@@ -6839,8 +6883,8 @@ const printNormal = async () => { ...@@ -6839,8 +6883,8 @@ const printNormal = async () => {
} }
.el-timeline .el-timeline
> .el-timeline-item:first-child > .el-timeline-item:first-child
.el-timeline-item__timestamp.is-top { .el-timeline-item__timestamp.is-top {
color: #409eff; color: #409eff;
} }
...@@ -6849,6 +6893,7 @@ const printNormal = async () => { ...@@ -6849,6 +6893,7 @@ const printNormal = async () => {
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
} }
.tabs-node-quantity { .tabs-node-quantity {
position: relative; position: relative;
color: red; color: red;
...@@ -6856,6 +6901,7 @@ const printNormal = async () => { ...@@ -6856,6 +6901,7 @@ const printNormal = async () => {
top: -10px; top: -10px;
right: 0px; right: 0px;
} }
.operate-item { .operate-item {
position: relative; position: relative;
} }
...@@ -6867,4 +6913,16 @@ const printNormal = async () => { ...@@ -6867,4 +6913,16 @@ const printNormal = async () => {
top: 30%; top: 30%;
transform: translateY(-50%); transform: translateY(-50%);
} }
.flex-1 {
flex: 1;
flex-shrink: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.red-big{
font-size: 15px;
color: red;
}
</style> </style>
...@@ -7,107 +7,136 @@ ...@@ -7,107 +7,136 @@
<span>系统配置</span> <span>系统配置</span>
</div> </div>
<div class="cardBox"> <div class="cardBox">
<div v-for="(item, index) in formList" style="width: 600px" :key="index"> <div class="card-box-item-container">
<el-form <div
v-if="item.type === 'RIIN'" v-for="(item, index) in formList"
class="form" :key="index"
ref="formRef" class="card-box-item"
label-width="120"
:model="item"
> >
<div class="formBox"> <template v-if="item.type === 'RIIN'">
<el-form-item label="转至RIIN生产"> <div class="formBox">
<el-switch <div class="form-item">
v-model="item.enable" <span>转至RIIN生产</span>
class="ml-2" <el-switch
style="--el-switch-on-color: #42b983" v-model="item.enable"
/> class="ml-2"
</el-form-item> style="--el-switch-on-color: #42b983"
<div class="formContent" v-if="item.enable"> />
<el-form-item </div>
label="账号" <div v-if="item.enable" class="formContent">
prop="appKey" <el-form
:rules="[{ required: true, message: '请输入RIIN账号' }]" v-if="item.type === 'RIIN'"
> ref="formRef"
<ElInput class="form"
ref="productionOrderRef" label-width="120"
v-model="item.appKey" :model="item"
placeholder="请输入RIIN账号" >
clearable <el-form-item
style="width: 100%" label="账号"
/></el-form-item> prop="appKey"
<el-form-item :rules="[{ required: true, message: '请输入RIIN账号' }]"
label="App Secret" >
prop="appSecret" <ElInput
:rules="[{ required: true, message: '请输入App Secret' }]" ref="productionOrderRef"
> v-model="item.appKey"
<ElInput placeholder="请输入RIIN账号"
ref="productionOrderRef" clearable
v-model="item.appSecret" style="width: 100%"
placeholder="请输入App Secret" /></el-form-item>
clearable <el-form-item
style="width: 100%" label="App Secret"
/></el-form-item> prop="appSecret"
:rules="[{ required: true, message: '请输入App Secret' }]"
>
<ElInput
ref="productionOrderRef"
v-model="item.appSecret"
placeholder="请输入App Secret"
clearable
style="width: 100%"
/></el-form-item>
</el-form>
</div>
</div> </div>
</div>
<ElButton <ElButton
class="btn" class="btn"
color="#42b983" color="#42b983"
@click="saveConfiguration(item, index)" @click="saveConfiguration(item, index)"
>保存配置</ElButton >保存配置</ElButton
> >
</el-form> </template>
<el-form <template v-if="item.type === 'TRACK'">
v-if="item.type === 'TRACK'" <div class="formBox">
class="form" <div class="form-item">
ref="formRef" <span>物流轨迹跟踪</span>
label-width="120" <el-switch
:model="item" v-model="item.enable"
> class="ml-2"
style="--el-switch-on-color: #42b983"
/>
</div>
<div v-if="item.enable" class="formContent">
<el-form
v-if="item.type === 'TRACK'"
class="form"
ref="formRef"
label-width="120"
:model="item"
>
<el-form-item
label="17Track账号"
prop="appKey"
:rules="[{ required: true, message: '请输入17Track账号' }]"
>
<ElInput
ref="productionOrderRef"
v-model="item.appKey"
placeholder="请输入17Track账号"
clearable
style="width: 100%"
/></el-form-item>
<el-form-item
label="账号Token"
prop="token"
:rules="[{ required: true, message: '请输入账号Token' }]"
>
<ElInput
ref="productionOrderRef"
v-model="item.token"
placeholder="请输入账号Token"
clearable
style="width: 100%"
/></el-form-item>
</el-form>
</div>
</div>
<ElButton
class="btn"
color="#42b983"
@click="saveConfiguration(item, index)"
>保存配置</ElButton
>
</template>
</div>
<div class="card-box-item">
<div class="formBox"> <div class="formBox">
<el-form-item label="物流轨迹跟踪"> <div class="form-item">
<el-switch <span>库存预警下限:</span>
v-model="item.enable" </div>
class="ml-2" <div class="formContent">
style="--el-switch-on-color: #42b983" <ElInput
v-model="inventoryLowerLimit"
clearable
placeholder="请输入库存预警下限"
/> />
</el-form-item>
<div class="formContent" v-if="item.enable">
<el-form-item
label="17Track账号"
prop="appKey"
:rules="[{ required: true, message: '请输入17Track账号' }]"
>
<ElInput
ref="productionOrderRef"
v-model="item.appKey"
placeholder="请输入17Track账号"
clearable
style="width: 100%"
/></el-form-item>
<el-form-item
label="账号Token"
prop="token"
:rules="[{ required: true, message: '请输入账号Token' }]"
>
<ElInput
ref="productionOrderRef"
v-model="item.token"
placeholder="请输入账号Token"
clearable
style="width: 100%"
/></el-form-item>
</div> </div>
</div> </div>
<ElButton class="btn" color="#42b983" @click="saveInventoryLowerLimit"
<ElButton
class="btn"
color="#42b983"
@click="saveConfiguration(item, index)"
>保存配置</ElButton >保存配置</ElButton
> >
</el-form> </div>
</div> </div>
</div> </div>
<div class="logBox"> <div class="logBox">
...@@ -122,6 +151,8 @@ import { ...@@ -122,6 +151,8 @@ import {
addExternalAuthorisationApi, addExternalAuthorisationApi,
getExternalAuthorisationListApi, getExternalAuthorisationListApi,
baseExternalAccountLogsApi, baseExternalAccountLogsApi,
saveInventoryLowerLimitApi,
getInventoryLowerLimitApi,
} from '@/api/externalAuth' } from '@/api/externalAuth'
import { ExternalAuthListData } from '@/types/api/externalAuth' import { ExternalAuthListData } from '@/types/api/externalAuth'
...@@ -134,7 +165,7 @@ interface formType { ...@@ -134,7 +165,7 @@ interface formType {
} }
const formRef = ref() const formRef = ref()
const inventoryLowerLimit = ref<number | null>(100)
const logList = ref([]) const logList = ref([])
async function saveConfiguration(item: formType, index: number) { async function saveConfiguration(item: formType, index: number) {
let loading let loading
...@@ -222,16 +253,49 @@ async function handleClick() { ...@@ -222,16 +253,49 @@ async function handleClick() {
console.log(error) console.log(error)
} }
} }
const saveInventoryLowerLimit = async () => {
if (!inventoryLowerLimit.value) {
ElMessage.error('请输入库存预警下限')
return
}
try {
const res = await saveInventoryLowerLimitApi(inventoryLowerLimit.value)
if (res.code !== 200) {
return
}
await ElMessageBox.confirm('保存配置成功!!需重新登录才能生效', '提示', {
confirmButtonText: '确定',
showCancelButton: false,
type: 'success',
})
getInventoryLowerLimit()
handleClick()
} catch (error) {
console.log(error)
}
}
const getInventoryLowerLimit = async () => {
try {
const res = await getInventoryLowerLimitApi()
if (res.code !== 200) {
return
}
inventoryLowerLimit.value = res.data
} catch (error) {
console.log(error)
}
}
onMounted(async () => { onMounted(async () => {
await getDetail() await getDetail()
getInventoryLowerLimit()
handleClick() handleClick()
}) })
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.card-header { .card-header {
margin-left: 200px; text-align: center;
font-size: 30px; font-size: 30px;
margin-bottom: 20px; margin-bottom: 20px;
} }
...@@ -240,9 +304,8 @@ onMounted(async () => { ...@@ -240,9 +304,8 @@ onMounted(async () => {
height: calc(100% - 60px); height: calc(100% - 60px);
} }
.cardBox { .cardBox {
flex: 3; flex: 1;
overflow-y: scroll; overflow-y: scroll;
height: 100%;
.el-card__footer { .el-card__footer {
border: none !important; border: none !important;
} }
...@@ -253,6 +316,9 @@ onMounted(async () => { ...@@ -253,6 +316,9 @@ onMounted(async () => {
padding: 20px; padding: 20px;
border: 1px solid #ebebeb; border: 1px solid #ebebeb;
border-radius: 8px; border-radius: 8px;
height: 220px;
display: flex;
flex-direction: column;
&:last-child { &:last-child {
margin-bottom: 0; margin-bottom: 0;
} }
...@@ -260,6 +326,8 @@ onMounted(async () => { ...@@ -260,6 +326,8 @@ onMounted(async () => {
padding: 20px; padding: 20px;
background-color: #f9f9f9; background-color: #f9f9f9;
border-radius: 5px; border-radius: 5px;
overflow: auto;
flex: 1;
.el-form-item:last-child { .el-form-item:last-child {
margin-bottom: 0 !important; margin-bottom: 0 !important;
} }
...@@ -274,8 +342,20 @@ onMounted(async () => { ...@@ -274,8 +342,20 @@ onMounted(async () => {
padding-top: 10px; padding-top: 10px;
height: 200px; height: 200px;
} }
.form { }
margin-bottom: 15px; .form-item {
display: flex;
align-items: center;
margin-bottom: 10px;
gap: 10px;
span {
color: #606266;
font-size: 14px;
} }
} }
.card-box-item-container {
display: grid;
grid-template-columns: repeat(3, minmax(100px, 1fr));
gap: 10px;
}
</style> </style>
<template>
<div
class="out-of-stock-statistics-page flex-column card h-100 overflow-hidden"
>
<div class="header-filter-form">
<ElForm v-enter-submit="search" :inline="true">
<ElFormItem label="缺货仓库">
<ElSelect
v-model="searchForm.warehouseId"
style="width: 180px"
placeholder="请选择仓库"
>
<ElOption
v-for="item in warehouseList"
:key="item.id"
:label="item.name"
:value="item.id"
></ElOption>
</ElSelect>
</ElFormItem>
<ElFormItem label="库存SKU">
<ElInput
v-model="searchForm.warehouseSku"
clearable
style="width: 180px"
placeholder="请输入库存SKU"
></ElInput>
</ElFormItem>
<ElFormItem label="款号">
<ElInput
v-model="searchForm.productNo"
clearable
style="width: 180px"
placeholder="请输入款号"
></ElInput>
</ElFormItem>
<ElFormItem label="商品名称">
<ElInput
v-model="searchForm.skuName"
clearable
style="width: 180px"
placeholder="请输入商品名称"
></ElInput>
</ElFormItem>
<ElFormItem>
<ElButton type="primary" @click="search"> 查询 </ElButton>
</ElFormItem>
<ElFormItem>
<ElButton type="success" @click="exportData"> 导出 </ElButton>
</ElFormItem>
</ElForm>
</div>
<div class="table-content flex-1 flex-column overflow-hidden">
<div v-loading="loading" class="table-list flex-1 overflow-hidden">
<TableView
:selectionable="true"
:serial-numberable="true"
:paginated-data="tableData"
:columns="tableColumns"
@selection-change="handleSelectionChange"
>
</TableView>
</div>
<ElPagination
v-model:current-page="currentPage"
v-model:page-size="pageSize"
:page-sizes="[50, 100, 200, 300, 500]"
background
layout="total, sizes, prev, pager, next, jumper"
:total="total"
style="margin: 10px auto 0; text-align: right"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
></ElPagination>
</div>
</div>
<ElDialog
v-model="exportVisible"
title="导出选项"
width="500px"
:close-on-click-modal="false"
>
<el-form :model="exportForm" label-width="80px">
<el-form-item label="" prop="resource">
<el-radio-group v-model="exportForm.resource">
<el-radio label="currentPage">导出本页</el-radio>
<el-radio label="selectedRows">导出选中</el-radio>
<el-radio label="all">全部</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="exportVisible = false">取消</el-button>
<el-button
:loading="exportLoading"
type="primary"
@click="submitExportForm"
>确认</el-button
>
</span>
</template>
</ElDialog>
</template>
<script setup lang="tsx">
import { computed, ref, onMounted } from 'vue'
import TableView from '@/components/TableView.vue'
import usePageList from '@/utils/hooks/usePageList'
import { loadWarehouseListApi } from '@/api/podCnOrder'
import type { WarehouseListData } from '@/types/api/podCnOrder'
import { SearchForm, OutOfStockItem } from '@/types/api/outOfStockStatistics'
import {
getOutOfStockStatisticsListApi,
exportOutOfStockStatisticsListApi,
} from '@/api/outOfStockStis'
import ImageView from '@/components/ImageView.vue'
import { filePath } from '@/api/axios'
const searchForm = ref<SearchForm>({
warehouseId: '',
warehouseSku: '',
productNo: '',
skuName: '',
})
const warehouseList = ref<WarehouseListData[]>([])
const exportVisible = ref(false)
const exportForm = ref({
resource: null,
})
const exportLoading = ref(false)
// 表格列配置
const tableColumns = computed(() => {
return [
{
label: '图片',
prop: 'variantImage',
width: 100,
align: 'center',
slot: 'image',
render: (item: OutOfStockItem) => (
<ImageView src={item.variantImage} width="40px" height="40px" />
),
},
{
label: '缺货仓库',
prop: 'warehouseName',
width: 120,
align: 'center',
},
{
label: '库位',
prop: 'locationCode',
width: 120,
align: 'center',
},
{
label: '库存SKU',
prop: 'warehouseSku',
width: 150,
align: 'center',
},
{
label: '款号',
prop: 'productNo',
width: 120,
align: 'center',
},
{
label: '商品名称',
prop: 'skuName',
minWidth: 200,
align: 'left',
},
{
label: '币种',
prop: 'currency',
width: 80,
align: 'center',
},
{
label: '商品成本价',
prop: 'costPrice',
width: 120,
align: 'right',
render: (item: OutOfStockItem) => (
<span>{item.costPrice ? item.costPrice.toFixed(2) : ''}</span>
),
},
{
label: '缺货数量',
prop: 'stockOutNum',
width: 100,
align: 'right',
},
{
label: '销售数量',
prop: 'salesNum',
width: 100,
align: 'right',
},
{
label: '库存SPU',
prop: 'warehouseSpu',
width: 150,
align: 'center',
},
{
label: '最长缺货天数',
prop: 'longestDelayDays',
width: 120,
align: 'right',
},
{
label: '库存数量',
prop: 'inventory',
width: 100,
align: 'right',
},
{
label: '占用数量',
prop: 'occupyInventory',
width: 100,
align: 'right',
},
{
label: '冻结数量',
prop: 'freezeInventory',
width: 100,
align: 'right',
},
{
label: '采购未入数量',
prop: 'purchaseNotInQuantity',
width: 120,
align: 'right',
},
]
})
const {
loading,
currentPage,
pageSize,
total,
data: tableData,
refresh: search,
onCurrentPageChange: handleCurrentChange,
onPageSizeChange: handleSizeChange,
} = usePageList<OutOfStockItem>({
query: (page, pageSize) =>
getOutOfStockStatisticsListApi(
{
...searchForm.value,
},
page,
pageSize,
).then((res) => res.data) as never,
initLoad: false,
})
// 加载仓库列表
const loadWarehouseList = async () => {
try {
const res = await loadWarehouseListApi()
if (res.code !== 200) return
warehouseList.value = res.data || []
searchForm.value.warehouseId = warehouseList.value[0].id
} catch (e) {
console.error(e)
}
}
// 导出数据
const exportData = async () => {
exportForm.value.resource = null
exportVisible.value = true
}
const submitExportForm = async () => {
if (!exportForm.value.resource) {
return ElMessage.error('请选择导出类型')
}
const params: { exportAll: boolean; indexes?: number[] } = {
exportAll: false,
indexes: [],
}
if (exportForm.value.resource === 'currentPage') {
params.exportAll = false
params.indexes = undefined
} else if (exportForm.value.resource === 'selectedRows') {
if (!selectedRows.value.length) {
return ElMessage.error('请选择要导出的数据')
}
params.exportAll = false
params.indexes = selectedRows.value.map((el: OutOfStockItem) =>
Number(el.sort),
)
} else if (exportForm.value.resource === 'all') {
params.exportAll = true
params.indexes = undefined
}
try {
const res = await exportOutOfStockStatisticsListApi({
...searchForm.value,
...params,
})
window.open(filePath + res.message, '_blank')
exportVisible.value = false
} catch (e) {
console.error(e)
}
}
// 处理表格选择变化
const selectedRows = ref<OutOfStockItem[]>([])
const handleSelectionChange = (val: OutOfStockItem[]) => {
selectedRows.value = val
}
onMounted(async () => {
await loadWarehouseList()
search()
})
</script>
<style lang="scss" scoped>
.out-of-stock-statistics-page {
.header-filter-form {
:deep(.el-form-item) {
margin-right: 14px;
margin-bottom: 10px;
}
}
.table-content {
.table-list {
border: 1px solid #ebeef5;
border-radius: 4px;
}
}
}
</style>
...@@ -20,6 +20,7 @@ import { ref, computed } from 'vue' ...@@ -20,6 +20,7 @@ import { ref, computed } from 'vue'
import SplitDiv from '@/components/splitDiv/splitDiv.vue' import SplitDiv from '@/components/splitDiv/splitDiv.vue'
import { filePath } from '@/api/axios.ts' import { filePath } from '@/api/axios.ts'
import { useEnterKeyTrigger } from '@/utils/hooks/useEnterKeyTrigger.ts' import { useEnterKeyTrigger } from '@/utils/hooks/useEnterKeyTrigger.ts'
import { getInventoryLowerLimitApi } from '@/api/externalAuth'
const searchForm = ref({ const searchForm = ref({
warehouseId: '', warehouseId: '',
...@@ -172,7 +173,24 @@ async function getData() { ...@@ -172,7 +173,24 @@ async function getData() {
...pagination.value, ...pagination.value,
...searchForm.value, ...searchForm.value,
}) })
leftData.value = res.data.records const sortedRecords = res.data.records.sort((a, b) => {
const aUsable =
Number(
(a as WarehouseWarning & { usableInventory?: number | string })
.usableInventory,
) || 0
const bUsable =
Number(
(b as WarehouseWarning & { usableInventory?: number | string })
.usableInventory,
) || 0
const aIsLow = aUsable < 100
const bIsLow = bUsable < 100
if (aIsLow && !bIsLow) return -1
if (!aIsLow && bIsLow) return 1
return 0
})
leftData.value = sortedRecords
pagination.value.total = res.data.total pagination.value.total = res.data.total
if (leftData.value.length) { if (leftData.value.length) {
getDetail(leftData.value[0].id) getDetail(leftData.value[0].id)
...@@ -292,8 +310,17 @@ const getWarehouse = async () => { ...@@ -292,8 +310,17 @@ const getWarehouse = async () => {
const { data } = await warehouseInfoGetAll() const { data } = await warehouseInfoGetAll()
warehouseList.value = data warehouseList.value = data
} }
getData()
getWarehouse() const getRowClassName = (row: { row: WarehouseWarning }) => {
const rowData = row.row as WarehouseWarning & {
usableInventory?: number | string
}
const usableInventory = Number(rowData.usableInventory) || 0
if (usableInventory < inventoryLowerLimit.value) {
return 'low-inventory-row'
}
return ''
}
/** /**
* @description: 页面添加回车监听 * @description: 页面添加回车监听
...@@ -310,6 +337,23 @@ useEnterKeyTrigger({ ...@@ -310,6 +337,23 @@ useEnterKeyTrigger({
getData() getData()
}, },
}) })
const inventoryLowerLimit = ref<number>(100)
const getInventoryLowerLimit = async () => {
try {
const res = await getInventoryLowerLimitApi()
if (res.code !== 200) {
return
}
inventoryLowerLimit.value = res.data
} catch (error) {
console.log(error)
}
}
onMounted(async () => {
getData()
getWarehouse()
getInventoryLowerLimit()
})
</script> </script>
<template> <template>
...@@ -509,6 +553,7 @@ useEnterKeyTrigger({ ...@@ -509,6 +553,7 @@ useEnterKeyTrigger({
height="100%" height="100%"
:data="leftData" :data="leftData"
border border
:row-class-name="getRowClassName"
@current-change="clickItem" @current-change="clickItem"
@selection-change="handleSelectionChange" @selection-change="handleSelectionChange"
> >
...@@ -831,6 +876,25 @@ useEnterKeyTrigger({ ...@@ -831,6 +876,25 @@ useEnterKeyTrigger({
} }
} }
::v-deep(.el-table) {
.low-inventory-row {
&:hover {
background-color: #f56c6c !important;
color: #fff !important;
}
td {
background-color: #f56c6c !important;
color: #fff !important;
}
&:hover td {
background-color: #f56c6c !important;
color: #fff !important;
}
}
}
.bottom-table { .bottom-table {
height: 100%; height: 100%;
background: white; background: white;
......
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