目錄
主要架構
前端項目結構
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...