Commit 2923b581 by linjinhong

Merge branch 'release' of http://47.122.114.111:9999/qinjianhui/factory_front into release

parents 01a0520f 5dac4fdb
...@@ -10,6 +10,9 @@ import { ...@@ -10,6 +10,9 @@ import {
AnyObject, AnyObject,
InterProductList, InterProductList,
ExportInWarehouseInfo, ExportInWarehouseInfo,
stockingPlanSearchForm,
InterStackingPlanDetail,
InterWarehouseBase
} from '@/types/api/warehouse' } from '@/types/api/warehouse'
export interface LogListData { export interface LogListData {
createTime: string createTime: string
...@@ -596,3 +599,121 @@ export function deleteWarehouseOutRecordApi(ids: string) { ...@@ -596,3 +599,121 @@ export function deleteWarehouseOutRecordApi(ids: string) {
}, },
) )
} }
// 备货计划 树状图
export function getStackingPlanStatusTree() {
return axios.get<never, BaseRespData<InterWarehouseTree[]>>(
'factoryStockingPlanRecord/status_tree',
)
}
// 备货计划 列表
export function getStackingPlanListPage(data: stockingPlanSearchForm, currentPage: number,
pageSize: number,) {
return axios.post<never, BasePaginationData<InterWarehousePage>>(
'factoryStockingPlanRecord/list_page',
{
...data,
currentPage,
pageSize,
},
)
}
// 备货计划 新增
export function addStackingPlanApi(data: InterWarehouseDetail) {
return axios.post<never, BaseRespData<never>>(
'factoryStockingPlanRecord/add',
data,
)
}
// 备货计划 编辑
export function updateStackingPlanApi(data: InterStackingPlanDetail) {
return axios.post<never, BaseRespData<never>>(
'factoryStockingPlanRecord/update',
data,
)
}
// 备货计划 详情
export function getStackingPlanDetailApi(id: number | undefined) {
return axios.get<never, BaseRespData<InterStackingPlanDetail>>(
'factoryStockingPlanRecord/get',
{
params: {
id,
},
},
)
}
// 备货计划 日志
export function getStackingPlanLogApi(stockingPlanRecordId?: number) {
return axios.get<never, BaseRespData<LogListData[]>>(
`factoryStockingPlanRecord/log/${stockingPlanRecordId}`,
)
}
// 备货计划 驳回
export function rejectStackingPlanApi({
list,
rejectReason,
status,
}: {
list: WarehouseParams[]
rejectReason: string
status: string
}) {
return axios.post<never, BaseRespData<never>>(
'factoryStockingPlanRecord/reject',
{
list,
rejectReason,
status,
},
)
}
// 备货计划 删除
export function deleteStackingPlanApi(ids: string) {
return axios.get<never, BaseRespData<never>>(
'factoryStockingPlanRecord/delete',
{
params: { ids },
},
)
}
// 备货计划 更新物流单号
export function updateShipmentNumberApi(data: InterWarehouseBase[]) {
return axios.post<never, BaseRespData<never>>(
'factoryStockingPlanRecord/update_shipmentNumber',
{ stockingPlanRecordParamList: data },
)
}
// 备货计划 导出
export function stackingPlanRecordExport(data: ExportInWarehouseInfo) {
return axios.post<never, BasePaginationData<never>>(
'factoryStockingPlanRecord/export',
data,
{
responseType: 'blob',
},
)
}
// 备货计划 盘点
export function scanBoxCodeApi(boxCode: string) {
return axios.get<never, BaseRespData<never>>(
'factoryStockingPlanRecord/scan_box_code',
{
params: { boxCode },
},
)
}
// 备货计划 打印箱贴
export function printBarcodeApi(data: { id: number, dataVersion: number }[]) {
return axios.post<never, BaseRespData<never[]>>(
'factoryStockingPlanRecord/print_barcode',
data,
)
}
\ No newline at end of file
...@@ -4,6 +4,7 @@ import { ...@@ -4,6 +4,7 @@ import {
RouteLocationNormalized, RouteLocationNormalized,
NavigationGuardNext, NavigationGuardNext,
} from 'vue-router' } from 'vue-router'
import { cleanupImagePreview } from '@/utils/hooks/useImagePreview.'
import Login from '@/views/Login.vue' import Login from '@/views/Login.vue'
import Reset from '@/views/Reset.vue' import Reset from '@/views/Reset.vue'
...@@ -31,6 +32,7 @@ import receiptDoc from '@/views/warehouse/receiptDoc.vue' ...@@ -31,6 +32,7 @@ import receiptDoc from '@/views/warehouse/receiptDoc.vue'
import issueDoc from '@/views/warehouse/issueDoc.vue' import issueDoc from '@/views/warehouse/issueDoc.vue'
import ExternalAuthorisationPage from '@/views/system/externalAuthorisationPage.vue' import ExternalAuthorisationPage from '@/views/system/externalAuthorisationPage.vue'
import CustomersPage from '@/views/system/CustomersPage.vue' import CustomersPage from '@/views/system/CustomersPage.vue'
import stockingPlan from '@/views/warehouse/stockingPlan.vue'
const router = createRouter({ const router = createRouter({
history: createWebHistory(), history: createWebHistory(),
routes: [ routes: [
...@@ -129,7 +131,7 @@ const router = createRouter({ ...@@ -129,7 +131,7 @@ const router = createRouter({
meta: { meta: {
title: '下载生产客户端', title: '下载生产客户端',
}, },
component: () => {}, component: () => { },
beforeEnter() { beforeEnter() {
// 假设你的下载链接是这个 // 假设你的下载链接是这个
const downloadLink = '/exeFiles/JomallProductionAssistantSetup.exe' const downloadLink = '/exeFiles/JomallProductionAssistantSetup.exe'
...@@ -280,6 +282,13 @@ const router = createRouter({ ...@@ -280,6 +282,13 @@ const router = createRouter({
component: issueDoc, component: issueDoc,
}, },
{ {
path: '/warehouse/stocking-plan',
meta: {
title: '备货计划',
},
component: stockingPlan,
},
{
path: '/warehouse/warning', path: '/warehouse/warning',
meta: { meta: {
title: '仓库预警', title: '仓库预警',
...@@ -333,6 +342,8 @@ router.beforeEach( ...@@ -333,6 +342,8 @@ router.beforeEach(
_from: RouteLocationNormalized, _from: RouteLocationNormalized,
next: NavigationGuardNext, next: NavigationGuardNext,
) => { ) => {
// 路由切换时清理图片预览,防止预览元素残留
cleanupImagePreview()
const token = getToken() const token = getToken()
if (to.query.factoryCode) { if (to.query.factoryCode) {
localStorage.setItem('factory_code', String(to.query.factoryCode)) localStorage.setItem('factory_code', String(to.query.factoryCode))
......
...@@ -88,7 +88,6 @@ const menu: MenuItem[] = [ ...@@ -88,7 +88,6 @@ const menu: MenuItem[] = [
id: 124, id: 124,
label: '出库单', label: '出库单',
}, },
{ {
index: '/warehouse/manage', index: '/warehouse/manage',
id: 121, id: 121,
...@@ -99,6 +98,11 @@ const menu: MenuItem[] = [ ...@@ -99,6 +98,11 @@ const menu: MenuItem[] = [
id: 122, id: 122,
label: '库位管理', label: '库位管理',
}, },
{
index: '/warehouse/stocking-plan',
id: 124,
label: '备货计划',
},
], ],
}, },
......
...@@ -22,6 +22,7 @@ export interface InterProductList { ...@@ -22,6 +22,7 @@ export interface InterProductList {
productNo?: string | null //custom的货号 productNo?: string | null //custom的货号
buyStored?: number | null //入库数量 buyStored?: number | null //入库数量
outCount?: number | null //出库数量 outCount?: number | null //出库数量
stockUpStored?: number | null //备货数量
remark?: string | null remark?: string | null
skuImage?: string skuImage?: string
skuName?: string skuName?: string
...@@ -54,9 +55,10 @@ export interface InterWarehouseBase { ...@@ -54,9 +55,10 @@ export interface InterWarehouseBase {
rejectReason?: string | null rejectReason?: string | null
number?: number | string | null number?: number | string | null
supplierItemNo?: string | null supplierItemNo?: string | null
sourceOn?: string | null //备货单号or入库单号
} }
// 主表列表ts // 主表列表ts
export interface InterWarehousePage extends InterWarehouseBase {} export interface InterWarehousePage extends InterWarehouseBase { }
// 子表列表ts // 子表列表ts
export interface InterWarehouseDetail extends InterWarehouseBase { export interface InterWarehouseDetail extends InterWarehouseBase {
productList: InterProductList[] productList: InterProductList[]
...@@ -81,6 +83,7 @@ export interface InterProductList { ...@@ -81,6 +83,7 @@ export interface InterProductList {
productNo?: string | null //货号 productNo?: string | null //货号
buyStored?: number | null //入库数量 buyStored?: number | null //入库数量
outCount?: number | null //出库数量 outCount?: number | null //出库数量
stockUpStored?: number | null //备货数量
usableInventory?: number | null //可用库存数量 usableInventory?: number | null //可用库存数量
remark?: string | null remark?: string | null
skuImage?: string skuImage?: string
...@@ -118,3 +121,21 @@ export interface ILocation { ...@@ -118,3 +121,21 @@ export interface ILocation {
locationId?: number | null locationId?: number | null
locationCode?: string | null locationCode?: string | null
} }
// 备货计划 查询
export interface stockingPlanSearchForm extends InterWarehouseBase {
timeType?: string
startDate?: string
endDate?: string
dateStr?: string
warehouseSku?: string
}
// 备货计划
export interface InterStackingPlanDetail extends InterWarehouseDetail {
boxSum?: number
checkBoxSum?: number
box?: number | string
}
import { ref } from 'vue' import { ref, onUnmounted } from 'vue'
export default function useImagePreview() { // 单例模式:所有实例共享同一个预览元素
const show = ref(false) let previewDiv: HTMLDivElement | null = null
const div = document.createElement('div') let previewImg: HTMLImageElement | null = null
div.style.position = 'fixed' const show = ref(false)
div.style.zIndex = '9999999999999' let currentTarget: HTMLElement | null = null
div.style.display = 'none' let mousemoveHandler: ((ev: MouseEvent) => void) | null = null
const img = document.createElement('img')
img.style.width = '300px' // 初始化预览元素(只创建一次)
div.appendChild(img) function initPreviewElement() {
document.body.appendChild(div) if (previewDiv) return
previewDiv = document.createElement('div')
previewDiv.style.position = 'fixed'
previewDiv.style.zIndex = '9999999999999'
previewDiv.style.display = 'none'
previewImg = document.createElement('img')
previewImg.style.width = '300px'
previewDiv.appendChild(previewImg)
document.body.appendChild(previewDiv)
}
// 清理函数:移除事件监听器和重置状态
function cleanup() {
if (mousemoveHandler) {
window.removeEventListener('mousemove', mousemoveHandler)
mousemoveHandler = null
}
if (previewDiv) {
previewDiv.style.display = 'none'
}
show.value = false
currentTarget = null
}
let currentTarget: HTMLElement | null = null // 导出清理函数,供路由切换时使用
export function cleanupImagePreview() {
cleanup()
}
export default function useImagePreview() {
// 确保预览元素已初始化
initPreviewElement()
const mousemoveHandler = (ev: MouseEvent) => { // 创建 mousemove 处理器(如果还没有)
if (!currentTarget) return if (!mousemoveHandler) {
mousemoveHandler = (ev: MouseEvent) => {
if (!currentTarget || !previewDiv) {
cleanup()
return
}
const rect = currentTarget.getBoundingClientRect() const rect = currentTarget.getBoundingClientRect()
const inOrigin = const inOrigin =
ev.clientX >= rect.left && ev.clientX >= rect.left &&
...@@ -22,7 +57,7 @@ export default function useImagePreview() { ...@@ -22,7 +57,7 @@ export default function useImagePreview() {
ev.clientY >= rect.top && ev.clientY >= rect.top &&
ev.clientY <= rect.bottom ev.clientY <= rect.bottom
const divRect = div.getBoundingClientRect() const divRect = previewDiv.getBoundingClientRect()
const inPreview = const inPreview =
ev.clientX >= divRect.left && ev.clientX >= divRect.left &&
ev.clientX <= divRect.right && ev.clientX <= divRect.right &&
...@@ -30,10 +65,8 @@ export default function useImagePreview() { ...@@ -30,10 +65,8 @@ export default function useImagePreview() {
ev.clientY <= divRect.bottom ev.clientY <= divRect.bottom
if (!inOrigin && !inPreview) { if (!inOrigin && !inPreview) {
div.style.display = 'none' cleanup()
show.value = false }
window.removeEventListener('mousemove', mousemoveHandler)
currentTarget = null
} }
} }
...@@ -44,12 +77,13 @@ export default function useImagePreview() { ...@@ -44,12 +77,13 @@ export default function useImagePreview() {
newBorder?: boolean, newBorder?: boolean,
positionBOOTTOM?: boolean, positionBOOTTOM?: boolean,
) => { ) => {
if (!previewDiv || !previewImg) return
ev.preventDefault() ev.preventDefault()
if (show.value === true) return if (show.value === true) return
img.src = url previewImg.src = url
img.style.backgroundColor = '#eee' previewImg.style.backgroundColor = '#eee'
if (newBorder) img.style.border = '1px solid #eee' if (newBorder) previewImg.style.border = '1px solid #eee'
if (newWitdh) img.style.width = newWitdh if (newWitdh) previewImg.style.width = newWitdh
const cW = document.body.clientWidth const cW = document.body.clientWidth
const cH = document.body.clientHeight const cH = document.body.clientHeight
const cX = ev.clientX const cX = ev.clientX
...@@ -59,14 +93,15 @@ export default function useImagePreview() { ...@@ -59,14 +93,15 @@ export default function useImagePreview() {
else y = cY - 150 else y = cY - 150
if (cX + 300 >= cW) x = cX - 300 if (cX + 300 >= cW) x = cX - 300
else x = cX + 60 else x = cX + 60
img.onload = () => { previewImg.onload = () => {
div.style.left = x + 'px' if (!previewDiv || !previewImg) return
div.style.top = y + 'px' previewDiv.style.left = x + 'px'
div.style.display = 'block' previewDiv.style.top = y + 'px'
previewDiv.style.display = 'block'
if (positionBOOTTOM) { if (positionBOOTTOM) {
// 获取图片实际尺寸 // 获取图片实际尺寸
const imgWidth = img.clientWidth const imgWidth = previewImg.clientWidth
const imgHeight = img.clientHeight const imgHeight = previewImg.clientHeight
// 计算新位置(鼠标正下方) // 计算新位置(鼠标正下方)
let x = cX / 2 let x = cX / 2
...@@ -85,20 +120,26 @@ export default function useImagePreview() { ...@@ -85,20 +120,26 @@ export default function useImagePreview() {
if (y < 0) { if (y < 0) {
y = 10 y = 10
} }
div.style.left = x + 'px' previewDiv.style.left = x + 'px'
div.style.top = y + 'px' previewDiv.style.top = y + 'px'
} }
show.value = true show.value = true
currentTarget = ev.currentTarget as HTMLElement currentTarget = ev.currentTarget as HTMLElement
if (mousemoveHandler) {
window.addEventListener('mousemove', mousemoveHandler) window.addEventListener('mousemove', mousemoveHandler)
} }
} }
}
const mouseleaveImg = () => { const mouseleaveImg = () => {
if (show.value === false) return // 在 mouseleave 时也要清理事件监听器
div.style.display = 'none' cleanup()
show.value = false
} }
// 组件卸载时清理(防止内存泄漏)
onUnmounted(() => {
cleanup()
})
return { mouseoverImg, mouseleaveImg } return { mouseoverImg, mouseleaveImg }
} }
...@@ -184,6 +184,14 @@ ...@@ -184,6 +184,14 @@
align="center" align="center"
></ElTableColumn> ></ElTableColumn>
<ElTableColumn <ElTableColumn
label="备货单号"
show-overflow-tooltip
prop="sourceOn"
width="130"
header-align="center"
align="center"
></ElTableColumn>
<ElTableColumn
label="单据状态" label="单据状态"
width="130" width="130"
prop="billStatusTxt" prop="billStatusTxt"
......
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