Files
dvcp_v2_webapp/project/pingchang/apps/AppCommunityMember/Statistics.vue
liuye a86f37ecfc bug
2022-10-27 18:07:44 +08:00

660 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;
}
}
}
}
::v-deep .el-col-24 {
width: auto;
}
::v-deep .ai-list__content--right-wrapper {
background-color: none!important;
padding: 0!important;
}
::v-deep .el-tree .is-current>.el-tree-node__content {
min-width: 100%!important;
}
}
</style>