添加统计分析
This commit is contained in:
parent
d703bd2a4a
commit
cc77824dc9
@ -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
|
||||
}
|
||||
})
|
||||
}
|
206
src/views/Analysis/AccessStatistics/index.vue
Normal file
206
src/views/Analysis/AccessStatistics/index.vue
Normal 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>
|
173
src/views/Analysis/AccessType/index.vue
Normal file
173
src/views/Analysis/AccessType/index.vue
Normal 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>
|
@ -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">
|
||||
|
@ -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>
|
||||
@ -22,7 +49,7 @@
|
||||
</el-icon>
|
||||
导入
|
||||
</el-button>
|
||||
<upload ref="uploadRef" @refresh="getLists" />
|
||||
<upload ref="uploadRef" @refresh="getLists"/>
|
||||
</el-space>
|
||||
</el-col>
|
||||
</el-row>
|
||||
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user