Compare commits

..

No commits in common. "62b2f6ab3d9c4aebe23abc28028796a4e1fce8cb" and "16670433d091f0f83d2dee8cdf462c3d83983ef4" have entirely different histories.

19 changed files with 3233 additions and 4858 deletions

View File

@ -1,70 +0,0 @@
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

View File

@ -6,420 +6,217 @@
<a-cascader v-model:value="collegeMajor" :options="collegeMajorOptions" change-on-select />
<a-button style="margin-left: 10px" type="primary" @click="query">查询</a-button>
</template>
<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>
<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>
</div>
<div id="map1" style="width: 100%; height: 500px"></div>
</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-col>
</a-row>
</div>
</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 {
data() {
return {
Url: {
getBatch: '/cet/getBatch',
getCollege: '/cet/getCollege',
getRate: '/cet/getRateByAllBatch',
getCollegeMajor: '/cet/getCollegeMajor',
getRateByMajor: '/cet/getgetRateByMajor',
getRateByMajorAndLastestBatch: '/cet/getRateByMajorAndLastestBatch',
getRateByEntryDate: '/cet/getRateByEntryDate',
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: ' / ',
},
loading: false,
participate_Piechartloading: false,
pass_Piechartloading: false,
collegeOptions: [],
collegeMajorOptions: [],
batchOptions: [],
levelOptions: [
{ value: 'cet4', label: '英语四级' },
{ value: 'cet6', label: '英语六级' },
xAxis: {
type: 'category',
data: xData,
axisLabel: {
interval: 0, //x
rotate: -10, //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;">' +
'&nbsp;&nbsp;&nbsp;&nbsp;' +
params[0].value +
'%' +
'</td></tr>' +
'<tr>' +
'</table>'
);
},
},
yAxis: {
type: 'value',
name: '通过率',
axisLabel: {
formatter: '{value} %',
},
},
series: [
{
data: yData,
type: 'line',
itemStyle: {
normal: {
label: {
show: true, //
position: 'top', //
textStyle: {
//
color: 'black',
fontSize: 12,
},
formatter: '{c}%',
},
},
},
},
],
level: null,
college: null,
batch: null,
collegeMajor: null,
topCollege: null, //
topMajor: null, //
};
// 使
myChart.setOption(option);
},
mounted() {
this.getCollegeMajorData();
this.getBatch();
this.query();
//
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();
},
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: ' / ',
},
xAxis: {
type: 'category',
data: xData,
axisLabel: {
interval: 1, //x
rotate: -10, //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;">' +
'&nbsp;&nbsp;&nbsp;&nbsp;' +
params[0].value +
'%' +
'</td></tr>' +
'<tr>' +
'</table>'
);
},
},
yAxis: {
type: 'value',
name: '通过率',
axisLabel: {
formatter: '{value} %',
},
},
series: [
{
data: yData,
type: 'line',
itemStyle: {
normal: {
label: {
show: true, //
position: 'top', //
textStyle: {
//
color: 'black',
fontSize: 12,
},
formatter: '{c}%',
},
},
},
},
],
//
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,
};
}),
};
// 使
myChart.setOption(option);
},
});
this.collegeMajor = ['东语学院', '日语'];
},
//
async query() {
let data = null;
console.log(this.collegeMajor, 'collegeMajor');
try {
//--
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 = {
//this.collegeMajornull
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',
};
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;
data = await defHttp.get({ url: this.Url.getRate, params });
} finally {
this.loading = false;
this.$nextTick(() => {
var myChart = echarts.init(document.getElementById('participate_Piechart'));
myChart.setOption(option);
this.dataChart(data);
});
},
//--/
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.collegeMajornull
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;
}
.tip {
margin-bottom: 10px;
background-color: #d0e5fe;
opacity: 0.9;
}
.title {
font-size: 20px;
color: rgb(8, 8, 8);
font-weight: bold;
}
</style>

View File

@ -1,448 +1,244 @@
<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 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>
<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>
<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>
<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>
</div>
<div id="map1" style="width: 100%; height: 600px;"></div>
</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-col>
</a-row>
</div>
</a-card>
</div>
</template>
<script>
//import { pagination } from 'mock/_util';
import { defHttp } from '/@/utils/http/axios';
import * as echarts from 'echarts';
import { result } from 'lodash-es';
import { defHttp } from '/@/utils/http/axios';
import * as echarts from 'echarts';
export default {
data() {
return {
dataSourceCet4: [],
columns: [
{
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',
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: " / ",
},
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, //
};
},
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));
}
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'
},
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;">' +
'&nbsp;&nbsp;&nbsp;&nbsp;' +
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}%',
formatter: function (params) {
return params[0].name + '<br/>' +
'<table>' +
'<tr><td>' + params[0].marker + '</td><td style="font-weight: bold;">' + '&nbsp;&nbsp;&nbsp;&nbsp;' + 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: [
{
data: yData,
type: 'bar',
itemStyle: {
normal: {
label: {
show: true, //
position: 'top', //
textStyle: { //
color: 'black',
fontSize: 12
},
},
},
},
],
};
// 使
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();
},
//
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.batchnull
if (!this.batch) {
this.batch = '2017-12-01';
formatter: '{c}%',
}
}
}
}
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();
});
]
};
// 使
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 });
//--
async draPieChart_Participate() {
//console.log(this.passRatePie);
//console.log('piedata', piedata);
let queryParams = {
// 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.batchnull
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 = {
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,
});
}
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,
// animationnfalse,
tooltip: {
show: false,
},
data: chartsData,
},
],
animationDurationUpate: 500,
};
this.participate_Piechartloading = false;
this.tableloading = false;
resultData = await defHttp.get({ url: this.Url.getRate, params });
this.sumRate = resultData.sumRate;
console.log("result", resultData)
} finally {
this.loading = false;
this.$nextTick(() => {
var myChart = echarts.init(document.getElementById('participate_Piechart'));
myChart.setOption(option);
});
},
},
};
this.dataChart(resultData.data);
})
}
}
},
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;
}
.tip {
margin-bottom: 10px;
background-color: #d0e5fe;
opacity: 0.9;
}
.title {
font-size: 20px;
color: rgb(8, 8, 8);
font-weight: bold;
}
</style>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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,36 +47,37 @@ export const formSchema: FormSchema[] = [
},
{
label: '考场人数',
field: 'personNumber',
component: 'Input',
field: 'personNumber',
component: 'Input',
},
{
label: '排序号',
field: 'sortNumber',
component: 'InputNumber',
show: false,
},
// TODO 主键隐藏字段目前写死为ID
{
label: '',
field: 'id',
component: 'Input',
show: false,
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;
}

View File

@ -1,203 +1,206 @@
<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" @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 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>
</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: [],
},
actionColumn: {
width: 120,
fixed: 'right',
},
beforeFetch: (params) => {
return Object.assign(params, queryParam);
},
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: [
],
},
exportConfig: {
name: 'cet_location',
url: getExportUrl,
params: queryParam,
actionColumn: {
width: 120,
fixed: 'right'
},
importConfig: {
url: getImportUrl,
success: handleSuccess,
beforeFetch: (params) => {
return Object.assign(params, queryParam);
},
},
exportConfig: {
name: "cet_location",
url: getExportUrl,
params: queryParam,
},
importConfig: {
url: getImportUrl,
success: handleSuccess
},
})
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext
//
const superQueryConfig = reactive(superQuerySchema);
/**
* 高级查询事件
*/
function handleSuperQuery(params) {
Object.keys(params).map((k) => {
queryParam[k] = params[k];
});
const [registerTable, { reload }, { rowSelection, selectedRowKeys }] = tableContext;
//
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.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();
}
/**
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 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>

View File

@ -1,70 +1,70 @@
<template>
<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 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>
</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';
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 },
});
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}
});
const formDisabled = computed(() => {
if (props.formData.disabled === false) {
return false;
const formDisabled = computed(()=>{
if(props.formData.disabled === false){
return false;
}
return true;
});
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,
}
}
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>

View File

@ -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="code">
<a-input-number :controls="false" v-model:value="search.code" placeholder="请输入学生学号" />
<a-form-item label="学号" name="id">
<a-input-number :controls="false" v-model:value="search.id" 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]?.code }}</span>
<span>学生学号{{ tableData[tableData.length - 1]?.id }}</span>
</a-col>
<a-col :span="6">
<span>所在学院{{ tableData[tableData.length - 1]?.college }}</span>
@ -46,12 +46,12 @@
import type { Rule } from 'ant-design-vue/es/form';
interface FormState {
name: string;
code: string;
id: string;
}
const search: UnwrapRef<FormState> = reactive({
name: '',
code: '',
id: '',
});
const isShow = ref(false);
const loading = ref(false);
@ -90,7 +90,7 @@
]);
const rules: Record<string, Rule[]> = {
name: [{ required: true, message: '请输入学生姓名', trigger: 'change' }],
code: [{ required: true, message: '请输入学生学号', trigger: 'change' }],
id: [{ required: true, message: '请输入学生学号', trigger: 'change' }],
};
const url = ref({
getData: '/cet_4/getDataByStudent',
@ -116,7 +116,7 @@
};
const handleClear = () => {
search.name = '';
search.code = '';
search.id = '';
isShow.value = false;
tableData.value = [];
};

View File

@ -1,72 +0,0 @@
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 });
}

View File

@ -1,103 +0,0 @@
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' },
};

View File

@ -1,248 +0,0 @@
<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>

View File

@ -1,193 +0,0 @@
<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>

View File

@ -1,75 +0,0 @@
<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>

View File

@ -1,233 +0,0 @@
<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>

View File

@ -1,233 +0,0 @@
<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>

View File

@ -1,9 +0,0 @@
import { defHttp } from '/@/utils/http/axios';
export function downloadTemplateExcel() {
return defHttp.request<Blob>({
url: '/cetDataImport/downloadTemplate',
method: 'post',
responseType: 'blob',
});
}

View File

@ -3,43 +3,42 @@
<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-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-select>
<a-button style="margin-left: 10px;" type="primary" @click="query">查询</a-button>
<!-- <a-button @click=test()>test</a-button> -->
</template>
<a-row :gutter="12">
<a-row :gutter="24">
<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 #passRateSlot>
<a-table :dataSource="dataSourceCet4" :columns="columns" :pagination='false' bordered>
<template v-slot:passRateSlot>
累计总通过率
<a-tooltip :title="'累计通过人数 / ' + totalName + '总人数'" placement="top">
<a-tooltip :title="'累计通过人数 / ' + this.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>{{ totalName }}总人数{{ total }}</span>
<div style="display: flex; justify-content: space-between; font-size: 15px; margin-top: 10px;"
v-if="total && total > 0">
<span>{{ this.totalName }}总人数{{ total }}</span>
<span>累计通过人数: {{ passNumberBottom }}</span>
<span>累计总通过率: {{ passRateBottom }}</span>
</div>
</div>
</a-col>
<a-col :xl="11">
<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>
<div style="width: 100%;height: 500px;padding: 10px;" class="piechart" id="piechart">
</div>
</a-col>
</a-row>
<!-- <div style="height: 300px;">
@ -50,361 +49,306 @@
</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 {
data() {
return {
loading: false,
dataSourceCet4: [],
columns: [
{
title: '学年',
dataIndex: 'grade',
key: 'grade',
align: 'center',
customCell: (_, index) => ({
rowSpan: index % 2 === 0 ? 2 : 0, //graderowSpan
}),
},
{
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',
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,//graderowSpan
}),
},
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;
{
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'
},
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,
},
},
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;">' +
'&nbsp;&nbsp;&nbsp;&nbsp;' +
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: {
normal: {
label: {
show: true, //
position: 'top', //
textStyle: {
//
color: 'black',
fontSize: 12,
},
formatter: '{c}%',
},
},
},
},
],
};
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);
},
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,
//
//
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
// },
//
{
name: '四级通过率',
type: 'pie',
radius: ['35%', '60%'],
itemStyle: {
fontSize: 100,
borderRadius: 10,
borderColor: '#fff',
borderWidth: 2,
},
},
title: {
text: '四级通过率分析',
left: 'left',
top: '0%',
textStyle: {
fontSize: 16,
label: {
show: true,
fontSize: 14,
overflow: 'truncate'
},
},
legend: {
top: 'center',
right: '0%',
orient: 'vertical',
},
color: ['#b3cde0', '#6497b1', '#005b96', '#03396c', '#e5e5e5'],
series: [
//
{
name: '四级通过率',
type: 'pie',
center: ['30%', '50%'],
radius: ['35%', '70%'],
emphasis: {
itemStyle: {
borderRadius: 10,
borderColor: '#fff',
borderWidth: 2,
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
},
label: {
show: true,
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,
fontSize: 15,
fontWeight: 'bold'
}
},
],
};
data: piedata
}
]
};
myChart.setOption(option);
},
},
};
myChart.setOption(option);
}
},
mounted() {
this.getEntrydateAndCollegeData();
this.getCollegeMajorData();
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: 34px;
color: rgb(8, 8, 8);
font-weight: bold;
}
.title {
font-size: 34px;
color: rgb(8, 8, 8);
font-weight: bold;
}
</style>