473 lines
18 KiB
Vue
473 lines
18 KiB
Vue
<template>
|
||
<n-spin :show="dataLoading">
|
||
<n-space justify="center">
|
||
<h1>级网格长网格化工作考核细则(以季度为考核周期)</h1>
|
||
</n-space>
|
||
<n-space class="container" vertical>
|
||
<n-space class="search" vertical>
|
||
<n-grid :cols="7" :x-gap="10">
|
||
<n-grid-item>
|
||
<n-select placeholder="请选择街道" v-model:value="search.select.street.value"
|
||
:options="search.select.street.options" :clearable="true" />
|
||
</n-grid-item>
|
||
<n-grid-item>
|
||
<n-select placeholder="请选择社区" v-model:value="search.select.community.value"
|
||
:options="search.select.community.options" :clearable="true" />
|
||
</n-grid-item>
|
||
<n-grid-item>
|
||
<n-input v-model:value="search.input.keywords" type="text" placeholder="姓名|手机号" />
|
||
</n-grid-item>
|
||
<n-grid-item>
|
||
<n-select placeholder="请选择年份" v-model:value="search.select.year.value"
|
||
:options="search.select.year.options" :clearable="true" />
|
||
</n-grid-item>
|
||
<n-grid-item>
|
||
<n-select placeholder="请选择月份" v-model:value="search.select.month.value"
|
||
:options="search.select.month.options" :clearable="true" />
|
||
</n-grid-item>
|
||
<n-grid-item>
|
||
<n-space>
|
||
<n-button type="primary" @click="onSearchClick">搜索</n-button>
|
||
<n-button type="default" @click="onSaveClick">保存</n-button>
|
||
<n-button type="info" @click="onExportClick" :disabled="btnExportDisabled">导出</n-button>
|
||
</n-space>
|
||
</n-grid-item>
|
||
</n-grid>
|
||
</n-space>
|
||
<n-space class="body">
|
||
<n-data-table size="small" :columns="table.columns" :data="table.data" :bordered="true" :single-line="false"
|
||
:min-height="table.minHeight" :max-height="table.maxHeight" :scroll-x="table.scrollX" />
|
||
</n-space>
|
||
</n-space>
|
||
</n-spin>
|
||
<n-modal preset="dialog" style="width: 600px" :title="`【${modal.scoring.userName}】${modal.scoring.title}打分`"
|
||
:show="modal.scoring.show" :show-icon="false" :mask-closable="true" :closable="false"
|
||
:on-update-show="onScroingCloseClick">
|
||
<scoring :row-key="modal.scoring.rowKey" :row-index="modal.scoring.rowIndex" :score="modal.scoring.score"
|
||
:reason="modal.scoring.reason" :min-score="modal.scoring.minScore" :max-score="modal.scoring.maxScore"
|
||
@confirm="onScroingConfimClick" />
|
||
</n-modal>
|
||
</template>
|
||
|
||
|
||
<script>
|
||
import { h } from 'vue';
|
||
import {
|
||
NSpace,
|
||
NGrid,
|
||
NGridItem,
|
||
NSelect,
|
||
NRadio,
|
||
NInput,
|
||
NButton,
|
||
NDataTable,
|
||
NModal,
|
||
NSpin,
|
||
useMessage,
|
||
useDialog,
|
||
} from 'naive-ui';
|
||
import Scoring from '../common/Scoring.vue';
|
||
import { listYear, listMonth, getCurrentYear, getCurrentMonth, download } from '../utils/common'
|
||
|
||
export default {
|
||
name: 'Wgy3',
|
||
components: {
|
||
NSpace,
|
||
NGrid,
|
||
NGridItem,
|
||
NSelect,
|
||
NRadio,
|
||
NInput,
|
||
NButton,
|
||
NDataTable,
|
||
NModal,
|
||
NSpin,
|
||
|
||
Scoring,
|
||
},
|
||
data() {
|
||
let vueSelf = this;
|
||
return {
|
||
message: useMessage(),
|
||
dialog: useDialog(),
|
||
dataLoading: false,
|
||
btnExportDisabled: false,
|
||
search: {
|
||
userId: null,
|
||
userName: null,
|
||
select: {
|
||
street: {
|
||
value: null,
|
||
options: [
|
||
{ label: '稀土路街道', value: 'xtl' }
|
||
]
|
||
},
|
||
community: {
|
||
value: null,
|
||
options: [
|
||
{ label: '社区', value: 'sq' }
|
||
]
|
||
},
|
||
year: {
|
||
value: null,
|
||
options: [
|
||
{ label: '2023年', value: '2023' }
|
||
]
|
||
},
|
||
month: {
|
||
value: null,
|
||
options: [
|
||
{ label: '1月', value: '1' }
|
||
]
|
||
}
|
||
},
|
||
radio: {
|
||
level: {
|
||
value: 5,
|
||
}
|
||
},
|
||
input: {
|
||
keywords: ''
|
||
}
|
||
},
|
||
table: {
|
||
minHeight: 300,
|
||
maxHeight: 300,
|
||
scrollX: 900,
|
||
columns: [
|
||
{
|
||
align: 'center',
|
||
title: '序号',
|
||
key: 'A',
|
||
keyName: 'key',
|
||
fixed: 'left',
|
||
width: 60
|
||
},
|
||
{
|
||
align: 'center',
|
||
title: '姓名',
|
||
key: 'B',
|
||
keyName: 'name',
|
||
fixed: 'left',
|
||
width: 140
|
||
},
|
||
{
|
||
align: 'center',
|
||
title: '网格签到巡片情况',
|
||
children: [
|
||
{
|
||
align: 'center',
|
||
title: '基础分值',
|
||
key: 'C',
|
||
keyName: 'signBaseScore',
|
||
width: 60
|
||
},
|
||
{
|
||
align: 'center',
|
||
title: '不合格人员数',
|
||
key: 'E',
|
||
keyName: 'signUnPassCount',
|
||
width: 60
|
||
},
|
||
{
|
||
align: 'center',
|
||
title: '不合格扣分',
|
||
key: 'E',
|
||
keyName: 'signUnPassScore',
|
||
width: 60
|
||
},
|
||
]
|
||
},
|
||
{
|
||
align: 'center',
|
||
title: '网格案件调度情况',
|
||
children: [
|
||
{
|
||
align: 'center',
|
||
title: '基础分值',
|
||
key: 'F',
|
||
keyName: 'gridBaseScore',
|
||
width: 60
|
||
},
|
||
{
|
||
align: 'center',
|
||
title: '案件报送数量',
|
||
children: [
|
||
{
|
||
align: 'center',
|
||
title: '不合格人员数',
|
||
key: 'G',
|
||
keyName: 'gridUnPassCount',
|
||
width: 60
|
||
},
|
||
{
|
||
align: 'center',
|
||
title: '不合格扣分',
|
||
key: 'H',
|
||
keyName: 'gridUnPassScore',
|
||
width: 60
|
||
},
|
||
]
|
||
},
|
||
{
|
||
align: 'center',
|
||
title: '案件受理过程质量',
|
||
children: [
|
||
{
|
||
align: 'center',
|
||
title: '没完成办理流程',
|
||
key: 'I',
|
||
keyName: 'unComplete',
|
||
width: 60
|
||
},
|
||
{
|
||
align: 'center',
|
||
title: '未上报案件造成严重影响',
|
||
key: 'J',
|
||
keyName: 'unReportError',
|
||
width: 60,
|
||
render(row, index) {
|
||
return h('a', {
|
||
href: 'javascript:void(0);',
|
||
onClick() {
|
||
vueSelf.onUnReportErrorClick(row, index);
|
||
}
|
||
}, row.J);
|
||
}
|
||
},
|
||
{
|
||
align: 'center',
|
||
title: '其它情况',
|
||
key: 'K',
|
||
keyName: 'others',
|
||
width: 60,
|
||
render(row, index) {
|
||
return h('a', {
|
||
href: 'javascript:void(0);',
|
||
onClick() {
|
||
vueSelf.onOthersClick(row, index);
|
||
}
|
||
}, row.K);
|
||
}
|
||
},
|
||
]
|
||
},
|
||
{
|
||
align: 'center',
|
||
title: '网格案件调度情况得分',
|
||
key: 'L',
|
||
keyName: 'unComplete',
|
||
width: 60
|
||
},
|
||
]
|
||
},
|
||
{
|
||
align: 'center',
|
||
title: '网格工作季度考核',
|
||
key: 'M',
|
||
keyName: 'quarter',
|
||
width: 60,
|
||
render(row, index) {
|
||
return h('a', {
|
||
href: 'javascript:void(0);',
|
||
onClick() {
|
||
vueSelf.onQuarterClick(row, index);
|
||
}
|
||
}, row.M);
|
||
}
|
||
},
|
||
{
|
||
align: 'center',
|
||
title: '总得分',
|
||
key: 'N',
|
||
keyName: 'totalScore',
|
||
fixed: 'right',
|
||
width: 60,
|
||
render(row, index) {
|
||
return vueSelf.computeN(row);
|
||
}
|
||
},
|
||
{
|
||
align: 'center',
|
||
title: '应发绩效工资',
|
||
key: 'O',
|
||
keyName: 'shouldPay',
|
||
fixed: 'right',
|
||
width: 60
|
||
},
|
||
{
|
||
align: 'center',
|
||
title: '实发绩效工资',
|
||
key: 'P',
|
||
keyName: 'actualPay',
|
||
fixed: 'right',
|
||
width: 60,
|
||
render(row, index) {
|
||
return vueSelf.computeN(row) * row.O / 100;
|
||
}
|
||
}
|
||
],
|
||
data: []
|
||
},
|
||
modal: {
|
||
scoring: {
|
||
show: false,
|
||
userName: null,
|
||
title: null,
|
||
rowKey: null,
|
||
rowIndex: null,
|
||
score: 0,
|
||
reason: '',
|
||
minScore: null,
|
||
maxScore: null
|
||
}
|
||
}
|
||
}
|
||
},
|
||
methods: {
|
||
// 打分确定
|
||
onScroingConfimClick(key, index, { score, reason, userId, userName, date }) {
|
||
this.modal.scoring.show = false;
|
||
this.table.data[index][key] = score;
|
||
this.table.data[index][`reason${key}`] = reason;
|
||
},
|
||
// 打分关闭
|
||
onScroingCloseClick() {
|
||
this.modal.scoring.show = false;
|
||
},
|
||
// 未上报案件造成严重影响 -
|
||
onUnReportErrorClick(row, index) {
|
||
let unReportError = row.J;
|
||
this.modal.scoring.show = true;
|
||
this.modal.scoring.rowKey = 'J';
|
||
this.modal.scoring.rowIndex = index;
|
||
this.modal.scoring.score = unReportError;
|
||
this.modal.scoring.reason = row.reasonJ;
|
||
this.modal.scoring.maxScore = null;
|
||
this.modal.scoring.minScore = null;
|
||
this.modal.scoring.userName = row.B;
|
||
this.modal.scoring.title = '未上报案件造成严重影响';
|
||
},
|
||
// 其它情况 -
|
||
onOthersClick(row, index) {
|
||
let others = row.K;
|
||
this.modal.scoring.show = true;
|
||
this.modal.scoring.rowKey = 'K';
|
||
this.modal.scoring.rowIndex = index;
|
||
this.modal.scoring.score = others;
|
||
this.modal.scoring.reason = row.reasonK;
|
||
this.modal.scoring.maxScore = null;
|
||
this.modal.scoring.minScore = null;
|
||
this.modal.scoring.userName = row.B;
|
||
this.modal.scoring.title = '其它情况';
|
||
},
|
||
// 网格工作季度考核 +
|
||
onQuarterClick(row, index) {
|
||
let quarter = row.M;
|
||
this.modal.scoring.show = true;
|
||
this.modal.scoring.rowKey = 'M';
|
||
this.modal.scoring.rowIndex = index;
|
||
this.modal.scoring.score = quarter;
|
||
this.modal.scoring.reason = row.reasonM;
|
||
this.modal.scoring.maxScore = 30;
|
||
this.modal.scoring.minScore = 0;
|
||
this.modal.scoring.userName = row.B;
|
||
this.modal.scoring.title = '网格工作季度考核';
|
||
},
|
||
computeN(row) {
|
||
return row.C - row.E + row.L + row.M
|
||
},
|
||
resize() {
|
||
let body = document.body;
|
||
this.table.minHeight = body.clientHeight - 355;
|
||
this.table.maxHeight = body.clientHeight - 355;
|
||
// this.table.scrollX = body.clientWidth;
|
||
},
|
||
onSearchClick() {
|
||
this.listData();
|
||
},
|
||
onSaveClick() {
|
||
let vueSelf = this;
|
||
let tableDatas = [];
|
||
vueSelf.table.data.forEach(item => {
|
||
item.AE = vueSelf.computeAE(item);
|
||
item.AG = (item.AE * item.AF / 100).toFixed(2);
|
||
tableDatas.push({...item});
|
||
})
|
||
vueSelf.dialog.warning({
|
||
title: "提示",
|
||
content: "确定更新吗?",
|
||
positiveText: "确定",
|
||
negativeText: "取消",
|
||
onPositiveClick: () => {
|
||
vueSelf.dataLoading = true;
|
||
vueSelf.$axios.put(`api/kpi/khxz/update-wgy/${vueSelf.search.select.wgy.value}`, {
|
||
datas: tableDatas
|
||
}).then( resp => {
|
||
vueSelf.message.info('保存成功');
|
||
}).catch( ({data}) => {
|
||
console.error(resp);
|
||
vueSelf.message.error(data.data.msg);
|
||
}).finally(() => {
|
||
vueSelf.dataLoading = false;
|
||
});
|
||
},
|
||
onNegativeClick: () => {
|
||
}
|
||
})
|
||
},
|
||
onExportClick() {
|
||
let vueSelf = this;
|
||
vueSelf.btnExportDisabled = true;
|
||
download(vueSelf.$axios, `api/kpi/khxz/export-wgy`, vueSelf.getQuery(), () => {
|
||
vueSelf.btnExportDisabled = false;
|
||
});
|
||
},
|
||
getQuery() {
|
||
return {
|
||
khYear: this.search.select.year.value,
|
||
khMonth: this.search.select.month.value,
|
||
keywords: this.search.input.keywords
|
||
}
|
||
},
|
||
listData() {
|
||
let vueSelf = this;
|
||
vueSelf.dataLoading = true;
|
||
vueSelf.$axios.get(`api/kpi/khxz/list-wgz`, {
|
||
params: vueSelf.getQuery()
|
||
}).then(({ data }) => {
|
||
data.forEach((item, index) => {
|
||
item.A = index + 1;
|
||
})
|
||
this.table.data = data;
|
||
}).catch(({ data }) => {
|
||
vueSelf.message.error(data.msg);
|
||
}).finally(() => {
|
||
vueSelf.dataLoading = false;
|
||
});
|
||
},
|
||
init() {
|
||
this.search.select.year.options = listYear();
|
||
this.search.select.year.value = getCurrentYear();
|
||
this.search.select.month.options = listMonth();
|
||
this.search.select.month.value = getCurrentMonth();
|
||
this.listData();
|
||
}
|
||
},
|
||
mounted() {
|
||
let vueSelf = this;
|
||
vueSelf.init();
|
||
vueSelf.resize();
|
||
window.onresize = this.resize
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<style lang="stylus" scoped>
|
||
.container
|
||
padding 0 10px
|
||
:deep(.score-plus)
|
||
background-color yellow
|
||
:deep(.score-minus)
|
||
background-color red
|
||
</style> |