You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
697 lines
28 KiB
697 lines
28 KiB
<template> |
|
<div> |
|
<el-card shadow="hover" class="mgb20"> |
|
<div> |
|
<div class="flex-center mgb20"> |
|
<p class="hr_tag"></p> |
|
<span>学生情况分析</span> |
|
</div> |
|
<div> |
|
<div class="stat"> |
|
<div class="item"> |
|
<div class="chart" id="chart1"></div> |
|
</div> |
|
<div class="item"> |
|
<div class="chart" id="chart2"></div> |
|
</div> |
|
<div class="item"> |
|
<div class="chart" id="chart3"></div> |
|
</div> |
|
</div> |
|
</div> |
|
</div> |
|
</el-card> |
|
|
|
<el-card shadow="hover"> |
|
<div class="flex-between mgb20"> |
|
<div> |
|
<el-button type="primary" size="small" v-auth round @click="addStudent">新增学生</el-button> |
|
<el-button type="primary" size="small" v-auth round @click="batchImport">批量导入</el-button> |
|
<el-button type="primary" size="small" v-auth round @click="delAllSelection">批量删除</el-button> |
|
</div> |
|
<div> |
|
<el-input placeholder="请输入学生姓名/学号/学校名称" prefix-icon="el-icon-search" style="width: 260px" v-model="keyword" clearable></el-input> |
|
</div> |
|
</div> |
|
<el-table :data="studentData" class="table" ref="table" stripe header-align="center" @selection-change="handleSelectionChange" :row-key="getRowKeys"> |
|
<el-table-column type="selection" width="55" align="center" :reserve-selection="true"></el-table-column> |
|
<el-table-column type="index" width="100" label="序号" align="center"> |
|
</el-table-column> |
|
<el-table-column prop="account" label="账号" align="center"> |
|
</el-table-column> |
|
<el-table-column prop="schoolName" label="院校" align="center"></el-table-column> |
|
<el-table-column prop="workNumber" label="学号" align="center"> |
|
</el-table-column> |
|
<el-table-column prop="userName" label="学生姓名" align="center"> |
|
</el-table-column> |
|
<el-table-column prop="className" label="班级" align="center"></el-table-column> |
|
<el-table-column prop="countries" label="账号角色" align="center"> |
|
<template slot-scope="scope"> |
|
{{roleStatus(scope.row.roleId)}} |
|
</template> |
|
</el-table-column> |
|
<el-table-column prop="loginNumber" label="登录次数" align="center"> |
|
</el-table-column> |
|
<el-table-column prop="lastLoginTime" label="上次登录时间" align="center"> |
|
</el-table-column> |
|
<el-table-column label="操作" align="center" width="300"> |
|
<template slot-scope="scope"> |
|
<el-button type="text" v-auth @click="editStudent(scope.row,true)">查看</el-button> |
|
<el-button type="text" v-auth @click="editStudent(scope.row,false)">编辑</el-button> |
|
<el-button type="text" v-auth @click="resetPassword(scope.row)">重置密码</el-button> |
|
<el-button type="text" v-auth @click="handleDelete(scope.row)">删除</el-button> |
|
<el-switch |
|
v-model="scope.row.disableAccount" |
|
:active-value="0" |
|
:inactive-value="1" |
|
style="margin: 0 5px" |
|
@change="switchOff($event,scope.row,scope.$index)" |
|
v-auth="'学生管理:禁用'" |
|
></el-switch> |
|
</template> |
|
</el-table-column> |
|
</el-table> |
|
<div class="pagination"> |
|
<el-pagination background @current-change="currentChange" :current-page="pageNo" layout="total, prev, pager, next" :total="totals"> |
|
</el-pagination> |
|
</div> |
|
</el-card> |
|
|
|
<el-dialog :title="isDetail ? '查看学生' : (isAdd ? '新增学生' : '编辑学生')" :visible.sync="studentVisible" |
|
width="30%" center @close="closeStudent" class="dialog" :close-on-click-modal="false"> |
|
<el-form ref="form" :model="form" :rules="rules" :disabled="isDetail" label-width="100px"> |
|
<el-form-item prop="account" label="账号"> |
|
<el-input v-model="form.account" placeholder="请输入学生账号" @change="accountChange"></el-input> |
|
</el-form-item> |
|
<el-form-item prop="userName" label="学生姓名"> |
|
<el-input v-model="form.userName" placeholder="请输入学生姓名"></el-input> |
|
</el-form-item> |
|
<el-form-item prop="roleId" label="账号角色"> |
|
学生 |
|
</el-form-item> |
|
<el-form-item prop="workNumber" label="学生学号"> |
|
<el-input v-model="form.workNumber" placeholder="" @change="worknumberChange"></el-input> |
|
</el-form-item> |
|
<el-form-item prop="phone" label="手机号"> |
|
<el-input v-model="form.phone" placeholder="可用于登录平台,以及找回密码" maxlength="11"></el-input> |
|
</el-form-item> |
|
<el-form-item prop="email" label="邮箱"> |
|
<el-input v-model="form.email" placeholder="可用于登录平台,以及找回密码"></el-input> |
|
</el-form-item> |
|
<el-form-item prop="schoolAppellationId" label="所在院校"> |
|
<el-select v-model="form.schoolAppellationId" placeholder="默认为当前院校(可修改)" filterable @change="worknumberChange"> |
|
<el-option v-for="(item,index) in schoolList" :key="index" :label="item.schoolName" :value="item.schoolId"></el-option> |
|
</el-select> |
|
</el-form-item> |
|
<el-form-item prop="uniqueIdentificationAccount" label="唯一标识"> |
|
<el-input disabled v-model="form.uniqueIdentificationAccount"></el-input> |
|
</el-form-item> |
|
</el-form> |
|
<span slot="footer" class="dialog-footer" v-if="!isDetail"> |
|
<el-button @click="studentVisible = false">取消</el-button> |
|
<el-button type="primary" @click="saveData">确 定</el-button> |
|
</span> |
|
</el-dialog> |
|
|
|
<!-- 批量导入 --> |
|
<el-dialog title="批量导入" :visible.sync="importVisible" width="24%" center :close-on-click-modal="false"> |
|
<div style="text-align: center"> |
|
<div style="margin-bottom: 10px;"><el-button type="primary" @click="downLoad">模板下载<i class="el-icon-download el-icon--right"></i></el-button></div> |
|
<el-upload |
|
accept=".xls,.xlsx" |
|
:on-remove="handleRemove" |
|
:on-error="uploadError" |
|
:on-success="uploadSuccess" |
|
:before-remove="beforeRemove" |
|
:limit="1" |
|
:on-exceed="handleExceed" |
|
:action="this.api.uploadFile" |
|
:file-list="uploadList" |
|
name="file" |
|
> |
|
<el-button type="primary" class="ml20">上传文件<i class="el-icon-upload2 el-icon--right"></i></el-button> |
|
</el-upload> |
|
<el-link v-if="uploadFaild" type="primary" @click="showFaild">部分数据导入失败,查看失败原因</el-link> |
|
</div> |
|
<span slot="footer" class="dialog-footer"> |
|
<el-button @click="importVisible = false">取 消</el-button> |
|
<el-button type="primary" @click="uploadSure">确 定</el-button> |
|
</span> |
|
</el-dialog> |
|
|
|
<el-dialog |
|
title="重置密码" |
|
:visible.sync="passwordVisible" |
|
:close-on-click-modal="false" |
|
@close="closePassword" |
|
width="30%"> |
|
<el-form ref="passwordForm" :model="form" label-width="60px"> |
|
<el-form-item label="原密码"> |
|
<el-input type="password" v-model="passwordForm.password" placeholder="请输入原密码"></el-input> |
|
</el-form-item> |
|
<el-form-item label="新密码"> |
|
<el-input type="password" v-model="passwordForm.newPassword" placeholder="请输入新密码" @keyup.enter.native="editPassword"></el-input> |
|
</el-form-item> |
|
<el-form-item label="新密码"> |
|
<el-input type="password" v-model="passwordForm.reNewPassword" placeholder="请确认新密码" @keyup.enter.native="editPassword"></el-input> |
|
</el-form-item> |
|
</el-form> |
|
<span slot="footer" class="dialog-footer"> |
|
<el-button @click="passwordVisible = false">取 消</el-button> |
|
<el-button type="primary" @click="editPassword">确 定</el-button> |
|
</span> |
|
</el-dialog> |
|
</div> |
|
</template> |
|
|
|
<script> |
|
import echarts from 'echarts' |
|
export default { |
|
name: 'dashboard', |
|
data() { |
|
return { |
|
isDetail: false, |
|
keyword: '', |
|
schoolId: 2105, |
|
form: { |
|
userName: '', |
|
account: '', |
|
phone: '', |
|
uniqueIdentificationAccount: '', |
|
workNumber: '', |
|
email: '', |
|
account: '', |
|
roleId: 4, |
|
schoolId: 2105, |
|
schoolAppellationId: '' |
|
}, |
|
rules: { |
|
account: [ |
|
{ required: true, message: '请输入账号', trigger: 'blur' }, |
|
{ |
|
pattern: /^[a-zA-Z0-9_-]{1,16}$/, |
|
message: '请输入正确的账号', |
|
trigger: 'blur' |
|
} |
|
], |
|
userName: [ |
|
{ required: true, message: '请输入学生姓名', trigger: 'blur' } |
|
], |
|
schoolAppellationId: [ |
|
{ required: true, message: '请选择所在院校', trigger: 'change' } |
|
], |
|
// uniqueIdentificationAccount: [ |
|
// { required: true, message: '请输入唯一标识', trigger: 'blur' }, |
|
// ], |
|
workNumber: [ |
|
{ required: true, message: '请输入学生学号', trigger: 'blur' } |
|
], |
|
phone: [ |
|
// { required: true, message: '请输入职工手机号', trigger: 'blur' }, |
|
{ |
|
pattern: /^1[3456789]\d{9}$/, |
|
message: '请输入正确的手机号', |
|
trigger: 'blur' |
|
} |
|
], |
|
email: [ |
|
// { required: true, message: '请输入邮箱', trigger: 'blur' }, |
|
{ |
|
pattern: /^([a-zA-Z]|[0-9])(\w|\-)+@[a-zA-Z0-9]+\.([a-zA-Z]{2,4})$/, |
|
message: '请输入正确的邮箱', |
|
trigger: 'blur' |
|
} |
|
] |
|
}, |
|
studentData:[], |
|
pageNo: 1, |
|
pageSize: 10, |
|
totals: 0, |
|
multipleSelection: [], |
|
uploadList: [], |
|
importVisible: false, |
|
isAdd: true, |
|
studentVisible: false, |
|
accountReapeat: false, |
|
originalAccount: '', |
|
phoneRepeat: false, |
|
workNumberRepeat: false, |
|
originalWorkNumber: '', |
|
isDetail: false, |
|
resetVisible: false, |
|
passwordVisible: false, |
|
passwordForm: { |
|
password: '', |
|
newPassword: '', |
|
reNewPassword: '' |
|
}, |
|
schoolList: [], |
|
uploadFaild: false, |
|
token: '', |
|
accountMsg: '' |
|
}; |
|
}, |
|
mounted() { |
|
this.form.schoolAppellationId = 2105 |
|
this.getData() |
|
this.getSchoolData() |
|
this.getStat() |
|
}, |
|
watch: { |
|
keyword: function(val) { |
|
clearTimeout(this.searchTimer) |
|
this.searchTimer = setTimeout(() => { |
|
this.getData() |
|
},500) |
|
} |
|
}, |
|
methods: { |
|
getData() { |
|
let data = { |
|
schoolId: '', |
|
seachContent: this.encodeString(this.keyword), |
|
page: this.pageNo, |
|
size: this.pageSize |
|
} |
|
this.$get(this.api.queryStudent,data).then(res => { |
|
this.studentData = res.data.list |
|
this.totals = res.data.totalCount |
|
}).catch(res => {}); |
|
}, |
|
getStat() { |
|
this.$get(this.api.queryStudentData).then(res => { |
|
let stat1 = [] |
|
res.data['学生分布情况'].map(n => { |
|
stat1.push({ |
|
name: n.schoolName, |
|
value: n.schoolNumber |
|
}) |
|
}) |
|
let myChart = echarts.init(document.getElementById('chart1')) |
|
myChart.setOption({ |
|
title: { text: '实验学生的学校分布情况' }, |
|
tooltip: { |
|
trigger: 'item' |
|
}, |
|
legend: { |
|
top: 'bottom' |
|
}, |
|
series: [ |
|
{ |
|
name: '学校分布情况', |
|
type: 'pie', |
|
center: ['50%', '47%'], |
|
top: 30, |
|
bottom: 50, |
|
// radius: ['40%', '70%'], |
|
avoidLabelOverlap: false, |
|
// roseType: 'area', |
|
itemStyle: { |
|
borderRadius: 10, |
|
borderColor: '#fff', |
|
borderWidth: 2 |
|
}, |
|
// emphasis: { |
|
// label: { |
|
// show: true, |
|
// fontSize: '20', |
|
// fontWeight: 'bold' |
|
// } |
|
// }, |
|
labelLine: { |
|
show: false |
|
}, |
|
data: stat1 |
|
} |
|
] |
|
}) |
|
|
|
let schoolList = [] |
|
let frequencyList = [] |
|
res.data['学生平均登录情况'].map(n => { |
|
schoolList.push(n.schoolName) |
|
frequencyList.push(n.studentLoginNumber) |
|
}) |
|
let myChart1 = echarts.init(document.getElementById('chart2')) |
|
myChart1.setOption({ |
|
title: { text: '实验学生平均登录次数' }, |
|
tooltip: { |
|
trigger: 'item' |
|
}, |
|
xAxis: { |
|
type: 'category', |
|
data: schoolList |
|
}, |
|
yAxis: { |
|
type: 'value' |
|
}, |
|
series: [{ |
|
data: frequencyList, |
|
type: 'bar', |
|
smooth: true, |
|
color: ['#8191fd'] |
|
}] |
|
}) |
|
|
|
let schoolList1 = [] |
|
let timeList = [] |
|
res.data['学生实验平均时长'].map(n => { |
|
schoolList1.push(n.schoolName) |
|
timeList.push(n.studentAvgTime) |
|
}) |
|
let myChart2 = echarts.init(document.getElementById('chart3')) |
|
myChart2.setOption({ |
|
title: { |
|
text: '实验学生的平均实验时间情况', |
|
}, |
|
tooltip: { |
|
trigger: 'axis', |
|
axisPointer: { |
|
type: 'shadow' |
|
} |
|
}, |
|
grid: { |
|
left: '3%', |
|
right: '10%', |
|
bottom: '3%', |
|
containLabel: true |
|
}, |
|
xAxis: { |
|
name: '小时', |
|
type: 'value', |
|
boundaryGap: [0, 0.01] |
|
}, |
|
yAxis: { |
|
type: 'category', |
|
data: schoolList1 |
|
}, |
|
series: [ |
|
{ |
|
name: '平均实验时间:', |
|
type: 'bar', |
|
data: timeList, |
|
color: ['#9278ff'] |
|
}, |
|
] |
|
}) |
|
}).catch(res => {}); |
|
}, |
|
saveData() { |
|
this.$refs.form.validate((valid) => { |
|
if (valid) { |
|
if(this.accountReapeat) return this.$message.warning(this.accountMsg) |
|
if(this.workNumberRepeat) return this.$message.warning('该学生学号已存在') |
|
if(this.phoneRepeat) return this.$message.warning('该手机号已存在') |
|
if(this.form.studentId) { |
|
this.$put(this.api.updateStudent,this.form).then(res => { |
|
if(res.errmessage == 'success') { |
|
this.$message.success('提交成功!'); |
|
this.studentVisible = false |
|
this.getData() |
|
this.getStat() |
|
}else{ |
|
this.$message.error(res.message); |
|
} |
|
}).catch(res => {}); |
|
}else{ |
|
this.form.uniqueIdentificationAccount = new Date().getTime() |
|
this.$post(this.api.addStudent,this.form).then(res => { |
|
if(res.errmessage == 'success') { |
|
this.$message.success('提交成功!'); |
|
this.studentVisible = false |
|
this.getData() |
|
this.getStat() |
|
}else{ |
|
this.$message.error(res.message); |
|
} |
|
}).catch(res => {}); |
|
} |
|
}else{ |
|
return false; |
|
} |
|
}) |
|
}, |
|
async accountChange(){ |
|
if(this.form.account !== this.originalAccount){ |
|
let res = await this.$get(this.api.queryAccountIsExist, { |
|
account: this.encodeString(this.form.account), |
|
schoolId: this.schoolId |
|
}); |
|
if(res.message.user.length){ |
|
let roleId = res.message.user[0].roleId |
|
this.accountMsg = roleId == 4 ? '该账号已存在' : (roleId.includes(',') ? '该账号已绑定老师和管理员' : `该账号已绑定${this.roleStatus(roleId)}`) |
|
this.$message.warning(this.accountMsg) |
|
this.accountReapeat = true |
|
}else{ |
|
this.accountReapeat = false |
|
} |
|
}else{ |
|
this.accountReapeat = false |
|
} |
|
}, |
|
async worknumberChange(){ |
|
// if(this.form.workNumber !== this.originalWorkNumber){ |
|
let res = await this.$get(this.api.queryWorkNumberIsExist, { |
|
workNumber: this.encodeString(this.form.workNumber), |
|
schoolAppellationId: this.form.schoolAppellationId |
|
}); |
|
if(res.status != 200){ |
|
this.$message.warning('该学生学号已存在'); |
|
this.workNumberRepeat = true |
|
}else{ |
|
this.workNumberRepeat = false |
|
} |
|
// }else{ |
|
// this.workNumberRepeat = false |
|
// } |
|
}, |
|
async phoneChange(){ |
|
let res = await this.$get(this.api.queryPhone, { phone: this.form.phone }); |
|
if(res.message.length != 0){ |
|
this.$message.warning('该手机号已存在'); |
|
this.phoneRepeat = true |
|
}else{ |
|
this.phoneRepeat = false |
|
} |
|
}, |
|
batchImport(){ |
|
this.importVisible = true |
|
this.uploadList = [] |
|
this.uploadFaild = false |
|
}, |
|
// 获取学校/客户名称 |
|
getSchool(){ |
|
this.clearcity() |
|
this.getSchoolData() |
|
this.pageNo = 1 |
|
this.getData() |
|
}, |
|
getSchoolData(){ |
|
let data = { |
|
schoolName: '', |
|
provinceId: '', |
|
cityId: '' |
|
} |
|
this.$get(this.api.querySchool,data).then(res => { |
|
this.schoolList = res.message |
|
}).catch(res => {}); |
|
}, |
|
closeStudent(){ |
|
this.isDetail = false |
|
this.$refs.form.clearValidate() |
|
this.form = { |
|
schoolId: 2105, |
|
userName: '', |
|
account: '', |
|
phone: '', |
|
uniqueIdentificationAccount: '', |
|
workNumber: '', |
|
email: '', |
|
account: '', |
|
roleId: 4, |
|
schoolAppellationId: 2105 |
|
} |
|
}, |
|
currentChange(val) { |
|
this.pageNo = val; |
|
this.getData(); |
|
}, |
|
addStudent(){ |
|
this.isAdd = true |
|
this.studentVisible = true |
|
}, |
|
editStudent(row,isDetail){ |
|
this.isAdd = false |
|
this.isDetail = isDetail |
|
this.studentVisible = true |
|
this.form = Object.assign({},row) |
|
this.originalWorkNumber = row.workNumber |
|
this.originalAccount = row.account |
|
this.$nextTick(() => { |
|
this.$refs.form.clearValidate() |
|
}) |
|
}, |
|
downLoad(){ |
|
location.href = this.api.download |
|
}, |
|
handleDelete(row) { |
|
this.$confirm('确定要删除吗?', '提示', { |
|
type: 'warning' |
|
}) |
|
.then(() => { |
|
this.$post(this.api.daleteStudent,[row.studentId]).then(res => { |
|
this.$message.success('删除成功'); |
|
this.getData() |
|
this.getStat() |
|
}).catch(res => {}); |
|
}) |
|
.catch(() => {}); |
|
}, |
|
getRowKeys(row) { |
|
return row.userId; |
|
}, |
|
handleSelectionChange(val) { |
|
this.multipleSelection = val; |
|
}, |
|
delAllSelection() { |
|
if(this.multipleSelection.length != ''){ |
|
let newArr = this.multipleSelection |
|
let delList = newArr.map(item => { |
|
return item.studentId |
|
}) |
|
this.$confirm('确定要删除选中用户吗?', '提示', { |
|
type: 'warning' |
|
}) |
|
.then(() => { |
|
let data = delList |
|
this.$post(this.api.daleteStudent,data).then(res => { |
|
this.$refs.table.clearSelection() |
|
this.$message.success('删除成功'); |
|
this.getData() |
|
this.getStat() |
|
}).catch(res => {}); |
|
}).catch(() => {}); |
|
}else{ |
|
this.$message.error('请先选择数据 !'); |
|
} |
|
}, |
|
resetPassword(row){ |
|
this.$confirm(`重置后的密码为:${this.$config.initialPassword},确定重置?`, '提示', { |
|
}).then(() => { |
|
this.$put(this.api.reSetPassword,[row.userId]).then(res => { |
|
if(res.errmessage == 'success') this.$message.success('重置成功') |
|
}).catch(res => {}); |
|
}).catch(() => { |
|
}); |
|
}, |
|
switchOff(val,row,index) { |
|
let data = { |
|
studentId: row.studentId, |
|
disableAccount: row.disableAccount ? 0 : 1 |
|
} |
|
this.$put(this.api.disableAccount,data) |
|
.then(res => {}) |
|
.catch(err => {}); |
|
}, |
|
closePassword() { |
|
this.passwordForm = { |
|
password: '', |
|
newPassword: '', |
|
reNewPassword: '' |
|
} |
|
}, |
|
editPassword(){ |
|
if(!this.passwordForm.password) return this.$message.warning('请输入原密码') |
|
if(!this.passwordForm.newPassword) return this.$message.warning('请输入新密码') |
|
if(!this.passwordForm.reNewPassword) return this.$message.warning('请确认新密码') |
|
if(this.passwordForm.newPassword.length < 6 || this.passwordForm.reNewPassword.length < 6) return this.$message.warning('请输入6位数以上的密码') |
|
if(this.passwordForm.newPassword !== this.passwordForm.reNewPassword) return this.$message.warning('输入的新密码不一致,请重新确认') |
|
if(this.passwordForm.password === this.passwordForm.newPassword) return this.$message.warning('原密码跟新密码不能一致') |
|
|
|
let data = this.passwordForm |
|
data.userid = this.userId |
|
this.$put(this.api.reSetPassword,data) |
|
.then(res => { |
|
if(res.errmessage == 'success'){ |
|
this.$message.success('更换成功') |
|
this.passwordVisible = false |
|
} |
|
}) |
|
.catch(err => { |
|
console.log(err); |
|
}); |
|
}, |
|
// 上传文件 |
|
handleExceed(files, fileList) { |
|
this.$message.warning( |
|
`当前限制选择 1 个文件,如需更换,请删除上一个文件再重新选择!` |
|
); |
|
}, |
|
showFaild(){ |
|
location.href = `${this.api.export_failure}?token=${this.token}` |
|
}, |
|
uploadSuccess(res, file, fileList) { |
|
this.uploadFaild = false |
|
if(res.errmessage == 'success'){ |
|
if(res.data.token){ |
|
this.token = res.data.token |
|
this.uploadFaild = true |
|
}else{ |
|
this.$message.success('上传成功') |
|
} |
|
}else{ |
|
res.message ? this.$message.error(res.message) : this.$message.error('上传失败,请检查数据') |
|
} |
|
}, |
|
uploadError(err, file, fileList) { |
|
this.$message({ |
|
message: "上传出错,请重试!", |
|
type: "error", |
|
center: true |
|
}); |
|
}, |
|
beforeRemove(file, fileList) { |
|
return this.$confirm(`确定移除 ${file.name}?`); |
|
}, |
|
handleRemove(file, fileList) { |
|
this.uploadList = fileList |
|
this.uploadFaild = false |
|
}, |
|
uploadSure(){ |
|
this.importVisible = false |
|
this.pageNo = 1 |
|
this.keyword = '' |
|
this.getData() |
|
}, |
|
} |
|
}; |
|
</script> |
|
|
|
<style lang="scss" scoped> |
|
.mag{ |
|
margin-right: 20px; |
|
} |
|
.no-mb /deep/.el-form-item{ |
|
margin-bottom: 0; |
|
} |
|
/deep/.el-row{ |
|
padding: 0 !important; |
|
margin-bottom: 0; |
|
} |
|
.stat{ |
|
display: flex; |
|
.item{ |
|
flex: 1; |
|
padding: 15px; |
|
margin-right: 20px; |
|
box-shadow: 1px 1px 3px 1px rgba(146,120,255,.3); |
|
box-sizing: border-box; |
|
&:last-child{ |
|
margin-right: 0; |
|
} |
|
.chart{ |
|
height: 300px; |
|
} |
|
} |
|
} |
|
</style> |