diff --git a/pgweb/src/api/businessManage/inquiry.js b/pgweb/src/api/businessManage/inquiry.js index 0a9e54b..dccd227 100644 --- a/pgweb/src/api/businessManage/inquiry.js +++ b/pgweb/src/api/businessManage/inquiry.js @@ -140,3 +140,9 @@ export async function checkBusinessNoIsValid (params) { const res = await post('admin/Bussiness/checkBusinessNoIsValid', params) return res } + +// 获取未回价数量(return_price_status=2) +export async function getUnreturnedPriceCount (params) { + const res = await post('admin/Pending/getUnreturnedPriceCount', params) + return res +} diff --git a/pgweb/src/components/menu/nxIconMenu.vue b/pgweb/src/components/menu/nxIconMenu.vue index f90f6c7..9fbf43d 100644 --- a/pgweb/src/components/menu/nxIconMenu.vue +++ b/pgweb/src/components/menu/nxIconMenu.vue @@ -1,9 +1,8 @@ - + - + \ No newline at end of file +.push-value-badge { + display: inline-flex; + align-items: center; + justify-content: center; + min-width: 18px; + height: 18px; + line-height: 18px; + padding: 0 4px; + font-size: 11px; + color: #fff; + background-color: #f56c6c; + border-radius: 9px; + margin-left: 4px; + text-align: center; + flex-shrink: 0; +} + diff --git a/pgweb/src/components/menu/nxMenu.vue b/pgweb/src/components/menu/nxMenu.vue index c8861c1..387609d 100644 --- a/pgweb/src/components/menu/nxMenu.vue +++ b/pgweb/src/components/menu/nxMenu.vue @@ -3,27 +3,85 @@
- - + @@ -37,4 +95,26 @@ :deep .el-menu-item.is-active.menu-custom { color: var(--main-color); } - \ No newline at end of file + .push-value-badge { + display: inline-block; + min-width: 20px; + height: 20px; + line-height: 20px; + padding: 0 6px; + font-size: 12px; + color: #fff; + background-color: #f56c6c; + border-radius: 10px; + margin-left: 8px; + text-align: center; + } + .push-dot-badge { + display: inline-block; + width: 8px; + height: 8px; + background-color: #f56c6c; + border-radius: 50%; + margin-left: 8px; + margin-top: 4px; + } + diff --git a/pgweb/src/libs/socket.js b/pgweb/src/libs/socket.js index 7c74449..1910f28 100644 --- a/pgweb/src/libs/socket.js +++ b/pgweb/src/libs/socket.js @@ -1,9 +1,65 @@ import io from 'socket.io-client' +// 使用 polling 模式以兼容 PHPSocketIO 1.1 const socket = io(process.env.VUE_APP_SOCKET_URL, { - transports: ['websocket'], - reconnection: true, // 是否自动重新建立连接,默认为true - reconnectionAttempts: 1 // 尝试重连的次数,默认为无限次 + transports: ['polling'], + reconnection: true, + reconnectionAttempts: 5, + autoConnect: false, + forceNew: true, + timeout: 10000, + jsonp: false, + query: {}, + upgrade: false, + allowUpgrades: false, + rejectUnauthorized: false, + timestampRequests: true }) +// 添加连接状态监听 +socket.on('connect', () => { + console.log('WebSocket已成功连接到服务器:', process.env.VUE_APP_SOCKET_URL) +}) + +socket.on('disconnect', (reason) => { + console.log('WebSocket连接断开,原因:', reason) +}) + +socket.on('connect_error', (error) => { + console.error('WebSocket连接失败:', error) +}) + +socket.on('connect_timeout', () => { + console.error('WebSocket连接超时') +}) + +// 连接方法 +export const connectSocket = () => { + console.log('尝试启动WebSocket连接...') + console.log('当前连接状态:', socket.connected) + console.log('连接状态详细:', socket.io && socket.io.engine ? socket.io.engine.transport.name : '未知') + console.log('目标地址:', process.env.VUE_APP_SOCKET_URL) + + // 如果未连接或者正在断开连接,尝试连接 + if (!socket.connected || socket.disconnected) { + socket.connect() + console.log('WebSocket连接请求已发送') + } else { + console.log('WebSocket已经处于连接状态') + } +} + +// 断开连接方法 +export const disconnectSocket = () => { + console.log('尝试断开WebSocket连接...') + console.log('当前连接状态:', socket.connected) + + if (socket.connected) { + socket.disconnect() + console.log('WebSocket连接已断开') + } else { + console.log('WebSocket未连接,无需断开') + } +} + export default socket diff --git a/pgweb/src/libs/unreturnedPrice.js b/pgweb/src/libs/unreturnedPrice.js new file mode 100644 index 0000000..3260195 --- /dev/null +++ b/pgweb/src/libs/unreturnedPrice.js @@ -0,0 +1,26 @@ +import { EventBus } from './eventBus' +import { getUnreturnedPriceCount } from '@/api/businessManage/inquiry' + +/** + * 获取并更新未回价数量 + * 调用API获取最新数量,并通过EventBus广播给所有监听者 + */ +export const fetchAndUpdateUnreturnedPriceCount = async () => { + console.log('fetchAndUpdateUnreturnedPriceCount: 开始获取未回价数量...') + try { + const response = await getUnreturnedPriceCount() + if (response && response.code === 1) { + const count = response.data.count || 0 + console.log('fetchAndUpdateUnreturnedPriceCount: 获取到未回价数量:', count) + // 通过事件总线传递数量给菜单组件 + EventBus.$emit('updateUnreturnedCount', count) + return count + } else { + console.warn('fetchAndUpdateUnreturnedPriceCount: 接口返回异常:', response) + return 0 + } + } catch (error) { + console.error('fetchAndUpdateUnreturnedPriceCount: 获取未回价数量失败:', error) + return 0 + } +} \ No newline at end of file diff --git a/pgweb/src/router/index.js b/pgweb/src/router/index.js index 46d61d8..d907be4 100644 --- a/pgweb/src/router/index.js +++ b/pgweb/src/router/index.js @@ -5,6 +5,8 @@ import iView from 'view-design' import { getToken, canTurnTo, initRouter, isRefreshToken } from '@/libs/util' import * as localStore from 'store' import store from '@/store' +import { connectSocket } from '@/libs/socket' +import { fetchAndUpdateUnreturnedPriceCount } from '@/libs/unreturnedPrice' Vue.use(Router) let routers = routes @@ -30,6 +32,14 @@ const HOME_PAGE_NAME = 'home' // 平台首页 router.beforeEach((to, from, next) => { iView.LoadingBar.start() const token = getToken() + + // 如果用户已登录,确保WebSocket连接已建立并获取最新未回价数量 + if (token && to.name !== LOGIN_PAGE_NAME) { + connectSocket() + // 每次刷新页面都获取最新的未回价数量 + fetchAndUpdateUnreturnedPriceCount() + } + if (!token && to.name !== LOGIN_PAGE_NAME) { localStore.clearAll() // 未登录且要跳转的页面不是登录页 diff --git a/pgweb/src/store/modules/user.js b/pgweb/src/store/modules/user.js index e7ac8ea..a7c835f 100644 --- a/pgweb/src/store/modules/user.js +++ b/pgweb/src/store/modules/user.js @@ -3,6 +3,7 @@ import { login, checkLogin } from '@/api/user' import store from 'store' import config from '@/config' import Cookies from 'js-cookie' +import { connectSocket } from '@/libs/socket' export default { state: { @@ -33,8 +34,8 @@ export default { login (state, data) { console.log("user.js::login::userinfo",data.userinfo) // store.set('indexMenuList', JSON.stringify(data.menu['index'])) - // store.set('busMenuList', JSON.stringify(data.menu)) - store.set('busMenuList', JSON.stringify(data.admmenu)) + // store.set('busMenuList', JSON.stringify(data.menu)) + store.set('busMenuList', JSON.stringify(data.admmenu)) store.set('userinfo', data.userinfo) store.set('isAdmin',data.userinfo.roleCode.includes("ROLE_ADMIN")) store.set('access', data.perFlags) @@ -53,7 +54,7 @@ export default { }, actions: { handleLogin ({ commit }, { username, password }) { - + username = username.trim() return new Promise((resolve, reject) => { login({ username, password, version: config.version }).then(res => { @@ -61,6 +62,8 @@ export default { store.clearAll() commit('setToken', res.data.apiAuth) commit('login', res.data) + // 登录成功后启动WebSocket连接 + connectSocket() } resolve(res) }).catch(err => { diff --git a/pgweb/src/views/home/components/message.vue b/pgweb/src/views/home/components/message.vue index ae8a47e..8d8de99 100644 --- a/pgweb/src/views/home/components/message.vue +++ b/pgweb/src/views/home/components/message.vue @@ -196,13 +196,10 @@ export default { WorkflowProgressCount: 0 // 工作流进度-未读消息数量 }, label1: (h) => { - return h('div', [ + const count = this.formItem.inquiryPendingCount || 0 + return h('div', { style: { display: 'flex', alignItems: 'center' } }, [ h('span', '询价待处理'), - h('Badge', { - props: { - count: this.formItem.inquiryPendingCount - } - }) + count > 0 ? h('span', { class: 'message-badge' }, count) : null ]) }, /* label2: (h) => { @@ -321,6 +318,8 @@ export default { getMessageList().then(res => { if (res.code === 1) { this.formItem = res.data + console.log('message.vue 获取消息列表成功:', this.formItem) + console.log('询价待处理数量:', this.formItem.inquiryPendingCount) } else { this.$Message.error(res.msg) } @@ -332,7 +331,7 @@ export default { if (res.code === 1) { if (row.message_type == 5 || row.message_type == 8 || row.message_type == 11 || row.message_type == 14 || row.message_type == 29 || row.message_type == 31){ this.getMessageList() - } + } } else { this.$Message.error(res.msg) } @@ -372,4 +371,17 @@ export default { .issee { color: #ccc; } +.message-badge { + display: inline-block; + min-width: 18px; + height: 18px; + line-height: 18px; + padding: 0 4px; + font-size: 11px; + color: #fff; + background-color: #f56c6c; + border-radius: 9px; + margin-left: 6px; + text-align: center; +} diff --git a/pgweb/src/views/home/home.vue b/pgweb/src/views/home/home.vue index 2b58a8a..aadaeb5 100644 --- a/pgweb/src/views/home/home.vue +++ b/pgweb/src/views/home/home.vue @@ -24,8 +24,33 @@ diff --git a/pgweb/src/views/main/components/avatar/avatar.vue b/pgweb/src/views/main/components/avatar/avatar.vue index 5f8c1ab..ff23731 100644 --- a/pgweb/src/views/main/components/avatar/avatar.vue +++ b/pgweb/src/views/main/components/avatar/avatar.vue @@ -1,10 +1,10 @@