views下面新建home.vue
<template>
<div class="index">
<HeadNav />
<router-view />
</div>
</template>
<script>
import HeadNav from '../components/HeadNav';
export default {
name: 'index',
components: { HeadNav }
};
</script>
<style scoped>
.index {
height: 100%;
width: 100%;
overflow: hidden;
}
</style>
home是index的二级路由
修改路由
{
path: '/index',
component: Index,
children: [
{ path: '', component: Home },
{ path: '/home',name: 'home', component: Home }
]
},
这样是index.vue是不显示的,在index.vue下面添加router-view
<template>
<div class="index">
<HeadNav />
<router-view />
</div>
</template>
配置二级路由 infoshow
{ path: '/infoshow',name: 'infoshow', component: InfoShow }
views下面新建InfoShow.vue
<template>
<div class="infoshow">
<el-row type="flex" class="row-bg" justify="center">
<el-col :span='8'>
<div class="user">
<img src="user.avatar" class='avatar' alt="">
</div>
</el-col>
<el-col :span='16'>
<div class="userinfo">
<div class="user-item">
<i class="fa fa-user"></i>
<span style="margin: 0 5px">name</span>
</div>
<div class="user-item">
<i class="fa fa-cog"></i>
<span style="margin: 0 5px">identity</span>
</div>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
export default {
name: 'infoshow',
components: {}
};
</script>
<style scoped>
.index {
height: 100%;
width: 100%;
overflow: hidden;
}
.infoshow {
width: 100%;
height: 100%;
box-sizing: border-box;
/* padding: 16px; */
}
.row-bg {
width: 100%;
height: 100%;
}
.user {
text-align: center;
position: relative;
top: 30%;
}
.user img {
width: 150px;
border-radius: 50%;
}
.user span {
display: block;
text-align: center;
margin-top: 20px;
font-size: 20px;
font-weight: bold;
}
.userinfo {
height: 100%;
background-color: #eee;
}
.user-item {
position: relative;
top: 30%;
padding: 26px;
font-size: 28px;
color: #333;
}
</style>
在index.html中引入图标
<!-- 图标 -->
<link href="//cdn.bootcss.com/font-awesome/4.7.0/css/font-awesome.css" rel="stylesheet">
记得保存
去HeadNav中设置点击个人信息进行跳转
showInfoList() {
this.$router.push('/infoshow')
},```
测试ok,
获取全局user
```js
computed:{
user(){
return this.$store.getters.user
}
}
绑定 img :src,把要{{}}显示的地方改好
搞定,完成左侧导航栏,elecopy一份
index.vue引入component
测试ok,
接下来敲table,ele找自定义table 自定义table模板
views文件夹下面新建formList.vue
created时候请求api GET info,然后将info保存到tableData中
复制ele的table html
<template>
<!-- el-tbale 绑定值 tableData -->
<el-table
v-if="tableData.length >= 0"
:data="tableData"
border
style="width: 100%"
>
<el-table-column label="序号" align="center" type="index" width="70">
</el-table-column>
<el-table-column
label="创建时间"
align="center"
prop="date"
width="180"
>
</el-table-column>
<el-table-column
label="收支类型"
align="center"
prop="type"
width="180"
>
</el-table-column>
<el-table-column
label="收支描述"
align="center"
prop="describe"
width="180"
>
</el-table-column>
<el-table-column label="收入" align="center" prop="income" width="180">
</el-table-column>
<el-table-column label="支出" align="center" prop="expend" width="180">
</el-table-column>
<el-table-column
label="账户现金"
align="center"
prop="cash"
width="180"
>
</el-table-column>
<el-table-column label="备注" align="center" prop="remark" width="180">
</el-table-column>
</el-table>
</template>
<script>
export default {
name: 'fund-list',
components: {},
data() {
return {
tableData: []
};
},
created() {
this.getProfile();
},
methods: {
getProfile() {
this.$axios.get('/api/profiles').then(res => {
this.tableData = res.data;
console.log(res.data)
});
}
}
};
</script>
<style scoped></style>
美工 加入icon ,类似的就不放重复的了
<el-table-column
label="创建时间"
align="center"
prop="date"
width="180"
>
<template slot-scope="scope">
<i class="el-icon-time"></i>
<span style="margin-left: 10px">{{ scope.row.date }}</span>
</template>
</el-table-column>
<el-table-column label="支出" align="center" prop="expend" width="180">
<template slot-scope="scope">
<i class="el-icon-money"></i>
<span style="margin-left: 10px; color:#00d053">- {{
scope.row.expend
}}</span>
</template>
</el-table-column>
最外层加上div 加上 padding,美工做完后,写handle方法
获取数据,完善增删改
加入操作 写handle方法
加入添加按钮,点击添加会有dialo弹框
在components下面创建Dialog.vue
我们希望点击添加按钮时 弹出弹框
在父组件添加dialog
data() {
return {
tableData: [],
dialog:{
show: false
}
};
},
在Dialog.vue中用props引入进来
export default {
name: 'dialog',
// 父组件 属性传值过来
props:{
dialog: Object,
}
}
那么点击添加按钮时调用的方法为 把show改成true
handleAdd() {
this.dialog.show = true
}
在Dialog.vue中 把:visible绑定成dialog的show
<template>
<div class="dialog">
<el-dialog
title="添加资金信息"
:visible="dialog.show"
:modal-append-to-body="false"
>
</el-dialog>
</div>
</template>
父组件我要把信息传递到弹框中,绑定dialog
<Dialog :dialog="dialog"/>
去测试的时候是不能关闭对话框的
我们需要加上.sync
:visible.sync="dialog.show"
写弹框 里面的form表单
传递的值有formData,format_tpye_list是用来遍历展示的
rules是写在data()里面的
写onSubmit ,格式
onSubmit(form){
this.$refs[form].validate(valid => {
if(valid){
this.$axios.post('/api/profiles/add', this.formData)
.then(res => {
this.$message({
message: '数据添加成功',
type: 'success'
})
})
// 隐藏dialog
this.dialog.show = false
// 自动刷新
this.$emit('update')
}
})
}
注册一个update事件让父级去执行 @update就是接收到这个事件后去执行get信息的操作
<Dialog :dialog="dialog" @update="getProfile()"/>
接下来是编辑功能
我们想让data信息由父级传递,我们把formData: {} 剪切走,贴到FundList.vue里面去
:formData这样传递过去
<Dialog :dialog="dialog" :formData="formData" @update="getProfile()"/>
子组件用props接收
props: {
dialog: Object,
formData:Object
},
回到父级,修改属性添加 title和option 传递给子组件用来判断是添加还是修改
dialog:{
show: false,
title: '',
option: 'edit',
}
那么子组件title应该绑成
:title="dialog.title"
所以在点击的时候 需要修改这些对应的属性以显示对应的title
handleEdit(index, row) {
// 编辑
this.dialog.show = true
this.dialog.title = '修改资金信息'
this.dialog.option = 'edit'
}
handleAdd() {
this.dialog.show = true
this.dialog.title = '添加资金信息'
this.dialog.option = 'add'
}
这样去做一个区分,接下来在编辑的时候,我们要拿到当前行的信息保存到formdata中
handleEdit(index, row) {
// 编辑
this.dialog.show = true
this.dialog.title = '修改资金信息'
this.dialog.option = 'edit'
// 我们要拿到当前行的信息保存到formdata中
this.formData = {
type: row.type,
describe: row.describe,
income: row.income,
expend: row.expend,
cash: row.cash,
remark: row.remark,
id: row._id
}
},
同理 提交的时候 formdata是全空的,这里就不放出来了, 大同小异
回到表单的提交方法onSubmit,我们还要对提交和编辑进行区分以调用不同的api
onSubmit(form) {
this.$refs[form].validate(valid => {
if (valid) {
const url =
this.dialog.option == 'add'
? 'add'
: `edit/${this.formData.id}
`;
this.$axios
.post(`/api/profiles/${url}`, this.formData)
.then(res => {
if (url == 'add') {
this.$message({
message: '数据添加成功',
type: 'success'
});
} else {
this.$message({
message: '数据修改成功',
type: 'success'
});
}
});
// 隐藏dialog
this.dialog.show = false;
// 自动刷新
this.$emit('update');
}
});
}
最后是写delete方法
handleDelete(index, row) {
this.$axios.delete(`/api/profiles/delete/${row._id}`).then(res => {
// 提醒框
this.$message('删除成功');
// 刷新页面
this.getProfile();
});
},
测试一下,ok
分页,用ele 去官网copy一下
去到FundList组件下,copy
<!--分页-->
<el-row>
<el-col :span="24">
<div class="pagination">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage4"
:page-sizes="[5, 10, 15, 20]"
:page-size="100"
layout="total, sizes, prev, pager, next, jumper"
:total="400"
>
</el-pagination>
</div>
</el-col>
</el-row>
创建data给一个paginations属性
paginations: {
// 当前位于页数
page_index: 1,
total: 0,
page_size: 5,
// 每页显示多少条
page_sizes: [5, 10, 15, 20],
// 翻页属性
layout: "total, sizes, prev, pager, next, jumper"
}
修改绑定属性
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="paginations.page_index"
:page-sizes="paginations.page_sizes"
:page-size="paginations.page_size"
:layout="paginations.layout"
:total="paginations.total"
>
实现两个方法handleSizeChange,handleCurrentChange
加多一个data属性 allTableData: [],
把getProfile()里面的tableData和所有tableData都改成AllTableData
getProfile() {
this.$axios.get('/api/profiles').then(res => {
this.allTableData = res.data;
// console.log(res.data);
// 设置分页数据
this.setPainations();
});
},
并且加多调用一个setPainations函数,主要是用作初始化
setPainations() {
// 分页属性初始化设置
this.paginations.total = this.allTableData.length;
this.paginations.page_index = 1;
this.paginations.page_size = 5;
// 设置tabelData数据
this.tableData = this.allTableData.filter((item, index) => {
return index < this.paginations.page_size;
});
},
切换size函数实现
handleSizeChange(page_size) {
// 切换size
this.paginations.page_index = 1;
this.paginations.page_size = page_size;
// 设置tabelData数据
this.tableData = this.allTableData.filter((item, index) => {
return index < page_size;
});
},
实现切换页面
handleCurrentChange(page) {
// 当前页
let sortnum = this.paginations.page_size * (page - 1);
// 设置tableData 取页头往后
let table = this.allTableData.filter((item, index) => {
return index >= sortnum;
});
// 取页尾往前
this.tableData = table.filter((item, index) => {
return index < this.paginations.page_size;
});
}
时间选择器 筛选功能,把html结构写上
<el-form :inline="true" ref="add_data">
<!--时间选择器-->
<el-form-item label="按照时间筛选:">
<el-date-picker
v-model="value2"
type="datetime"
placeholder="开始时间"
align="right"
>
</el-date-picker>
<el-date-picker
v-model="value2"
type="datetime"
placeholder="结束时间"
align="right"
>
</el-date-picker>
</el-form-item>
<!--筛选btn-->
<el-form-item class="btn">
<el-button type="primary"
size="small"
icon="search"
@click="handleSearch()">
筛选</el-button
>
</el-form-item>
<!--添加btn-->
<el-form-item class="btnRight">
<el-button type="primary" size="small" @click="handleAdd()">
添加</el-button
>
</el-form-item>
</el-form>
添加关于时间的容器
search_data:{
startTime :'',
endTime :'',
},
把他们绑定上
v-model="search_data.startTime"
v-model="search_data.endTime"
<el-form :inline="true" ref="add_data" :model="search_data">
这里也要search_data
handleSearch实现方法
handleSearch() {
if (!this.search_data.startTime || !this.search_data.endTime) {
this.$message({
message: '请选择时间区间',
type: 'warning'
});
} else {
const sTime = this.search_data.startTime.getTime();
const eTime = this.search_data.endTime.getTime();
console.log(sTime);
console.log(eTime);
this.allTableData = this.filterTableData.filter(
(item, index) => {
let date = new Date(item.date);
let time = date.getTime();
console.log(time);
console.log(time >= sTime && time <= eTime);
return time >= sTime && time <= eTime;
}
);
// 分页数据调用
this.setPainations();
}
},
ctrl+k+4 所有代码折叠
添加filterTableData:[],容器 用来保存筛选的内容
在getProfile()时将所有内容保存到filterTableData
修改nodejs date时间格式化 引用moment
dateFormat(date) {
{
return moment(date).format('YYYY-MM-DD HH:mm:ss');
}
}
展示的时候调用这个函数
{{ dateFormat(scope.row.date) }}
ok 搞定
权限设定
添加computed,获取权限
computed: {
user(){
return this.$store.getters.user
}
}
在btn中添加v-if="user.identity == 'manage'"
项目打包, heroku免费,注册 登陆
下载heroku cli
前端打包 private false, npm run build
后端server.js设置
// 执行前端静态页面
if(process.env.NODE_ENV === 'production'){
const pass = require('path')
app.use(express.static('client/dist'))
// 其他页面都跳转到index.html
app.get('*', (req, res) => {
res.sendFile(path.resolve(__dirname, 'client', 'dist'
,'index.html'
))
})
}