目录
简介
vue-element-admin 是一个后台前端解决方案,它基于 vue 和 element-ui实现。它使用了最新的前端技术栈,内置了 i18n 国际化解决方案,动态路由,权限验证,提炼了典型的业务模型,提供了丰富的功能组件,它可以帮助你快速搭建企业级中后台产品原型。相信不管你的需求是什么,本项目都能帮助到你。
前序准备
你需要在本地安装 node 和 git。本项目技术栈基于 ES2015+、vue、vuex、vue-router 、vue-cli 、axios 和 element-ui,所有的请求数据都使用Mock.js进行模拟,提前了解和学习这些知识会对使用本项目有很大的帮助。
前后端分离
前端 vue-element-admin,后端 Spring Boot、Maven
参考 vue-element-admin complex-table 示例,写一个简单的 Java 后端 增删查改应用
Spring Boot
Maven
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>vue-element-admin</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>vue-element-admin</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.3</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.pagehelper/pagehelper-spring-boot-starter -->
<dependency>
<groupId>com.github.pagehelper</groupId>
<artifactId>pagehelper-spring-boot-starter</artifactId>
<version>1.3.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.4.0</version>
<configuration>
<configurationFile>${basedir}/src/main/resources/generatorConfig.xml</configurationFile>
<overwrite>true</overwrite>
<verbose>true</verbose>
</configuration>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.mybatis.generator/mybatis-generator-core -->
<dependency>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-core</artifactId>
<version>1.4.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
</project>
使用 MyBatis Generator 快速生成 model、mapper、xml
generatorConfig.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration PUBLIC
"-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
"http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
<context id="Table2Model" targetRuntime="MyBatis3" defaultModelType="flat">
<property name="javaFileEncoding" value="UTF-8"/>
<commentGenerator>
<!-- <property name="suppressDate" value="true" /> -->
<property name="addRemarkComments" value="true"/>
</commentGenerator>
<jdbcConnection
connectionURL="jdbc:mysql://localhost:3306/vue_element_admin?serverTimezone=Asia/Shanghai"
driverClass="com.mysql.cj.jdbc.Driver" password="snapshot" userId="wuyong"/>
<javaTypeResolver>
<property name="forceBigDecimals" value="false"/>
</javaTypeResolver>
<javaModelGenerator targetPackage="com.example.model" targetProject="src/main/java"/>
<sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources"/>
<javaClientGenerator targetPackage="com.example.mapper" targetProject="src/main/java"
type="XMLMAPPER"/>
<table schema="vue_element_admin" tableName="article" domainObjectName="Article"
enableSelectByExample="false" enableDeleteByExample="false"
enableCountByExample="enableCountByExample" enableUpdateByExample="false"
selectByExampleQueryId="false">
<!-- <domainObjectRenamingRule searchString="^Sys" replaceString="" /> -->
<!-- <columnRenamingRule searchString="^CUST_" replaceString="" /> -->
</table>
</context>
</generatorConfiguration>
application.yml
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/vue_element_admin?characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&useSSL=false&useUnicode=true
username: wuyong
password: snapshot
jackson:
serialization:
write-dates-as-timestamps: true
server:
port: 8080
servlet:
context-path: /dev-api/vue-element-admin
mybatis:
mapper-locations: classpath:mapper/*.xml
type-aliases-package: com.example.model
configuration:
map-underscore-to-camel-case: true
use-generated-keys: true
pagehelper:
helperDialect: mysql
reasonable: true
supportMethodsArguments: true
params: count=countSql
Spring 启动程序
package com.example;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author wuyong
*/
@MapperScan("com.example.mapper")
@SpringBootApplication
public class VueElementAdminApplication {
public static void main(String[] args) {
SpringApplication.run(VueElementAdminApplication.class, args);
}
}
web
UserController
package com.example.web;
import com.example.model.LoginForm;
import java.util.HashMap;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author wuyong
*/
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/user")
public class UserController {
@PostMapping("/login")
public Map<String, Object> login(@RequestBody LoginForm loginForm) {
Map<String, Object> res = new HashMap<>();
Map<String, Object> data = new HashMap<>();
if ("admin".equals(loginForm.getUsername()) && "111111".equals(loginForm.getPassword())) {
data.put("token", "admin-token");
res.put("code", 20000);
res.put("data", data);
} else {
res.put("code", 60204);
res.put("message", "Account and password are incorrect.");
}
return res;
}
@GetMapping("/info")
public Map<String, Object> info(String token) {
Map<String, Object> res = new HashMap<>();
Map<String, Object> data = new HashMap<>();
String[] roles = {"admin"};
String introduction = "I am a super administrator";
String avatar = "https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif";
String name = "Super Admin";
if ("admin-token".equals(token)) {
data.put("roles", roles);
data.put("introduction", introduction);
data.put("avatar", avatar);
data.put("name", name);
res.put("code", 20000);
res.put("data", data);
} else {
res.put("code", 50008);
res.put("message", "Login failed, unable to get user details.");
}
return res;
}
@PostMapping("/logout")
public Map<String, Object> logout() {
Map<String, Object> res = new HashMap<>();
res.put("code", 20000);
res.put("data", "success");
return res;
}
}
ArticleController
package com.example.web;
import com.example.mapper.ArticleMapper;
import com.example.model.Article;
import com.example.service.ArticleService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author wuyong
*/
@Slf4j
@CrossOrigin
@RestController
@RequestMapping("/article")
public class ArticleController {
@Autowired private ArticleService articleService;
@Autowired private ArticleMapper articleMapper;
@GetMapping("/list")
public Map<String, Object> fetchList(Integer page, Integer limit, String title, String sort) {
log.info("page:{}, limit:{}, title:{}, sort:{}", page, limit, title, sort);
Map<String, Object> res = new HashMap<>();
Map<String, Object> data = new HashMap<>();
PageHelper.startPage(page, limit);
if ("-id".equals(sort)) {
PageHelper.orderBy("id desc");
}
List<Article> articleList;
if (title == null) {
articleList = articleMapper.selectAll();
} else {
articleList = articleMapper.searchKeyword(title);
}
PageInfo pageInfo = new PageInfo(articleList);
long total = pageInfo.getTotal();
data.put("total", total);
data.put("items", articleList);
res.put("code", 20000);
res.put("data", data);
return res;
}
@GetMapping("/detail")
public Map<String, Object> fetchArticle(Integer id) {
Map<String, Object> res = new HashMap<>();
Map<String, Object> data = new HashMap<>();
Article article = articleMapper.selectByPrimaryKey(id);
data.put("article", article);
res.put("code", 20000);
res.put("data", article);
return res;
}
@PostMapping("/create")
public Map<String, Object> createArticle(@RequestBody Article article) {
log.info("{}", article);
Map<String, Object> res = new HashMap<>();
Map<String, Object> data = new HashMap<>();
int result = articleMapper.insertSelective(article);
if (result > 0) {
res.put("code", 20000);
res.put("data", "success");
}
return res;
}
@PostMapping("/update")
public Map<String, Object> updateArticle(@RequestBody Article article) {
log.info("{}", article);
Map<String, Object> res = new HashMap<>();
Map<String, Object> data = new HashMap<>();
int result = articleMapper.updateByPrimaryKey(article);
if (result > 0) {
res.put("code", 20000);
res.put("data", "success");
}
return res;
}
@PostMapping("/delete")
public Map<String, Object> deleteArticle(@RequestBody Article article) {
log.info("{}", article);
Map<String, Object> res = new HashMap<>();
Map<String, Object> data = new HashMap<>();
int result = articleMapper.updateByPrimaryKey(article);
if (result > 0) {
res.put("code", 20000);
res.put("data", "success");
}
return res;
}
@PostMapping("/modifystatus")
public Map<String, Object> modifyStatus(@RequestBody Article article) {
log.info("{}", article);
Map<String, Object> res = new HashMap<>();
Map<String, Object> data = new HashMap<>();
int result = articleMapper.updateByPrimaryKey(article);
if (result > 0) {
res.put("code", 20000);
res.put("data", "success");
}
return res;
}
}
service
ArticleService
package com.example.service;
import org.springframework.stereotype.Service;
/**
* @author wuyong
*/
@Service
public class ArticleService {}
mapper
ArticleMapper.java
List<Article> selectAll();
List<Article> searchKeyword(String title);
ArticleMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.mapper.ArticleMapper">
...
<select id="selectAll" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from article
</select>
<select id="searchKeyword" resultMap="BaseResultMap">
select
<include refid="Base_Column_List"/>
from article
where title like concat('%',#{title},'%')
</select>
</mapper>
vue-element-admin
新增 api
article.js
import request from '@/utils/request'
export function fetchList(query) {
return request({
url: '/vue-element-admin/article/list',
method: 'get',
params: query
})
}
export function fetchArticle(id) {
return request({
url: '/vue-element-admin/article/detail',
method: 'get',
params: { id }
})
}
export function createArticle(data) {
return request({
url: '/vue-element-admin/article/create',
method: 'post',
data
})
}
export function updateArticle(data) {
return request({
url: '/vue-element-admin/article/update',
method: 'post',
data
})
}
export function deleteArticle(data) {
return request({
url: '/vue-element-admin/article/delete',
method: 'post',
data
})
}
export function modifyStatus(data) {
return request({
url: '/vue-element-admin/article/modifystatus',
method: 'post',
data
})
}
新增 view
<template>
<div class="app-container">
<div class="filter-container">
<el-input v-model="listQuery.title" placeholder="Title" style="width: 200px;" class="filter-item" @keyup.enter.native="handleFilter" />
<!-- <el-select v-model="listQuery.importance" placeholder="Imp" clearable style="width: 90px" class="filter-item">
<el-option v-for="item in importanceOptions" :key="item" :label="item" :value="item" />
</el-select> -->
<!-- <el-select v-model="listQuery.type" placeholder="Type" clearable class="filter-item" style="width: 130px">
<el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name+'('+item.key+')'" :value="item.key" />
</el-select> -->
<el-select v-model="listQuery.sort" style="width: 140px" class="filter-item" @change="handleFilter">
<el-option v-for="item in sortOptions" :key="item.key" :label="item.label" :value="item.key" />
</el-select>
<el-button v-waves class="filter-item" type="primary" icon="el-icon-search" @click="handleFilter">
Search
</el-button>
<el-button class="filter-item" style="margin-left: 10px;" type="primary" icon="el-icon-edit" @click="handleCreate">
Add
</el-button>
<el-button v-waves :loading="downloadLoading" class="filter-item" type="primary" icon="el-icon-download" @click="handleDownload">
Export
</el-button>
<el-checkbox v-model="showReviewer" class="filter-item" style="margin-left:15px;" @change="tableKey=tableKey+1">
reviewer
</el-checkbox>
</div>
<el-table
:key="tableKey"
v-loading="listLoading"
:data="list"
border
fit
highlight-current-row
style="width: 100%;"
@sort-change="sortChange"
>
<el-table-column label="ID" prop="id" sortable="custom" align="center" width="80" :class-name="getSortClass('id')">
<template slot-scope="{row}">
<span>{{ row.id }}</span>
</template>
</el-table-column>
<el-table-column label="Date" width="150px" align="center">
<template slot-scope="{row}">
<span>{{ row.timestamp | parseTime('{y}-{m}-{d} {h}:{i}') }}</span>
</template>
</el-table-column>
<el-table-column label="Title" min-width="150px">
<template slot-scope="{row}">
<span class="link-type" @click="handleUpdate(row)">{{ row.title }}</span>
<!-- <el-tag>{{ row.type | typeFilter }}</el-tag> -->
</template>
</el-table-column>
<el-table-column label="Author" width="110px" align="center">
<template slot-scope="{row}">
<span>{{ row.author }}</span>
</template>
</el-table-column>
<el-table-column v-if="showReviewer" label="Reviewer" width="110px" align="center">
<template slot-scope="{row}">
<span style="color:red;">{{ row.reviewer }}</span>
</template>
</el-table-column>
<!-- <el-table-column label="Imp" width="80px">
<template slot-scope="{row}">
<svg-icon v-for="n in + row.importance" :key="n" icon-class="star" class="meta-item__icon" />
</template>
</el-table-column> -->
<!-- <el-table-column label="Readings" align="center" width="95">
<template slot-scope="{row}">
<span v-if="row.pageviews" class="link-type" @click="handleFetchPv(row.pageviews)">{{ row.pageviews }}</span>
<span v-else>0</span>
</template>
</el-table-column> -->
<el-table-column label="Status" class-name="status-col" width="100">
<template slot-scope="{row}">
<el-tag :type="row.status | statusFilter">
{{ row.status }}
</el-tag>
</template>
</el-table-column>
<el-table-column label="Actions" align="center" width="230" class-name="small-padding fixed-width">
<template slot-scope="{row,$index}">
<el-button type="primary" size="mini" @click="handleUpdate(row)">
Edit
</el-button>
<el-button v-if="row.status!='published'" size="mini" type="success" @click="handleModifyStatus(row,'published')">
Publish
</el-button>
<el-button v-if="row.status!='draft'" size="mini" @click="handleModifyStatus(row,'draft')">
Draft
</el-button>
<el-button v-if="row.status!='deleted'" size="mini" type="danger" @click="handleDelete(row,$index)">
Delete
</el-button>
</template>
</el-table-column>
</el-table>
<pagination v-show="total>0" :total="total" :page.sync="listQuery.page" :limit.sync="listQuery.limit" @pagination="getList" />
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
<el-form ref="dataForm" :rules="rules" :model="temp" label-position="left" label-width="70px" style="width: 400px; margin-left:50px;">
<!-- <el-form-item label="Type" prop="type">
<el-select v-model="temp.type" class="filter-item" placeholder="Please select">
<el-option v-for="item in calendarTypeOptions" :key="item.key" :label="item.display_name" :value="item.key" />
</el-select>
</el-form-item> -->
<el-form-item label="Date" prop="timestamp">
<el-date-picker v-model="temp.timestamp" type="datetime" placeholder="Please pick a date" />
</el-form-item>
<el-form-item label="Title" prop="title">
<el-input v-model="temp.title" />
</el-form-item>
<el-form-item label="Status">
<el-select v-model="temp.status" class="filter-item" placeholder="Please select">
<el-option v-for="item in statusOptions" :key="item" :label="item" :value="item" />
</el-select>
</el-form-item>
<!-- <el-form-item label="Imp">
<el-rate v-model="temp.importance" :colors="['#99A9BF', '#F7BA2A', '#FF9900']" :max="3" style="margin-top:8px;" />
</el-form-item> -->
<!-- <el-form-item label="Remark">
<el-input v-model="temp.remark" :autosize="{ minRows: 2, maxRows: 4}" type="textarea" placeholder="Please input" />
</el-form-item> -->
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogFormVisible = false">
Cancel
</el-button>
<el-button type="primary" @click="dialogStatus==='create'?createData():updateData()">
Confirm
</el-button>
</div>
</el-dialog>
<!-- <el-dialog :visible.sync="dialogPvVisible" title="Reading statistics">
<el-table :data="pvData" border fit highlight-current-row style="width: 100%">
<el-table-column prop="key" label="Channel" />
<el-table-column prop="pv" label="Pv" />
</el-table>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="dialogPvVisible = false">Confirm</el-button>
</span>
</el-dialog> -->
</div>
</template>
<script>
import { fetchList, createArticle, updateArticle, deleteArticle, modifyStatus } from '@/api/article'
import waves from '@/directive/waves' // waves directive
import { parseTime } from '@/utils'
import Pagination from '@/components/Pagination' // secondary package based on el-pagination
// const calendarTypeOptions = [
// { key: 'CN', display_name: 'China' },
// { key: 'US', display_name: 'USA' },
// { key: 'JP', display_name: 'Japan' },
// { key: 'EU', display_name: 'Eurozone' }
// ]
// arr to obj, such as { CN : "China", US : "USA" }
// const calendarTypeKeyValue = calendarTypeOptions.reduce((acc, cur) => {
// acc[cur.key] = cur.display_name
// return acc
// }, {})
export default {
name: 'ComplexTable',
components: { Pagination },
directives: { waves },
filters: {
statusFilter(status) {
const statusMap = {
published: 'success',
draft: 'info',
deleted: 'danger'
}
return statusMap[status]
}
// typeFilter(type) {
// return calendarTypeKeyValue[type]
// }
},
data() {
return {
tableKey: 0,
list: null,
total: 0,
listLoading: true,
listQuery: {
page: 1,
limit: 10,
// importance: undefined,
title: undefined,
// type: undefined,
sort: '+id'
},
// importanceOptions: [1, 2, 3],
// calendarTypeOptions,
sortOptions: [{ label: 'ID Ascending', key: '+id' }, { label: 'ID Descending', key: '-id' }],
statusOptions: ['published', 'draft', 'deleted'],
showReviewer: false,
temp: {
id: undefined,
// importance: 1,
// remark: '',
timestamp: new Date(),
title: '',
// type: '',
status: 'published'
},
dialogFormVisible: false,
dialogStatus: '',
textMap: {
update: 'Edit',
create: 'Create'
},
dialogPvVisible: false,
pvData: [],
rules: {
// type: [{ required: true, message: 'type is required', trigger: 'change' }],
timestamp: [{ type: 'date', required: true, message: 'timestamp is required', trigger: 'change' }],
title: [{ required: true, message: 'title is required', trigger: 'blur' }]
},
downloadLoading: false
}
},
created() {
this.getList()
},
methods: {
getList() {
console.clear()
this.listLoading = true
console.log('fetchList-------------------->')
console.log('request\n%c%s', 'color: red; font-style: italic; font-size: 13px', JSON.stringify(this.listQuery, null, 2))
fetchList(this.listQuery).then(response => {
this.list = response.data.items
console.log('this.list\n%c%s', 'color: red; font-style: italic; font-size: 13px', JSON.stringify(this.list, null, 2))
this.total = response.data.total
console.log('this.total\n%c%d', 'color: red; font-style: italic; font-size: 13px', this.total)
// Just to simulate the time of the request
setTimeout(() => {
this.listLoading = false
}, 1.5 * 1000)
})
},
handleFilter() {
this.listQuery.page = 1
this.getList()
},
handleModifyStatus(row, status) {
console.clear()
console.log('点击 状态切换 按钮')
this.temp = Object.assign({}, row)
this.temp.status = status
console.log('modifyStatus-------------------->')
console.log('request\n%c%s', 'color: red; font-style: italic; font-size: 13px', JSON.stringify(this.temp, null, 2))
modifyStatus(this.temp).then(() => {
this.$message({
message: '操作Success',
type: 'success'
})
})
row.status = status
},
sortChange(data) {
const { prop, order } = data
if (prop === 'id') {
this.sortByID(order)
}
},
sortByID(order) {
if (order === 'ascending') {
this.listQuery.sort = '+id'
} else {
this.listQuery.sort = '-id'
}
this.handleFilter()
},
resetTemp() {
this.temp = {
id: undefined,
// importance: 1,
// remark: '',
timestamp: new Date(),
title: '',
status: 'published'
// type: ''
}
},
handleCreate() {
console.clear()
console.log('点击 添加 按钮')
this.resetTemp()
this.dialogStatus = 'create'
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
})
},
createData() {
console.log('点击 对话框 确认 按钮')
this.$refs['dataForm'].validate((valid) => {
if (valid) {
this.temp.author = 'vue-element-admin'
const tempData = Object.assign({}, this.temp)
this.temp.id = ++this.total
console.log('createArticle-------------------->')
console.log('request\n%c%s', 'color: red; font-style: italic; font-size: 13px', JSON.stringify(tempData, null, 2))
createArticle(tempData).then(() => {
this.list.unshift(this.temp)
this.dialogFormVisible = false
this.$notify({
title: 'Success',
message: 'Created Successfully',
type: 'success',
duration: 2000
})
})
}
})
},
handleUpdate(row) {
console.clear()
console.log('点击 编辑 按钮')
this.temp = Object.assign({}, row) // copy obj
this.temp.timestamp = new Date(this.temp.timestamp)
this.dialogStatus = 'update'
this.dialogFormVisible = true
this.$nextTick(() => {
this.$refs['dataForm'].clearValidate()
})
},
updateData() {
console.log('点击 对话框 确认 按钮')
this.$refs['dataForm'].validate((valid) => {
if (valid) {
const tempData = Object.assign({}, this.temp)
tempData.timestamp = +new Date(tempData.timestamp) // change Thu Nov 30 2017 16:41:05 GMT+0800 (CST) to 1512031311464
console.log('updateArticle-------------------->')
console.log('request\n%c%s', 'color: red; font-style: italic; font-size: 13px', JSON.stringify(tempData, null, 2))
updateArticle(tempData).then(() => {
const index = this.list.findIndex(v => v.id === this.temp.id)
this.list.splice(index, 1, this.temp)
this.dialogFormVisible = false
this.$notify({
title: 'Success',
message: 'Update Successfully',
type: 'success',
duration: 2000
})
})
}
})
},
handleDelete(row, index) {
console.clear()
console.log('点击 删除 按钮')
this.temp = Object.assign({}, row)
this.temp.status = 'deleted'
console.log('deleteArticle-------------------->')
console.log('request\n%c%s', 'color: red; font-style: italic; font-size: 13px', JSON.stringify(this.temp, null, 2))
deleteArticle(this.temp).then(() => {
this.$notify({
title: 'Success',
message: 'Delete Successfully',
type: 'success',
duration: 2000
})
this.list.splice(index, 1)
})
row.status = 'deleted'
},
// handleFetchPv(pv) {
// fetchPv(pv).then(response => {
// this.pvData = response.data.pvData
// this.dialogPvVisible = true
// })
// },
handleDownload() {
console.clear()
console.log('点击 导出 按钮')
this.downloadLoading = true
import('@/vendor/Export2Excel').then(excel => {
// const tHeader = ['timestamp', 'title', 'type', 'importance', 'status']
const tHeader = ['timestamp', 'title', 'status']
// const filterVal = ['timestamp', 'title', 'type', 'importance', 'status']
const filterVal = ['timestamp', 'title', 'status']
const data = this.formatJson(filterVal)
console.log('data\n%c%s', 'color: red; font-style: italic; font-size: 13px', JSON.stringify(data, null, 2))
excel.export_json_to_excel({
header: tHeader,
data,
filename: 'table-list'
})
this.downloadLoading = false
})
},
formatJson(filterVal) {
return this.list.map(v => filterVal.map(j => {
if (j === 'timestamp') {
return parseTime(v[j])
} else {
return v[j]
}
}))
},
getSortClass: function(key) {
const sort = this.listQuery.sort
return sort === `+${key}` ? 'ascending' : 'descending'
}
}
}
</script>