下载 vue-element-admin,并启动官方:https://github.com/PanJiaChen/vue-element-admin框架里的组件样式可以从 element 上找 element:http://element-cn.eleme.io/#/zh-CN/component/table可以直接下载压缩包解压,也可以通过 git 下载 # 克隆项目
git clone https://github.com/PanJiaChen/vue-element-admin.git
#设置淘宝仓库
npm install --registry=https://registry.npm.taobao.org
# 安装依赖
npm install
# 启动服务
npm run dev
├── build // 构建相关
├── config // 配置相关
├── src // 源代码
│ ├── api // 所有请求
│ ├── assets // 主题 字体等静态资源
│ ├── components // 全局公用组件
│ ├── directive // 全局指令
│ ├── filtres // 全局 filter
│ ├── icons // 项目所有 svg icons
│ ├── lang // 国际化 language
│ ├── mock // 项目mock 模拟数据
│ ├── router // 路由
│ ├── store // 全局 store管理
│ ├── styles // 全局样式
│ ├── utils // 全局公用方法
│ ├── vendor // 公用vendor
│ ├── views // view
│ ├── App.vue // 入口页面
│ ├── main.js // 入口 加载组件 初始化等
│ └── permission.js // 权限管理
├── static // 第三方不打包资源
│ └── Tinymce // 富文本
├── .babelrc // babel-loader 配置
├── eslintrc.js // eslint 配置项
├── .gitignore // git 忽略项
├── favicon.ico // favicon图标
├── index.html // html模板
└── package.json // package.json
dev.env.js先来看下 config 文件夹下的 dev.env.js这个文件夹里的 BASE_API 后台接口的就是公共路径,调后台的时候要记得改,这是本地的,剩下的 prod 和 sit 分别是正式环境打包和 测试环境打包的/src/router/index.js先来看下目录详细的解释在这个目录文件的上面有,每个属性什么意思,可以在上面看mock 假数据页面mock 主要是帮助前后分离的项目为前端提供数据,这样才好测试先来画个页面,一个分页列表吧,路径 /src/service/dataLog.vue 用来显示一些信息我在 element 组件里找了一个列表功能和分页功能/src/service/dataLog.vuedataLog.vue 的 template 部分<template>
<div class="app-container">
<!-- 查询框 双向绑定 keyword-->
<el-input
v-model="keyword"
placeholder="请输入关键字"
clearable
style="width:500px" />
<!-- 搜索按钮 绑定点击事件 -->
<el-button type="primary" icon="el-icon-search" @click="getDataLog()">搜索</el-button>
<!-- data就是绑定数据用的 -->
<el-table
:data="dataLog"
style="width: 100%">
<el-table-column type="expand">
<template slot-scope="props">
<el-form label-position="left" inline class="demo-table-expand">
<el-form-item label="错误信息">
<span>{{ props.row.log }}</span>
</el-form-item>
</el-form>
</template>
</el-table-column>
<el-table-column
label="服务单"
prop="data"/>
<el-table-column
label="时间"
prop="time"/>
</el-table>
<!-- 分页 -->
<pagination
v-show="total>0"
:total="total"
:page.sync="listQuery.page"
:limit.sync="listQuery.limit"
@pagination="getDataLog" />
<!-- total总条数
listQuery.page 当前页
listQuery.limit 每页几条
getDataLog 后买点击分页时候要回调的函数 -->
</div>
</template>
注意 template 下只能有一个节点,两个就报错了,可以试下,所有我放在一个统一的 div 里至于这些值为啥这样写,我只能说照着人家给的模板改就好,人家写啥你写啥,样式啥的人家上面都有样式部分就不贴了,最后会把完整的代码贴出来,来看下 js 的部分这里解释下分页,分页除了初始化给了第 1 页和每页 10 条后,之后每次点击页码,数据都会双向绑定到值上,所有在调后台函数的时候,直接取 page 和 limit 值就行了,不想要再去想我怎么去拿 div 上面的数字<script>
// 这里要调用我使用的 api
// 括号里的是要使用的函数接口,多个的话逗号隔开
import { getDataLog } from '@/api/service/dataLog'
// 引入分页组件
import Pagination from '@/components/Pagination'
export default {
// 这里需要把分页组件注册进来
components: { Pagination },
data() {
return {
// 搜索关键字
keyword: '',
// 数据条数
total: 0,
// 分页参数
listQuery: {
page: 1,
limit: 10
},
// 列表数据
dataLog: []
}
},
// 这个是生命周期函数,这个时候是 data 和 methods 都初始化好了,具体看基础知识
created() {
this.getDataLog()
},
methods: {
// 函数部分
getDataLog() {
// 参数
this.listQuery = {
page: this.listQuery.page,
limit: this.listQuery.limit,
object: this.keyword
}
// 调用上面引入的 api 里的 getDataLog
// 不引入就报函数未定义了,刚开始一个人折腾好久,老子明明定义在这了,为啥还没定义
getDataLog(this.listQuery).then(response => {
// 返回值处理
this.dataLog = []
this.total = response.data.total
this.dataLog = response.data.items
// 查询后要把关键字给清空
this.keyword = ''
})
}
}
}
</script>
接下来看看上面的 api 接口/src/api/service/dataLog.js每次点击就会去调用 api 接口里的方法,参数都看得懂上面引用的 request 文件使得每次调用的时候都会对请求进行拦截,上面的 BASE_API 就会在里面被拼上去 import request from '@/utils/request'
// 获取错误信息列表
export function getDataLog(query) {
return request({
url: '/log/getDataLog',
method: 'get',
params: query
})
}
/src/mock/service/dataLog.js接下来就是使用 mock 假数据,我就循环了10条,因为假的分页,特意去实现太费劲了如果有多个接口的数据要返回,可以在 export default 里写多个接口去返回import Mock from 'mockjs'
const List = []
const count = 10
// 模拟错误信息
for (let i = 0; i < count; i++) {
List.push(Mock.mock({
data: '12987122',
time: '好滋好味鸡蛋仔',
log: '江浙小吃、小吃零食江浙小吃、小吃零食'
}))
}
export default {
// 获取错误信息列表
getDataLog: () => {
return {
total: List.length,
items: List,
limit: 10
}
}
}
/src/mock/index.js上面的写完还不行,因为通过 api 提交的请求,mock 不知道哪些是需要请求假数据的,所有需要在 index 文件里进行拦截直接加就好了,就这两行,把刚写的假数据引用进来,对请求进行拦截第一个参数,就是要拦截的 url 这里就和 api 挂钩起来了第二个参数,get 类型请求第三个参数,/src/mock/service/dataLog.js 里 export 的对应接口,这样就和 mock 假数据也挂钩起来了需要拦截多少个请求就要写多少个然后 npm run dev 运行测试就好了axios 连接后台真数据这里我偷了个懒,由于 utils/request.js 已经帮我们把 axios 都弄好了,像 BASE_API 的路径拼接,我又不想再写个 api 文件,所以我就直接拿过来用了先引入import request from '@/utils/request'js 部分:methods: {
getDataLog() {
this.listQuery = {
page: this.listQuery.page,
limit: this.listQuery.limit,
object: this.keyword
}
// mock 请求假数据
// getDataLog(this.listQuery).then(response => {
// this.dataLog = []
// this.total = response.data.total
// this.dataLog = response.data.items
// // 查询后要把关键字给清空
// this.keyword = ''
// })
// 请求后台获得真实数据
request({
url: '/log/getDataLog/',
method: 'post',
data: this.listQuery
}).then(response => {
this.dataLog = []
this.total = response.data.pageEntity.total
this.dataLog = response.data.retData
})
}
}
这里访问路径就是 http://127.0.0.1:8081/log/getDataLog,如果全路径访问也是可以的,url 前面带了 “/”意思就是会进行路径的拼接,如果写的是 url: 'log/getDataLog' 那么访问就报错了,因为前缀没拼上,还有要把 mock 里的 index.js 文件里的注掉,要不会拦截变成假数据这里用的是 post 方法,后台部分直接用 @RequestBody 接收参数就好了也可以用 get 方法,把参数拼在 url 上传递,我这采用 restful 形式的接口,用 @PathVariable 接收参数这时候你可能会遇到跨域问题新建 config 包@Configuration
public class CorssDomainConfig implements WebMvcConfigurer {
@Autowired
private CorsInterceptor corsInterceptor;
@Override
public void addInterceptors(InterceptorRegistry registry) {
InterceptorRegistration registration = registry.addInterceptor(corsInterceptor);
registration.addPathPatterns("/**");
}
}
然后新建 interceptor 包@Component
public class CorsInterceptor extends HandlerInterceptorAdapter {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
// 添加跨域CORS
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Headers", "Origin,X-Requested-With,Content-Type,Accept,Authorization,token, x-token");
response.setHeader("Access-Control-Allow-Methods", "GET, HEAD, POST, PUT, DELETE, TRACE, OPTIONS, PATCH");
return true;
}
}
项目再启动时,addInterceptors 就会把 preHandle 给注册成对象,后续请求都会经过 preHandle 接口对请求做出处理正式环境部署我这前端采用 Nginx 作为前端的运行容器详细部署:Docker 上部署 Nginx我 Nginx html 文件夹下我保留了 dist目录所以 /conf.d/default.conf 要改下vue 里 config/sit.env.js,这里我配置了测试服的,然后在 prod.env.js 配置了正式服的module.exports = {
NODE_ENV: '"production"',
ENV_CONFIG: '"sit"',
// 项目访问根路径
// 测试服
BASE_API: '"http://xx.xx.xxx.xxx:xxxx"',
}
#测试服打包
npm run build:sit
#正式服打包
npm run build:prod
命令就在 package.json 里打包后会在根目录生成 dist 文件夹,把文件夹放到服务器的 html 文件夹下就好了,然后启动 Nginx,启动过就不用启动了,由于我 Nginx 直接配置了 80 端口的,所以直接服务器路径访问就行了PS:如果遇到了打包报错的情况,那就把 npm 更新下 npm install ,这会在项目根目录生成 node_modules 文件夹,这些是需要的依赖,在 linux 上打包我这试了不行,依赖更新了也不对,不知道问题出在哪,应该是 windows 和 linux 依赖不太一样吧前端完整代码/src/views/service/dataLog.vue<template>
<div class="app-container">
<!-- 查询框 双向绑定 keyword-->
<el-input
v-model="keyword"
placeholder="请输入关键字"
clearable
style="width:500px" />
<!-- 搜索按钮 -->
<el-button type="primary" icon="el-icon-search" @click="getDataLog()">搜索</el-button>
<!-- data就是绑定数据用的 -->
<el-table
:data="dataLog"
height="600"
style="width: 100%">
<el-table-column type="expand">
<template slot-scope="props">
<el-form label-position="left" inline class="demo-table-expand">
<el-form-item label="错误信息">
<div v-html="props.row.log"/>
</el-form-item>
</el-form>
</template>
</el-table-column>
<el-table-column
label="服务单"
prop="data"/>
<el-table-column
label="时间"
prop="time"/>
</el-table>
<!-- 分页 -->
<pagination
v-show="total>0"
:total="total"
:page.sync="listQuery.page"
:limit.sync="listQuery.limit"
@pagination="getDataLog" />
<!-- total总条数
listQuery.page 当前页
listQuery.limit 每页几条
getDataLog 后买点击分页时候要回调的函数 -->
</div>
</template>
<script>
// import { getDataLog } from '@/api/service/dataLog'
import Pagination from '@/components/Pagination'
import request from '@/utils/request'
export default {
components: { Pagination },
data() {
return {
// 搜索关键字
keyword: '',
// 数据条数
total: 0,
// 分页参数
listQuery: {
page: 1,
limit: 10
},
// 列表数据
dataLog: []
}
},
created() {
this.getDataLog()
},
methods: {
getDataLog() {
this.listQuery = {
page: this.listQuery.page,
limit: this.listQuery.limit,
object: this.keyword
}
// mock 请求假数据
// getDataLog(this.listQuery).then(response => {
// this.dataLog = []
// this.total = response.data.total
// this.dataLog = response.data.items
// // 查询后要把关键字给清空
// this.keyword = ''
// })
// 请求后台获得真实数据
request({
url: '/log/getDataLog/',
method: 'post',
data: this.listQuery
}).then(response => {
this.dataLog = []
this.total = response.data.pageEntity.total
this.dataLog = response.data.retData
})
}
}
}
</script>
<style>
.demo-table-expand {
font-size: 0;
}
.demo-table-expand label {
width: 90px;
color: #99a9bf;
}
.demo-table-expand .el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 50%;
}
</style>
/src/api/service/dataLog.jsimport request from '@/utils/request'
// 获取错误信息列表
export function getDataLog(query) {
return request({
url: '/log/getDataLog',
method: 'get',
params: query
})
}
/src/mock/service/index.js拦截原因,请求后台就注掉// Mock.mock(/\/log\/getDataLog/, 'get', dataLogAPI.getDataLog)/src/mock/service/dataLog.jsimport Mock from 'mockjs'
const List = []
const count = 10
// 模拟错误信息
for (let i = 0; i < count; i++) {
List.push(Mock.mock({
data: '12987122',
time: '好滋好味鸡蛋仔',
log: '江浙小吃、小吃零食江浙小吃、小吃零食'
}))
}
export default {
// 获取错误信息列表
getDataLog: () => {
return {
total: List.length,
items: List,
limit: 10
}
}
}