1
This commit is contained in:
1774
package-lock.json
generated
Normal file
1774
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
24
package.json
Normal file
24
package.json
Normal 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
101
src/App.vue
Normal 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>
|
||||
13
src/components/HomeView.vue
Normal file
13
src/components/HomeView.vue
Normal 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
0
src/components/Login.vue
Normal file
212
src/components/OrderList.vue
Normal file
212
src/components/OrderList.vue
Normal 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
57
src/main.js
Normal 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
14
src/public/index.html
Normal 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
41
src/router/index.js
Normal 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
23
vite.config.js
Normal 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/, '')
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user