415 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			415 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
| <template>
 | |
|   <section class="staPane">
 | |
|     <ai-list isTabs>
 | |
|       <template #blank>
 | |
|         <ai-tree-menu title="组织目录" @search="v=>$refs.areaTree.filter(v)">
 | |
|           <el-tree ref="areaTree" lazy node-key="id" :load="getAreas"
 | |
|                    :filter-node-method="handleTreeFilter"
 | |
|                    :default-expanded-keys="[selectedAreaId]"
 | |
|                    @node-click="handleSelectArea"
 | |
|                    :props="{label:'name',isLeaf:'leaf'}"/>
 | |
|         </ai-tree-menu>
 | |
|         <el-scrollbar>
 | |
|           <div class="mainPane">
 | |
|             <el-row type="flex">
 | |
|               <div class="cardPane orgCountMap" v-for="v in orgCountMap" :key="v.key">
 | |
|                 <b v-html="v.name"/>
 | |
|                 <span v-html="v.desc"/>
 | |
|                 <b class="count" v-html="v.v1"/>
 | |
|               </div>
 | |
|             </el-row>
 | |
|             <el-row type="flex">
 | |
|               <div class="cardPane">
 | |
|                 <ai-title title="各类组织成员数量" class="pad-l32"/>
 | |
|                 <div id="orgMemberCountMapChart"/>
 | |
|               </div>
 | |
|               <div class="cardPane">
 | |
|                 <ai-title title="待建党组织关注度统计" class="pad-l32"/>
 | |
|                 <div id="buildPartyCountMapChart"/>
 | |
|               </div>
 | |
|             </el-row>
 | |
|             <el-row type="flex" v-if="top.bizType==0">
 | |
|               <div class="cardPane">
 | |
|                 <ai-title title="新经济组织类型分布" class="pad-l32"/>
 | |
|                 <div id="companyCategoryCountMapChart"/>
 | |
|               </div>
 | |
|               <div class="cardPane">
 | |
|                 <ai-title title="安全隐患类型占比" class="pad-l32"/>
 | |
|                 <div id="dangerousTypeCountMapChart"/>
 | |
|               </div>
 | |
|             </el-row>
 | |
|             <el-row type="flex" v-if="top.bizType==1">
 | |
|               <div class="cardPane">
 | |
|                 <ai-title title="新社会组织类型分布" class="pad-l32"/>
 | |
|                 <div id="socialTypeCountMapChart"/>
 | |
|               </div>
 | |
|               <div class="cardPane">
 | |
|                 <ai-title title="外资背景统计" class="pad-l32"/>
 | |
|                 <div id="foreignCountMapChart"/>
 | |
|               </div>
 | |
|             </el-row>
 | |
|           </div>
 | |
|         </el-scrollbar>
 | |
|       </template>
 | |
|     </ai-list>
 | |
|   </section>
 | |
| </template>
 | |
| 
 | |
| <script>
 | |
| import {mapState} from "vuex";
 | |
| import * as echarts from "echarts";
 | |
| 
 | |
| export default {
 | |
|   name: "staPane",
 | |
|   label: "两新组织统计",
 | |
|   props: {
 | |
|     instance: Function,
 | |
|     dict: Object,
 | |
|     permissions: Function,
 | |
|   },
 | |
|   inject: ['top'],
 | |
|   computed: {
 | |
|     ...mapState(['user']),
 | |
|     typeName() {
 | |
|       return this.top.bizType == 0 ? '新经济' : '新社会'
 | |
|     },
 | |
|     orgCountMap() {
 | |
|       let init = [
 | |
|         {name: `${this.typeName}组织总量`, desc: `当前所有的${this.typeName}组织总数量`, key: "zzzl", v1: 0},
 | |
|         {name: "含有党群组织的数量", desc: `含有党群组织的${this.typeName}组织总数量`, key: "dqzzsl", v1: 0},
 | |
|         {name: "具备建立中共党组织条件的数量", desc: "具备条件但尚未建立党组织的数量", key: "jbjldzztjsl", v1: 0}
 | |
|       ]
 | |
|       return init.map(e => ({
 | |
|         ...e,
 | |
|         v1: Number(this.meta.orgCountMap?.[e.key]) || 0
 | |
|       }))
 | |
|     },
 | |
|     chartOps() {
 | |
|       let orgMemberCountMapData = this.dict.getDict('orgMemberTypes').map(e => [e.dictName, Number(this.meta?.orgMemberCountMap?.[e.dictValue] || 0)]),
 | |
|           buildPartyCountMapData = this.dict.getDict('twoNewOrgConcernDegree').map(e => [e.dictName, Number(this.meta?.buildPartyCountMap?.[e.dictValue] || 0)]),
 | |
|           companyCategoryCountMapData = this.dict.getDict('twoNewOrgCompanyCategory').map(e => [e.dictName, Number(this.meta?.companyCategoryCountMap?.[e.dictValue] || 0)]),
 | |
|           dangerousTypeCountMapData = this.dict.getDict('twoNewOrgDangerousType').slice(1).map(e => [e.dictName, Number(this.meta?.dangerousTypeCountMap?.[e.dictValue] || 0)]),
 | |
|           socialTypeCountMapData = this.dict.getDict('twoNewOrgSocialType').map(e => [e.dictName, Number(this.meta?.socialTypeCountMap?.[e.dictValue] || 0)]),
 | |
|           foreignCountMapData = this.dict.getDict('twoNewOrgIsForeign').map(e => [e.dictName, Number(this.meta?.foreignCountMap?.[e.dictValue] || 0)])
 | |
|       return {
 | |
|         orgMemberCountMap: {
 | |
|           tooltip: {},
 | |
|           grid: {
 | |
|             left: 82,
 | |
|             right: 40,
 | |
|             bottom: 80,
 | |
|             top: 30
 | |
|           },
 | |
|           xAxis: {
 | |
|             type: 'category', axisLine: {lineStyle: {color: '#D8DDE8'}}, axisTick: false,
 | |
|             axisLabel: {color: '#666', margin: 19}
 | |
|           },
 | |
|           yAxis: {
 | |
|             type: 'value', axisLine: false, min: 0, minInterval: 1,
 | |
|             axisLabel: {color: '#666', margin: 19},
 | |
|             splitLine: {lineStyle: {color: '#D8DDE8', type: 'dashed'}}
 | |
|           },
 | |
|           series: {
 | |
|             type: 'bar',
 | |
|             barWidth: 24,
 | |
|             itemStyle: {color: '#22AA99'},
 | |
|             emphasis: {itemStyle: {color: "#2266FF"}},
 | |
|           },
 | |
|           dataset: {
 | |
|             source: orgMemberCountMapData
 | |
|           }
 | |
|         },
 | |
|         buildPartyCountMap: {
 | |
|           tooltip: {},
 | |
|           grid: {
 | |
|             left: 82,
 | |
|             right: 40,
 | |
|             bottom: 80,
 | |
|             top: 30
 | |
|           },
 | |
|           xAxis: {
 | |
|             type: 'category', axisLine: {lineStyle: {color: '#D8DDE8'}}, axisTick: false,
 | |
|             axisLabel: {color: '#666', margin: 19}
 | |
|           },
 | |
|           yAxis: {
 | |
|             type: 'value', axisLine: false, min: 0, minInterval: 1,
 | |
|             axisLabel: {color: '#666', margin: 19},
 | |
|             splitLine: {lineStyle: {color: '#D8DDE8', type: 'dashed'}}
 | |
|           },
 | |
|           series: {
 | |
|             type: 'bar',
 | |
|             barWidth: 24,
 | |
|             itemStyle: {color: '#22AA99'},
 | |
|             emphasis: {itemStyle: {color: "#2266FF"}},
 | |
|           },
 | |
|           dataset: {
 | |
|             source: buildPartyCountMapData
 | |
|           }
 | |
|         },
 | |
|         companyCategoryCountMap: {
 | |
|           legend: {
 | |
|             orient: 'vertical', left: 220, y: 'center',
 | |
|             itemGap: 4, itemWidth: 8, itemHeight: 8,
 | |
|             formatter: name => {
 | |
|               let item = companyCategoryCountMapData.find(e => e?.[0] == name)
 | |
|               return `  {a|${name.replace(/(.{10}).*/g, '$1...')}} {b|${item?.[1]}}`
 | |
|             },
 | |
|             tooltip: {show: true},
 | |
|             textStyle: {
 | |
|               rich: {
 | |
|                 a: {color: '#666', width: 130, fontSize: 14, lineHeight: 22},
 | |
|                 b: {fontWeight: 'bold', align: 'right', color: '#333', fontSize: 14, width: 54, lineHeight: 22}
 | |
|               }
 | |
|             },
 | |
|           },
 | |
|           tooltip: {},
 | |
|           color: ['#02A499', '#F8B425', '#EC4461', '#D846E4', '#38A4F8'],
 | |
|           series: {
 | |
|             name: '重点青少年类型分布',
 | |
|             center: [100, '50%'], radius: 80,
 | |
|             type: 'pie', label: false,
 | |
|             itemStyle: {borderColor: '#fff', borderWidth: 2},
 | |
|           },
 | |
|           dataset: {
 | |
|             source: companyCategoryCountMapData
 | |
|           }
 | |
|         },
 | |
|         dangerousTypeCountMap: {
 | |
|           legend: {
 | |
|             orient: 'vertical', left: 220, y: 'center',
 | |
|             itemGap: 4, itemWidth: 8, itemHeight: 8,
 | |
|             formatter: name => {
 | |
|               let item = dangerousTypeCountMapData.find(e => e?.[0] == name)
 | |
|               return `  {a|${name.replace(/(.{10}).*/g, '$1...')}} {b|${item?.[1]}}`
 | |
|             },
 | |
|             tooltip: {show: true},
 | |
|             textStyle: {
 | |
|               rich: {
 | |
|                 a: {color: '#666', width: 166, fontSize: 14, lineHeight: 22},
 | |
|                 b: {fontWeight: 'bold', align: 'right', color: '#333', fontSize: 14, lineHeight: 22}
 | |
|               }
 | |
|             },
 | |
|           },
 | |
|           tooltip: {},
 | |
|           color: ['#02A499', '#F8B425', '#EC4461', '#D846E4', '#38A4F8'],
 | |
|           series: {
 | |
|             name: '重点青少年性别分布', type: 'pie',
 | |
|             center: [100, '50%'], radius: [40, 80], label: false,
 | |
|             itemStyle: {borderColor: '#fff', borderWidth: 2},
 | |
|           },
 | |
|           dataset: {
 | |
|             source: dangerousTypeCountMapData
 | |
|           }
 | |
|         },
 | |
|         socialTypeCountMap: {
 | |
|           legend: {
 | |
|             orient: 'vertical', left: 220, y: 'center',
 | |
|             itemGap: 4, itemWidth: 8, itemHeight: 8,
 | |
|             formatter: name => {
 | |
|               let item = socialTypeCountMapData.find(e => e?.[0] == name)
 | |
|               return `  {a|${name.replace(/(.{10}).*/g, '$1...')}} {b|${item?.[1]}}`
 | |
|             },
 | |
|             tooltip: {show: true},
 | |
|             textStyle: {
 | |
|               rich: {
 | |
|                 a: {color: '#666', width: 130, fontSize: 14, lineHeight: 22},
 | |
|                 b: {fontWeight: 'bold', align: 'right', color: '#333', fontSize: 14, width: 54, lineHeight: 22}
 | |
|               }
 | |
|             },
 | |
|           },
 | |
|           tooltip: {},
 | |
|           color: ['#02A499', '#F8B425', '#EC4461', '#D846E4', '#38A4F8'],
 | |
|           series: {
 | |
|             name: '重点青少年类型分布',
 | |
|             center: [100, '50%'], radius: 80,
 | |
|             type: 'pie', label: false,
 | |
|             itemStyle: {borderColor: '#fff', borderWidth: 2},
 | |
|           },
 | |
|           dataset: {
 | |
|             source: socialTypeCountMapData
 | |
|           }
 | |
|         },
 | |
|         foreignCountMap: {
 | |
|           legend: {
 | |
|             orient: 'vertical', left: 220, y: 'center',
 | |
|             itemGap: 4, itemWidth: 8, itemHeight: 8,
 | |
|             formatter: name => {
 | |
|               let item = foreignCountMapData.find(e => e?.[0] == name)
 | |
|               return `  {a|${name.replace(/(.{10}).*/g, '$1...')}} {b|${item?.[1]}}`
 | |
|             },
 | |
|             tooltip: {show: true},
 | |
|             textStyle: {
 | |
|               rich: {
 | |
|                 a: {color: '#666', width: 166, fontSize: 14, lineHeight: 22},
 | |
|                 b: {fontWeight: 'bold', align: 'right', color: '#333', fontSize: 14, lineHeight: 22}
 | |
|               }
 | |
|             },
 | |
|           },
 | |
|           tooltip: {},
 | |
|           color: ['#02A499', '#F8B425', '#EC4461', '#D846E4', '#38A4F8'],
 | |
|           series: {
 | |
|             name: '重点青少年性别分布', type: 'pie',
 | |
|             center: [100, '50%'], radius: [40, 80], label: false,
 | |
|             itemStyle: {borderColor: '#fff', borderWidth: 2},
 | |
|           },
 | |
|           dataset: {
 | |
|             source: foreignCountMapData
 | |
|           }
 | |
|         },
 | |
|       }
 | |
|     }
 | |
|   },
 | |
|   data() {
 | |
|     return {
 | |
|       selectedAreaId: "",
 | |
|       meta: {},
 | |
|       charts: {
 | |
|         orgMemberCountMap: null,
 | |
|         buildPartyCountMap: null,
 | |
|         companyCategoryCountMap: null,
 | |
|         dangerousTypeCountMap: null,
 | |
|         socialTypeCountMap: null,
 | |
|         foreignCountMap: null,
 | |
|       }
 | |
|     }
 | |
|   },
 | |
|   methods: {
 | |
|     getAreas(node, resolve) {
 | |
|       if (node.level == 0) {
 | |
|         let {areaName: name, areaId: id} = this.user.info
 | |
|         resolve([{name, id}])
 | |
|       } else {
 | |
|         let {id} = node?.data
 | |
|         this.instance.post("/admin/area/queryAreaByParentId", null, {
 | |
|           params: {id}
 | |
|         }).then(res => {
 | |
|           if (res?.data) {
 | |
|             resolve(res.data.map(e => ({...e, leaf: e.type == 5})))
 | |
|           }
 | |
|         })
 | |
|       }
 | |
|     },
 | |
|     handleTreeFilter(v, data) {
 | |
|       return data.name.indexOf(v) > -1
 | |
|     },
 | |
|     getStaData() {
 | |
|       let {bizType} = this.top
 | |
|       return this.instance.post("/app/apptwoneworganization/countByAreaIdAndBizType", null, {
 | |
|         params: {areaId: this.selectedAreaId, bizType}
 | |
|       }).then(res => {
 | |
|         if (res?.data) {
 | |
|           this.meta = res.data
 | |
|         }
 | |
|       })
 | |
|     },
 | |
|     handleSelectArea({id}) {
 | |
|       this.selectedAreaId = id
 | |
|       this.getStaData().then(() => this.getChartData())
 | |
|     },
 | |
|     initEcharts() {
 | |
|       Object.keys(this.charts).map(id => {
 | |
|         let ref = document.getElementById(id + "Chart")
 | |
|         if (ref) this.charts[id] = echarts.init(ref)
 | |
|       })
 | |
|       this.getChartData()
 | |
|     },
 | |
|     getChartData() {
 | |
|       Object.keys(this.charts).map(e => {
 | |
|         this.charts[e]?.setOption(this.chartOps?.[e])
 | |
|       })
 | |
|     }
 | |
|   },
 | |
|   created() {
 | |
|     this.dict.load("twoNewOrgCompanyCategory", 'twoNewOrgDangerousType',
 | |
|         'twoNewOrgConcernDegree', 'orgMemberTypes', 'twoNewOrgSocialType', 'twoNewOrgIsForeign')
 | |
|     this.selectedAreaId = JSON.parse(JSON.stringify(this.user.info.areaId))
 | |
|   },
 | |
|   mounted() {
 | |
|     this.initEcharts()
 | |
|     this.getStaData().then(() => this.getChartData())
 | |
|   }
 | |
| }
 | |
| </script>
 | |
| 
 | |
| <style lang="scss" scoped>
 | |
| .staPane {
 | |
|   height: 100%;
 | |
| 
 | |
|   ::v-deep .ai-list__blank {
 | |
|     display: flex;
 | |
|     height: 100% !important;
 | |
|     gap: 16px;
 | |
| 
 | |
|     .el-scrollbar {
 | |
|       flex: 1;
 | |
|       min-width: 0;
 | |
| 
 | |
|       .el-scrollbar__wrap {
 | |
|         overflow-x: hidden;
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     .mainPane {
 | |
|       display: flex;
 | |
|       flex-direction: column;
 | |
|       gap: 16px;
 | |
| 
 | |
|       & > .el-row {
 | |
|         width: 100%;
 | |
|         gap: 16px;
 | |
|         height: auto;
 | |
| 
 | |
|         & > div {
 | |
|           flex: 1;
 | |
|           min-width: 0;
 | |
|         }
 | |
|       }
 | |
|     }
 | |
| 
 | |
|     .cardPane {
 | |
|       background: #FFFFFF;
 | |
|       box-shadow: 0 0 4px 0 rgba(0, 0, 0, 0.05);
 | |
|       border-radius: 4px;
 | |
| 
 | |
|       &.orgCountMap {
 | |
|         padding: 16px 24px;
 | |
|         box-sizing: border-box;
 | |
|         height: 120px;
 | |
|         font-size: 14px;
 | |
|         color: #888;
 | |
|         display: flex;
 | |
|         flex-direction: column;
 | |
|         gap: 8px;
 | |
| 
 | |
|         b {
 | |
|           font-size: 16px;
 | |
|           color: #333333;
 | |
| 
 | |
|           &.count {
 | |
|             font-size: 24px;
 | |
|             color: #2266FF;
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   #orgMemberCountMapChart, #buildPartyCountMapChart {
 | |
|     width: 100%;
 | |
|     height: 270px;
 | |
|   }
 | |
| 
 | |
|   #companyCategoryCountMapChart, #dangerousTypeCountMapChart, #socialTypeCountMapChart, #foreignCountMapChart {
 | |
|     width: 100%;
 | |
|     height: 220px;
 | |
|   }
 | |
|   .pad-l32 {
 | |
|     padding-left: 32px;
 | |
|   }
 | |
|   ::v-deep .el-tree .is-current>.el-tree-node__content {
 | |
|     background-color: #26f;
 | |
|     color: #fff;
 | |
|   }
 | |
| }
 | |
| </style>
 |