| | |
| | | <template> |
| | | <div> |
| | | <p>异步导出任务入队(无 RabbitMQ 时后端仅记录日志并返回 taskId)。</p> |
| | | <el-button v-permission="'exports:enqueue'" type="primary" @click="enqueue">发起导出</el-button> |
| | | <p v-if="taskId">taskId: {{ taskId }}</p> |
| | | <div class="page-head"> |
| | | <div class="page-title">操作日志</div> |
| | | <div class="page-subtitle">展示小程序员工端写操作记录</div> |
| | | </div> |
| | | |
| | | <el-table :data="rows" v-loading="loading" stripe> |
| | | <el-table-column prop="opTime" label="操作时间" min-width="180" /> |
| | | <el-table-column prop="operatorName" label="操作人" min-width="120" /> |
| | | <el-table-column prop="module" label="模块" min-width="120" /> |
| | | <el-table-column prop="action" label="动作" min-width="140" /> |
| | | <el-table-column prop="resourceType" label="资源类型" min-width="140" show-overflow-tooltip /> |
| | | <el-table-column prop="resourceId" label="资源标识" min-width="220" show-overflow-tooltip /> |
| | | <el-table-column prop="traceId" label="TraceId" min-width="220" show-overflow-tooltip /> |
| | | <el-table-column label="详情" min-width="280"> |
| | | <template #default="{ row }"> |
| | | <span class="detail-text">{{ row.detailJson || "—" }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | |
| | | <div class="pager"> |
| | | <el-pagination |
| | | background |
| | | layout="total, prev, pager, next" |
| | | :current-page="page" |
| | | :page-size="size" |
| | | :total="total" |
| | | @current-change="handlePageChange" |
| | | /> |
| | | </div> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup lang="ts"> |
| | | import { ref } from "vue"; |
| | | import { onMounted, ref } from "vue"; |
| | | import { ElMessage } from "element-plus"; |
| | | import http from "../api/http"; |
| | | |
| | | const taskId = ref(""); |
| | | type OpLogRow = { |
| | | id: number; |
| | | opTime?: string; |
| | | operatorName?: string; |
| | | module?: string; |
| | | action?: string; |
| | | resourceType?: string; |
| | | resourceId?: string; |
| | | traceId?: string; |
| | | detailJson?: string; |
| | | }; |
| | | |
| | | async function enqueue() { |
| | | const loading = ref(false); |
| | | const rows = ref<OpLogRow[]>([]); |
| | | const page = ref(1); |
| | | const size = ref(10); |
| | | const total = ref(0); |
| | | |
| | | async function load() { |
| | | loading.value = true; |
| | | try { |
| | | const { data } = await http.post("/exports/enqueue", { |
| | | type: "appointment", |
| | | criteria: { status: "PENDING_APPROVAL" }, |
| | | const { data } = await http.get("/op-logs", { |
| | | params: { |
| | | page: page.value, |
| | | size: size.value, |
| | | sourceType: "MINI_EMPLOYEE", |
| | | }, |
| | | }); |
| | | taskId.value = data.result?.taskId || ""; |
| | | ElMessage.success("已入队"); |
| | | rows.value = data.result || []; |
| | | total.value = data.total || 0; |
| | | } catch (e: unknown) { |
| | | ElMessage.error(e instanceof Error ? e.message : "失败"); |
| | | ElMessage.error(e instanceof Error ? e.message : "加载失败"); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | } |
| | | |
| | | function handlePageChange(nextPage: number) { |
| | | page.value = nextPage; |
| | | load(); |
| | | } |
| | | |
| | | onMounted(load); |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .page-head { |
| | | margin-bottom: 16px; |
| | | } |
| | | |
| | | .page-title { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #1f2937; |
| | | } |
| | | |
| | | .page-subtitle { |
| | | margin-top: 4px; |
| | | font-size: 13px; |
| | | color: #6b7280; |
| | | } |
| | | |
| | | .pager { |
| | | display: flex; |
| | | justify-content: flex-end; |
| | | margin-top: 16px; |
| | | } |
| | | |
| | | .detail-text { |
| | | display: inline-block; |
| | | max-width: 100%; |
| | | color: #4b5563; |
| | | white-space: nowrap; |
| | | overflow: hidden; |
| | | text-overflow: ellipsis; |
| | | } |
| | | </style> |