Commit 4545b5dc by wuqian

Merge branch 'wq' into dev

parents 02083ceb 22a5a2d2
import { BasePaginationData, BaseRespData, RejectParams } from '@/types/api'
import { BasePaginationData, BaseRespData } from '@/types/api'
import axios from './axios'
import { PaymentForm } from '@/types/api/index.ts'
import {
LogListData,
OrderData,
......@@ -11,6 +10,8 @@ import {
ShipmentOrderRes,
Tab,
InspectionData,
PaymentForm,
RejectParams
} from '@/types/api/order'
import {
apiSubmitPodOrderForm,
......@@ -151,7 +152,7 @@ export function apiSetCraftData({
}: {
id: number | undefined
craftTotalPrice: number | undefined
recNumber:string|undefined
recNumber: string | undefined
craftPriceList: IUpdatePrice[]
}) {
return axios.post<never, BaseRespData<never>>(
......
......@@ -314,9 +314,9 @@ export function InRecordBatchCheckPrintApi(ids: string) {
},
)
}
export function warehouseInRecordInventory(data: ExportInWarehouseInfo) {
export function warehouseInRecordExport(data: ExportInWarehouseInfo) {
return axios.post<never, BasePaginationData<never>>(
'factory/warehouseInRecord/inventory',
'factory/warehouseInRecord/export',
data,
)
}
......@@ -438,6 +438,20 @@ export function getInRecordLogApi(inRecordId?: number) {
)
}
// 出库单
export function warehouseOutRecordExport(data: ExportInWarehouseInfo) {
return axios.post<never, BasePaginationData<never>>(
'factory/warehouseOutRecord/export',
data,
)
}
export function OutRecordBatchCheckPrintApi(ids: string) {
return axios.get<never, BaseRespData<never[]>>(
'factory/warehouseOutRecord/batchCheckPrint',
{
params: { ids },
},
)
}
export function getOutRecordStatusTree() {
return axios.get<never, BaseRespData<InterWarehouseTree[]>>(
'factory/warehouseOutRecord/status_tree',
......
......@@ -87,8 +87,9 @@
>
<div class="nav-tabs-node_label">
<span>{{ item.title }}</span>
<!-- 首页不可删除 -->
<el-icon
v-if="tabs.length > 1"
v-if="item.path != '/dashboard' && tabs.length > 1"
class="el-icon-close"
@click.stop="removeTab(item.name)"
>
......
......@@ -27,8 +27,8 @@ import WarehouseManage from '@/views/warehouse/manage.vue'
import WarehouseWarning from '@/views/warehouse/warning.vue'
import WarehousePosition from '@/views/warehouse/position.vue'
import receiptDoc from '@/views/warehouse/receiptDoc.vue'
import issueDoc from '@/views/warehouse/issueDoc.vue'
import ExternalAuthorisationPage from '@/views/system/externalAuthorisationPage.vue'
// import issueDoc from '@/views/warehouse/issueDoc.vue'
const router = createRouter({
history: createWebHistory(),
routes: [
......@@ -197,13 +197,13 @@ const router = createRouter({
},
component: receiptDoc,
},
// {
// path: '/warehouse/issue-doc',
// meta: {
// title: '出库单',
// },
// component: issueDoc,
// },
{
path: '/warehouse/issue-doc',
meta: {
title: '出库单',
},
component: issueDoc,
},
{
path: '/warehouse/warning',
meta: {
......
......@@ -78,11 +78,11 @@ const menu: MenuItem[] = [
id: 123,
label: '入库单',
},
// {
// index: '/warehouse/issue-doc',
// id: 124,
// label: '出库单',
// },
{
index: '/warehouse/issue-doc',
id: 124,
label: '出库单',
},
{
index: '/warehouse/manage',
......
......@@ -35,17 +35,4 @@ export interface baseRes {
code: number
msg: string
}
export interface PaymentForm {
waterList: string
id?: number | string
actualAmount?: number | string
payableAmount?: number | string
recNumber?: number | string
}
export interface RejectParams {
id: number
description?: string
ids?: string
pass?: number
}
......@@ -81,7 +81,7 @@ export interface ProductList {
subOrderNumber?: string
shopNumber?: string
material?: string
materialPrice?: number|null
materialPrice?: number | null
count?: number
baseSku?: string
erpSubOrderNumber?: string
......@@ -277,3 +277,16 @@ export interface ICompareObjects {
lanshouPost?: string
lanshouRegion?: string
}
export interface PaymentForm {
waterList: string
id?: number | string
actualAmount?: number | string
payableAmount?: number | string
recNumber?: number | string
}
export interface RejectParams {
id: number
description?: string
ids?: string
pass?: number
}
......@@ -5,6 +5,8 @@ export interface warehouseSearchForm {
billStatus?: string
createTimeEnd?: string
createTimeStart?: string
startTime?: string
endTime?: string
inNo?: string
outNo?: string
warehouseSku?: string
......@@ -14,6 +16,7 @@ export interface warehouseSearchForm {
export interface InterProductList {
createTime?: string
id?: number
inventoryId?: number | null
inId?: number
productNo?: string | null //custom的货号
buyStored?: number | null //入库数量
......@@ -42,6 +45,7 @@ export interface InterWarehouseBase {
total?: number
totalPrice?: number
billStatus?: string
billStatusTxt?: string
remark?: string | null
dataVersion?: number
createTime?: string | null
......@@ -86,6 +90,9 @@ export interface InterProductList {
warehouseSku?: string
locationId?: number | null
locationCode?: string | null
inventory?: {
usableInventory?: number
}
}
export interface InterskuList {
id?: number
......@@ -101,6 +108,7 @@ export interface InterskuList {
price?: number | null //出库单的
usableInventory?: number | null
warehouseSku?: string
remark?: string | null
}
export interface ILocation {
id?: number
......
......@@ -108,7 +108,6 @@ export function checkUpdateParams(
removeList = arr1.map((item) => item['id'] as IdType)
}
if (isBackKeyName) {
console.log(isBackKeyName)
// 将列表直接添加到 params 顶层
if (addList.length > 0) params['addList'] = addList || undefined
if (updateList.length > 0)
......
......@@ -31,7 +31,7 @@
<template #top>
<div class="header-filter-form">
<ElForm :model="searchForm" inline>
<ElFormItem label="采购仓库">
<ElFormItem label="仓库">
<ElSelect
v-model="searchForm.warehouseId"
clearable
......@@ -117,10 +117,10 @@
>
删除
</el-button>
<!-- <el-button type="success" @click="handleExport"> 导出 </el-button>
<el-button type="success" @click="handleExport"> 导出 </el-button>
<el-button type="primary" @click="printProductTag">
打印商品SKU标签
</el-button> -->
</el-button>
<el-button
v-if="nodeCode === 'PENDING_AUDIT'"
type="warning"
......@@ -190,7 +190,7 @@
<ElTableColumn
label="单据状态"
width="130"
prop="billStatus"
prop="billStatusTxt"
header-align="center"
align="center"
></ElTableColumn>
......@@ -211,14 +211,6 @@
align="center"
></ElTableColumn>
<ElTableColumn
label="物流单号"
show-overflow-tooltip
prop="shipmentNumber"
width="200"
header-align="center"
align="center"
></ElTableColumn>
<ElTableColumn
label="总金额(¥)"
show-overflow-tooltip
width="120"
......@@ -259,6 +251,7 @@
align="center"
></ElTableColumn>
<ElTableColumn
v-if="nodeCode === 'PENDING_SUBMIT'"
width="100"
align="center"
header-align="center"
......@@ -572,13 +565,13 @@
<div class="product-dialog-footer">
<div>
<el-input
v-model="selectSku"
v-model.trim="selectSku"
placeholder="商品SKU"
style="width: 200px; margin: 0 10px"
clearable
size="small"
></el-input>
<el-popover placement="top-start" width="900" trigger="click">
<el-popover placement="top-start" width="1000" trigger="click">
<div v-if="skuData.length > 0" style="height: 50vh">
<ElTable size="small" :data="skuData" height="100%" border>
<ElTableColumn
......@@ -658,14 +651,14 @@
</el-button>
</template>
</el-popover>
<!-- <el-button
<el-button
style="margin-left: 6px"
type="success"
size="small"
@click="addPurchase"
>
批量新增
</el-button> -->
</el-button>
<el-button
type="danger"
style="margin-left: 10px"
......@@ -706,7 +699,7 @@
>
<el-form :model="exportForm" label-width="80px">
<el-form-item label="" prop="resource">
<el-radio-group v-model="exportForm.resource">
<el-radio-group v-model="exportForm.resource" @change="isAllExport">
<el-radio :label="0">导出本页</el-radio>
<el-radio :label="1">导出选中</el-radio>
<el-radio :label="2">全部</el-radio>
......@@ -724,7 +717,7 @@
</template>
</ElDialog>
<el-dialog v-model="showPrintDialog" title="打印参数设置">
<el-table height="400px" :data="selections" border>
<el-table height="400px" :data="printData" border>
<el-table-column
width="60"
align="center"
......@@ -743,18 +736,18 @@
></el-table-column>
<el-table-column
align="center"
prop="locationCode"
prop="locationName"
label="库位编码"
></el-table-column>
<el-table-column
align="center"
prop="productNo"
label="货号 "
prop="supplierItemNo"
label="货号"
></el-table-column>
<el-table-column align="center" prop="number" label="打印数量">
<template #default="{ row }">
<el-input
v-model="row.number"
v-model.number="row.number"
oninput="value=value.replace(/[^\-?\d.]/g,'')"
placeholder="打印数量"
clearable
......@@ -767,6 +760,33 @@
<el-button type="primary" @click="handlePrintProductTag">打印</el-button>
</template>
</el-dialog>
<ElDialog
v-model="addPurchaseVisible"
title="批量添加"
width="500px"
:close-on-click-modal="false"
>
<div>
<el-input
v-model.trim="purchaseTextarea"
type="textarea"
placeholder="请输入库存 SKU"
:rows="5"
minlength="1"
maxlength="1000"
show-word-limit
/>
<div style="margin-top: 12px; color: #777">
{{ '多个字段使用_##_,_##_隔开' }}
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="addPurchaseVisible = false">取消</el-button>
<el-button type="primary" @click="submitPurchase">确认</el-button>
</span>
</template>
</ElDialog>
</template>
<script setup lang="ts">
......@@ -793,9 +813,11 @@ import {
rejectOutRecordApi,
LogListData,
warehouseInfo,
warehouseOutRecordExport,
factoryWarehouseInventoryPrint,
OutRecordBatchCheckPrintApi,
} from '@/api/warehouse'
// factoryWarehouseInventoryPrint,
// import { filePath } from '@/api/axios.ts'
import { filePath } from '@/api/axios'
import BigNumber from 'bignumber.js'
import { ref, onMounted, watch, nextTick } from 'vue'
import 'element-plus/dist/index.css'
......@@ -943,6 +965,11 @@ const logList = ref<LogListData[]>([])
const rules = {
warehouseId: [{ required: true, message: '请选择仓库', trigger: 'change' }],
}
const isAllExport = () => {
if (exportForm.value.resource == '2') {
ElMessage.warning('最多支持5000条!')
}
}
const nodeCode = ref<string>(
sessionStorage.getItem('InRecord_NodeCode') || 'all',
)
......@@ -962,12 +989,12 @@ const {
{
...searchForm.value,
billStatus: nodeCode.value == 'all' ? 'all' : nodeCode.value,
createTimeStart: tradingTime.value && tradingTime.value[0],
createTimeEnd: tradingTime.value && tradingTime.value[1],
startTime: tradingTime.value && tradingTime.value[0],
endTime: tradingTime.value && tradingTime.value[1],
},
page,
pageSize,
).then((res) => res.data) as never,
).then((res) => res.data),
})
const setCostPrice = (item: InterProductList) => {
......@@ -995,72 +1022,192 @@ const getTreeNum = async () => {
}
}
const showPrintDialog = ref(false)
// const printProductTag = async () => {
// if (!selections.value.length) {
// return ElMessage.warning('请选择要操作的数据')
// }
// showPrintDialog.value = true
// selections.value.forEach((el:InterWarehousePage) => {
// el.number = ''
// })
// }
const printData = ref([])
const printProductTag = async () => {
if (!selections.value.length) {
return ElMessage.warning('请选择要操作的数据')
}
const str = selections.value.map((el: InterWarehousePage) => el.id).join(',')
try {
const res = await OutRecordBatchCheckPrintApi(str)
if (res.code === 200) {
printData.value = res.data
showPrintDialog.value = true
} else {
ElMessage.error(res.message)
}
} catch (e) {
console.error(e)
}
}
async function handlePrintProductTag() {
// const flag = selections.value.every((el:InterWarehousePage) => el.number && el.number != '0')
// if (!flag) {
// return ElMessage.warning('打印数量需大于0')
// }
// const list = selections.value.map((item:InterWarehousePage) => {
// return {
// skuName: item.skuName,
// warehouseSku: item.warehouseSku,
// supplierItemNo: item.productNumber,
// number: item.number,
// locationName: item.locationCode,
// }
// })
// const res = await factoryWarehouseInventoryPrint({
// list,
// code: 'PT002',
// })
// showPrintDialog.value = false
// window.open(filePath + res.message, '_blank')
const flag = printData.value.every(
(el: InterWarehousePage) => el.number && el.number != '0',
)
if (!flag) {
return ElMessage.warning('打印数量需大于0')
}
const list = printData.value.map(
({
skuName = '',
warehouseSku = '',
supplierItemNo = '',
number = '',
locationName = '',
}) => ({
skuName,
warehouseSku,
supplierItemNo,
number,
locationName,
}),
)
const res = await factoryWarehouseInventoryPrint({
list,
code: 'PT002',
})
showPrintDialog.value = false
window.open(filePath + res.message, '_blank')
}
const batchAddCommodity = async (sku: string): Promise<InterskuList[]> => {
if (!editForm.value.warehouseId) {
ElMessage.error('请选择仓库')
return []
}
try {
const res = await getBySkuAndWarehouseIdApi(editForm.value.warehouseId, sku)
const arr: InterskuList[] = res.data || []
const ids: Record<string, boolean> = {}
// 过滤掉商品列表已经加了的
for (const item of otherPurchaseData.value) {
if (item.warehouseSku !== undefined) {
ids[item.warehouseSku] = true
}
}
// 使用 filter 方法过滤掉已经存在的 SKU
const filteredArr = arr.filter((currentItem: InterskuList) => {
return (
currentItem.warehouseSku === undefined || !ids[currentItem.warehouseSku]
)
})
return filteredArr
} catch (e) {
console.error(e)
return []
}
}
interface InterImportData {
warehouseSku: string;
remark?: string | null;
buyStored?: string | number | null | object; // 扩大 buyStored 类型,以兼容原始数据
[propName: string]: string | number | boolean | undefined | unknown
}
// 前端导入Excel
const excelFieldMap: Record<string, keyof InterProductList> = {
SKU图片: 'skuImage',
const excelFieldMap: Record<string, keyof InterImportData> = {
// SKU图片: 'skuImage',
商品SKU: 'warehouseSku',
SKU名称: 'skuName',
出库数量: 'outCount',
可用库存数量: 'usableInventory',
'成本价(¥)': 'costPrice',
'总成本(¥)': 'totalPrice',
库位: 'locationCode',
// SKU名称: 'skuName',
// 出库数量: 'outCount',
// 可用库存数量: 'usableInventory',
// '成本价(¥)': 'costPrice',
// '总成本(¥)': 'totalPrice',
// 库位: 'locationCode',
备注: 'remark',
}
const handleLocalImport = ({
const handleLocalImport = async ({
path,
data,
}: {
path: string
data: InterProductList[]
data: Record<string, any>[]
}) => {
const result: InterProductList[] = data.map((item) => {
const obj = {} as InterProductList
Object.keys(excelFieldMap).forEach((excelKey) => {
const field = excelFieldMap[excelKey] as keyof InterProductList
const value = item[excelKey]
// // 类型转换和默认值
// if (['outCount', 'costPrice', 'totalPrice'].includes(field)) {
// value = value == null || value === '' ? 0 : Number(value)
// } else {
// value = value == null ? '' : value
// }
obj[field] = value as InterProductList[typeof field]
})
return obj
})
otherPurchaseData.value = result
// 1. 将原始导入数据映射到 InterImportData[]
const importedData: InterImportData[] = data.map(item => {
const obj: InterImportData = { warehouseSku: '' };
Object.keys(excelFieldMap).forEach(excelKey => {
const field = excelFieldMap[excelKey];
const value = item[excelKey];
if (field === 'warehouseSku') {
obj[field] = typeof value === 'string' ? value : String(value ?? '');
} else if (field === 'remark') {
obj[field] = typeof value === 'string' ? value : (value === null || value === undefined ? null : String(value));
} else if (field === 'buyStored') {
// 处理 buyStored: 确保它是一个数字、数字字符串,否则设置为 null
if (typeof value === 'number') {
obj[field] = String(value); // 将数字转换为字符串
} else if (typeof value === 'string' && !isNaN(Number(value))) {
obj[field] = value; // 保持有效的数字字符串
} else {
// 如果不是数字或有效的数字字符串,则设置为 null
obj[field] = null;
}
} else {
obj[field] = value;
}
});
return obj;
}).filter(item => item.warehouseSku);
if (importedData.length === 0) {
ElMessage.warning('导入数据中没有有效的商品SKU');
importDialogVisible.value = false;
return;
}
// 2. 提取导入的 SKU 列表
const importedSkus = importedData.map(item => item.warehouseSku).join(',');
// 3. 调用 batchAddCommodity 获取商品的完整信息并过滤掉已有的 SKU
const filteredSkusList = await batchAddCommodity(importedSkus);
if (filteredSkusList.length === 0) {
ElMessage.warning('导入的商品SKU已存在或无效');
importedFileUrl.value = path;
importDialogVisible.value = false;
return;
}
// 4. 将备注信息合并到获取到的商品列表中
const mergedProductList = filteredSkusList.map(skuItem => {
const importedItem = importedData.find(item => item.warehouseSku === skuItem.warehouseSku);
let outCountValueForBigNumber: string | number = '0'; // 初始化为安全默认值
if (importedItem?.buyStored !== null && importedItem?.buyStored !== undefined) {
if (typeof importedItem.buyStored === 'string' && !isNaN(Number(importedItem.buyStored))) {
outCountValueForBigNumber = importedItem.buyStored;
} else if (typeof importedItem.buyStored === 'number') {
outCountValueForBigNumber = importedItem.buyStored;
} else {
// 如果是对象或其他意外类型,则默认为 '0'
outCountValueForBigNumber = '0';
}
}
const calculatedOutCount = new BigNumber(outCountValueForBigNumber).toNumber();
return {
skuImage: skuItem.image,
warehouseSku: skuItem.warehouseSku,
skuName: skuItem.skuName,
productNo: skuItem.productNumber,
locationCode: skuItem.locationCode ?? '',
locationId: skuItem.locationId ?? null,
costPrice: skuItem.price,
outCount: calculatedOutCount,
totalPrice: new BigNumber(calculatedOutCount).multipliedBy(skuItem.price ?? 0).toNumber(),
usableInventory: skuItem.usableInventory,
inventoryId: skuItem.id,
remark: importedItem?.remark ?? skuItem.remark ?? null,
} as InterProductList;
});
// 5. 更新 otherPurchaseData
otherPurchaseData.value = [...otherPurchaseData.value, ...mergedProductList];
importedFileUrl.value = path
importDialogVisible.value = false
}
......@@ -1069,10 +1216,46 @@ const exportForm = ref({
delivery: false,
resource: '',
})
// const handleExport = () => {
// exportVisible.value = true
// }
const submitExportForm = () => {}
const handleExport = () => {
exportVisible.value = true
}
const submitExportForm = async () => {
if (exportForm.value.resource === '') {
return ElMessage.error('请选择导出类型')
}
let purchaseIds: number[] = []
let exportTotal: number | undefined = undefined
const params: AnyObject = {}
const resourceType = Number(exportForm.value.resource)
if (resourceType === 0) {
purchaseIds = (tableData.value as InterWarehousePage[]).map(
(el: InterWarehousePage) => Number(el.id),
)
} else if (resourceType === 1) {
purchaseIds = selections.value.map((el: InterWarehousePage) =>
Number(el.id),
)
} else if (resourceType === 2) {
purchaseIds = []
exportTotal = total.value
params.billStatus = nodeCode.value == 'all' ? 'all' : nodeCode.value
}
params.idList = purchaseIds
if (exportTotal !== undefined) {
params.total = exportTotal
}
try {
const res = await warehouseOutRecordExport({
showDetail: exportForm.value.delivery,
...params,
...searchForm.value,
})
window.open(filePath + res.message, '_blank')
exportVisible.value = false
} catch (e) {
exportVisible.value = false
}
}
const getWarehouseList = async () => {
try {
const res = await warehouseInfoGetAll()
......@@ -1099,7 +1282,25 @@ const selectbySku = async () => {
editForm.value.warehouseId,
selectSku.value,
)
skuData.value = res.data || []
const arr: InterskuList[] = res.data || []
const ids: Record<string, boolean> = {}
// 过滤掉商品列表已经加了的
for (const item of otherPurchaseData.value) {
if (item.warehouseSku !== undefined) {
ids[item.warehouseSku] = true
}
}
for (let i = 0; i < arr.length; i++) {
const currentItem: InterskuList = arr[i]
if (
currentItem.warehouseSku !== undefined &&
ids[currentItem.warehouseSku]
) {
arr.splice(i, 1)
i--
}
}
skuData.value = arr || []
} catch (e) {
console.error(e)
}
......@@ -1109,12 +1310,13 @@ const skudblclick = (val: InterskuList) => {
const {
locationCode = '',
price = null,
productNumber = '',
productNo = '',
warehouseSku = '',
skuName = '',
image = '',
locationId = null,
usableInventory = null,
id = null,
} = val || {}
otherPurchaseData.value = [
...otherPurchaseData.value,
......@@ -1122,13 +1324,14 @@ const skudblclick = (val: InterskuList) => {
skuImage: image,
warehouseSku,
skuName,
productNo: productNumber,
productNo,
locationCode: locationCode ?? '', // 确保空值处理
locationId: locationId ?? null, // 确保空值处理
costPrice: price,
outCount: null, //出库数量
totalPrice: null,
usableInventory, //可用库存数量
inventoryId: id,
},
]
// 使用filter代替forEach+splice,时间复杂度从O(n^2)降到O(n)
......@@ -1197,13 +1400,27 @@ const addDialog = async (i: number, v: InterWarehousePage | null) => {
formId.value = undefined
}
fetchLocationList('')
selectSku.value = ''
newDialogVisible.value = true
}
const getProduct = async (id: number | undefined) => {
try {
const res = await getWarehouseOutRecordDetailApi(id)
const productList = res.data?.productList
const newProductList = (Array.isArray(productList) ? productList : []).map(
(item: InterProductList) => {
const { inventory, ...rest } = item
return {
...rest,
usableInventory: inventory?.usableInventory ?? null,
}
},
)
if (res.data) {
res.data.productList = newProductList
}
editForm.value = JSON.parse(JSON.stringify(res.data))
otherPurchaseData.value = res.data?.productList || []
otherPurchaseData.value = newProductList || []
} catch (e) {
console.error(e)
}
......@@ -1414,7 +1631,7 @@ const upSection = async () => {
editForm.value as unknown as AnyObject,
'id',
{
productList: 'warehouseSku',
productList: 'id',
},
)
try {
......@@ -1427,9 +1644,36 @@ const upSection = async () => {
console.error(e)
}
}
// const addPurchase = async () => {
// if (!editForm.value.warehouseId) return ElMessage.error('请选择仓库')
// }
const addPurchaseVisible = ref(false)
const purchaseTextarea = ref(null)
const addPurchase = async () => {
addPurchaseVisible.value = true
}
const submitPurchase = async () => {
if (!purchaseTextarea.value) {
ElMessage.warning('请输入库存 SKU')
return
}
const filteredSkusList = await batchAddCommodity(purchaseTextarea.value)
const mergedProductList = filteredSkusList.map((skuItem) => {
return {
skuImage: skuItem.image,
warehouseSku: skuItem.warehouseSku,
skuName: skuItem.skuName,
productNo: skuItem.productNumber,
locationCode: skuItem.locationCode ?? '',
locationId: skuItem.locationId ?? null,
costPrice: skuItem.price,
outCount: null,
totalPrice: null,
usableInventory: skuItem.usableInventory,
inventoryId: skuItem.id,
remark: null,
} as InterProductList
})
otherPurchaseData.value = [...otherPurchaseData.value, ...mergedProductList]
addPurchaseVisible.value = false
}
const deleteOtherWarehousing = () => {
const arr = otherWarehouseSelection.value
if (arr.length === 0) return
......@@ -1441,8 +1685,8 @@ const deleteOtherWarehousing = () => {
const importDialogVisible = ref(false)
const importedFileUrl = ref('')
const importData = async () => {
// if (!editForm.value.warehouseId) return ElMessage.error('请选择仓库')
importDialogVisible.value = true
importedFileUrl.value = ''
}
const handleBatchDelete = async () => {
if (!selections.value.length) {
......@@ -1464,11 +1708,6 @@ const nodeClick = (data: InterWarehouseTree) => {
sessionStorage.setItem('InRecord_NodeCode', data.code ?? '')
search()
}
// const detailPager = ref({
// page: 1,
// rows: 100,
// total: 0,
// })
const searchDetail = async () => {
try {
const res = await getItemListByIdApi(currentRow.value?.id)
......@@ -1489,10 +1728,6 @@ const locationList = ref<ILocation[]>([])
const locationLoading = ref(false)
const fetchLocationList = async (query: string) => {
// if (!query) {
// locationList.value = []
// return
// }
if (!editForm.value.warehouseId) return
locationLoading.value = true
try {
......
......@@ -190,7 +190,7 @@
<ElTableColumn
label="单据状态"
width="130"
prop="billStatus"
prop="billStatusTxt"
header-align="center"
align="center"
></ElTableColumn>
......@@ -446,12 +446,6 @@
/>
</div>
</div>
<!-- <template #footer>
<span class="dialog-footer">
<el-button @click="importDialogVisible = false">取消</el-button>
<el-button type="primary" @click="packedData">确认</el-button>
</span>
</template> -->
</ElDialog>
<ElDialog
v-model="newDialogVisible"
......@@ -607,7 +601,7 @@
<div class="product-dialog-footer">
<div>
<el-input
v-model="selectSku"
v-model.trim="selectSku"
placeholder="商品SKU"
style="width: 200px; margin: 0 10px"
clearable
......@@ -693,14 +687,14 @@
</el-button>
</template>
</el-popover>
<!-- <el-button
<el-button
style="margin-left: 6px"
type="success"
size="small"
@click="addPurchase"
>
批量新增
</el-button> -->
</el-button>
<el-button
type="danger"
style="margin-left: 10px"
......@@ -741,7 +735,7 @@
>
<el-form :model="exportForm" label-width="80px">
<el-form-item label="" prop="resource">
<el-radio-group v-model="exportForm.resource">
<el-radio-group v-model="exportForm.resource" @change="isAllExport">
<el-radio :label="0">导出本页</el-radio>
<el-radio :label="1">导出选中</el-radio>
<el-radio :label="2">全部</el-radio>
......@@ -789,7 +783,7 @@
<el-table-column align="center" prop="number" label="打印数量">
<template #default="{ row }">
<el-input
v-model="row.number"
v-model.number="row.number"
oninput="value=value.replace(/[^\-?\d.]/g,'')"
placeholder="打印数量"
clearable
......@@ -802,6 +796,33 @@
<el-button type="primary" @click="handlePrintProductTag">打印</el-button>
</template>
</el-dialog>
<ElDialog
v-model="addPurchaseVisible"
title="批量添加"
width="500px"
:close-on-click-modal="false"
>
<div>
<el-input
v-model.trim="purchaseTextarea"
type="textarea"
placeholder="请输入库存 SKU"
:rows="5"
minlength="1"
maxlength="1000"
show-word-limit
/>
<div style="margin-top: 12px; color: #777">
{{ '多个字段使用_##_,_##_隔开' }}
</div>
</div>
<template #footer>
<span class="dialog-footer">
<el-button @click="addPurchaseVisible = false">取消</el-button>
<el-button type="primary" @click="submitPurchase">确认</el-button>
</span>
</template>
</ElDialog>
</template>
<script setup lang="ts">
......@@ -829,7 +850,7 @@ import {
warehouseInfo,
InRecordBatchCheckPrintApi,
factoryWarehouseInventoryPrint,
warehouseInRecordInventory,
warehouseInRecordExport,
} from '@/api/warehouse'
import { filePath } from '@/api/axios.ts'
import BigNumber from 'bignumber.js'
......@@ -979,6 +1000,11 @@ const logList = ref<LogListData[]>([])
const rules = {
warehouseId: [{ required: true, message: '请选择仓库', trigger: 'change' }],
}
const isAllExport = () => {
if (exportForm.value.resource == '2') {
ElMessage.warning('最多支持5000条!')
}
}
const nodeCode = ref<string>(
sessionStorage.getItem('InRecord_NodeCode') || 'all',
)
......@@ -1078,41 +1104,130 @@ async function handlePrintProductTag() {
showPrintDialog.value = false
window.open(filePath + res.message, '_blank')
}
const batchAddCommodity = async (sku: string): Promise<InterskuList[]> => {
if (!editForm.value.warehouseId) {
ElMessage.error('请选择仓库')
return []
}
try {
const res = await getBySkuApi(editForm.value.warehouseId, sku)
const arr: InterskuList[] = res.data || []
const ids: Record<string, boolean> = {}
// 过滤掉商品列表已经加了的
for (const item of otherPurchaseData.value) {
if (item.warehouseSku !== undefined) {
ids[item.warehouseSku] = true
}
}
// 使用 filter 方法过滤掉已经存在的 SKU
const filteredArr = arr.filter((currentItem: InterskuList) => {
return currentItem.sku === undefined || !ids[currentItem.sku]
})
return filteredArr
} catch (e) {
console.error(e)
return []
}
}
interface InterImportData {
warehouseSku: string
remark?: string | null
[key: string]: unknown
}
// 前端导入Excel
const excelFieldMap: Record<string, keyof InterProductList> = {
SKU图片: 'skuImage',
// SKU图片: 'skuImage',
商品SKU: 'warehouseSku',
SKU名称: 'skuName',
// SKU名称: 'skuName',
入库数量: 'buyStored',
'成本价(¥)': 'costPrice',
'总成本(¥)': 'totalPrice',
库位: 'locationCode',
// '成本价(¥)': 'costPrice',
// '总成本(¥)': 'totalPrice',
// 库位: 'locationCode',
备注: 'remark',
}
const handleLocalImport = ({
const handleLocalImport = async ({
path,
data,
}: {
path: string
data: InterProductList[]
data: InterImportData[]
}) => {
const result: InterProductList[] = data.map((item) => {
const obj = {} as InterProductList
Object.keys(excelFieldMap).forEach((excelKey) => {
const field = excelFieldMap[excelKey] as keyof InterProductList
const value = item[excelKey]
// // 类型转换和默认值
// if (['buyStored', 'costPrice', 'totalPrice'].includes(field)) {
// value = value == null || value === '' ? 0 : Number(value)
// } else {
// value = value == null ? '' : value
// }
obj[field] = value as InterProductList[typeof field]
// 1. 将原始导入数据映射到 InterImportData[]
const importedData: InterImportData[] = data
.map((item) => {
const obj: InterImportData = { warehouseSku: '' }
Object.keys(excelFieldMap).forEach((excelKey) => {
const field = excelFieldMap[excelKey]
const value = item[excelKey]
if (field === 'warehouseSku') {
obj[field] = typeof value === 'string' ? value : String(value ?? '')
} else if (field === 'remark') {
obj[field] =
typeof value === 'string'
? value
: value === null || value === undefined
? null
: String(value)
} else if (field === 'buyStored') {
// 确保 value 是一个有效的数字或数字字符串,否则设置为 null
if (
typeof value === 'number' ||
(typeof value === 'string' && !isNaN(Number(value)))
) {
obj[field] = String(value) // 转换为字符串
} else {
obj[field] = null // 无效值设置为 null
}
} else {
obj[field] = value
}
})
return obj
})
return obj
.filter((item) => item.warehouseSku)
if (importedData.length === 0) {
ElMessage.warning('导入数据中没有有效的商品SKU')
importDialogVisible.value = false
return
}
// 2. 提取导入的 SKU 列表
const importedSkus = importedData.map((item) => item.warehouseSku).join(',')
// 3. 调用 batchAddCommodity 获取商品的完整信息并过滤掉已有的 SKU
const filteredSkusList = await batchAddCommodity(importedSkus) // 使用 await 等待结果
if (filteredSkusList.length === 0) {
ElMessage.warning('导入的商品SKU已存在或无效')
importedFileUrl.value = path
importDialogVisible.value = false
return
}
// 4. 将备注信息合并到获取到的商品列表中
const mergedProductList = filteredSkusList.map((skuItem) => {
// 在导入数据中找到匹配的备注信息
const importedItem = importedData.find(
(item) => item.warehouseSku === skuItem.sku,
)
return {
skuImage: skuItem.image,
warehouseSku: skuItem.sku,
skuName: skuItem.skuName,
productNo: skuItem.productNo,
locationCode: skuItem.locationCode ?? '',
locationId: skuItem.locationId ?? null,
costPrice: skuItem.factoryPrice,
buyStored: importedItem?.buyStored ?? null,
totalPrice: new BigNumber(
(importedItem?.buyStored ?? 0) as number | string,
)
.multipliedBy(skuItem.price ?? 0)
.toNumber(),
usableInventory: skuItem.usableInventory,
remark: importedItem?.remark ?? null,
} as InterProductList // 明确类型
})
otherPurchaseData.value = result
// 5. 更新 otherPurchaseData
otherPurchaseData.value = [...otherPurchaseData.value, ...mergedProductList]
importedFileUrl.value = path
importDialogVisible.value = false
}
......@@ -1150,7 +1265,7 @@ const submitExportForm = async () => {
params.total = exportTotal
}
try {
const res = await warehouseInRecordInventory({
const res = await warehouseInRecordExport({
showDetail: exportForm.value.delivery,
...params,
...searchForm.value,
......@@ -1280,6 +1395,7 @@ const addDialog = async (i: number, v: InterWarehousePage | null) => {
formId.value = undefined
}
fetchLocationList('')
selectSku.value = ''
newDialogVisible.value = true
}
const getProduct = async (id: number | undefined) => {
......@@ -1415,31 +1531,6 @@ const addOtherCurrency = async () => {
return
}
}
// 看新增后要不要打印标签
// try {
// if (!editId.value) {
// await addUserApi({
// ...editForm.value,
// supperMark: Number(editForm.value.supperMark),
// status: Number(editForm.value.status),
// })
// } else {
// await updateUserApi({
// ...editForm.value,
// supperMark: Number(editForm.value.supperMark),
// status: Number(editForm.value.status),
// })
// }
// ElMessage({
// message: '保存成功',
// type: 'success',
// offset: window.innerHeight / 2,
// })
// newDialogVisible.value = false
// search()
// } catch (e) {
// return
// }
if (!formId.value) {
addSection()
} else {
......@@ -1507,9 +1598,35 @@ const upSection = async () => {
console.error(e)
}
}
// const addPurchase = async () => {
// if (!editForm.value.warehouseId) return ElMessage.error('请选择仓库')
// }
const addPurchaseVisible = ref(false)
const purchaseTextarea = ref(null)
const addPurchase = async () => {
addPurchaseVisible.value = true
}
const submitPurchase = async () => {
if (!purchaseTextarea.value) {
ElMessage.warning('请输入库存 SKU')
return
}
const filteredSkusList = await batchAddCommodity(purchaseTextarea.value)
const mergedProductList = filteredSkusList.map((skuItem) => {
return {
skuImage: skuItem.image,
warehouseSku: skuItem.sku,
skuName: skuItem.skuName,
productNo: skuItem.productNo,
locationCode: skuItem.locationCode ?? '',
locationId: skuItem.locationId ?? null,
costPrice: skuItem.factoryPrice,
buyStored: null,
totalPrice: null,
usableInventory: skuItem.usableInventory,
remark: null,
} as InterProductList
})
otherPurchaseData.value = [...otherPurchaseData.value, ...mergedProductList]
addPurchaseVisible.value = false
}
const deleteOtherWarehousing = () => {
const arr = otherWarehouseSelection.value
if (arr.length === 0) return
......@@ -1521,8 +1638,8 @@ const deleteOtherWarehousing = () => {
const importDialogVisible = ref(false)
const importedFileUrl = ref('')
const importData = async () => {
// if (!editForm.value.warehouseId) return ElMessage.error('请选择仓库')
importDialogVisible.value = true
importedFileUrl.value = ''
}
const handleBatchDelete = async () => {
if (!selections.value.length) {
......
......@@ -112,18 +112,16 @@ const submitExportForm = async () => {
return ElMessage.error('请选择导出类型')
}
exportLoading.value = true
let purchaseIds = ''
let purchaseIds: number[] = []
let exportTotal: number | undefined = undefined
const params: AnyObject = {}
const resourceType = Number(exportForm.value.resource)
if (resourceType === 0) {
purchaseIds = leftData.value.map((el: WarehouseWarning) => el.id).join(',')
purchaseIds = leftData.value.map((el: WarehouseWarning) => Number(el.id))
} else if (resourceType === 1) {
purchaseIds = selections.value
.map((el: WarehouseWarning) => el.id)
.join(',')
purchaseIds = selections.value.map((el: WarehouseWarning) => Number(el.id))
} else if (resourceType === 2) {
purchaseIds = ''
purchaseIds = []
exportTotal = pagination.value.total
}
params.idList = purchaseIds
......
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