webpack+element+vue+express+mangodb+axios增删查(页面适配至移动端320*568)

webpack+element+vue+express+mangodb+axios增删查(页面适配至移动端320*568)

接上一章博文:webpack+element+vue+express+mangodb+axios显示数据库数据(vue过渡动画)
这次做显示数据库内容,增加插入和删除功能,适配移动端,优化代码结构

demo

下面是demo,自己下着看吧!
demo:https://github.com/jsq-github/department-statistics

目录

在这里插入图片描述

代码

与上一篇博文一样或只有小调整的我就不重复贴出来了!!!!!!!!!!!

webpack.prod.js

// eslint-disable-next-line no-undef
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
// eslint-disable-next-line no-undef
const merge = require('webpack-merge');
// eslint-disable-next-line no-undef
const webpackBaseConfig = require('./webpack.base');
// eslint-disable-next-line no-undef
const uglify = require('uglifyjs-webpack-plugin');
// eslint-disable-next-line no-undef
const { CleanWebpackPlugin } = require('clean-webpack-plugin');
// eslint-disable-next-line no-undef
const FileManagerPlugin = require('filemanager-webpack-plugin');
// eslint-disable-next-line no-undef
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
// eslint-disable-next-line no-undef
const json = require('../package.json');

// eslint-disable-next-line no-undef
module.exports = merge(webpackBaseConfig,{
	module: {
		rules: [{
			test:/\.css$/,
			use:[MiniCssExtractPlugin.loader,'css-loader']
		}]
	},
	plugins: [
		new CleanWebpackPlugin(),
		new FileManagerPlugin({  //初始化 filemanager-webpack-plugin 插件实例
			onEnd: {
				// eslint-disable-next-line no-mixed-spaces-and-tabs
			  copy: [//前后端同时打包,包括依赖,可直接使用 node index直接运行,无需求可删除此copy
					{ source: './backend', destination: './staff-stats/backend' },
					{ source: './node_modules', destination: './staff-stats/node_modules' },
					{ source: './config', destination: './staff-stats/config' }
				],
				delete: [   //首先需要删除项目根目录下的staff-stats.zip
					'./staff-stats-'+json.version+'.zip',
				],
				archive: [ //然后我们选择staff-stats文件夹将之打包成staff-stats.zip并放在根目录
					{source: './staff-stats', destination: './staff-stats-'+json.version+'.zip'},
				]
			}
		}),
		new MiniCssExtractPlugin({
			filename: 'css/[name].[hash].css',
		}),
		new OptimizeCSSAssetsPlugin({}),
		new uglify()
	]
});

App.vue

<template>
  <div id="app" class="app">
    <div class="heard" id="heard">
      <h1>部门统计</h1>
    </div>
    <div id="main">
    <div id="Statistics">
      <div id="heard3">
        <h4>统计项</h4>
      </div>
      <el-col :span="12" class="left" style="width: 100%">
        <el-menu
          class="el-menu-vertical-demo"
          background-color="#545c63"
          text-color="#fff"
          :default-openeds="defaultOpen"
          @open="handleOpen"
          active-text-color="#ffd04b">
          <el-submenu index="1" @click.native="bugs()">
            <template slot="title">
              <i class="el-icon-info"></i>
              <span>BUG排行榜</span>
            </template>
            <transition
              appear
              appear-active-class="animated flash"
              name="submenu1-transition"
              enter-active-class="animated fadeInLeftBig"
            >
            <el-menu-item-group v-if="showBugs">
              <template v-for="user in bugsData">
                <el-menu-item align="center" @click="timeOutBugs(user._id)">
                  <p >{{user._id}} 累计: {{user._sum}}</p>
                </el-menu-item>
              </template>
            </el-menu-item-group>
            </transition>
          </el-submenu>
          <el-submenu index="2" @click.native="ideas" >
            <template slot="title">
              <i class="el-icon-info"></i>
              <span>IDEAS排行榜</span>
            </template>
            <transition
              appear
              appear-active-class="animated flash"
              name="submenu2-transition"
              enter-active-class="animated fadeInLeftBig"
            >
            <el-menu-item-group v-if="showIdeas">
              <template v-for="user in ideasData">
                <el-menu-item align="center" @click.native="timeOutIseas(user._id)">
                  <p>{{user._id}} 累计: {{user._sum}}</p>
                </el-menu-item>
              </template>
            </el-menu-item-group>
            </transition>
          </el-submenu>
        </el-menu>
      </el-col>
    </div>
    <div id="table" class="table">
      <div id="heard2">
        <h4>{{title}}</h4>
      </div>
      <div id="add1" v-if="add1">
        <el-button type="primary" icon="el-icon-plus" round @click="insertBugInfor()">BUG</el-button>
      </div>
      <div id="add2" v-if="add2">
        <el-button type="primary" icon="el-icon-plus" round @click="insertIdeasInfor()">IDEAS</el-button>
      </div>
      <transition
        appear
        appear-active-class="animated bounce"
        name="table1-transition"
        enter-active-class="animated fadeInDown"
      >
      <el-table :data="tableData.slice((currentPage-1)*pagesize,currentPage*pagesize)"
                empty-text="暂时没有数据............."
                style="width: 100%"
                :cell-style="changeCellStyle"
                v-loading="loading"
                v-if="showBugs">
        <el-table-column min-width="60px" prop="create_date" label="日期" align="center" :formatter="dateFormat"></el-table-column>
        <el-table-column min-width="40px" prop="name" label="姓名" align="center"></el-table-column>
        <el-table-column min-width="40px" prop="project_name" label="项目" align="center"></el-table-column>
        <el-table-column min-width="100px" prop="desc" label="描述"></el-table-column>
        <el-table-column
          label="操作"
          align="center"
          min-width="60px">
          <template slot-scope="scope">
            <el-button type="danger" size="mini" @click="deleteBugInfor(scope.row['desc'])" icon="el-icon-delete"></el-button>
          </template>
        </el-table-column>
      </el-table>
      </transition>
      <transition
        appear
        appear-active-class="animated bounce"
        name="table2-transition"
        enter-active-class="animated fadeInUp"
      >
      <el-table :data="tableData.slice((currentPage-1)*pagesize,currentPage*pagesize)"
                empty-text="暂时没有数据............."
                style="width: 100%"
                :cell-style="changeCellStyle"
                v-if="showIdeas">
        <el-table-column min-width="60px" prop="create_date" label="日期" align="center" :formatter="dateFormat"></el-table-column>
        <el-table-column min-width="40px" prop="name" label="姓名" align="center"></el-table-column>
        <el-table-column min-width="40px" prop="project_name" label="项目" align="center"></el-table-column>
        <el-table-column min-width="100px" prop="desc" label="描述"></el-table-column>
        <el-table-column
          label="操作"
          align="center"
          min-width="60px">
          <template slot-scope="scope">
            <el-button type="danger" size="mini" @click="deleteIdeasInfor(scope.row['desc'])" icon="el-icon-delete"></el-button>
          </template>
        </el-table-column>
      </el-table>
      </transition>
      <div id="pagination1" class="pagination1" v-if="fenye1">
        <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="currentPage"
          :page-sizes="[5, 10, 20, 40]"
          :page-size="pagesize"
          layout="total, sizes, prev, pager, next"
          :total="tableData.length"
          :pager-count="5">
        </el-pagination>
      </div>
      <div id="pagination2" class="pagination2" v-if="fenye2">
        <el-pagination
          @size-change="handleSizeChange"
          @current-change="handleCurrentChange"
          :current-page="currentPage"
          :page-sizes="[5, 10, 20, 40]"
          :page-size="10"
          layout="total, sizes, prev, next"
          :total="tableData.length">
        </el-pagination>
      </div>
    </div>
    <!--添加数据-->
    <el-dialog title="添加数据" :visible.sync="insertFormVisible" class="addArea" modal custom-class="insertFormArea" @close="closeInsert('insertForm')">
      <el-form :model="insertForm" class="insertForm" :rules="rules" status-icon ref="insertForm">
        <el-form-item label="姓名:"  prop="name">
          <el-input v-model="insertForm.name" auto-complete="off" placeholder="请输入姓名"></el-input>
        </el-form-item>
        <el-form-item label="项目:"  prop="project_name">
          <el-input v-model="insertForm.project_name" auto-complete="off" placeholder="请输入项目名"></el-input>
        </el-form-item>
        <el-form-item label="描述:"  prop="desc">
          <el-input v-model="insertForm.desc" auto-complete="off" placeholder="请输入描述"></el-input>
        </el-form-item>
      </el-form>
      <div slot="footer" class="dialog-footer">
        <el-button @click="insertFormVisible = false">取 消</el-button>
        <el-button type="primary" @click="insertSure('insertForm')">提交</el-button>
      </div>
    </el-dialog>
    </div>
  </div>
</template>

<script>
import axios from 'axios';
import moment from 'moment';
export default {
	name: 'App2',
	data () {
		return {
			message: 'index.html',
			tableData: [],
			bugsData: [],
			title: '详情',
			ideasData: [],
			loading: true,
			showBugs: true,
			showIdeas: false,
			// eslint-disable-next-line vue/no-reserved-keys
			_id: '',
			url: 'bugs',
			flag: 1,
			add1: true,
			add2: false,
			defaultOpen: ['1'],
			currentPage: 1, //默认显示页面为1
			pagesize: 10, //每页的数据条数
			insertFormVisible: false,
			insertForm: {
				project_name: '',
				desc: '',
				name: '',
				screenWidth: window.innerHeight,
			},
			fenye1: true,
			fenye2: false,
			screenWidth: 0,
			rules: {
				name: [{ required: true, message: '请输入姓名', trigger: 'blur' }],
				project_name: [{ required: true, message: '请输入项目名', trigger: 'blur' }],
				desc: [{ required: true, message: '请输入描述', trigger: 'blur' }]
			}
		};
	},
	methods: {
		dateFormat:function(row, column) {
			const date = row[column.property];
			if (date == undefined) {
				return '';
			}
			return moment(date).format('YYYY-MM-DD HH:mm:ss');
		},
		handleSizeChange: function(size) {
			this.pagesize = size;
		},
		//点击第几页
		handleCurrentChange: function(currentPage) {
			this.currentPage = currentPage;
		},
		changeCellStyle({rowIndex}) {
			//第八列添加 red 类
			if(rowIndex%2 === 1){
				return 'backgroundColor: #FFFFEE';
			}
		},
		ideas: function () {
			this.flag=2;
			this.title = 'IDEAS详情';
			axios.get('http://localhost:3000/api/ideas/find').then((res)=>{
				this.tableData = (res.data);
				console.log(this.tableData);
			}).catch((err)=>{
				console.log(err);
			});
			this.showBugs = false;
			this.showIdeas = true;
			this.loading = false;
			this.add2 = true;
			this.add1 = false;
			this.ideasNum();
		},
		bugs: function () {
			this.flag=1;
			this.title = 'BUG详情';
			axios.get('http://localhost:3000/api/bugs/find').then((res)=>{
				this.tableData = (res.data);
				console.log(this.tableData);
				console.log();
			}).catch((err)=>{
				console.log(err);
			});
			this.showBugs = true;
			this.showIdeas = false;
			this.loading =false;
			this.add1 = true;
			this.add2 = false;
			this.bugNum();
		},
		bugNum: function () {
			axios.get('http://localhost:3000/api/bugs/find_group').then((res)=>{
				this.bugsData = (res.data);
				console.log(this.bugsData);
			}).catch((err)=>{
				console.log(err);
			});
		},
		ideasNum: function () {
			axios.get('http://localhost:3000/api/ideas/find_group').then((res)=>{
				this.ideasData = (res.data);
				console.log(this.ideasData);
			}).catch((err)=>{
				console.log(err);
			});
		},
		//展开当前一级菜单,关闭其他的菜单
		handleOpen: function(key) {
			//当前打开的sub-menu的 key 数组
			this.defaultOpen = [key];
			console.log(this.defaultOpen);
		},
		selfBugsInfor: function (name) {
			let params = {
				name: name,
			};
			this.flag = 2;
			this.title = name+'的BUG详情';
			axios.post('http://localhost:3000/api/bugs/findSelf', params).then((res)=>{
				this.tableData = (res.data);
				console.log(res.data);
			}).catch((err)=>{
				console.log(err);
			});
		},
		selfIdeasInfor: function (name) {
			let params = {
				name: name,
			};
			this.flag = 2;
			this.title = name+'的IDEAS详情';
			axios.post('http://localhost:3000/api/ideas/findSelf', params).then((res)=>{
				this.tableData = (res.data);
				console.log(res.data);
			}).catch((err)=>{
				console.log(err);
			});
		},
		timeOutBugs: function (name) {
			const that = this;
			setTimeout(() =>{that.selfBugsInfor(name);},30);
		},
		timeOutIseas: function (name) {
			const that = this;
			setTimeout(() =>{that.selfIdeasInfor(name);},30);
		},
		insertBugInfor: function () {
			this.insertFormVisible = true;
		},
		insertIdeasInfor: function () {
			// eslint-disable-next-line no-mixed-spaces-and-tabs
		  this.insertFormVisible = true;
		},
		deleteBugInfor: function (desc) {
			this.$confirm('此操作永久删除该数据,是否继续?', '提示',{
				confirmButtonText: '确定',
				cancelButtonText: '取消',
				type: 'warning'
			}).then(() => {
				let params = {
					desc: desc,
				};
				this.showBugs = true;
				this.showIdeas = false;
				this.loading = false;
				this.currentPage = 1;
				axios.post('http://localhost:3000/api/bugs/delete', params).then((res) => {
					if (res.data) {
						alert('删除成功!');
					}
					this.bugs();
					this.bugNum();
				}).catch((err) => {
					console.log(err);
					alert('删除失败!');
				});
			});
		},
		deleteIdeasInfor: function (desc) {
			this.$confirm('此操作永久删除该数据,是否继续?', '提示',{
				confirmButtonText: '确定',
				cancelButtonText: '取消',
				type: 'warning'
			}).then(() => {
				let params = {
					desc: desc,
				};
				this.showBugs = false;
				this.showIdeas = true;
				this.loading = false;
				this.currentPage = 1;
				axios.post('http://localhost:3000/api/ideas/delete', params).then((res) => {
					if (res.data) {
						alert('删除成功!');
					}
					this.ideas();
					this.ideasNum();
				}).catch((err) => {
					console.log(err);
					alert('删除失败!');
				});
			});
		},
		insertSure: function () {
			console.log(this.insertForm);
			if(this.add1) {
				this.url = 'bugs';
			}
			if(this.add2) {
				this.url = 'ideas';
			}
			if(this.insertForm === '' || this.insertForm.project_name === '' || this.insertForm.desc === ''){
				alert('添加失败!输入不能为空!');
				return;
			}
			axios.post('http://localhost:3000/api/'+this.url+'/insert',this.insertForm).then((res)=>{
				if(res.data){
					alert('添加成功!');
				}
				this.insertFormVisible = false;
				if(this.add1) {
					this.bugs();
					this.bugNum();
				}
				if(this.add2) {
					this.ideas();
					this.ideasNum();
				}
				this.insertForm.desc = '';
				this.insertForm.name = '';
				this.insertForm.project_name = '';
			}).catch((err)=>{
				console.log(err);
				alert('添加失败!');
			});
		},
		closeInsert: function(formName) {
			this.$refs[formName].resetFields();
		},
	},
	mounted () {
		const that = this;
		that.screenWidth = `${document.documentElement.clientWidth}`;
		if(that.screenWidth >= 1036 ) {
			that.fenye1 = true;
			that.fenye2 = false;
			console.log(that.fenye2);
		}else {
			that.fenye1 = false;
			that.fenye2 = true;
		}
		window.onresize = function temp() {
			that.screenWidth = `${document.documentElement.clientWidth}`;
			if(that.screenWidth >= 1036 ) {
				that.fenye1 = true;
				that.fenye2 = false;
				console.log(that.fenye2);
			}else {
				that.fenye1 = false;
				that.fenye2 = true;
			}
		};
		axios.get('http://localhost:3000/api/bugs/find').then((res)=>{
			this.tableData = (res.data);
			this.loading = false;
			this.title = 'BUG详情';
			console.log(this.tableData);
		}).catch((err)=>{
			console.log(err);
		});
		axios.get('http://localhost:3000/api/bugs/find_group').then((res)=>{
			this.bugsData = (res.data);
			console.log(this.bugsData);
		}).catch((err)=>{
			console.log(err);
		});
		axios.get('http://localhost:3000/api/ideas/find_group').then((res)=>{
			this.ideasData = (res.data);
			console.log(this.ideasData);
		}).catch((err)=>{
			console.log(err);
		});
	},
};
</script>

<style>
  @media screen and (min-width:1050px) {
    #heard {
      width: 100%;
      height: 80px;
      margin: 0px auto;
    }
    #main {
      width: 100%;
      margin: 10px auto;
      height: 780px;
    }
    #Statistics {
      width: 22%;
      height: 780px;
      float: left;
      margin-left:30px;
    }
    #table {
      width: 65%;
      height: 780px;
      float: right;
      margin-right:30px;
    }
    .pagination1 {
      float: right;
    }
    .pagination2 {
      float: right;
    }
    #heard2{
      float:left;
    }
    #add1{
      float: right;
      margin-top: 20px;
    }
    #add2{
      float: right;
      margin-top: 20px;
    }
  }
  @media screen and (max-width:1050px) {
    #heard {
      width: 100%;
      height: 9%;
    }
    #main {
      width: 100%;
      height: 200%;
    }
    #Statistics {
      width: 100%;
      height: 100%;
      float: top;
    }
    #table {
      width: 100%;
      height: 100%;
      float: bottom;
    }
    .pagination1 {
      float: right;
    }
    .pagination2 {
      float: right;
    }
    #heard2 {
      float:left;
    }
    #add1 {
      float: right;
      margin-top: 10px;
    }
    #add2 {
      float: right;
      margin-top: 10px;
    }
  }
</style>

api.js

// eslint-disable-next-line no-undef
const bugs = require('../model/bugs').bugs;
// eslint-disable-next-line no-undef
const ideas = require('../model/ideas').ideas;
// eslint-disable-next-line no-undef
const express = require('express');
const router = express.Router();
// eslint-disable-next-line no-undef
const send = require('../../config/send');

// eslint-disable-next-line no-undef
const mongoose = require('mongoose');

const date = Date.now();

router.get('/api/bugs/find', (function (req, res) {
	bugs.aggregate([{$sort: {create_date: -1}}] , function (err, results) {
		send(err,res,results);
	});
}));

router.post('/api/bugs/findSelf', (function (req, res) {
	bugs.aggregate([{$match: {'name': req.body.name}},{$sort: {create_date: -1}}] , function (err, results) {
		send(err,res,results);
	});
}));

router.get('/api/bugs/find_group', (function (req, res) {
	bugs.aggregate([{$group : {_id: '$name', _sum: {$sum : 1}}},{$sort: {_sum:-1}}] , function (err, results) {
		send(err,res,results);
	});
}));

router.post('/api/bugs/insert', (function (req, res) {
	bugs.create({'_id': mongoose.Types.ObjectId(), 'desc': req.body.desc, 'name': req.body.name, 'project_name': req.body.project_name, 'create_date': date}, function (err,results) {
		send(err,res,results);
	});
}));

router.post('/api/bugs/delete', (function (req, res) {
	bugs.deleteOne({'desc': req.body.desc}, function (err,results) {
		send(err,res,results);
	});
}));

router.get('/api/ideas/find', (function (req, res) {
	ideas.aggregate([{$sort: {create_date: -1}}] , function (err, results) {
		send(err,res,results);
	});
}));

router.post('/api/ideas/findSelf', (function (req, res) {
	ideas.aggregate([{$match: {'name': req.body.name}},{$sort: {create_date: -1}}] , function (err, results) {
		send(err,res,results);
	});
}));

router.get('/api/ideas/find_group', (function (req, res) {
	ideas.aggregate([{$group : {_id: '$name', _sum: {$sum : 1}}},{$sort: {_sum:-1}}] , function (err, results) {
		send(err,res,results);
	});
}));

router.post('/api/ideas/insert', (function (req, res) {
	ideas.create({'_id': mongoose.Types.ObjectId(), 'desc': req.body.desc, 'name': req.body.name, 'project_name': req.body.project_name, 'create_date': date}, function (err,results) {
		send(err,res,results);
	});
}));

router.post('/api/ideas/delete', (function (req, res) {
	ideas.deleteOne({'desc': req.body.desc}, function (err,results) {
		send(err,res,results);
	});
}));

// eslint-disable-next-line no-undef
module.exports = router;

db.js

// eslint-disable-next-line no-undef
const mongoose = require('mongoose');

function conn() {
	mongoose.connect('mongodb://xxxx:cE8ab5d9sdsdfefdfwefR3yRY94U@xxxxx-dev.xxxxxxx.com:000008/xxxxxxx', {useNewUrlParser:true});
	const message = mongoose.connection;
	message.once('error', () => console.log('Mongo connection error'));
	message.once('open', () => console.log('Mongo connection successed'));
}

// eslint-disable-next-line no-undef
module.exports = conn;

_index.js

扫描目录下的model,一个model对应数据库一个表

'use strict';

// eslint-disable-next-line no-undef
const requireDirectory = require('require-directory');

// eslint-disable-next-line no-undef
module.exports = requireDirectory(module, './');

bugs.js

// eslint-disable-next-line no-undef
const mongoose = require('mongoose');
// eslint-disable-next-line no-undef
const connect = require('../../config/db');

connect();

const model = mongoose.Schema({
	_id: String,
	name: String,
	desc: String,
	project_name: String,
	create_date: Number
},{versionKey: false});

const Models = {
	bugs: mongoose.model('bugs', model),
};

// eslint-disable-next-line no-undef
module.exports = Models;

ideas.js

// eslint-disable-next-line no-undef
const mongoose = require('mongoose');
// eslint-disable-next-line no-undef
const connect = require('../../config/db');

connect();

const model = mongoose.Schema({
	_id: String,
	name: String,
	desc: String,
	project_name: String,
	create_date: Number
},{versionKey: false});

const Models = {
	ideas: mongoose.model('ideas', model),
};

// eslint-disable-next-line no-undef
module.exports = Models;

send.js

function send(err,res,results) {
	if(err){
		console.log('Error:' + err);
		res.send(err);
	}else{
		res.header('Access-Control-Allow-Origin', '*');
		res.send(results);
	}
}

// eslint-disable-next-line no-undef
module.exports = send;

运行结果

网页正常比例
在这里插入图片描述
移动端,适配至iphone5(320*568)
在这里插入图片描述
在这里插入图片描述
插入功能
在这里插入图片描述
删除功能
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值