学校、部门接口

main
significative 4 months ago
parent 34f2e164e2
commit e8c9ce5f1c
  1. 13
      jeecgboot-vue3-master/src/api/demo/depart.ts
  2. 127
      jeecgboot-vue3-master/src/views/depart/workbench/components/chDepartment/index.vue
  3. 112
      jeecgboot-vue3-master/src/views/depart/workbench/components/chSchool/index.vue
  4. 259
      jeecgboot-vue3-master/src/views/depart/workbench/components/chSchool/options.js

@ -0,0 +1,13 @@
import { defHttp } from '/@/utils/http/axios';
import { GetAccountInfoModel } from './model/accountModel';
enum Api {
PAGE_SCHOOL = '/user/login/homepage/school',
PAGE_DEPARTMENT ='/user/login/homepage/depart'
}
// Get personal center-basic settings
export const pageSchoolApi = () => defHttp.get<GetAccountInfoModel>({ url: Api.PAGE_SCHOOL });
export const pageDepartmentApi = (orgCode:string) => defHttp.get<GetAccountInfoModel>({ url: Api.PAGE_DEPARTMENT ,params:{orgCode}});

@ -2,67 +2,31 @@
<div class="department">
<div class="header">
<a-row :gutter="[16, 16]" type="flex" justify="space-between" style="width: 100%;">
<a-col :xs="12" :xl="6">
<a-col :lg="12" :xl="6" v-for="i in [
{ svg: 'mainHome-time|svg', title: '本年度已开展比赛项目数' },
{ svg: 'mainHome-time|svg', title: '本年度参加比赛队伍数' },
{ svg: 'mainHome-time|svg', title: '正在进行的比赛数' },
]" :key="i">
<div class="card">
<div class="top">
<div class="text">
本年度已开展比赛数
{{ i.title }}
</div>
<Icon icon="mainHome-time|svg" :size="20" />
<Icon :icon="i.svg" :size="20" />
</div>
<div class="center">
<div class="text">
67
{{ match[i.title] || 0 }}
</div>
</div>
<div class="bottom">
<div class="bot_card">国赛12</div>
<div class="bot_card">省赛12</div>
<div class="bot_card">校赛24</div>
<div class="bot_card">国赛{{ match['国赛'] || 0 }}</div>
<div class="bot_card">省赛{{ match['省赛'] || 0 }}</div>
<div class="bot_card">校赛{{ match['校赛'] || 0 }}</div>
</div>
</div>
</a-col>
<a-col :xs="12" :xl="6">
<div class="card">
<div class="top">
<div class="text">
本年度参加比赛队伍数
</div>
<Icon icon="mainHome-mp|svg" :size="20" />
</div>
<div class="center">
<div class="text">
1262
</div>
</div>
<div class="bottom">
<div class="bot_card">国赛120</div>
<div class="bot_card">省赛1230</div>
<div class="bot_card">校赛24</div>
</div>
</div>
</a-col>
<a-col :xs="12" :xl="6">
<div class="card">
<div class="top">
<div class="text">
正在进行的比赛数
</div>
<Icon icon="mainHome-down|svg" :size="20" />
</div>
<div class="center">
<div class="text" style="color: #74D472;">
45
</div>
</div>
<div class="bottom">
<div class="bot_card">国赛9</div>
<div class="bot_card">省赛13</div>
<div class="bot_card">校赛26</div>
</div>
</div>
</a-col>
<a-col :xs="12" :xl="6">
<div class="card2">
<div class="top">
@ -73,18 +37,19 @@
</div>
<div class="center">
<div class="percent">
78%
{{ (match['已完成比赛比率'] || 0) * 100 + '%' }}
</div>
<div>
<a-progress stroke-linecap="square" :percent="78" :show-info="false" />
<a-progress stroke-linecap="square" :percent="(match['已完成比赛比率'] || 0) * 100"
:show-info="false" />
</div>
</div>
<div class="bottom">
<div class="text">
已完成的比赛11
已完成的比赛{{ match['已完成的比赛'] || 0 }}
</div>
<div class="text">
未完成的比赛11
未完成的比赛{{ match['未完成的比赛'] || 0 }}
</div>
</div>
</div>
@ -115,9 +80,9 @@
<div id="ec_bar" ref="ec_bar"></div>
<div class="infor">
<ul class="card-box">
<li v-for="i in 12" :key="i">
<div class="ol">{{ i }}</div>
<div class="text">奠定基础</div>
<li v-for="item, i in names" :key="item">
<div class="ol">{{ i + 1 }}</div>
<div class="text" :title="item">{{ item }}</div>
</li>
</ul>
</div>
@ -184,18 +149,63 @@
</div>
</template>
<script lang="ts" setup>
function traYears(arr: any[], attr = 'value', option: any = { attrs: [], values: [] }): any[] {
if (!Array.isArray(arr)) return []
if (option.attrs.length && option.values.length) {
return arr.map(item => {
let o = {}
option.attrs.map((at, i) => {
if (typeof option.values[i] === 'object') o[at] = option.values[i].value
else o[at] = item[option.values[i]]
})
return o
})
}
return arr.map(item => item[attr])
}
import { Progress as AProgress } from 'ant-design-vue';
import { onMounted, ref } from 'vue';
import { onMounted, ref, reactive } from 'vue';
import * as echarts from 'echarts';
import { optionRing, optionBar } from './options'
import { pageDepartmentApi } from '/@/api/demo/depart';
import { useUserStore } from '/@/store/modules/user';
const userStore = useUserStore()
const match = reactive<any>({})
const names = reactive<any[]>([])
if (userStore.userInfo) {
pageDepartmentApi(userStore.userInfo.orgCode as string).then(res => {
// pageDepartmentApi('A03').then(res => {
Object.assign(match, res)
optionBar.series[0].data = traYears(res['部门近2年能力分析']?.[0][2023])
optionBar.series[1].data = traYears(res['部门近2年能力分析']?.[1][2024])
setBar.value()
names.push(...traYears(res['部门近2年能力分析']?.[0][2023], 'capacityName'))
optionRing.series[0].data = [
{ name: '已完成',value: res['已完成的比赛'] || 0, },
{ name: '比赛中',value: res['正在进行的比赛数']|| 0 },
{ name: '未开始',value: res['未完成的比赛'] || 0 },
]
setRing.value()
})
}
const ec = ref()
const ec_bar = ref()
const setBar = ref(() => { })
const setRing = ref(() => { })
onMounted(() => {
const myChart = echarts.init(ec.value);
myChart.setOption(optionRing);
setRing.value = ()=> myChart.setOption(optionRing);
const bar = echarts.init(ec_bar.value);
bar.setOption(optionBar);
setBar.value = () => bar.setOption(optionBar);
window.addEventListener('resize', function () {
myChart.resize()
bar.resize()
@ -515,6 +525,9 @@ onMounted(() => {
}
.text {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 67px;
font-size: 14px;
color: rgba(51, 51, 51, 0.88);

@ -1,26 +1,28 @@
<template>
<div class="school">
<a-row :gutter="[16, 16]" type="flex" justify="space-between">
<a-col :lg="12" :xl="6" v-for="i in 4" :key="i">
<div class="card">
<div class="top">
<div class="text">
本年度已开展比赛数
<a-row :gutter="[16, 16]" type="flex" justify="space-between">
<a-col :lg="12" :xl="6" v-for="i in ['本年度已开展比赛项目数', '本年度参加比赛队伍数', '正在进行的比赛数', '已完成的比赛']" :key="i">
<div class="card">
<div class="top">
<div class="text">
{{ i }}
</div>
<Icon icon="mainHome-time|svg" :size="20" />
</div>
<Icon icon="mainHome-time|svg" :size="20" />
</div>
<div class="center">
<div class="text">
67
<div class="center">
<div class="text">
{{ match[i] }}
</div>
</div>
<div class="bottom">
<div class="bot_card">国赛{{ match['国赛'] || 0 }}</div>
<div class="bot_card">省赛{{ match['省赛'] || 0 }}</div>
<div class="bot_card">校赛{{ match['校赛'] || 0 }}</div>
</div>
</div>
<div class="bottom">
<div class="bot_card">国赛12</div>
<div class="bot_card">省赛12</div>
<div class="bot_card">校赛24</div>
</div>
</div>
</a-col>
</a-col>
</a-row>
</a-row>
<a-row :gutter="[16, 16]" type="flex" justify="space-between">
<a-col :xs="24" :xl="8">
@ -36,7 +38,7 @@
<a-col :xs="24" :xl="16">
<div class="con_right">
<div class="title-box">
<div class="tit">部门近两年维度积分</div>
<div class="tit">学校近两年能力分析</div>
<div class="bas"></div>
</div>
<div class="ec-box">
@ -44,9 +46,9 @@
<div id="ec_bar" ref="ec_bar"></div>
<div class="infor">
<ul class="card-box">
<li v-for="i in 12" :key="i">
<div class="ol">{{ i }}</div>
<div class="text">奠定基础</div>
<li v-for="item, i in names" :key="item">
<div class="ol">{{ i + 1 }}</div>
<div class="text" :title="item">{{ item }}</div>
</li>
</ul>
</div>
@ -59,13 +61,14 @@
<a-col :xs="24" :xl="12">
<div class="foo_card">
<div class="title">
部门比赛积分排名
本年度全校部门积分排名
</div>
<div class="table">
<div class="t_item t_head">
<div class="ranking">排名</div>
<div class="name">比赛名称</div>
<div class="name2">比赛名称</div>
<div class="name2">项目名称</div>
<div class="total">比赛积分</div>
<div class="operate">操作</div>
</div>
@ -73,7 +76,8 @@
<div class="ranking">
<div class="ol" :class="{ ac: i <= 3 }">{{ i }}</div>
</div>
<div class="name">国家电网竞赛</div>
<div class="name2">国家电网竞赛</div>
<div class="name2">国家电网竞赛</div>
<div class="total">7059</div>
<div class="operate">详情</div>
</div>
@ -83,13 +87,13 @@
<a-col :xs="24" :xl="12">
<div class="foo_card">
<div class="title">
部门学生积分排名
本年度项目积分排名
</div>
<div class="table">
<div class="t_item t_head">
<div class="ranking">排名</div>
<div class="name">参赛选手名</div>
<div class="name">院系名称</div>
<div class="total">比赛积分</div>
<div class="operate">操作</div>
</div>
@ -110,17 +114,58 @@
<script setup lang="ts">
import { onMounted, ref } from 'vue';
import { onMounted, reactive, ref } from 'vue';
import * as echarts from 'echarts';
import { optionRadar, optionBar } from '../chDepartment/options'
import { optionRadar, optionBar } from './options'
import { pageSchoolApi } from '/@/api/demo/depart';
function traYears(arr: any[], attr = 'value',option:any={attrs:[],values: []}): any[] {
if (!Array.isArray(arr)) return []
if(option.attrs.length&&option.values.length){
return arr.map(item => {
let o = {}
option.attrs.map((at,i)=>{
if(typeof option.values[i] === 'object')o[at] = option.values[i].value
else o[at]=item[option.values[i]]
})
return o
})
}
return arr.map(item => item[attr])
}
const match = reactive({})
const names = reactive<any[]>([])
pageSchoolApi().then(res => {
Object.assign(match, res)
optionBar.series[0].data = traYears(res['近2年能力分析']?.[0][2023])
optionBar.series[1].data = traYears(res['近2年能力分析']?.[1][2024])
setBar.value()
names.push(...traYears(res['近2年能力分析']?.[0][2023], 'capacityName'))
optionRadar.radar.indicator = traYears(res['近2年能力分析']?.[0][2023],undefined,{attrs:['text','max'],values:['capacityName',{value:100}]})
optionRadar.series[0].data[0].value = traYears(res['近2年能力分析']?.[0][2023])
setRadar.value()
})
const ec_radar = ref()
const ec_bar = ref()
const setRadar = ref(() => { })
const setBar = ref(() => { })
onMounted(() => {
const myChart = echarts.init(ec_radar.value);
myChart.setOption(optionRadar);
setRadar.value = () => myChart.setOption(optionRadar)
const bar = echarts.init(ec_bar.value);
bar.setOption(optionBar);
setBar.value = () => bar.setOption(optionBar)
window.addEventListener('resize', function () {
myChart.resize()
bar.resize()
@ -339,6 +384,9 @@ onMounted(() => {
}
.text {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
width: 67px;
font-size: 14px;
color: rgba(51, 51, 51, 0.88);
@ -398,6 +446,10 @@ onMounted(() => {
width: calc((542 / 756) * 100%);
}
.name2 {
width: calc((271 / 756) * 100%);
}
.total {
width: calc((74 / 756) * 100%);
}

@ -0,0 +1,259 @@
// 部门比赛情况分布 圆环
export const optionRing = {
color: [
'#0052D9',
'#699EF5',
'#B5C7FF',
],
legend: {
x: 'center',
orient: 'horizontal',
bottom: '48px',
data: ['已完成', '比赛中', '未开始']
},
series: [
{
type: 'pie',
center: ['50%', '41%'],
radius: ['35%', '45%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center'
},
labelLine: {
show: false
},
emphasis: {
label: {
show: true,
fontSize: '25',
fontWeight: 'bold'
}
},
data: [
{ value: 335, name: '已完成' },
{ value: 50, name: '比赛中' },
{ value: 23, name: '未开始' },
]
}
]
};
export const optionBar = {
tooltip: {
trigger: 'axis', // 触发类型为坐标轴触发
axisPointer: {
type: 'line',
label: {
backgroundColor: '#6a7985' // 自定义交叉线标签的背景色
}
},
formatter: function (params) {
let result = '<div class="bar_card">';
result += `<div class="title">维度名称</div>`
params.forEach(param => {
result += `<div class="item" style="color: ${param.color};">
${param.seriesName} ${param.value}
</div>`;
});
result += '</div>';
return result;
}
},
grid: {
left: '0%',
right: '0%',
top: '5%',
bottom: '86px',
// 如果需要,还可以设置containLabel来控制坐标轴标签是否完全包含在grid区域内
containLabel: true
},
legend: {
data: ['2023', '2024'],
bottom: '39px',
},
xAxis: {
data: ['维度一', '维度一', '维度一', '维度一', '维度一', '维度一', '维度一']
},
yAxis: {
type: 'value',
min: 0,
max: 100,
},
series: [
{
name: '2023',
type: 'bar',
data: [33, 44, 58, 85, 47, 38, 45],
barWidth: '20px',
itemStyle: {
color: '#0052D9',
}
},
{
name: '2024',
type: 'bar',
data: [36, 34, 48, 62, 43, 30, 37],
barWidth: '20px',
itemStyle: {
color: '#699EF5',
}
},
]
};
var colorArr = ['#fff', '#fff']; //颜色
var dataArr = [
{
value: [4000, 700, 3600, 3900, 1800, 4200, 700, 3600, 4200, 700, 3600, 4200, 700, 3600],
name: '1',
itemStyle: {
normal: {
lineStyle: {
color: '#55d7f2',
},
shadowColor: '#4A99FF',
shadowBlur: 10,
},
},
areaStyle: {
normal: {
// 单项区域填充样式
color: {
type: 'linear',
x: 1, //右
y: 0, //下
x2: 1, //左
y2: 1, //上
colorStops: [
{
offset: 0,
color: '#f0a223',
},
{
offset: 1,
color: '#093138',
},
],
globalCoord: false,
},
opacity: 1, // 区域透明度
},
},
},
];
var indicator = [
{
text: '前言探索',
max: 6000,
},
{
text: '奠定基础',
max: 5000,
},
{
text: '知识分析',
max: 5000,
},
{
text: '社会责任',
max: 5000,
},
{
text: '独立思考',
max: 5500,
},
{
text: '拓宽视野',
max: 5000,
},
{
text: '激发兴趣',
max: 5000,
},
{
text: '沟通协调',
max: 5000,
},
{
text: '设计开发',
max: 5000,
},
{
text: '研判分析',
max: 5000,
},
{
text: '创新能力',
max: 5000,
},
{
text: '团队协作',
max: 5000,
},
];
export const optionRadar = {
backgroundColor: "transparent",
color: colorArr,
// legend: {
// orient: "vertical",
// // icon: 'circle', //图例形状
// // data: legendData,
// top: 0,
// left: 20,
// itemWidth: 8, // 图例标记的图形宽度。[ default: 25 ]
// itemHeight: 8, // 图例标记的图形高度。[ default: 14 ]
// itemGap: 22, // 图例每项之间的间隔。[ default: 10 ]横向布局时为水平间隔,纵向布局时为纵向间隔。
// textStyle: {
// fontSize: 12,
// fontWeight: "bold",
// color: "#00E4FF",
// },
// },
tooltip: {
trigger: 'item'
},
radar: {
// shape: 'circle',
name: {
textStyle: {
color: "#9ca4a6",
fontSize: 12,
},
},
indicator: indicator,
splitArea: {
// 坐标轴在 grid 区域中的分隔区域,默认不显示。
show: true,
areaStyle: {
// 分隔区域的样式设置。
color: ["rgba(255,255,255,0)", "rgba(255,255,255,0)"], // 分隔区域颜色。分隔区域会按数组中颜色的顺序依次循环设置颜色。默认是一个深浅的间隔色。
},
},
axisLine: {
//指向外圈文本的分隔线样式
lineStyle: {
color: "#2a5f61",
},
},
splitLine: {
lineStyle: {
color: "#2a5f61", // 分隔线颜色
width: 1, // 分隔线线宽
},
},
},
series: [
{
type: "radar",
symbolSize: 6,
symbol: "circle",
data: dataArr,
},
],
};
Loading…
Cancel
Save