parent
53af4689fc
commit
6c3bfe54f5
After Width: | Height: | Size: 4.2 KiB |
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||
<title><%= htmlWebpackPlugin.options.title %></title>
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,22 @@
|
||||
<template>
|
||||
<div id="app">
|
||||
<main-layout>
|
||||
<router-view />
|
||||
</main-layout>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import MainLayout from './components/layout/MainLayout.vue'
|
||||
|
||||
export default {
|
||||
name: 'App',
|
||||
components: {
|
||||
MainLayout
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/* 全局样式已经移至assets/css/global.css */
|
||||
</style>
|
@ -0,0 +1,71 @@
|
||||
import request from './index'
|
||||
import Mock from '../utils/mock'
|
||||
|
||||
// 是否使用模拟数据
|
||||
const useMock = process.env.NODE_ENV === 'development'
|
||||
|
||||
// 获取词频列表
|
||||
export function getTermFrequencies() {
|
||||
if (useMock) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve(Mock.getTermFrequencies())
|
||||
}, 800)
|
||||
})
|
||||
}
|
||||
|
||||
return request({
|
||||
url: '/analysis/terms',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
// 获取词的上下文
|
||||
export function getTermContexts(term) {
|
||||
if (useMock) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve(Mock.getTermContexts(term))
|
||||
}, 800)
|
||||
})
|
||||
}
|
||||
|
||||
return request({
|
||||
url: '/analysis/contexts',
|
||||
method: 'get',
|
||||
params: { term }
|
||||
})
|
||||
}
|
||||
|
||||
// 获取词的搭配词
|
||||
export function getTermCollocates(term) {
|
||||
if (useMock) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve(Mock.getTermCollocates(term))
|
||||
}, 800)
|
||||
})
|
||||
}
|
||||
|
||||
return request({
|
||||
url: '/analysis/collocates',
|
||||
method: 'get',
|
||||
params: { term }
|
||||
})
|
||||
}
|
||||
|
||||
// 获取文档段落数据
|
||||
export function getDocumentSegments() {
|
||||
if (useMock) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve(Mock.getDocumentSegments())
|
||||
}, 800)
|
||||
})
|
||||
}
|
||||
|
||||
return request({
|
||||
url: '/analysis/segments',
|
||||
method: 'get'
|
||||
})
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
import axios from 'axios'
|
||||
import store from '../store'
|
||||
|
||||
// 创建axios实例
|
||||
const service = axios.create({
|
||||
baseURL: process.env.VUE_APP_BASE_API || '/api',
|
||||
timeout: 10000
|
||||
})
|
||||
|
||||
// 请求拦截器
|
||||
service.interceptors.request.use(
|
||||
config => {
|
||||
// 在发送请求前显示加载状态
|
||||
store.dispatch('app/setLoading', true)
|
||||
return config
|
||||
},
|
||||
error => {
|
||||
store.dispatch('app/setLoading', false)
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
// 响应拦截器
|
||||
service.interceptors.response.use(
|
||||
response => {
|
||||
store.dispatch('app/setLoading', false)
|
||||
return response.data
|
||||
},
|
||||
error => {
|
||||
store.dispatch('app/setLoading', false)
|
||||
const errorMsg = error.response?.data?.message || error.message
|
||||
store.dispatch('app/setError', errorMsg)
|
||||
return Promise.reject(error)
|
||||
}
|
||||
)
|
||||
|
||||
export default service
|
@ -0,0 +1,96 @@
|
||||
import request from './index'
|
||||
import Mock from '../utils/mock'
|
||||
|
||||
// 是否使用模拟数据
|
||||
const useMock = process.env.NODE_ENV === 'development'
|
||||
|
||||
// 上传文件API
|
||||
export function uploadFile(file) {
|
||||
if (useMock) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve(Mock.getUploadData())
|
||||
}, 1000)
|
||||
})
|
||||
}
|
||||
|
||||
const formData = new FormData()
|
||||
formData.append('file', file)
|
||||
|
||||
return request({
|
||||
url: '/upload',
|
||||
method: 'post',
|
||||
data: formData,
|
||||
headers: {
|
||||
'Content-Type': 'multipart/form-data'
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 预处理数据API
|
||||
export function preprocessData(data) {
|
||||
if (useMock) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve(Mock.getPreprocessData())
|
||||
}, 1500)
|
||||
})
|
||||
}
|
||||
|
||||
return request({
|
||||
url: '/preprocess',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 合并格式API
|
||||
export function mergeFormat(data) {
|
||||
if (useMock) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve(Mock.getMergeData())
|
||||
}, 1500)
|
||||
})
|
||||
}
|
||||
|
||||
return request({
|
||||
url: '/merge',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 单词纠错API
|
||||
export function correctWords(data) {
|
||||
if (useMock) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve(Mock.getCorrectionData())
|
||||
}, 1500)
|
||||
})
|
||||
}
|
||||
|
||||
return request({
|
||||
url: '/correct',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
// 大模型分析API
|
||||
export function analyzeText(data) {
|
||||
if (useMock) {
|
||||
return new Promise(resolve => {
|
||||
setTimeout(() => {
|
||||
resolve(Mock.getAnalysisData())
|
||||
}, 2000)
|
||||
})
|
||||
}
|
||||
|
||||
return request({
|
||||
url: '/analyze',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
@ -0,0 +1,34 @@
|
||||
/* 全局样式 */
|
||||
* {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html, body, #app {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
font-family: "Helvetica Neue", Helvetica, "PingFang SC", "Hiragino Sans GB", "Microsoft YaHei", Arial, sans-serif;
|
||||
}
|
||||
|
||||
body {
|
||||
background-image: url('../images/background.png');
|
||||
background-size: cover;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
background-attachment: fixed;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
/* 过渡动画 */
|
||||
.fade-enter-active, .fade-leave-active {
|
||||
transition: opacity 0.3s;
|
||||
}
|
||||
.fade-enter, .fade-leave-to {
|
||||
opacity: 0;
|
||||
}
|
After Width: | Height: | Size: 1.3 MiB |
After Width: | Height: | Size: 6.7 KiB |
@ -0,0 +1,58 @@
|
||||
<template>
|
||||
<div class="hello">
|
||||
<h1>{{ msg }}</h1>
|
||||
<p>
|
||||
For a guide and recipes on how to configure / customize this project,<br>
|
||||
check out the
|
||||
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
|
||||
</p>
|
||||
<h3>Installed CLI Plugins</h3>
|
||||
<ul>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
|
||||
</ul>
|
||||
<h3>Essential Links</h3>
|
||||
<ul>
|
||||
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
|
||||
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
|
||||
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
|
||||
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
|
||||
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
|
||||
</ul>
|
||||
<h3>Ecosystem</h3>
|
||||
<ul>
|
||||
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
|
||||
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
|
||||
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
|
||||
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
|
||||
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'HelloWorld',
|
||||
props: {
|
||||
msg: String
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
h3 {
|
||||
margin: 40px 0 0;
|
||||
}
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
}
|
||||
li {
|
||||
display: inline-block;
|
||||
margin: 0 10px;
|
||||
}
|
||||
a {
|
||||
color: #42b983;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
title="错误提示"
|
||||
:visible.sync="dialogVisible"
|
||||
width="30%"
|
||||
@close="handleClose"
|
||||
>
|
||||
<div class="error-content">
|
||||
<i class="el-icon-error error-icon"></i>
|
||||
<p class="error-text">{{ error }}</p>
|
||||
</div>
|
||||
<span slot="footer" class="dialog-footer">
|
||||
<el-button @click="handleClose">关闭</el-button>
|
||||
</span>
|
||||
</el-dialog>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapActions } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'ErrorMessage',
|
||||
|
||||
computed: {
|
||||
...mapState('app', ['error']),
|
||||
dialogVisible() {
|
||||
return !!this.error
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
...mapActions('app', ['clearError']),
|
||||
|
||||
handleClose() {
|
||||
this.clearError()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.error-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 10px 0;
|
||||
}
|
||||
|
||||
.error-icon {
|
||||
font-size: 48px;
|
||||
color: #f56c6c;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.error-text {
|
||||
font-size: 16px;
|
||||
color: #606266;
|
||||
text-align: center;
|
||||
word-break: break-word;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,63 @@
|
||||
<template>
|
||||
<div class="app-header">
|
||||
<div class="header-container">
|
||||
<div class="logo">
|
||||
<router-link to="/" style="text-decoration: none;">
|
||||
<h1>航班数据处理及分析系统</h1>
|
||||
</router-link>
|
||||
</div>
|
||||
<div class="nav-menu">
|
||||
<router-link to="/process" active-class="active">
|
||||
<el-button type="text">处理流程</el-button>
|
||||
</router-link>
|
||||
<router-link to="/analysis" active-class="active">
|
||||
<el-button type="text">分析结果</el-button>
|
||||
</router-link>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'AppHeader'
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.app-header {
|
||||
background-color: #fff;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 1000;
|
||||
}
|
||||
|
||||
.header-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
height: 60px;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.logo h1 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.nav-menu {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
.active button {
|
||||
color: #1890ff;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,42 @@
|
||||
<template>
|
||||
<div class="main-layout">
|
||||
<app-header />
|
||||
<div class="main-content">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<el-backtop :right="20" :bottom="20"></el-backtop>
|
||||
<global-loading />
|
||||
<error-message />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import AppHeader from './Header.vue'
|
||||
import GlobalLoading from '../base/GlobalLoading.vue'
|
||||
import ErrorMessage from '../base/ErrorMessage.vue'
|
||||
|
||||
export default {
|
||||
name: 'MainLayout',
|
||||
components: {
|
||||
AppHeader,
|
||||
GlobalLoading,
|
||||
ErrorMessage
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.main-layout {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.main-content {
|
||||
flex: 1;
|
||||
margin-top: 60px;
|
||||
padding-top: 20px;
|
||||
background-color: #f0f2f5;
|
||||
min-height: calc(100vh - 60px);
|
||||
}
|
||||
</style>
|
@ -0,0 +1,16 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import ElementUI from 'element-ui'
|
||||
import 'element-ui/lib/theme-chalk/index.css'
|
||||
import './assets/css/global.css'
|
||||
|
||||
Vue.config.productionTip = false
|
||||
Vue.use(ElementUI)
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
store,
|
||||
render: h => h(App),
|
||||
}).$mount('#app')
|
@ -0,0 +1,33 @@
|
||||
import Vue from 'vue'
|
||||
import VueRouter from 'vue-router'
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
redirect: '/process'
|
||||
},
|
||||
{
|
||||
path: '/process',
|
||||
name: 'ProcessView',
|
||||
component: () => import('../views/Process.vue')
|
||||
},
|
||||
{
|
||||
path: '/analysis',
|
||||
name: 'AnalysisView',
|
||||
component: () => import('../views/Analysis.vue')
|
||||
},
|
||||
{
|
||||
path: '*',
|
||||
redirect: '/process'
|
||||
}
|
||||
]
|
||||
|
||||
const router = new VueRouter({
|
||||
mode: 'history',
|
||||
base: process.env.BASE_URL,
|
||||
routes
|
||||
})
|
||||
|
||||
export default router
|
@ -0,0 +1,15 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
import app from './modules/app'
|
||||
import process from './modules/process'
|
||||
import analysis from './modules/analysis'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
export default new Vuex.Store({
|
||||
modules: {
|
||||
app,
|
||||
process,
|
||||
analysis
|
||||
}
|
||||
})
|
@ -0,0 +1,39 @@
|
||||
// 全局应用状态模块
|
||||
const state = {
|
||||
loading: false,
|
||||
error: null
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
SET_LOADING(state, loading) {
|
||||
state.loading = loading
|
||||
},
|
||||
SET_ERROR(state, error) {
|
||||
state.error = error
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
setLoading({ commit }, loading) {
|
||||
commit('SET_LOADING', loading)
|
||||
},
|
||||
setError({ commit }, error) {
|
||||
commit('SET_ERROR', error)
|
||||
},
|
||||
clearError({ commit }) {
|
||||
commit('SET_ERROR', null)
|
||||
}
|
||||
}
|
||||
|
||||
const getters = {
|
||||
isLoading: state => state.loading,
|
||||
error: state => state.error
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions,
|
||||
getters
|
||||
}
|
@ -0,0 +1,107 @@
|
||||
// 处理流程相关状态模块
|
||||
const state = {
|
||||
currentStep: 1,
|
||||
uploadedFiles: [],
|
||||
fileData: null,
|
||||
preprocessResults: null,
|
||||
mergeResults: null,
|
||||
correctionResults: null,
|
||||
analysisResults: null,
|
||||
stepStatus: {
|
||||
upload: 'pending',
|
||||
preprocess: 'pending',
|
||||
merge: 'pending',
|
||||
correction: 'pending',
|
||||
analysis: 'pending'
|
||||
}
|
||||
}
|
||||
|
||||
const mutations = {
|
||||
SET_CURRENT_STEP(state, step) {
|
||||
state.currentStep = step
|
||||
},
|
||||
SET_UPLOADED_FILES(state, files) {
|
||||
state.uploadedFiles = files
|
||||
},
|
||||
SET_FILE_DATA(state, data) {
|
||||
state.fileData = data
|
||||
},
|
||||
SET_PREPROCESS_RESULTS(state, results) {
|
||||
state.preprocessResults = results
|
||||
},
|
||||
SET_MERGE_RESULTS(state, results) {
|
||||
state.mergeResults = results
|
||||
},
|
||||
SET_CORRECTION_RESULTS(state, results) {
|
||||
state.correctionResults = results
|
||||
},
|
||||
SET_ANALYSIS_RESULTS(state, results) {
|
||||
state.analysisResults = results
|
||||
},
|
||||
UPDATE_STEP_STATUS(state, { step, status }) {
|
||||
state.stepStatus[step] = status
|
||||
}
|
||||
}
|
||||
|
||||
const actions = {
|
||||
setCurrentStep({ commit }, step) {
|
||||
commit('SET_CURRENT_STEP', step)
|
||||
},
|
||||
uploadFiles({ commit }, files) {
|
||||
commit('SET_UPLOADED_FILES', files)
|
||||
commit('UPDATE_STEP_STATUS', { step: 'upload', status: 'completed' })
|
||||
},
|
||||
setFileData({ commit }, data) {
|
||||
commit('SET_FILE_DATA', data)
|
||||
},
|
||||
processPreprocess({ commit }, results) {
|
||||
commit('SET_PREPROCESS_RESULTS', results)
|
||||
commit('UPDATE_STEP_STATUS', { step: 'preprocess', status: 'completed' })
|
||||
},
|
||||
processMerge({ commit }, results) {
|
||||
commit('SET_MERGE_RESULTS', results)
|
||||
commit('UPDATE_STEP_STATUS', { step: 'merge', status: 'completed' })
|
||||
},
|
||||
processCorrection({ commit }, results) {
|
||||
commit('SET_CORRECTION_RESULTS', results)
|
||||
commit('UPDATE_STEP_STATUS', { step: 'correction', status: 'completed' })
|
||||
},
|
||||
processAnalysis({ commit }, results) {
|
||||
commit('SET_ANALYSIS_RESULTS', results)
|
||||
commit('UPDATE_STEP_STATUS', { step: 'analysis', status: 'completed' })
|
||||
},
|
||||
resetProcess({ commit }) {
|
||||
commit('SET_CURRENT_STEP', 1)
|
||||
commit('SET_UPLOADED_FILES', [])
|
||||
commit('SET_FILE_DATA', null)
|
||||
commit('SET_PREPROCESS_RESULTS', null)
|
||||
commit('SET_MERGE_RESULTS', null)
|
||||
commit('SET_CORRECTION_RESULTS', null)
|
||||
commit('SET_ANALYSIS_RESULTS', null)
|
||||
|
||||
const steps = ['upload', 'preprocess', 'merge', 'correction', 'analysis']
|
||||
steps.forEach(step => {
|
||||
commit('UPDATE_STEP_STATUS', { step, status: 'pending' })
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const getters = {
|
||||
currentStep: state => state.currentStep,
|
||||
uploadedFiles: state => state.uploadedFiles,
|
||||
fileData: state => state.fileData,
|
||||
preprocessResults: state => state.preprocessResults,
|
||||
mergeResults: state => state.mergeResults,
|
||||
correctionResults: state => state.correctionResults,
|
||||
analysisResults: state => state.analysisResults,
|
||||
stepStatus: state => state.stepStatus,
|
||||
isStepCompleted: state => step => state.stepStatus[step] === 'completed'
|
||||
}
|
||||
|
||||
export default {
|
||||
namespaced: true,
|
||||
state,
|
||||
mutations,
|
||||
actions,
|
||||
getters
|
||||
}
|
@ -0,0 +1,176 @@
|
||||
// 模拟数据生成工具
|
||||
|
||||
// 文件上传模拟数据
|
||||
export function getUploadData() {
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
fileName: 'sample.xlsx',
|
||||
rows: 150,
|
||||
columns: 5,
|
||||
preview: [
|
||||
{ id: 1, content: '示例内容1', date: '2023-05-10', source: '来源A', type: '类型1' },
|
||||
{ id: 2, content: '示例内容2', date: '2023-05-11', source: '来源B', type: '类型2' },
|
||||
{ id: 3, content: '示例内容3', date: '2023-05-12', source: '来源A', type: '类型1' }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 预处理模拟数据
|
||||
export function getPreprocessData() {
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
processed: 150,
|
||||
invalidRows: 2,
|
||||
normalizedFields: ['date', 'content'],
|
||||
preview: [
|
||||
{ id: 1, content: '规范化后的内容1', date: '2023-05-10', source: '来源A', type: '类型1' },
|
||||
{ id: 2, content: '规范化后的内容2', date: '2023-05-11', source: '来源B', type: '类型2' },
|
||||
{ id: 3, content: '规范化后的内容3', date: '2023-05-12', source: '来源A', type: '类型1' }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 合并格式模拟数据
|
||||
export function getMergeData() {
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
merged: 148,
|
||||
format: 'standardized',
|
||||
preview: [
|
||||
{ id: 1, content: '合并格式后的内容1', date: '2023-05-10', source: '来源A', type: '类型1' },
|
||||
{ id: 2, content: '合并格式后的内容2', date: '2023-05-11', source: '来源B', type: '类型2' },
|
||||
{ id: 3, content: '合并格式后的内容3', date: '2023-05-12', source: '来源A', type: '类型1' }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 纠错模拟数据
|
||||
export function getCorrectionData() {
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
corrected: 148,
|
||||
corrections: 25,
|
||||
preview: [
|
||||
{ id: 1, content: '纠错后的内容1', date: '2023-05-10', source: '来源A', type: '类型1' },
|
||||
{ id: 2, content: '纠错后的内容2', date: '2023-05-11', source: '来源B', type: '类型2' },
|
||||
{ id: 3, content: '纠错后的内容3', date: '2023-05-12', source: '来源A', type: '类型1' }
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 分析模拟数据
|
||||
export function getAnalysisData() {
|
||||
return {
|
||||
success: true,
|
||||
data: {
|
||||
termFrequencies: getTermFrequencies().data,
|
||||
documentSegments: getDocumentSegments().data,
|
||||
summary: {
|
||||
totalWords: 12568,
|
||||
uniqueWords: 3452,
|
||||
averageSentenceLength: 15.7,
|
||||
documentCount: 148
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 词频列表模拟数据
|
||||
export function getTermFrequencies() {
|
||||
return {
|
||||
success: true,
|
||||
data: [
|
||||
{ term: '数据', frequency: 189, rank: 1 },
|
||||
{ term: '分析', frequency: 156, rank: 2 },
|
||||
{ term: '模型', frequency: 143, rank: 3 },
|
||||
{ term: '学习', frequency: 122, rank: 4 },
|
||||
{ term: '算法', frequency: 118, rank: 5 },
|
||||
{ term: '机器', frequency: 105, rank: 6 },
|
||||
{ term: '深度', frequency: 92, rank: 7 },
|
||||
{ term: '训练', frequency: 87, rank: 8 },
|
||||
{ term: '人工智能', frequency: 76, rank: 9 },
|
||||
{ term: '神经网络', frequency: 65, rank: 10 },
|
||||
{ term: '预测', frequency: 58, rank: 11 },
|
||||
{ term: '精度', frequency: 51, rank: 12 },
|
||||
{ term: '特征', frequency: 45, rank: 13 },
|
||||
{ term: '计算', frequency: 40, rank: 14 },
|
||||
{ term: '优化', frequency: 35, rank: 15 }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// 上下文模拟数据
|
||||
export function getTermContexts(term) {
|
||||
return {
|
||||
success: true,
|
||||
data: [
|
||||
{ left: '使用各种', keyword: term, right: '方法处理大规模数据集' },
|
||||
{ left: '通过深度学习改进', keyword: term, right: '结果的准确性和可靠性' },
|
||||
{ left: '传统的统计学习方法在某些', keyword: term, right: '任务中仍然表现良好' },
|
||||
{ left: '研究表明,增加训练数据可以提高', keyword: term, right: '模型的泛化能力' },
|
||||
{ left: '在数据处理过程中,', keyword: term, right: '步骤起到了关键作用' }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// 搭配词模拟数据
|
||||
export function getTermCollocates(term) {
|
||||
// 根据不同的term返回不同的搭配词
|
||||
const baseData = [
|
||||
{ word: '深度', frequency: 23, score: 0.85 },
|
||||
{ word: '机器', frequency: 19, score: 0.82 },
|
||||
{ word: '数据', frequency: 18, score: 0.78 },
|
||||
{ word: '模型', frequency: 17, score: 0.75 },
|
||||
{ word: '算法', frequency: 15, score: 0.72 },
|
||||
{ word: '训练', frequency: 12, score: 0.68 },
|
||||
{ word: '优化', frequency: 10, score: 0.65 },
|
||||
{ word: '预测', frequency: 9, score: 0.62 },
|
||||
{ word: '特征', frequency: 8, score: 0.58 },
|
||||
{ word: '精度', frequency: 7, score: 0.55 }
|
||||
]
|
||||
|
||||
// 在数据中添加关联到term的信息
|
||||
const result = baseData.map(item => ({
|
||||
...item,
|
||||
relatedTo: term // 使用term参数
|
||||
}))
|
||||
|
||||
return {
|
||||
success: true,
|
||||
data: result
|
||||
}
|
||||
}
|
||||
|
||||
// 文档段落模拟数据
|
||||
export function getDocumentSegments() {
|
||||
return {
|
||||
success: true,
|
||||
data: [
|
||||
{ id: 1, name: '段落1', wordCount: 850 },
|
||||
{ id: 2, name: '段落2', wordCount: 920 },
|
||||
{ id: 3, name: '段落3', wordCount: 780 },
|
||||
{ id: 4, name: '段落4', wordCount: 860 },
|
||||
{ id: 5, name: '段落5', wordCount: 910 }
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
export default {
|
||||
getUploadData,
|
||||
getPreprocessData,
|
||||
getMergeData,
|
||||
getCorrectionData,
|
||||
getAnalysisData,
|
||||
getTermFrequencies,
|
||||
getTermContexts,
|
||||
getTermCollocates,
|
||||
getDocumentSegments
|
||||
}
|
@ -0,0 +1,197 @@
|
||||
<template>
|
||||
<div class="analysis-container">
|
||||
<h1 class="analysis-title">文本分析结果</h1>
|
||||
|
||||
<div class="analysis-panels">
|
||||
<div class="grid-container">
|
||||
<!-- 左侧词频面板 -->
|
||||
<div class="panel terms-panel">
|
||||
<div class="panel-header">
|
||||
<h3>词频列表</h3>
|
||||
</div>
|
||||
<div class="panel-content">
|
||||
<p>词频列表组件将在这里显示</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 中间词云面板 -->
|
||||
<div class="panel wordcloud-panel">
|
||||
<div class="panel-header">
|
||||
<h3>词云图</h3>
|
||||
</div>
|
||||
<div class="panel-content">
|
||||
<p>词云组件将在这里显示</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 右上角趋势图面板 -->
|
||||
<div class="panel trends-panel">
|
||||
<div class="panel-header">
|
||||
<h3>趋势分析</h3>
|
||||
</div>
|
||||
<div class="panel-content">
|
||||
<p>趋势图组件将在这里显示</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 底部详情面板 -->
|
||||
<div class="panel details-panel">
|
||||
<div class="panel-header">
|
||||
<h3>详细信息</h3>
|
||||
</div>
|
||||
<div class="panel-content">
|
||||
<el-tabs type="border-card">
|
||||
<el-tab-pane label="摘要">
|
||||
<p>摘要内容将在这里显示</p>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="上下文">
|
||||
<p>上下文组件将在这里显示</p>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="搭配词">
|
||||
<p>搭配词组件将在这里显示</p>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="文档">
|
||||
<p>文档视图将在这里显示</p>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="analysis-actions">
|
||||
<el-button
|
||||
icon="el-icon-back"
|
||||
@click="returnToProcess"
|
||||
>返回处理页面</el-button>
|
||||
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-download"
|
||||
@click="exportResults"
|
||||
>导出结果</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapActions } from 'vuex'
|
||||
|
||||
export default {
|
||||
name: 'AnalysisView',
|
||||
|
||||
computed: {
|
||||
...mapState('analysis', ['termFrequencies', 'selectedTerms'])
|
||||
},
|
||||
|
||||
methods: {
|
||||
...mapActions('analysis', [
|
||||
'setTermFrequencies',
|
||||
'setSelectedTerms'
|
||||
]),
|
||||
|
||||
returnToProcess() {
|
||||
this.$router.push('/process')
|
||||
},
|
||||
|
||||
exportResults() {
|
||||
// 导出功能将在后续实现
|
||||
this.$message({
|
||||
message: '结果导出功能将在后续版本中实现',
|
||||
type: 'info'
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
created() {
|
||||
// 初始化时从store获取数据或从API加载
|
||||
// 在实际实现中将调用API方法
|
||||
if (this.termFrequencies.length === 0) {
|
||||
// 模拟数据获取
|
||||
setTimeout(() => {
|
||||
this.setTermFrequencies([
|
||||
{ term: '示例词1', frequency: 100 },
|
||||
{ term: '示例词2', frequency: 80 },
|
||||
{ term: '示例词3', frequency: 60 }
|
||||
])
|
||||
}, 500)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.analysis-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.analysis-title {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.grid-container {
|
||||
display: grid;
|
||||
grid-template-columns: 250px 1fr 300px;
|
||||
grid-template-rows: 300px 1fr;
|
||||
grid-gap: 15px;
|
||||
height: calc(100vh - 200px);
|
||||
min-height: 600px;
|
||||
}
|
||||
|
||||
.panel {
|
||||
background-color: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 12px 0 rgba(0,0,0,.05);
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.panel-header {
|
||||
padding: 10px 15px;
|
||||
border-bottom: 1px solid #e6e6e6;
|
||||
background-color: #f9f9f9;
|
||||
}
|
||||
|
||||
.panel-header h3 {
|
||||
margin: 0;
|
||||
font-size: 16px;
|
||||
color: #606266;
|
||||
}
|
||||
|
||||
.panel-content {
|
||||
padding: 15px;
|
||||
flex: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.terms-panel {
|
||||
grid-column: 1;
|
||||
grid-row: 1 / span 2;
|
||||
}
|
||||
|
||||
.wordcloud-panel {
|
||||
grid-column: 2;
|
||||
grid-row: 1 / span 2;
|
||||
}
|
||||
|
||||
.trends-panel {
|
||||
grid-column: 3;
|
||||
grid-row: 1;
|
||||
}
|
||||
|
||||
.details-panel {
|
||||
grid-column: 3;
|
||||
grid-row: 2;
|
||||
}
|
||||
|
||||
.analysis-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-top: 20px;
|
||||
padding: 10px 0;
|
||||
}
|
||||
</style>
|
@ -0,0 +1,130 @@
|
||||
<template>
|
||||
<div class="process-container">
|
||||
<h1 class="process-title">文件处理流程</h1>
|
||||
<div class="process-steps">
|
||||
<el-steps :active="currentStep" finish-status="success" align-center>
|
||||
<el-step title="文件上传" description="上传Excel或CSV文件"></el-step>
|
||||
<el-step title="数据预处理" description="规范化文本格式"></el-step>
|
||||
<el-step title="格式合并" description="统一数据格式"></el-step>
|
||||
<el-step title="单词纠错" description="纠正错误拼写"></el-step>
|
||||
<el-step title="大模型分析" description="使用AI分析内容"></el-step>
|
||||
</el-steps>
|
||||
</div>
|
||||
|
||||
<div class="step-content">
|
||||
<!-- 步骤内容区域 -->
|
||||
<div v-if="currentStep === 1">
|
||||
<file-upload />
|
||||
</div>
|
||||
<div v-else-if="currentStep === 2">
|
||||
<pre-process />
|
||||
</div>
|
||||
<div v-else-if="currentStep === 3">
|
||||
<merge-format />
|
||||
</div>
|
||||
<div v-else-if="currentStep === 4">
|
||||
<word-correction />
|
||||
</div>
|
||||
<div v-else-if="currentStep === 5">
|
||||
<model-analysis />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState, mapActions, mapGetters } from 'vuex'
|
||||
import FileUpload from '../components/process/FileUpload.vue'
|
||||
import PreProcess from '../components/process/PreProcess.vue'
|
||||
import MergeFormat from '../components/process/MergeFormat.vue'
|
||||
import WordCorrection from '../components/process/WordCorrection.vue'
|
||||
import ModelAnalysis from '../components/process/ModelAnalysis.vue'
|
||||
|
||||
export default {
|
||||
name: 'ProcessView',
|
||||
|
||||
components: {
|
||||
FileUpload,
|
||||
PreProcess,
|
||||
MergeFormat,
|
||||
WordCorrection,
|
||||
ModelAnalysis
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapState('process', ['currentStep', 'uploadedFiles']),
|
||||
...mapGetters('process', ['isStepCompleted']),
|
||||
|
||||
canProceedToNextStep() {
|
||||
// 根据当前步骤判断是否可以进行下一步
|
||||
switch (this.currentStep) {
|
||||
case 1:
|
||||
return this.isStepCompleted('upload')
|
||||
case 2:
|
||||
return this.isStepCompleted('preprocess')
|
||||
case 3:
|
||||
return this.isStepCompleted('merge')
|
||||
case 4:
|
||||
return this.isStepCompleted('correction')
|
||||
case 5:
|
||||
return this.isStepCompleted('analysis')
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
...mapActions('process', ['setCurrentStep']),
|
||||
|
||||
prevStep() {
|
||||
if (this.currentStep > 1) {
|
||||
this.setCurrentStep(this.currentStep - 1)
|
||||
}
|
||||
},
|
||||
|
||||
nextStep() {
|
||||
if (this.currentStep < 5 && this.canProceedToNextStep) {
|
||||
this.setCurrentStep(this.currentStep + 1)
|
||||
}
|
||||
},
|
||||
|
||||
completeProcess() {
|
||||
// 完成处理后跳转到分析页面
|
||||
this.$router.push('/analysis')
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.process-container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.process-title {
|
||||
text-align: center;
|
||||
margin-bottom: 30px;
|
||||
color: #1890ff;
|
||||
}
|
||||
|
||||
.process-steps {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
|
||||
.step-content {
|
||||
background-color: #f5f7fa;
|
||||
border-radius: 4px;
|
||||
padding: 30px;
|
||||
min-height: 300px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.process-actions {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 10px 0;
|
||||
}
|
||||
</style>
|
Loading…
Reference in new issue