661 lines
16 KiB
Vue
661 lines
16 KiB
Vue
<template>
|
|
<ai-list class="Statistics">
|
|
<template #left>
|
|
<ai-tree-menu
|
|
title="应报到单位名单"
|
|
searchPlaceholder="请输入单位..."
|
|
@search="onSearch"
|
|
>
|
|
<ai-party-tree
|
|
:filter-node-method="filterNode"
|
|
ref="tree"
|
|
:instance="instance"
|
|
:root="user.info.organizationId"
|
|
:current-node-key="selected.id"
|
|
@select="handleNodeClick"
|
|
/>
|
|
</ai-tree-menu>
|
|
</template>
|
|
<template slot="content">
|
|
<div class="top">
|
|
<header>近12个月党员活动参与情况统计</header>
|
|
<div class="month" id="month"></div>
|
|
</div>
|
|
<div class="middle">
|
|
<header>
|
|
<el-date-picker
|
|
v-model="selectMonth"
|
|
type="month"
|
|
@change="typeScale()"
|
|
size="mini"
|
|
:clearable="false"
|
|
value-format="yyyy-MM-dd"
|
|
placeholder="选择年月"
|
|
>
|
|
</el-date-picker>
|
|
</header>
|
|
<div class="content">
|
|
<div class="middle-left">
|
|
<ul>
|
|
<li>
|
|
<p>应报到党员人数</p>
|
|
<div class="num">
|
|
<span>{{ numObj.party_num }}</span>
|
|
<span>人</span>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>本月报名活动人数</p>
|
|
<div class="num">
|
|
<span>{{ numObj.registered_num }}</span>
|
|
<span>人</span>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>实际参与活动人数</p>
|
|
<div class="num">
|
|
<span>{{ numObj.actual_num }}</span>
|
|
<span>人</span>
|
|
</div>
|
|
</li>
|
|
<li>
|
|
<p>活动实际参与率</p>
|
|
<div class="num">
|
|
<span>{{ numObj.proportion }}</span>
|
|
</div>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
<div class="middle-right" id="middle-right"></div>
|
|
</div>
|
|
</div>
|
|
<div class="bottom">
|
|
<header>
|
|
<ul>
|
|
<li
|
|
v-for="(e, index) in table"
|
|
:key="index"
|
|
@click="handleClick(e, index)"
|
|
:class="{ activeNav: e.id == activeId }"
|
|
>
|
|
{{ e.label }}
|
|
</li>
|
|
<span ref="border"></span>
|
|
</ul>
|
|
</header>
|
|
<ai-search-bar>
|
|
<template #left>
|
|
<el-date-picker
|
|
v-model="searchObj.ymd"
|
|
type="month"
|
|
@change="(page.current = 1), searchList()"
|
|
size="small"
|
|
:clearable="false"
|
|
value-format="yyyy-MM-01"
|
|
placeholder="选择年月"
|
|
>
|
|
</el-date-picker>
|
|
<el-button
|
|
icon="iconfont iconExported"
|
|
size="mini"
|
|
style="margin-left: 8px"
|
|
@click="outPut()"
|
|
:disabled="!Boolean(tableData.length)"
|
|
>导出
|
|
</el-button>
|
|
</template>
|
|
<template #right>
|
|
<el-input
|
|
v-model="searchObj.name"
|
|
size="small"
|
|
placeholder="请输入姓名"
|
|
clearable
|
|
@change="(page.current = 1), searchList()"
|
|
suffix-icon="iconfont iconSearch"
|
|
/>
|
|
</template>
|
|
</ai-search-bar>
|
|
<ai-table
|
|
:dict="dict"
|
|
:tableData="tableData"
|
|
:col-configs="colConfigs"
|
|
:total="page.total"
|
|
style="margin-top: 6px"
|
|
:current.sync="page.current"
|
|
:size.sync="page.size"
|
|
@getList="searchList"
|
|
>
|
|
</ai-table>
|
|
</div>
|
|
</template>
|
|
</ai-list>
|
|
</template>
|
|
|
|
<script>
|
|
import { mapState } from "vuex";
|
|
import * as echarts from "echarts";
|
|
|
|
export default {
|
|
name: "Statistics",
|
|
props: {
|
|
instance: Function,
|
|
dict: Object,
|
|
permissions: Function,
|
|
},
|
|
data() {
|
|
return {
|
|
filterText: "",
|
|
defaultArr: "",
|
|
partyOrgId: "", //当前选中的id
|
|
data12: {},
|
|
selectMonth: "",
|
|
activeId: "0",
|
|
numObj: {},
|
|
searchObj: {
|
|
name: "",
|
|
listType: "0",
|
|
ymd: "",
|
|
},
|
|
tableData: [],
|
|
page: {
|
|
size: 5,
|
|
current: 1,
|
|
total: 0,
|
|
},
|
|
selected: {},
|
|
colConfigs: [
|
|
{ prop: "name", label: "姓名", align: "center" },
|
|
{ prop: "sex", label: "性别", align: "center", dict: "sex" },
|
|
{ prop: "partyOrg", label: "所属组织", align: "center" },
|
|
{ prop: "signupCount", label: "报名次数", align: "center", width: 150 },
|
|
{ prop: "partakeCount", label: "参与次数", align: "center", width: 150 },
|
|
],
|
|
};
|
|
},
|
|
watch: {
|
|
filterText(val) {
|
|
this.$refs.tree.filter(val);
|
|
},
|
|
},
|
|
computed: {
|
|
...mapState(["user"]),
|
|
table() {
|
|
return [
|
|
{ label: "党员活动记录", id: "0" },
|
|
{ label: "未参与活动名单", id: "1" },
|
|
];
|
|
},
|
|
defaultProps() {
|
|
return {
|
|
children: "children",
|
|
label: "label",
|
|
};
|
|
},
|
|
orgTree() {
|
|
return this.$refs.tree?.$refs?.partyTree;
|
|
},
|
|
},
|
|
methods: {
|
|
handleNodeClick(data) {
|
|
this.selected = data;
|
|
this.partyOrgId = data.id;
|
|
this.activeId = "0";
|
|
this.searchObj.name = "";
|
|
this.searchObj.listType = "0";
|
|
this.$nextTick(() => {
|
|
this.month12();
|
|
this.typeScale();
|
|
this.searchList();
|
|
});
|
|
},
|
|
filterNode(value, data) {
|
|
if (!value) return true;
|
|
return data.name.indexOf(value) !== -1;
|
|
},
|
|
month12() {
|
|
this.instance
|
|
.post("/app/apppartyreport/trend", null, {
|
|
params: {
|
|
partyOrgId: this.partyOrgId,
|
|
},
|
|
})
|
|
.then((res) => {
|
|
if (res.code == 0) {
|
|
this.data12 = res.data;
|
|
this.showMonth12(res.data);
|
|
}
|
|
});
|
|
},
|
|
typeScale() {
|
|
this.instance
|
|
.post("/app/apppartyreport/type-scale", null, {
|
|
params: {
|
|
partyOrgId: this.partyOrgId,
|
|
ymd: this.selectMonth,
|
|
},
|
|
})
|
|
.then((res) => {
|
|
if (res.code == 0) {
|
|
this.numObj = res.data;
|
|
this.showPartyScale();
|
|
}
|
|
});
|
|
},
|
|
handleClick(e, index) {
|
|
this.activeId = e.id;
|
|
this.searchObj.listType = e.id;
|
|
this.searchObj.name = "";
|
|
this.page.current = 1;
|
|
this.page.size = 5;
|
|
this.searchList();
|
|
this.$refs.border.style.left = index * 160 + "px";
|
|
},
|
|
searchList() {
|
|
this.instance
|
|
.post(`/app/apppartyreport/list-signup`, null, {
|
|
params: {
|
|
...this.searchObj,
|
|
partyOrgId: this.partyOrgId,
|
|
...this.page,
|
|
},
|
|
})
|
|
.then((res) => {
|
|
if (res?.data) {
|
|
this.tableData = res.data.records;
|
|
this.page.total = res.data.total;
|
|
}
|
|
});
|
|
},
|
|
outPut() {
|
|
this.instance
|
|
.post("/app/apppartyreport/export-signup", null, {
|
|
responseType: "blob",
|
|
params: {
|
|
partyOrgId: this.partyOrgId,
|
|
...this.searchObj,
|
|
},
|
|
})
|
|
.then((res) => {
|
|
const link = document.createElement("a");
|
|
let blob = new Blob([res], { type: "application/vnd.ms-excel" });
|
|
link.style.display = "none";
|
|
link.href = URL.createObjectURL(blob);
|
|
let fileName = "";
|
|
this.activeId == 0
|
|
? (fileName = "党员活动记录")
|
|
: (fileName = "未参与活动名单");
|
|
link.setAttribute("download", fileName + ".xls");
|
|
document.body.appendChild(link);
|
|
link.click();
|
|
document.body.removeChild(link);
|
|
});
|
|
},
|
|
showMonth12(data) {
|
|
let myChart2 = echarts.init(document.getElementById("month"));
|
|
let months = [];
|
|
let arr1 = [];
|
|
let arr2 = [];
|
|
let arr3 = [];
|
|
data.forEach((e) => {
|
|
months.push(e.cycle);
|
|
arr1.push(e.partyNum);
|
|
arr2.push(e.registeredNumrc);
|
|
arr3.push(e.actualNumrc);
|
|
});
|
|
let option = {
|
|
tooltip: {
|
|
trigger: "axis",
|
|
axisPointer: {
|
|
type: "cross",
|
|
label: {
|
|
backgroundColor: "#6a7985",
|
|
},
|
|
},
|
|
},
|
|
dataset: {
|
|
source: [
|
|
["product", ...months],
|
|
["应报到党员人次", ...arr1],
|
|
["报名活动人次", ...arr2],
|
|
["实际参与活动人次", ...arr3],
|
|
],
|
|
},
|
|
legend: {
|
|
data: ["应报到党员人次", "报名活动人次", "实际参与活动人次"],
|
|
},
|
|
toolbox: {
|
|
feature: {
|
|
saveAsImage: {},
|
|
},
|
|
},
|
|
grid: {
|
|
left: "3%",
|
|
right: "4%",
|
|
bottom: "3%",
|
|
containLabel: true,
|
|
},
|
|
xAxis: {
|
|
boundaryGap: false,
|
|
type: "category",
|
|
},
|
|
yAxis: { gridIndex: 0 },
|
|
|
|
series: [
|
|
{ type: "line", smooth: true, seriesLayoutBy: "row" },
|
|
{ type: "line", smooth: true, seriesLayoutBy: "row" },
|
|
{ type: "line", smooth: true, seriesLayoutBy: "row" },
|
|
],
|
|
};
|
|
|
|
myChart2.setOption(option);
|
|
|
|
window.onresize = function () {
|
|
myChart2.resize();
|
|
};
|
|
},
|
|
showPartyScale() {
|
|
let myChart = echarts.init(document.getElementById("middle-right"));
|
|
let legendData = [];
|
|
let seriesData = [];
|
|
if (JSON.stringify(this.numObj.reportTypeMap) != "[]") {
|
|
this.numObj.reportTypeMap.forEach((e) => {
|
|
legendData.push(
|
|
this.dict.getLabel("partyReportSignupReportType", e.report_type)
|
|
);
|
|
seriesData.push({
|
|
value: e.count,
|
|
name: this.dict.getLabel(
|
|
"partyReportSignupReportType",
|
|
e.report_type
|
|
),
|
|
});
|
|
});
|
|
} else {
|
|
legendData = [
|
|
"居住地社区报到服务",
|
|
"单位联系社区报到服务",
|
|
"其他社区报到服务",
|
|
];
|
|
seriesData = [
|
|
{ value: 0, name: "居住地社区报到服务" },
|
|
{ value: 0, name: "单位联系社区报到服务" },
|
|
{ value: 0, name: "其他社区报到服务" },
|
|
];
|
|
}
|
|
let option = {
|
|
backgroundColor: "rgba(249,249,249,1)",
|
|
|
|
title: {
|
|
text: "党员报到类型比例",
|
|
x: "left",
|
|
},
|
|
|
|
tooltip: {
|
|
trigger: "item",
|
|
formatter: "{a} <br/>{b} : {c} ({d}%)",
|
|
},
|
|
legend: {
|
|
orient: "vertical",
|
|
right: 50,
|
|
top: 70,
|
|
bottom: 20,
|
|
width: "auto",
|
|
data: legendData,
|
|
},
|
|
series: [
|
|
{
|
|
name: "党员报到类型比例",
|
|
type: "pie",
|
|
radius: ["45%", "75%"],
|
|
center: ["30%", "55%"],
|
|
avoidLabelOverlap: false,
|
|
label: {
|
|
position: "inside",
|
|
formatter: "{d}%",
|
|
},
|
|
|
|
data: seriesData,
|
|
itemStyle: {
|
|
normal: {
|
|
color: function (params) {
|
|
//自定义颜色
|
|
var colorList = [
|
|
"#4B87FE",
|
|
"#FFAA44",
|
|
"#FF4466",
|
|
"#FFAA44",
|
|
"#2EA222",
|
|
];
|
|
return colorList[params.dataIndex];
|
|
},
|
|
},
|
|
},
|
|
},
|
|
],
|
|
};
|
|
myChart.setOption(option);
|
|
window.onresize = function () {
|
|
myChart.resize();
|
|
};
|
|
},
|
|
getNowDate() {
|
|
let mydate = new Date();
|
|
let mymonth = mydate.getMonth() + 1;
|
|
mymonth < 10 ? (mymonth = `0${mymonth}`) : mymonth;
|
|
let year = mydate.getFullYear();
|
|
return `${year}-${mymonth}-01`;
|
|
},
|
|
|
|
onSearch(v) {
|
|
this.orgTree.filter(v);
|
|
},
|
|
},
|
|
mounted() {
|
|
this.partyOrgId = this.user.info.organizationId;
|
|
this.dict.load("partyReportSignupReportType", "sex");
|
|
this.selectMonth = this.getNowDate();
|
|
this.searchObj.ymd = this.getNowDate();
|
|
this.$nextTick(() => {
|
|
this.month12();
|
|
this.typeScale();
|
|
this.searchList();
|
|
});
|
|
},
|
|
};
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.Statistics {
|
|
width: 100%;
|
|
height: 100%;
|
|
padding: 16px;
|
|
box-sizing: border-box;
|
|
overflow: auto;
|
|
|
|
.top {
|
|
width: 100%;
|
|
height: 288px;
|
|
background-color: #fff;
|
|
border-radius: 4px;
|
|
padding: 16px 12px;
|
|
box-sizing: border-box;
|
|
|
|
header {
|
|
color: #333333;
|
|
padding: 0 16px;
|
|
box-sizing: border-box;
|
|
height: 47px;
|
|
font-size: 16px;
|
|
font-weight: bold;
|
|
line-height: 47px;
|
|
background: rgba(255, 255, 255, 1);
|
|
border-bottom: 1px solid #eee;
|
|
}
|
|
|
|
.month {
|
|
width: 100%;
|
|
padding: 16px;
|
|
box-sizing: border-box;
|
|
height: calc(100% - 47px);
|
|
}
|
|
}
|
|
|
|
.middle {
|
|
width: 100%;
|
|
height: 346px;
|
|
margin-top: 16px;
|
|
background-color: #fff;
|
|
border-radius: 4px;
|
|
padding: 16px 12px;
|
|
box-sizing: border-box;
|
|
|
|
header {
|
|
padding: 0 16px;
|
|
box-sizing: border-box;
|
|
height: 48px;
|
|
display: flex;
|
|
align-items: center;
|
|
}
|
|
|
|
.content {
|
|
width: 100%;
|
|
padding: 16px;
|
|
box-sizing: border-box;
|
|
height: calc(100% - 48px);
|
|
|
|
.middle-left {
|
|
width: 50%;
|
|
height: 100%;
|
|
float: left;
|
|
|
|
ul {
|
|
overflow: hidden;
|
|
width: 95%;
|
|
height: 100%;
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
|
|
li {
|
|
width: 48%;
|
|
height: 112px;
|
|
padding: 8px;
|
|
box-sizing: border-box;
|
|
background: rgba(249, 249, 249, 1);
|
|
border-radius: 2px;
|
|
margin-bottom: 16px;
|
|
margin-left: 4%;
|
|
|
|
&:nth-of-type(2n - 1) {
|
|
margin-left: 0;
|
|
}
|
|
|
|
p {
|
|
color: #333333;
|
|
font-size: 16px;
|
|
height: 32px;
|
|
font-weight: bold;
|
|
}
|
|
|
|
.num {
|
|
height: 80px;
|
|
line-height: 60px;
|
|
|
|
span:nth-of-type(1) {
|
|
color: #2266ff;
|
|
font-size: 32px;
|
|
}
|
|
|
|
span:nth-of-type(2) {
|
|
font-size: 16px;
|
|
color: rgba(153, 153, 153, 1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
.middle-right {
|
|
width: 50%;
|
|
height: 100%;
|
|
float: left;
|
|
padding: 4px;
|
|
box-sizing: border-box;
|
|
background: rgba(249, 249, 249, 1);
|
|
border-radius: 2px;
|
|
}
|
|
}
|
|
}
|
|
|
|
.bottom {
|
|
width: 100%;
|
|
height: 464px;
|
|
margin-top: 16px;
|
|
background-color: #fff;
|
|
border-radius: 4px;
|
|
padding: 16px 12px;
|
|
box-sizing: border-box;
|
|
|
|
header {
|
|
width: 100%;
|
|
height: 56px;
|
|
padding: 0 16px;
|
|
box-sizing: border-box;
|
|
border-bottom: 1px solid rgb(241, 237, 237);
|
|
margin-bottom: 16px;
|
|
|
|
ul {
|
|
width: 100%;
|
|
height: 100%;
|
|
position: relative;
|
|
|
|
li {
|
|
width: 160px;
|
|
height: 56px;
|
|
line-height: 56px;
|
|
float: left;
|
|
text-align: center;
|
|
font-size: 16px;
|
|
color: #333333;
|
|
position: relative;
|
|
transition: opacity 1s;
|
|
cursor: pointer;
|
|
opacity: 0.7;
|
|
|
|
&:hover {
|
|
color: rgba(34, 102, 255, 1);
|
|
}
|
|
}
|
|
|
|
.activeNav {
|
|
opacity: 1;
|
|
font-weight: bold;
|
|
color: rgba(34, 102, 255, 1);
|
|
}
|
|
|
|
span {
|
|
width: 160px;
|
|
height: 3px;
|
|
display: block;
|
|
background-color: rgba(34, 102, 255, 1);
|
|
transition: left 0.5s;
|
|
position: absolute;
|
|
bottom: 0;
|
|
left: 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
:deep( .el-col-24 ){
|
|
width: auto;
|
|
}
|
|
:deep( .ai-list__content--right-wrapper ){
|
|
background-color: none!important;
|
|
padding: 0!important;
|
|
}
|
|
:deep( .el-tree .is-current>.el-tree-node__content ){
|
|
min-width: 100%!important;
|
|
}
|
|
}
|
|
</style>
|