目录
主要架构
前端项目结构
1. 核心实现代码
1.1 API服务封装 (src/api/log.ts)
1.2 TS类型定义 (src/types/api.ts)
1.3 Pinia状态管理 (src/stores/logStore.ts)
1.4 日志分析页面 (src/views/LogAnalysis.vue)
1.5 日志详情组件 (src/components/LogDetail.vue)
2. 项目配置
2.1 Vite配置 (vite.config.ts)
2.2 Element Plus按需导入 (src/main.ts)
3. 路由配置 (src/router/index.ts)
4. 环境变量配置 (.env.development)
5. 系统功能演示
5.1 主界面及历史记录页面
5.2 主要工作流
6. 关键集成点
前后端通信
状态管理
UI组件
类型安全
备注参考来源
主要架构:
前端: Vue 3 + TypeScript + Element Plus(本篇介绍)
其他:LangGraph、LangChain、Django、向量数据库、Ollama、Mysql/Postgres数据库等
环境搭建参考另一篇博客: Vue3 基础教程-CSDN博客
前端项目结构
frontend/
├── public/ # 静态资源
├── src/
│ ├── api/ # API接口
│ ├── assets/ # 静态资源
│ ├── components/ # 通用组件
│ ├── router/ # 路由配置
│ ├── stores/ # Pinia状态管理
│ ├── types/ # TS类型定义
│ ├── views/ # 页面组件
│ ├── App.vue # 根组件
│ └── main.ts # 入口文件
├── tsconfig.json # TypeScript配置
├── vite.config.ts # Vite配置
└── package.json
1. 核心实现代码
1.1 API服务封装 (src/api/log.ts)
import axios from 'axios'
import type { LogAnalysisRequest, LogAnalysisResponse } from '@/types/api'const apiClient = axios.create({baseURL: import.meta.env.VITE_API_BASE_URL,timeout: 10000
})export const logService = {async analyzeLog(logData: string): Promise<LogAnalysisResponse> {const response = await apiClient.post<LogAnalysisResponse>('/api/analyze', {log: logData})return response.data},async getRecentLogs(page = 1, pageSize = 10) {return apiClient.get('/api/logs', {params: { page, pageSize }})}
}
1.2 TS类型定义 (src/types/api.ts)
export interface LogAnalysisRequest {log: string
}export interface LogAnalysisResponse {log_id: numbersolution: {description: stringsteps: string[]confidence: number}
}export interface LogRecord {id: numberraw_message: stringcomponent: string | nullsource: string | nulltimestamp: stringsolution?: {description: stringsteps: string[]}
}
1.3 Pinia状态管理 (src/stores/logStore.ts)
import { defineStore } from 'pinia'
import { logService } from '@/api/log'
import type { LogAnalysisResponse, LogRecord } from '@/types/api'interface LogState {analysisResult: LogAnalysisResponse | nullhistory: LogRecord[]isLoading: boolean
}export const useLogStore = defineStore('log', {state: (): LogState => ({analysisResult: null,history: [],isLoading: false}),actions: {async analyzeLog(logData: string) {this.isLoading = truetry {this.analysisResult = await logService.analyzeLog(logData)await this.loadHistory()} finally {this.isLoading = false}},async loadHistory(page = 1) {const response = await logService.getRecentLogs(page)this.history = response.data.results}}
})
1.4 日志分析页面 (src/views/LogAnalysis.vue)
<template><div class="log-analysis-container"><el-card shadow="hover"><template #header><div class="card-header"><span>工业设备日志分析</span></div></template><el-form @submit.prevent="handleSubmit"><el-form-item label="日志内容"><el-inputv-model="logInput"type="textarea":rows="5"placeholder="粘贴设备日志内容..."clearable/></el-form-item><el-form-item><el-buttontype="primary":loading="store.isLoading"native-type="submit">分析日志</el-button></el-form-item></el-form><el-divider /><template v-if="store.analysisResult"><h3>分析结果</h3><el-alert:title="store.analysisResult.solution.description"type="success":closable="false"/><el-steps direction="vertical" :active="store.analysisResult.solution.steps.length"class="solution-steps"><el-stepv-for="(step, index) in store.analysisResult.solution.steps":key="index":title="`步骤 ${index + 1}`":description="step"/></el-steps><el-tag type="info">置信度: {{ (store.analysisResult.solution.confidence * 100).toFixed(1) }}%</el-tag></template></el-card><el-card shadow="hover" class="history-card"><template #header><div class="card-header"><span>历史记录</span><el-button @click="store.loadHistory()">刷新</el-button></div></template><el-table :data="store.history" stripe><el-table-column prop="timestamp" label="时间" width="180" /><el-table-column prop="component" label="部件" width="120" /><el-table-column prop="source" label="来源" width="150" /><el-table-column prop="raw_message" label="日志内容" show-overflow-tooltip /><el-table-column label="操作" width="120"><template #default="{ row }"><el-button size="small" @click="showDetail(row)">详情</el-button></template></el-table-column></el-table></el-card><el-dialog v-model="detailVisible" title="日志详情"><log-detail :log="currentLog" /></el-dialog></div>
</template><script setup lang="ts">
import { ref } from 'vue'
import { useLogStore } from '@/stores/logStore'
import LogDetail from '@/components/LogDetail.vue'const store = useLogStore()
const logInput = ref('')
const detailVisible = ref(false)
const currentLog = ref<any>(null)const handleSubmit = async () => {if (!logInput.value.trim()) returnawait store.analyzeLog(logInput.value)
}const showDetail = (log: any) => {currentLog.value = logdetailVisible.value = true
}// 初始化加载历史记录
store.loadHistory()
</script><style scoped>
.log-analysis-container {max-width: 1200px;margin: 0 auto;padding: 20px;
}.history-card {margin-top: 20px;
}.solution-steps {margin: 20px 0;padding-left: 20px;
}
</style>
1.5 日志详情组件 (src/components/LogDetail.vue)
<template><div v-if="log" class="log-detail"><el-descriptions :column="2" border><el-descriptions-item label="日志ID">{{ log.id }}</el-descriptions-item><el-descriptions-item label="记录时间">{{ formatDateTime(log.timestamp) }}</el-descriptions-item><el-descriptions-item label="部件"><el-tag :type="getComponentTagType(log.component)">{{ log.component || '未知' }}</el-tag></el-descriptions-item><el-descriptions-item label="来源">{{ log.source || '未知' }}</el-descriptions-item></el-descriptions><el-divider /><h4>原始日志内容</h4><el-inputtype="textarea":model-value="log.raw_message"readonly:rows="5"resize="none"class="log-content"/><template v-if="log.solution"><el-divider /><h4>解决方案</h4><el-alert:title="log.solution.description"type="success":closable="false"class="solution-alert"/><el-steps direction="vertical" :active="log.solution.steps.length" class="solution-steps"><el-stepv-for="(step, index) in log.solution.steps":key="index":title="`步骤 ${index + 1}`":description="step"/></el-steps></template></div>
</template><script setup lang="ts">
import { formatDateTime, getComponentTagType } from '@/utils/common'defineProps<{log: any
}>()
</script><style scoped>
.log-detail {padding: 10px;
}.log-content {margin-top: 10px;
}.solution-alert {margin: 15px 0;
}.solution-steps {margin-top: 20px;padding-left: 20px;
}
</style>
2. 项目配置
2.1 Vite配置 (vite.config.ts)
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import path from 'path'export default defineConfig({plugins: [vue()],resolve: {alias: {'@': path.resolve(__dirname, './src')}},server: {proxy: {'/api': {target: 'http://localhost:8000', // Django后端地址changeOrigin: true}}}
})
2.2 Element Plus按需导入 (src/main.ts)
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { createPinia } from 'pinia'import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'const app = createApp(App)app.use(createPinia())
app.use(router)
app.use(ElementPlus)app.mount('#app')
3. 路由配置 (src/router/index.ts)
import { createRouter, createWebHistory } from 'vue-router'
import LogAnalysis from '@/views/LogAnalysis.vue'const router = createRouter({history: createWebHistory(import.meta.env.BASE_URL),routes: [{path: '/',name: 'home',component: LogAnalysis},{path: '/history',name: 'history',component: () => import('@/views/LogHistory.vue')}]
})export default router
4. 环境变量配置 (.env.development)
VITE_API_BASE_URL=/
VITE_APP_TITLE=工业设备智能运维系统
5. 系统功能演示
5.1 主界面及历史记录页面
首页分析页面
历史记录页面
5.2 主要工作流
- 用户粘贴错误日志:
- xxx restoration fail,x.x.x.x not in "0.0.0.0" error.
- 点击"分析日志"按钮
- 系统显示:
- 解决方案:"重新...操作..."
- 详细步骤:4步操作指南("1. 关闭xxx" "2. 找到xxx" "3. 重新xxx" "4. 重启xxx")
- 置信度:92%
6. 关键集成点
-
前后端通信:
- 通过Axios封装API调用
- 使用Vite代理解决跨域
-
状态管理:
- Pinia集中管理分析结果和历史记录
- 类型安全的TypeScript接口
-
UI组件:
- Element Plus的Form、Table、Steps等组件
- 响应式布局适应不同屏幕
-
类型安全:
- 所有API接口都有TS类型定义
- 组件Props类型检查
备注参考来源:
万能的deepseek...