This commit is contained in:
雷欧(林平凡)
2025-07-13 14:52:41 +08:00
commit e7a2951c68
10 changed files with 2259 additions and 0 deletions

1774
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

24
package.json Normal file
View File

@@ -0,0 +1,24 @@
{
"name": "jarvis_vue",
"version": "1.0.0",
"main": "index.js",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"keywords": [],
"author": "",
"license": "ISC",
"description": "",
"dependencies": {
"axios": "^1.6.2",
"element-plus": "^2.4.10",
"vue": "^3.4.28",
"vue-router": "^4.2.5"
},
"devDependencies": {
"@vitejs/plugin-vue": "^5.0.4",
"vite": "^5.1.8"
}
}

101
src/App.vue Normal file
View File

@@ -0,0 +1,101 @@
<template>
<div id="app">
<el-container v-if="isLoggedIn">
<!-- 顶部导航 -->
<el-header>
<div class="header-container">
<div class="logo">订单管理系统</div>
<div class="user-info">
<el-dropdown trigger="click">
<span class="el-dropdown-link">
{{ username }} <i class="el-icon-arrow-down el-icon--right"></i>
</span>
<template #dropdown>
<el-dropdown-menu>
<el-dropdown-item @click="logout">退出登录</el-dropdown-item>
</el-dropdown-menu>
</template>
</el-dropdown>
</div>
</div>
</el-header>
<!-- 主内容区 -->
<el-main>
<router-view />
</el-main>
</el-container>
<!-- 未登录时显示登录页 -->
<router-view v-else />
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
username: ''
}
},
computed: {
isLoggedIn() {
return localStorage.getItem('token') !== null
}
},
created() {
const userInfo = localStorage.getItem('userInfo')
if (userInfo) {
try {
const user = JSON.parse(userInfo)
this.username = user.username || '用户'
} catch (error) {
console.error('解析用户信息失败', error)
this.username = '用户'
}
}
},
methods: {
logout() {
localStorage.removeItem('token')
localStorage.removeItem('userInfo')
this.$axios.defaults.headers.common['Authorization'] = null
this.$router.push('/login')
}
}
}
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
height: 100vh;
}
.el-header {
background-color: #409EFF;
color: #fff;
line-height: 60px;
}
.header-container {
display: flex;
justify-content: space-between;
align-items: center;
padding: 0 20px;
}
.logo {
font-size: 20px;
font-weight: bold;
}
.user-info {
cursor: pointer;
}
</style>

View File

@@ -0,0 +1,13 @@
<template>
<div>
<h1>首页</h1>
<p>欢迎来到首页</p>
<router-link to="/login">去登录页</router-link>
</div>
</template>
<script>
export default {
name: 'HomeView'
}
</script>

0
src/components/Login.vue Normal file
View File

View File

@@ -0,0 +1,212 @@
<template>
<div class="order-container">
<el-card class="box-card">
<template #header>
<div class="clearfix">
<span>订单列表</span>
<el-button style="float: right; padding: 3px 0" type="text" @click="fetchOrders">刷新</el-button>
</div>
</template>
<!-- 搜索表单 -->
<el-form :inline="true" :model="searchForm" class="demo-form-inline">
<el-form-item label="订单编号">
<el-input v-model="searchForm.orderNo" placeholder="请输入订单编号"></el-input>
</el-form-item>
<el-form-item label="客户名称">
<el-input v-model="searchForm.customerName" placeholder="请输入客户名称"></el-input>
</el-form-item>
<el-form-item label="订单状态">
<el-select v-model="searchForm.status" placeholder="请选择订单状态">
<el-option label="待支付" value="PENDING"></el-option>
<el-option label="已支付" value="PAID"></el-option>
<el-option label="已发货" value="SHIPPED"></el-option>
<el-option label="已完成" value="COMPLETED"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="fetchOrders">查询</el-button>
<el-button @click="resetForm">重置</el-button>
</el-form-item>
</el-form>
<!-- 订单表格 -->
<el-table
:data="orders"
stripe
style="width: 100%">
<el-table-column prop="orderNo" label="订单编号"></el-table-column>
<el-table-column prop="customerName" label="客户名称"></el-table-column>
<el-table-column prop="orderAmount" label="订单金额"></el-table-column>
<el-table-column prop="createTime" label="创建时间"></el-table-column>
<el-table-column prop="status" label="订单状态">
<template #default="scope">
<el-tag
:type="statusMap[scope.row.status].type">
{{ statusMap[scope.row.status].label }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="操作">
<template #default="scope">
<el-button size="small" type="text" @click="viewDetail(scope.row)">查看详情</el-button>
<el-button size="small" type="text" @click="editOrder(scope.row)">编辑</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页控件 -->
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="[10, 20, 30, 50]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</el-card>
<!-- 订单详情对话框 -->
<el-dialog :visible.sync="detailDialogVisible" title="订单详情">
<template #content>
<el-form :model="currentOrder">
<el-form-item label="订单编号" :label-width="formLabelWidth">
<span>{{ currentOrder.orderNo }}</span>
</el-form-item>
<el-form-item label="客户名称" :label-width="formLabelWidth">
<span>{{ currentOrder.customerName }}</span>
</el-form-item>
<el-form-item label="订单金额" :label-width="formLabelWidth">
<span>{{ currentOrder.orderAmount }}</span>
</el-form-item>
<el-form-item label="订单状态" :label-width="formLabelWidth">
<el-tag :type="statusMap[currentOrder.status].type">
{{ statusMap[currentOrder.status].label }}
</el-tag>
</el-form-item>
<el-form-item label="创建时间" :label-width="formLabelWidth">
<span>{{ currentOrder.createTime }}</span>
</el-form-item>
<el-form-item label="订单详情" :label-width="formLabelWidth">
<el-table :data="currentOrder.items" stripe style="width: 100%">
<el-table-column prop="productName" label="商品名称"></el-table-column>
<el-table-column prop="quantity" label="数量"></el-table-column>
<el-table-column prop="price" label="单价"></el-table-column>
<el-table-column prop="subtotal" label="小计"></el-table-column>
</el-table>
</el-form-item>
</el-form>
</template>
<template #footer>
<el-button @click="detailDialogVisible = false">关闭</el-button>
</template>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'OrderList',
data() {
return {
// 状态映射
statusMap: {
PENDING: { label: '待支付', type: 'warning' },
PAID: { label: '已支付', type: 'success' },
SHIPPED: { label: '已发货', type: 'info' },
COMPLETED: { label: '已完成', type: 'primary' }
},
// 搜索表单
searchForm: {
orderNo: '',
customerName: '',
status: ''
},
// 分页信息
currentPage: 1,
pageSize: 10,
total: 0,
orders: [],
// 详情对话框
detailDialogVisible: false,
currentOrder: {},
formLabelWidth: '120px'
}
},
mounted() {
this.fetchOrders()
},
methods: {
// 获取订单列表
fetchOrders() {
this.$axios.get('/orders', {
params: {
...this.searchForm,
page: this.currentPage,
size: this.pageSize
}
})
.then(response => {
this.orders = response.data.content
this.total = response.data.totalElements
})
.catch(error => {
this.$message.error('获取订单列表失败,请稍后重试')
console.error(error)
})
},
// 重置表单
resetForm() {
this.searchForm.orderNo = ''
this.searchForm.customerName = ''
this.searchForm.status = ''
this.fetchOrders()
},
// 分页相关方法
handleSizeChange(newSize) {
this.pageSize = newSize
this.fetchOrders()
},
handleCurrentChange(newPage) {
this.currentPage = newPage
this.fetchOrders()
},
// 查看订单详情
viewDetail(order) {
this.$axios.get(`/orders/${order.id}`)
.then(response => {
this.currentOrder = response.data
this.detailDialogVisible = true
})
.catch(error => {
this.$message.error('获取订单详情失败,请稍后重试')
console.error(error)
})
},
// 编辑订单
editOrder(order) {
this.$message.info(`编辑订单: ${order.orderNo}`)
// 实现编辑逻辑
}
}
}
</script>
<style scoped>
.order-container {
padding: 20px;
}
.box-card {
margin-bottom: 20px;
}
</style>

57
src/main.js Normal file
View File

@@ -0,0 +1,57 @@
import { createApp } from 'vue'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
import App from './App.vue'
import router from './router'
import axios from 'axios'
const app = createApp(App)
// 配置axios基础URL http://134.175.126.60:36666
axios.defaults.baseURL = 'http://134.175.126.60:36666/api'
// 请求拦截器 - 携带token
// axios.interceptors.request.use(
// config => {
// const token = localStorage.getItem('token')
// if (token) {
// config.headers['Authorization'] = `Bearer ${token}`
// }
// return config
// },
// error => {
// return Promise.reject(error)
// }
// )
// 响应拦截器 - 处理401未授权
// axios.interceptors.response.use(
// response => {
// return response
// },
// error => {
// if (error.response && error.response.status === 401) {
// localStorage.removeItem('token')
// localStorage.removeItem('userInfo')
// app.config.globalProperties.$message.error('登录已过期,请重新登录')
// router.push('/login')
// }
// return Promise.reject(error)
// }
// )
// 仅在开发环境启用调试模式
if (import.meta.env.DEV) {
app.config.performance = true // 启用性能追踪
app.config.devtools = true // 启用 DevTools 调试
}
// main.js
app.config.errorHandler = (err, instance, info) => {
console.error('全局错误捕获:', err, info)
// 可以添加错误上报逻辑
}
// 将axios挂载到全局
app.config.globalProperties.$axios = axios
app.use(ElementPlus)
app.use(router)
app.mount('#app')

14
src/public/index.html Normal file
View File

@@ -0,0 +1,14 @@
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>订单管理系统</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.js"></script>
</body>
</html>

41
src/router/index.js Normal file
View File

@@ -0,0 +1,41 @@
import { createRouter, createWebHistory } from 'vue-router'
import OrderList from '../components/OrderList.vue'
import Login from '../components/Login.vue'
const routes = [
// src/router/index.js
{
path: '/',
redirect: '/login'
},
{
path: '/',
name: 'OrderList',
component: OrderList,
meta: { requiresAuth: true }
},
{
path: '/login',
name: 'Login',
component: Login
}
]
const router = createRouter({
history: createWebHashHistory(),
routes
})
// 全局前置守卫 - 验证登录状态
router.beforeEach((to, from, next) => {
const requiresAuth = to.matched.some(record => record.meta.requiresAuth)
const isLoggedIn = localStorage.getItem('token') !== null
if (requiresAuth && !isLoggedIn) {
next('/login')
} else {
next()
}
})
export default router

23
vite.config.js Normal file
View File

@@ -0,0 +1,23 @@
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
export default defineConfig({
plugins: [vue()],
resolve: {
alias: {
'@': '/src'
}
},
server: {
host:'0.0.0.0',
port:9999,
// 解决开发环境跨域
proxy: {
'/api': {
target: 'http://134.175.126.206:6666',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, '')
}
}
}
})