完善采集日志功能:原始数据详情弹窗、周期详情弹窗、修复排行榜日期格式

main
haoliang 1 hour ago
parent 4366cf9347
commit f703f92098

@ -31,9 +31,15 @@ export interface CollectCycle {
export interface CollectRaw {
id: number
logTime: string
sourceAddress?: string
contentPreview?: string
collectAddressId: number
requestTime: string
responseTime: string
responseDuration?: number | null
isSuccess: number
statusCode?: number | null
rawJson?: string
errorMessage?: string
createdAt: string
}
// --- 公开的 API 封装 ---
@ -91,4 +97,9 @@ export function fetchRawList(params?: {
)
}
// 获取原始日志详情
export function fetchRawDetail(id: number) {
return request.get<CollectRaw>(`/admin/collect-log/raw/${id}`)
}
export default {}

@ -132,6 +132,25 @@
background
layout="total, sizes, prev, pager, next, jumper"
/>
<!-- 采集周期详情弹窗 -->
<el-dialog v-model="cycleDetailVisible" title="采集周期详情" width="640px" destroy-on-close>
<el-descriptions :column="2" border v-if="cycleDetailRow">
<el-descriptions-item label="周期时间">{{ cycleDetailRow.cycleTime }}</el-descriptions-item>
<el-descriptions-item label="采集地址">{{ cycleDetailRow.addressName || cycleDetailRow.collectAddressId }}</el-descriptions-item>
<el-descriptions-item label="总机床数">{{ cycleDetailRow.totalMachines }}</el-descriptions-item>
<el-descriptions-item label="成功数">{{ cycleDetailRow.successCount }}</el-descriptions-item>
<el-descriptions-item label="失败数">{{ cycleDetailRow.failCount }}</el-descriptions-item>
<el-descriptions-item label="是否异常">
<el-tag :type="cycleDetailRow.hasAnomaly ? 'danger' : 'success'" size="small">{{ cycleDetailRow.hasAnomaly ? '有异常' : '无异常' }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="变更分布" :span="2">{{ cycleDetailRow.changeDistribution || '无' }}</el-descriptions-item>
<el-descriptions-item label="摘要" :span="2">{{ cycleDetailRow.cycleSummary || '无' }}</el-descriptions-item>
</el-descriptions>
<template #footer>
<el-button @click="cycleDetailVisible = false">关闭</el-button>
</template>
</el-dialog>
</el-tab-pane>
<!-- 3) Raw -->
@ -153,9 +172,20 @@
<el-table :data="rawList" border stripe v-loading="rawLoading" style="width: 100%">
<el-table-column prop="id" label="ID" width="80" />
<el-table-column prop="logTime" label="时间" width="170" />
<el-table-column prop="sourceAddress" label="地址" />
<el-table-column prop="contentPreview" label="内容摘要" show-overflow-tooltip />
<el-table-column prop="requestTime" label="请求时间" width="170" />
<el-table-column prop="responseDuration" label="耗时(ms)" width="100" />
<el-table-column label="成功" width="80" align="center">
<template #default="{ row }">
<el-tag :type="row.isSuccess ? 'success' : 'danger'" size="small">{{ row.isSuccess ? '成功' : '失败' }}</el-tag>
</template>
</el-table-column>
<el-table-column prop="statusCode" label="状态码" width="90" />
<el-table-column prop="errorMessage" label="错误信息" show-overflow-tooltip />
<el-table-column label="操作" width="120" fixed="right" align="center">
<template #default="{ row }">
<el-button type="text" @click="viewRawDetail(row)"></el-button>
</template>
</el-table-column>
</el-table>
<el-pagination
@ -166,6 +196,30 @@
background
layout="total, sizes, prev, pager, next, jumper"
/>
<!-- 原始数据详情弹窗 -->
<el-dialog v-model="rawDetailVisible" title="原始采集数据详情" width="860px" destroy-on-close>
<el-descriptions :column="2" border v-if="rawDetail">
<el-descriptions-item label="ID">{{ rawDetail.id }}</el-descriptions-item>
<el-descriptions-item label="采集地址ID">{{ rawDetail.collectAddressId }}</el-descriptions-item>
<el-descriptions-item label="请求时间">{{ rawDetail.requestTime }}</el-descriptions-item>
<el-descriptions-item label="响应时间">{{ rawDetail.responseTime }}</el-descriptions-item>
<el-descriptions-item label="响应耗时">{{ rawDetail.responseDuration }} ms</el-descriptions-item>
<el-descriptions-item label="状态码">{{ rawDetail.statusCode }}</el-descriptions-item>
<el-descriptions-item label="是否成功">
<el-tag :type="rawDetail.isSuccess ? 'success' : 'danger'" size="small">{{ rawDetail.isSuccess ? '成功' : '失败' }}</el-tag>
</el-descriptions-item>
<el-descriptions-item label="创建时间">{{ rawDetail.createdAt }}</el-descriptions-item>
<el-descriptions-item label="错误信息" :span="2">{{ rawDetail.errorMessage || '无' }}</el-descriptions-item>
</el-descriptions>
<div style="margin-top: 16px">
<div style="font-weight: bold; margin-bottom: 8px">原始JSON</div>
<el-input type="textarea" :rows="16" readonly :model-value="formatJson(rawDetail?.rawJson)" style="font-family: monospace" />
</div>
<template #footer>
<el-button @click="rawDetailVisible = false">关闭</el-button>
</template>
</el-dialog>
</el-tab-pane>
</el-tabs>
</div>
@ -301,10 +355,13 @@ function resetCycle() {
}
function viewCycle(row: CollectCycle) {
//
ElMessage.info(`周期 ${row.cycleTime} 区间分析完成,共 ${row.totalMachines} 台机床`)
cycleDetailRow.value = row
cycleDetailVisible.value = true
}
const cycleDetailRow = ref<CollectCycle | null>(null)
const cycleDetailVisible = ref(false)
watch(() => cyclePage.page + cyclePage.pageSize, loadCycles)
//
onMounted(() => {
@ -320,7 +377,28 @@ const rawList = ref<CollectRaw[]>([])
const rawLoading = ref(false)
const rawPage = reactive({ page: 1, pageSize: 20, total: 0 })
const rawQuery = reactive({ dateRange: null as string[] | null, addressId: undefined as number | undefined })
const rawURLList = ref<string[]>([])
const rawDetailVisible = ref(false)
const rawDetail = ref<CollectRaw | null>(null)
async function viewRawDetail(row: CollectRaw) {
rawDetailVisible.value = true
rawDetail.value = null
try {
const res = await request.get<CollectRaw>(`/admin/collect-log/raw/${row.id}`)
rawDetail.value = res.data as CollectRaw
} catch {
rawDetail.value = row
}
}
function formatJson(json: string | undefined | null): string {
if (!json) return ''
try {
return JSON.stringify(JSON.parse(json), null, 2)
} catch {
return json
}
}
async function loadRaw() {
rawLoading.value = true
@ -345,6 +423,8 @@ function resetRaw() {
loadRaw()
}
watch(() => [rawPage.page, rawPage.pageSize], () => loadRaw())
onMounted(() => {
loadRaw()
})
@ -376,8 +456,6 @@ async function loadMachines() {
}
// -------------- Helpers --------------
// tag/label
</script>
<style scoped lang="scss">

@ -335,7 +335,7 @@ const workshopUnitLabel = computed(() => workshopDays.value > 1 ? '日均' : '
function getDateRange(type: DateType, customRange?: [string, string]): { startDate: string; endDate: string } {
const today = new Date()
const fmt = (d: Date) => d.toISOString().slice(0, 10)
const fmt = (d: Date) => `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`
const endDate = fmt(today)
switch (type) {
case 'today': return { startDate: endDate, endDate }

@ -50,6 +50,19 @@ namespace CncRepository.Impl.Log
}
}
/// <summary>分页获取所有原始记录</summary>
public PagedResult<CollectRaw> GetAll(int page, int pageSize)
{
using (var conn = CreateConnection())
{
int skip = Math.Max(0, (page - 1) * pageSize);
var items = conn.Query<CollectRaw>($"SELECT {SelectColumns} FROM log_collect_raw ORDER BY created_at DESC LIMIT @PageSize OFFSET @Skip", new { PageSize = pageSize, Skip = skip }).AsList();
int total = conn.ExecuteScalar<int>(@"SELECT COUNT(1) FROM log_collect_raw");
return new PagedResult<CollectRaw> { Items = items.ToList(), Total = total, Page = page, PageSize = pageSize };
}
}
/// <summary>写入原始采集记录</summary>
public long Create(CollectRaw entity)
{

@ -13,6 +13,8 @@ namespace CncRepository.Interface
PagedResult<CollectRaw> GetByAddressId(int collectAddressId, int page, int pageSize);
PagedResult<CollectRaw> GetAll(int page, int pageSize);
CollectRaw GetLatestByAddressId(int collectAddressId);
long Create(CollectRaw entity);

@ -75,8 +75,21 @@ namespace CncWebApi.Controllers
[ResponseType(typeof(ApiResponse<PagedResult<CollectRaw>>))]
public IHttpActionResult GetRawList([FromUri] int? collectAddressId = null, [FromUri] int page = 1, [FromUri] int pageSize = 20)
{
var result = _rawRepository.GetByAddressId(collectAddressId ?? 0, page, pageSize);
var result = collectAddressId.HasValue
? _rawRepository.GetByAddressId(collectAddressId.Value, page, pageSize)
: _rawRepository.GetAll(page, pageSize);
return Ok(ApiResponse<PagedResult<CollectRaw>>.Success(result));
}
/// <summary>获取原始采集日志详情</summary>
[HttpGet]
[Route("raw/{id:long}")]
[ResponseType(typeof(ApiResponse<CollectRaw>))]
public IHttpActionResult GetRawDetail(long id)
{
var entity = _rawRepository.GetById(id);
if (entity == null) return NotFound();
return Ok(ApiResponse<CollectRaw>.Success(entity));
}
}
}

Loading…
Cancel
Save