Files
points-mall/supplied-h5/src/view/joyful-selection/supplier-logs/index.vue
T
2026-07-31 19:08:15 +08:00

261 lines
6.1 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<main class="supplier-logs-page">
<van-nav-bar title="供应商日志" left-arrow @click-left="$router.back()" />
<section class="toolbar">
<span :class="{ active: listening }">{{ listening ? '监听中' : '已暂停' }}</span>
<button type="button" @click="loadLogs">刷新</button>
<button type="button" @click="clearLogs">清除</button>
</section>
<section class="console-panel">
<div v-if="consoleLogs.length === 0" class="console-empty">暂无日志,正在监听请求...</div>
<article v-for="item in consoleLogs" :key="item.id" class="console-line" :class="item.type">
<p><span>{{ formatTime(item.time) }}</span><b>{{ item.title }}:</b></p>
<pre>{{ formatRequestLine(item) }}</pre>
<pre>请求参数:{{ formatRequestParams(item.content) }}</pre>
</article>
</section>
</main>
</template>
<script>
import { Toast } from 'vant'
import { getFunction } from '@/api/supplied-service'
const API_BASE = process.env.VUE_APP_SUPPLIED_API_BASE || 'http://localhost:8888/api'
const LOG_GROUPS = [
{ type: 'backend-receive', title: '当前后端接收请求', emptyText: '暂无后端接收请求' },
{ type: 'zhgh-send', title: '向ZHGH发送请求', emptyText: '暂无向ZHGH发送请求' },
{ type: 'zhgh-receive', title: '接收ZHGH请求', emptyText: '暂无接收ZHGH请求' }
]
const POLL_INTERVAL = 2000
export default {
name: 'JoyfulSelectionSupplierLogs',
data: () => ({
logs: [],
timer: null,
listening: false
}),
computed: {
consoleLogs() {
return this.logs
.filter(item => LOG_GROUPS.some(group => group.type === item.type))
.slice()
.reverse()
}
},
created() {
this.loadLogs()
this.startListening()
},
beforeDestroy() {
this.stopListening()
},
methods: {
async loadLogs() {
try {
const data = await getFunction('supplier-logs')
this.logs = data?.logs || []
} catch (error) {
Toast(error.message || '查询日志失败')
}
},
async clearLogs() {
try {
const response = await fetch(`${API_BASE.replace(/\/$/, '')}/supplier-logs`, {
method: 'DELETE'
})
const payload = await response.json().catch(() => ({}))
if (!response.ok || payload.success === false) {
throw new Error(payload.error?.message || payload.msg || '清除日志失败')
}
this.logs = []
Toast('日志已清除')
} catch (error) {
Toast(error.message || '清除日志失败')
}
},
startListening() {
this.stopListening()
this.listening = true
this.timer = window.setInterval(() => {
this.loadLogs()
}, POLL_INTERVAL)
},
stopListening() {
if (this.timer) {
window.clearInterval(this.timer)
this.timer = null
}
this.listening = false
},
formatTime(time) {
if (!time) return '-'
const date = new Date(time)
if (Number.isNaN(date.getTime())) return time
const pad = value => String(value).padStart(2, '0')
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
},
formatRequestLine(item) {
const content = item.content || {}
const method = content.method || 'POST'
const url = this.fullUrl(content.url || content.path || '-')
return `${method} ${url}`
},
fullUrl(url) {
if (!url || url === '-') return '-'
if (/^https?:\/\//i.test(url)) return url
const base = API_BASE.replace(/\/api\/?$/, '').replace(/\/$/, '')
const path = String(url).startsWith('/') ? url : `/${url}`
return `${base}${path}`
},
formatRequestParams(content = {}) {
const params = {
...(content.query || {}),
...(content.body || {})
}
const entries = Object.entries(params).filter(([, value]) => value !== undefined && value !== null && value !== '')
if (entries.length === 0) {
return '-'
}
return entries.map(([key, value]) => `${key}=${this.formatParamValue(value)}`).join('&')
},
formatParamValue(value) {
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
return value
}
return JSON.stringify(value)
}
}
}
</script>
<style scoped lang="less">
.supplier-logs-page {
height: 100vh;
padding: 56px 10px 18px;
overflow: hidden;
background: #f7f8fa;
}
.supplier-logs-page ::v-deep .van-nav-bar {
position: fixed;
z-index: 20;
top: 0;
right: 0;
left: 0;
}
.toolbar {
display: flex;
align-items: center;
justify-content: flex-end;
gap: 10px;
margin-bottom: 10px;
}
.toolbar span {
position: relative;
padding-left: 14px;
color: #999;
font-size: 12px;
}
.toolbar span::before {
content: '';
position: absolute;
top: 50%;
left: 0;
width: 8px;
height: 8px;
border-radius: 50%;
background: #bbb;
transform: translateY(-50%);
}
.toolbar span.active {
color: #20b879;
}
.toolbar span.active::before {
background: #20b879;
}
.toolbar button {
height: 32px;
padding: 0 14px;
border: 1px solid #ff5b20;
border-radius: 6px;
color: #ff5b20;
font-size: 13px;
background: #fff7f2;
}
.console-panel {
height: calc(100vh - 116px);
overflow: auto;
padding: 12px;
border-radius: 8px;
background: #111;
}
.console-empty {
color: #7fda89;
font-size: 12px;
line-height: 20px;
}
.console-line + .console-line {
margin-top: 14px;
}
.console-line p {
display: flex;
flex-wrap: wrap;
gap: 8px;
margin: 0;
color: #7fda89;
font-size: 12px;
line-height: 20px;
}
.console-line span {
color: #8aa0b4;
}
.console-line b {
color: #ffd166;
font-weight: 700;
}
.console-line.backend-receive b {
color: #7fda89;
}
.console-line.zhgh-send b {
color: #5cc8ff;
}
.console-line.zhgh-receive b {
color: #ff8a5c;
}
.console-line pre {
overflow-x: auto;
margin: 4px 0 0;
color: #e6edf3;
font-size: 12px;
line-height: 18px;
white-space: pre-wrap;
word-break: break-all;
}
</style>