13 大改动 数据分析+注册

master
markma 3 years ago
parent e9e2877b95
commit 98bd86ca71

934
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -8,12 +8,18 @@
},
"dependencies": {
"core-js": "^3.6.5",
"echart": "^0.1.3",
"echarts": "^4.8.0",
"element-ui": "^2.15.6",
"exceljs": "^4.3.0",
"file-saver": "^2.0.5",
"live2d-widget": "^3.1.4",
"v-charts": "^1.19.0",
"vue": "^2.6.11",
"vue-router": "^3.2.0",
"vuex": "^3.4.0",
"xlsx": "^0.18.4"
"xlsx": "^0.18.4",
"zrender": "^4.3.1"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",

@ -16,6 +16,7 @@ export default {
getCookie,
delCookie
}
}
},
}
</script>
</script>

@ -4,7 +4,9 @@ import App from './App.vue'
import router from './router'
import store from './store'
import './plugins/element.js'
import VCharts from 'v-charts'
Vue.use(VCharts)
Vue.config.productionTip = false
new Vue({

@ -15,7 +15,9 @@ import OuterAppDetail from "../views/OuterAppDetail";
import NoAuthority from "../views/NoAuthority";
import SetComment from "../views/SetComment"
import GetComment from "../views/GetComment"
import ImportData from "../views/ImportData";
import DataAnalysis from "../views/DataAnalysis";
import StudentAnalysis from "../views/StudentAnalysis";
Vue.use(VueRouter)
@ -50,6 +52,11 @@ const routes = [
path: "/user/student/:id/setComment",
name: "匿名评论",
component: SetComment
},
{
path: "/user/student/:id/studentAnalysis",
name: "学生请假数据分析",
component: StudentAnalysis
}
]
},
@ -103,9 +110,9 @@ const routes = [
component: GetComment
},
{
path: "/user/outer/:id/importData",
name: "导入用户信息",
component: ImportData
path: "/user/outer/:id/dataAnalysis/",
name: "请假数据分析",
component: DataAnalysis
}
]
},

@ -0,0 +1,190 @@
<template>
<div>
<h4 style="text-align: center">整体分析</h4>
<el-container>
<div style="width: 45%">
<ve-line :data="chartData_H" :extend="chartExtend_H" height="400px"></ve-line>
</div>
<div style="width: 45%">
<ve-line :data="chartData_D" :extend="chartExtend_D" height="400px"></ve-line>
</div>
</el-container>
<h4 style="text-align: center">具体用户分析</h4>
<el-table
ref="multipleTable"
:data="tableData"
:default-sort="{prop: 'date', order: 'descending'}"
border
stripe
style="width: 90%">
<el-table-column
type="selection">
</el-table-column>
<el-table-column
fixed
label="用户编号"
prop="id"
sortable
width="100">
</el-table-column>
<el-table-column
label="用户名"
prop="username"
sortable
width="200">
</el-table-column>
<el-table-column
label="密码"
prop="password"
sortable
width="200">
</el-table-column>
<el-table-column
label="学号"
prop="school_id"
sortable
width="200">
</el-table-column>
<el-table-column
label="姓名"
prop="name"
sortable
width="150">
</el-table-column>
<el-table-column>
<template slot-scope="scope">
<el-button type="text" @click="dataAnalysis(scope.row)"></el-button>
</template>
</el-table-column>
</el-table>
<one-stu-chart ref="onestuchart"></one-stu-chart>
<el-pagination
:page-size="pageSize"
:total="total"
background
layout="prev, pager, next"
@current-change="page">
</el-pagination>
</div>
</template>
<script>
import OneStuChart from "./OneStuChart";
export default {
name: 'DataAnalysis',
components: {OneStuChart},
data() {
this.chartExtend_H = {
title: {
text: '外出时间段情况',
x: 'middle', //x left, right, middle
y: 'bottom', //y top, bottom
textAlign: 'center' // text subtext auto, left, right, center
},
};
this.chartExtend_D = {
title: {
text: '本月外出情况',
x: 'middle', //x left, right, middle
y: 'bottom', //y top, bottom
textAlign: 'center' // text subtext auto, left, right, center
},
};
return {
chartData_H: {
columns: ["小时", "预计离开次数", "预计返回次数", "实际离开次数", "实际返回次数"],
rows: []
},
chartData_D: {
columns: ["日期", "预计离开人数", "预计返回人数", "实际离开人数", "实际返回人数"],
rows: []
},
pageSize: 20,
total: 11,
tableData: [{
id: 1,
username: 'markma',
password: '123',
school_id: '123456',
name: '马铁诚'
}]
}
},
methods: {
page(currentPage) {
const _this = this
let id = window.location.pathname.split('/')[3];
axios.get('http://localhost:8181/userDetail/findAllStudentUserPaged/' + (currentPage) + '/20').then(function (resp) {
_this.tableData = resp.data
_this.pageSize = 20
})
axios.get('http://localhost:8181/userDetail/findAllStudentUserNum').then(function (resp) {
_this.total = resp.data
})
},
dataAnalysis(row) {
console.log(row)
this.$refs.onestuchart.dialogFormVisible = true
this.$refs.onestuchart.student_id = row.id
this.$refs['onestuchart'].loadData()
},
toggleSelection(rows) {
if (rows) {
rows.forEach(row => {
this.$refs.multipleTable.toggleRowSelection(row);
});
} else {
this.$refs.multipleTable.clearSelection();
}
},
handleSelectionChange(val) {
this.multipleSelection = val;
},
},
created() {
const _this = this
let id = window.location.pathname.split('/')[3];
let type = window.location.pathname.split('/')[2];
axios.get('http://localhost:8181/user/checkUseridAndType/' + id + '/' + type).then(function (resp) {
if (resp.data != 'success') {
_this.$router.push("/NoAuthority")
} else {
let login_id = _this.$cookieStore.getCookie("login_id")
console.log(login_id)
if (login_id != id) {
_this.$router.push("/NoAuthority")
}
}
})
axios.get('http://localhost:8181/userDetail/findAllStudentUserPaged/1/20').then(function (resp) {
_this.tableData = resp.data
_this.pageSize = 20
})
axios.get('http://localhost:8181/userDetail/findAllStudentUserNum').then(function (resp) {
_this.total = resp.data
})
axios.get('http://localhost:8181/dataAnalysis/DATime/*/H').then(function (resp) {
_this.chartData_H.rows = resp.data;
})
axios.get('http://localhost:8181/dataAnalysis/DATime/*/D').then(function (resp) {
_this.chartData_D.rows = resp.data;
})
}
}
</script>
<style scoped>
.el-header {
background-color: #1F5DEA;
color: white;
text-align: center;
line-height: 60px;
font-size: 24px;
}
</style>

@ -1,43 +0,0 @@
<template>
<div>
<p>上传用户信息文件须符合模版格式</p>
<el-upload
action="http://localhost:8181/userDetail/import/"
class="upload-demo"
drag
multiple>
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处<em>点击上传</em></div>
<div slot="tip" class="el-upload__tip">只能上传xlsx文件</div>
</el-upload>
</div>
</template>
<script>
export default {
name: "ImportData",
data() {
return {};
},
methods: {},
created() {
const _this = this
let id = window.location.pathname.split('/')[3];
let type = window.location.pathname.split('/')[2];
axios.get('http://localhost:8181/user/checkUseridAndType/' + id + '/' + type).then(function (resp) {
if (resp.data != 'success') {
_this.$router.push("/NoAuthority")
} else {
let login_id = _this.$cookieStore.getCookie("login_id")
if (login_id != id) {
_this.$router.push("/NoAuthority")
}
}
})
}
}
</script>
<style scoped>
</style>

@ -18,20 +18,53 @@
</el-carousel>
</el-col>
<el-col :span="12">
<el-form ref="ruleForm" :model="ruleForm" :rules="rules" class="login-box" label-width="80px" status-icon>
<h4 align="center" class="login-title">欢迎来到国防科大请销假系统</h4>
<el-form-item label="账号" maxlength="255" prop="username">
<el-input v-model="ruleForm.username"></el-input>
</el-form-item>
<el-form-item label="密码" maxlength="64" prop="password">
<el-input v-model="ruleForm.password" autocomplete="off" type="password"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')"></el-button>
<el-button @click="resetForm('ruleForm')"></el-button>
</el-form-item>
</el-form>
<div v-if="login_type === 'login'">
<el-form ref="ruleForm" :model="ruleForm" :rules="rules" class="login-box" label-width="80px" status-icon>
<h4 align="center" class="login-title">欢迎来到国防科大请销假系统</h4>
<el-form-item label="账号" maxlength="255" prop="username">
<el-input v-model="ruleForm.username"></el-input>
</el-form-item>
<el-form-item label="密码" maxlength="64" prop="password">
<el-input v-model="ruleForm.password" autocomplete="off" type="password"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm')"></el-button>
<el-button @click="setLoginType('register')"></el-button>
<el-button @click="resetForm('ruleForm')"></el-button>
</el-form-item>
</el-form>
</div>
<div v-else>
<el-form ref="ruleForm_register" :model="ruleForm_register" :rules="rules_register" class="register-box"
label-width="80px" status-icon>
<h4 align="center" class="login-title">欢迎来到国防科大请销假系统</h4>
<el-form-item label="账号" maxlength="255" prop="username">
<el-input v-model="ruleForm_register.username"></el-input>
</el-form-item>
<el-form-item label="密码" maxlength="64" prop="password">
<el-input v-model="ruleForm_register.password" autocomplete="off" type="password"></el-input>
</el-form-item>
<el-form-item label="确认密码" maxlength="64" prop="check_password">
<el-input v-model="ruleForm_register.check_password" autocomplete="off" type="password"></el-input>
</el-form-item>
<el-form-item label="真实姓名" maxlength="20" prop="name">
<el-input v-model="ruleForm_register.name"></el-input>
</el-form-item>
<el-form-item label="学号" maxlength="64" prop="school_id">
<el-input v-model="ruleForm_register.school_id"></el-input>
</el-form-item>
<el-radio v-model="ruleForm_register.type" label="student"></el-radio>
<el-radio v-model="ruleForm_register.type" label="teacher"></el-radio>
<el-radio v-model="ruleForm_register.type" label="outer"></el-radio>
<p></p>
<el-form-item style="text-align: left">
<el-button type="primary" @click="submitFormRegister()"></el-button>
<el-button @click="setLoginType('login')"></el-button>
<el-button @click="resetForm('ruleForm_register')"></el-button>
</el-form-item>
</el-form>
</div>
</el-col>
</el-row>
@ -39,9 +72,13 @@
</div>
</template>
<script>
import {L2Dwidget} from 'live2d-widget'
export default {
data() {
return {
login_type: "login",
ruleForm: {
username: '',
password: '',
@ -54,6 +91,32 @@ export default {
{required: true, message: '请输入密码', trigger: 'blur'}
],
},
ruleForm_register: {
username: '',
password: '',
check_password: '',
type: '',
name: '',
school_id: '',
email: ''
},
rules_register: {
username: [
{required: true, message: '请输入账号', trigger: 'blur'}
],
password: [
{required: true, message: '请输入密码', trigger: 'blur'}
],
check_password: [
{required: true, message: '请确认密码', trigger: 'blur'}
],
name: [
{required: true, message: '请输入姓名', trigger: 'blur'}
],
school_id: [
{required: true, message: '请输入学校id', trigger: 'blur'}
],
},
pictures: [
'https://www.nudt.edu.cn/images/2020-09/315f04ae3e4e4e488db721ba151f0fcc.jpg',
'https://www.nudt.edu.cn/images/2020-09/a41b098679a047bba53623f64958a4c2.jpg',
@ -94,9 +157,61 @@ export default {
);
},
resetForm(formName) {
console.log(this.$refs)
this.$refs[formName].resetFields();
},
setLoginType(type) {
this.login_type = type;
},
submitFormRegister() {
const _this = this
if (this.ruleForm_register.type === '') {
this.$message({
message: '请填写您的职业!',
type: 'warning'
});
return false;
}
if (this.ruleForm_register.password !== this.ruleForm_register.check_password) {
this.$message({
message: '两次密码不一致!',
type: 'warning'
});
return false;
}
axios.get('http://localhost:8181/userDetail/checkValuable/' + this.ruleForm_register.username + '/' + this.ruleForm_register.school_id + '/' + this.ruleForm_register.name).then(function (resp) {
if (resp.data !== 'success') {
_this.$message.error(resp.data + '重复,请登录!');
return false;
}
})
axios.post('http://localhost:8181/userDetail/saveUAD', _this.ruleForm_register).then(function (resp) {
if (resp.data === 'success') {
_this.$message({
message: '保存成功,已提交到管理员,请等待管理员批准',
type: 'success'
})
} else {
_this.$message.error('保存失败')
}
})
}
},
created() {
setTimeout(function () {
L2Dwidget.init({
model: {
jsonPath: 'https://cdn.jsdelivr.net/gh/wangsrGit119/wangsr-image-bucket/L2Dwidget/live2d-widget-model-miku/assets/miku.model.json',
},
display: {
width: 150,
height: 350,
}
});
}, 1000);
}
}
</script>
@ -143,6 +258,17 @@ export default {
margin: 110px 190px;
}
.register-box {
border: 1px solid #DCDFE6;
width: 350px;
margin: 110px 0px;
padding: 35px 35px 15px 35px;
border-radius: 5px;
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
box-shadow: 0 0 25px #909399;
}
.el-carousel__item:nth-child(2n) {
background-color: #99a9bf;
}

@ -0,0 +1,62 @@
<template>
<el-dialog :visible.sync="dialogFormVisible" @close="closeDialog">
<div>
<ve-line :data="chartData_H" :extend="chartExtend_H" height="400px"></ve-line>
<ve-line :data="chartData_D" :extend="chartExtend_D" height="400px"></ve-line>
</div>
</el-dialog>
</template>
<script>
export default {
name: "oneStuChart",
data() {
this.chartExtend_H = {
title: {
text: '外出时间段情况',
x: 'middle', //x left, right, middle
y: 'bottom', //y top, bottom
textAlign: 'center' // text subtext auto, left, right, center
},
};
this.chartExtend_D = {
title: {
text: '本月外出情况',
x: 'middle', //x left, right, middle
y: 'bottom', //y top, bottom
textAlign: 'center' // text subtext auto, left, right, center
},
};
return {
student_id: '',
dialogFormVisible: false,
chartData_H: {
columns: ["小时", "预计离开次数", "预计返回次数", "实际离开次数", "实际返回次数"],
rows: []
},
chartData_D: {
columns: ["日期", "预计离开人数", "预计返回人数", "实际离开人数", "实际返回人数"],
rows: []
},
}
},
methods: {
loadData() {
const _this = this
axios.get('http://localhost:8181/dataAnalysis/DATime/' + _this.student_id + '/H').then(function (resp) {
_this.chartData_H.rows = resp.data;
})
axios.get('http://localhost:8181/dataAnalysis/DATime/' + _this.student_id + '/D').then(function (resp) {
_this.chartData_D.rows = resp.data;
})
},
closeDialog() {
this.chartData.rows = []
},
}
}
</script>
<style scoped>
</style>

@ -138,6 +138,7 @@ export default {
_this.pageSize = 20
_this.total = resp.data.length
})
}
}
</script>

@ -10,6 +10,74 @@
<el-button type="primary" @click="submitInForm('ruleForm')"></el-button>
<el-button @click="resetForm('ruleForm')"></el-button>
</el-form-item>
<p>所有学生请假数据详情</p>
<div>
<el-table
:data="tableData"
:default-sort="{prop: 'date', order: 'descending'}"
border
stripe
style="width: 90%">
<el-table-column
fixed
label="编号"
prop="id"
sortable
width="80">
</el-table-column>
<el-table-column
fixed
label="用户id"
prop="userid"
sortable
width="100">
</el-table-column>
<el-table-column
fixed
label="姓名"
prop="name"
sortable
width="100">
</el-table-column>
<el-table-column
label="出发时间"
prop="leave_time"
sortable
width="200">
</el-table-column>
<el-table-column
label="返回时间"
prop="back_time"
sortable
width="200">
</el-table-column>
<el-table-column
label="地点"
prop="place"
sortable
width="150">
</el-table-column>
<el-table-column
label="外出原因"
prop="reason"
sortable
width="200">
</el-table-column>
<el-table-column
label="状态"
prop="type"
sortable>
</el-table-column>
</el-table>
<el-pagination
:page-size="pageSize"
:total="total"
background
layout="prev, pager, next"
@current-change="page">
</el-pagination>
</div>
</el-form>
</template>
@ -18,6 +86,18 @@ export default {
name: "OuterAppForm",
data() {
return {
pageSize: 20,
total: 11,
tableData: [{
id: 1,
name: 'markma',
userid: 1,
leave_time: '2021-12-20 15:59:15',
back_time: '2222-12-21 17:28:59',
place: '万家丽',
reason: '见导师',
type: '已过期'
}],
ruleForm: {
school_id: ''
},
@ -29,14 +109,31 @@ export default {
};
},
methods: {
page(currentPage) {
const _this = this
axios.get('http://localhost:8181/leaveDetail/findAllPaged' + (currentPage) + '/20').then(function (resp) {
console.log(resp)
_this.tableData = resp.data
_this.pageSize = 20
axios.get('http://localhost:8181/leaveDetail/findAllNum').then(function (resp) {
_this.total = resp.data
for (let i = 0; i < _this.tableData.length; i++) {
let user_id = _this.tableData[i].userid
axios.get('http://localhost:8181/leaveDetail/LDUseridToName/' + user_id).then(function (resp) {
_this.tableData[i].name = resp.data
})
}
})
})
},
submitOutForm(formName) {
const _this = this
let id = window.location.pathname.split('/')[3];
let school_id = this.ruleForm.school_id;
console.log(school_id);
window.location.href = "/user/outer/" + id + "/appDetail?school_id=" + school_id;
},
submitInForm(formName) {
const _this = this
@ -76,6 +173,39 @@ export default {
resetForm(formName) {
this.$refs[formName].resetFields();
}
},
created() {
const _this = this
let id = window.location.pathname.split('/')[3];
let type = window.location.pathname.split('/')[2];
axios.get('http://localhost:8181/user/checkUseridAndType/' + id + '/' + type).then(function (resp) {
if (resp.data != 'success') {
_this.$router.push("/NoAuthority")
} else {
let login_id = _this.$cookieStore.getCookie("login_id")
console.log(login_id)
if (login_id != id) {
_this.$router.push("/NoAuthority")
}
}
})
axios.get('http://localhost:8181/leaveDetail/findAllPaged/1/20').then(function (resp) {
_this.tableData = resp.data
for (let i = 0; i < _this.tableData.length; i++) {
let user_id = _this.tableData[i].userid
axios.get('http://localhost:8181/leaveDetail/LDUseridToName/' + user_id).then(function (resp) {
_this.tableData[i].name = resp.data
})
}
_this.pageSize = 20
axios.get('http://localhost:8181/leaveDetail/findAllNum').then(function (resp) {
_this.total = resp.data
})
})
}
}
</script>

@ -18,23 +18,17 @@
<el-dropdown-item command="Comment">所有评论</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-divider direction="vertical"></el-divider>
<el-dropdown @command="importData">
<span class="el-dropdown-link" style="color: #409EFF">导入<i class="el-icon-arrow-down el-icon--right"></i></span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item command="model">下载导入用户信息模版</el-dropdown-item>
<el-dropdown-item command="UAD">导入用户信息</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-divider direction="vertical"></el-divider>
<el-button style="color: red" type="text" @click="quit()">退</el-button>
</div>
<el-container style="height: 500px; border: 1px solid #eee">
<el-aside width="200px" style="background-color: rgb(238, 241, 246)">
<el-menu router>
<el-menu-item index="history">外出批准历史</el-menu-item>
<el-menu-item index="history">实际外出历史</el-menu-item>
<el-menu-item index="appForm">处理外出申请</el-menu-item>
<el-menu-item index="getComment">查看评论</el-menu-item>
<el-menu-item index="dataAnalysis">请假数据分析</el-menu-item>
</el-menu>
</el-aside>
@ -127,22 +121,6 @@ export default {
}
}
},
importData(command) {
if (command === "model") {
let json = []
let columns = [
{title: '用户名', key: 'username'},
{title: '密码', key: 'password'},
{title: '类型(只能是student/teacher/outer)', key: 'type'},
{title: '学号', key: 'school_id'},
{title: '姓名', key: 'name'},
]
export2Excel(columns, json, "导入用户信息模版")
} else if (command === "UAD") {
let id = window.location.pathname.split('/')[3];
window.location.href = "/user/outer/" + id + "/importData";
}
}
},
data() {
return {

@ -1,7 +1,7 @@
<template>
<el-form ref="ruleForm" :model="ruleForm" :rules="rules" class="demo-ruleForm" label-width="100px">
<h4>请在这里写下对本系统的匿名评论</h4>
<h4 style="text-align: center">请在这里写下对本系统的匿名评论</h4>
<el-form-item label="评论" maxlength="255" prop="comment_detail">
<el-input v-model="ruleForm.comment_detail" autosize maxlength="100" show-word-limit type="textarea"></el-input>
</el-form-item>

@ -0,0 +1,75 @@
<template>
<el-container>
<div style="width: 45%">
<ve-line :data="chartData_H" :extend="chartExtend_H" height="400px"></ve-line>
</div>
<div style="width: 45%">
<ve-line :data="chartData_D" :extend="chartExtend_D" height="400px"></ve-line>
</div>
</el-container>
</template>
<script>
import OneStuChart from "./OneStuChart";
export default {
name: "StudentAnalysis",
components: {OneStuChart},
data() {
this.chartExtend_H = {
title: {
text: '外出时间段情况',
x: 'middle', //x left, right, middle
y: 'bottom', //y top, bottom
textAlign: 'center' // text subtext auto, left, right, center
},
};
this.chartExtend_D = {
title: {
text: '本月外出情况',
x: 'middle', //x left, right, middle
y: 'bottom', //y top, bottom
textAlign: 'center' // text subtext auto, left, right, center
},
};
return {
chartData_H: {
columns: ["小时", "预计离开次数", "预计返回次数", "实际离开次数", "实际返回次数"],
rows: []
},
chartData_D: {
columns: ["日期", "预计离开人数", "预计返回人数", "实际离开人数", "实际返回人数"],
rows: []
},
}
},
methods: {},
created() {
const _this = this
let id = window.location.pathname.split('/')[3];
let type = window.location.pathname.split('/')[2];
axios.get('http://localhost:8181/user/checkUseridAndType/' + id + '/' + type).then(function (resp) {
if (resp.data != 'success') {
_this.$router.push("/NoAuthority")
} else {
let login_id = _this.$cookieStore.getCookie("login_id")
console.log(login_id)
if (login_id != id) {
_this.$router.push("/NoAuthority")
}
}
})
axios.get('http://localhost:8181/dataAnalysis/DATime/' + id + '/H').then(function (resp) {
_this.chartData_H.rows = resp.data;
})
axios.get('http://localhost:8181/dataAnalysis/DATime/' + id + '/D').then(function (resp) {
_this.chartData_D.rows = resp.data;
})
}
}
</script>
<style scoped>
</style>

@ -118,14 +118,14 @@ export default {
this.ruleForm.userid = id
axios.post('http://localhost:8181/leaveDetail/save', this.ruleForm).then(function (resp) {
if (resp.data == 'success') {
if (resp.data === 'success') {
_this.$alert('保存成功', '消息', {
confirmButtonText: '确定',
callback: action => {
_this.$router.push('/user/student/' + id + '/history')
}
})
} else if (resp.data == 'time failed') {
} else if (resp.data === 'time failed') {
_this.$alert('时间错误', '消息', {
confirmButtonText: '确定',
})

@ -19,6 +19,7 @@
<el-menu-item index="application">申请记录</el-menu-item>
<el-menu-item index="appForm">填写申请表单</el-menu-item>
<el-menu-item index="setComment">匿名评论</el-menu-item>
<el-menu-item index="studentAnalysis">我的请假数据分析</el-menu-item>
</el-menu>
</el-aside>

File diff suppressed because it is too large Load Diff
Loading…
Cancel
Save