提交 f98a35c0 authored 作者: 何忠建's avatar 何忠建

物业缴费+报表统计

上级 1c8592de
...@@ -5,6 +5,12 @@ import {UI_CACHE_DB_DICT_DATA } from "@/store/mutation-types" ...@@ -5,6 +5,12 @@ import {UI_CACHE_DB_DICT_DATA } from "@/store/mutation-types"
const homeDataStatistics = (params)=>getAction("/community/homepage/dataStatistics",params); const homeDataStatistics = (params)=>getAction("/community/homepage/dataStatistics",params);
const companyNoticeList = (params)=>getAction("/property-company/notice/companyNotice/list",params); const companyNoticeList = (params)=>getAction("/property-company/notice/companyNotice/list",params);
// 报表统计
const propertyFeeStatistics = (params)=>getAction("/property-community/payment/communityPayment/propertyFeeStatistics",params);
const paymentStatistics = (params)=>getAction("/property-community/payment/communityPayment/paymentStatistics",params);
const repairStatistics = (params)=>getAction("/property-community/property/communityRepair/repairStatistics",params);
const complaintStatistics = (params)=>getAction("/property-community/property/communityComplaint/complaintStatistics",params);
//角色管理 //角色管理
const addRole = (params)=>postAction("/sys/role/add",params); const addRole = (params)=>postAction("/sys/role/add",params);
const editRole = (params)=>putAction("/sys/role/edit",params); const editRole = (params)=>putAction("/sys/role/edit",params);
...@@ -74,6 +80,8 @@ const auditCommunityOwnerApi = (params)=>postAction("/property-community/info/co ...@@ -74,6 +80,8 @@ const auditCommunityOwnerApi = (params)=>postAction("/property-community/info/co
const downloadOwnerTemplate = (params)=>postAction("/property-community/info/communityOwner/downloadOwnerTemplate",params); const downloadOwnerTemplate = (params)=>postAction("/property-community/info/communityOwner/downloadOwnerTemplate",params);
// 生活缴费-费用规则 // 生活缴费-费用规则
const companyPropertyChargerulesApi = (params)=>getAction("/property-company/system/companyChargerule/companyPropertyChargerules",params);
const getTotalMoneyApi = (params)=>getAction("/property-community/payment/communityPayment/getTotalMoney",params);
const geCommunityRuleListApi = (params)=>getAction("/property-company/system/companyChargerule/communityRuleList",params); const geCommunityRuleListApi = (params)=>getAction("/property-company/system/companyChargerule/communityRuleList",params);
const queryByRoomIdApi = (params)=>getAction("/property-community/info/communityOwner/queryByRoomId",params); const queryByRoomIdApi = (params)=>getAction("/property-community/info/communityOwner/queryByRoomId",params);
const queryLastDegreesByIdApi = (params)=>getAction("/property-community/payment/communityPayment/queryLastDegreesById",params); const queryLastDegreesByIdApi = (params)=>getAction("/property-community/payment/communityPayment/queryLastDegreesById",params);
...@@ -136,6 +144,10 @@ export const transitRESTful = { ...@@ -136,6 +144,10 @@ export const transitRESTful = {
export { export {
homeDataStatistics, homeDataStatistics,
companyNoticeList, companyNoticeList,
propertyFeeStatistics,
paymentStatistics,
repairStatistics,
complaintStatistics,
addRole, addRole,
editRole, editRole,
checkRoleCode, checkRoleCode,
...@@ -201,6 +213,8 @@ export { ...@@ -201,6 +213,8 @@ export {
geCommunityOwnertInfoApi, geCommunityOwnertInfoApi,
auditCommunityOwnerApi, auditCommunityOwnerApi,
geCommunityRuleListApi, geCommunityRuleListApi,
companyPropertyChargerulesApi,
getTotalMoneyApi,
queryByRoomIdApi, queryByRoomIdApi,
queryLastDegreesByIdApi, queryLastDegreesByIdApi,
callPayMentApi, callPayMentApi,
......
...@@ -35,6 +35,10 @@ ...@@ -35,6 +35,10 @@
<a-button type="primary" icon="import">导入</a-button> <a-button type="primary" icon="import">导入</a-button>
</a-upload> </a-upload>
<a-button type="primary" icon="download" @click="handleExportXls('生活缴费')">导出</a-button> <a-button type="primary" icon="download" @click="handleExportXls('生活缴费')">导出</a-button>
<div style="float: right; color: #f00;">
<span style="margin-right: 20px;">已缴费金额 (元):{{ statistical.paidMoney || 0 }}</span>
<span>待缴费金额 (元):{{ statistical.unPaidMoney || 0 }}</span>
</div>
<a-dropdown v-if="selectedRowKeys.length > 0"> <a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay"> <a-menu slot="overlay">
<a-menu-item key="1" @click="onBatchCallpay"><a-icon type="message" />催缴</a-menu-item> <a-menu-item key="1" @click="onBatchCallpay"><a-icon type="message" />催缴</a-menu-item>
...@@ -88,7 +92,7 @@ ...@@ -88,7 +92,7 @@
</template> </template>
<script> <script>
import { getBuildingListApi, getUnitListApi, getRoomListApi, callPayMentApi } from '@/api/api' import { getBuildingListApi, getUnitListApi, getRoomListApi, callPayMentApi,getTotalMoneyApi } from '@/api/api'
import { downFile } from '@/api/manage' import { downFile } from '@/api/manage'
import { JeecgListMixin } from '@/mixins/JeecgListMixin' import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import NoticeModal from './modules/NoticeModal' import NoticeModal from './modules/NoticeModal'
...@@ -215,11 +219,12 @@ export default { ...@@ -215,11 +219,12 @@ export default {
downloadExcelUrl: '/property-community/payment/communityPayment/downloadPaymentTemplate', downloadExcelUrl: '/property-community/payment/communityPayment/downloadPaymentTemplate',
}, },
treeData: [], treeData: [],
statistical: {},
} }
}, },
created() { created() {
this.getBuildingList() this.getBuildingList()
// this.initDictData() this.getTotalMoney()
}, },
computed: { computed: {
importExcelUrl: function () { importExcelUrl: function () {
...@@ -243,6 +248,10 @@ export default { ...@@ -243,6 +248,10 @@ export default {
} }
}) })
}, },
async getTotalMoney() {
let { result } = await getTotalMoneyApi({ type: 'payment' })
this.statistical = result
},
onClickTree(value, option) { onClickTree(value, option) {
console.log(value, option) console.log(value, option)
let level = option.node.pos.split('-').length let level = option.node.pos.split('-').length
......
<template>
<a-spin :spinning="confirmLoading">
<j-form-container :disabled="formDisabled">
<a-form-model ref="form" :model="model" :rules="validatorRules" slot="detail">
<a-row>
<a-col :span="24">
<a-form-model-item label="收费标准" :labelCol="{ xs: { span: 24 }, sm: { span: 2 } }" :wrapperCol="wrapperCol" prop="chargingStandardId">
<a-select style="width:50%" v-model="model.chargingStandardId" placeholder="请选择收费标准" @change="onStandardChange">
<a-select-option v-for="item in ruleList" :key="item.id" :value="item.id">{{item.chargeTypeCodeName}}</a-select-option>
</a-select>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="收费类型" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="chargeTypeName">
<a-input v-model="model.chargeTypeName" placeholder="请输入" disabled></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="收费项目" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="chargeItem">
<a-input v-model="model.chargeItem" placeholder="请输入" disabled></a-input>
</a-form-model-item>
</a-col>
</a-row>
<a-row>
<a-col :span="12">
<a-form-model-item label="关联房屋" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="roomId">
<a-tree-select
v-model="model.roomId"
style="width: 100%"
:defaultExpandAll="true"
:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
:tree-data="treeData"
placeholder="请选择关联房屋"
:load-data="onLoadData"
@select="onSelectRoom"
/>
</a-form-model-item>
</a-col>
<a-col :span="12" style="padding-left:16px">
<p style="line-height:30px">{{this.model.buildingName}}{{this.model.unitName}}{{this.model.roomName}}</p>
</a-col>
</a-row>
<a-row>
<a-col :span="12">
<a-form-model-item label="业主" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="ownerName">
<a-input v-model="model.ownerName" placeholder="请输入" disabled></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="住户" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="residentName">
<a-input v-model="model.residentName" placeholder="请输入" disabled></a-input>
</a-form-model-item>
</a-col>
<template v-if="model.designFormulas === 2">
<a-col :span="12">
<a-form-model-item label="房屋面积" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="floorSpace">
<a-input v-model="model.floorSpace" placeholder="请输入房屋面积" style="width:100%" disabled></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="单价" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="unitPrice">
<a-input v-model="model.unitPrice" placeholder="请输入单价" style="width:100%" disabled></a-input>
</a-form-model-item>
</a-col>
</template>
<template v-if="model.designFormulas === 3">
<a-col :span="12">
<a-form-model-item label="上期度数" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="lastDegrees">
<a-input v-model="model.lastDegrees" placeholder="请输入上期度数" style="width:100%" disabled></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="本期度数" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="currentDegrees">
<a-input-number v-model="model.currentDegrees" placeholder="请输入本期度数" style="width:100%" @change="onDegreesChange"></a-input-number>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="用量" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="useAmount">
<a-input v-model="model.useAmount" placeholder="请输入用量" style="width:100%" disabled></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="单价" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="unitPrice">
<a-input v-model="model.unitPrice" placeholder="请输入单价" style="width:100%" disabled></a-input>
</a-form-model-item>
</a-col>
</template>
<a-col :span="12">
<a-form-model-item label="金额" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="totalAmount">
<a-input v-model="model.totalAmount" placeholder="请输入金额" style="width:100%" disabled></a-input>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="时间" :labelCol="{ xs: { span: 24 }, sm: { span: 2 } }" :wrapperCol="wrapperCol" prop="meterReadingTime">
<j-date placeholder="请选择时间" v-model="model.meterReadingTime" :showTime="true" dateFormat="YYYY-MM-DD HH:mm:ss" style="width: 50%;" />
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
</j-form-container>
</a-spin>
</template>
<script>
import { httpAction, getAction } from '@/api/manage'
import { formatDate } from '@/utils/util'
import { getBuildingListApi, getUnitListApi, getRoomListApi, companyPropertyChargerulesApi, queryByRoomIdApi, queryLastDegreesByIdApi} from '@/api/api'
export default {
name: 'PropertyChargruleForm',
components: {
},
props: {
//表单禁用
disabled: {
type: Boolean,
default: false,
required: false
}
},
data () {
return {
ruleList: [],
treeData: [],
amount: 0,
model:{
chargeCycle: '',
chargeItem: '',
chargingStandardId: '',
chargeTypeCode: '',
chargeTypeId: '',
chargeTypeName: '',
unitPrice: '',
designFormulas: 3,
ownerId: '',
buildingId: '',
buildingName: '',
unitId: '',
unitName: '',
roomId: '',
roomName: '',
floorSpace: '',
ownerName: '',
ownerPhone: '',
residentName: '',
residentPhone: '',
relationShip: '',
lastDegrees: '',
currentDegrees: '',
useAmount: '',
totalAmount: '',
meterReadingTime: ''
},
labelCol: {
xs: { span: 24 },
sm: { span: 4 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 20 },
},
confirmLoading: false,
validatorRules: {
chargingStandardId: [{ required: true, message: '请选择收费标准', trigger: 'change' }],
roomId: [{ required: true, message: '请选择关联房屋', trigger: 'change' }],
currentDegrees: [{ required: true, message: '请输入本期度数', trigger: 'blur' }],
// useAmount: [{ required: true, message: '请输入', trigger: 'blur' }],
meterReadingTime: [{ required: true, message: '请选择抄表时间', trigger: 'change' }]
},
url: {
add: "/property-community/payment/communityPayment/add",
edit: "/property-community/payment/communityPayment/edit",
queryById: "/property-community/payment/communityPayment/queryById"
}
}
},
computed: {
formDisabled(){
return this.disabled
},
},
created () {
//备份model原始值
this.modelDefault = JSON.parse(JSON.stringify(this.model));
this.getRuleList()
},
methods: {
async getRuleList() {
let {result} = await companyPropertyChargerulesApi()
this.ruleList = result.map(item=> {
return {
...item,
chargeTypeCodeName: `${item.chargeTypeCode}-${item.chargeTypeName}`
}
})
},
async getBuildingList() {
let {result} = await getBuildingListApi()
this.treeData = result.map(item=> {
return {
value: item.id,
label: item.buildingName,
pId: 0,
disabled: true
}
})
},
onStandardChange(id) {
let row = this.ruleList.find(item=>item.id === id)
this.model.chargeCycle = row.chargeCycle
this.model.chargeItem = row.chargeItem
this.model.chargeTypeCode = row.chargeTypeCode
this.model.chargeTypeId = row.chargeTypeId
this.model.chargeTypeName = row.chargeTypeName
this.model.designFormulas = row.designFormulas
this.amount = row.amount
this.model.unitPrice = this.model.designFormulas === 1 ? '' : row.amount
if(this.model.designFormulas === 1) {
this.model.totalAmount = this.amount.toFixed(2)
}
if(this.model.designFormulas === 2 && this.model.roomId) { // 获取上期度数
this.model.totalAmount = (this.model.unitPrice * this.model.floorSpace).toFixed(2)
}
if(this.model.designFormulas === 3 && this.model.roomId) { // 获取上期度数
this.onqueryLastDegreesById()
}
},
add () {
this.getBuildingList()
this.modelDefault.meterReadingTime = formatDate(new Date().getTime(), 'yyyy-MM-dd hh:mm:ss')
this.edit(this.modelDefault);
},
edit (record) {
console.log(record)
this.model = Object.assign({}, record);
this.visible = true;
},
onSelectRoom(value, node) {
let data = node.dataRef
this.model.roomId = data.value
this.model.roomName = data.label
this.model.floorSpace = data.floorSpace
this.model.unitId = data.parent.value
this.model.unitName = data.parent.label
this.model.buildingId = data.parent.parent.value
this.model.buildingName = data.parent.parent.label
this.onqueryByRoomId()
if(this.model.designFormulas === 2) {
this.model.totalAmount = (this.model.unitPrice * this.model.floorSpace).toFixed(2)
}
},
async onqueryLastDegreesById() {
let res = await queryLastDegreesByIdApi({ownerId: this.model.ownerId,chargeTypeId: this.model.chargeTypeId})
this.model.lastDegrees = res.result
if(this.model.currentDegrees) {
this.onDegreesChange(this.model.currentDegrees)
}
},
async onqueryByRoomId() {
let res = await queryByRoomIdApi({roomId: this.model.roomId})
if(res.code === 200) {
this.model.ownerName = res.result.ownerName
this.model.ownerPhone = res.result.ownerPhone
this.model.residentName = res.result.residentName
this.model.residentPhone = res.result.residentPhone
this.model.relationShip = res.result.relationShip
this.model.ownerId = res.result.id
if(this.model.designFormulas === 3 && this.model.chargeTypeId) {
this.onqueryLastDegreesById()
}
} else {
this.$message.warning(res.message);
this.model.roomId = ''
this.model.roomName = ''
this.model.floorSpace = ''
this.model.unitId = ''
this.model.unitName = ''
this.model.buildingId = ''
this.model.buildingName = ''
}
},
onLoadData(treeNode) {
return new Promise(async resolve => {
if (treeNode.dataRef.children) {
resolve();
return;
}
if(treeNode.pos.split('-').length === 2) { // 单元
let {result} = await getUnitListApi({id: treeNode.eventKey})
treeNode.dataRef.children = result.map(item=> {
return {
value: item.id,
label: item.unitName,
pId: treeNode.dataRef.id,
parent: {...treeNode.dataRef},
disabled: true
}
})
this.treeData = [...this.treeData];
resolve();
} else { // 房屋
let {result} = await getRoomListApi({id: treeNode.eventKey})
treeNode.dataRef.children = result.map(item=> {
return {
value: item.id,
label: item.roomNum,
pId: treeNode.dataRef.id,
floorSpace: item.floorSpace,
parent: {...treeNode.dataRef},
isLeaf: true
}
})
this.treeData = [...this.treeData];
resolve();
}
});
},
onDegreesChange(value) {
if(this.model.lastDegrees || this.model.lastDegrees == 0) {
this.model.useAmount = (value - Number(this.model.lastDegrees)).toFixed(2)
this.model.totalAmount = (Number(this.model.useAmount) * this.amount).toFixed(2)
}
},
submitForm () {
const that = this;
// 触发表单验证
this.$refs.form.validate(valid => {
if (valid) {
that.confirmLoading = true;
let httpurl = '';
let method = '';
if(!this.model.id){
httpurl+=this.url.add;
method = 'post';
}else{
httpurl+=this.url.edit;
method = 'put';
}
httpAction(httpurl,this.model,method).then((res)=>{
if(res.success){
that.$message.success(res.message);
that.$emit('ok');
}else{
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
})
}
})
},
}
}
</script>
\ No newline at end of file
<template>
<j-modal
:title="title"
:width="width"
:visible="visible"
switchFullscreen
@ok="handleOk"
:okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
@cancel="handleCancel"
cancelText="关闭">
<property-settled-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit"></property-settled-form>
</j-modal>
</template>
<script>
import PropertySettledForm from './NoticeForm'
export default {
name: 'PropertySettledModal',
components: {
PropertySettledForm
},
data () {
return {
title:'',
width: '70%',
visible: false,
disableSubmit: false
}
},
methods: {
add () {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.add();
})
},
edit (record) {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.edit(record);
})
},
close () {
this.$emit('close');
this.visible = false;
},
handleOk () {
this.$refs.realForm.submitForm();
},
submitCallback(){
this.$emit('ok');
this.visible = false;
},
handleCancel () {
this.close()
}
}
}
</script>
\ No newline at end of file
<template>
<div class="page-content">
<a-spin :spinning="confirmLoading">
<h4 style="padding:20px 0 0 30px;line-height:30px;font-weight:600;">缴费详情</h4>
<j-form-container :disabled="true">
<a-form-model ref="form" :model="model" slot="detail">
<a-row>
<a-col :span="12">
<a-form-model-item label="收费类型" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="chargeTypeName">
<a-input v-model="model.chargeTypeName" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="收费项目" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="chargeItem">
<a-input v-model="model.chargeItem" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="房屋" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="roomAllName">
<a-input v-model="model.roomAllName" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="业主" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="ownerName">
<a-input v-model="model.ownerName" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="与业主关系" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="relationShip">
<!-- <a-input v-model="model.relationShip" placeholder="请输入"></a-input> -->
<a-select v-model="model.relationShip" placeholder="请选择与业主关系">
<a-select-option v-for="item in relationShipList" :key="item.value"
:value="item.value">{{item.label}}</a-select-option>
</a-select>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="住户" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="residentName">
<a-input v-model="model.residentName" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="收费标准" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="chargeTypeCodeName">
<a-input v-model="model.chargeTypeCodeName" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="收费周期" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="chargeCycle">
<a-select style="width: 100%" v-model="model.chargeCycle" placeholder="请选择付费周期">
<a-select-option v-for="item in dictOptions" :key="item.value"
:value="item.value">{{item.label}}</a-select-option>
</a-select>
</a-form-model-item>
</a-col>
<template v-if="model.designFormulas === 2">
<a-col :span="12">
<a-form-model-item label="房屋面积" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="floorSpace">
<a-input v-model="model.floorSpace" placeholder="请输入房屋面积" style="width:100%"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="单价" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="unitPrice">
<a-input v-model="model.unitPrice" placeholder="请输入单价" style="width:100%"></a-input>
</a-form-model-item>
</a-col>
</template>
<template v-if="model.designFormulas === 3">
<a-col :span="12">
<a-form-model-item label="上期度数" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="lastDegrees">
<a-input v-model="model.lastDegrees" placeholder="请输入上期度数" style="width:100%"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="本期度数" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="currentDegrees">
<a-input-number v-model="model.currentDegrees" placeholder="请输入本期度数"
style="width:100%"></a-input-number>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="用量" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="useAmount">
<a-input v-model="model.useAmount" placeholder="请输入用量" style="width:100%"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="单价" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="unitPrice">
<a-input v-model="model.unitPrice" placeholder="请输入单价" style="width:100%"></a-input>
</a-form-model-item>
</a-col>
</template>
<a-col :span="12">
<a-form-model-item label="金额" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="totalAmount">
<a-input v-model="model.totalAmount" placeholder="请输入金额" style="width:100%"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="抄表时间" :labelCol="{ xs: { span: 24 }, sm: { span: 2 } }" :wrapperCol="wrapperCol"
prop="meterReadingTime">
<j-date placeholder="请选择抄表时间" v-model="model.meterReadingTime" :showTime="true"
dateFormat="YYYY-MM-DD HH:mm:ss" style="width: 50%;" />
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
</j-form-container>
<a-divider />
<div style="display:flex;justify-content: space-between;align-items: center;">
<h4 style="padding:0 0 0 30px;line-height:30px;font-weight:600;">历史记录</h4>
<p style="padding-right:50px;color:#EC808D">总缴费金额: {{totalAmount}}</p>
</div>
<div>
<a-table ref="table" size="middle" :scroll="{ x: 1500, y: 300 }" bordered rowKey="id" :columns="columns"
:dataSource="dataSource" :pagination="pagination" :loading="loading" class="j-table-force-nowrap">
<span slot="roomId" slot-scope="text, record">
<span>{{record.buildingName}}{{record.unitName}}{{record.roomName}}</span>
</span>
</a-table>
</div>
</a-spin>
<div style="text-align:center">
<a-button @click="onReturn">返回</a-button>
</div>
</div>
</template>
<script>
import { queryDetailByIdApi, ajaxGetDictItems, getDictItemsFromCache, getHistoryListdApi } from '@/api/api'
import { RELATION_SHIP } from '@/assets/static.js'
const columns = [
{
title: '收费类型',
dataIndex: 'chargeTypeName',
key: 'chargeTypeName',
width: 120,
align: 'center',
},
{
title: '收费项目',
dataIndex: 'chargeItem',
key: 'chargeItem',
width: 120,
align: 'center',
},
{
title: '房屋编号',
dataIndex: 'roomId',
scopedSlots: { customRender: 'roomId' },
key: 'roomId',
width: 140,
align: 'center',
},
{
title: '用量',
dataIndex: 'useAmount',
key: 'useAmount',
width: 120,
align: 'center',
},
{
title: '金额(元)',
dataIndex: 'totalAmount',
key: 'totalAmount',
width: 120,
align: 'center',
},
{
title: '缴费单号',
dataIndex: 'paymentNum',
key: 'paymentNum',
width: 120,
align: 'center',
},
{
title: '缴费日期',
dataIndex: 'paymentTime',
key: 'paymentTime',
width: 120,
align: 'center',
},
{
title: '创建日期',
dataIndex: 'createTime',
key: 'createTime',
width: 120,
align: 'center',
},
]
export default {
name: 'PropertyChargruleForm',
inject: ['closeCurrent'],
props: {
//表单禁用
disabled: {
type: Boolean,
default: false,
required: false,
},
},
data() {
return {
relationShipList: RELATION_SHIP,
dictOptions: [],
model: {
chargeCycle: '',
chargeItem: '',
chargingStandardId: '',
chargeTypeCode: '',
chargeTypeId: '',
chargeTypeName: '',
unitPrice: '',
ownerId: '',
buildingId: '',
buildingName: '',
unitId: '',
unitName: '',
roomId: '',
roomName: '',
floorSpace: '',
ownerName: '',
ownerPhone: '',
residentName: '',
residentPhone: '',
relationShip: '',
lastDegrees: '',
currentDegrees: '',
useAmount: '',
totalAmount: '',
meterReadingTime: '',
},
labelCol: {
xs: { span: 24 },
sm: { span: 4 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 20 },
},
totalAmount: '',
confirmLoading: false,
columns: columns,
dataSource: [],
pagination: {
total: 0,
current: 1,
pageSize: 10,
showSizeChanger: true,
},
loading: false,
}
},
computed: {
formDisabled() {
return this.disabled
},
},
created() {
//备份model原始值
this.getDetail()
this.initDictData()
},
methods: {
async getDetail() {
this.confirmLoading = true
let { result } = await queryDetailByIdApi({ id: this.$route.query.id })
result['chargeTypeCodeName'] = `${result.chargeTypeCode}-${result.chargeTypeName}`
result['roomAllName'] = `${result.buildingName}${result.unitName}${result.roomName}`
this.model = { ...result }
this.confirmLoading = false
this.getHistoryList(this.model.ownerId)
},
initDictData() {
//优先从缓存中读取字典配置
if (getDictItemsFromCache('chargingCycle')) {
this.dictOptions = getDictItemsFromCache('chargingCycle')
return
}
// //根据字典Code, 初始化字典数组
ajaxGetDictItems('chargingCycle', null).then((res) => {
if (res.success) {
this.dictOptions = res.result
}
})
},
async getHistoryList(ownerId) {
this.loading = true
let { result } = await getHistoryListdApi({ ownerId })
this.totalAmount = result.totalAmount
let data = result.pageList
this.pagination.total = data.total
this.pagination.current = data.current
this.pagination.pageSize = data.size
this.dataSource = data.records
this.loading = false
},
onReturn() {
// if(this.model.lastDegrees || this.model.lastDegrees == 0) {
// this.model.useAmount = (value - Number(this.model.lastDegrees)).toFixed(2)
// this.model.totalAmount = (Number(this.model.useAmount) * this.amount).toFixed(2)
// }
//this.closeCurrent()
this.$store.dispatch('tags/delView', this.$route.path)
this.$router.go(-1)
},
},
}
</script>
<style scoped lang="less">
.page-content {
min-height: 430px;
background-color: #fff;
padding: 0 15px 50px 5px;
}
</style>
\ No newline at end of file
<template>
<a-card :bordered="false">
<!-- 查询区域 -->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :md="6" :sm="8">
<a-form-item label="业主姓名">
<j-input placeholder="请输入业主姓名" v-model="queryParam.ownerName"></j-input>
</a-form-item>
</a-col>
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-col :md="6" :sm="24">
<a-button type="primary" @click="searchQuery">查询</a-button>
<a-button style="margin-left: 8px" @click="searchReset">重置</a-button>
</a-col>
</span>
</a-row>
</a-form>
</div>
<div style="display:flex">
<div style="flex: none;width:200px">
<a-tree :load-data="onLoadData" :tree-data="treeData" @select="onClickTree" />
</div>
<div style="flex:auto;width:80%;">
<!-- 操作按钮区域 -->
<div class="table-operator">
<a-button @click="onMeterReading" type="primary" icon="plus">手动生成账单</a-button>
<a-button icon="download" @click="downloadExportXls()">模板下载</a-button>
<a-upload name="file" :showUploadList="false" :multiple="false" :headers="tokenHeader"
:action="importExcelUrl" @change="handleImportExcel">
<a-button type="primary" icon="import">导入</a-button>
</a-upload>
<a-button type="primary" icon="download" @click="handleExportXls('生活缴费')">导出</a-button>
<div style="float: right; color: #f00;">
<span style="margin-right: 20px;">已缴费金额 (元):{{ statistical.paidMoney || 0 }}</span>
<span>待缴费金额 (元):{{ statistical.unPaidMoney || 0 }}</span>
</div>
<a-dropdown v-if="selectedRowKeys.length > 0">
<a-menu slot="overlay">
<a-menu-item key="1" @click="onBatchCallpay"><a-icon type="message" />催缴</a-menu-item>
<a-menu-item key="2" @click="batchDel"><a-icon type="delete" />删除</a-menu-item>
</a-menu>
<a-button style="margin-left: 8px"> 批量操作 <a-icon type="down" /></a-button>
</a-dropdown>
</div>
<!-- table区域-begin -->
<div>
<div class="ant-alert ant-alert-info" style="margin-bottom: 16px;">
<i class="anticon anticon-info-circle ant-alert-icon"></i>已选择&nbsp;<a style="font-weight: 600">{{
selectedRowKeys.length }}</a>&nbsp;&nbsp;
<a style="margin-left: 24px" v-if="selectedRowKeys.length > 0" @click="onClearSelected">清空</a>
</div>
<a-table ref="table" size="middle" :scroll="{ x: 1500}" bordered rowKey="id" :columns="columns"
:dataSource="dataSource" :pagination="ipagination" :loading="loading" :rowSelection="{
selectedRowKeys: selectedRowKeys,
onChange: onSelectChange,
getCheckboxProps: onCheckboxProps
}" class="j-table-force-nowrap" @change="handleTableChange">
<span slot="ownerId" slot-scope="text, record">
<span>{{record.ownerName}}{{record.ownerPhone}}</span>
</span>
<span slot="residentPhone" slot-scope="text, record">
<span>{{record.residentName}}{{record.residentPhone}}</span>
</span>
<span slot="roomId" slot-scope="text, record">
<span>{{record.buildingName}}{{record.unitName}}{{record.roomName}}</span>
</span>
<span slot="action" slot-scope="text, record">
<a @click="onDetail(record.id)">查看</a>
<template v-if="record.paymentStatus === 'unPaid'">
<a-divider type="vertical" />
<a @click="onCallPay(record.id)">催缴</a>
<a-divider type="vertical" />
<a @click="handleDelete(record.id)">删除</a>
</template>
</span>
</a-table>
</div>
<!-- table区域-end -->
</div>
</div>
<notice-modal ref="modalForm" @ok="modalFormOk"></notice-modal>
</a-card>
</template>
<script>
import { getBuildingListApi, getUnitListApi, getRoomListApi, callPayMentApi, getTotalMoneyApi } from '@/api/api'
import { downFile } from '@/api/manage'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import NoticeModal from './modules/NoticeModal'
import { PAYMENT_STATUS, RELATION_SHIP, filterDictTextByStatic } from '@/assets/static.js'
const columns = [
{
title: '收费类型',
dataIndex: 'chargeTypeName',
key: 'chargeTypeName',
width: 120,
align: 'center',
},
{
title: '收费项目',
dataIndex: 'chargeItem',
key: 'chargeItem',
width: 120,
align: 'center',
},
{
title: '业主',
dataIndex: 'ownerId',
key: 'ownerId',
width: 160,
scopedSlots: { customRender: 'ownerId' },
align: 'center',
},
{
title: '与业主关系',
dataIndex: 'relationShip',
key: 'relationShip',
width: 120,
align: 'center',
customRender: function (text) {
return filterDictTextByStatic(RELATION_SHIP, text)
},
},
{
title: '住户',
dataIndex: 'residentPhone',
key: 'residentPhone',
width: 160,
scopedSlots: { customRender: 'residentPhone' },
align: 'center',
},
{
title: '房屋编号',
dataIndex: 'roomId',
scopedSlots: { customRender: 'roomId' },
key: 'roomId',
width: 140,
align: 'center',
},
{
title: '金额(元)',
dataIndex: 'totalAmount',
key: 'totalAmount',
width: 120,
align: 'center',
},
{
title: '本期读表时间',
dataIndex: 'meterReadingTime',
key: 'meterReadingTime',
width: 150,
align: 'center',
},
{
title: '缴费状态',
dataIndex: 'paymentStatus',
key: 'paymentStatus',
width: 120,
align: 'center',
customRender: function (text) {
return filterDictTextByStatic(PAYMENT_STATUS, text)
},
},
{
title: '缴费单号',
dataIndex: 'paymentNum',
key: 'paymentNum',
width: 120,
align: 'center',
},
{
title: '缴费日期',
dataIndex: 'paymentTime',
key: 'paymentTime',
width: 150,
align: 'center',
},
{
title: '创建日期',
dataIndex: 'createTime',
key: 'createTime',
width: 150,
align: 'center',
},
{
title: '操作',
dataIndex: 'action',
scopedSlots: { customRender: 'action' },
align: 'center',
width: 150,
fixed: 'right',
},
]
export default {
name: 'PermissionListAsync',
mixins: [JeecgListMixin],
components: { NoticeModal },
data() {
return {
// 表头
columns: columns,
url: {
list: '/property-community/payment/communityPayment/propertyFeeList',
delete: '/property-community/payment/communityPayment/delete',
deleteBatch: '/property-community/payment/communityPayment/deleteBatch',
exportXlsUrl: '/property-community/payment/communityPayment/exportXls',
importExcelUrl: 'property-community/payment/communityPayment/importExcel',
downloadExcelUrl: '/property-community/payment/communityPayment/downloadPaymentTemplate',
},
treeData: [],
statistical: {},
}
},
created() {
this.getBuildingList()
this.getTotalMoney()
},
computed: {
importExcelUrl: function () {
return `${window._CONFIG['domianURL']}/${this.url.importExcelUrl}`
},
},
methods: {
onCheckboxProps(record) {
let props = {
disabled: record.paymentStatus === 'paid',
name: record.chargeTypeName,
}
return props
},
async getTotalMoney() {
let { result } = await getTotalMoneyApi({ type: 'propertyFee' })
this.statistical = result
},
async getBuildingList() {
let { result } = await getBuildingListApi()
this.treeData = result.map((item) => {
return {
title: item.buildingName,
key: item.id,
}
})
},
onClickTree(value, option) {
console.log(value, option)
let level = option.node.pos.split('-').length
if (level === 2) {
this.queryParam['buildingId'] = value[0]
this.queryParam['unitId'] = undefined
this.queryParam['roomId'] = undefined
}
if (level === 3) {
this.queryParam['buildingId'] = undefined
this.queryParam['unitId'] = value[0]
this.queryParam['roomId'] = undefined
}
if (level === 4) {
this.queryParam['buildingId'] = undefined
this.queryParam['unitId'] = undefined
this.queryParam['roomId'] = value[0]
}
this.searchQuery()
},
onLoadData(treeNode) {
return new Promise(async (resolve) => {
if (treeNode.dataRef.children) {
resolve()
return
}
if (treeNode.pos.split('-').length === 2) {
let { result } = await getUnitListApi({ id: treeNode.eventKey })
treeNode.dataRef.children = result.map((item) => {
return {
title: item.unitName,
key: item.id,
}
})
this.treeData = [...this.treeData]
resolve()
} else {
let { result } = await getRoomListApi({ id: treeNode.eventKey })
treeNode.dataRef.children = result.map((item) => {
return {
title: item.roomNum,
key: item.id,
isLeaf: true,
}
})
this.treeData = [...this.treeData]
resolve()
}
})
},
onMeterReading() {
this.$refs.modalForm.add()
this.$refs.modalForm.title = '抄表'
this.$refs.modalForm.disableSubmit = false
},
onBatchCallpay() {
// console.log(this.selectionRows)
let chooseIds = this.selectedRowKeys.join(',')
this.onCallPay(chooseIds)
},
onDetail(id) {
this.$router.push({
path: '/property/propertyfee-detail?id=' + id,
})
},
onCallPay(chooseIds) {
let that = this
this.$confirm({
title: '催缴账单',
content: '是否催缴当前选择的账单发送给对应业主?',
onOk: function () {
that.loading = true
callPayMentApi({ chooseIds })
.then((res) => {
if (res.success) {
//重新计算分页问题
that.$message.success(res.message)
// that.searchQuery();
that.onClearSelected()
} else {
that.$message.warning(res.message)
}
})
.finally(() => {
that.loading = false
})
},
})
},
downloadExportXls() {
let fileName = '生活缴费模板'
downFile(this.url.downloadExcelUrl, '').then((data) => {
if (!data) {
this.$message.warning('文件下载失败')
return
}
if (typeof window.navigator.msSaveBlob !== 'undefined') {
window.navigator.msSaveBlob(new Blob([data], { type: 'application/vnd.ms-excel' }), fileName + '.xls')
} else {
let url = window.URL.createObjectURL(new Blob([data], { type: 'application/vnd.ms-excel' }))
let link = document.createElement('a')
link.style.display = 'none'
link.href = url
link.setAttribute('download', fileName + '.xls')
document.body.appendChild(link)
link.click()
document.body.removeChild(link) //下载完成移除元素
window.URL.revokeObjectURL(url) //释放掉blob对象
}
})
},
},
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>
\ No newline at end of file
<template>
<div class="page-content">
<a-spin :spinning="confirmLoading">
<div style="padding:24px 30px;font-weight:600;">投诉详情</div>
<j-form-container :disabled="true">
<a-form-model ref="form" :model="model" slot="detail">
<a-row>
<a-col :span="12">
<a-form-model-item label="投诉主题" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="complaintTheme">
<a-input v-model="model.complaintTheme" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="投诉人" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="userName">
<a-input v-model="model.userName" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="联系方式" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="userPhone">
<a-input v-model="model.userPhone" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<!-- <a-col :span="12">
<a-form-model-item label="住户地址" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="repairAddress">
<a-input v-model="model.repairAddress" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col> -->
<a-col :span="12">
<a-form-model-item label="投诉时间" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="createTime">
<a-input v-model="model.createTime" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="图片" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="complaintImg">
<j-image-upload bizPath="scott/pic" accept="image/png, image/jpeg"
v-model="model.complaintImg"></j-image-upload>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="问题描述" :labelCol="{ xs: { span: 24 }, sm: { span: 2 } }" :wrapperCol="wrapperCol"
prop="problemDesc">
<a-textarea v-model="model.problemDesc" placeholder="请输入" style="width:80%" />
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
</j-form-container>
<j-form-container v-if="!formDisabled || model.handleStatus == 'finish'"
:disabled="model.handleStatus == 'finish'">
<a-form-model ref="form" :model="form" slot="detail">
<a-row>
<a-col :span="24">
<a-form-model-item label="处理状态" :labelCol="{ xs: { span: 24 }, sm: { span: 2 } }" :wrapperCol="wrapperCol"
prop="handleStatus">
<a-select v-model="form.handleStatus" placeholder="请选择处理状态" style="width:50%">
<a-select-option value="pending">处理中</a-select-option>
<a-select-option value="finish">处理完成</a-select-option>
</a-select>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="处理结果" :labelCol="{ xs: { span: 24 }, sm: { span: 2 } }" :wrapperCol="wrapperCol"
prop="handleResult">
<a-textarea v-model="form.handleResult" placeholder="请输入" style="width:80%" />
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
</j-form-container>
<div style="text-align:center">
<a-button @click="onReturn">返回</a-button>
<a-button style="margin-left: 16px" type="primary" v-if="!formDisabled" @click="onSubmit">提交</a-button>
</div>
</a-spin>
</div>
</template>
<script>
import { querycommunityComplaintApi, auditCommunityComplaintApi } from '@/api/api'
export default {
name: 'PropertyChargruleForm',
inject: ['closeCurrent'],
data() {
return {
currentStep: 1,
model: {},
form: {
handleStatus: 'pending',
handleResult: '',
},
labelCol: {
xs: { span: 24 },
sm: { span: 4 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 20 },
},
confirmLoading: false,
}
},
computed: {
formDisabled() {
return this.$route.query.type === '1'
},
},
created() {
//备份model原始值
this.getDetail()
},
methods: {
async getDetail() {
this.confirmLoading = true
let { result } = await querycommunityComplaintApi({ id: this.$route.query.id })
this.model = { ...result }
if (this.model.handleStatus == 'finish') {
this.form.handleStatus = this.model.handleStatus
this.form.handleResult = this.model.handleResult
}
this.confirmLoading = false
},
onReturn() {
this.$store.dispatch('tags/delView', this.$route.path)
this.$router.go(-1)
},
async onSubmit() {
let res = await auditCommunityComplaintApi({
id: this.$route.query.id,
handleStatus: this.form.handleStatus,
handleResult: this.form.handleResult,
})
this.$message.success(res.message)
this.$store.dispatch('tags/delView', this.$route.path)
this.$router.go(-1)
},
},
}
</script>
<style scoped lang="less">
.page-content {
min-height: 430px;
background-color: #fff;
padding: 0 15px 50px 5px;
.row-box {
padding: 0 50px;
}
}
</style>
\ No newline at end of file
<template>
<a-card :bordered="false">
<!-- 查询区域 -->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :md="6" :sm="8">
<a-form-item label="投诉单号">
<j-input placeholder="请输入投诉单号" v-model="queryParam.complaintNo"></j-input>
</a-form-item>
</a-col>
<a-col :md="6" :sm="8">
<a-form-model-item label="状态">
<a-select style="width: 100%" v-model="queryParam.handleStatus" placeholder="请选择状态">
<a-select-option v-for="item in dictOptions" :key="item.value"
:value="item.value">{{item.label}}</a-select-option>
</a-select>
</a-form-model-item>
</a-col>
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-col :md="6" :sm="24">
<a-button type="primary" @click="searchQuery">查询</a-button>
<a-button style="margin-left: 8px" @click="searchReset">重置</a-button>
</a-col>
</span>
</a-row>
</a-form>
</div>
<!-- table区域-begin -->
<div>
<a-row :gutter="24">
<a-col :sm="24" :md="12" :xl="14" :style="{ marginBottom: '24px' }">
<a-table ref="table" size="middle" :scroll="{x:true}" bordered rowKey="id" :columns="columns"
:dataSource="dataSource" :pagination="ipagination" :loading="loading" class="j-table-force-nowrap"
@change="handleTableChange">
</a-table>
</a-col>
<a-col :sm="24" :md="12" :xl="10" :style="{ marginBottom: '24px' }">
<div class="pay-cost t-box">
<h3 class="box-title">投诉</h3>
<pie :dataSource="repairData" />
<div class="number">
<p>全部报修 {{totalNum}}</p>
<p v-for="(item, index) in repairData" :key="index">{{ item.item }} {{ item.count }}</p>
</div>
</div>
</a-col>
</a-row>
</div>
<!-- table区域-end -->
</a-card>
</template>
<script>
import { complaintStatistics } from '@/api/api'
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import { COMPLAINT_STATUS, filterDictTextByStatic } from '@/assets/static.js'
import Pie from '@/components/chart/Pie'
const columns = [
{
title: '投诉工单',
dataIndex: 'complaintNo',
key: 'complaintNo',
width: 130,
align: 'center',
},
{
title: '投诉主题',
dataIndex: 'complaintTheme',
key: 'complaintTheme',
align: 'center',
},
// {
// title: '问题描述',
// dataIndex: 'problemDesc',
// key: 'problemDesc',
// align: 'center',
// },
{
title: '投诉人',
dataIndex: 'userName',
key: 'userName',
align: 'center',
},
{
title: '联系方式',
dataIndex: 'userPhone',
key: 'userPhone',
align: 'center',
},
{
title: '状态',
dataIndex: 'handleStatus',
key: 'handleStatus',
align: 'center',
customRender: function (text) {
return filterDictTextByStatic(COMPLAINT_STATUS, text)
},
},
]
export default {
name: 'PermissionListAsync',
mixins: [JeecgListMixin],
components: { Pie },
data() {
return {
dictOptions: COMPLAINT_STATUS,
// 表头
columns: columns,
url: {
list: '/property-community/property/communityComplaint/list'
},
repairData:[],
totalNum:0
}
},
created() {
this.onDetail()
},
methods: {
async onDetail(typeCode) {
let { result } = await complaintStatistics({ typeCode: typeCode })
this.totalNum = result.totalNum
this.repairData = [
// { item: '全部报修', count: result.repairTotal || 0 },
// { item: '待派单', count: result.waitDispatch || 0 },
{ item: '未完成', count: result.incompleteNum|| 0 },
{ item: '已完成', count: result.finishComplaintNum || 0 },
]
},
},
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>
<style lang="less" scoped>
.number {
width: 80%;
margin: 0 10%;
display: flex;
justify-content: space-evenly;
p {
font-size: 14px;
margin: 0;
}
}
.pay-cost{
height: 506px;
}
.t-box {
background: #fff;
padding: 15px;
border: 1px solid #e8e8e8;
}
.box-title {
font-weight: bold;
margin-bottom: 15px;
display: inline-block;
padding-left: 10px;
border-left: 3px solid #1890ff;
height: 20px;
line-height: 20px;
}
</style>
\ No newline at end of file
<template>
<a-spin :spinning="confirmLoading">
<j-form-container :disabled="formDisabled">
<a-form-model ref="form" :model="model" :rules="validatorRules" slot="detail">
<a-row>
<a-col :span="12">
<a-form-model-item label="投诉主题" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="complaintTheme">
<a-input v-model="model.complaintTheme" readonly placeholder="请输入投诉主题"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="投诉人" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="userName">
<a-input v-model="model.userName" placeholder="请输入投诉人"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="联系方式" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="userPhone">
<a-input v-model="model.userPhone" placeholder="请输入联系方式"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="住户地址" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="userAddress">
<a-input v-model="model.userAddress" placeholder="请输入住户地址"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="投诉时间" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="complaintTime">
<a-input v-model="model.complaintTime" placeholder="请输入投诉时间"></a-input>
</a-form-model-item>
</a-col>
</a-row>
<a-row>
<a-col :span="24">
<a-form-model-item label="问题描述" :labelCol="{ xs:{ span: 24 }, sm:{ span: 3 } }" :wrapperCol="wrapperCol" prop="problemDesc">
<a-textarea placeholder="请输入问题描述" v-model="model.problemDesc" :auto-size="{ minRows: 3, maxRows: 5 }" allow-clear />
</a-form-model-item>
</a-col>
</a-row>
<a-row>
<a-col :span="24">
<a-form-model-item label="处理结果" :labelCol="{ xs:{ span: 24 }, sm:{ span: 3 } }" :wrapperCol="wrapperCol" prop="handleResult">
<a-textarea placeholder="请输入处理结果" v-model="model.handleResult" :auto-size="{ minRows: 3, maxRows: 5 }" allow-clear />
</a-form-model-item>
</a-col>
</a-row>
<a-row>
<a-col :span="24">
<a-form-model-item label="处理状态" :labelCol="{ xs:{ span: 24 }, sm:{ span: 3 } }" :wrapperCol="wrapperCol" prop="handleStatus">
<a-select style="width: 100%" v-model="model.handleStatus" placeholder="请选择处理状态">
<a-select-option v-for="item in dictOptions" :key="item.value" :value="item.value">{{item.label}}</a-select-option>
</a-select>
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
</j-form-container>
</a-spin>
</template>
<script>
import { httpAction, getAction } from '@/api/manage'
import { validateDuplicateValue } from '@/utils/util'
import {ajaxGetDictItems,getDictItemsFromCache} from '@/api/api'
export default {
name: 'PropertyChargruleForm',
components: {
},
props: {
//表单禁用
disabled: {
type: Boolean,
default: false,
required: false
}
},
data () {
return {
dictOptions: [],
model:{
complaintTheme: '',
userName: '',
userPhone: '',
userAddress: '',
complaintTime: '',
problemDesc: '',
handleResult: '',
handleStatus: ''
},
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
validatorRules: {
complaintTheme: [{ required: true, message: '请输入员工姓名', trigger: 'blur' }],
employeePhone: [{ required: true, message: '请输入联系电话', trigger: 'blur' }],
employeeDuties: [{ required: true, message: '请选择员工职务', trigger: 'change' }]
},
url: {
add: "/property-community/employee/companyEmployee/add",
edit: "/property-community/property/communityComplaint/edit",
queryById: "/property-community/property/communityComplaint/queryById"
}
}
},
computed: {
formDisabled(){
return this.disabled
},
},
created () {
//备份model原始值
this.modelDefault = JSON.parse(JSON.stringify(this.model));
this.initDictData()
},
methods: {
initDictData() {
//优先从缓存中读取字典配置
if(getDictItemsFromCache('complaint_status')){
this.dictOptions = getDictItemsFromCache('complaint_status');
return
}
// //根据字典Code, 初始化字典数组
ajaxGetDictItems('complaint_status', null).then((res) => {
if (res.success) {
this.dictOptions = res.result;
}
})
},
ruleNumberInput(event) {
let rateValue = event.target.value.replace(/[^\d]/g,"");//清除"数字"和"."和"-"以外的字符
this.model['empowerDays'] = rateValue
},
add () {
this.edit(this.modelDefault);
},
edit (record) {
console.log(record)
this.model = Object.assign({}, record);
this.visible = true;
},
submitForm () {
const that = this;
// 触发表单验证
this.$refs.form.validate(valid => {
if (valid) {
that.confirmLoading = true;
let httpurl = '';
let method = '';
if(!this.model.id){
httpurl+=this.url.add;
method = 'post';
}else{
httpurl+=this.url.edit;
method = 'put';
}
httpAction(httpurl,this.model,method).then((res)=>{
if(res.success){
that.$message.success(res.message);
that.$emit('ok');
}else{
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
})
}
})
},
}
}
</script>
\ No newline at end of file
<template>
<j-modal
:title="title"
:width="width"
:visible="visible"
switchFullscreen
@ok="handleOk"
:okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
@cancel="handleCancel"
cancelText="关闭">
<property-settled-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit"></property-settled-form>
</j-modal>
</template>
<script>
import PropertySettledForm from './NoticeForm'
export default {
name: 'PropertySettledModal',
components: {
PropertySettledForm
},
data () {
return {
title:'',
width: '70%',
visible: false,
disableSubmit: false
}
},
methods: {
add () {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.add();
})
},
edit (record) {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.edit(record);
})
},
close () {
this.$emit('close');
this.visible = false;
},
handleOk () {
this.$refs.realForm.submitForm();
},
submitCallback(){
this.$emit('ok');
this.visible = false;
},
handleCancel () {
this.close()
}
}
}
</script>
\ No newline at end of file
<template>
<div class="hone-content-box">
<a-row :gutter="24">
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<div class="statistics">
<div class="icon" style="background-color:#1890ff;"><a-icon type="area-chart" /></div>
<div>
<p style="color:#666;margin-bottom:5px;">已缴水费</p>
<p style="margin-bottom:0;color:#333;font-size:28px;line-height:1;">{{pageForm.waterFeePaidTotal}}</p>
</div>
</div>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<div class="statistics">
<div class="icon" style="background-color:#7262fd;"><a-icon type="pie-chart" /></div>
<div>
<p style="color:#666;margin-bottom:5px;">已缴电费</p>
<p style="margin-bottom:0;color:#333;font-size:28px;line-height:1;">{{pageForm.electricFeePaidTotal}}</p>
</div>
</div>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<div class="statistics">
<div class="icon" style="background-color:#ffaa00;"><a-icon type="bar-chart" /></div>
<div>
<p style="color:#666;margin-bottom:5px;">已缴燃气费</p>
<p style="margin-bottom:0;color:#333;font-size:28px;line-height:1;">{{pageForm.gasFeePaidTotal}}</p>
</div>
</div>
</a-col>
<a-col :sm="24" :md="12" :xl="6" :style="{ marginBottom: '24px' }">
<div class="statistics">
<div class="icon" style="background-color:#52c41a;"><a-icon type="dot-chart" /></div>
<div>
<p style="color:#666;margin-bottom:5px;">已缴暖气费</p>
<p style="margin-bottom:0;color:#333;font-size:28px;line-height:1;">{{pageForm.heatFeePaidTotal}}</p>
</div>
</div>
</a-col>
</a-row>
<a-row :gutter="24">
<div class="pay-cost t-box">
<div class="pay-cost-tit">水费统计</div>
<a-col :sm="24" :md="12" :xl="12">
<pie :dataSource="dataSource1" />
</a-col>
<a-col :sm="24" :md="12" :xl="12">
<pie :dataSource="dataSource2" />
</a-col>
</div>
</a-row>
<a-row :gutter="24">
<div class="pay-cost t-box">
<div class="pay-cost-tit">电费统计</div>
<a-col :sm="24" :md="12" :xl="12">
<pie :dataSource="dataSource3" />
</a-col>
<a-col :sm="24" :md="12" :xl="12">
<pie :dataSource="dataSource4" />
</a-col>
</div>
</a-row>
<a-row :gutter="24">
<div class="pay-cost t-box">
<div class="pay-cost-tit">燃气费统计</div>
<a-col :sm="24" :md="12" :xl="12">
<pie :dataSource="dataSource5" />
</a-col>
<a-col :sm="24" :md="12" :xl="12">
<pie :dataSource="dataSource6" />
</a-col>
</div>
</a-row>
<a-row :gutter="24">
<div class="pay-cost t-box">
<div class="pay-cost-tit">暖气费统计</div>
<a-col :sm="24" :md="12" :xl="12">
<pie :dataSource="dataSource7" />
</a-col>
<a-col :sm="24" :md="12" :xl="12">
<pie :dataSource="dataSource8" />
</a-col>
</div>
</a-row>
<a-row :gutter="24">
<a-col :sm="24" :md="24" :xl="24" :style="{ marginBottom: '24px' }">
<div class="salesCard t-box">
<!-- <h3 class="box-title">缴费统计</h3> -->
<div class="extra-type">
<a-radio-group @change="handleSizeChange" :value="typeCode">
<a-radio-button value="1">水费</a-radio-button>
<a-radio-button value="2">电费</a-radio-button>
<a-radio-button value="3">燃气费</a-radio-button>
<a-radio-button value="4">暖气费</a-radio-button>
<a-radio-button value="5">已缴金额</a-radio-button>
</a-radio-group>
</div>
<div>
<bar :dataSource="barData" style="padding: 0;" />
</div>
</div>
</a-col>
</a-row>
</div>
</template>
<script>
import Bar from '@/components/chart/Bar'
import Pie from '@/components/chart/Pie'
import { paymentStatistics, companyNoticeList } from '@/api/api'
// const barData = []
// for (let i = 0; i < 12; i += 1) {
// barData.push({
// x: `${i + 1}月`,
// y: 1000,
// })
// }
export default {
name: 'Analysis',
components: {
Bar,
Pie,
},
data() {
return {
pageForm: {},
loading: true,
dataSource1:[],
dataSource2:[],
dataSource3:[],
dataSource4:[],
dataSource5:[],
dataSource6:[],
dataSource7:[],
dataSource8:[],
typeCode: '1',
repairData: [],
complaintsData: [],
barData: [],
visible: false,
}
},
created() {
this.onDetail('1')
},
methods: {
async onDetail(typeCode) {
let { result } = await paymentStatistics({ beginDate: '', endDate: '' })
this.pageForm = { ...result }
this.barData = result.monthlyStatistics.map((item) => {
var num = '';
if(typeCode == '1'){
num = item.waterFeePaidTotal
}else if(typeCode == '2'){
num = item.electricFeePaidTotal
}else if(typeCode == '3'){
num = item.gasFeePaidTotal
}else if(typeCode == '4'){
num = item.heatFeePaidTotal
}else if(typeCode == '5'){
num = item.totalAmount
}
return {
x: item.monthNum + '月',
y: num
}
})
this.dataSource1 = [
{ item: '未缴总金额', count: result.waterFeeUnPaidTotal || 0 },
{ item: '已缴总金额', count: result.waterFeePaidTotal || 0 },
]
this.dataSource2 = [
{ item: '未缴纳业主', count: result.electricFeeUnPaidOwnerNum || 0 },
{ item: '已缴纳业主', count: result.waterFeePaidOwnerNum || 0 },
]
this.dataSource3 = [
{ item: '未缴总金额', count: result.electricFeeUnPaidTotal || 0 },
{ item: '已缴总金额', count: result.electricFeePaidTotal || 0 },
]
this.dataSource4 = [
{ item: '未缴纳业主', count: result.electricFeeUnPaidOwnerNum || 0 },
{ item: '已缴纳业主', count: result.electricFeePaidOwnerNum || 0 },
]
this.dataSource5 = [
{ item: '未缴总金额', count: result.gasFeeUnPaidTotal || 0 },
{ item: '已缴总金额', count: result.gasFeePaidTotal || 0 },
]
this.dataSource6 = [
{ item: '未缴纳业主', count: result.gasFeeUnPaidOwnerNum || 0 },
{ item: '已缴纳业主', count: result.gasFeePaidOwnerNum || 0 },
]
this.dataSource7 = [
{ item: '未缴总金额', count: result.heatFeeUnPaidTotal || 0 },
{ item: '已缴总金额', count: result.heatFeePaidTotal || 0 },
]
this.dataSource8 = [
{ item: '未缴纳业主', count: result.heatFeeUnPaidOwnerNum || 0 },
{ item: '已缴纳业主', count: result.heatFeePaidOwnerNum || 0 },
]
this.loading = !this.loading
},
handleSizeChange(e) {
let that = this
this.typeCode = e.target.value
that.onDetail(this.typeCode)
},
},
}
</script>
<style lang="less" scoped>
.hone-content-box {
padding: 10px;
.statistics {
// flex: none;
background: #fff;
width: 100%;
height: 90px;
box-sizing: border-box;
border: 1px solid #e0dfdf;
display: flex;
align-items: center;
padding-left: 20px;
.icon {
width: 50px;
height: 50px;
border-radius: 50px;
margin-right: 12px;
display: flex;
text-align: center;
align-items: center;
justify-content: center;
.anticon {
font-size: 26px;
color: #ffffff;
}
}
}
.pay-box {
display: flex;
.left-box {
flex: none;
width: 50%;
}
}
}
.t-box {
background: #fff;
padding: 15px;
border: 1px solid #e0dfdf;
}
.box-title {
font-weight: bold;
margin-bottom: 15px;
display: inline-block;
padding-left: 10px;
border-left: 3px solid #1890ff;
height: 20px;
line-height: 20px;
}
.pay-cost {
height: 280px;
padding: 50px 0 0;
margin: 0 12px;
position: relative;
.pay-cost-tit {
writing-mode: vertical-rl;
position: absolute;
padding: 0 12px;
text-align: center;
background: #dcedff;
height: 278px;
top: 0;
color: #000;
font-weight: bold;
font-size: 16px;
letter-spacing: 12px;
}
}
.salesCard {
height: 380px;
}
.extra-type {
text-align: center;
a {
margin-right: 20px;
}
}
.number {
width: 80%;
margin: 0 10%;
display: flex;
justify-content: space-evenly;
p {
font-size: 14px;
margin: 0;
}
}
</style>
\ No newline at end of file
<template>
<div class="page-content">
<a-spin :spinning="confirmLoading">
<div style="padding:24px 30px;font-weight:600;">报修流程</div>
<div class="row-box">
<a-steps :current="currentStep">
<a-step v-for="(item, index) in auditList" :key="index" :title="item.title" :description="item.time" />
</a-steps>
</div>
<a-divider />
<div style="padding:0 30px 24px;font-weight:600;">报修信息</div>
<j-form-container :disabled="true">
<a-form-model ref="form" :model="model" slot="detail">
<a-row>
<a-col :span="12">
<a-form-model-item label="报修主题" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="repairTitle">
<a-input v-model="model.repairTitle" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="报修单号" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="id">
<a-input v-model="model.id" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="报修物品" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="repairArticle">
<a-input v-model="model.repairArticle" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="预约上门时间" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="reservationTime">
<a-input v-model="model.reservationTime" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="报修人" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="ownerName">
<a-input v-model="model.ownerName" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="报修位置" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="repairAddress">
<a-input v-model="model.repairAddress" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="报修描述" :labelCol="{ xs: { span: 24 }, sm: { span: 2 } }" :wrapperCol="wrapperCol"
prop="repairDesc">
<a-textarea v-model="model.repairDesc" placeholder="请输入" style="width:80%" />
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="报修图片" :labelCol="{ xs:{ span: 24 }, sm:{ span: 2 } }" :wrapperCol="wrapperCol"
prop="repairPhotoList">
<j-image-upload :isMultiple="true" text="点击上传" bizPath="scott/pic"
v-model="model.repairPhotoList"></j-image-upload>
</a-form-model-item>
</a-col>
<template v-if="model.maintenanceName">
<a-col :span="12">
<a-form-model-item label="维修员" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="maintenanceName">
<a-input v-model="model.maintenanceName" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="24">
<a-form-model-item label="维修记录" :labelCol="{ xs:{ span: 24 }, sm:{ span: 2 } }" :wrapperCol="wrapperCol"
prop="maintenancePhoto">
<j-image-upload :isMultiple="true" text="点击上传" bizPath="scott/pic"
v-model="model.maintenancePhoto"></j-image-upload>
</a-form-model-item>
</a-col>
</template>
<a-col :span="12">
<a-form-model-item label="工单状态" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="repairStatusName">
<a-input v-model="model.repairStatusName" placeholder="请输入"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="24"
v-if="(model.repairStatus === 'initiateRefuse' || model.repairStatus === 'finishRefuse') && model.auditOpinion">
<a-form-model-item label="驳回理由" :labelCol="{ xs: { span: 24 }, sm: { span: 2 } }" :wrapperCol="wrapperCol"
prop="auditOpinion">
<a-textarea v-model="model.auditOpinion" placeholder="请输入" style="width:80%" />
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
</j-form-container>
<j-form-container v-if="formShow">
<a-form-model ref="form" :model="form" slot="detail">
<a-row>
<a-col :span="24">
<a-form-model-item label="审核意见" :labelCol="{ xs: { span: 24 }, sm: { span: 2 } }" :wrapperCol="wrapperCol"
prop="repairStatus">
<a-select v-model="form.repairStatus" placeholder="请选择与业主关系" style="width:50%">
<template v-if="model.repairStatus === 'initiateWaitAudit'">
<a-select-option value="waitDispatch">审核通过</a-select-option>
<a-select-option value="initiateRefuse">审核驳回</a-select-option>
</template>
<template v-if="model.repairStatus === 'finishWaitAudit'">
<a-select-option value="finishAuditPass">审核通过</a-select-option>
<a-select-option value="finishRefuse">审核驳回</a-select-option>
</template>
</a-select>
</a-form-model-item>
</a-col>
<a-col :span="24" v-if="form.repairStatus === 'initiateRefuse' || form.repairStatus === 'finishRefuse'">
<a-form-model-item label="驳回理由" :labelCol="{ xs: { span: 24 }, sm: { span: 2 } }" :wrapperCol="wrapperCol"
prop="auditOpinion">
<a-textarea v-model="form.auditOpinion" placeholder="请输入" style="width:80%" />
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
</j-form-container>
<div style="text-align:center">
<a-button @click="onReturn">返回</a-button>
<a-button style="margin-left: 16px" type="primary" v-if="formShow" @click="onSubmit">提交</a-button>
</div>
</a-spin>
</div>
</template>
<script>
import { auditCommunityRepairApi, queryCommunityRepairApi } from '@/api/api'
import { REPAIR_STATUS, filterDictTextByStatic } from '@/assets/static.js'
const initiatewaitAuditList = [
{ title: '提交维修信息', time: '' },
{ title: '报单待审核', time: '' },
{ title: '待派单', time: '' },
{ title: '维修中', time: '' },
{ title: '提单待审核', time: '' },
{ title: '完成', time: '' },
]
export default {
name: 'PropertyChargruleForm',
inject: ['closeCurrent'],
data() {
return {
repairStatus: REPAIR_STATUS,
auditList: [],
currentStep: 1,
model: {},
form: {
repairStatus: '',
auditOpinion: '',
},
labelCol: {
xs: { span: 24 },
sm: { span: 4 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 20 },
},
confirmLoading: false,
}
},
computed: {
formShow() {
return this.$route.query.type === 'audit'
},
},
created() {
//备份model原始值
this.getDetail()
},
methods: {
async getDetail() {
this.confirmLoading = true
let { result } = await queryCommunityRepairApi({ id: this.$route.query.id })
result.repairPhotoList = result.repairPhoto.split(',')
this.model = { ...result }
this.confirmLoading = false
this.model.repairStatusName = filterDictTextByStatic(REPAIR_STATUS, this.model.repairStatus)
if (result.repairStatus === 'initiateWaitAudit') {
initiatewaitAuditList[0].time = '提交成功' + result.createTime
this.auditList = [...initiatewaitAuditList]
} else if (result.repairStatus === 'waitDispatch') {
initiatewaitAuditList[0].time = '提交成功' + result.createTime
initiatewaitAuditList[1].time = '审核通过' + result.initiateAuditTime
this.auditList = [...initiatewaitAuditList]
this.currentStep = 2
} else if (result.repairStatus === 'waitReceive') {
initiatewaitAuditList[0].time = '提交成功' + result.createTime
initiatewaitAuditList[1].time = '审核通过' + result.initiateAuditTime
initiatewaitAuditList[2].time = '派单成功待接收' + result.updateTime
this.auditList = [...initiatewaitAuditList]
this.currentStep = 2
} else if (result.repairStatus === 'inRepair') {
initiatewaitAuditList[0].time = '提交成功' + result.createTime
initiatewaitAuditList[1].time = '审核通过' + result.initiateAuditTime
initiatewaitAuditList[2].time = '派单成功待接收' + result.updateTime
this.auditList = [...initiatewaitAuditList]
this.currentStep = 3
} else if (
result.repairStatus === 'finishWaitAudit' ||
result.repairStatus === 'finishRefuse' ||
result.repairStatus === 'finishAuditPass'
) {
initiatewaitAuditList[0].time = '提交成功' + result.createTime
initiatewaitAuditList[1].time = '审核通过' + result.initiateAuditTime
initiatewaitAuditList[2].time = '派单成功待接收' + result.updateTime
this.auditList = [...initiatewaitAuditList]
this.currentStep = 4
} else if (result.repairStatus === 'finish') {
initiatewaitAuditList[0].time = '提交成功' + result.createTime
initiatewaitAuditList[1].time = '审核通过' + result.initiateAuditTime
initiatewaitAuditList[2].time = '派单成功待接收' + result.updateTime
this.auditList = [...initiatewaitAuditList]
this.currentStep = 5
} else {
initiatewaitAuditList[0].time = '提交成功' + result.createTime
this.auditList = [...initiatewaitAuditList]
this.currentStep = 0
}
},
onReturn() {
this.$store.dispatch('tags/delView', this.$route.path)
this.$router.go(-1)
},
async onSubmit() {
if (this.form.repairStatus) {
let res = await auditCommunityRepairApi({
id: this.$route.query.id,
repairStatus: this.form.repairStatus,
auditOpinion: this.form.auditOpinion,
})
this.$message.success(res.message)
this.onReturn()
}else{
this.$message.warning('请选择审核意见');
}
},
},
}
</script>
<style scoped lang="less">
.page-content {
min-height: 430px;
background-color: #fff;
padding: 0 15px 50px 5px;
.row-box {
padding: 0 50px;
}
}
</style>
\ No newline at end of file
<template>
<a-card :bordered="false">
<!-- 查询区域 -->
<div class="table-page-search-wrapper">
<a-form layout="inline" @keyup.enter.native="searchQuery">
<a-row :gutter="24">
<a-col :md="6" :sm="8">
<a-form-item label="报修单号">
<j-input placeholder="请输入报修单号" v-model="queryParam.id"></j-input>
</a-form-item>
</a-col>
<a-col :md="6" :sm="8">
<a-form-model-item label="工单状态">
<a-select style="width: 100%" v-model="queryParam.repairStatus" placeholder="请选择工单状态">
<a-select-option v-for="item in repairStatus" :key="item.value"
:value="item.value">{{item.label}}</a-select-option>
</a-select>
</a-form-model-item>
</a-col>
<span style="float: left;overflow: hidden;" class="table-page-search-submitButtons">
<a-col :md="6" :sm="24">
<a-button type="primary" @click="searchQuery">查询</a-button>
<a-button style="margin-left: 8px" @click="searchReset">重置</a-button>
</a-col>
</span>
</a-row>
</a-form>
</div>
<!-- table区域-begin -->
<div>
<a-row :gutter="24">
<a-col :sm="24" :md="12" :xl="14" :style="{ marginBottom: '24px' }">
<a-table ref="table" size="middle" :scroll="{x:true}" bordered rowKey="id" :columns="columns"
:dataSource="dataSource" :pagination="ipagination" :loading="loading" class="j-table-force-nowrap"
@change="handleTableChange">
</a-table>
</a-col>
<a-col :sm="24" :md="12" :xl="10" :style="{ marginBottom: '24px' }">
<div class="pay-cost t-box">
<h3 class="box-title">报修统计</h3>
<pie :dataSource="repairData" />
<div class="number">
<p>全部报修 {{totalNum}}</p>
<p v-for="(item, index) in repairData" :key="index">{{ item.item }} {{ item.count }}</p>
</div>
</div>
</a-col>
</a-row>
</div>
<!-- table区域-end -->
</a-card>
</template>
<script>
import { JeecgListMixin } from '@/mixins/JeecgListMixin'
import { dispatchCommunityRepairApi,repairStatistics } from '@/api/api'
import { REPAIR_STATUS, filterDictTextByStatic } from '@/assets/static.js'
import Pie from '@/components/chart/Pie'
const columns = [
{
title: '报修单号',
dataIndex: 'id',
key: 'id',
width: 170,
align: 'center',
ellipsis: true,
},
// {
// title: '报修地址',
// dataIndex: 'repairAddress',
// key: 'repairAddress',
// align: 'center',
// ellipsis: true
// },
{
title: '报修物品',
dataIndex: 'repairArticle',
key: 'repairArticle',
align: 'center',
},
{
title: '报修人',
dataIndex: 'ownerName',
scopedSlots: { customRender: 'ownerName' },
align: 'center',
},
{
title: '工单状态',
dataIndex: 'repairStatus',
key: 'repairStatus',
align: 'center',
customRender: function (text) {
return filterDictTextByStatic(REPAIR_STATUS, text)
},
},
{
title: '报修时间',
dataIndex: 'createTime',
key: 'createTime',
align: 'center',
},
// {
// title: '维修员',
// dataIndex: 'maintenanceName',
// key: 'maintenanceName',
// align: 'center'
// }
]
let currentDispathId = ''
export default {
name: 'PermissionListAsync',
mixins: [JeecgListMixin],
components: {Pie },
data() {
return {
repairStatus: REPAIR_STATUS,
// 表头
columns: columns,
url: {
list: '/property-community/property/communityRepair/list'
},
repairData:[],
totalNum:0
}
},
created() {
this.onDetail()
},
methods: {
async onDetail(typeCode) {
let { result } = await repairStatistics({ typeCode: typeCode })
this.totalNum = result.totalNum
this.repairData = [
// { item: '全部报修', count: result.repairTotal || 0 },
// { item: '待派单', count: result.waitDispatch || 0 },
{ item: '未完成', count: result.incompleteNum|| 0 },
{ item: '已完成', count: result.finishRepairNum || 0 },
]
},
onDispatch(id) {
currentDispathId = id
this.$nextTick(() => {
this.$refs.jPopupOnlReport.show()
})
},
async callBack(rows) {
let row = rows[0]
let res = await dispatchCommunityRepairApi({
id: currentDispathId,
maintainerId: row.id,
maintenanceName: row.employeeName,
maintenancePhone: row.employeePhone,
})
this.$message.success(res.message)
this.searchQuery()
},
},
}
</script>
<style scoped>
@import '~@assets/less/common.less';
</style>
<style lang="less" scoped>
.number {
width: 80%;
margin: 0 10%;
display: flex;
justify-content: space-evenly;
p {
font-size: 14px;
margin: 0;
}
}
.pay-cost{
height: 506px;
}
.t-box {
background: #fff;
padding: 15px;
border: 1px solid #e8e8e8;
}
.box-title {
font-weight: bold;
margin-bottom: 15px;
display: inline-block;
padding-left: 10px;
border-left: 3px solid #1890ff;
height: 20px;
line-height: 20px;
}
</style>
\ No newline at end of file
<template>
<j-modal
:title="title"
:width="width"
:visible="visible"
switchFullscreen
@ok="handleOk"
:okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
@cancel="handleCancel"
cancelText="关闭">
<property-settled-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit"></property-settled-form>
</j-modal>
</template>
<script>
import PropertySettledForm from './NoticeForm'
export default {
name: 'PropertySettledModal',
components: {
PropertySettledForm
},
data () {
return {
title:'',
width: '70%',
visible: false,
disableSubmit: false
}
},
methods: {
add () {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.add();
})
},
edit (record) {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.edit(record);
})
},
close () {
this.$emit('close');
this.visible = false;
},
handleOk () {
this.$refs.realForm.submitForm();
},
submitCallback(){
this.$emit('ok');
this.visible = false;
},
handleCancel () {
this.close()
}
}
}
</script>
\ No newline at end of file
<template>
<a-spin :spinning="confirmLoading">
<j-form-container :disabled="formDisabled">
<a-form-model ref="form" :model="model" :rules="validatorRules" slot="detail">
<a-row>
<a-col :span="12">
<a-form-model-item label="报修物品" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="repairArticle">
<a-input v-model="model.repairArticle" placeholder="请输入报修物品"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="报修地址" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="repairAddress">
<a-input v-model="model.repairAddress" placeholder="请输入报修地址"></a-input>
</a-form-model-item>
</a-col>
<a-col :span="12">
<a-form-model-item label="预约上门时间" :labelCol="labelCol" :wrapperCol="wrapperCol" prop="reservationTime">
<j-date style="width:100%" v-model="model.reservationTime" placeholder="请选择预约上门时间" :showTime="true" dateFormat="YYYY-MM-DD HH:mm:ss"/>
</a-form-model-item>
</a-col>
</a-row>
<a-row>
<a-col :span="24">
<a-form-model-item label="报修描述" :labelCol="{ xs:{ span: 24 }, sm:{ span: 3 } }" :wrapperCol="wrapperCol" prop="repairDesc">
<a-textarea placeholder="请输入报修描述" v-model="model.repairDesc" :auto-size="{ minRows: 3, maxRows: 5 }" allow-clear />
</a-form-model-item>
</a-col>
</a-row>
<a-row>
<a-col :span="24">
<a-form-model-item label="报修图片" :labelCol="{ xs:{ span: 24 }, sm:{ span: 3 } }" :wrapperCol="wrapperCol" prop="repairPhoto">
<j-image-upload :isMultiple="false" text="点击上传" bizPath="scott/pic" v-model="model.repairPhoto"></j-image-upload>
</a-form-model-item>
</a-col>
</a-row>
</a-form-model>
</j-form-container>
</a-spin>
</template>
<script>
import { httpAction, getAction } from '@/api/manage'
import { validateDuplicateValue } from '@/utils/util'
import {ajaxGetDictItems,getDictItemsFromCache} from '@/api/api'
export default {
name: 'PropertyChargruleForm',
components: {
},
props: {
//表单禁用
disabled: {
type: Boolean,
default: false,
required: false
}
},
data () {
return {
dictOptions: [],
model:{
repairArticle: '',
repairAddress: '',
reservationTime: '',
repairDesc: '',
repairPhoto: ''
},
labelCol: {
xs: { span: 24 },
sm: { span: 6 },
},
wrapperCol: {
xs: { span: 24 },
sm: { span: 16 },
},
confirmLoading: false,
validatorRules: {
repairArticle: [{ required: true, message: '请输入报修物品', trigger: 'blur' }],
employeeDuties: [{ required: true, message: '请输入报修地址', trigger: 'change' }],
reservationTime: [{ required: true, message: '请选择预约上门时间', trigger: 'change' }],
},
url: {
add: "/property-community/property/communityRepair/add",
edit: "/property-community/property/communityRepair/edit",
queryById: "/property-community/property/communityRepair/queryById"
}
}
},
computed: {
formDisabled(){
return this.disabled
},
},
created () {
//备份model原始值
this.modelDefault = JSON.parse(JSON.stringify(this.model));
this.initDictData()
},
methods: {
initDictData() {
//优先从缓存中读取字典配置
if(getDictItemsFromCache('duties')){
this.dictOptions = getDictItemsFromCache('duties');
return
}
// //根据字典Code, 初始化字典数组
ajaxGetDictItems('duties', null).then((res) => {
if (res.success) {
this.dictOptions = res.result;
}
})
},
ruleNumberInput(event) {
let rateValue = event.target.value.replace(/[^\d]/g,"");//清除"数字"和"."和"-"以外的字符
this.model['empowerDays'] = rateValue
},
add () {
this.edit(this.modelDefault);
},
edit (record) {
console.log(record)
this.model = Object.assign({}, record);
this.visible = true;
},
submitForm () {
const that = this;
// 触发表单验证
this.$refs.form.validate(valid => {
if (valid) {
that.confirmLoading = true;
let httpurl = '';
let method = '';
if(!this.model.id){
httpurl+=this.url.add;
method = 'post';
}else{
httpurl+=this.url.edit;
method = 'put';
}
httpAction(httpurl,this.model,method).then((res)=>{
if(res.success){
that.$message.success(res.message);
that.$emit('ok');
}else{
that.$message.warning(res.message);
}
}).finally(() => {
that.confirmLoading = false;
})
}
})
},
}
}
</script>
\ No newline at end of file
<template>
<j-modal
:title="title"
:width="width"
:visible="visible"
switchFullscreen
@ok="handleOk"
:okButtonProps="{ class:{'jee-hidden': disableSubmit} }"
@cancel="handleCancel"
cancelText="关闭">
<property-settled-form ref="realForm" @ok="submitCallback" :disabled="disableSubmit"></property-settled-form>
</j-modal>
</template>
<script>
import PropertySettledForm from './NoticeForm'
export default {
name: 'PropertySettledModal',
components: {
PropertySettledForm
},
data () {
return {
title:'',
width: '70%',
visible: false,
disableSubmit: false
}
},
methods: {
add () {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.add();
})
},
edit (record) {
this.visible=true
this.$nextTick(()=>{
this.$refs.realForm.edit(record);
})
},
close () {
this.$emit('close');
this.visible = false;
},
handleOk () {
this.$refs.realForm.submitForm();
},
submitCallback(){
this.$emit('ok');
this.visible = false;
},
handleCancel () {
this.close()
}
}
}
</script>
\ No newline at end of file
<template>
<div class="hone-content-box">
<a-row :gutter="24">
<a-col :sm="24" :md="12" :xl="4" :style="{ marginBottom: '24px' }">
<div class="statistics">
<div class="icon" style="background-color:#1890ff;"><a-icon type="team" /></div>
<div>
<p style="color:#666;margin-bottom:5px;">总人口</p>
<p style="margin-bottom:0;color:#333;font-size:28px;line-height:1;">{{pageForm.ownerTotalNum}}</p>
</div>
</div>
</a-col>
<a-col :sm="24" :md="12" :xl="4" :style="{ marginBottom: '24px' }">
<div class="statistics">
<div class="icon" style="background-color:#7262fd;"><a-icon type="home" /></div>
<div>
<p style="color:#666;margin-bottom:5px;">业主</p>
<p style="margin-bottom:0;color:#333;font-size:28px;line-height:1;">{{pageForm.ownerNum}}</p>
</div>
</div>
</a-col>
<a-col :sm="24" :md="12" :xl="4" :style="{ marginBottom: '24px' }">
<div class="statistics">
<div class="icon" style="background-color:#ffaa00;"><a-icon type="user" /></div>
<div>
<p style="color:#666;margin-bottom:5px;">租客</p>
<p style="margin-bottom:0;color:#333;font-size:28px;line-height:1;">{{pageForm.tenantNum}}</p>
</div>
</div>
</a-col>
<a-col :sm="24" :md="12" :xl="4" :style="{ marginBottom: '24px' }">
<div class="statistics">
<div class="icon" style="background-color:#52c41a;"><a-icon type="bank" /></div>
<div>
<p style="color:#666;margin-bottom:5px;">房屋数量</p>
<p style="margin-bottom:0;color:#333;font-size:28px;line-height:1;">{{pageForm.roomNum}}</p>
</div>
</div>
</a-col>
<a-col :sm="24" :md="12" :xl="4" :style="{ marginBottom: '24px' }">
<div class="statistics">
<div class="icon" style="background-color:#36cfc9;"><a-icon type="appstore" /></div>
<div>
<p style="color:#666;margin-bottom:5px;">单元数量</p>
<p style="margin-bottom:0;color:#333;font-size:28px;line-height:1;">{{pageForm.unitNum}}</p>
</div>
</div>
</a-col>
<a-col :sm="24" :md="12" :xl="4" :style="{ marginBottom: '24px' }">
<div class="statistics">
<div class="icon" style="background-color:#ff7875;"><a-icon type="database" /></div>
<div>
<p style="color:#666;margin-bottom:5px;">楼栋数量</p>
<p style="margin-bottom:0;color:#333;font-size:28px;line-height:1;">{{pageForm.buildingNum}}</p>
</div>
</div>
</a-col>
</a-row>
<a-row :gutter="24">
<a-col :sm="24" :md="12" :xl="12" :style="{ marginBottom: '24px' }">
<div class="pay-cost t-box">
<pie :dataSource="repairData" />
</div>
</a-col>
<a-col :sm="24" :md="12" :xl="12" :style="{ marginBottom: '24px' }">
<div class="pay-cost t-box">
<pie :dataSource="complaintsData" />
</div>
</a-col>
</a-row>
<a-row :gutter="24">
<a-col :sm="24" :md="24" :xl="24" :style="{ marginBottom: '24px' }">
<div class="salesCard t-box">
<!-- <h3 class="box-title">缴费统计</h3> -->
<div class="extra-type">
<a-radio-group @change="handleSizeChange" :value="typeCode">
<a-radio-button value="1">已缴纳总金额</a-radio-button>
<a-radio-button value="2">未缴纳总金额</a-radio-button>
<a-radio-button value="3">已缴纳业主</a-radio-button>
<a-radio-button value="4">未缴纳业主</a-radio-button>
</a-radio-group>
</div>
<div>
<bar :dataSource="barData" style="padding: 0;" />
</div>
</div>
</a-col>
</a-row>
</div>
</template>
<script>
import Bar from '@/components/chart/Bar'
import Pie from '@/components/chart/Pie'
import { propertyFeeStatistics, companyNoticeList } from '@/api/api'
// const barData = []
// for (let i = 0; i < 12; i += 1) {
// barData.push({
// x: `${i + 1}月`,
// y: 1000,
// })
// }
export default {
name: 'Analysis',
components: {
Bar,
Pie,
},
data() {
return {
pageForm: {},
loading: true,
noticeList: [],
typeCode: '2',
repairData: [],
complaintsData: [],
barData: [],
visible: false,
}
},
created() {
this.onDetail('2')
},
methods: {
async onDetail(typeCode) {
console.log(typeCode)
let { result } = await propertyFeeStatistics({ beginDate: '',endDate:'' })
this.pageForm = { ...result }
this.barData = result.monthlyStatistics.map((item) => {
var num = '';
if(typeCode == '1'){
num = item.paidTotal
}else if(typeCode == '2'){
num = item.unPaidTotal
}else if(typeCode == '3'){
num = item.paidOwnerNum
}else if(typeCode == '4'){
num = item.unPaidOwnerNum
}
return {
x: item.monthNum + '月',
y: num
}
})
this.repairData = [
{ item: '未缴总金额', count: result.unPaidTotal || 0 },
{ item: '已缴总金额', count: result.paidTotal || 0 },
]
this.complaintsData = [
{ item: '未缴纳业主', count: result.unPaidOwnerNum || 0 },
{ item: '已缴纳业主', count: result.paidOwnerNum || 0 },
]
this.loading = !this.loading
},
handleSizeChange(e) {
let that = this
this.typeCode = e.target.value
that.onDetail(this.typeCode)
},
},
}
</script>
<style lang="less" scoped>
.hone-content-box {
padding: 10px;
.statistics {
// flex: none;
background: #fff;
width: 100%;
height: 90px;
box-sizing: border-box;
border: 1px solid #e0dfdf;
display: flex;
align-items: center;
padding-left: 20px;
.icon {
width: 50px;
height: 50px;
border-radius: 50px;
margin-right: 12px;
display: flex;
text-align: center;
align-items: center;
justify-content: center;
.anticon {
font-size: 26px;
color: #ffffff;
}
}
}
.pay-box {
display: flex;
.left-box {
flex: none;
width: 50%;
}
}
}
.t-box {
background: #fff;
padding: 15px;
border: 1px solid #e0dfdf;
}
.box-title {
font-weight: bold;
margin-bottom: 15px;
display: inline-block;
padding-left: 10px;
border-left: 3px solid #1890ff;
height: 20px;
line-height: 20px;
}
.pay-cost {
height: 260px;
padding: 30px 0;
}
.salesCard {
height: 380px;
padding-top: 50px;
}
.extra-type {
text-align: center;
a {
margin-right: 20px;
}
}
.number {
width: 80%;
margin: 0 10%;
display: flex;
justify-content: space-evenly;
p {
font-size: 14px;
margin: 0;
}
}
</style>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论