fix: socket连接代码优化,耗材增加具体统计弹窗
This commit is contained in:
parent
7e9a9d1767
commit
814ca603d7
|
|
@ -44,6 +44,14 @@ const Api = {
|
||||||
data
|
data
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
//耗材库存变动记录
|
||||||
|
flow(params: any) {
|
||||||
|
return request<any>({
|
||||||
|
url: `${baseURL}/flow`,
|
||||||
|
method: "get",
|
||||||
|
params
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -167,7 +167,7 @@
|
||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import NoticeAPI, { NoticePageVO } from "@/api/system/notice";
|
import NoticeAPI, { NoticePageVO } from "@/api/system/notice";
|
||||||
import WebSocketManager from "@/utils/websocket";
|
// import WebSocketManager from "@/utils/websocket";
|
||||||
import router from "@/router";
|
import router from "@/router";
|
||||||
|
|
||||||
const activeTab = ref("notice");
|
const activeTab = ref("notice");
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ export default {
|
||||||
// 路由守卫
|
// 路由守卫
|
||||||
setupPermission();
|
setupPermission();
|
||||||
// 初始化 WebSocket
|
// 初始化 WebSocket
|
||||||
webSocketManager.setupWebSocket();
|
// webSocketManager.setupWebSocket();
|
||||||
// 注册 CodeMirror
|
// 注册 CodeMirror
|
||||||
app.use(InstallCodeMirror);
|
app.use(InstallCodeMirror);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,44 @@
|
||||||
import { Client } from "@stomp/stompjs";
|
import qs from "qs";
|
||||||
import { getToken } from "@/utils/auth";
|
import { useUserStoreHook } from "@/store";
|
||||||
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
|
const user = useUserStoreHook()
|
||||||
|
|
||||||
|
export interface ApifoxModel {
|
||||||
|
account: string;
|
||||||
|
/**
|
||||||
|
* 操作类型
|
||||||
|
*/
|
||||||
|
operate_type: string;
|
||||||
|
shop_id: string;
|
||||||
|
/**
|
||||||
|
* 桌码
|
||||||
|
*/
|
||||||
|
table_code?: string;
|
||||||
|
/**
|
||||||
|
* 消息类型
|
||||||
|
*/
|
||||||
|
type: string;
|
||||||
|
[property: string]: any;
|
||||||
|
}
|
||||||
|
export type msgType = 'add' | 'reduce' | 'remove' | 'edit' | 'init' | 'cleanup' | 'del' | 'rottable' | 'batch'
|
||||||
class WebSocketManager {
|
class WebSocketManager {
|
||||||
private client: Client | null = null;
|
private client: WebSocket | null = null;
|
||||||
|
private connected: boolean = false;
|
||||||
|
private shop_id = user.userInfo.shopId ? String(user.userInfo.shopId) : '';
|
||||||
|
private initParams: ApifoxModel = {
|
||||||
|
type: 'manage',
|
||||||
|
account: this.shop_id,
|
||||||
|
operate_type: 'init',
|
||||||
|
table_code: '',
|
||||||
|
shop_id: this.shop_id,
|
||||||
|
};
|
||||||
|
private onMessage: (message: any) => void = function () { };
|
||||||
private messageHandlers: Map<string, ((message: string) => void)[]> = new Map();
|
private messageHandlers: Map<string, ((message: string) => void)[]> = new Map();
|
||||||
|
private type: string = 'manage';
|
||||||
private reconnectAttempts = 0;
|
private reconnectAttempts = 0;
|
||||||
private maxReconnectAttempts = 3; // 自定义最大重试次数
|
private maxReconnectAttempts = 3; // 自定义最大重试次数
|
||||||
private reconnectDelay = 5000; // 重试延迟(单位:毫秒)
|
private reconnectDelay = 5000; // 重试延迟(单位:毫秒)
|
||||||
|
private timer: any | null = null;
|
||||||
// 初始化 WebSocket 客户端
|
// 初始化 WebSocket 客户端
|
||||||
setupWebSocket() {
|
setupWebSocket() {
|
||||||
const endpoint = import.meta.env.VITE_APP_WS_ENDPOINT;
|
const endpoint = import.meta.env.VITE_APP_WS_ENDPOINT;
|
||||||
|
|
@ -18,74 +49,112 @@ class WebSocketManager {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.client && this.client.connected) {
|
if (this.client && this.connected) {
|
||||||
console.log("客户端已存在并且连接正常");
|
console.log("客户端已存在并且连接正常");
|
||||||
return this.client;
|
return this.client;
|
||||||
}
|
}
|
||||||
|
const url = qs.stringify(this.initParams)
|
||||||
this.client = new Client({
|
this.client = new WebSocket(endpoint + '?' + url);
|
||||||
brokerURL: endpoint,
|
this.client.onopen = () => {
|
||||||
connectHeaders: {
|
this.connected = true;
|
||||||
Authorization: getToken(),
|
console.log("WebSocket 连接已建立");
|
||||||
},
|
// ElNotification.success('WebSocket 连接已建立')
|
||||||
heartbeatIncoming: 30000,
|
this.sendMessage(this.initParams)
|
||||||
heartbeatOutgoing: 30000,
|
clearTimeout(this.timer)
|
||||||
reconnectDelay: 0, // 设置为 0 禁用重连
|
this.timer = setInterval(() => {
|
||||||
onConnect: () => {
|
this.sendMessage({ "type": "ping_interval" })
|
||||||
console.log(`连接到 WebSocket 服务器: ${endpoint}`);
|
}, 1000 * 10);
|
||||||
this.reconnectAttempts = 0; // 重置重连计数
|
};
|
||||||
this.messageHandlers.forEach((handlers, topic) => {
|
this.client.onclose = () => {
|
||||||
handlers.forEach((handler) => {
|
clearTimeout(this.timer)
|
||||||
this.subscribeToTopic(topic, handler);
|
if (!this.connected) {
|
||||||
});
|
// ElMessageBox.alert('WebSocket 连接已断开', 'Title', {
|
||||||
});
|
// confirmButtonText: '立即重连',
|
||||||
},
|
// callback: () => {
|
||||||
onStompError: (frame) => {
|
// this.sendMessage(this.initParams)
|
||||||
console.error(`连接错误: ${frame.headers["message"]}`);
|
// },
|
||||||
console.error(`错误详情: ${frame.body}`);
|
// })
|
||||||
},
|
}
|
||||||
onDisconnect: () => {
|
this.connected = false;
|
||||||
console.log(`WebSocket 连接已断开: ${endpoint}`);
|
console.log("WebSocket 连接已断开");
|
||||||
this.reconnectAttempts++;
|
};
|
||||||
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
this.client.onerror = (error) => {
|
||||||
console.log(`正在尝试重连... 尝试次数: ${this.reconnectAttempts}`);
|
clearTimeout(this.timer)
|
||||||
} else {
|
console.error("WebSocket 发生错误:", error);
|
||||||
console.log("重连次数已达上限,停止重连");
|
// ElNotification({
|
||||||
this.client?.deactivate();
|
// title: "提示",
|
||||||
|
// message: "WebSocket 发生错误",
|
||||||
|
// type: "error",
|
||||||
|
// });
|
||||||
|
// ElMessageBox.alert('WebSocket 发生错误', 'Title', {
|
||||||
|
// confirmButtonText: '立即重连',
|
||||||
|
// callback: () => {
|
||||||
|
// this.sendMessage(this.initParams)
|
||||||
|
// },
|
||||||
|
// })
|
||||||
|
};
|
||||||
|
this.client.onmessage = (event) => {
|
||||||
|
const message = event.data;
|
||||||
|
const msg = JSON.parse(message)
|
||||||
|
if (msg && msg.msg_id) {
|
||||||
|
this.onMessageHandler({ msg_id: msg.msg_id })
|
||||||
|
}
|
||||||
|
this.onMessage(msg);
|
||||||
|
};
|
||||||
}
|
}
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
this.client.activate();
|
// 消息回执
|
||||||
|
public onMessageHandler(data: any) {
|
||||||
|
if (this.client && this.connected) {
|
||||||
|
this.client.send(JSON.stringify({ ...data, type: 'receipt' }));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 订阅主题
|
// 订阅主题
|
||||||
public subscribeToTopic(topic: string, onMessage: (message: string) => void) {
|
public subscribeToTopic(initParams: ApifoxModel, onMessage: (message: any) => void) {
|
||||||
console.log(`正在订阅主题: ${topic}`);
|
console.log(`正在订阅主题: `, initParams);
|
||||||
if (!this.client || !this.client.connected) {
|
this.initParams = { ...this.initParams, ...initParams }
|
||||||
|
if (this.client && this.connected) {
|
||||||
|
this.disconnect();
|
||||||
|
}
|
||||||
this.setupWebSocket();
|
this.setupWebSocket();
|
||||||
|
this.onMessage = onMessage;
|
||||||
}
|
}
|
||||||
|
public sendMessage(message: any) {
|
||||||
|
if (!this.client || !this.connected) {
|
||||||
|
ElMessage.error('发送失败,已重新连接,请重新操作')
|
||||||
|
this.disconnect()
|
||||||
|
this.setupWebSocket();
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if (this.client && this.connected) {
|
||||||
|
const msg = JSON.stringify({
|
||||||
|
...this.initParams,
|
||||||
|
...message,
|
||||||
|
})
|
||||||
|
try {
|
||||||
|
this.client.send(msg);
|
||||||
|
|
||||||
if (this.messageHandlers.has(topic)) {
|
} catch (error) {
|
||||||
this.messageHandlers.get(topic)?.push(onMessage);
|
console.log('error')
|
||||||
} else {
|
ElMessage.error('发送失败,已重新连接,请重新操作')
|
||||||
this.messageHandlers.set(topic, [onMessage]);
|
this.disconnect()
|
||||||
}
|
this.setupWebSocket();
|
||||||
|
|
||||||
if (this.client?.connected) {
|
|
||||||
this.client.subscribe(topic, (message) => {
|
|
||||||
const handlers = this.messageHandlers.get(topic);
|
|
||||||
handlers?.forEach((handler) => handler(message.body));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
public canSendMessage() {
|
||||||
|
return this.client && this.connected;
|
||||||
|
}
|
||||||
// 断开 WebSocket 连接
|
// 断开 WebSocket 连接
|
||||||
public disconnect() {
|
public disconnect() {
|
||||||
if (this.client) {
|
if (this.client && this.connected) {
|
||||||
console.log("断开 WebSocket 连接");
|
console.log("断开 WebSocket 连接");
|
||||||
this.client.deactivate();
|
clearTimeout(this.timer)
|
||||||
|
this.client.close();
|
||||||
this.client = null;
|
this.client = null;
|
||||||
|
this.connected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,51 +1,45 @@
|
||||||
import qs from "qs";
|
import qs from "qs";
|
||||||
import { useUserStoreHook } from "@/store";
|
import { useUserStoreHook } from "@/store";
|
||||||
import { ElMessage, ElMessageBox } from "element-plus";
|
import { ElMessage, ElMessageBox } from "element-plus";
|
||||||
const user = useUserStoreHook()
|
|
||||||
|
const user = useUserStoreHook();
|
||||||
|
|
||||||
export interface ApifoxModel {
|
export interface ApifoxModel {
|
||||||
account: string;
|
account: string;
|
||||||
/**
|
|
||||||
* 操作类型
|
|
||||||
*/
|
|
||||||
operate_type: string;
|
operate_type: string;
|
||||||
shop_id: string;
|
shop_id: string;
|
||||||
/**
|
|
||||||
* 桌码
|
|
||||||
*/
|
|
||||||
table_code?: string;
|
table_code?: string;
|
||||||
/**
|
|
||||||
* 消息类型
|
|
||||||
*/
|
|
||||||
type: string;
|
type: string;
|
||||||
[property: string]: any;
|
[property: string]: string | number | undefined; // 限制额外属性类型
|
||||||
}
|
}
|
||||||
export type msgType = 'add' | 'reduce' | 'remove' | 'edit' | 'init' | 'cleanup' | 'del' | 'rottable' | 'batch'
|
|
||||||
|
export type msgType = 'add' | 'reduce' | 'remove' | 'edit' | 'init' | 'cleanup' | 'del' | 'rottable' | 'batch';
|
||||||
|
|
||||||
class WebSocketManager {
|
class WebSocketManager {
|
||||||
private client: WebSocket | null = null;
|
private client: WebSocket | null = null;
|
||||||
private connected: boolean = false;
|
private connected: boolean = false;
|
||||||
private shop_id = user.userInfo.shopId ? String(user.userInfo.shopId) : '';
|
private shop_id = user.userInfo.shopId ? String(user.userInfo.shopId) : '';
|
||||||
private initParams: ApifoxModel = {
|
private initParams: ApifoxModel = {
|
||||||
type: 'manage',
|
type: 'manage',
|
||||||
account: this.shop_id,
|
account: this.shop_id || '', // 提供默认值
|
||||||
operate_type: 'init',
|
operate_type: 'init',
|
||||||
table_code: '',
|
table_code: '',
|
||||||
shop_id: this.shop_id,
|
shop_id: this.shop_id || '', // 提供默认值
|
||||||
};
|
};
|
||||||
private onMessage: (message: any) => void = function () { };
|
private onMessage: (message: any) => void = () => { };
|
||||||
private messageHandlers: Map<string, ((message: string) => void)[]> = new Map();
|
private messageHandlers: Map<string, ((message: string) => void)[]> = new Map();
|
||||||
private type: string = 'manage';
|
private type: string = 'manage';
|
||||||
private reconnectAttempts = 0;
|
private reconnectAttempts = 0;
|
||||||
private maxReconnectAttempts = 3; // 自定义最大重试次数
|
private maxReconnectAttempts = 3; // 自定义最大重试次数
|
||||||
private reconnectDelay = 5000; // 重试延迟(单位:毫秒)
|
private reconnectDelay = 5000; // 重试延迟(单位:毫秒)
|
||||||
private timer: any | null = null;
|
private timer: any | null = null;
|
||||||
|
|
||||||
// 初始化 WebSocket 客户端
|
// 初始化 WebSocket 客户端
|
||||||
setupWebSocket() {
|
setupWebSocket() {
|
||||||
const endpoint = import.meta.env.VITE_APP_WS_ENDPOINT;
|
const endpoint = import.meta.env.VITE_APP_WS_ENDPOINT;
|
||||||
|
|
||||||
// 如果没有配置 WebSocket 端点或显式关闭,直接返回
|
|
||||||
if (!endpoint) {
|
if (!endpoint) {
|
||||||
console.log("WebSocket 已被禁用,如需打开请在配置文件中配置 VITE_APP_WS_ENDPOINT");
|
console.warn("WebSocket 已被禁用,请在配置文件中配置 VITE_APP_WS_ENDPOINT");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -53,60 +47,49 @@ class WebSocketManager {
|
||||||
console.log("客户端已存在并且连接正常");
|
console.log("客户端已存在并且连接正常");
|
||||||
return this.client;
|
return this.client;
|
||||||
}
|
}
|
||||||
const url = qs.stringify(this.initParams)
|
|
||||||
|
const url = qs.stringify(this.initParams);
|
||||||
this.client = new WebSocket(endpoint + '?' + url);
|
this.client = new WebSocket(endpoint + '?' + url);
|
||||||
|
|
||||||
this.client.onopen = () => {
|
this.client.onopen = () => {
|
||||||
this.connected = true;
|
this.connected = true;
|
||||||
console.log("WebSocket 连接已建立");
|
console.log("WebSocket 连接已建立");
|
||||||
// ElNotification.success('WebSocket 连接已建立')
|
this.sendMessage(this.initParams);
|
||||||
this.sendMessage(this.initParams)
|
this.clearTimer();
|
||||||
clearTimeout(this.timer)
|
|
||||||
this.timer = setInterval(() => {
|
this.timer = setInterval(() => {
|
||||||
this.sendMessage({ "type": "ping_interval" })
|
this.sendMessage({ type: "ping_interval" });
|
||||||
}, 1000 * 10);
|
}, 1000 * 10);
|
||||||
};
|
};
|
||||||
|
|
||||||
this.client.onclose = () => {
|
this.client.onclose = () => {
|
||||||
clearTimeout(this.timer)
|
this.clearTimer();
|
||||||
if (!this.connected) {
|
|
||||||
// ElMessageBox.alert('WebSocket 连接已断开', 'Title', {
|
|
||||||
// confirmButtonText: '立即重连',
|
|
||||||
// callback: () => {
|
|
||||||
// this.sendMessage(this.initParams)
|
|
||||||
// },
|
|
||||||
// })
|
|
||||||
}
|
|
||||||
this.connected = false;
|
this.connected = false;
|
||||||
console.log("WebSocket 连接已断开");
|
console.log("WebSocket 连接已断开");
|
||||||
|
this.reconnect(); // 自动重连
|
||||||
};
|
};
|
||||||
this.client.onerror = (error) => {
|
|
||||||
clearTimeout(this.timer)
|
this.client.onerror = (error: Event) => {
|
||||||
this.connected = false;
|
this.clearTimer();
|
||||||
console.error("WebSocket 发生错误:", error);
|
console.error("WebSocket 发生错误:", error);
|
||||||
// ElNotification({
|
this.reconnect(); // 自动重连
|
||||||
// title: "提示",
|
|
||||||
// message: "WebSocket 发生错误",
|
|
||||||
// type: "error",
|
|
||||||
// });
|
|
||||||
// ElMessageBox.alert('WebSocket 发生错误', 'Title', {
|
|
||||||
// confirmButtonText: '立即重连',
|
|
||||||
// callback: () => {
|
|
||||||
// this.sendMessage(this.initParams)
|
|
||||||
// },
|
|
||||||
// })
|
|
||||||
};
|
};
|
||||||
this.client.onmessage = (event) => {
|
|
||||||
const message = event.data;
|
this.client.onmessage = (event: MessageEvent) => {
|
||||||
const msg = JSON.parse(message)
|
try {
|
||||||
if (msg && msg.msg_id) {
|
const message = JSON.parse(event.data);
|
||||||
this.onMessageHandler({ msg_id: msg.msg_id })
|
if (message && message.msg_id) {
|
||||||
|
this.onMessageHandler({ msg_id: message.msg_id });
|
||||||
|
}
|
||||||
|
this.onMessage(message);
|
||||||
|
} catch (e) {
|
||||||
|
console.error("消息解析失败:", e);
|
||||||
}
|
}
|
||||||
this.onMessage(msg);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// 消息回执
|
// 消息回执
|
||||||
public onMessageHandler(data: any) {
|
public onMessageHandler(data: any) {
|
||||||
if (this.client) {
|
if (this.client && this.connected) {
|
||||||
this.client.send(JSON.stringify({ ...data, type: 'receipt' }));
|
this.client.send(JSON.stringify({ ...data, type: 'receipt' }));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -114,49 +97,64 @@ class WebSocketManager {
|
||||||
// 订阅主题
|
// 订阅主题
|
||||||
public subscribeToTopic(initParams: ApifoxModel, onMessage: (message: any) => void) {
|
public subscribeToTopic(initParams: ApifoxModel, onMessage: (message: any) => void) {
|
||||||
console.log(`正在订阅主题: `, initParams);
|
console.log(`正在订阅主题: `, initParams);
|
||||||
this.initParams = { ...this.initParams, ...initParams }
|
this.initParams = { ...this.initParams, ...initParams };
|
||||||
if (this.client && this.connected) {
|
|
||||||
this.disconnect();
|
this.disconnect();
|
||||||
}
|
|
||||||
this.setupWebSocket();
|
this.setupWebSocket();
|
||||||
this.onMessage = onMessage;
|
this.onMessage = onMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
public sendMessage(message: any) {
|
public sendMessage(message: any) {
|
||||||
if (!this.client || !this.connected) {
|
if (!this.client || !this.connected) {
|
||||||
ElMessage.error('发送失败,已重新连接,请重新操作')
|
// ElMessage.error('发送失败,已重新连接,请重新操作');
|
||||||
this.disconnect()
|
this.reconnect();
|
||||||
this.setupWebSocket();
|
return;
|
||||||
return
|
|
||||||
}
|
}
|
||||||
if (this.client && this.connected) {
|
|
||||||
const msg = JSON.stringify({
|
const msg = JSON.stringify({ ...this.initParams, ...message });
|
||||||
...this.initParams,
|
|
||||||
...message,
|
|
||||||
})
|
|
||||||
try {
|
try {
|
||||||
this.client.send(msg);
|
this.client?.send(msg);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('error')
|
console.error("发送消息失败:", error);
|
||||||
ElMessage.error('发送失败')
|
// ElMessage.error('发送失败,已重新连接,请重新操作');
|
||||||
this.disconnect()
|
this.reconnect();
|
||||||
this.setupWebSocket();
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
public canSendMessage() {
|
public canSendMessage() {
|
||||||
return this.client && this.connected;
|
return this.client && this.connected;
|
||||||
}
|
}
|
||||||
|
|
||||||
// 断开 WebSocket 连接
|
// 断开 WebSocket 连接
|
||||||
public disconnect() {
|
public disconnect() {
|
||||||
if (this.client) {
|
if (this.client && this.connected) {
|
||||||
console.log("断开 WebSocket 连接");
|
console.log("断开 WebSocket 连接");
|
||||||
|
this.clearTimer();
|
||||||
this.client.close();
|
this.client.close();
|
||||||
this.client = null;
|
this.client = null;
|
||||||
this.connected = false;
|
this.connected = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 自动重连机制
|
||||||
|
private reconnect() {
|
||||||
|
if (this.reconnectAttempts < this.maxReconnectAttempts) {
|
||||||
|
this.reconnectAttempts++;
|
||||||
|
console.log(`尝试第 ${this.reconnectAttempts} 次重连...`);
|
||||||
|
setTimeout(() => {
|
||||||
|
this.setupWebSocket();
|
||||||
|
}, this.reconnectDelay);
|
||||||
|
} else {
|
||||||
|
console.error("达到最大重连次数,停止重连");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 清除定时器
|
||||||
|
private clearTimer() {
|
||||||
|
if (this.timer) {
|
||||||
|
clearInterval(this.timer);
|
||||||
|
this.timer = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default new WebSocketManager();
|
export default new WebSocketManager();
|
||||||
|
|
@ -14,17 +14,23 @@
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<span>增加数量:</span>
|
<span>增加数量:</span>
|
||||||
<span class="num">{{ data.inSumTotal || 0 }}</span>
|
<span class="num" @click="refStockHistoryShow('addCountNumber')">
|
||||||
|
{{ data.inSumTotal || 0 }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex">
|
<div style="display: flex">
|
||||||
<div>
|
<div>
|
||||||
<span>手动增加:</span>
|
<span>手动增加:</span>
|
||||||
<span class="num">{{ data.winInNum || 0 }}</span>
|
<span class="num" @click="refStockHistoryShow('addNumber')">
|
||||||
|
{{ data.winInNum || 0 }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<span style="margin: 0 20px; color: #ccc">|</span>
|
<span style="margin: 0 20px; color: #ccc">|</span>
|
||||||
<div>
|
<div>
|
||||||
<span>入库:</span>
|
<span>入库:</span>
|
||||||
<span class="num">{{ data.stockInNum || 0 }}</span>
|
<span class="num" @click="refStockHistoryShow('manualIn')">
|
||||||
|
{{ data.stockInNum || 0 }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -36,34 +42,47 @@
|
||||||
<div>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
<span>减少数量:</span>
|
<span>减少数量:</span>
|
||||||
<span class="num">{{ data.outSumTotal || 0 }}</span>
|
<span class="num" @click="refStockHistoryShow('subCountNumber')">
|
||||||
|
{{ data.outSumTotal || 0 }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div style="display: flex">
|
<div style="display: flex">
|
||||||
<div>
|
<div>
|
||||||
<span>手动减少:</span>
|
<span>手动减少:</span>
|
||||||
<span class="num">{{ data.lossOutNum || 0 }}</span>
|
<span class="num" @click="refStockHistoryShow('subNumber')">
|
||||||
|
{{ data.lossOutNum || 0 }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<span style="margin: 0 20px; color: #ccc">|</span>
|
<span style="margin: 0 20px; color: #ccc">|</span>
|
||||||
<div>
|
<div>
|
||||||
<span>消耗:</span>
|
<span>消耗:</span>
|
||||||
<span class="num">{{ data.consumeNum || 0 }}</span>
|
<span class="num" @click="refStockHistoryShow('saleNumber')">
|
||||||
|
{{ data.consumeNum || 0 }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<span style="margin: 0 20px; color: #ccc">|</span>
|
<span style="margin: 0 20px; color: #ccc">|</span>
|
||||||
<div>
|
<div>
|
||||||
<span>报损:</span>
|
<span>报损:</span>
|
||||||
<span class="num">{{ data.damageNum || 0 }}</span>
|
<span class="num" @click="refStockHistoryShow('lossNumber')">
|
||||||
|
{{ data.damageNum || 0 }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<span style="margin: 0 20px; color: #ccc">|</span>
|
<span style="margin: 0 20px; color: #ccc">|</span>
|
||||||
<div>
|
<div>
|
||||||
<span>出库:</span>
|
<span>出库:</span>
|
||||||
<span class="num">{{ data.stockOutNum || 0 }}</span>
|
<span class="num" @click="refStockHistoryShow('manualOut')">
|
||||||
|
{{ data.stockOutNum || 0 }}
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<stockHistory ref="refStockHistory"></stockHistory>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
|
import stockHistory from "./stockHistory.vue";
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
data: {
|
data: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
|
@ -72,6 +91,10 @@ const props = defineProps({
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
const refStockHistory = ref();
|
||||||
|
function refStockHistoryShow(key) {
|
||||||
|
refStockHistory.value.show(key);
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -109,6 +132,7 @@ const props = defineProps({
|
||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
&.num {
|
&.num {
|
||||||
color: #3f9eff;
|
color: #3f9eff;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
export const paramsMap = {
|
||||||
|
addCountNumber: {
|
||||||
|
inOutType: "in",
|
||||||
|
},
|
||||||
|
addNumber: {
|
||||||
|
inOutType: "in",
|
||||||
|
inOutItem: "win-in",
|
||||||
|
},
|
||||||
|
manualIn: {
|
||||||
|
inOutType: "in",
|
||||||
|
inOutItem: "manual-in",
|
||||||
|
},
|
||||||
|
subCountNumber: {
|
||||||
|
inOutType: "out",
|
||||||
|
},
|
||||||
|
subNumber: {
|
||||||
|
inOutType: "out",
|
||||||
|
inOutItem: "loss-out",
|
||||||
|
},
|
||||||
|
saleNumber: {
|
||||||
|
inOutType: "out",
|
||||||
|
inOutItem: "order-out",
|
||||||
|
},
|
||||||
|
lossNumber: {
|
||||||
|
inOutType: "out",
|
||||||
|
inOutItem: "damage-out",
|
||||||
|
},
|
||||||
|
manualOut: {
|
||||||
|
inOutType: "out",
|
||||||
|
inOutItem: "manual-out",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const inOutItemMap = {
|
||||||
|
"manual-in": "手动入库",
|
||||||
|
"manual-out": "手动出库",
|
||||||
|
"win-in": "盘盈入库",
|
||||||
|
"loss-out": "盘亏出库",
|
||||||
|
"order-in": "订单退款入库",
|
||||||
|
"order-out": "订单消费出库"
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,132 @@
|
||||||
|
<!-- 商品库存记录 -->
|
||||||
|
<template>
|
||||||
|
<el-dialog width="80%" :title="`${keysList[key]}`" v-model="dialogVisible" @close="reset">
|
||||||
|
<div class="head-container">
|
||||||
|
<el-table ref="table" :data="tableData.data" v-loading="tableData.loading" height="400px">
|
||||||
|
<!-- 共存前面 -->
|
||||||
|
<el-table-column label="耗材名称" prop="conName" />
|
||||||
|
<el-table-column label="原有库存" prop="beforeNumber"></el-table-column>
|
||||||
|
<el-table-column label="变动后库存" prop="afterNumber"></el-table-column>
|
||||||
|
<el-table-column label="库存变动数量" prop="inOutNumber"></el-table-column>
|
||||||
|
<el-table-column label="操作类型" prop="inOutItem">
|
||||||
|
<template v-slot="scope">
|
||||||
|
{{ inOutItemMap[scope.row.inOutItem] }}
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column v-if="variabilitytitle == '消耗'" label="订单编号" prop="orderNo">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<div>
|
||||||
|
<el-button type="text" @click="toGoodslist(scope.row.orderNo)">
|
||||||
|
{{ scope.row.orderNo }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<!-- 减少数量 -->
|
||||||
|
<el-table-column v-if="variabilitytitle == '报损'" label="图片" prop="coverImg" />
|
||||||
|
<!-- 尾巴 -->
|
||||||
|
<el-table-column v-if="variabilitytitle != '消耗'" label="操作人" prop="createUserName" />
|
||||||
|
<el-table-column v-if="variabilitytitle != '消耗'" label="备注" prop="remark" />
|
||||||
|
<el-table-column label="操作时间" prop="createTime"></el-table-column>
|
||||||
|
|
||||||
|
<!-- <el-table-column label="现有库存" prop="balance" />
|
||||||
|
<el-table-column label="业务说明" prop="bizName" />
|
||||||
|
<el-table-column label="创建时间" prop="createTime"></el-table-column> -->
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
<div class="head-container">
|
||||||
|
<el-pagination
|
||||||
|
:total="tableData.total"
|
||||||
|
@size-change="handleSizeChange"
|
||||||
|
:current-page="tableData.page + 1"
|
||||||
|
:page-size="tableData.size"
|
||||||
|
@current-change="paginationChange"
|
||||||
|
layout="total, sizes, prev, pager, next, jumper"
|
||||||
|
></el-pagination>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
import stockApi from "@/api/product/stock";
|
||||||
|
import { paramsMap, inOutItemMap } from "./data";
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
query: {
|
||||||
|
type: Object,
|
||||||
|
default: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
dayjs,
|
||||||
|
dialogVisible: false,
|
||||||
|
inOutItemMap,
|
||||||
|
key: "",
|
||||||
|
keysList: {
|
||||||
|
stockNumber: "现有数量",
|
||||||
|
addCountNumber: "增加数量",
|
||||||
|
addNumber: "手动增加",
|
||||||
|
manualIn: "入库",
|
||||||
|
refundNumber: "退货",
|
||||||
|
subCountNumber: "减少数量",
|
||||||
|
subNumber: "手动减少",
|
||||||
|
saleNumber: "消耗",
|
||||||
|
lossNumber: "报损",
|
||||||
|
manualOut: "出库",
|
||||||
|
},
|
||||||
|
productId: "",
|
||||||
|
tableData: {
|
||||||
|
sort: 1,
|
||||||
|
data: [],
|
||||||
|
page: 1,
|
||||||
|
size: 10,
|
||||||
|
loading: false,
|
||||||
|
total: 0,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// 库存记录列表
|
||||||
|
async tbProductStockDetailStock() {
|
||||||
|
try {
|
||||||
|
this.tableData.loading = true;
|
||||||
|
const res = await stockApi.flow({
|
||||||
|
page: this.tableData.page,
|
||||||
|
size: this.tableData.size,
|
||||||
|
...paramsMap[this.key],
|
||||||
|
});
|
||||||
|
this.tableData.loading = false;
|
||||||
|
this.tableData.data = res.records;
|
||||||
|
this.tableData.total = res.totalRow * 1;
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 分页回调
|
||||||
|
paginationChange(e) {
|
||||||
|
this.tableData.page = e;
|
||||||
|
this.tbProductStockDetailStock();
|
||||||
|
},
|
||||||
|
handleSizeChange(val) {
|
||||||
|
this.tableData.size = val;
|
||||||
|
this.tbProductStockDetailStock();
|
||||||
|
},
|
||||||
|
// 显示
|
||||||
|
show(key) {
|
||||||
|
this.dialogVisible = true;
|
||||||
|
this.key = key;
|
||||||
|
this.tbProductStockDetailStock();
|
||||||
|
},
|
||||||
|
// 初始化dialog
|
||||||
|
reset() {
|
||||||
|
this.tableData.page = 1;
|
||||||
|
this.tableData.data = [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss"></style>
|
||||||
|
|
@ -733,7 +733,6 @@ onMounted(async () => {
|
||||||
table.value = tableRes || {};
|
table.value = tableRes || {};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
console.log(table.value);
|
|
||||||
init();
|
init();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue