261 lines
6.1 KiB
Vue
261 lines
6.1 KiB
Vue
<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>
|