Compare commits
21 Commits
Author | SHA1 | Date |
---|---|---|
|
62b2f6ab3d | |
|
f0b15ce2da | |
|
c8c15e6182 | |
|
03ad85478f | |
|
87daede414 | |
|
d0a33280d3 | |
|
347fb88477 | |
|
baf4b4246b | |
|
60750d0ca4 | |
|
4aef7d706d | |
|
cf89aae584 | |
|
df1aab15cd | |
|
e60233645a | |
|
dd0090a826 | |
|
5610e30c11 | |
|
aaedf72cf3 | |
|
54d1bcb9aa | |
|
ccd3305924 | |
|
cf6302cc71 | |
|
16670433d0 | |
|
80a240675d |
|
@ -0,0 +1,70 @@
|
|||
function myBrowser() {
|
||||
var userAgent = navigator.userAgent; // 取得浏览器的userAgent字符串
|
||||
var isOpera = userAgent.indexOf('Opera') > -1;
|
||||
if (isOpera) {
|
||||
return 'Opera';
|
||||
} // 判断是否Opera浏览器
|
||||
if (userAgent.indexOf('Firefox') > -1) {
|
||||
return 'FF';
|
||||
} // 判断是否Firefox浏览器
|
||||
if (userAgent.indexOf('Chrome') > -1) {
|
||||
return 'Chrome';
|
||||
}
|
||||
if (userAgent.indexOf('Safari') > -1) {
|
||||
return 'Safari';
|
||||
} // 判断是否Safari浏览器
|
||||
if (userAgent.indexOf('compatible') > -1 && userAgent.indexOf('MSIE') > -1 && !isOpera) {
|
||||
return 'IE';
|
||||
} // 判断是否IE浏览器
|
||||
if (userAgent.indexOf('Trident') > -1) {
|
||||
return 'Edge';
|
||||
} // 判断是否Edge浏览器
|
||||
}
|
||||
function SaveAs5(imgURL) {
|
||||
var oPop = window.open(imgURL, '', 'width=1, height=1, top=5000, left=5000');
|
||||
for (; oPop.document.readyState !== 'complete'; ) {
|
||||
if (oPop.document.readyState === 'complete') break;
|
||||
}
|
||||
oPop.document.execCommand('SaveAs');
|
||||
oPop.close();
|
||||
}
|
||||
function download(src, fileName) {
|
||||
// 创建隐藏的可下载链接
|
||||
var eleLink = document.createElement('a');
|
||||
if (fileName) {
|
||||
eleLink.setAttribute('download', fileName);
|
||||
} else {
|
||||
eleLink.download = src;
|
||||
}
|
||||
eleLink.style.display = 'none';
|
||||
// // 字符内容转变成blob地址
|
||||
eleLink.href = src;
|
||||
// // 触发点击
|
||||
document.body.appendChild(eleLink);
|
||||
eleLink.click();
|
||||
// // 然后移除
|
||||
document.body.removeChild(eleLink);
|
||||
}
|
||||
function downLoadFile(url, fileName = '') {
|
||||
if (myBrowser() === 'IE' || myBrowser() === 'Edge') {
|
||||
SaveAs5(url);
|
||||
} else {
|
||||
download(url, fileName);
|
||||
}
|
||||
}
|
||||
function conversionFileDownload(res) {
|
||||
const a = document.createElement('a');
|
||||
const blob = new Blob([res.data], { type: 'application/vnd.ms-excel' });
|
||||
const temp = res.headers['content-disposition'].split(';')[1].split('filename=')[1];
|
||||
// 对文件名乱码转义--【Node.js】使用iconv-lite解决中文乱码
|
||||
const iconv = require('iconv-lite');
|
||||
iconv.skipDecodeWarning = true; // 忽略警告
|
||||
const fileName = iconv.decode(temp, 'utf-8');
|
||||
console.log(fileName);
|
||||
a.setAttribute('download', fileName);
|
||||
const objectUrl = URL.createObjectURL(blob);
|
||||
a.setAttribute('href', objectUrl);
|
||||
a.click();
|
||||
}
|
||||
|
||||
export { downLoadFile, conversionFileDownload };
|
File diff suppressed because it is too large
Load Diff
|
@ -6,217 +6,420 @@
|
|||
<a-cascader v-model:value="collegeMajor" :options="collegeMajorOptions" change-on-select />
|
||||
<a-button style="margin-left: 10px" type="primary" @click="query">查询</a-button>
|
||||
</template>
|
||||
<div>
|
||||
<a-row :gutter="24">
|
||||
<a-col :xl="24" :style="{ marginBottom: '24px' }">
|
||||
<div class="container">
|
||||
<div style="display: flex;">
|
||||
<span class="title">学院 / 专业四级通过率变化</span>
|
||||
<div v-if="topCollege != null">
|
||||
<span style="font-size: 15px;padding-left: 100px;">该数据为 </span>
|
||||
<span style="color: red; font-size: 18px; ">{{ topCollege}}</span>
|
||||
<span v-if="topMajor != null && topMajor != ''" style="color: red; font-size: 18px; "> / {{ topMajor}}</span>
|
||||
<span style="font-size: 15px;"> 的四级通过率变化趋势 </span>
|
||||
</div>
|
||||
|
||||
<a-row :gutter="12">
|
||||
<a-col :xl="16" :style="{ marginBottom: '24px' }">
|
||||
<!-- 根据需求 删除 或 更改-->
|
||||
<a-card class="tip">
|
||||
<div style="display: flex">
|
||||
<div v-if="topCollege != null">
|
||||
<span style="font-size: 15px; padding-left: 100px">该数据为 </span>
|
||||
<span style="color: red; font-size: 18px">{{ topCollege }}</span>
|
||||
<span v-if="topMajor != null && topMajor != ''" style="color: red; font-size: 18px"> / {{ topMajor }}</span>
|
||||
<span style="font-size: 15px"> 的四级通过率变化趋势 </span>
|
||||
</div>
|
||||
<div id="map1" style="width: 100%; height: 500px"></div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</a-card>
|
||||
|
||||
<a-card>
|
||||
<div>
|
||||
<div id="map1" style="width: 100%; height: 400px"></div>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
|
||||
<a-col :xl="8">
|
||||
<a-card :loading="participate_Piechartloading" style="margin-bottom: 10px">
|
||||
<div style="width: 100%; height: 210px; padding: 10px" class="participate_Piechart" id="participate_Piechart"></div>
|
||||
</a-card>
|
||||
|
||||
<a-card :loading="pass_Piechartloading">
|
||||
<div style="width: 100%; height: 210px; padding: 10px" class="pass_Piechart" id="pass_Piechart"></div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import * as echarts from 'echarts';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
export default {
|
||||
name: 'Analysis',
|
||||
data() {
|
||||
return {
|
||||
Url: {
|
||||
getBatch: '/cet/getBatch',
|
||||
getCollege: '/cet/getCollege',
|
||||
getRate: '/cet/getRateByAllBatch',
|
||||
getCollegeMajor: '/cet/getCollegeMajor',
|
||||
},
|
||||
loading: false,
|
||||
collegeOptions: [],
|
||||
collegeMajorOptions: [],
|
||||
batchOptions: [],
|
||||
levelOptions: [
|
||||
{ value: 'cet4', label: '英语四级' },
|
||||
{ value: 'cet6', label: '英语六级' },
|
||||
],
|
||||
level: null,
|
||||
college: null,
|
||||
batch: null,
|
||||
collegeMajor: null,
|
||||
topCollege: null,//顶部解释行
|
||||
topMajor: null,//顶部解释行
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
dataChart(data) {
|
||||
let xData = [];
|
||||
let yData = [];
|
||||
for (let key in data) {
|
||||
xData.push(key);
|
||||
// 将数据转换为百分比(加上%)
|
||||
yData.push(data[key].toFixed(1));
|
||||
}
|
||||
let myChart = echarts.init(document.getElementById('map1'));
|
||||
// 指定图表的配置项和数据
|
||||
let option = {
|
||||
title: {
|
||||
// text: '学院 / 专业四级通过率变化',
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
Url: {
|
||||
getBatch: '/cet/getBatch',
|
||||
getCollege: '/cet/getCollege',
|
||||
getRate: '/cet/getRateByAllBatch',
|
||||
getCollegeMajor: '/cet/getCollegeMajor',
|
||||
getRateByMajor: '/cet/getgetRateByMajor',
|
||||
getRateByMajorAndLastestBatch: '/cet/getRateByMajorAndLastestBatch',
|
||||
getRateByEntryDate: '/cet/getRateByEntryDate',
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xData,
|
||||
axisLabel: {
|
||||
interval: 0, //代表显示所有x轴标签显示
|
||||
rotate: -10, //代表倾斜30度显示
|
||||
loading: false,
|
||||
participate_Piechartloading: false,
|
||||
pass_Piechartloading: false,
|
||||
collegeOptions: [],
|
||||
collegeMajorOptions: [],
|
||||
batchOptions: [],
|
||||
levelOptions: [
|
||||
{ value: 'cet4', label: '英语四级' },
|
||||
{ value: 'cet6', label: '英语六级' },
|
||||
],
|
||||
level: null,
|
||||
college: null,
|
||||
batch: null,
|
||||
collegeMajor: null,
|
||||
topCollege: null, //顶部解释行
|
||||
topMajor: null, //顶部解释行
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getCollegeMajorData();
|
||||
this.getBatch();
|
||||
this.query();
|
||||
},
|
||||
methods: {
|
||||
dataChart(data) {
|
||||
let xData = [];
|
||||
let yData = [];
|
||||
for (let key in data) {
|
||||
xData.push(key);
|
||||
// 将数据转换为百分比(加上%)
|
||||
yData.push(data[key].toFixed(1));
|
||||
}
|
||||
let myChart = echarts.init(document.getElementById('map1'));
|
||||
// 指定图表的配置项和数据
|
||||
let option = {
|
||||
title: {
|
||||
// text: '学院 / 专业四级通过率变化',
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xData,
|
||||
axisLabel: {
|
||||
interval: 1, //代表显示所有x轴标签显示
|
||||
rotate: -10, //代表倾斜30度显示
|
||||
},
|
||||
},
|
||||
formatter: function (params) {
|
||||
return (
|
||||
params[0].name +
|
||||
'<br/>' +
|
||||
'<table>' +
|
||||
'<tr><td>' +
|
||||
params[0].marker +
|
||||
'</td><td style="font-weight: bold;">' +
|
||||
' ' +
|
||||
params[0].value +
|
||||
'%' +
|
||||
'</td></tr>' +
|
||||
'<tr>' +
|
||||
'</table>'
|
||||
);
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
},
|
||||
formatter: function (params) {
|
||||
return (
|
||||
params[0].name +
|
||||
'<br/>' +
|
||||
'<table>' +
|
||||
'<tr><td>' +
|
||||
params[0].marker +
|
||||
'</td><td style="font-weight: bold;">' +
|
||||
' ' +
|
||||
params[0].value +
|
||||
'%' +
|
||||
'</td></tr>' +
|
||||
'<tr>' +
|
||||
'</table>'
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
name: '通过率',
|
||||
axisLabel: {
|
||||
formatter: '{value} %',
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
name: '通过率',
|
||||
axisLabel: {
|
||||
formatter: '{value} %',
|
||||
},
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: yData,
|
||||
type: 'line',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
label: {
|
||||
show: true, //开启显示
|
||||
position: 'top', //在上方显示
|
||||
textStyle: {
|
||||
//数值样式
|
||||
color: 'black',
|
||||
fontSize: 12,
|
||||
series: [
|
||||
{
|
||||
data: yData,
|
||||
type: 'line',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
label: {
|
||||
show: true, //开启显示
|
||||
position: 'top', //在上方显示
|
||||
textStyle: {
|
||||
//数值样式
|
||||
color: 'black',
|
||||
fontSize: 12,
|
||||
},
|
||||
formatter: '{c}%',
|
||||
},
|
||||
formatter: '{c}%',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
// 使用刚指定的配置项和数据显示图表。
|
||||
myChart.setOption(option);
|
||||
},
|
||||
// 获取批次数据
|
||||
async getBatch() {
|
||||
const getBatch = await defHttp.get({ url: this.Url.getBatch });
|
||||
// const getCollege = await defHttp.get({ url: this.Url.getCollege });
|
||||
|
||||
// this.collegeOptions = getCollege.colleges;
|
||||
// this.college = this.collegeOptions[0].value;
|
||||
|
||||
this.level = this.levelOptions[0].value;
|
||||
|
||||
// this.query();
|
||||
},
|
||||
//获取学院专业级联数据
|
||||
async getCollegeMajorData() {
|
||||
const res = await defHttp.get({ url: this.Url.getCollegeMajor });
|
||||
//通过map方法将数据转换为级联选择器需要的数据格式
|
||||
this.collegeMajorOptions = res.collegeMajor.map((item) => {
|
||||
return {
|
||||
value: item.college,
|
||||
label: item.college,
|
||||
children: item.major.map((major) => {
|
||||
return {
|
||||
value: major,
|
||||
label: major,
|
||||
};
|
||||
}),
|
||||
],
|
||||
};
|
||||
});
|
||||
this.collegeMajor = ['东语学院', '日语'];
|
||||
},
|
||||
// 查询数据
|
||||
async query() {
|
||||
let data = null;
|
||||
console.log(this.collegeMajor, 'collegeMajor');
|
||||
try {
|
||||
// 使用刚指定的配置项和数据显示图表。
|
||||
myChart.setOption(option);
|
||||
},
|
||||
|
||||
//如果this.collegeMajor为null则先赋个值
|
||||
if (!this.collegeMajor) {
|
||||
this.collegeMajor = ['东语学院', '日语'];
|
||||
}
|
||||
let major = null;
|
||||
let college = null;
|
||||
//如果this.collegeMajor[1]不存在则设为null
|
||||
college = this.collegeMajor[0];
|
||||
major = this.collegeMajor.length > 1 ? this.collegeMajor[1] : '';
|
||||
this.topCollege = college;
|
||||
this.topMajor = major;
|
||||
this.loading = true;
|
||||
console.log(college, major, "college,major");
|
||||
let params = {
|
||||
//绘画饼图--最新批次每一年级的通过率饼图
|
||||
async draPieChart_Participate() {
|
||||
console.log(this.collegeMajor, 'collegeMajor');
|
||||
let college = this.collegeMajor[0];
|
||||
let major = this.collegeMajor[1];
|
||||
console.log(college, major, 'college major');
|
||||
|
||||
let queryParams = {
|
||||
college: college,
|
||||
major: major,
|
||||
level: 'cet4',
|
||||
};
|
||||
data = await defHttp.get({ url: this.Url.getRate, params });
|
||||
} finally {
|
||||
this.loading = false;
|
||||
let url = this.Url.getRateByMajorAndLastestBatch;
|
||||
this.participate_Piechartloading = true;
|
||||
console.log(queryParams, 'queryParams');
|
||||
|
||||
let result = await defHttp.post({ url: url, data: queryParams });
|
||||
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
console.log(result.data, 'result');
|
||||
|
||||
let titleText = major ? `${college} / ${major}专业 最新批次通过人数` : `${college} 最新批次通过人数`;
|
||||
|
||||
// 使用 API 返回的数据填充饼图
|
||||
let chartData = [];
|
||||
|
||||
for (let key in result.data) {
|
||||
chartData.push({
|
||||
name: key + '级',
|
||||
value: result.data[key].passRate,
|
||||
});
|
||||
}
|
||||
console.log(chartData, '123');
|
||||
let xData = chartData.map((item) => item.name); // 提取类别数据
|
||||
let yData = chartData.map((item) => item.value); // 提取值数据
|
||||
let option = {
|
||||
grid: {
|
||||
left: '20%', // 增加左边距,可以根据需要调整
|
||||
right: '5%', // 右边距
|
||||
top: '20%', // 上边距
|
||||
bottom: '10%', // 下边距
|
||||
},
|
||||
title: {
|
||||
text: '最新批次每一年级的通过率',
|
||||
left: 'top',
|
||||
top: '0%',
|
||||
textStyle: {
|
||||
fontSize: 14,
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xData,
|
||||
//data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'],
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
formatter: '{value}%',
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: titleText,
|
||||
data: yData,
|
||||
//data: [150, 230, 224, 218, 135, 147, 260],
|
||||
type: 'line',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
label: {
|
||||
show: true, //开启显示
|
||||
position: 'top', //在上方显示
|
||||
textStyle: {
|
||||
//数值样式
|
||||
color: 'black',
|
||||
fontSize: 12,
|
||||
},
|
||||
formatter: '{c}%',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
animationDurationUpdate: 500,
|
||||
};
|
||||
this.participate_Piechartloading = false;
|
||||
this.$nextTick(() => {
|
||||
this.dataChart(data);
|
||||
var myChart = echarts.init(document.getElementById('participate_Piechart'));
|
||||
myChart.setOption(option);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
//绘画饼图--学院/专业每个年级的通过率柱状图
|
||||
async draPieChart_Pass() {
|
||||
//console.log(this.passRatePie);
|
||||
//console.log('piedata', piedata);
|
||||
let college = this.collegeMajor[0];
|
||||
let major = this.collegeMajor[1];
|
||||
let queryParams = {
|
||||
college: college,
|
||||
major: major,
|
||||
level: 'cet4',
|
||||
};
|
||||
let url = this.Url.getRateByEntryDate;
|
||||
this.pass_Piechartloading = true;
|
||||
console.log(queryParams, 'queryParams');
|
||||
let result = await defHttp.post({ url: url, data: queryParams });
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
console.log(result, 'result');
|
||||
// 从 result 提取数据
|
||||
let xData = result.data.map((item) => item.entryDate); // 用于 X 轴
|
||||
let values = result.data.map((item) => item.passRate); // 用于柱状图的数据
|
||||
console.log(xData, values, 'xData values');
|
||||
let titleText = major ? `${college} / ${major}专业 每个年级的通过率柱状图` : `${college} 每个年级的通过率柱状图`;
|
||||
let option = {
|
||||
grid: {
|
||||
left: '15%', // 调整左边距,向右移动
|
||||
top: '20%', // 调整上边距,向下移动
|
||||
right: '10%', // 可根据需要调整右边距
|
||||
bottom: '10%', // 可根据需要调整底边距
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
formatter: function (params) {
|
||||
// 在默认格式基础上添加 %
|
||||
return `${params.marker}${params.name} ${params.value}%`;
|
||||
},
|
||||
},
|
||||
title: {
|
||||
text: titleText,
|
||||
left: 'left',
|
||||
top: '0%',
|
||||
textStyle: {
|
||||
fontSize: 14,
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xData,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
axisLabel: {
|
||||
formatter: '{value}%', // Y 轴显示百分比符号
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: values,
|
||||
type: 'bar',
|
||||
showBackground: true,
|
||||
backgroundStyle: {
|
||||
color: 'rgba(180, 180, 180, 0.2)',
|
||||
},
|
||||
label: {
|
||||
show: true, // 显示数据标签
|
||||
position: 'top', // 标签位置在柱体顶部
|
||||
formatter: '{c}%', // 标签内容为百分比
|
||||
fontSize: '10px',
|
||||
},
|
||||
},
|
||||
],
|
||||
animationDurationUpdate: 500,
|
||||
};
|
||||
this.pass_Piechartloading = false;
|
||||
this.$nextTick(() => {
|
||||
var myChart = echarts.init(document.getElementById('pass_Piechart'));
|
||||
myChart.setOption(option);
|
||||
});
|
||||
},
|
||||
// 获取批次数据
|
||||
async getBatch() {
|
||||
const getBatch = await defHttp.get({ url: this.Url.getBatch });
|
||||
// const getCollege = await defHttp.get({ url: this.Url.getCollege });
|
||||
|
||||
// this.collegeOptions = getCollege.colleges;
|
||||
// this.college = this.collegeOptions[0].value;
|
||||
|
||||
this.level = this.levelOptions[0].value;
|
||||
|
||||
// this.query();
|
||||
},
|
||||
//获取学院专业级联数据
|
||||
async getCollegeMajorData() {
|
||||
const res = await defHttp.get({ url: this.Url.getCollegeMajor });
|
||||
//通过map方法将数据转换为级联选择器需要的数据格式
|
||||
this.collegeMajorOptions = res.collegeMajor.map((item) => {
|
||||
return {
|
||||
value: item.college,
|
||||
label: item.college,
|
||||
children: item.major.map((major) => {
|
||||
return {
|
||||
value: major,
|
||||
label: major,
|
||||
};
|
||||
}),
|
||||
};
|
||||
});
|
||||
this.collegeMajor = ['东语学院', '日语'];
|
||||
},
|
||||
// 查询数据
|
||||
async query() {
|
||||
let data = null;
|
||||
console.log(this.collegeMajor, 'collegeMajor');
|
||||
try {
|
||||
//如果this.collegeMajor为null则先赋个值
|
||||
if (!this.collegeMajor) {
|
||||
this.collegeMajor = ['东语学院', '日语'];
|
||||
}
|
||||
let major = null;
|
||||
let college = null;
|
||||
//如果this.collegeMajor[1]不存在则设为null
|
||||
college = this.collegeMajor[0];
|
||||
major = this.collegeMajor.length > 1 ? this.collegeMajor[1] : '';
|
||||
this.topCollege = college;
|
||||
this.topMajor = major;
|
||||
this.loading = true;
|
||||
console.log(college, major, 'college,major');
|
||||
let params = {
|
||||
college: college,
|
||||
major: major,
|
||||
level: 'cet4',
|
||||
};
|
||||
data = await defHttp.get({ url: this.Url.getRate, params });
|
||||
console.log(data, 'data');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
this.$nextTick(() => {
|
||||
this.dataChart(data);
|
||||
this.draPieChart_Pass();
|
||||
this.draPieChart_Participate();
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getCollegeMajorData();
|
||||
this.getBatch();
|
||||
this.query();
|
||||
},
|
||||
};
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.container {
|
||||
// display: flex;
|
||||
background-color: #fff;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.09);
|
||||
}
|
||||
.container {
|
||||
// display: flex;
|
||||
background-color: #fff;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.09);
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 20px;
|
||||
color: rgb(8, 8, 8);
|
||||
font-weight: bold;
|
||||
}
|
||||
.title {
|
||||
font-size: 20px;
|
||||
color: rgb(8, 8, 8);
|
||||
font-weight: bold;
|
||||
}
|
||||
.tip {
|
||||
margin-bottom: 10px;
|
||||
background-color: #d0e5fe;
|
||||
opacity: 0.9;
|
||||
}
|
||||
</style>
|
||||
|
|
|
@ -1,244 +1,448 @@
|
|||
<template>
|
||||
<div style="background: #ececec; padding: 15px">
|
||||
<a-card title="按批次对比分析" :loading="loading" :bordered="false">
|
||||
<a-card title="按单批次对比分析" :loading="loading" :bordered="false">
|
||||
<template #extra>
|
||||
<a-select v-model:value="collegeMajor" style="width: 300px" :options="collegeMajorOptions"></a-select>
|
||||
<a-select v-model:value="batch" :options="batchOptions" change-on-select
|
||||
style="margin-left: 10px;width: 120px" />
|
||||
<a-button style="margin-left: 10px;" type="primary" @click="query">查询</a-button>
|
||||
<a-select v-model:value="collegeMajor" style="width: 300px" :options="collegeMajorOptions" />
|
||||
<a-select v-model:value="batch" :options="batchOptions" change-on-select style="margin-left: 10px; width: 120px" />
|
||||
<a-button style="margin-left: 10px" type="primary" @click="query">查询</a-button>
|
||||
</template>
|
||||
<div>
|
||||
<a-row :gutter="24">
|
||||
<a-col :xl="24" :style="{ marginBottom: '24px' }">
|
||||
<div class="container">
|
||||
<div style="display: flex;">
|
||||
<span class="title">学院 / 专业四级通过率变化</span>
|
||||
<div v-if="topCollege != null">
|
||||
<span style="color: red; font-size: 18px; padding-left: 100px;"> {{ topCollege }}</span>
|
||||
<span style="font-size: 15px;"> 在 </span>
|
||||
<span style="color: red; font-size: 18px;"> {{ topBath }} </span>
|
||||
<span style="font-size: 15px;"> 批次的四级通过率为:</span>
|
||||
<span style="color: red; font-size: 18px;"> {{ sumRate }}%</span>
|
||||
</div>
|
||||
|
||||
<a-row :grutter="24">
|
||||
<a-col :xl="16" :style="{ marginBottom: '24px' }">
|
||||
<!-- 根据需求 删除 或 更改-->
|
||||
<a-card style="margin-bottom: 10px" class="tip">
|
||||
<div style="display: flex">
|
||||
<div v-if="topCollege != null">
|
||||
<span style="color: red; font-size: 18px; padding-left: 100px"> {{ topCollege }}</span>
|
||||
<span style="font-size: 15px"> 在 </span>
|
||||
<span style="color: red; font-size: 18px"> {{ topBath }} </span>
|
||||
<span style="font-size: 15px"> 批次的四级通过率为:</span>
|
||||
<span style="color: red; font-size: 18px"> {{ sumRate }}%</span>
|
||||
</div>
|
||||
<div id="map1" style="width: 100%; height: 600px;"></div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</div>
|
||||
</a-card>
|
||||
|
||||
<a-card>
|
||||
<div>
|
||||
<div id="map1" style="width: 100%; height: 400px"></div>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
|
||||
<a-col :xl="8" style="padding-left: 10px">
|
||||
<a-card :loading="participate_Piechartloading" style="margin-bottom: 10px">
|
||||
<div style="width: 100%; height: 210px; padding: 10px" class="participate_Piechart" id="participate_Piechart"></div>
|
||||
</a-card>
|
||||
|
||||
<a-card :loading="tableloading" style="height: 268px">
|
||||
<div>
|
||||
<a-table
|
||||
:dataSource="dataSourceCet4"
|
||||
:columns="columns"
|
||||
:pagination="false"
|
||||
bordered
|
||||
class="custom-table"
|
||||
:style="{ fontSize: '12px', color: '#333', marginTop: '-11px' }"
|
||||
/>
|
||||
</div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { result } from 'lodash-es';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import * as echarts from 'echarts';
|
||||
//import { pagination } from 'mock/_util';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
export default {
|
||||
name: "Analysis",
|
||||
|
||||
data() {
|
||||
return {
|
||||
Url: {
|
||||
getBatch: '/cet/getBatch',
|
||||
getCollege: '/cet/getCollege',
|
||||
getRate: '/cet/getRateByBatch',
|
||||
getCollegeMajor: '/cet/getCollegeMajor'
|
||||
},
|
||||
loading: false,
|
||||
collegeOptions: [],
|
||||
collegeMajorOptions: [],
|
||||
batchOptions: [],
|
||||
levelOptions: [
|
||||
{ value: 'cet4', label: '英语四级' },
|
||||
{ value: 'cet6', label: '英语六级' }
|
||||
],
|
||||
level: null,
|
||||
college: null,
|
||||
batch: null,
|
||||
collegeMajor: null,
|
||||
sumRate: null,//总通过率
|
||||
topCollege: null,//顶部选择器选择的学院
|
||||
topBath: null,//顶部选择器选择的批次
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
dataChart(data) {
|
||||
let xData = [];
|
||||
let yData = [];
|
||||
for (let key in data) {
|
||||
xData.push(key);
|
||||
// 将数据转换为百分比(加上%)
|
||||
yData.push((data[key]).toFixed(1));
|
||||
}
|
||||
xData = xData.map(label => label.split("").join("\n"));//将x轴竖着展示
|
||||
let myChart = echarts.init(document.getElementById("map1"));
|
||||
// 指定图表的配置项和数据
|
||||
let option = {
|
||||
title: {
|
||||
// text: "学院 / 专业通过率变化",
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xData,
|
||||
axisLabel: {
|
||||
interval: 0,//代表显示所有x轴标签显示
|
||||
rotate: 0,//代表倾斜30度显示
|
||||
}
|
||||
},
|
||||
//提示框
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow'
|
||||
},
|
||||
formatter: function (params) {
|
||||
return params[0].name + '<br/>' +
|
||||
'<table>' +
|
||||
'<tr><td>' + params[0].marker + '</td><td style="font-weight: bold;">' + ' ' + params[0].value + '%' + '</td></tr>' +
|
||||
'<tr>'
|
||||
+ '</table>';
|
||||
}
|
||||
},
|
||||
toolbox: {
|
||||
// show: true,
|
||||
// feature: {
|
||||
// magicType: { show: true, type: ['line', 'bar'] },
|
||||
// restore: { show: true },
|
||||
// saveAsImage: { show: true },
|
||||
// },
|
||||
},
|
||||
//网格
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '1%',//网格距离容器底部的距离是容器高度的3%
|
||||
containLabel: true
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
name: '通过率',
|
||||
axisLabel: {
|
||||
formatter: '{value} %'
|
||||
}
|
||||
},
|
||||
series: [
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
dataSourceCet4: [],
|
||||
columns: [
|
||||
{
|
||||
data: yData,
|
||||
type: 'bar',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
label: {
|
||||
show: true, //开启显示
|
||||
position: 'top', //在上方显示
|
||||
textStyle: { //数值样式
|
||||
color: 'black',
|
||||
fontSize: 12
|
||||
},
|
||||
formatter: '{c}%',
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
title: '年级',
|
||||
dataIndex: 'grade',
|
||||
key: 'grade',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '参加人数',
|
||||
dataIndex: 'attendNumber',
|
||||
key: 'attendNumber',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '通过人数',
|
||||
dataIndex: 'passNumber',
|
||||
key: 'passNumber',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '通过率',
|
||||
dataIndex: 'passrate',
|
||||
key: 'passrate',
|
||||
align: 'center',
|
||||
},
|
||||
],
|
||||
Url: {
|
||||
getBatch: '/cet/getBatch',
|
||||
getCollege: '/cet/getCollege',
|
||||
getRate: '/cet/getRateByBatch',
|
||||
getCollegeMajor: '/cet/getCollegeMajor',
|
||||
},
|
||||
loading: false,
|
||||
participate_Piechartloading: false,
|
||||
tableloading: false,
|
||||
collegeOptions: [],
|
||||
collegeMajorOptions: [],
|
||||
batchOptions: [],
|
||||
levelOptions: [
|
||||
{ value: 'cet4', label: '英语四级' },
|
||||
{ value: 'cet6', label: '英语六级' },
|
||||
],
|
||||
level: null,
|
||||
college: null,
|
||||
batch: null,
|
||||
collegeMajor: null,
|
||||
sumRate: null, //总通过率
|
||||
topCollege: null, //顶部选择器选择的学院
|
||||
topBath: null, //顶部选择器选择的批次
|
||||
};
|
||||
// 使用刚指定的配置项和数据显示图表。
|
||||
myChart.setOption(option);
|
||||
},
|
||||
// 获取批次数据
|
||||
async getBatch() {
|
||||
const getBatch = await defHttp.get({ url: this.Url.getBatch });
|
||||
this.batchOptions = getBatch.batches.map(item => {
|
||||
return {
|
||||
value: item.value,
|
||||
label: item.label
|
||||
}
|
||||
});
|
||||
// const getCollege = await defHttp.get({ url: this.Url.getCollege });
|
||||
|
||||
// this.collegeOptions = getCollege.colleges;
|
||||
// this.college = this.collegeOptions[0].value;
|
||||
|
||||
this.level = this.levelOptions[0].value;
|
||||
|
||||
// this.query();
|
||||
mounted() {
|
||||
this.getCollegeMajorData();
|
||||
this.getBatch();
|
||||
this.query();
|
||||
},
|
||||
//获取学院专业级联数据
|
||||
async getCollegeMajorData() {
|
||||
const res = await defHttp.get({ url: this.Url.getCollegeMajor });
|
||||
methods: {
|
||||
dataChart(data) {
|
||||
let xData = [];
|
||||
let yData = [];
|
||||
for (let key in data) {
|
||||
xData.push(key);
|
||||
// 将数据转换为百分比(加上%)
|
||||
yData.push(data[key].toFixed(1));
|
||||
}
|
||||
xData = xData.map((label) => label.split('').join('\n')); //将x轴竖着展示
|
||||
let myChart = echarts.init(document.getElementById('map1'));
|
||||
// 指定图表的配置项和数据
|
||||
let option = {
|
||||
title: {
|
||||
// text: "学院 / 专业通过率变化",
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: xData,
|
||||
axisLabel: {
|
||||
interval: 0, //代表显示所有x轴标签显示
|
||||
rotate: 0, //代表倾斜30度显示
|
||||
},
|
||||
},
|
||||
//提示框
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
},
|
||||
formatter: function (params) {
|
||||
return (
|
||||
params[0].name +
|
||||
'<br/>' +
|
||||
'<table>' +
|
||||
'<tr><td>' +
|
||||
params[0].marker +
|
||||
'</td><td style="font-weight: bold;">' +
|
||||
' ' +
|
||||
params[0].value +
|
||||
'%' +
|
||||
'</td></tr>' +
|
||||
'<tr>' +
|
||||
'</table>'
|
||||
);
|
||||
},
|
||||
},
|
||||
toolbox: {
|
||||
// show: true,
|
||||
// feature: {
|
||||
// magicType: { show: true, type: ['line', 'bar'] },
|
||||
// restore: { show: true },
|
||||
// saveAsImage: { show: true },
|
||||
// },
|
||||
},
|
||||
//网格
|
||||
grid: {
|
||||
left: '3%',
|
||||
right: '4%',
|
||||
bottom: '1%', //网格距离容器底部的距离是容器高度的3%
|
||||
containLabel: true,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
name: '通过率',
|
||||
axisLabel: {
|
||||
formatter: '{value} %',
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
barMaxWidth: 50, // 设置柱子的最大宽度
|
||||
data: yData,
|
||||
type: 'bar',
|
||||
itemStyle: {
|
||||
normal: {
|
||||
label: {
|
||||
show: true, //开启显示
|
||||
position: 'top', //在上方显示
|
||||
textStyle: {
|
||||
//数值样式
|
||||
color: 'black',
|
||||
fontSize: 12,
|
||||
},
|
||||
formatter: '{c}%',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
// 使用刚指定的配置项和数据显示图表。
|
||||
myChart.setOption(option);
|
||||
},
|
||||
// 获取批次数据
|
||||
async getBatch() {
|
||||
const getBatch = await defHttp.get({ url: this.Url.getBatch });
|
||||
this.batchOptions = getBatch.batches.map((item) => {
|
||||
return {
|
||||
value: item.value,
|
||||
label: item.label,
|
||||
};
|
||||
});
|
||||
// const getCollege = await defHttp.get({ url: this.Url.getCollege });
|
||||
|
||||
//通过map方法将数据转换为级联选择器需要的数据格式
|
||||
this.collegeMajorOptions = res.collegeMajor.map(item => {
|
||||
return {
|
||||
value: item.college,
|
||||
label: item.college,
|
||||
children: item.major.map(major => {
|
||||
return {
|
||||
value: major,
|
||||
label: major
|
||||
}
|
||||
})
|
||||
// this.collegeOptions = getCollege.colleges;
|
||||
// this.college = this.collegeOptions[0].value;
|
||||
|
||||
this.level = this.levelOptions[0].value;
|
||||
|
||||
// this.query();
|
||||
},
|
||||
//获取学院专业级联数据
|
||||
async getCollegeMajorData() {
|
||||
const res = await defHttp.get({ url: this.Url.getCollegeMajor });
|
||||
|
||||
//通过map方法将数据转换为级联选择器需要的数据格式
|
||||
this.collegeMajorOptions = res.collegeMajor.map((item) => {
|
||||
return {
|
||||
value: item.college,
|
||||
label: item.college,
|
||||
children: item.major.map((major) => {
|
||||
return {
|
||||
value: major,
|
||||
label: major,
|
||||
};
|
||||
}),
|
||||
};
|
||||
});
|
||||
this.collegeMajorOptions.unshift({ value: '全校', label: '全校' });
|
||||
this.collegeMajor = this.collegeMajorOptions[0].value;
|
||||
console.log(this.collegeMajor);
|
||||
console.log(this.collegeMajorOptions);
|
||||
},
|
||||
// 查询数据
|
||||
async query() {
|
||||
let resultData = null;
|
||||
try {
|
||||
//如果this.batch为null则先赋个值
|
||||
if (!this.batch) {
|
||||
this.batch = '2017-12-01';
|
||||
}
|
||||
if (!this.collegeMajor) {
|
||||
this.collegeMajor = '全校';
|
||||
}
|
||||
//如果this.batch[1]不存在则设为null
|
||||
this.topCollege = this.collegeMajor;
|
||||
this.topBath = this.batch;
|
||||
this.loading = true;
|
||||
let params = {
|
||||
batch: this.batch,
|
||||
college: this.collegeMajor,
|
||||
level: 'cet4',
|
||||
};
|
||||
resultData = await defHttp.get({ url: this.Url.getRate, params });
|
||||
this.sumRate = resultData.sumRate;
|
||||
|
||||
console.log('result', resultData);
|
||||
//表格数据
|
||||
let tableData = [];
|
||||
for (let grade in resultData.gradeData) {
|
||||
tableData.push({
|
||||
grade: grade + '级',
|
||||
attendNumber: resultData.gradeData[grade].allStudent,
|
||||
passNumber: resultData.gradeData[grade].passed,
|
||||
passrate: resultData.gradeData[grade].passRate,
|
||||
});
|
||||
}
|
||||
this.dataSourceCet4 = tableData; //表格数据
|
||||
console.log(this.dataSourceCet4, 'dataSourceCet4');
|
||||
} finally {
|
||||
this.loading = false;
|
||||
this.$nextTick(() => {
|
||||
this.dataChart(resultData.data);
|
||||
|
||||
this.draPieChart_Participate();
|
||||
});
|
||||
}
|
||||
});
|
||||
this.collegeMajorOptions.unshift({ value: '全校', label: '全校' });
|
||||
this.collegeMajor = this.collegeMajorOptions[0].value;
|
||||
console.log(this.collegeMajor)
|
||||
console.log(this.collegeMajorOptions);
|
||||
},
|
||||
// 查询数据
|
||||
async query() {
|
||||
let resultData = null;
|
||||
try {
|
||||
//如果this.batch为null则先赋个值
|
||||
if (!this.batch) {
|
||||
this.batch = '2017-12-01';
|
||||
}
|
||||
if (!this.collegeMajor) {
|
||||
this.collegeMajor = '全校';
|
||||
}
|
||||
//如果this.batch[1]不存在则设为null
|
||||
let major = this.batch.length > 1 ? this.batch[1] : "";
|
||||
this.topCollege = this.collegeMajor;
|
||||
this.topBath = this.batch;
|
||||
this.loading = true;
|
||||
let params = {
|
||||
},
|
||||
|
||||
//绘画饼图--该批次每一年级的通过率饼图
|
||||
async draPieChart_Participate() {
|
||||
//console.log(this.passRatePie);
|
||||
//console.log('piedata', piedata);
|
||||
let queryParams = {
|
||||
batch: this.batch,
|
||||
college: this.collegeMajor,
|
||||
level: 'cet4',
|
||||
};
|
||||
console.log(queryParams, 'queryParams');
|
||||
let url = this.Url.getRate;
|
||||
this.participate_Piechartloading = true;
|
||||
this.tableloading = true;
|
||||
let result = await defHttp.get({ url: url, params: queryParams });
|
||||
console.log(result, 'result');
|
||||
let chartsData = [];
|
||||
for (let key in result.gradeData) {
|
||||
chartsData.push({
|
||||
name: key + '级',
|
||||
value: result.gradeData[key].passRate,
|
||||
});
|
||||
}
|
||||
resultData = await defHttp.get({ url: this.Url.getRate, params });
|
||||
this.sumRate = resultData.sumRate;
|
||||
console.log("result", resultData)
|
||||
} finally {
|
||||
this.loading = false;
|
||||
this.$nextTick(() => {
|
||||
this.dataChart(resultData.data);
|
||||
})
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getCollegeMajorData();
|
||||
this.getBatch();
|
||||
this.query();
|
||||
}
|
||||
let option = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
conginee: false,
|
||||
//字体大小
|
||||
itemStytle: {
|
||||
// 设置阴影效果
|
||||
shadowBlur: 10, // 阴影模糊大小
|
||||
shadowColor: 'rgba(0, 0, 0, 0.3)', // 阴影颜色
|
||||
shadowOffsetX: 5, // 阴影水平方向偏移
|
||||
shadowOffsetY: 5, // 阴影垂直方向偏移
|
||||
fontSize: 100,
|
||||
},
|
||||
},
|
||||
title: {
|
||||
text: '该批次每一年级的通过率饼图',
|
||||
left: 'top',
|
||||
top: '0%',
|
||||
textStyle: {
|
||||
fontSize: 12,
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
top: '10%',
|
||||
left: 'center',
|
||||
|
||||
}
|
||||
itemGap: 3,
|
||||
selectedMode: true,
|
||||
},
|
||||
color: ['#ec2e30', '#c75af1', '#2b9eef', '#eee03f', '#2aed91', '#c5ed3c'],
|
||||
|
||||
series: [
|
||||
{
|
||||
name: '学院/专业该批次通过人数饼图',
|
||||
type: 'pie',
|
||||
radius: ['50%', '100%'],
|
||||
center: ['50%', '50%'],
|
||||
startAngle: 130,
|
||||
top: 80,
|
||||
//暂时没有
|
||||
itemStyle: {
|
||||
// borderRadius: 5,
|
||||
// borderColor: '#fff',
|
||||
borderWidth: 2,
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
// position: 'inside',
|
||||
fontSize: 12,
|
||||
overflow: 'truncate',
|
||||
},
|
||||
labelLine: {
|
||||
show: true,
|
||||
smooth: true,
|
||||
length: 10,
|
||||
},
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: 15,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
},
|
||||
data: chartsData,
|
||||
},
|
||||
{
|
||||
type: 'pie',
|
||||
startAngle: 130,
|
||||
top: 80,
|
||||
radius: ['40%', '51%'],
|
||||
center: ['50%', '50%'],
|
||||
//暂时没有
|
||||
itemStyle: {
|
||||
// borderRadius: 3,
|
||||
// borderColor: '#fff',
|
||||
borderWidth: 2,
|
||||
},
|
||||
label: {
|
||||
show: false,
|
||||
},
|
||||
hoverAnimation: false,
|
||||
legendHoverLink: false,
|
||||
// animationn:false,
|
||||
tooltip: {
|
||||
show: false,
|
||||
},
|
||||
data: chartsData,
|
||||
},
|
||||
],
|
||||
animationDurationUpate: 500,
|
||||
};
|
||||
this.participate_Piechartloading = false;
|
||||
this.tableloading = false;
|
||||
this.$nextTick(() => {
|
||||
var myChart = echarts.init(document.getElementById('participate_Piechart'));
|
||||
myChart.setOption(option);
|
||||
});
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.container {
|
||||
// display: flex;
|
||||
background-color: #fff;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.09);
|
||||
}
|
||||
.container {
|
||||
// display: flex;
|
||||
background-color: #fff;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.09);
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 20px;
|
||||
color: rgb(8, 8, 8);
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
.title {
|
||||
font-size: 20px;
|
||||
color: rgb(8, 8, 8);
|
||||
font-weight: bold;
|
||||
}
|
||||
.tip {
|
||||
margin-bottom: 10px;
|
||||
background-color: #d0e5fe;
|
||||
opacity: 0.9;
|
||||
}
|
||||
</style>
|
||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,24 +1,24 @@
|
|||
import {BasicColumn} from '/@/components/Table';
|
||||
import {FormSchema} from '/@/components/Table';
|
||||
import { rules} from '/@/utils/helper/validator';
|
||||
import { BasicColumn } from '/@/components/Table';
|
||||
import { FormSchema } from '/@/components/Table';
|
||||
import { rules } from '/@/utils/helper/validator';
|
||||
import { render } from '/@/utils/common/renderUtils';
|
||||
//列表数据
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
{
|
||||
title: '考场名称',
|
||||
align:"center",
|
||||
dataIndex: 'locationName'
|
||||
},
|
||||
align: 'center',
|
||||
dataIndex: 'locationName',
|
||||
},
|
||||
// {
|
||||
// title: '父节点id',
|
||||
// align:"center",
|
||||
// dataIndex: 'parentLocationId'
|
||||
// },
|
||||
{
|
||||
{
|
||||
title: '考场人数',
|
||||
align:"center",
|
||||
dataIndex: 'personNumber'
|
||||
},
|
||||
align: 'center',
|
||||
dataIndex: 'personNumber',
|
||||
},
|
||||
// {
|
||||
// title: '排序号',
|
||||
// align:"center",
|
||||
|
@ -47,37 +47,36 @@ export const formSchema: FormSchema[] = [
|
|||
},
|
||||
{
|
||||
label: '考场人数',
|
||||
field: 'personNumber',
|
||||
component: 'Input',
|
||||
|
||||
field: 'personNumber',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: '排序号',
|
||||
field: 'sortNumber',
|
||||
component: 'InputNumber',
|
||||
show: false
|
||||
show: false,
|
||||
},
|
||||
// TODO 主键隐藏字段,目前写死为ID
|
||||
{
|
||||
label: '',
|
||||
field: 'id',
|
||||
component: 'Input',
|
||||
show: false,
|
||||
},
|
||||
// TODO 主键隐藏字段,目前写死为ID
|
||||
{
|
||||
label: '',
|
||||
field: 'id',
|
||||
component: 'Input',
|
||||
show: false
|
||||
},
|
||||
];
|
||||
|
||||
// 高级查询数据
|
||||
export const superQuerySchema = {
|
||||
locationName: {title: '存放地名称',order: 0,view: 'text', type: 'string',},
|
||||
parentLocationId: {title: '父节点id',order: 1,view: 'text', type: 'string',},
|
||||
sortNumber: {title: '排序号',order: 2,view: 'number', type: 'number',},
|
||||
locationName: { title: '存放地名称', order: 0, view: 'text', type: 'string' },
|
||||
parentLocationId: { title: '父节点id', order: 1, view: 'text', type: 'string' },
|
||||
sortNumber: { title: '排序号', order: 2, view: 'number', type: 'number' },
|
||||
};
|
||||
|
||||
/**
|
||||
* 流程表单调用这个方法获取formSchema
|
||||
* @param param
|
||||
*/
|
||||
export function getBpmFormSchema(_formData): FormSchema[]{
|
||||
* 流程表单调用这个方法获取formSchema
|
||||
* @param param
|
||||
*/
|
||||
export function getBpmFormSchema(_formData): FormSchema[] {
|
||||
// 默认和原始表单保持一致 如果流程中配置了权限数据,这里需要单独处理formSchema
|
||||
return formSchema;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,206 +1,203 @@
|
|||
<template>
|
||||
<div style="background: #ececec; padding-top: 0px;padding-left: 20px;padding-right: 20px;padding-bottom: 20px;">
|
||||
<a-card title="考场座位查询" :bordered="false">
|
||||
<a-row>
|
||||
<a-col :span="5">
|
||||
<locationaTree ref="locationaTrees" :height="700" @onSelect="onSelect"></locationaTree>
|
||||
</a-col>
|
||||
<a-col :span="19">
|
||||
<!--引用表格-->
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" preIcon="ant-design:import-outlined"
|
||||
@click="onImportXls">导入</j-upload-button>
|
||||
<a-dropdown v-if="selectedRowKeys.length > 0">
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item key="1" @click="batchHandleDelete">
|
||||
<Icon icon="ant-design:delete-outlined"></Icon>
|
||||
删除
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button>批量操作
|
||||
<Icon icon="mdi:chevron-down"></Icon>
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
<!-- 高级查询 -->
|
||||
<super-query :config="superQueryConfig" @search="handleSuperQuery" />
|
||||
</template>
|
||||
<!--操作栏-->
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
|
||||
</template>
|
||||
<!--字段回显插槽-->
|
||||
<template v-slot:bodyCell="{ column, record, index, text }">
|
||||
</template>
|
||||
</BasicTable>
|
||||
<!-- 表单区域 -->
|
||||
<CetLocationModal @register="registerModal" @success="handleSuccess"></CetLocationModal>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
<div style="background: #ececec; padding-top: 0px; padding-left: 20px; padding-right: 20px; padding-bottom: 20px">
|
||||
|
||||
<a-card title="考场座位查询" :bordered="false">
|
||||
<a-row>
|
||||
<a-col :span="5">
|
||||
<locationaTree ref="locationaTrees" :height="700" @on-select="onSelect" />
|
||||
</a-col>
|
||||
<a-col :span="19">
|
||||
<!--引用表格-->
|
||||
<BasicTable @register="registerTable" :rowSelection="rowSelection">
|
||||
<!--插槽:table标题-->
|
||||
<template #tableTitle>
|
||||
<a-button type="primary" @click="handleAdd" preIcon="ant-design:plus-outlined"> 新增</a-button>
|
||||
<a-button type="primary" preIcon="ant-design:export-outlined" @click="onExportXls"> 导出</a-button>
|
||||
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<a-dropdown v-if="selectedRowKeys.length > 0">
|
||||
<template #overlay>
|
||||
<a-menu>
|
||||
<a-menu-item key="1" @click="batchHandleDelete">
|
||||
<Icon icon="ant-design:delete-outlined" />
|
||||
删除
|
||||
</a-menu-item>
|
||||
</a-menu>
|
||||
</template>
|
||||
<a-button
|
||||
>批量操作
|
||||
<Icon icon="mdi:chevron-down" />
|
||||
</a-button>
|
||||
</a-dropdown>
|
||||
<!-- 高级查询 -->
|
||||
<super-query :config="superQueryConfig" @search="handleSuperQuery" />
|
||||
</template>
|
||||
<!--操作栏-->
|
||||
<template #action="{ record }">
|
||||
<TableAction :actions="getTableAction(record)" :dropDownActions="getDropDownAction(record)" />
|
||||
</template>
|
||||
<!--字段回显插槽-->
|
||||
<template #bodyCell="{ column, record, index, text }"> </template>
|
||||
</BasicTable>
|
||||
<!-- 表单区域 -->
|
||||
<CetLocationModal @register="registerModal" @success="handleSuccess" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" name="CET-cetLocation" setup>
|
||||
import { ref, reactive, computed, unref } from 'vue';
|
||||
import { BasicTable, useTable, TableAction } from '/@/components/Table';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { useListPage } from '/@/hooks/system/useListPage'
|
||||
import CetLocationModal from './components/CetLocationModal.vue'
|
||||
import locationaTree from './components/locationaTree.vue'
|
||||
import { columns, searchFormSchema, superQuerySchema } from './CetLocation.data';
|
||||
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './CetLocation.api';
|
||||
import { downloadFile } from '/@/utils/common/renderUtils';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { ref, reactive, computed, unref } from 'vue';
|
||||
import { BasicTable, useTable, TableAction } from '/@/components/Table';
|
||||
import { useModal } from '/@/components/Modal';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import CetLocationModal from './components/CetLocationModal.vue';
|
||||
import locationaTree from './components/locationaTree.vue';
|
||||
import { columns, searchFormSchema, superQuerySchema } from './CetLocation.data';
|
||||
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './CetLocation.api';
|
||||
import { downloadFile } from '/@/utils/common/renderUtils';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
|
||||
const queryParam = reactive<any>({});
|
||||
const checkedKeys = ref<Array<string | number>>([]);
|
||||
const userStore = useUserStore();
|
||||
//注册model
|
||||
const [registerModal, { openModal }] = useModal();
|
||||
//注册table数据
|
||||
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
|
||||
tableProps: {
|
||||
title: 'cet_location',
|
||||
api: list,
|
||||
columns,
|
||||
canResize: false,
|
||||
formConfig: {
|
||||
//labelWidth: 120,
|
||||
schemas: searchFormSchema,
|
||||
autoSubmitOnEnter: true,
|
||||
showAdvancedButton: true,
|
||||
fieldMapToNumber: [
|
||||
],
|
||||
fieldMapToTime: [
|
||||
],
|
||||
const queryParam = reactive<any>({});
|
||||
const checkedKeys = ref<Array<string | number>>([]);
|
||||
const userStore = useUserStore();
|
||||
//注册model
|
||||
const [registerModal, { openModal }] = useModal();
|
||||
//注册table数据
|
||||
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
|
||||
tableProps: {
|
||||
title: 'cet_location',
|
||||
api: list,
|
||||
columns,
|
||||
canResize: false,
|
||||
formConfig: {
|
||||
//labelWidth: 120,
|
||||
schemas: searchFormSchema,
|
||||
autoSubmitOnEnter: true,
|
||||
showAdvancedButton: true,
|
||||
fieldMapToNumber: [],
|
||||
fieldMapToTime: [],
|
||||
},
|
||||
actionColumn: {
|
||||
width: 120,
|
||||
fixed: 'right',
|
||||
},
|
||||
beforeFetch: (params) => {
|
||||
return Object.assign(params, queryParam);
|
||||
},
|
||||
},
|
||||
actionColumn: {
|
||||
width: 120,
|
||||
fixed: 'right'
|
||||
exportConfig: {
|
||||
name: 'cet_location',
|
||||
url: getExportUrl,
|
||||
params: queryParam,
|
||||
},
|
||||
beforeFetch: (params) => {
|
||||
return Object.assign(params, queryParam);
|
||||
importConfig: {
|
||||
url: getImportUrl,
|
||||
success: handleSuccess,
|
||||
},
|
||||
},
|
||||
exportConfig: {
|
||||
name: "cet_location",
|
||||
url: getExportUrl,
|
||||
params: queryParam,
|
||||
},
|
||||
importConfig: {
|
||||
url: getImportUrl,
|
||||
success: handleSuccess
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext
|
||||
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
|
||||
|
||||
// 高级查询配置
|
||||
const superQueryConfig = reactive(superQuerySchema);
|
||||
// 高级查询配置
|
||||
const superQueryConfig = reactive(superQuerySchema);
|
||||
|
||||
/**
|
||||
* 高级查询事件
|
||||
*/
|
||||
function handleSuperQuery(params) {
|
||||
Object.keys(params).map((k) => {
|
||||
queryParam[k] = params[k];
|
||||
});
|
||||
reload();
|
||||
}
|
||||
/*
|
||||
* 树查询
|
||||
*/
|
||||
function onSelect(selectedRowKeys) {
|
||||
//将其切分为字符串
|
||||
selectedRowKeys = selectedRowKeys.join(',')
|
||||
console.log(selectedRowKeys)
|
||||
queryParam.id = selectedRowKeys
|
||||
reload()
|
||||
}
|
||||
/**
|
||||
* 新增事件
|
||||
*/
|
||||
function handleAdd() {
|
||||
openModal(true, {
|
||||
isUpdate: false,
|
||||
showFooter: true,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 编辑事件
|
||||
*/
|
||||
function handleEdit(record: Recordable) {
|
||||
openModal(true, {
|
||||
record,
|
||||
isUpdate: true,
|
||||
showFooter: true,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 详情
|
||||
*/
|
||||
function handleDetail(record: Recordable) {
|
||||
openModal(true, {
|
||||
record,
|
||||
isUpdate: true,
|
||||
showFooter: false,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 删除事件
|
||||
*/
|
||||
async function handleDelete(record) {
|
||||
await deleteOne({ id: record.id }, handleSuccess);
|
||||
}
|
||||
/**
|
||||
* 批量删除事件
|
||||
*/
|
||||
async function batchHandleDelete() {
|
||||
await batchDelete({ ids: selectedRowKeys.value }, handleSuccess);
|
||||
}
|
||||
/**
|
||||
* 成功回调
|
||||
*/
|
||||
function handleSuccess() {
|
||||
(selectedRowKeys.value = []) && reload();
|
||||
}
|
||||
/**
|
||||
/**
|
||||
* 高级查询事件
|
||||
*/
|
||||
function handleSuperQuery(params) {
|
||||
Object.keys(params).map((k) => {
|
||||
queryParam[k] = params[k];
|
||||
});
|
||||
reload();
|
||||
}
|
||||
/*
|
||||
* 树查询
|
||||
*/
|
||||
function onSelect(selectedRowKeys) {
|
||||
//将其切分为字符串
|
||||
selectedRowKeys = selectedRowKeys.join(',');
|
||||
console.log(selectedRowKeys);
|
||||
queryParam.code = selectedRowKeys;
|
||||
reload();
|
||||
}
|
||||
/**
|
||||
* 新增事件
|
||||
*/
|
||||
function handleAdd() {
|
||||
openModal(true, {
|
||||
isUpdate: false,
|
||||
showFooter: true,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 编辑事件
|
||||
*/
|
||||
function handleEdit(record: Recordable) {
|
||||
openModal(true, {
|
||||
record,
|
||||
isUpdate: true,
|
||||
showFooter: true,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 详情
|
||||
*/
|
||||
function handleDetail(record: Recordable) {
|
||||
openModal(true, {
|
||||
record,
|
||||
isUpdate: true,
|
||||
showFooter: false,
|
||||
});
|
||||
}
|
||||
/**
|
||||
* 删除事件
|
||||
*/
|
||||
async function handleDelete(record) {
|
||||
await deleteOne({ code: record.code }, handleSuccess);
|
||||
}
|
||||
/**
|
||||
* 批量删除事件
|
||||
*/
|
||||
async function batchHandleDelete() {
|
||||
await batchDelete({ codes: selectedRowKeys.value }, handleSuccess);
|
||||
}
|
||||
/**
|
||||
* 成功回调
|
||||
*/
|
||||
function handleSuccess() {
|
||||
(selectedRowKeys.value = []) && reload();
|
||||
}
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record) {
|
||||
return [
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
}
|
||||
]
|
||||
}
|
||||
/**
|
||||
function getTableAction(record) {
|
||||
return [
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
/**
|
||||
* 下拉操作栏
|
||||
*/
|
||||
function getDropDownAction(record) {
|
||||
return [
|
||||
{
|
||||
label: '详情',
|
||||
onClick: handleDetail.bind(null, record),
|
||||
}, {
|
||||
label: '删除',
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
function getDropDownAction(record) {
|
||||
return [
|
||||
{
|
||||
label: '详情',
|
||||
onClick: handleDetail.bind(null, record),
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped></style>
|
||||
<style scoped></style>
|
||||
|
|
|
@ -1,70 +1,70 @@
|
|||
<template>
|
||||
<div style="min-height: 400px">
|
||||
<BasicForm @register="registerForm"></BasicForm>
|
||||
<div style="width: 100%;text-align: center" v-if="!formDisabled">
|
||||
<a-button @click="submitForm" pre-icon="ant-design:check" type="primary">提 交</a-button>
|
||||
</div>
|
||||
<div style="min-height: 400px">
|
||||
<BasicForm @register="registerForm" />
|
||||
<div style="width: 100%; text-align: center" v-if="!formDisabled">
|
||||
<a-button @click="submitForm" pre-icon="ant-design:check" type="primary">提 交</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import {BasicForm, useForm} from '/@/components/Form/index';
|
||||
import {computed, defineComponent} from 'vue';
|
||||
import {defHttp} from '/@/utils/http/axios';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import {getBpmFormSchema} from '../CetLocation.data';
|
||||
import {saveOrUpdate} from '../CetLocation.api';
|
||||
|
||||
export default defineComponent({
|
||||
name: "CetLocationForm",
|
||||
components:{
|
||||
BasicForm
|
||||
},
|
||||
props:{
|
||||
formData: propTypes.object.def({}),
|
||||
formBpm: propTypes.bool.def(true),
|
||||
},
|
||||
setup(props){
|
||||
const [registerForm, { setFieldsValue, setProps, getFieldsValue }] = useForm({
|
||||
labelWidth: 150,
|
||||
schemas: getBpmFormSchema(props.formData),
|
||||
showActionButtonGroup: false,
|
||||
baseColProps: {span: 24}
|
||||
});
|
||||
import { BasicForm, useForm } from '/@/components/Form/index';
|
||||
import { computed, defineComponent } from 'vue';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { propTypes } from '/@/utils/propTypes';
|
||||
import { getBpmFormSchema } from '../CetLocation.data';
|
||||
import { saveOrUpdate } from '../CetLocation.api';
|
||||
|
||||
const formDisabled = computed(()=>{
|
||||
if(props.formData.disabled === false){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
export default defineComponent({
|
||||
name: 'CetLocationForm',
|
||||
components: {
|
||||
BasicForm,
|
||||
},
|
||||
props: {
|
||||
formData: propTypes.object.def({}),
|
||||
formBpm: propTypes.bool.def(true),
|
||||
},
|
||||
setup(props) {
|
||||
const [registerForm, { setFieldsValue, setProps, getFieldsValue }] = useForm({
|
||||
labelWidth: 150,
|
||||
schemas: getBpmFormSchema(props.formData),
|
||||
showActionButtonGroup: false,
|
||||
baseColProps: { span: 24 },
|
||||
});
|
||||
|
||||
let formData = {};
|
||||
const queryByIdUrl = '/CET/cetLocation/queryById';
|
||||
async function initFormData(){
|
||||
let params = {id: props.formData.dataId};
|
||||
const data = await defHttp.get({url: queryByIdUrl, params});
|
||||
formData = {...data}
|
||||
//设置表单的值
|
||||
await setFieldsValue(formData);
|
||||
//默认是禁用
|
||||
await setProps({disabled: formDisabled.value})
|
||||
}
|
||||
|
||||
async function submitForm() {
|
||||
let data = getFieldsValue();
|
||||
let params = Object.assign({}, formData, data);
|
||||
console.log('表单数据', params)
|
||||
await saveOrUpdate(params, true)
|
||||
}
|
||||
|
||||
initFormData();
|
||||
|
||||
return {
|
||||
registerForm,
|
||||
formDisabled,
|
||||
submitForm,
|
||||
}
|
||||
const formDisabled = computed(() => {
|
||||
if (props.formData.disabled === false) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
return true;
|
||||
});
|
||||
|
||||
let formData = {};
|
||||
const queryByIdUrl = '/CET/cetLocation/queryById';
|
||||
async function initFormData() {
|
||||
let params = { code: props.formData.dataId };
|
||||
const data = await defHttp.get({ url: queryByIdUrl, params });
|
||||
formData = { ...data };
|
||||
//设置表单的值
|
||||
await setFieldsValue(formData);
|
||||
//默认是禁用
|
||||
await setProps({ disabled: formDisabled.value });
|
||||
}
|
||||
|
||||
async function submitForm() {
|
||||
let data = getFieldsValue();
|
||||
let params = Object.assign({}, formData, data);
|
||||
console.log('表单数据', params);
|
||||
await saveOrUpdate(params, true);
|
||||
}
|
||||
|
||||
initFormData();
|
||||
|
||||
return {
|
||||
registerForm,
|
||||
formDisabled,
|
||||
submitForm,
|
||||
};
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -6,8 +6,8 @@
|
|||
<a-form-item label="姓名" name="name">
|
||||
<a-input v-model:value="search.name" placeholder="请输入学生姓名" />
|
||||
</a-form-item>
|
||||
<a-form-item label="学号" name="id">
|
||||
<a-input-number :controls="false" v-model:value="search.id" placeholder="请输入学生学号" />
|
||||
<a-form-item label="学号" name="code">
|
||||
<a-input-number :controls="false" v-model:value="search.code" placeholder="请输入学生学号" />
|
||||
</a-form-item>
|
||||
<a-form-item>
|
||||
<a-button type="primary" @click="handleSearch">查询</a-button>
|
||||
|
@ -23,7 +23,7 @@
|
|||
<span>学生姓名:{{ tableData[tableData.length - 1]?.name }}</span>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<span>学生学号:{{ tableData[tableData.length - 1]?.id }}</span>
|
||||
<span>学生学号:{{ tableData[tableData.length - 1]?.code }}</span>
|
||||
</a-col>
|
||||
<a-col :span="6">
|
||||
<span>所在学院:{{ tableData[tableData.length - 1]?.college }}</span>
|
||||
|
@ -46,16 +46,16 @@
|
|||
import type { Rule } from 'ant-design-vue/es/form';
|
||||
interface FormState {
|
||||
name: string;
|
||||
id: string;
|
||||
code: string;
|
||||
}
|
||||
|
||||
const search: UnwrapRef<FormState> = reactive({
|
||||
name: '',
|
||||
id: '',
|
||||
code: '',
|
||||
});
|
||||
const isShow = ref(false);
|
||||
const loading = ref(false);
|
||||
const tableData = ref([]);
|
||||
const tableData: any = ref([]);
|
||||
const tableLabel = ref([
|
||||
{
|
||||
title: '考试批次',
|
||||
|
@ -90,7 +90,7 @@
|
|||
]);
|
||||
const rules: Record<string, Rule[]> = {
|
||||
name: [{ required: true, message: '请输入学生姓名', trigger: 'change' }],
|
||||
id: [{ required: true, message: '请输入学生学号', trigger: 'change' }],
|
||||
code: [{ required: true, message: '请输入学生学号', trigger: 'change' }],
|
||||
};
|
||||
const url = ref({
|
||||
getData: '/cet_4/getDataByStudent',
|
||||
|
@ -116,7 +116,7 @@
|
|||
};
|
||||
const handleClear = () => {
|
||||
search.name = '';
|
||||
search.id = '';
|
||||
search.code = '';
|
||||
isShow.value = false;
|
||||
tableData.value = [];
|
||||
};
|
||||
|
|
|
@ -0,0 +1,72 @@
|
|||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { useMessage } from "/@/hooks/web/useMessage";
|
||||
|
||||
const { createConfirm } = useMessage();
|
||||
|
||||
enum Api {
|
||||
list = '/com/cet4Major/list',
|
||||
save='/com/cet4Major/add',
|
||||
edit='/com/cet4Major/edit',
|
||||
deleteOne = '/com/cet4Major/delete',
|
||||
deleteBatch = '/com/cet4Major/deleteBatch',
|
||||
importExcel = '/com/cet4Major/importExcel',
|
||||
exportXls = '/com/cet4Major/exportXls',
|
||||
}
|
||||
|
||||
/**
|
||||
* 导出api
|
||||
* @param params
|
||||
*/
|
||||
export const getExportUrl = Api.exportXls;
|
||||
|
||||
/**
|
||||
* 导入api
|
||||
*/
|
||||
export const getImportUrl = Api.importExcel;
|
||||
|
||||
/**
|
||||
* 列表接口
|
||||
* @param params
|
||||
*/
|
||||
export const list = (params) => defHttp.get({ url: Api.list, params });
|
||||
|
||||
/**
|
||||
* 删除单个
|
||||
* @param params
|
||||
* @param handleSuccess
|
||||
*/
|
||||
export const deleteOne = (params,handleSuccess) => {
|
||||
return defHttp.delete({url: Api.deleteOne, params}, {joinParamsToUrl: true}).then(() => {
|
||||
handleSuccess();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除
|
||||
* @param params
|
||||
* @param handleSuccess
|
||||
*/
|
||||
export const batchDelete = (params, handleSuccess) => {
|
||||
createConfirm({
|
||||
iconType: 'warning',
|
||||
title: '确认删除',
|
||||
content: '是否删除选中数据',
|
||||
okText: '确认',
|
||||
cancelText: '取消',
|
||||
onOk: () => {
|
||||
return defHttp.delete({url: Api.deleteBatch, data: params}, {joinParamsToUrl: true}).then(() => {
|
||||
handleSuccess();
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存或者更新
|
||||
* @param params
|
||||
* @param isUpdate
|
||||
*/
|
||||
export const saveOrUpdate = (params, isUpdate) => {
|
||||
let url = isUpdate ? Api.edit : Api.save;
|
||||
return defHttp.post({ url: url, params }, { isTransformResponse: false });
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
import { BasicColumn } from '/@/components/Table';
|
||||
import { FormSchema } from '/@/components/Table';
|
||||
import { rules } from '/@/utils/helper/validator';
|
||||
import { render } from '/@/utils/common/renderUtils';
|
||||
//列表数据
|
||||
export const columns: BasicColumn[] = [
|
||||
{
|
||||
title: '年级',
|
||||
dataIndex: 'entrydate',
|
||||
key: 'entrydate',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '学生人数',
|
||||
dataIndex: 'studentNumber',
|
||||
key: 'studentNumber',
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
|
||||
//查询数据
|
||||
export const searchFormSchema: FormSchema[] = [];
|
||||
|
||||
//表单数据
|
||||
export const formSchema: FormSchema[] = [
|
||||
{
|
||||
label: 'name',
|
||||
field: 'name',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: 'college',
|
||||
field: 'college',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: 'majorId',
|
||||
field: 'majorId',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: 'majorname',
|
||||
field: 'majorname',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: 'className',
|
||||
field: 'className',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: 'educate',
|
||||
field: 'educate',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: 'entrydate',
|
||||
field: 'entrydate',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: 'campus',
|
||||
field: 'campus',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: 'state',
|
||||
field: 'state',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: 'level',
|
||||
field: 'level',
|
||||
component: 'Input',
|
||||
},
|
||||
{
|
||||
label: 'category',
|
||||
field: 'category',
|
||||
component: 'Input',
|
||||
},
|
||||
// TODO 主键隐藏字段,目前写死为ID
|
||||
{
|
||||
label: '',
|
||||
field: 'id',
|
||||
component: 'Input',
|
||||
show: false,
|
||||
},
|
||||
];
|
||||
|
||||
// 高级查询数据
|
||||
export const superQuerySchema = {
|
||||
name: { title: 'name', order: 0, view: 'text', type: 'string' },
|
||||
college: { title: 'college', order: 1, view: 'text', type: 'string' },
|
||||
majorId: { title: 'majorId', order: 2, view: 'text', type: 'string' },
|
||||
majorname: { title: 'majorname', order: 3, view: 'text', type: 'string' },
|
||||
className: { title: 'className', order: 4, view: 'text', type: 'string' },
|
||||
educate: { title: 'educate', order: 5, view: 'text', type: 'string' },
|
||||
entrydate: { title: 'entrydate', order: 6, view: 'text', type: 'string' },
|
||||
campus: { title: 'campus', order: 7, view: 'text', type: 'string' },
|
||||
state: { title: 'state', order: 8, view: 'text', type: 'string' },
|
||||
level: { title: 'level', order: 9, view: 'text', type: 'string' },
|
||||
category: { title: 'category', order: 10, view: 'text', type: 'string' },
|
||||
};
|
|
@ -0,0 +1,248 @@
|
|||
<template>
|
||||
<div class="p-2">
|
||||
<a-card title="学生信息导入" :bordered="false">
|
||||
<a-row :gutter="2">
|
||||
<a-col :xl="24" :style="{ marginBottom: '24px' }">
|
||||
<div class="clearfix">
|
||||
<j-upload-button type="primary" preIcon="ant-design:import-outlined" @click="onImportXls">导入</j-upload-button>
|
||||
<div class="clearfix">
|
||||
<a-button type="primary" preIcon="ant-design:import-outlined" @click="asyncData">同步数据</a-button>
|
||||
</div>
|
||||
<!--<div class="clearfix">
|
||||
<a-button preIcon="ant-design:export-outlined" @click="downloadTemplate"> 下载模板</a-button>
|
||||
</div>-->
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="10">
|
||||
<a-col :xl="24">
|
||||
<a-table :dataSource="dataSourceCet4" :columns="columns" :pagination="false" :loading="loading" bordered class="custom-table" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
|
||||
<!--查询区域-->
|
||||
<!--<div class="jeecg-basic-table-form-container">
|
||||
<a-form ref="formRef" @keyup.enter.native="searchQuery" :model="queryParam" :label-col="labelCol" :wrapper-col="wrapperCol">
|
||||
<a-row :gutter="24" />
|
||||
</a-form>
|
||||
</div>-->
|
||||
<!--引用表格-->
|
||||
|
||||
<!-- 表单区域 -->
|
||||
<Cet4MajorModal ref="registerModal" @success="handleSuccess" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts" name="com-cet4Major" setup>
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { BasicTable, useTable, TableAction } from '/@/components/Table';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { useListPage } from '/@/hooks/system/useListPage';
|
||||
import { columns, superQuerySchema } from './Cet4Major.data';
|
||||
import { list, deleteOne, batchDelete, getImportUrl, getExportUrl } from './Cet4Major.api';
|
||||
import { downloadFile } from '/@/utils/common/renderUtils';
|
||||
import Cet4MajorModal from './components/Cet4MajorModal.vue';
|
||||
import { useUserStore } from '/@/store/modules/user';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
const url = {
|
||||
downLoadTemplate: '/cetDataImport/downloadTemplate',
|
||||
importCet4Data: '/cetDataImport/dbfImport',
|
||||
loadImportData: '/com/cet4Major/loadTable',
|
||||
asyncData: '/com/cet4Major/asyncData',
|
||||
};
|
||||
const asyncData = async () => {
|
||||
const res = await defHttp.post({ url: url.asyncData });
|
||||
message.success('正在同步');
|
||||
};
|
||||
const loading = ref(false);
|
||||
// 定义表格的数据源
|
||||
const dataSourceCet4 = ref([]);
|
||||
const formRef = ref();
|
||||
const queryParam = reactive<any>({});
|
||||
const toggleSearchStatus = ref<boolean>(false);
|
||||
const registerModal = ref();
|
||||
const userStore = useUserStore();
|
||||
//注册table数据
|
||||
const { prefixCls, tableContext, onExportXls, onImportXls } = useListPage({
|
||||
tableProps: {
|
||||
title: 'cet4_major',
|
||||
api: list,
|
||||
columns,
|
||||
canResize: false,
|
||||
useSearchForm: false,
|
||||
actionColumn: {
|
||||
width: 120,
|
||||
fixed: 'right',
|
||||
},
|
||||
beforeFetch: (params) => {
|
||||
return Object.assign(params, queryParam);
|
||||
},
|
||||
},
|
||||
exportConfig: {
|
||||
name: 'cet4_major',
|
||||
url: getExportUrl,
|
||||
params: queryParam,
|
||||
},
|
||||
importConfig: {
|
||||
url: getImportUrl,
|
||||
success: handleSuccess,
|
||||
},
|
||||
});
|
||||
//处理表格数据源
|
||||
const fetchData = async () => {
|
||||
loading.value = true; // 开始加载
|
||||
try {
|
||||
const response = await defHttp.post({ url: url.loadImportData });
|
||||
console.log(response, 'response');
|
||||
dataSourceCet4.value = response.data; // 将数据绑定到表格
|
||||
} catch (error) {
|
||||
message.error('Failed to load data.');
|
||||
} finally {
|
||||
loading.value = false; // 加载结束
|
||||
}
|
||||
};
|
||||
const [registerTable, { reload, collapseAll, updateTableDataRecord, findTableDataRecord, getDataSource }, { rowSelection, selectedRowKeys }] =
|
||||
tableContext;
|
||||
const labelCol = reactive({
|
||||
xs: 24,
|
||||
sm: 4,
|
||||
xl: 6,
|
||||
xxl: 4,
|
||||
});
|
||||
const wrapperCol = reactive({
|
||||
xs: 24,
|
||||
sm: 20,
|
||||
});
|
||||
|
||||
// 高级查询配置
|
||||
const superQueryConfig = reactive(superQuerySchema);
|
||||
|
||||
/**
|
||||
* 高级查询事件
|
||||
*/
|
||||
function handleSuperQuery(params) {
|
||||
Object.keys(params).map((k) => {
|
||||
queryParam[k] = params[k];
|
||||
});
|
||||
searchQuery();
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增事件
|
||||
*/
|
||||
function handleAdd() {
|
||||
registerModal.value.disableSubmit = false;
|
||||
registerModal.value.add();
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑事件
|
||||
*/
|
||||
function handleEdit(record: Recordable) {
|
||||
registerModal.value.disableSubmit = false;
|
||||
registerModal.value.edit(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* 详情
|
||||
*/
|
||||
function handleDetail(record: Recordable) {
|
||||
registerModal.value.disableSubmit = true;
|
||||
registerModal.value.edit(record);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除事件
|
||||
*/
|
||||
async function handleDelete(record) {
|
||||
await deleteOne({ id: record.id }, handleSuccess);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除事件
|
||||
*/
|
||||
async function batchHandleDelete() {
|
||||
await batchDelete({ ids: selectedRowKeys.value }, handleSuccess);
|
||||
}
|
||||
|
||||
/**
|
||||
* 成功回调
|
||||
*/
|
||||
function handleSuccess() {
|
||||
(selectedRowKeys.value = []) && reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 操作栏
|
||||
*/
|
||||
function getTableAction(record) {
|
||||
return [
|
||||
{
|
||||
label: '编辑',
|
||||
onClick: handleEdit.bind(null, record),
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 下拉操作栏
|
||||
*/
|
||||
function getDropDownAction(record) {
|
||||
return [
|
||||
{
|
||||
label: '详情',
|
||||
onClick: handleDetail.bind(null, record),
|
||||
},
|
||||
{
|
||||
label: '删除',
|
||||
popConfirm: {
|
||||
title: '是否确认删除',
|
||||
confirm: handleDelete.bind(null, record),
|
||||
placement: 'topLeft',
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询
|
||||
*/
|
||||
function searchQuery() {
|
||||
reload();
|
||||
}
|
||||
|
||||
/**
|
||||
* 重置
|
||||
*/
|
||||
function searchReset() {
|
||||
formRef.value.resetFields();
|
||||
selectedRowKeys.value = [];
|
||||
//刷新数据
|
||||
reload();
|
||||
}
|
||||
onMounted(fetchData);
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.jeecg-basic-table-form-container {
|
||||
padding: 0;
|
||||
.table-page-search-submitButtons {
|
||||
display: block;
|
||||
margin-bottom: 24px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.query-group-cust {
|
||||
min-width: 100px !important;
|
||||
}
|
||||
.query-group-split-cust {
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
}
|
||||
}
|
||||
.clearfix {
|
||||
display: flex;
|
||||
padding-left: 10px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,193 @@
|
|||
<template>
|
||||
<a-spin :spinning="confirmLoading">
|
||||
<a-form ref="formRef" class="antd-modal-form" :labelCol="labelCol" :wrapperCol="wrapperCol">
|
||||
<a-row>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="name" v-bind="validateInfos.name">
|
||||
<a-input v-model:value="formData.name" placeholder="请输入name" :disabled="disabled"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="college" v-bind="validateInfos.college">
|
||||
<a-input v-model:value="formData.college" placeholder="请输入college" :disabled="disabled"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="majorId" v-bind="validateInfos.majorId">
|
||||
<a-input v-model:value="formData.majorId" placeholder="请输入majorId" :disabled="disabled"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="majorname" v-bind="validateInfos.majorname">
|
||||
<a-input v-model:value="formData.majorname" placeholder="请输入majorname" :disabled="disabled"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="className" v-bind="validateInfos.className">
|
||||
<a-input v-model:value="formData.className" placeholder="请输入className" :disabled="disabled"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="educate" v-bind="validateInfos.educate">
|
||||
<a-input v-model:value="formData.educate" placeholder="请输入educate" :disabled="disabled"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="entrydate" v-bind="validateInfos.entrydate">
|
||||
<a-input v-model:value="formData.entrydate" placeholder="请输入entrydate" :disabled="disabled"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="campus" v-bind="validateInfos.campus">
|
||||
<a-input v-model:value="formData.campus" placeholder="请输入campus" :disabled="disabled"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="state" v-bind="validateInfos.state">
|
||||
<a-input v-model:value="formData.state" placeholder="请输入state" :disabled="disabled"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="level" v-bind="validateInfos.level">
|
||||
<a-input v-model:value="formData.level" placeholder="请输入level" :disabled="disabled"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
<a-col :span="24">
|
||||
<a-form-item label="category" v-bind="validateInfos.category">
|
||||
<a-input v-model:value="formData.category" placeholder="请输入category" :disabled="disabled"></a-input>
|
||||
</a-form-item>
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, reactive, defineExpose, nextTick, defineProps, computed, onMounted } from 'vue';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { useMessage } from '/@/hooks/web/useMessage';
|
||||
import { getValueType } from '/@/utils';
|
||||
import { saveOrUpdate } from '../Cet4Major.api';
|
||||
import { Form } from 'ant-design-vue';
|
||||
|
||||
const props = defineProps({
|
||||
formDisabled: { type: Boolean, default: false },
|
||||
formData: { type: Object, default: ()=>{} },
|
||||
formBpm: { type: Boolean, default: true }
|
||||
});
|
||||
const formRef = ref();
|
||||
const useForm = Form.useForm;
|
||||
const emit = defineEmits(['register', 'ok']);
|
||||
const formData = reactive<Record<string, any>>({
|
||||
id: '',
|
||||
name: '',
|
||||
college: '',
|
||||
majorId: '',
|
||||
majorname: '',
|
||||
className: '',
|
||||
educate: '',
|
||||
entrydate: '',
|
||||
campus: '',
|
||||
state: '',
|
||||
level: '',
|
||||
category: '',
|
||||
});
|
||||
const { createMessage } = useMessage();
|
||||
const labelCol = ref<any>({ xs: { span: 24 }, sm: { span: 5 } });
|
||||
const wrapperCol = ref<any>({ xs: { span: 24 }, sm: { span: 16 } });
|
||||
const confirmLoading = ref<boolean>(false);
|
||||
//表单验证
|
||||
const validatorRules = {
|
||||
};
|
||||
const { resetFields, validate, validateInfos } = useForm(formData, validatorRules, { immediate: false });
|
||||
|
||||
// 表单禁用
|
||||
const disabled = computed(()=>{
|
||||
if(props.formBpm === true){
|
||||
if(props.formData.disabled === false){
|
||||
return false;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return props.formDisabled;
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
function add() {
|
||||
edit({});
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*/
|
||||
function edit(record) {
|
||||
nextTick(() => {
|
||||
resetFields();
|
||||
const tmpData = {};
|
||||
Object.keys(formData).forEach((key) => {
|
||||
if(record.hasOwnProperty(key)){
|
||||
tmpData[key] = record[key]
|
||||
}
|
||||
})
|
||||
//赋值
|
||||
Object.assign(formData, tmpData);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 提交数据
|
||||
*/
|
||||
async function submitForm() {
|
||||
// 触发表单验证
|
||||
await validate();
|
||||
confirmLoading.value = true;
|
||||
const isUpdate = ref<boolean>(false);
|
||||
//时间格式化
|
||||
let model = formData;
|
||||
if (model.id) {
|
||||
isUpdate.value = true;
|
||||
}
|
||||
//循环数据
|
||||
for (let data in model) {
|
||||
//如果该数据是数组并且是字符串类型
|
||||
if (model[data] instanceof Array) {
|
||||
let valueType = getValueType(formRef.value.getProps, data);
|
||||
//如果是字符串类型的需要变成以逗号分割的字符串
|
||||
if (valueType === 'string') {
|
||||
model[data] = model[data].join(',');
|
||||
}
|
||||
}
|
||||
}
|
||||
await saveOrUpdate(model, isUpdate.value)
|
||||
.then((res) => {
|
||||
if (res.success) {
|
||||
createMessage.success(res.message);
|
||||
emit('ok');
|
||||
} else {
|
||||
createMessage.warning(res.message);
|
||||
}
|
||||
})
|
||||
.finally(() => {
|
||||
confirmLoading.value = false;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
defineExpose({
|
||||
add,
|
||||
edit,
|
||||
submitForm,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.antd-modal-form {
|
||||
height: 500px !important;
|
||||
overflow-y: auto;
|
||||
padding: 14px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,75 @@
|
|||
<template>
|
||||
<a-modal :title="title" :width="width" :visible="visible" @ok="handleOk" :okButtonProps="{ class: { 'jee-hidden': disableSubmit } }" @cancel="handleCancel" cancelText="关闭">
|
||||
<Cet4MajorForm ref="registerForm" @ok="submitCallback" :formDisabled="disableSubmit" :formBpm="false"></Cet4MajorForm>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { ref, nextTick, defineExpose } from 'vue';
|
||||
import Cet4MajorForm from './Cet4MajorForm.vue'
|
||||
|
||||
const title = ref<string>('');
|
||||
const width = ref<number>(800);
|
||||
const visible = ref<boolean>(false);
|
||||
const disableSubmit = ref<boolean>(false);
|
||||
const registerForm = ref();
|
||||
const emit = defineEmits(['register', 'success']);
|
||||
|
||||
/**
|
||||
* 新增
|
||||
*/
|
||||
function add() {
|
||||
title.value = '新增';
|
||||
visible.value = true;
|
||||
nextTick(() => {
|
||||
registerForm.value.add();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
* @param record
|
||||
*/
|
||||
function edit(record) {
|
||||
title.value = disableSubmit.value ? '详情' : '编辑';
|
||||
visible.value = true;
|
||||
nextTick(() => {
|
||||
registerForm.value.edit(record);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 确定按钮点击事件
|
||||
*/
|
||||
function handleOk() {
|
||||
registerForm.value.submitForm();
|
||||
}
|
||||
|
||||
/**
|
||||
* form保存回调事件
|
||||
*/
|
||||
function submitCallback() {
|
||||
handleCancel();
|
||||
emit('success');
|
||||
}
|
||||
|
||||
/**
|
||||
* 取消按钮回调事件
|
||||
*/
|
||||
function handleCancel() {
|
||||
visible.value = false;
|
||||
}
|
||||
|
||||
defineExpose({
|
||||
add,
|
||||
edit,
|
||||
disableSubmit,
|
||||
});
|
||||
</script>
|
||||
|
||||
<style>
|
||||
/**隐藏样式-modal确定按钮 */
|
||||
.jee-hidden {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,233 @@
|
|||
<template>
|
||||
<div style="background: #ececec; padding-top: 0px; padding-left: 20px; padding-right: 20px; padding-bottom: 20px">
|
||||
<a-card title="英语四级数据导入" :bordered="false">
|
||||
<a-row :gutter="2">
|
||||
<a-col :xl="24" :style="{ marginBottom: '24px' }">
|
||||
<div class="clearfix">
|
||||
<span style="padding-top: 5px">考试批次:</span>
|
||||
<a-space direction="vertical" :size="12">
|
||||
<a-date-picker v-model:value="month" picker="month" />
|
||||
</a-space>
|
||||
<div class="clearfix">
|
||||
<!-- accept=".dbf" 属性限制文件类型 -->
|
||||
<a-upload
|
||||
:file-list="fileList"
|
||||
accept=".dbf"
|
||||
:max-count="1"
|
||||
:customRequest="handleUpload"
|
||||
:before-upload="beforeUpload"
|
||||
@remove="handleRemove"
|
||||
>
|
||||
<a-button type="primary">
|
||||
<upload-outlined />
|
||||
导入文件
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</div>
|
||||
<!--<div class="clearfix">
|
||||
<a-button preIcon="ant-design:export-outlined" @click="downloadTemplate"> 下载模板</a-button>
|
||||
</div>-->
|
||||
<div class="clearfix">
|
||||
<a-button type="primary" :disabled="!canUpload" :loading="uploading" @click="handleUpload">
|
||||
{{ uploading ? 'Uploading' : '确认上传文件' }}
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="10">
|
||||
<a-col :xl="24">
|
||||
<a-table :dataSource="dataSourceCet4" :columns="columns" :pagination="false" :loading="loading" bordered class="custom-table" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { downloadTemplateExcel } from './dataImportApi';
|
||||
import { conversionFileDownload } from '@/utils/download';
|
||||
const loading = ref(false);
|
||||
// 批次选择(月份选择器)
|
||||
const month = ref(null);
|
||||
const url = {
|
||||
downLoadTemplate: '/cetDataImport/downloadTemplate',
|
||||
importCet4Data: '/cetDataImport/dbfImport',
|
||||
loadImportData: '/cet_4/loadImportDataList',
|
||||
};
|
||||
// 文件上传部分
|
||||
const fileList: any = ref([]);
|
||||
const uploading = ref(false);
|
||||
|
||||
// 计算属性:控制上传按钮的可用性
|
||||
const canUpload = computed(() => fileList.value.length > 0 && month.value !== null);
|
||||
|
||||
// 移除文件
|
||||
const handleRemove = (file) => {
|
||||
const index = fileList.value.indexOf(file);
|
||||
const newFileList = fileList.value.slice();
|
||||
newFileList.splice(index, 1);
|
||||
fileList.value = newFileList;
|
||||
};
|
||||
|
||||
// 文件选择前的校验处理
|
||||
const beforeUpload = (file) => {
|
||||
console.log(file);
|
||||
fileList.value = [];
|
||||
fileList.value = [...fileList.value, file];
|
||||
let fileType = file.name.split('.').pop().toLowerCase();
|
||||
if (fileType !== 'dbf') {
|
||||
message.error('请上传.dbf文件');
|
||||
fileList.value = fileList.value.filter((item) => item.uid !== file.uid);
|
||||
}
|
||||
return false; // 阻止自动上传
|
||||
};
|
||||
// 处理上传逻辑
|
||||
const handleUpload = async () => {
|
||||
// 检查是否选择了文件
|
||||
if (!fileList.value || fileList.value.length === 0) {
|
||||
message.error('没有选择文件');
|
||||
return;
|
||||
}
|
||||
|
||||
const file = fileList.value[0];
|
||||
if (!file) {
|
||||
message.error('没有选择文件');
|
||||
return;
|
||||
}
|
||||
|
||||
// 读取文件为 Base64 编码
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = async () => {
|
||||
const base64File = reader.result as string;
|
||||
|
||||
// 构建请求体
|
||||
const payload = {
|
||||
fileName: file.name,
|
||||
fileContent: base64File,
|
||||
batch: '',
|
||||
level: 'cet4',
|
||||
};
|
||||
|
||||
// 处理 batch 参数
|
||||
let batch: any = month.value;
|
||||
if (batch) {
|
||||
batch = batch.format('YYYY-MM-DD');
|
||||
batch = setDayToFirst(batch); // 将日期的天改为当月第一天
|
||||
payload.batch = batch;
|
||||
}
|
||||
|
||||
try {
|
||||
uploading.value = true;
|
||||
|
||||
// 发送 POST 请求
|
||||
const response: any = await defHttp.post(
|
||||
{
|
||||
url: url.importCet4Data,
|
||||
data: payload,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
},
|
||||
{
|
||||
isTransformResponse: false,
|
||||
}
|
||||
);
|
||||
|
||||
// 清空文件列表和日期选择(根据需要)
|
||||
fileList.value = [];
|
||||
|
||||
// 处理响应
|
||||
if (response.success) {
|
||||
message.success('上传成功');
|
||||
} else {
|
||||
message.error(response.message || '上传失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('上传失败:', error);
|
||||
message.error('上传失败');
|
||||
} finally {
|
||||
uploading.value = false;
|
||||
}
|
||||
};
|
||||
reader.onerror = (error) => {
|
||||
console.error('文件读取错误:', error);
|
||||
message.error('文件读取失败');
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* 将 'yyyy-MM-dd' 格式的日期字符串的天部分设置为 '01'
|
||||
* @param {string} dateStr - 原始日期字符串,格式为 'yyyy-MM-dd'
|
||||
* @returns {string} 修改后的日期字符串,格式为 'yyyy-MM-01'
|
||||
*/
|
||||
const setDayToFirst = (dateStr) => {
|
||||
// 使用正则表达式验证日期格式
|
||||
const regex = /^(\d{4})-(\d{2})-(\d{2})$/;
|
||||
const match = dateStr.match(regex);
|
||||
|
||||
if (!match) {
|
||||
throw new Error("日期格式不正确,应为 'yyyy-MM-dd'");
|
||||
}
|
||||
|
||||
const year = match[1];
|
||||
const month = match[2];
|
||||
|
||||
// 构造新的日期字符串,天部分设置为 '01'
|
||||
return `${year}-${month}-01`;
|
||||
};
|
||||
|
||||
// 定义表格的数据源
|
||||
const dataSourceCet4 = ref([]);
|
||||
// 定义表格的列配置
|
||||
const columns = [
|
||||
{
|
||||
title: '考试批次',
|
||||
dataIndex: 'batch',
|
||||
key: 'batch',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '参加人数',
|
||||
dataIndex: 'attendNumber',
|
||||
key: 'attendNumber',
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
//处理表格数据源
|
||||
const fetchData = async () => {
|
||||
loading.value = true; // 开始加载
|
||||
try {
|
||||
const response = await defHttp.post({ url: url.loadImportData });
|
||||
console.log(response, 'response');
|
||||
dataSourceCet4.value = response.data; // 将数据绑定到表格
|
||||
} catch (error) {
|
||||
message.error('Failed to load data.');
|
||||
} finally {
|
||||
loading.value = false; // 加载结束
|
||||
}
|
||||
};
|
||||
|
||||
//const downloadTemplate = async () => {
|
||||
// downloadTemplateExcel()
|
||||
// .then((response: any) => {
|
||||
// console.log(response, '123');
|
||||
// conversionFileDownload(response);
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// console.error(error);
|
||||
// });
|
||||
//};
|
||||
|
||||
// 在组件挂载时调用 fetchData
|
||||
onMounted(fetchData);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.clearfix {
|
||||
display: flex;
|
||||
padding-left: 10px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,233 @@
|
|||
<template>
|
||||
<div style="background: #ececec; padding-top: 0px; padding-left: 20px; padding-right: 20px; padding-bottom: 20px">
|
||||
<a-card title="英语六级数据导入" :bordered="false">
|
||||
<a-row :gutter="2">
|
||||
<a-col :xl="24" :style="{ marginBottom: '24px' }">
|
||||
<div class="clearfix">
|
||||
<span style="padding-top: 5px">考试批次:</span>
|
||||
<a-space direction="vertical" :size="12">
|
||||
<a-date-picker v-model:value="month" picker="month" />
|
||||
</a-space>
|
||||
<div class="clearfix">
|
||||
<!-- accept=".dbf" 属性限制文件类型 -->
|
||||
<a-upload
|
||||
:file-list="fileList"
|
||||
accept=".dbf"
|
||||
:max-count="1"
|
||||
:customRequest="handleUpload"
|
||||
:before-upload="beforeUpload"
|
||||
@remove="handleRemove"
|
||||
>
|
||||
<a-button type="primary">
|
||||
<upload-outlined />
|
||||
导入文件
|
||||
</a-button>
|
||||
</a-upload>
|
||||
</div>
|
||||
<!--<div class="clearfix">
|
||||
<a-button preIcon="ant-design:export-outlined" @click="downloadTemplate"> 下载模板</a-button>
|
||||
</div>-->
|
||||
<div class="clearfix">
|
||||
<a-button type="primary" :disabled="!canUpload" :loading="uploading" @click="handleUpload">
|
||||
{{ uploading ? 'Uploading' : '确认上传文件' }}
|
||||
</a-button>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<a-row :gutter="10">
|
||||
<a-col :xl="24">
|
||||
<a-table :dataSource="dataSourceCet4" :columns="columns" :pagination="false" :loading="loading" bordered class="custom-table" />
|
||||
</a-col>
|
||||
</a-row>
|
||||
</a-card>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, computed, onMounted } from 'vue';
|
||||
import { message } from 'ant-design-vue';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import { downloadTemplateExcel } from './dataImportApi';
|
||||
import { conversionFileDownload } from '@/utils/download';
|
||||
const loading = ref(false);
|
||||
// 批次选择(月份选择器)
|
||||
const month = ref(null);
|
||||
const url = {
|
||||
downLoadTemplate: '/cetDataImport/downloadTemplate',
|
||||
importCet4Data: '/cetDataImport/dbfImport',
|
||||
loadImportData: '/cet_6/loadImportDataList',
|
||||
};
|
||||
// 文件上传部分
|
||||
const fileList: any = ref([]);
|
||||
const uploading = ref(false);
|
||||
|
||||
// 计算属性:控制上传按钮的可用性
|
||||
const canUpload = computed(() => fileList.value.length > 0 && month.value !== null);
|
||||
|
||||
// 移除文件
|
||||
const handleRemove = (file) => {
|
||||
const index = fileList.value.indexOf(file);
|
||||
const newFileList = fileList.value.slice();
|
||||
newFileList.splice(index, 1);
|
||||
fileList.value = newFileList;
|
||||
};
|
||||
|
||||
// 文件选择前的校验处理
|
||||
const beforeUpload = (file) => {
|
||||
console.log(file);
|
||||
fileList.value = [];
|
||||
fileList.value = [...fileList.value, file];
|
||||
let fileType = file.name.split('.').pop().toLowerCase();
|
||||
if (fileType !== 'dbf') {
|
||||
message.error('请上传.dbf文件');
|
||||
fileList.value = fileList.value.filter((item) => item.uid !== file.uid);
|
||||
}
|
||||
return false; // 阻止自动上传
|
||||
};
|
||||
// 处理上传逻辑
|
||||
const handleUpload = async () => {
|
||||
// 检查是否选择了文件
|
||||
if (!fileList.value || fileList.value.length === 0) {
|
||||
message.error('没有选择文件');
|
||||
return;
|
||||
}
|
||||
|
||||
const file = fileList.value[0];
|
||||
if (!file) {
|
||||
message.error('没有选择文件');
|
||||
return;
|
||||
}
|
||||
|
||||
// 读取文件为 Base64 编码
|
||||
const reader = new FileReader();
|
||||
reader.readAsDataURL(file);
|
||||
reader.onload = async () => {
|
||||
const base64File = reader.result as string;
|
||||
|
||||
// 构建请求体
|
||||
const payload = {
|
||||
fileName: file.name,
|
||||
fileContent: base64File,
|
||||
batch: '',
|
||||
level: 'cet6',
|
||||
};
|
||||
|
||||
// 处理 batch 参数
|
||||
let batch: any = month.value;
|
||||
if (batch) {
|
||||
batch = batch.format('YYYY-MM-DD');
|
||||
batch = setDayToFirst(batch); // 将日期的天改为当月第一天
|
||||
payload.batch = batch;
|
||||
}
|
||||
|
||||
try {
|
||||
uploading.value = true;
|
||||
|
||||
// 发送 POST 请求
|
||||
const response: any = await defHttp.post(
|
||||
{
|
||||
url: url.importCet4Data,
|
||||
data: payload,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
},
|
||||
{
|
||||
isTransformResponse: false,
|
||||
}
|
||||
);
|
||||
|
||||
// 清空文件列表和日期选择(根据需要)
|
||||
fileList.value = [];
|
||||
|
||||
// 处理响应
|
||||
if (response.success) {
|
||||
message.success('上传成功');
|
||||
} else {
|
||||
message.error(response.message || '上传失败');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('上传失败:', error);
|
||||
message.error('上传失败');
|
||||
} finally {
|
||||
uploading.value = false;
|
||||
}
|
||||
};
|
||||
reader.onerror = (error) => {
|
||||
console.error('文件读取错误:', error);
|
||||
message.error('文件读取失败');
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* 将 'yyyy-MM-dd' 格式的日期字符串的天部分设置为 '01'
|
||||
* @param {string} dateStr - 原始日期字符串,格式为 'yyyy-MM-dd'
|
||||
* @returns {string} 修改后的日期字符串,格式为 'yyyy-MM-01'
|
||||
*/
|
||||
const setDayToFirst = (dateStr) => {
|
||||
// 使用正则表达式验证日期格式
|
||||
const regex = /^(\d{4})-(\d{2})-(\d{2})$/;
|
||||
const match = dateStr.match(regex);
|
||||
|
||||
if (!match) {
|
||||
throw new Error("日期格式不正确,应为 'yyyy-MM-dd'");
|
||||
}
|
||||
|
||||
const year = match[1];
|
||||
const month = match[2];
|
||||
|
||||
// 构造新的日期字符串,天部分设置为 '01'
|
||||
return `${year}-${month}-01`;
|
||||
};
|
||||
|
||||
// 定义表格的数据源
|
||||
const dataSourceCet4 = ref([]);
|
||||
// 定义表格的列配置
|
||||
const columns = [
|
||||
{
|
||||
title: '考试批次',
|
||||
dataIndex: 'batch',
|
||||
key: 'batch',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '参加人数',
|
||||
dataIndex: 'attendNumber',
|
||||
key: 'attendNumber',
|
||||
align: 'center',
|
||||
},
|
||||
];
|
||||
//处理表格数据源
|
||||
const fetchData = async () => {
|
||||
loading.value = true; // 开始加载
|
||||
try {
|
||||
const response = await defHttp.post({ url: url.loadImportData });
|
||||
console.log(response, 'response');
|
||||
dataSourceCet4.value = response.data; // 将数据绑定到表格
|
||||
} catch (error) {
|
||||
message.error('Failed to load data.');
|
||||
} finally {
|
||||
loading.value = false; // 加载结束
|
||||
}
|
||||
};
|
||||
|
||||
//const downloadTemplate = async () => {
|
||||
// downloadTemplateExcel()
|
||||
// .then((response: any) => {
|
||||
// console.log(response, '123');
|
||||
// conversionFileDownload(response);
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// console.error(error);
|
||||
// });
|
||||
//};
|
||||
|
||||
// 在组件挂载时调用 fetchData
|
||||
onMounted(fetchData);
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.clearfix {
|
||||
display: flex;
|
||||
padding-left: 10px;
|
||||
}
|
||||
</style>
|
|
@ -0,0 +1,9 @@
|
|||
import { defHttp } from '/@/utils/http/axios';
|
||||
|
||||
export function downloadTemplateExcel() {
|
||||
return defHttp.request<Blob>({
|
||||
url: '/cetDataImport/downloadTemplate',
|
||||
method: 'post',
|
||||
responseType: 'blob',
|
||||
});
|
||||
}
|
|
@ -3,42 +3,43 @@
|
|||
<a-card title="四级总通过率查询" :loading="loading" :bordered="false">
|
||||
<template #extra>
|
||||
<a-cascader v-model:value="collegeMajor" :options="collegeMajorOptions" change-on-select />
|
||||
<a-select v-model:value="entrydate" style="margin-left: 10px;width: 100px"
|
||||
:options="entrydateOptions"></a-select>
|
||||
<a-button style="margin-left: 10px;" type="primary" @click="query">查询</a-button>
|
||||
<a-select v-model:value="entrydate" style="margin-left: 10px; width: 100px" :options="entrydateOptions" />
|
||||
<a-button style="margin-left: 10px" type="primary" @click="query">查询</a-button>
|
||||
<!-- <a-button @click=test()>test</a-button> -->
|
||||
</template>
|
||||
<a-row :gutter="24">
|
||||
<a-row :gutter="12">
|
||||
<a-col :xl="13">
|
||||
<div style="padding-left: 10px;min-height: 400px;">
|
||||
<div v-if="topCollege != null" style="margin-bottom: 5px;">
|
||||
<span style="font-size: 15px;">当前数据为 </span>
|
||||
<span style="color: red; font-size: 18px;">{{ topCollege }}</span>
|
||||
<span v-if="topMajor != null && topMajor != '' " style="color: red; font-size: 18px;"> / {{ topMajor }}</span>
|
||||
<span style="font-size: 15px;"> 的 </span>
|
||||
<span style="color: red; font-size: 20px;">{{ topEntrydate }}</span>
|
||||
<span style="font-size: 15px;"> 级数据</span>
|
||||
<div style="padding-left: 10px; min-height: 400px">
|
||||
<div v-if="topCollege != null" style="margin-bottom: 5px">
|
||||
<span style="font-size: 15px">当前数据为 </span>
|
||||
<span style="color: red; font-size: 18px">{{ topCollege }}</span>
|
||||
<span v-if="topMajor != null && topMajor != ''" style="color: red; font-size: 18px"> / {{ topMajor }}</span>
|
||||
<span style="font-size: 15px"> 的 </span>
|
||||
<span style="color: red; font-size: 20px">{{ topEntrydate }}</span>
|
||||
<span style="font-size: 15px"> 级数据</span>
|
||||
</div>
|
||||
<a-table :dataSource="dataSourceCet4" :columns="columns" :pagination='false' bordered>
|
||||
<template v-slot:passRateSlot>
|
||||
<a-table :dataSource="dataSourceCet4" :columns="columns" :pagination="false" bordered>
|
||||
<template #passRateSlot>
|
||||
累计总通过率
|
||||
<a-tooltip :title="'累计通过人数 / ' + this.totalName + '总人数'" placement="top">
|
||||
<a-tooltip :title="'累计通过人数 / ' + totalName + '总人数'" placement="top">
|
||||
<a-icon type="question-circle" />
|
||||
</a-tooltip>
|
||||
</template>
|
||||
</a-table>
|
||||
<div style="display: flex; justify-content: space-between; font-size: 15px; margin-top: 10px;"
|
||||
v-if="total && total > 0">
|
||||
<span>{{ this.totalName }}总人数:{{ total }}</span>
|
||||
<div style="display: flex; justify-content: space-between; font-size: 15px; margin-top: 10px" v-if="total && total > 0">
|
||||
<span>{{ totalName }}总人数:{{ total }}</span>
|
||||
<span>累计通过人数: {{ passNumberBottom }}</span>
|
||||
<span>累计总通过率: {{ passRateBottom }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</a-col>
|
||||
<a-col :xl="11">
|
||||
<div style="width: 100%;height: 500px;padding: 10px;" class="piechart" id="piechart">
|
||||
|
||||
</div>
|
||||
<a-card style="margin-top: 33px; margin-bottom: 12px">
|
||||
<div style="width: 100%; height: 215px" class="piechart" id="piechart"> </div>
|
||||
</a-card>
|
||||
<a-card>
|
||||
<div style="width: 100%; height: 180px" id="map2"> </div>
|
||||
</a-card>
|
||||
</a-col>
|
||||
</a-row>
|
||||
<!-- <div style="height: 300px;">
|
||||
|
@ -49,306 +50,361 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import * as echarts from 'echarts';
|
||||
import { defHttp } from '/@/utils/http/axios';
|
||||
import * as echarts from 'echarts';
|
||||
|
||||
export default {
|
||||
name: "Analysis",
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
dataSourceCet4: [],
|
||||
columns: [
|
||||
{
|
||||
title: '学年',
|
||||
dataIndex: 'grade',
|
||||
key: 'grade',
|
||||
align: 'center',
|
||||
customCell: (_, index) => ({
|
||||
rowSpan: index % 2 === 0 ? 2 : 0,//每两行合并一次grade列的单元格,rowSpan为跨度
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: '考试批次',
|
||||
dataIndex: 'batch',
|
||||
key: 'batch',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '参加人数',
|
||||
dataIndex: 'attendNumber',
|
||||
key: 'attendNumber',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '通过人数',
|
||||
dataIndex: 'passNumber',
|
||||
key: 'passNumber',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '本批次通过率',
|
||||
dataIndex: 'batchpassrate',
|
||||
key: 'batchpassrate',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
slots: { title: 'passRateSlot' },
|
||||
dataIndex: 'gradepassrate',
|
||||
key: 'gradepassrate',
|
||||
align: 'center',
|
||||
customCell: (_, index) => ({
|
||||
rowSpan: index % 2 === 0 ? 2 : 0,
|
||||
}),
|
||||
}
|
||||
],
|
||||
Url: {
|
||||
getEntrydate: '/cet/getEntrydate',
|
||||
getCollege: '/cet/getCollege',
|
||||
getData: '/cet/getData',
|
||||
getCollegeMajor: '/cet/getCollegeMajor'
|
||||
},
|
||||
total: 0,
|
||||
totalName: '',
|
||||
passNumberBottom: 0,
|
||||
passRateBottom: 0,
|
||||
passRatePie: [],
|
||||
collegeOptions: [],
|
||||
collegeMajorOptions: [],
|
||||
entrydateOptions: [],
|
||||
college: null,
|
||||
entrydate: 2017,//年级选择器
|
||||
//设置默认值为全校
|
||||
collegeMajor: ['全校'],//学院专业选择器
|
||||
topCollege: null,//顶部选择器
|
||||
topMajor: null,//顶部选择器
|
||||
topEntrydate: null,//顶部选择器
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
// 获取年级和学院数据
|
||||
async getEntrydateAndCollegeData() {
|
||||
const getEntrydate = await defHttp.get({ url: this.Url.getEntrydate });
|
||||
const getCollege = await defHttp.get({ url: this.Url.getCollege });
|
||||
this.collegeOptions = getCollege.colleges;
|
||||
// 手动添加一个全校字段
|
||||
this.collegeOptions.unshift({ value: '全校', label: '全校' });
|
||||
this.college = this.collegeOptions[0].value;
|
||||
this.entrydateOptions = getEntrydate.entrydates;
|
||||
// this.entrydate = this.entrydateOptions[0].value;
|
||||
},
|
||||
//获取学院专业级联数据
|
||||
async getCollegeMajorData() {
|
||||
const res = await defHttp.get({ url: this.Url.getCollegeMajor });
|
||||
//通过map方法将数据转换为级联选择器需要的数据格式
|
||||
this.collegeMajorOptions = res.collegeMajor.map(item => {
|
||||
return {
|
||||
value: item.college,
|
||||
label: item.college,
|
||||
children: item.major.map(major => {
|
||||
return {
|
||||
value: major,
|
||||
label: major
|
||||
}
|
||||
})
|
||||
}
|
||||
});
|
||||
//手动添加一个专升本字段
|
||||
this.collegeMajorOptions.unshift({ value: '专升本', label: '专升本' });
|
||||
// 手动添加一个全校字段
|
||||
this.collegeMajorOptions.unshift({ value: '全校', label: '全校' });
|
||||
// this.collegeMajor = ['全校'];
|
||||
console.log(this.collegeMajorOptions);
|
||||
},
|
||||
|
||||
// 查询数据
|
||||
async query() {
|
||||
try {
|
||||
//如果this.collegeMajor[1]不存在则设为null
|
||||
let major = this.collegeMajor.length > 1 ? this.collegeMajor[1] : "";
|
||||
this.topCollege = this.collegeMajor[0];
|
||||
this.topMajor = major;
|
||||
this.topEntrydate = this.entrydate;
|
||||
if (this.college)
|
||||
this.loading = true;
|
||||
let params = {
|
||||
college: this.collegeMajor[0],
|
||||
major: major,
|
||||
entrydate: this.entrydate
|
||||
}
|
||||
console.log("params", params);
|
||||
const result = await defHttp.get({ url: this.Url.getData, params });
|
||||
let tableData = [];
|
||||
let piedata = [];
|
||||
let passrate = 0;
|
||||
let index = 0;
|
||||
const passRate = {}
|
||||
if(result.cet4["大一学年"] != undefined) {
|
||||
passRate["大一学年"] = result.cet4["大一学年"];
|
||||
}
|
||||
if(result.cet4["大二学年"] != undefined) {
|
||||
passRate["大二学年"] = result.cet4["大二学年"];
|
||||
}
|
||||
if(result.cet4["大三学年"] != undefined) {
|
||||
passRate["大三学年"] = result.cet4["大三学年"];
|
||||
}
|
||||
if(result.cet4["大四学年"] != undefined) {
|
||||
passRate["大四学年"] = result.cet4["大四学年"];
|
||||
}
|
||||
result.cet4 = passRate;
|
||||
for (let grade in result.cet4) {
|
||||
result.cet4[grade].forEach(item => {
|
||||
if (index % 2 == 0) {
|
||||
piedata.push({ value: parseFloat(item.gradepassrate - passrate).toFixed(3), name: grade + "时通过" });
|
||||
passrate = parseFloat(item.gradepassrate).toFixed(3);
|
||||
}
|
||||
index++
|
||||
tableData.push({
|
||||
grade: grade,
|
||||
attendNumber: item.attendNumber,
|
||||
batch: item.batch,
|
||||
gradepassrate: (item.gradepassrate * 100).toFixed(1) + '%',
|
||||
passNumber: item.passNumber,
|
||||
batchpassrate: (item.batchpassrate * 100).toFixed(1) + '%'
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
console.log("tableData", tableData);
|
||||
this.dataSourceCet4 = tableData;//表格数据
|
||||
this.total = result.total;//总人数
|
||||
this.totalName = result.totalName;//总人数名称
|
||||
this.passNumberBottom = result.passNumber;//通过人数
|
||||
this.passRateBottom = (result.passRate * 100).toFixed(1) + '%';//通过率
|
||||
//内置饼图
|
||||
this.passRatePie = []//清空数据
|
||||
this.passRatePie.push({ value: result.passRate, name: '已通过' });
|
||||
this.passRatePie.push({ value: 1 - result.passRate, name: '未通过' })
|
||||
piedata.push({ value: (1 - passrate).toFixed(3), name: '未通过' });//外置饼图
|
||||
setTimeout(() => {
|
||||
this.drawPieChart(piedata);
|
||||
}, 100);
|
||||
// this.drawPieChart();
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
test() {
|
||||
defHttp.get({ url: "/cet/getTest" });
|
||||
},
|
||||
|
||||
drawPieChart(piedata) {
|
||||
console.log(this.passRatePie)
|
||||
console.log("piedata", piedata)
|
||||
let myChart = echarts.init(document.getElementById('piechart'));
|
||||
let option = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
confine: false,
|
||||
//字体大小
|
||||
itemStyle: {
|
||||
fontSize: 100
|
||||
}
|
||||
},
|
||||
|
||||
title: {
|
||||
text: '四级通过率分析',
|
||||
left: 'left',
|
||||
top: '0%',
|
||||
textStyle: {
|
||||
fontSize: 20
|
||||
}
|
||||
},
|
||||
legend: {
|
||||
top: '5%',
|
||||
left: 'center'
|
||||
},
|
||||
color: ['#b3cde0', '#6497b1', '#005b96', '#03396c', '#e5e5e5'],
|
||||
|
||||
series: [
|
||||
//内圈饼图
|
||||
// {
|
||||
// name: '四级通过率',
|
||||
// type: 'pie',
|
||||
// radius: ['0', '30%'],
|
||||
// avoidLabelOverlap: false,
|
||||
// itemStyle: {
|
||||
// borderRadius: 3,
|
||||
// borderColor: '#fff',
|
||||
// borderWidth: 2,
|
||||
// },
|
||||
// label: {
|
||||
// position: 'inner',
|
||||
// fontSize: 14
|
||||
// },
|
||||
// emphasis: {
|
||||
// label: {
|
||||
// show: true,
|
||||
// fontSize: 20,
|
||||
// fontWeight: 'bold'
|
||||
// }
|
||||
// },
|
||||
// data: this.passRatePie
|
||||
// },
|
||||
//外圈饼图
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
dataSourceCet4: [],
|
||||
columns: [
|
||||
{
|
||||
name: '四级通过率',
|
||||
type: 'pie',
|
||||
radius: ['35%', '60%'],
|
||||
itemStyle: {
|
||||
borderRadius: 10,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2,
|
||||
title: '学年',
|
||||
dataIndex: 'grade',
|
||||
key: 'grade',
|
||||
align: 'center',
|
||||
customCell: (_, index) => ({
|
||||
rowSpan: index % 2 === 0 ? 2 : 0, //每两行合并一次grade列的单元格,rowSpan为跨度
|
||||
}),
|
||||
},
|
||||
{
|
||||
title: '考试批次',
|
||||
dataIndex: 'batch',
|
||||
key: 'batch',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '参加人数',
|
||||
dataIndex: 'attendNumber',
|
||||
key: 'attendNumber',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '通过人数',
|
||||
dataIndex: 'passNumber',
|
||||
key: 'passNumber',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
title: '本批次通过率',
|
||||
dataIndex: 'batchpassrate',
|
||||
key: 'batchpassrate',
|
||||
align: 'center',
|
||||
},
|
||||
{
|
||||
slots: { title: 'passRateSlot' },
|
||||
dataIndex: 'gradepassrate',
|
||||
key: 'gradepassrate',
|
||||
align: 'center',
|
||||
customCell: (_, index) => ({
|
||||
rowSpan: index % 2 === 0 ? 2 : 0,
|
||||
}),
|
||||
},
|
||||
],
|
||||
Url: {
|
||||
getEntrydate: '/cet/getEntrydate',
|
||||
getCollege: '/cet/getCollege',
|
||||
getData: '/cet/getData',
|
||||
getCollegeMajor: '/cet/getCollegeMajor',
|
||||
},
|
||||
total: 0,
|
||||
totalName: '',
|
||||
passNumberBottom: 0,
|
||||
passRateBottom: 0,
|
||||
passRatePie: [],
|
||||
lineXData: [],
|
||||
lineYData: [],
|
||||
collegeOptions: [],
|
||||
collegeMajorOptions: [],
|
||||
entrydateOptions: [],
|
||||
college: null,
|
||||
entrydate: 2017, //年级选择器
|
||||
//设置默认值为全校
|
||||
collegeMajor: ['全校'], //学院专业选择器
|
||||
topCollege: null, //顶部选择器
|
||||
topMajor: null, //顶部选择器
|
||||
topEntrydate: null, //顶部选择器
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.getEntrydateAndCollegeData();
|
||||
this.getCollegeMajorData();
|
||||
this.query();
|
||||
//this.map2Chart();
|
||||
},
|
||||
methods: {
|
||||
// 获取年级和学院数据
|
||||
async getEntrydateAndCollegeData() {
|
||||
const getEntrydate = await defHttp.get({ url: this.Url.getEntrydate });
|
||||
const getCollege = await defHttp.get({ url: this.Url.getCollege });
|
||||
this.collegeOptions = getCollege.colleges;
|
||||
// 手动添加一个全校字段
|
||||
this.collegeOptions.unshift({ value: '全校', label: '全校' });
|
||||
this.college = this.collegeOptions[0].value;
|
||||
this.entrydateOptions = getEntrydate.entrydates;
|
||||
// this.entrydate = this.entrydateOptions[0].value;
|
||||
},
|
||||
//获取学院专业级联数据
|
||||
async getCollegeMajorData() {
|
||||
const res = await defHttp.get({ url: this.Url.getCollegeMajor });
|
||||
//通过map方法将数据转换为级联选择器需要的数据格式
|
||||
this.collegeMajorOptions = res.collegeMajor.map((item) => {
|
||||
return {
|
||||
value: item.college,
|
||||
label: item.college,
|
||||
children: item.major.map((major) => {
|
||||
return {
|
||||
value: major,
|
||||
label: major,
|
||||
};
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
//手动添加一个专升本字段
|
||||
this.collegeMajorOptions.unshift({ value: '专升本', label: '专升本' });
|
||||
// 手动添加一个全校(不含艺体美外语)字段
|
||||
this.collegeMajorOptions.unshift({ value: '全校(不含艺体美外语)', label: '全校(不含艺体美外语)' });
|
||||
// 手动添加一个全校字段
|
||||
this.collegeMajorOptions.unshift({ value: '全校', label: '全校' });
|
||||
|
||||
// this.collegeMajor = ['全校'];
|
||||
console.log(this.collegeMajorOptions);
|
||||
},
|
||||
|
||||
// 查询数据
|
||||
async query() {
|
||||
try {
|
||||
//如果this.collegeMajor[1]不存在则设为null
|
||||
let major = this.collegeMajor.length > 1 ? this.collegeMajor[1] : '';
|
||||
this.topCollege = this.collegeMajor[0];
|
||||
this.topMajor = major;
|
||||
this.topEntrydate = this.entrydate;
|
||||
if (this.college) this.loading = true;
|
||||
let params = {
|
||||
college: this.collegeMajor[0],
|
||||
major: major,
|
||||
entrydate: this.entrydate,
|
||||
};
|
||||
console.log('params', params);
|
||||
const result = await defHttp.get({ url: this.Url.getData, params });
|
||||
let tableData = [];
|
||||
let piedata = [];
|
||||
let passrate = 0;
|
||||
let index = 0;
|
||||
const passRate = {};
|
||||
if (result.cet4['大一学年'] != undefined) {
|
||||
passRate['大一学年'] = result.cet4['大一学年'];
|
||||
}
|
||||
if (result.cet4['大二学年'] != undefined) {
|
||||
passRate['大二学年'] = result.cet4['大二学年'];
|
||||
}
|
||||
if (result.cet4['大三学年'] != undefined) {
|
||||
passRate['大三学年'] = result.cet4['大三学年'];
|
||||
}
|
||||
if (result.cet4['大四学年'] != undefined) {
|
||||
passRate['大四学年'] = result.cet4['大四学年'];
|
||||
}
|
||||
result.cet4 = passRate;
|
||||
this.lineXData = [];
|
||||
this.lineYData = [];
|
||||
for (let grade in result.cet4) {
|
||||
result.cet4[grade].forEach((item) => {
|
||||
this.lineXData.push(item.batch);
|
||||
this.lineYData.push((item.batchpassrate * 100).toFixed(1));
|
||||
if (index % 2 == 0) {
|
||||
piedata.push({ value: parseFloat(item.gradepassrate - passrate).toFixed(3), name: grade + '时通过' });
|
||||
passrate = parseFloat(item.gradepassrate).toFixed(3);
|
||||
}
|
||||
index++;
|
||||
tableData.push({
|
||||
grade: grade,
|
||||
attendNumber: item.attendNumber,
|
||||
batch: item.batch,
|
||||
gradepassrate: (item.gradepassrate * 100).toFixed(1) + '%',
|
||||
passNumber: item.passNumber,
|
||||
batchpassrate: (item.batchpassrate * 100).toFixed(1) + '%',
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
console.log('tableData', tableData);
|
||||
this.dataSourceCet4 = tableData; //表格数据
|
||||
this.total = result.total; //总人数
|
||||
this.totalName = result.totalName; //总人数名称
|
||||
this.passNumberBottom = result.passNumber; //通过人数
|
||||
this.passRateBottom = (result.passRate * 100).toFixed(1) + '%'; //通过率
|
||||
//内置饼图
|
||||
this.passRatePie = []; //清空数据
|
||||
this.passRatePie.push({ value: result.passRate, name: '已通过' });
|
||||
this.passRatePie.push({ value: 1 - result.passRate, name: '未通过' });
|
||||
piedata.push({ value: (1 - passrate).toFixed(3), name: '未通过' }); //外置饼图
|
||||
setTimeout(() => {
|
||||
this.drawPieChart(piedata);
|
||||
this.map2Chart();
|
||||
}, 100);
|
||||
// this.drawPieChart();
|
||||
} finally {
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
test() {
|
||||
defHttp.get({ url: '/cet/getTest' });
|
||||
},
|
||||
map2Chart() {
|
||||
var myChart = echarts.init(document.getElementById('map2'));
|
||||
var option = {
|
||||
title: {
|
||||
text: '各批次通过率分析',
|
||||
left: 'left',
|
||||
top: '0%',
|
||||
textStyle: {
|
||||
fontSize: 16,
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: 14,
|
||||
overflow: 'truncate'
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
},
|
||||
emphasis: {
|
||||
formatter: function (params) {
|
||||
return (
|
||||
params[0].name +
|
||||
'<br/>' +
|
||||
'<table>' +
|
||||
'<tr><td>' +
|
||||
params[0].marker +
|
||||
'</td><td style="font-weight: bold;">' +
|
||||
' ' +
|
||||
params[0].value +
|
||||
'%' +
|
||||
'</td></tr>' +
|
||||
'<tr>' +
|
||||
'</table>'
|
||||
);
|
||||
},
|
||||
},
|
||||
grid: {
|
||||
top: '50px',
|
||||
left: '50px',
|
||||
right: '50px',
|
||||
bottom: '30px',
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
data: this.lineXData,
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: this.lineYData,
|
||||
type: 'line',
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)'
|
||||
normal: {
|
||||
label: {
|
||||
show: true, //开启显示
|
||||
position: 'top', //在上方显示
|
||||
textStyle: {
|
||||
//数值样式
|
||||
color: 'black',
|
||||
fontSize: 12,
|
||||
},
|
||||
formatter: '{c}%',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
option && myChart.setOption(option);
|
||||
},
|
||||
drawPieChart(piedata) {
|
||||
console.log(this.passRatePie);
|
||||
console.log('piedata', piedata);
|
||||
let myChart = echarts.init(document.getElementById('piechart'));
|
||||
let option = {
|
||||
tooltip: {
|
||||
trigger: 'item',
|
||||
confine: false,
|
||||
avoidLabelOverlap: true,
|
||||
//字体大小
|
||||
itemStyle: {
|
||||
fontSize: 100,
|
||||
},
|
||||
},
|
||||
|
||||
title: {
|
||||
text: '四级通过率分析',
|
||||
left: 'left',
|
||||
top: '0%',
|
||||
textStyle: {
|
||||
fontSize: 16,
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
top: 'center',
|
||||
right: '0%',
|
||||
orient: 'vertical',
|
||||
},
|
||||
color: ['#b3cde0', '#6497b1', '#005b96', '#03396c', '#e5e5e5'],
|
||||
|
||||
series: [
|
||||
//外圈饼图
|
||||
{
|
||||
name: '四级通过率',
|
||||
type: 'pie',
|
||||
center: ['30%', '50%'],
|
||||
radius: ['35%', '70%'],
|
||||
itemStyle: {
|
||||
borderRadius: 10,
|
||||
borderColor: '#fff',
|
||||
borderWidth: 2,
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: 15,
|
||||
fontWeight: 'bold'
|
||||
}
|
||||
fontSize: 14,
|
||||
overflow: 'truncate',
|
||||
minMargin: -1,
|
||||
},
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: 'rgba(0, 0, 0, 0.5)',
|
||||
},
|
||||
label: {
|
||||
show: true,
|
||||
fontSize: 15,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
},
|
||||
data: piedata,
|
||||
},
|
||||
data: piedata
|
||||
}
|
||||
]
|
||||
};
|
||||
],
|
||||
};
|
||||
|
||||
|
||||
|
||||
myChart.setOption(option);
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getEntrydateAndCollegeData();
|
||||
this.getCollegeMajorData();
|
||||
this.query();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
myChart.setOption(option);
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.container {
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.09);
|
||||
}
|
||||
.container {
|
||||
display: flex;
|
||||
background-color: #fff;
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.09);
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 34px;
|
||||
color: rgb(8, 8, 8);
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
.title {
|
||||
font-size: 34px;
|
||||
color: rgb(8, 8, 8);
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
|
Loading…
Reference in New Issue