添加统计分析

This commit is contained in:
lonewolfyx 2025-01-06 14:33:02 +08:00
parent d703bd2a4a
commit cc77824dc9
5 changed files with 439 additions and 6 deletions

View File

@ -85,3 +85,22 @@ export const exportVisit = () => {
url: '/visiting/visit/export'
})
}
// 获取来访类型统计
export const getVisitTypeStatistics = () => {
return request({
method: 'get',
url: '/visiting/visit/stat_type',
})
}
// 获取年度访问统计趋势
export const getVisitTrendStatistics = (data) => {
return request({
method: 'get',
url: '/visiting/visit/stat_year_month',
params: {
year: data
}
})
}

View File

@ -0,0 +1,206 @@
<template>
<div class="app-container">
<div class="analysis-wrapper">
<el-form
:model="queryForm"
:inline="true"
>
<el-form-item label="年份:">
<el-select
v-model="queryForm.year"
placeholder="请选择案件类别年份"
style="width: 8rem"
@change="listenerChangeHandle"
>
<el-option
v-for="item in yearList"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select>
</el-form-item>
</el-form>
<div class="echarts">
<VChart :option="option" autoresize @click="handleClick"/>
</div>
<div>
<el-table
ref="tableDataRef"
v-loading="loading"
:data="tableData"
show-overflow-tooltip
>
<el-table-column label="日期" prop="visitTime" width="230">
<template #default="scope">
{{ dayjs(scope.row.visitTime).format('YYYY-MM-DD hh:mm:ss') }}
</template>
</el-table-column>
<el-table-column label="上访人" prop="visitorName" width="150"/>
<el-table-column label="电话" prop="visitorMobile" width="200"/>
<el-table-column label="工作单位或住址" prop="visitorContact" width="230"/>
<el-table-column label="身份证号码" prop="visitorCode" width="230"/>
<el-table-column label="反映事项" prop="demand" width="230"/>
<el-table-column label="历史信访" prop="state" width="230"/>
<el-table-column label="处理情况" prop="reply" width="230"/>
<el-table-column label="答复形式" prop="replyType" width="230">
<template #default="scope">
<dict-tag :options="visit_reply_type" :value="scope.row.replyType"/>
</template>
</el-table-column>
<el-table-column label="备注" prop="remark" width="230"/>
<el-table-column align="center" label="操作">
<template #default="scope">
<el-button link size="small" type="warning"
@click="AddEditRegisterVisitRef.showDetail(scope.row)">
<el-icon class="me-1">
<View/>
</el-icon>
详情
</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="paging.pageNum"
v-model:limit="paging.pageSize"
@pagination="getLists"
/>
</div>
</div>
</div>
<AddEditRegisterVisit ref="AddEditRegisterVisitRef" @refresh="getLists"/>
</template>
<script setup>
import VChart from 'vue-echarts';
import * as echarts from 'echarts/core';
import {GridComponent} from 'echarts/components';
import {BarChart} from 'echarts/charts';
import {CanvasRenderer} from 'echarts/renderers';
import dayjs from 'dayjs';
import DictTag from '@/components/DictTag/index.vue';
import {getCurrentInstance, useTemplateRef} from 'vue';
import AddEditRegisterVisit from '@/views/PoliceWork/RegisterVisit/components/AddEditRegisterVisit.vue';
import {getVisitList, getVisitTrendStatistics} from '@/api/RegistVisitApi/RegistVisitApi.js';
import PageEnum from '@/enum/PageEnum.js';
echarts.use([GridComponent, BarChart, CanvasRenderer]);
const yearList = Array.from({length: 10}, (_, i) => i + 1).map(item => 2023 + item).map(item => {
return {
label: item,
value: String(item)
}
})
const {proxy} = getCurrentInstance();
const {visit_reply_type} = proxy.useDict('visit_reply_type');
const AddEditRegisterVisitRef = useTemplateRef('AddEditRegisterVisitRef')
const tableDataRef = useTemplateRef('tableDataRef')
const loading = ref(false);
const tableData = ref([])
const total = ref(0)
const paging = ref({
pageNum: 1,
pageSize: PageEnum.SIZE,
});
const queryForm = ref({
year: String(new Date().getUTCFullYear()),
})
const queryParams = ref({
params: {
beginTime: '',
endTime: ''
},
});
const option = ref({})
onMounted(async () => {
await getVisitTrend()
await getLists()
})
//
const listenerChangeHandle = async () => {
const year = queryForm.value.year;
queryParams.value.params.beginTime = `${year}-01-01`;
queryParams.value.params.endTime = `${Number(year) + 1}-01-01`;
await getVisitTrend()
await getLists()
}
//
const handleClick = async (e) => {
const year = queryForm.value.year;
const month = e.data.month.toString().padStart(2, '0');
const nextMonth = (e.data.month + 1).toString().padStart(2, '0');
queryParams.value.params.beginTime = `${year}-${month}-01`;
queryParams.value.params.endTime = `${year}-${nextMonth}-01`;
await getLists()
}
// 访
const getVisitTrend = async () => {
const res = await getVisitTrendStatistics(queryForm.value.year)
const year = res.data.map(item => `${item.month}`)
const data = res.data.map(item => {
return {
...item,
value: item.count,
name: item.month
}
})
setChartOptions(year, data)
}
//
const getLists = async () => {
const res = await getVisitList(queryParams.value, paging.value)
tableData.value = res.rows;
total.value = res.total
};
//
const setChartOptions = (year, data) => {
option.value = {
grid: {
top: '10%',
left: '5%',
right: '5%',
bottom: '10%'
},
xAxis: {
type: 'category',
data: year
},
yAxis: {
type: 'value'
},
series: [
{
data: data,
type: 'bar'
}
]
}
}
</script>
<style scoped lang="scss">
.analysis-wrapper {
display: flex;
flex-direction: column;
.echarts {
width: 100%;
height: 20rem;
}
}
</style>

View File

@ -0,0 +1,173 @@
<template>
<div class="app-container">
<div class="analysis-wrapper">
<div class="echarts">
<VChart :option="option" autoresize @click="handleClick"/>
</div>
<div>
<el-table
ref="tableDataRef"
v-loading="loading"
:data="tableData"
show-overflow-tooltip
>
<el-table-column label="日期" prop="visitTime" width="230">
<template #default="scope">
{{ dayjs(scope.row.visitTime).format('YYYY-MM-DD hh:mm:ss') }}
</template>
</el-table-column>
<el-table-column label="上访人" prop="visitorName" width="150"/>
<el-table-column label="电话" prop="visitorMobile" width="200"/>
<el-table-column label="工作单位或住址" prop="visitorContact" width="230"/>
<el-table-column label="身份证号码" prop="visitorCode" width="230"/>
<el-table-column label="反映事项" prop="demand" width="230"/>
<el-table-column label="历史信访" prop="state" width="230"/>
<el-table-column label="处理情况" prop="reply" width="230"/>
<el-table-column label="答复形式" prop="replyType" width="230">
<template #default="scope">
<dict-tag :options="visit_reply_type" :value="scope.row.replyType"/>
</template>
</el-table-column>
<el-table-column label="备注" prop="remark" width="230"/>
<el-table-column align="center" label="操作">
<template #default="scope">
<el-button link size="small" type="warning"
@click="AddEditRegisterVisitRef.showDetail(scope.row)">
<el-icon class="me-1">
<View/>
</el-icon>
详情
</el-button>
</template>
</el-table-column>
</el-table>
<pagination
v-show="total > 0"
:total="total"
v-model:page="paging.pageNum"
v-model:limit="paging.pageSize"
@pagination="getLists"
/>
</div>
</div>
</div>
<AddEditRegisterVisit ref="AddEditRegisterVisitRef" @refresh="getLists"/>
</template>
<script setup>
import VChart from 'vue-echarts';
import * as echarts from 'echarts/core';
import {LegendComponent, TitleComponent, TooltipComponent} from 'echarts/components';
import {PieChart} from 'echarts/charts';
import {LabelLayout} from 'echarts/features';
import {CanvasRenderer} from 'echarts/renderers';
import {randomNumberInRange} from '@/utils/utils.js';
import dayjs from 'dayjs';
import DictTag from '@/components/DictTag/index.vue';
import {getCurrentInstance, useTemplateRef} from 'vue';
import AddEditRegisterVisit from '@/views/PoliceWork/RegisterVisit/components/AddEditRegisterVisit.vue';
import {getVisitList, getVisitTypeStatistics} from '@/api/RegistVisitApi/RegistVisitApi.js';
import PageEnum from '@/enum/PageEnum.js';
echarts.use([
TitleComponent,
TooltipComponent,
LegendComponent,
PieChart,
CanvasRenderer,
LabelLayout
]);
const years = Array.from({length: 12}, (_, i) => `${i + 1}`)
const randomData = Array.from({length: 12}, (_, i) => randomNumberInRange(100, 500))
const {proxy} = getCurrentInstance();
const {visit_reply_type} = proxy.useDict('visit_reply_type');
const AddEditRegisterVisitRef = useTemplateRef('AddEditRegisterVisitRef')
const tableDataRef = useTemplateRef('tableDataRef')
const loading = ref(false);
const tableData = ref([])
const total = ref(0)
const paging = ref({
pageNum: 1,
pageSize: PageEnum.SIZE,
});
const queryParams = ref({
name: '',
});
const option = ref({})
onMounted(async () => {
await getTypes()
await getLists()
})
// 访
const getTypes = async () => {
const res = await getVisitTypeStatistics()
const data = res.data.map(item => {
return {
...item,
value: item.count
}
})
setChartOptions(data)
}
//
const handleClick = async (e) => {
queryParams.value.type = e.data.type
await getLists()
}
//
const getLists = async () => {
const res = await getVisitList(queryParams.value, paging.value)
tableData.value = res.rows;
total.value = res.total
};
const setChartOptions = (data) => {
option.value = {
tooltip: {
trigger: 'item'
},
legend: {
orient: 'vertical',
left: 'left'
},
series: [
{
type: 'pie',
radius: '50%',
data: data,
emphasis: {
itemStyle: {
shadowBlur: 10,
shadowOffsetX: 0,
shadowColor: 'rgba(0, 0, 0, 0.5)'
}
}
}
]
}
}
</script>
<style scoped lang="scss">
.analysis-wrapper {
display: flex;
flex-direction: column;
.echarts {
width: 100%;
height: 20rem;
}
}
</style>

View File

@ -46,6 +46,7 @@
type="datetime"
placeholder="请选择上访时间"
value-format="YYYY-MM-DD hh:mm:ss"
:disabled-date="disableDate"
/>
</el-form-item>
</el-col>
@ -327,7 +328,6 @@ const carryHandle = (row) => {
const getRegisterVisitList = async () => {
const res = await getRegisterList()
registerList.value = res.data
console.log(res.data)
}
//
@ -336,7 +336,6 @@ const getDetail = async (row) => {
queryParams.value = res.data;
queryParams.value.visitTime = dayjs(res.data.visitTime).format('YYYY-MM-DD hh:mm:ss')
idCardChangeHandle(res.data.visitorCode)
console.log(res)
}
// 访
@ -347,7 +346,6 @@ const createHandle = async (elForm) => {
await addVisit(queryParams.value)
changeShowStatus()
emit('refresh')
console.log(queryParams.value)
}
})
}
@ -360,7 +358,6 @@ const updateHandle = async (elForm) => {
await updateVisit(queryParams.value)
changeShowStatus()
emit('refresh')
console.log(queryParams.value)
}
})
}
@ -369,6 +366,11 @@ const updateHandle = async (elForm) => {
const idCardChangeHandle = (value) => {
viewHistoryDisable.value = !value;
}
//
const disableDate = (date) => {
return date.getTime() < new Date().getTime()
}
</script>
<style scoped lang="scss">

View File

@ -1,6 +1,33 @@
<template>
<div class="app-container">
<el-form
ref="queryParamsRef"
:inline="true"
:model="queryParams"
>
<el-form-item label="上访人" prop="name">
<el-input v-model="queryParams.name"/>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="getLists">
<el-icon class="me-1">
<Search/>
</el-icon>
查询
</el-button>
</el-form-item>
<el-form-item>
<el-button @click="handleRest(queryParamsRef)">
<el-icon class="me-1">
<Refresh/>
</el-icon>
重置
</el-button>
</el-form-item>
</el-form>
<el-row class="mb-3">
<el-col :span="24">
<el-space>
@ -96,7 +123,7 @@ import {getCurrentInstance, useTemplateRef} from 'vue';
import PageEnum from '@/enum/PageEnum.js';
import {ElMessageBox} from 'element-plus';
import AddEditRegisterVisit from '@/views/PoliceWork/RegisterVisit/components/AddEditRegisterVisit.vue';
import {deleteVisit, exportVisit, getVisitList} from '@/api/RegistVisitApi/RegistVisitApi.js';
import {deleteVisit, getVisitList} from '@/api/RegistVisitApi/RegistVisitApi.js';
import DictTag from '@/components/DictTag/index.vue';
import dayjs from 'dayjs';
import Upload from '@/views/PoliceWork/RegisterVisit/components/upload.vue';
@ -118,6 +145,7 @@ const queryParams = ref({
const tableDataRef = useTemplateRef('tableDataRef')
const AddEditRegisterVisitRef = useTemplateRef('AddEditRegisterVisitRef')
const uploadRef = useTemplateRef('uploadRef')
const queryParamsRef = useTemplateRef('queryParamsRef')
const total = ref(0);
const tableData = ref([
@ -158,6 +186,11 @@ const handleExport = async () => {
...queryParams.value,
}, `user_${new Date().getTime()}.xlsx`);
}
const handleRest = (formEl) => {
formEl.resetFields();
// console.log()
};
</script>
<style lang="scss" scoped></style>