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 {
AnyObject,
InterProductList,
ExportInWarehouseInfo,
stockingPlanSearchForm,
InterStackingPlanDetail,
InterWarehouseBase
} from '@/types/api/warehouse'
export interface LogListData {
createTime: 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 {
RouteLocationNormalized,
NavigationGuardNext,
} from 'vue-router'
import { cleanupImagePreview } from '@/utils/hooks/useImagePreview.'
import Login from '@/views/Login.vue'
import Reset from '@/views/Reset.vue'
......@@ -31,6 +32,7 @@ import receiptDoc from '@/views/warehouse/receiptDoc.vue'
import issueDoc from '@/views/warehouse/issueDoc.vue'
import ExternalAuthorisationPage from '@/views/system/externalAuthorisationPage.vue'
import CustomersPage from '@/views/system/CustomersPage.vue'
import stockingPlan from '@/views/warehouse/stockingPlan.vue'
const router = createRouter({
history: createWebHistory(),
routes: [
......@@ -129,7 +131,7 @@ const router = createRouter({
meta: {
title: '下载生产客户端',
},
component: () => {},
component: () => { },
beforeEnter() {
// 假设你的下载链接是这个
const downloadLink = '/exeFiles/JomallProductionAssistantSetup.exe'
......@@ -280,6 +282,13 @@ const router = createRouter({
component: issueDoc,
},
{
path: '/warehouse/stocking-plan',
meta: {
title: '备货计划',
},
component: stockingPlan,
},
{
path: '/warehouse/warning',
meta: {
title: '仓库预警',
......@@ -333,6 +342,8 @@ router.beforeEach(
_from: RouteLocationNormalized,
next: NavigationGuardNext,
) => {
// 路由切换时清理图片预览,防止预览元素残留
cleanupImagePreview()
const token = getToken()
if (to.query.factoryCode) {
localStorage.setItem('factory_code', String(to.query.factoryCode))
......
......@@ -88,7 +88,6 @@ const menu: MenuItem[] = [
id: 124,
label: '出库单',
},
{
index: '/warehouse/manage',
id: 121,
......@@ -99,6 +98,11 @@ const menu: MenuItem[] = [
id: 122,
label: '库位管理',
},
{
index: '/warehouse/stocking-plan',
id: 124,
label: '备货计划',
},
],
},
......@@ -216,7 +220,7 @@ const menu: MenuItem[] = [
label: '工厂设置',
},
],
},
},
// {
// index: '',
// id: 3,
......
......@@ -22,6 +22,7 @@ export interface InterProductList {
productNo?: string | null //custom的货号
buyStored?: number | null //入库数量
outCount?: number | null //出库数量
stockUpStored?: number | null //备货数量
remark?: string | null
skuImage?: string
skuName?: string
......@@ -54,9 +55,10 @@ export interface InterWarehouseBase {
rejectReason?: string | null
number?: number | string | null
supplierItemNo?: string | null
sourceOn?: string | null //备货单号or入库单号
}
// 主表列表ts
export interface InterWarehousePage extends InterWarehouseBase {}
export interface InterWarehousePage extends InterWarehouseBase { }
// 子表列表ts
export interface InterWarehouseDetail extends InterWarehouseBase {
productList: InterProductList[]
......@@ -81,6 +83,7 @@ export interface InterProductList {
productNo?: string | null //货号
buyStored?: number | null //入库数量
outCount?: number | null //出库数量
stockUpStored?: number | null //备货数量
usableInventory?: number | null //可用库存数量
remark?: string | null
skuImage?: string
......@@ -118,3 +121,21 @@ export interface ILocation {
locationId?: number | 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)
const div = document.createElement('div')
div.style.position = 'fixed'
div.style.zIndex = '9999999999999'
div.style.display = 'none'
const img = document.createElement('img')
img.style.width = '300px'
div.appendChild(img)
document.body.appendChild(div)
// 单例模式:所有实例共享同一个预览元素
let previewDiv: HTMLDivElement | null = null
let previewImg: HTMLImageElement | null = null
const show = ref(false)
let currentTarget: HTMLElement | null = null
let mousemoveHandler: ((ev: MouseEvent) => void) | null = null
// 初始化预览元素(只创建一次)
function initPreviewElement() {
if (previewDiv) return
let currentTarget: HTMLElement | null = null
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)
}
const mousemoveHandler = (ev: MouseEvent) => {
if (!currentTarget) return
const rect = currentTarget.getBoundingClientRect()
const inOrigin =
ev.clientX >= rect.left &&
ev.clientX <= rect.right &&
ev.clientY >= rect.top &&
ev.clientY <= rect.bottom
// 清理函数:移除事件监听器和重置状态
function cleanup() {
if (mousemoveHandler) {
window.removeEventListener('mousemove', mousemoveHandler)
mousemoveHandler = null
}
if (previewDiv) {
previewDiv.style.display = 'none'
}
show.value = false
currentTarget = null
}
const divRect = div.getBoundingClientRect()
const inPreview =
ev.clientX >= divRect.left &&
ev.clientX <= divRect.right &&
ev.clientY >= divRect.top &&
ev.clientY <= divRect.bottom
// 导出清理函数,供路由切换时使用
export function cleanupImagePreview() {
cleanup()
}
if (!inOrigin && !inPreview) {
div.style.display = 'none'
show.value = false
window.removeEventListener('mousemove', mousemoveHandler)
currentTarget = null
export default function useImagePreview() {
// 确保预览元素已初始化
initPreviewElement()
// 创建 mousemove 处理器(如果还没有)
if (!mousemoveHandler) {
mousemoveHandler = (ev: MouseEvent) => {
if (!currentTarget || !previewDiv) {
cleanup()
return
}
const rect = currentTarget.getBoundingClientRect()
const inOrigin =
ev.clientX >= rect.left &&
ev.clientX <= rect.right &&
ev.clientY >= rect.top &&
ev.clientY <= rect.bottom
const divRect = previewDiv.getBoundingClientRect()
const inPreview =
ev.clientX >= divRect.left &&
ev.clientX <= divRect.right &&
ev.clientY >= divRect.top &&
ev.clientY <= divRect.bottom
if (!inOrigin && !inPreview) {
cleanup()
}
}
}
......@@ -44,12 +77,13 @@ export default function useImagePreview() {
newBorder?: boolean,
positionBOOTTOM?: boolean,
) => {
if (!previewDiv || !previewImg) return
ev.preventDefault()
if (show.value === true) return
img.src = url
img.style.backgroundColor = '#eee'
if (newBorder) img.style.border = '1px solid #eee'
if (newWitdh) img.style.width = newWitdh
previewImg.src = url
previewImg.style.backgroundColor = '#eee'
if (newBorder) previewImg.style.border = '1px solid #eee'
if (newWitdh) previewImg.style.width = newWitdh
const cW = document.body.clientWidth
const cH = document.body.clientHeight
const cX = ev.clientX
......@@ -59,14 +93,15 @@ export default function useImagePreview() {
else y = cY - 150
if (cX + 300 >= cW) x = cX - 300
else x = cX + 60
img.onload = () => {
div.style.left = x + 'px'
div.style.top = y + 'px'
div.style.display = 'block'
previewImg.onload = () => {
if (!previewDiv || !previewImg) return
previewDiv.style.left = x + 'px'
previewDiv.style.top = y + 'px'
previewDiv.style.display = 'block'
if (positionBOOTTOM) {
// 获取图片实际尺寸
const imgWidth = img.clientWidth
const imgHeight = img.clientHeight
const imgWidth = previewImg.clientWidth
const imgHeight = previewImg.clientHeight
// 计算新位置(鼠标正下方)
let x = cX / 2
......@@ -85,20 +120,26 @@ export default function useImagePreview() {
if (y < 0) {
y = 10
}
div.style.left = x + 'px'
div.style.top = y + 'px'
previewDiv.style.left = x + 'px'
previewDiv.style.top = y + 'px'
}
show.value = true
currentTarget = ev.currentTarget as HTMLElement
window.addEventListener('mousemove', mousemoveHandler)
if (mousemoveHandler) {
window.addEventListener('mousemove', mousemoveHandler)
}
}
}
const mouseleaveImg = () => {
if (show.value === false) return
div.style.display = 'none'
show.value = false
// 在 mouseleave 时也要清理事件监听器
cleanup()
}
// 组件卸载时清理(防止内存泄漏)
onUnmounted(() => {
cleanup()
})
return { mouseoverImg, mouseleaveImg }
}
......@@ -184,6 +184,14 @@
align="center"
></ElTableColumn>
<ElTableColumn
label="备货单号"
show-overflow-tooltip
prop="sourceOn"
width="130"
header-align="center"
align="center"
></ElTableColumn>
<ElTableColumn
label="单据状态"
width="130"
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