feat: 积分商城-完成
This commit is contained in:
@@ -0,0 +1,260 @@
|
||||
<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>
|
||||
Reference in New Issue
Block a user