You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

788 lines
27 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<template>
<div style="padding:20px 0">
<el-row :gutter="20" class='elrows'>
<el-col :span="24">
<PanelGroup :totaldata="list"></PanelGroup>
</el-col>
<el-col :span="24" class="chartSize">
<div class="search">
<div class="title">月度业务统计</div>
<div class="search-wrap">
<div>
<el-date-picker @change="getFillChart" v-model="monthSelect.year" value-format="yyyy" type="year"
placeholder="选择年">
</el-date-picker>
</div>
<div>
<el-select style="width:100%" @change="changeBussiness" v-model="monthSelect.business_id"
placeholder="请选择业务">
<el-option v-for="item in list_business" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</div>
<div v-if="stateObj.is_admin">
<el-select style="width:100%" @change="changeArea" v-model="monthSelect.area_id" placeholder="请选择区域">
<el-option v-for="item in list_areas" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</div>
<div>
<el-select style="width:100%" @change="getFillChart" v-model="monthSelect.business_type_id"
placeholder="请选择业务类别">
<el-option v-for="item in list_type" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</div>
</div>
</div>
<myecharts :width="'100%'" :height="'400px'" :data="overall_month_data"></myecharts>
</el-col>
<el-col :span="24" class="chartSize" v-if="stateObj.is_dashboard_show">
<div class="search">
<!-- 年度业务统计 -->
<div class="title">各区域应收款到账情况</div>
<div class="search-wrap">
<!-- <div>
<el-date-picker @change="getYearChart" v-model="yearSelect.year" value-format="yyyy" type="year"
placeholder="选择年">
</el-date-picker>
</div>
<div v-if="stateObj.is_admin">
<el-select style="width:100%" @change="getYearChart" v-model="yearSelect.area_id" placeholder="请选择区域">
<el-option v-for="item in all_areas" :key="item.id" :label="item.name" :value="item.id">
</el-option>
</el-select>
</div> -->
</div>
</div>
<div v-if="showList">
<xy-table :list="caiwuList" :is-page="false" :height="550"
:table-item="caiwuTable">
</xy-table>
</div>
<div class="yearData" v-if="false">
<myecharts v-if="false" style="margin-top:20px" :width="'100%'" :height="'350px'" :data="budget_data"></myecharts>
<div class="yearData-item" v-for="item in yearsArr">
<el-descriptions :title="item.name" direction="vertical" :column="1" border>
<!-- <el-descriptions-item>
<template slot="label">年度预算:{{item.budgets.all_year}}</template>
<myecharts style="margin-top:20px" :width="'100%'" :height="'250px'" :data="item.budgets"></myecharts>
<el-descriptions :column="2" v-else border v-for="budget in item.budgets">
<el-descriptions-item label="年度总预算" :span="2">
{{budget.all_year}}
</el-descriptions-item>
<el-descriptions-item label="第一季度预算">
{{budget.quarter_1}}
</el-descriptions-item>
<el-descriptions-item label="第二季度预算">
{{budget.quarter_2}}
</el-descriptions-item>
<el-descriptions-item label="第三季度预算">
{{budget.quarter_3}}
</el-descriptions-item>
<el-descriptions-item label="第四季度预算">
{{budget.quarter_4}}
</el-descriptions-item>
</el-descriptions>
</el-descriptions-item> -->
<el-descriptions-item label="业务数据">
<myecharts style="margin-top:20px" :width="'100%'" :height="'300px'" :data="item.list"></myecharts>
<!-- <div v-if="item.list.length<1" style="text-align: center;">暂无数据</div>
<el-descriptions :column="1" border v-else>
<el-descriptions-item v-for="li in item.list" :label="li.name">
{{li.total}}
</el-descriptions-item>
</el-descriptions> -->
</el-descriptions-item>
</el-descriptions>
</div>
</div>
<!-- <myecharts :width="'100%'" :height="'300px'" :data="overall_year_data"></myecharts> -->
</el-col>
</el-row>
</div>
</template>
<script>
import myecharts from '@/components/myecharts';
import PanelGroup from './components/PanelGroup';
import {
home,
yearChart,
fillChart
} from "@/api/home"
import {
index,
show
} from "@/api/system/baseForm.js"
import state from '@/store/modules/user.js'
export default {
components: {
myecharts,
PanelGroup
},
data() {
return {
list: {
// recordsTotal: 0,
// organizesTotal: 0,
// areasTotal: 0,
status1Total: 0,
dateTotal: 0,
person:{
total:0,
manage:0,
serve:0
}
},
stateObj: {},
nowDate: '',
// 月度统计
list_areas: [],
list_business: [],
list_type: [],
monthSelect: {
year: '',
business_id: '',
business_type_id: '',
area_id: ''
},
overall_month_data: {},
budget_data: {},
// 年度统计
yearSelect: {
year: '',
area_id: ''
},
yearsArr: [],
yearList: {},
all_areas: [],
overall_year_data: {},
monthArr: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
// 财务数据
caiwuTable:[{
prop:'name',
label:'区域',
width:180,
align:'center',
fixed:'left'
}],
showList:false,
caiwuList:[],
id_business_types_business_id_relation:[], //财务填报的业务类型
id_business_datas_business_id_relation:[], //财务填报的业务数据
}
},
watch: {
},
created() {
this.monthSelect.year = this.$moment(new Date).format("YYYY")
this.yearSelect.year = this.$moment(new Date).format("YYYY")
this.stateObj = state.state
this.init()
this.getRecords()
this.getPerson()
this.getMonthList()
this.getYearList()
this.getCaiwuTable()
},
mounted() {
},
methods: {
// 获取 预警
async getRecords() {
await this.getList()
await this.getStatusList()
},
async getList() {
this.nowDate = this.$moment().add(3, 'months').format('YYYY-MM-DD')
this.startDate = this.$moment('1900-01-01').format("YYYY-MM-DD")
const res = await index({
page_size: 9999,
page: 1,
table_name: 'records',
is_auth: 1,
filter: [{
key: 'status',
op: 'eq',
value: 0
}, {
key: 'end_date',
op: 'range',
value: [this.startDate, this.nowDate]
}]
})
this.list.dateTotal = res.total
},
// 获取当月员工人数 固定的数据获取
// http://sstt-dangan.ali251.langye.net/api/fill-datas-chart?business_id=20&year=2025&business_type_id=88&area_id=13
async getPerson(){
const res = await fillChart({
business_id: 20,
year: this.monthSelect.year,
business_type_id: 88,
area_id: 13
})
const monthNum = (new Date()).getMonth()
const currentMonth = monthNum===0?'01':String(new Date().getMonth()).padStart(2, '0');
const currentMonthData = res.list[currentMonth] || [];
currentMonthData.forEach(item => {
switch (item.name) {
case "总人数":
this.list.person.total = item.total; // 赋值总人数
break;
case "管理人员人数":
this.list.person.manage = item.total; // 赋值管理人员人数
break;
case "服务人员人数":
this.list.person.serve = item.total; // 赋值服务人员人数
break;
}
});
},
// 获取财务部 填报的数据内容
// http://sstt-dangan.ali251.langye.net/api/admin/base-form/show?id=15&table_name=businesses&json_data_fields[]=area_ids
async getCaiwuTable(){
const res = await show({
id: 15,
table_name: 'businesses',
})
res.id_business_types_business_id_relation.map(item=>{
this.caiwuList.push({
business_type_id:item.id,
name:item.name
})
})
res.id_business_datas_business_id_relation.map(item=>{
this.caiwuTable.push({
prop:item.name,
business_data_id:item.id,
label:item.name
})
this.caiwuList.map(item1=>{
item1.business_data_id = item.id
item1[item.name] = 0
})
})
this.getCaiwuList()
},
async getCaiwuList(){
const res = await index({
page_size: 9999,
page: 1,
table_name: 'fills',
filter: [{
"key": "business_id",
"op": "eq",
"value": 15
},{
"key": "year",
"op": "eq",
"value": this.monthSelect.year
}],
})
// return
// 1. 先将 id_fill_datas_fill_id_relation 转换为映射表,提高查询效率
if(res.data.length>0){
const data = res.data[0]
console.log("data",data)
// 1. 先按 business_type_id 对 id_fill_datas_fill_id_relation 分组,提高匹配效率
const relationGroup = {};
data.id_fill_datas_fill_id_relation.forEach(relationItem => {
const typeId = relationItem.business_type_id;
// 按 business_type_id 分组,每组存储该类型下的所有 relation 项
if (!relationGroup[typeId]) {
relationGroup[typeId] = [];
}
relationGroup[typeId].push(relationItem);
});
console.log("relationGroup",relationGroup)
// 2. 遍历 caiwuList匹配并赋值
this.caiwuList.forEach(caiwuItem => {
const targetTypeId = caiwuItem.business_type_id;
// 找到同 business_type_id 的所有 relation 项
const matchedRelations = relationGroup[targetTypeId] || [];
// 遍历同类型的 relation 项,匹配 business_data.name 与 caiwuItem 的属性
matchedRelations.forEach(relationItem => {
// 获取 relation 项中 business_data 的 name注意处理可能的空值
const targetProp = relationItem.business_data?.name;
if (!targetProp) return; // 若 name 不存在,跳过
// 若 caiwuItem 存在该属性,则赋值
if (caiwuItem.hasOwnProperty(targetProp)) {
caiwuItem[targetProp] = relationItem.value;
}
});
});
console.log("this.caiwuList",this.caiwuList)
console.log("this.caiwuTable",this.caiwuTable)
this.$forceUpdate()
}
this.showList = true
},
async getStatusList() {
this.nowDate = this.$moment().add(1, 'months').format('YYYY-MM-DD')
this.startDate = this.$moment('1900-01-01').format("YYYY-MM-DD")
const res = await index({
page_size: 9999,
page: 1,
table_name: 'records',
is_auth: 1,
filter: [{
key: 'status',
op: 'eq',
value: 1
}]
})
this.list.status1Total = res.total
},
// 获取 月度图表 相关
// 获取 业务
changeBussiness(e) {
this.list_business.map(item => {
if (e === item.id) {
// 如果是管理员 变更 区域
if (this.stateObj.is_admin) {
this.list_areas = item.area_ids_details
this.monthSelect.area_id = this.list_areas[0].id
}
this.list_type = item.id_business_types_business_id_relation.filter(item => {
return item.area_id == this.monthSelect.area_id
})
this.monthSelect.business_type_id = this.list_type[0].id
this.getFillChart()
}
})
},
changeArea(e) {
this.list_business.map(item => {
if (this.monthSelect.business_id === item.id) {
this.list_type = item.id_business_types_business_id_relation.filter(item => {
return item.area_id == e
})
this.monthSelect.business_type_id = this.list_type[0].id
this.getFillChart()
}
})
},
async getMonthList() {
await this.getBusinessList()
await this.getFillChart()
},
async getBusinessList() {
const res = await index({
page_size: 9999,
page: 1,
table_name: 'businesses',
json_data_fields: ['area_ids'],
})
// 区域只能查看自己的 业务
// 初始化赋值 获取月度统计
// 区域只能看到自己的 不用选择区域了,业务数据并选择
if (!this.stateObj.is_admin) {
this.list_business = res.data.filter(item => {
return item.area_ids.includes(this.stateObj.area_id)
})
this.monthSelect.business_id = this.list_business[0].id
this.monthSelect.area_id = this.stateObj.area_id
this.list_type = this.list_business[0].id_business_types_business_id_relation.filter(item => {
return item.area_id == this.monthSelect.area_id
})
this.monthSelect.business_type_id = this.list_type[0].id
} else {
this.list_business = res.data.reverse()
this.monthSelect.business_id = res.data[0].id
this.list_areas = res.data[0].area_ids_details
this.monthSelect.area_id = this.list_areas[0].id
this.list_type = res.data[0].id_business_types_business_id_relation.filter(item => {
return item.area_id == this.monthSelect.area_id
})
this.monthSelect.business_type_id = this.list_type[0].id
}
},
async getFillChart() {
// const res1 = await yearChart()
const res = await fillChart({
business_id: this.monthSelect.business_id,
year: this.monthSelect.year,
business_type_id: this.monthSelect.business_type_id,
area_id: this.monthSelect.area_id
})
let xMonth = this.monthArr
let dMonth = this.getMonthArr(res.list)
this.overall_month_data.x = xMonth
this.overall_month_data.list = dMonth
// console.log("this.overall_month_data", this.overall_month_data)
},
// 月度数据根据类别 归类
getMonthArr(list) {
// 定义正确的月份顺序
const monthsOrder = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'];
// 初始化归类对象
const categorizedData = {};
// 按照定义的顺序遍历 list 对象
monthsOrder.forEach(month => {
if (list[month]) {
list[month].forEach(item => {
const {
name,
business_data_id,
total
} = item;
if (!categorizedData[business_data_id]) {
categorizedData[business_data_id] = {
name,
business_data_id,
type: 'bar',
barGap: '0%',
// barWidth: '30%', // 设置柱子粗细
data: Array(12).fill(0), // 初始化长度为12且值全为0的数组
label: {
show: true,
position: 'top',
color: "#333",
formatter: function(para) {
if (para.value > 0) {
if (para.seriesName.includes('费用') || para.seriesName.includes('补贴')) {
return para.value + '万元'
}else if (para.seriesName=='服务人数') {
return para.value + '百人'
} else {
return para.value
}
} else {
return ''
}
}
},
};
}
// 将 total 添加到对应位置
let last_total = total
if (name.includes('费用') || name.includes('补贴')) {
last_total = parseFloat(total / 10000).toFixed(2)
}
if (name=='服务人数') {
last_total = total / 100
}
categorizedData[business_data_id].data[parseInt(month) - 1] = last_total;
});
}
});
// 构建最终结果
const result = Object.values(categorizedData);
return result
},
// 获取年度统计
async getYearList() {
await this.getAreas()
await this.getYearChart()
},
async getAreas() {
const res = await index({
page_size: 999,
page: 1,
table_name: 'areas',
sort_type: 'ASC',
sort_name: 'sort',
})
this.all_areas = res.data
// 只能查看自己区域的业务
if (!this.stateObj.is_admin) {
this.yearSelect.area_id = this.stateObj.area_id
} else {
this.yearSelect.area_id = this.all_areas[0].id
}
},
async getYearChart() {
const res = await yearChart({
year: this.yearSelect.year,
area_id: this.yearSelect.area_id
})
this.yearsArr = this.getYearObj(res.list, res.budgets)
// console.log("getYearObj", this.getYearObj(res.list, res.budgets))
},
// 合并预算 和业务数据
getYearObj(list, budgets) {
let flatBudgets = [].concat(...budgets);
let yearObjs = [];
let budget_data_x = []
this.budget_data.list.map(item=>{
item.data = []
})
for (let name in list) {
budget_data_x.push(name)
if (list.hasOwnProperty(name)) {
let yearObj = {
name: name,
budgets: {
},
list: {
trigger: 'item',
xShow: false,
yShow: false,
all_year: 0,
legend: {
left: 'left',
top: 0
},
list: [{
name: name,
type: 'pie',
radius: '60%',
tooltip: {
formatter: function(item) {
// console.log(item)
let result = `${item.seriesName}<br/>`;
const name = item.name; // 系列名称
const value = item.value; // 数据值
const marker = item.marker; // 标志图形
let unit = item.name.includes('费用') || item.name.includes('补贴') ? '万元' : ''
if(item.name=='服务人数'){
unit='百人'
}
result += `${marker}${name}: ${value}${unit}<br/>`;
return result;
},
},
data: [],
label: {
show: true,
position: 'outer',
},
}]
},
};
let matchedBudgets = flatBudgets.filter(budget =>
list[name].some(item => item.business_id === budget.business_id)
);
// console.log(name, list[name], matchedBudgets)
// 年度预算
this.budget_data.list.map(item=>{
if(item.id==='quarter_1'){
item.data.push(matchedBudgets.length > 0 ? matchedBudgets[0].quarter_1/10000 : 0)
}else if(item.id==='quarter_2'){
item.data.push(matchedBudgets.length > 0 ? matchedBudgets[0].quarter_2/10000 : 0)
}else if(item.id==='quarter_3'){
item.data.push(matchedBudgets.length > 0 ? matchedBudgets[0].quarter_3/10000 : 0)
}else if(item.id==='quarter_4'){
item.data.push(matchedBudgets.length > 0 ? matchedBudgets[0].quarter_4/10000 : 0)
}
})
// 业务数据
list[name].map(item => {
let last_total = item.total
if (item.name.includes('费用') || item.name.includes('补贴')) {
last_total = item.total / 10000
}
yearObj.list.list[0].data.push({
name: item.name,
value: last_total
})
})
yearObjs.push(yearObj);
// console.log("budget_data", this.budget_data)
}
}
this.budget_data.x = budget_data_x
return yearObjs
},
// 初始化图表
init() {
this.overall_month_data = {
xShow: true,
yShow: true,
xAxis: {
axisLabel: {
show: true,
// rotate: 35, //35度角倾斜显示
},
},
formatter: function(params) {
let result = `${params[0].name}<br/>`;
params.forEach(function(item) {
// item 是每一个系列的数据
const seriesName = item.seriesName; // 系列名称
const value = item.value; // 数据值
const marker = item.marker; // 标志图形
let unit = item.seriesName.includes('费用') || item.seriesName.includes('补贴') ? '万元' : ''
if(item.seriesName=='服务人数'){
unit = '百人'
}
result += `${marker}${seriesName}: ${value}${unit}<br/>`;
});
return result;
},
x: [],
list: []
}
this.overall_year_data = {
trigger: 'item',
xShow: false,
yShow: false,
list: [{
name: '档案数',
type: 'pie',
radius: '80%',
// center:['20%','20%'],
data: [],
label: {
show: true,
position: 'center'
},
}]
},
this.budget_data = {
xShow: true,
yShow: true,
xAxis: {
axisLabel: {
show: true,
// rotate: 35, //35度角倾斜显示
},
},
formatter: function(params) {
let result = `${params[0].name}<br/>`;
params.forEach(function(item) {
// item 是每一个系列的数据
const seriesName = item.seriesName; // 系列名称
const value = item.value; // 数据值
const marker = item.marker; // 标志图形
const unit = '万元'
result += `${marker}${seriesName}: ${value}${unit}<br/>`;
});
return result;
},
x: [],
list: []
}
let four = [{
name: '第一季度',
id: 'quarter_1'
}, {
name: '第二季度',
id: 'quarter_2'
}, {
name: '第三季度',
id: 'quarter_3'
}, {
name: '第四季度',
id: 'quarter_4'
}]
four.map(item => {
this.budget_data.list.push({
name:item.name,
id:item.id,
type: 'bar',
barGap: '0%',
// barWidth: '30%', // 设置柱子粗细
data: [], // 初始化长度为12且值全为0的数组
label: {
show: true,
position: 'top',
color: "#333",
formatter: function(para) {
if (para.value > 0) {
if (para.seriesName.includes('费用') || para.seriesName.includes('补贴')) {
return para.value + '万元'
} else {
return para.value
}
} else {
return ''
}
}
},
})
})
}
},
}
</script>
<style lang="scss" scoped>
.elrows {
// margin: 0 !important;
.el-col {
padding: 10px !important
}
.chartSize {
width: calc(100% - 20px) !important;
margin: 10px !important;
background: #fff;
.search {
display: flex;
align-items: center;
justify-content: space-between;
margin: 20px;
.title {
padding: 10px;
color: #b3241d;
font-size: 18px
}
&-wrap {
display: flex;
align-items: center;
&>div {
margin-left: 10px;
}
}
}
}
.yearData {
display: flex;
justify-content: flex-start;
align-items: flex-start;
flex-wrap: wrap;
min-height: 350px;
margin: 20px;
&-item {
// width: 30%;
flex-basis: 32%;
margin: 0.5%;
margin-bottom: 20px;
}
}
}
</style>