Commit 95629508a2c5d0ad943f1f3fde8bf73e93e045e3
1 parent
51f9221a
继续开发报表功能
Showing
23 changed files
with
3129 additions
and
7 deletions
src/api/report/reportNoFeeRoomApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 3 | + | |
| 4 | +// 查询未收费房屋列表 | |
| 5 | +export function queryNoFeeRooms(params) { | |
| 6 | + return new Promise((resolve, reject) => { | |
| 7 | + request({ | |
| 8 | + url: '/reportFeeMonthStatistics/queryNoFeeRooms', | |
| 9 | + method: 'get', | |
| 10 | + params: { | |
| 11 | + ...params, | |
| 12 | + communityId: params.communityId || getCommunityId() | |
| 13 | + } | |
| 14 | + }).then(response => { | |
| 15 | + const res = response.data | |
| 16 | + resolve({ | |
| 17 | + data: res.data, | |
| 18 | + total: res.total | |
| 19 | + }) | |
| 20 | + }).catch(error => { | |
| 21 | + reject(error) | |
| 22 | + }) | |
| 23 | + }) | |
| 24 | +} | |
| 25 | + | |
| 26 | +// 查询楼栋列表 | |
| 27 | +export function queryFloors(params) { | |
| 28 | + return new Promise((resolve, reject) => { | |
| 29 | + request({ | |
| 30 | + url: '/floor.queryFloors', | |
| 31 | + method: 'get', | |
| 32 | + params: { | |
| 33 | + ...params, | |
| 34 | + communityId: params.communityId || getCommunityId() | |
| 35 | + } | |
| 36 | + }).then(response => { | |
| 37 | + const res = response.data | |
| 38 | + resolve(res.apiFloorDataVoList || []) | |
| 39 | + }).catch(error => { | |
| 40 | + reject(error) | |
| 41 | + }) | |
| 42 | + }) | |
| 43 | +} | |
| 44 | + | |
| 45 | +// 查询单元列表 | |
| 46 | +export function queryUnits(params) { | |
| 47 | + return new Promise((resolve, reject) => { | |
| 48 | + request({ | |
| 49 | + url: '/unit.queryUnits', | |
| 50 | + method: 'get', | |
| 51 | + params: { | |
| 52 | + ...params, | |
| 53 | + communityId: params.communityId || getCommunityId() | |
| 54 | + } | |
| 55 | + }).then(response => { | |
| 56 | + const res = response.data | |
| 57 | + resolve(res || []) | |
| 58 | + }).catch(error => { | |
| 59 | + reject(error) | |
| 60 | + }) | |
| 61 | + }) | |
| 62 | +} | |
| 63 | + | |
| 64 | +// 查询房屋列表 | |
| 65 | +export function queryRooms(params) { | |
| 66 | + return new Promise((resolve, reject) => { | |
| 67 | + request({ | |
| 68 | + url: '/room.queryRooms', | |
| 69 | + method: 'get', | |
| 70 | + params: { | |
| 71 | + ...params, | |
| 72 | + communityId: params.communityId || getCommunityId() | |
| 73 | + } | |
| 74 | + }).then(response => { | |
| 75 | + const res = response.data | |
| 76 | + resolve(res || { rooms: [] }) | |
| 77 | + }).catch(error => { | |
| 78 | + reject(error) | |
| 79 | + }) | |
| 80 | + }) | |
| 81 | +} | |
| 82 | + | |
| 83 | +// 导出数据 | |
| 84 | +export function exportData(params) { | |
| 85 | + return new Promise((resolve, reject) => { | |
| 86 | + request({ | |
| 87 | + url: '/export.exportData', | |
| 88 | + method: 'get', | |
| 89 | + params: { | |
| 90 | + ...params, | |
| 91 | + communityId: params.communityId || getCommunityId() | |
| 92 | + } | |
| 93 | + }).then(response => { | |
| 94 | + const res = response.data | |
| 95 | + resolve(res) | |
| 96 | + }).catch(error => { | |
| 97 | + reject(error) | |
| 98 | + }) | |
| 99 | + }) | |
| 100 | +} | |
| 0 | 101 | \ No newline at end of file | ... | ... |
src/api/report/reportOweFeeDetailApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +// 查询欠费明细 | |
| 4 | +export function queryOweFeeDetail(params) { | |
| 5 | + return new Promise((resolve, reject) => { | |
| 6 | + request({ | |
| 7 | + url: '/reportFeeMonthStatistics/queryOweFeeDetail', | |
| 8 | + method: 'get', | |
| 9 | + params | |
| 10 | + }).then(response => { | |
| 11 | + const res = response.data | |
| 12 | + resolve(res) | |
| 13 | + }).catch(error => { | |
| 14 | + reject(error) | |
| 15 | + }) | |
| 16 | + }) | |
| 17 | +} | |
| 18 | + | |
| 19 | +// 导出数据 | |
| 20 | +export function exportData(params) { | |
| 21 | + return new Promise((resolve, reject) => { | |
| 22 | + request({ | |
| 23 | + url: '/export.exportData', | |
| 24 | + method: 'get', | |
| 25 | + params | |
| 26 | + }).then(response => { | |
| 27 | + const res = response.data | |
| 28 | + resolve(res) | |
| 29 | + }).catch(error => { | |
| 30 | + reject(error) | |
| 31 | + }) | |
| 32 | + }) | |
| 33 | +} | |
| 0 | 34 | \ No newline at end of file | ... | ... |
src/api/report/reportOwnerPayFeeApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 3 | + | |
| 4 | +// 查询业主缴费明细报表 | |
| 5 | +export function queryReportOwnerPayFee(params) { | |
| 6 | + return new Promise((resolve, reject) => { | |
| 7 | + const communityId = getCommunityId() | |
| 8 | + request({ | |
| 9 | + url: '/reportOwnerPayFee/queryReportOwnerPayFee', | |
| 10 | + method: 'get', | |
| 11 | + params: { | |
| 12 | + ...params, | |
| 13 | + communityId | |
| 14 | + } | |
| 15 | + }).then(response => { | |
| 16 | + const res = response.data | |
| 17 | + resolve(res) | |
| 18 | + }).catch(error => { | |
| 19 | + reject(error) | |
| 20 | + }) | |
| 21 | + }) | |
| 22 | +} | |
| 23 | + | |
| 24 | +// 查询收费项列表 | |
| 25 | +export function listFeeConfigs(params) { | |
| 26 | + return new Promise((resolve, reject) => { | |
| 27 | + const communityId = getCommunityId() | |
| 28 | + request({ | |
| 29 | + url: '/feeConfig.listFeeConfigs', | |
| 30 | + method: 'get', | |
| 31 | + params: { | |
| 32 | + ...params, | |
| 33 | + communityId | |
| 34 | + } | |
| 35 | + }).then(response => { | |
| 36 | + const res = response.data | |
| 37 | + resolve(res) | |
| 38 | + }).catch(error => { | |
| 39 | + reject(error) | |
| 40 | + }) | |
| 41 | + }) | |
| 42 | +} | |
| 0 | 43 | \ No newline at end of file | ... | ... |
src/api/report/reportPayFeeDetailApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +/** | |
| 4 | + * 查询缴费明细 | |
| 5 | + * @param {Object} params 查询参数 | |
| 6 | + * @returns {Promise} | |
| 7 | + */ | |
| 8 | +export function queryPayFeeDetail(params) { | |
| 9 | + return new Promise((resolve, reject) => { | |
| 10 | + request({ | |
| 11 | + url: '/reportFeeMonthStatistics/queryPayFeeDetail', | |
| 12 | + method: 'get', | |
| 13 | + params | |
| 14 | + }).then(response => { | |
| 15 | + const res = response.data | |
| 16 | + resolve({ | |
| 17 | + data: res.data, | |
| 18 | + total: res.total, | |
| 19 | + records: res.records, | |
| 20 | + sumTotal: res.sumTotal || {} | |
| 21 | + }) | |
| 22 | + }).catch(error => { | |
| 23 | + reject(error) | |
| 24 | + }) | |
| 25 | + }) | |
| 26 | +} | |
| 27 | + | |
| 28 | +/** | |
| 29 | + * 导出缴费明细数据 | |
| 30 | + * @param {Object} params 导出参数 | |
| 31 | + * @returns {Promise} | |
| 32 | + */ | |
| 33 | +export function exportData(params) { | |
| 34 | + return new Promise((resolve, reject) => { | |
| 35 | + request({ | |
| 36 | + url: '/export.exportData', | |
| 37 | + method: 'get', | |
| 38 | + params | |
| 39 | + }).then(response => { | |
| 40 | + const res = response.data | |
| 41 | + resolve(res) | |
| 42 | + }).catch(error => { | |
| 43 | + reject(error) | |
| 44 | + }) | |
| 45 | + }) | |
| 46 | +} | |
| 47 | + | |
| 48 | +/** | |
| 49 | + * 查询费用项列表 | |
| 50 | + * @param {Object} params 查询参数 | |
| 51 | + * @returns {Promise} | |
| 52 | + */ | |
| 53 | +export function listFeeConfigs(params) { | |
| 54 | + return new Promise((resolve, reject) => { | |
| 55 | + request({ | |
| 56 | + url: '/feeConfig.listFeeConfigs', | |
| 57 | + method: 'get', | |
| 58 | + params | |
| 59 | + }).then(response => { | |
| 60 | + const res = response.data | |
| 61 | + resolve({ | |
| 62 | + feeConfigs: res.feeConfigs || [] | |
| 63 | + }) | |
| 64 | + }).catch(error => { | |
| 65 | + reject(error) | |
| 66 | + }) | |
| 67 | + }) | |
| 68 | +} | |
| 69 | + | |
| 70 | +/** | |
| 71 | + * 查询小区列表 | |
| 72 | + * @param {Object} params 查询参数 | |
| 73 | + * @returns {Promise} | |
| 74 | + */ | |
| 75 | +export function listMyEnteredCommunitys(params) { | |
| 76 | + return new Promise((resolve, reject) => { | |
| 77 | + request({ | |
| 78 | + url: '/community.listMyEnteredCommunitys', | |
| 79 | + method: 'get', | |
| 80 | + params | |
| 81 | + }).then(response => { | |
| 82 | + const res = response.data | |
| 83 | + resolve({ | |
| 84 | + communitys: res.communitys || [] | |
| 85 | + }) | |
| 86 | + }).catch(error => { | |
| 87 | + reject(error) | |
| 88 | + }) | |
| 89 | + }) | |
| 90 | +} | |
| 0 | 91 | \ No newline at end of file | ... | ... |
src/api/report/reportQuestionAnswerDetailApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 3 | + | |
| 4 | +// 查询问卷回答明细 | |
| 5 | +export function queryUserQuestionAnswerValue(params) { | |
| 6 | + return new Promise((resolve, reject) => { | |
| 7 | + request({ | |
| 8 | + url: '/reportQuestionAnswer/queryUserQuestionAnswerValue', | |
| 9 | + method: 'get', | |
| 10 | + params: { | |
| 11 | + ...params, | |
| 12 | + communityId: params.communityId || getCommunityId() | |
| 13 | + } | |
| 14 | + }).then(response => { | |
| 15 | + const res = response.data | |
| 16 | + resolve(res) | |
| 17 | + }).catch(error => { | |
| 18 | + reject(error) | |
| 19 | + }) | |
| 20 | + }) | |
| 21 | +} | |
| 22 | + | |
| 23 | +// 导出问卷回答明细 | |
| 24 | +export function exportData(params) { | |
| 25 | + return new Promise((resolve, reject) => { | |
| 26 | + request({ | |
| 27 | + url: '/export.exportData', | |
| 28 | + method: 'get', | |
| 29 | + params: { | |
| 30 | + ...params, | |
| 31 | + communityId: params.communityId || getCommunityId() | |
| 32 | + } | |
| 33 | + }).then(response => { | |
| 34 | + const res = response.data | |
| 35 | + resolve(res) | |
| 36 | + }).catch(error => { | |
| 37 | + reject(error) | |
| 38 | + }) | |
| 39 | + }) | |
| 40 | +} | |
| 0 | 41 | \ No newline at end of file | ... | ... |
src/api/report/reportRepairApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +// 查询报修汇总数据 | |
| 4 | +export function queryRepair(params) { | |
| 5 | + return new Promise((resolve, reject) => { | |
| 6 | + request({ | |
| 7 | + url: '/reportFeeMonthStatistics/queryRepair', | |
| 8 | + method: 'get', | |
| 9 | + params | |
| 10 | + }).then(response => { | |
| 11 | + const res = response.data | |
| 12 | + resolve(res) | |
| 13 | + }).catch(error => { | |
| 14 | + reject(error) | |
| 15 | + }) | |
| 16 | + }) | |
| 17 | +} | |
| 18 | + | |
| 19 | +// 导出报修数据 | |
| 20 | +export function exportData(params) { | |
| 21 | + return new Promise((resolve, reject) => { | |
| 22 | + request({ | |
| 23 | + url: '/export.exportData', | |
| 24 | + method: 'get', | |
| 25 | + params | |
| 26 | + }).then(response => { | |
| 27 | + const res = response.data | |
| 28 | + resolve(res) | |
| 29 | + }).catch(error => { | |
| 30 | + reject(error) | |
| 31 | + }) | |
| 32 | + }) | |
| 33 | +} | |
| 34 | + | |
| 35 | +// 获取已入驻小区列表 | |
| 36 | +export function listMyEnteredCommunitys(params) { | |
| 37 | + return new Promise((resolve, reject) => { | |
| 38 | + request({ | |
| 39 | + url: '/community.listMyEnteredCommunitys', | |
| 40 | + method: 'get', | |
| 41 | + params | |
| 42 | + }).then(response => { | |
| 43 | + const res = response.data | |
| 44 | + resolve(res) | |
| 45 | + }).catch(error => { | |
| 46 | + reject(error) | |
| 47 | + }) | |
| 48 | + }) | |
| 49 | +} | |
| 0 | 50 | \ No newline at end of file | ... | ... |
src/api/room/searchFloorApi.js
| ... | ... | @@ -8,11 +8,8 @@ export function searchFloors(params) { |
| 8 | 8 | params |
| 9 | 9 | }).then(response => { |
| 10 | 10 | const res = response.data |
| 11 | - if (res.code === 0) { | |
| 12 | - resolve(res.data) | |
| 13 | - } else { | |
| 14 | - reject(new Error(res.msg || '查询楼栋失败')) | |
| 15 | - } | |
| 11 | + | |
| 12 | + resolve(res) | |
| 16 | 13 | }).catch(error => { |
| 17 | 14 | reject(error) |
| 18 | 15 | }) | ... | ... |
src/components/report/InputSearchOwner.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="input-search-owner"> | |
| 3 | + <el-popover placement="bottom" width="400" trigger="manual" v-model="visible"> | |
| 4 | + <div class="search-result-container"> | |
| 5 | + <div class="close-btn" @click="close"> | |
| 6 | + <i class="el-icon-close"></i> | |
| 7 | + </div> | |
| 8 | + <div class="search-item" v-for="(item, index) in owners" :key="index" @click="chooseOwner(item)"> | |
| 9 | + <span>{{ item.name }}</span> | |
| 10 | + <span class="separator">---</span> | |
| 11 | + <span>{{ item.link }}</span> | |
| 12 | + </div> | |
| 13 | + </div> | |
| 14 | + <el-button slot="reference" type="primary" icon="el-icon-search"></el-button> | |
| 15 | + </el-popover> | |
| 16 | + </div> | |
| 17 | +</template> | |
| 18 | + | |
| 19 | +<script> | |
| 20 | +import { queryOwners } from '@/api/owner/ownerApi' | |
| 21 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 22 | + | |
| 23 | +export default { | |
| 24 | + name: 'InputSearchOwner', | |
| 25 | + data() { | |
| 26 | + return { | |
| 27 | + visible: false, | |
| 28 | + owners: [], | |
| 29 | + searchParam: { | |
| 30 | + ownerName: '', | |
| 31 | + ownerTypeCd: '', | |
| 32 | + callComponent: '' | |
| 33 | + }, | |
| 34 | + communityId: '' | |
| 35 | + } | |
| 36 | + }, | |
| 37 | + created() { | |
| 38 | + this.communityId = getCommunityId() | |
| 39 | + }, | |
| 40 | + methods: { | |
| 41 | + open(param) { | |
| 42 | + this.searchParam = { ...param } | |
| 43 | + this.loadOwners() | |
| 44 | + this.visible = true | |
| 45 | + }, | |
| 46 | + close() { | |
| 47 | + this.visible = false | |
| 48 | + }, | |
| 49 | + async loadOwners() { | |
| 50 | + try { | |
| 51 | + const params = { | |
| 52 | + page: 1, | |
| 53 | + row: 10, | |
| 54 | + ownerTypeCd: this.searchParam.ownerTypeCd, | |
| 55 | + name: this.searchParam.ownerName, | |
| 56 | + communityId: this.communityId | |
| 57 | + } | |
| 58 | + | |
| 59 | + const { data } = await queryOwners(params) | |
| 60 | + this.owners = data.data || [] | |
| 61 | + if (this.owners.length === 0) { | |
| 62 | + this.$message.warning(this.$t('common.noData')) | |
| 63 | + } | |
| 64 | + } catch (error) { | |
| 65 | + console.error('查询业主失败:', error) | |
| 66 | + this.$message.error(this.$t('common.queryFailed')) | |
| 67 | + } | |
| 68 | + }, | |
| 69 | + chooseOwner(owner) { | |
| 70 | + this.$emit('notifyOwner', owner) | |
| 71 | + this.$emit('choose', owner) | |
| 72 | + this.close() | |
| 73 | + } | |
| 74 | + } | |
| 75 | +} | |
| 76 | +</script> | |
| 77 | + | |
| 78 | +<style lang="scss" scoped> | |
| 79 | +.input-search-owner { | |
| 80 | + display: inline-block; | |
| 81 | + | |
| 82 | + .search-result-container { | |
| 83 | + max-height: 300px; | |
| 84 | + overflow-y: auto; | |
| 85 | + padding: 10px; | |
| 86 | + | |
| 87 | + .close-btn { | |
| 88 | + text-align: right; | |
| 89 | + margin-bottom: 10px; | |
| 90 | + cursor: pointer; | |
| 91 | + | |
| 92 | + i { | |
| 93 | + font-size: 16px; | |
| 94 | + color: #999; | |
| 95 | + | |
| 96 | + &:hover { | |
| 97 | + color: #333; | |
| 98 | + } | |
| 99 | + } | |
| 100 | + } | |
| 101 | + | |
| 102 | + .search-item { | |
| 103 | + padding: 8px 10px; | |
| 104 | + border-bottom: 1px solid #eee; | |
| 105 | + cursor: pointer; | |
| 106 | + display: flex; | |
| 107 | + align-items: center; | |
| 108 | + | |
| 109 | + &:hover { | |
| 110 | + background-color: #f5f7fa; | |
| 111 | + } | |
| 112 | + | |
| 113 | + &:last-child { | |
| 114 | + border-bottom: none; | |
| 115 | + } | |
| 116 | + | |
| 117 | + .separator { | |
| 118 | + margin: 0 5px; | |
| 119 | + color: #ccc; | |
| 120 | + } | |
| 121 | + } | |
| 122 | + } | |
| 123 | + | |
| 124 | + .el-button { | |
| 125 | + padding: 10px; | |
| 126 | + } | |
| 127 | +} | |
| 128 | +</style> | |
| 0 | 129 | \ No newline at end of file | ... | ... |
src/components/report/InputSearchRoom.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="input-search-room"> | |
| 3 | + <el-popover placement="bottom" width="300" trigger="manual" v-model="visible"> | |
| 4 | + <div class="search-result-container"> | |
| 5 | + <div class="close-btn" @click="close"> | |
| 6 | + <i class="el-icon-close"></i> | |
| 7 | + </div> | |
| 8 | + <div class="search-item" v-for="(item, index) in rooms" :key="index" @click="chooseRoom(item)"> | |
| 9 | + <span>{{ item.floorNum }}-{{ item.unitNum }}-{{ item.roomNum }}</span> | |
| 10 | + </div> | |
| 11 | + </div> | |
| 12 | + <el-button slot="reference" type="primary" icon="el-icon-search"></el-button> | |
| 13 | + </el-popover> | |
| 14 | + </div> | |
| 15 | +</template> | |
| 16 | + | |
| 17 | +<script> | |
| 18 | +import { queryRooms } from '@/api/room/roomApi' | |
| 19 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 20 | + | |
| 21 | +export default { | |
| 22 | + name: 'InputSearchRoom', | |
| 23 | + data() { | |
| 24 | + return { | |
| 25 | + visible: false, | |
| 26 | + rooms: [], | |
| 27 | + searchParam: { | |
| 28 | + roomName: '', | |
| 29 | + callComponent: '' | |
| 30 | + }, | |
| 31 | + communityId: '' | |
| 32 | + } | |
| 33 | + }, | |
| 34 | + created() { | |
| 35 | + this.communityId = getCommunityId() | |
| 36 | + }, | |
| 37 | + methods: { | |
| 38 | + open(param) { | |
| 39 | + this.searchParam = { ...param } | |
| 40 | + this.loadRooms() | |
| 41 | + this.visible = true | |
| 42 | + }, | |
| 43 | + close() { | |
| 44 | + this.visible = false | |
| 45 | + }, | |
| 46 | + async loadRooms() { | |
| 47 | + try { | |
| 48 | + const params = { | |
| 49 | + page: 1, | |
| 50 | + row: 10, | |
| 51 | + flag: 1, | |
| 52 | + roomNum: this.searchParam.roomName, | |
| 53 | + communityId: this.communityId | |
| 54 | + } | |
| 55 | + | |
| 56 | + const { data } = await queryRooms(params) | |
| 57 | + this.rooms = data.rooms || [] | |
| 58 | + if (this.rooms.length === 0) { | |
| 59 | + this.$message.warning(this.$t('common.noData')) | |
| 60 | + } | |
| 61 | + } catch (error) { | |
| 62 | + console.error('查询房屋失败:', error) | |
| 63 | + this.$message.error(this.$t('common.queryFailed')) | |
| 64 | + } | |
| 65 | + }, | |
| 66 | + chooseRoom(room) { | |
| 67 | + this.$emit('notifyRoom', room) | |
| 68 | + this.$emit('choose', room) | |
| 69 | + this.close() | |
| 70 | + } | |
| 71 | + } | |
| 72 | +} | |
| 73 | +</script> | |
| 74 | + | |
| 75 | +<style lang="scss" scoped> | |
| 76 | +.input-search-room { | |
| 77 | + display: inline-block; | |
| 78 | + | |
| 79 | + .search-result-container { | |
| 80 | + max-height: 300px; | |
| 81 | + overflow-y: auto; | |
| 82 | + padding: 10px; | |
| 83 | + | |
| 84 | + .close-btn { | |
| 85 | + text-align: right; | |
| 86 | + margin-bottom: 10px; | |
| 87 | + cursor: pointer; | |
| 88 | + | |
| 89 | + i { | |
| 90 | + font-size: 16px; | |
| 91 | + color: #999; | |
| 92 | + | |
| 93 | + &:hover { | |
| 94 | + color: #333; | |
| 95 | + } | |
| 96 | + } | |
| 97 | + } | |
| 98 | + | |
| 99 | + .search-item { | |
| 100 | + padding: 8px 10px; | |
| 101 | + border-bottom: 1px solid #eee; | |
| 102 | + cursor: pointer; | |
| 103 | + | |
| 104 | + &:hover { | |
| 105 | + background-color: #f5f7fa; | |
| 106 | + } | |
| 107 | + | |
| 108 | + &:last-child { | |
| 109 | + border-bottom: none; | |
| 110 | + } | |
| 111 | + } | |
| 112 | + } | |
| 113 | + | |
| 114 | + .el-button { | |
| 115 | + padding: 10px; | |
| 116 | + } | |
| 117 | +} | |
| 118 | +</style> | |
| 0 | 119 | \ No newline at end of file | ... | ... |
src/i18n/reportI18n.js
| ... | ... | @@ -10,6 +10,12 @@ import { messages as reportFeeSummaryMessages } from '../views/report/reportFeeS |
| 10 | 10 | import { messages as reportFeeDetailMessages } from '../views/report/reportFeeDetailLang' |
| 11 | 11 | import { messages as feeRemindMessages } from '../views/report/feeRemindLang' |
| 12 | 12 | import { messages as dataReportMessages } from '../views/report/dataReportLang' |
| 13 | +import { messages as reportOweFeeDetailMessages } from '../views/report/reportOweFeeDetailLang' | |
| 14 | +import { messages as reportPayFeeDetailMessages } from '../views/report/reportPayFeeDetailLang' | |
| 15 | +import { messages as reportRepairMessages } from '../views/report/reportRepairLang' | |
| 16 | +import { messages as reportNoFeeRoomMessages } from '../views/report/reportNoFeeRoomLang' | |
| 17 | +import { messages as reportQuestionAnswerDetailMessages } from '../views/report/reportQuestionAnswerDetailLang' | |
| 18 | +import { messages as reportOwnerPayFeeMessages } from '../views/report/reportOwnerPayFeeLang' | |
| 13 | 19 | |
| 14 | 20 | export const messages = { |
| 15 | 21 | en: { |
| ... | ... | @@ -24,6 +30,12 @@ export const messages = { |
| 24 | 30 | ...reportFeeDetailMessages.en, |
| 25 | 31 | ...feeRemindMessages.en, |
| 26 | 32 | ...dataReportMessages.en, |
| 33 | + ...reportOweFeeDetailMessages.en, | |
| 34 | + ...reportPayFeeDetailMessages.en, | |
| 35 | + ...reportRepairMessages.en, | |
| 36 | + ...reportNoFeeRoomMessages.en, | |
| 37 | + ...reportQuestionAnswerDetailMessages.en, | |
| 38 | + ...reportOwnerPayFeeMessages.en, | |
| 27 | 39 | }, |
| 28 | 40 | zh: { |
| 29 | 41 | ...reportCustomComponentRelManageMessages.zh, |
| ... | ... | @@ -36,5 +48,11 @@ export const messages = { |
| 36 | 48 | ...reportFeeDetailMessages.zh, |
| 37 | 49 | ...feeRemindMessages.zh, |
| 38 | 50 | ...dataReportMessages.zh, |
| 51 | + ...reportOweFeeDetailMessages.zh, | |
| 52 | + ...reportPayFeeDetailMessages.zh, | |
| 53 | + ...reportRepairMessages.zh, | |
| 54 | + ...reportNoFeeRoomMessages.zh, | |
| 55 | + ...reportQuestionAnswerDetailMessages.zh, | |
| 56 | + ...reportOwnerPayFeeMessages.zh, | |
| 39 | 57 | } |
| 40 | 58 | } |
| 41 | 59 | \ No newline at end of file | ... | ... |
src/router/reportRouter.js
| ... | ... | @@ -20,9 +20,39 @@ export default [ |
| 20 | 20 | component: () => import('@/views/report/feeRemindList.vue') |
| 21 | 21 | }, |
| 22 | 22 | { |
| 23 | - path:'/pages/report/dataReport', | |
| 24 | - name:'/pages/report/dataReport', | |
| 23 | + path: '/pages/report/dataReport', | |
| 24 | + name: '/pages/report/dataReport', | |
| 25 | 25 | component: () => import('@/views/report/dataReportList.vue') |
| 26 | + }, | |
| 27 | + { | |
| 28 | + path: '/pages/property/reportOweFeeDetail', | |
| 29 | + name: '/pages/property/reportOweFeeDetail', | |
| 30 | + component: () => import('@/views/report/reportOweFeeDetailList.vue') | |
| 31 | + }, | |
| 32 | + { | |
| 33 | + path: '/pages/property/reportPayFeeDetail', | |
| 34 | + name: '/pages/property/reportPayFeeDetail', | |
| 35 | + component: () => import('@/views/report/reportPayFeeDetailList.vue') | |
| 36 | + }, | |
| 37 | + { | |
| 38 | + path: '/pages/property/reportRepair', | |
| 39 | + name: '/pages/property/reportRepair', | |
| 40 | + component: () => import('@/views/report/reportRepairList.vue') | |
| 41 | + }, | |
| 42 | + { | |
| 43 | + path: '/pages/property/reportNoFeeRoom', | |
| 44 | + name: '/pages/property/reportNoFeeRoom', | |
| 45 | + component: () => import('@/views/report/reportNoFeeRoomList.vue') | |
| 46 | + }, | |
| 47 | + { | |
| 48 | + path: '/pages/property/reportQuestionAnswerDetail', | |
| 49 | + name: '/pages/property/reportQuestionAnswerDetail', | |
| 50 | + component: () => import('@/views/report/reportQuestionAnswerDetailList.vue') | |
| 51 | + }, | |
| 52 | + { | |
| 53 | + path:'/pages/property/reportOwnerPayFee', | |
| 54 | + name:'/pages/property/reportOwnerPayFee', | |
| 55 | + component: () => import('@/views/report/reportOwnerPayFeeList.vue') | |
| 26 | 56 | }, |
| 27 | 57 | |
| 28 | 58 | ] |
| 29 | 59 | \ No newline at end of file | ... | ... |
src/views/report/reportNoFeeRoomLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + reportNoFeeRoom: { | |
| 4 | + search: { | |
| 5 | + title: 'Search Conditions', | |
| 6 | + floor: 'Select Building', | |
| 7 | + unit: 'Select Unit', | |
| 8 | + room: 'Select Room', | |
| 9 | + ownerName: 'Owner Name', | |
| 10 | + link: 'Owner Phone' | |
| 11 | + }, | |
| 12 | + list: { | |
| 13 | + title: 'No Fee Rooms', | |
| 14 | + tooltip: 'Rooms not associated with fee items' | |
| 15 | + }, | |
| 16 | + table: { | |
| 17 | + index: 'No.', | |
| 18 | + floor: 'Building', | |
| 19 | + unit: 'Unit', | |
| 20 | + room: 'Room', | |
| 21 | + ownerName: 'Owner Name', | |
| 22 | + link: 'Owner Phone' | |
| 23 | + }, | |
| 24 | + exportSuccess: 'Export started successfully', | |
| 25 | + exportFailed: 'Export failed' | |
| 26 | + } | |
| 27 | + }, | |
| 28 | + zh: { | |
| 29 | + reportNoFeeRoom: { | |
| 30 | + search: { | |
| 31 | + title: '查询条件', | |
| 32 | + floor: '请选择楼栋', | |
| 33 | + unit: '请选择单元', | |
| 34 | + room: '请选择房屋', | |
| 35 | + ownerName: '业主名称', | |
| 36 | + link: '业主电话' | |
| 37 | + }, | |
| 38 | + list: { | |
| 39 | + title: '未收费房屋', | |
| 40 | + tooltip: '未关联收费项的房屋信息' | |
| 41 | + }, | |
| 42 | + table: { | |
| 43 | + index: '序号', | |
| 44 | + floor: '楼栋', | |
| 45 | + unit: '单元', | |
| 46 | + room: '房屋', | |
| 47 | + ownerName: '业主名称', | |
| 48 | + link: '业主电话' | |
| 49 | + }, | |
| 50 | + exportSuccess: '导出任务已开始', | |
| 51 | + exportFailed: '导出失败' | |
| 52 | + } | |
| 53 | + } | |
| 54 | +} | |
| 0 | 55 | \ No newline at end of file | ... | ... |
src/views/report/reportNoFeeRoomList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="report-no-fee-room-container animated fadeInRight"> | |
| 3 | + <el-row :gutter="20"> | |
| 4 | + <el-col :span="24"> | |
| 5 | + <el-card class="search-card"> | |
| 6 | + <div slot="header" class="flex justify-between"> | |
| 7 | + <span>{{ $t('reportNoFeeRoom.search.title') }}</span> | |
| 8 | + </div> | |
| 9 | + <el-row :gutter="20"> | |
| 10 | + <el-col :span="4"> | |
| 11 | + <el-select v-model="searchForm.floorId" :placeholder="$t('reportNoFeeRoom.search.floor')" | |
| 12 | + @change="handleFloorChange" style="width:100%"> | |
| 13 | + <el-option v-for="item in floors" :key="item.floorId" :label="item.floorName" :value="item.floorId" /> | |
| 14 | + </el-select> | |
| 15 | + </el-col> | |
| 16 | + <el-col :span="4"> | |
| 17 | + <el-select v-model="searchForm.unitId" :placeholder="$t('reportNoFeeRoom.search.unit')" | |
| 18 | + @change="handleUnitChange" style="width:100%"> | |
| 19 | + <el-option v-for="item in units" :key="item.unitId" | |
| 20 | + :label="`${item.unitNum}${$t('reportNoFeeRoom.search.unit')}`" :value="item.unitId" /> | |
| 21 | + </el-select> | |
| 22 | + </el-col> | |
| 23 | + <el-col :span="4"> | |
| 24 | + <el-select v-model="searchForm.roomId" :placeholder="$t('reportNoFeeRoom.search.room')" style="width:100%"> | |
| 25 | + <el-option v-for="item in rooms" :key="item.roomId" | |
| 26 | + :label="`${item.roomNum}${$t('reportNoFeeRoom.search.room')}`" :value="item.roomId" /> | |
| 27 | + </el-select> | |
| 28 | + </el-col> | |
| 29 | + <el-col :span="4"> | |
| 30 | + <el-input v-model="searchForm.ownerName" :placeholder="$t('reportNoFeeRoom.search.ownerName')" clearable /> | |
| 31 | + </el-col> | |
| 32 | + <el-col :span="4"> | |
| 33 | + <el-input v-model="searchForm.link" :placeholder="$t('reportNoFeeRoom.search.link')" clearable /> | |
| 34 | + </el-col> | |
| 35 | + <el-col :span="4"> | |
| 36 | + <el-button type="primary" @click="handleSearch"> | |
| 37 | + <i class="el-icon-search"></i> | |
| 38 | + {{ $t('common.search') }} | |
| 39 | + </el-button> | |
| 40 | + <el-button @click="handleReset" style="margin-left:10px;"> | |
| 41 | + <i class="el-icon-refresh"></i> | |
| 42 | + {{ $t('common.reset') }} | |
| 43 | + </el-button> | |
| 44 | + </el-col> | |
| 45 | + </el-row> | |
| 46 | + </el-card> | |
| 47 | + </el-col> | |
| 48 | + </el-row> | |
| 49 | + | |
| 50 | + <el-row :gutter="20" style="margin-top:20px;"> | |
| 51 | + <el-col :span="24"> | |
| 52 | + <el-card> | |
| 53 | + <div slot="header" class="flex justify-between "> | |
| 54 | + <div> | |
| 55 | + <span>{{ $t('reportNoFeeRoom.list.title') }}</span> | |
| 56 | + <el-tooltip class="item" effect="dark" :content="$t('reportNoFeeRoom.list.tooltip')" placement="top"> | |
| 57 | + <i class="el-icon-info" style="margin-left:10px;cursor:pointer;"></i> | |
| 58 | + </el-tooltip> | |
| 59 | + </div> | |
| 60 | + <el-button type="primary" size="small" style="float:right;" @click="handleExport"> | |
| 61 | + <i class="el-icon-download"></i> | |
| 62 | + {{ $t('common.export') }} | |
| 63 | + </el-button> | |
| 64 | + </div> | |
| 65 | + | |
| 66 | + <el-table :data="tableData" border style="width:100%" v-loading="loading"> | |
| 67 | + <el-table-column prop="index" :label="$t('reportNoFeeRoom.table.index')" width="80" align="center" /> | |
| 68 | + <el-table-column prop="floorNum" :label="$t('reportNoFeeRoom.table.floor')" align="center" /> | |
| 69 | + <el-table-column prop="unitNum" :label="$t('reportNoFeeRoom.table.unit')" align="center" /> | |
| 70 | + <el-table-column prop="roomNum" :label="$t('reportNoFeeRoom.table.room')" align="center" /> | |
| 71 | + <el-table-column prop="ownerName" :label="$t('reportNoFeeRoom.table.ownerName')" align="center" /> | |
| 72 | + <el-table-column prop="link" :label="$t('reportNoFeeRoom.table.link')" align="center" /> | |
| 73 | + </el-table> | |
| 74 | + | |
| 75 | + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" | |
| 76 | + :current-page="pagination.current" :page-sizes="[10, 20, 30, 50]" :page-size="pagination.size" | |
| 77 | + layout="total, sizes, prev, pager, next, jumper" :total="pagination.total" style="margin-top:20px;" /> | |
| 78 | + </el-card> | |
| 79 | + </el-col> | |
| 80 | + </el-row> | |
| 81 | + </div> | |
| 82 | +</template> | |
| 83 | + | |
| 84 | +<script> | |
| 85 | +import { queryNoFeeRooms, queryFloors, queryUnits, queryRooms, exportData } from '@/api/report/reportNoFeeRoomApi' | |
| 86 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 87 | + | |
| 88 | +export default { | |
| 89 | + name: 'ReportNoFeeRoomList', | |
| 90 | + data() { | |
| 91 | + return { | |
| 92 | + loading: false, | |
| 93 | + searchForm: { | |
| 94 | + floorId: '', | |
| 95 | + unitId: '', | |
| 96 | + roomId: '', | |
| 97 | + ownerName: '', | |
| 98 | + link: '', | |
| 99 | + communityId: '' | |
| 100 | + }, | |
| 101 | + floors: [], | |
| 102 | + units: [], | |
| 103 | + rooms: [], | |
| 104 | + tableData: [], | |
| 105 | + pagination: { | |
| 106 | + current: 1, | |
| 107 | + size: 10, | |
| 108 | + total: 0 | |
| 109 | + } | |
| 110 | + } | |
| 111 | + }, | |
| 112 | + created() { | |
| 113 | + this.searchForm.communityId = getCommunityId() | |
| 114 | + this.loadFloors() | |
| 115 | + this.loadData() | |
| 116 | + }, | |
| 117 | + methods: { | |
| 118 | + async loadData() { | |
| 119 | + try { | |
| 120 | + this.loading = true | |
| 121 | + const params = { | |
| 122 | + ...this.searchForm, | |
| 123 | + page: this.pagination.current, | |
| 124 | + row: this.pagination.size | |
| 125 | + } | |
| 126 | + const { data, total } = await queryNoFeeRooms(params) | |
| 127 | + this.tableData = data.map((item, index) => ({ | |
| 128 | + ...item, | |
| 129 | + index: index + 1 | |
| 130 | + })) | |
| 131 | + this.pagination.total = total | |
| 132 | + } catch (error) { | |
| 133 | + console.error('加载数据失败:', error) | |
| 134 | + } finally { | |
| 135 | + this.loading = false | |
| 136 | + } | |
| 137 | + }, | |
| 138 | + async loadFloors() { | |
| 139 | + try { | |
| 140 | + const params = { | |
| 141 | + page: 1, | |
| 142 | + row: 100, | |
| 143 | + communityId: this.searchForm.communityId | |
| 144 | + } | |
| 145 | + const data = await queryFloors(params) | |
| 146 | + this.floors = data | |
| 147 | + } catch (error) { | |
| 148 | + console.error('加载楼栋数据失败:', error) | |
| 149 | + } | |
| 150 | + }, | |
| 151 | + async handleFloorChange(floorId) { | |
| 152 | + try { | |
| 153 | + this.searchForm.unitId = '' | |
| 154 | + this.searchForm.roomId = '' | |
| 155 | + this.units = [] | |
| 156 | + this.rooms = [] | |
| 157 | + | |
| 158 | + if (!floorId) return | |
| 159 | + | |
| 160 | + const params = { | |
| 161 | + floorId, | |
| 162 | + communityId: this.searchForm.communityId, | |
| 163 | + page: 1, | |
| 164 | + row: 100 | |
| 165 | + } | |
| 166 | + const data = await queryUnits(params) | |
| 167 | + this.units = data | |
| 168 | + } catch (error) { | |
| 169 | + console.error('加载单元数据失败:', error) | |
| 170 | + } | |
| 171 | + }, | |
| 172 | + async handleUnitChange(unitId) { | |
| 173 | + try { | |
| 174 | + this.searchForm.roomId = '' | |
| 175 | + this.rooms = [] | |
| 176 | + | |
| 177 | + if (!unitId) return | |
| 178 | + | |
| 179 | + const params = { | |
| 180 | + unitId, | |
| 181 | + communityId: this.searchForm.communityId, | |
| 182 | + page: 1, | |
| 183 | + row: 100 | |
| 184 | + } | |
| 185 | + const data = await queryRooms(params) | |
| 186 | + this.rooms = data.rooms | |
| 187 | + } catch (error) { | |
| 188 | + console.error('加载房屋数据失败:', error) | |
| 189 | + } | |
| 190 | + }, | |
| 191 | + handleSearch() { | |
| 192 | + this.pagination.current = 1 | |
| 193 | + this.loadData() | |
| 194 | + }, | |
| 195 | + handleReset() { | |
| 196 | + this.searchForm = { | |
| 197 | + floorId: '', | |
| 198 | + unitId: '', | |
| 199 | + roomId: '', | |
| 200 | + ownerName: '', | |
| 201 | + link: '', | |
| 202 | + communityId: this.searchForm.communityId | |
| 203 | + } | |
| 204 | + this.units = [] | |
| 205 | + this.rooms = [] | |
| 206 | + this.pagination.current = 1 | |
| 207 | + this.loadData() | |
| 208 | + }, | |
| 209 | + async handleExport() { | |
| 210 | + try { | |
| 211 | + this.loading = true | |
| 212 | + const params = { | |
| 213 | + ...this.searchForm, | |
| 214 | + pagePath: 'reportNoFeeRoom' | |
| 215 | + } | |
| 216 | + await exportData(params) | |
| 217 | + this.$message.success(this.$t('reportNoFeeRoom.exportSuccess')) | |
| 218 | + } catch (error) { | |
| 219 | + console.error('导出失败:', error) | |
| 220 | + this.$message.error(this.$t('reportNoFeeRoom.exportFailed')) | |
| 221 | + } finally { | |
| 222 | + this.loading = false | |
| 223 | + } | |
| 224 | + }, | |
| 225 | + handleSizeChange(size) { | |
| 226 | + this.pagination.size = size | |
| 227 | + this.loadData() | |
| 228 | + }, | |
| 229 | + handleCurrentChange(current) { | |
| 230 | + this.pagination.current = current | |
| 231 | + this.loadData() | |
| 232 | + } | |
| 233 | + } | |
| 234 | +} | |
| 235 | +</script> | |
| 236 | + | |
| 237 | +<style lang="scss" scoped> | |
| 238 | +.report-no-fee-room-container { | |
| 239 | + padding: 20px; | |
| 240 | + | |
| 241 | + .search-card { | |
| 242 | + margin-bottom: 20px; | |
| 243 | + | |
| 244 | + .el-select, | |
| 245 | + .el-input { | |
| 246 | + width: 100%; | |
| 247 | + } | |
| 248 | + } | |
| 249 | + | |
| 250 | + .el-icon-info { | |
| 251 | + color: #409EFF; | |
| 252 | + } | |
| 253 | +} | |
| 254 | +</style> | |
| 0 | 255 | \ No newline at end of file | ... | ... |
src/views/report/reportOweFeeDetailLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + reportOweFeeDetail: { | |
| 4 | + all: 'All', | |
| 5 | + searchCondition: 'Search Condition', | |
| 6 | + feeType: 'Fee Type', | |
| 7 | + selectFeeType: 'Select Fee Type', | |
| 8 | + roomNum: 'Room Number', | |
| 9 | + inputRoomNum: 'Input Room Number', | |
| 10 | + startTime: 'Start Time', | |
| 11 | + selectStartTime: 'Select Start Time', | |
| 12 | + endTime: 'End Time', | |
| 13 | + selectEndTime: 'Select End Time', | |
| 14 | + community: 'Community', | |
| 15 | + selectCommunity: 'Select Community', | |
| 16 | + search: 'Search', | |
| 17 | + reset: 'Reset', | |
| 18 | + ownerName: 'Owner Name', | |
| 19 | + inputOwnerName: 'Input Owner Name', | |
| 20 | + oweFeeDetail: 'Owe Fee Detail', | |
| 21 | + tooltip: 'Details of arrears associated with rooms and fee items', | |
| 22 | + updateDaily: 'Updated daily', | |
| 23 | + export: 'Export', | |
| 24 | + feeNum: 'Fee No.', | |
| 25 | + owner: 'Owner', | |
| 26 | + ownerTel: 'Owner Tel', | |
| 27 | + area: 'Area', | |
| 28 | + feeItem: 'Fee Item', | |
| 29 | + oweDays: 'Owe Days', | |
| 30 | + oweAmount: 'Owe Amount', | |
| 31 | + subtotal: 'Subtotal', | |
| 32 | + total: 'Total', | |
| 33 | + owe: 'Owe', | |
| 34 | + yuan: 'Yuan', | |
| 35 | + feeStartTimeDesc: 'Fee start time: The billing start time of the created fee', | |
| 36 | + oweDaysDesc1: 'Owe days (days): For deposit fee items, the number of days from the fee start time to the current day', | |
| 37 | + oweDaysDesc2: 'For non-deposit fee items, the number of days from the fee start time to the fee end time', | |
| 38 | + oweAmountDesc: 'Owe amount: The amount payable during the arrears period' | |
| 39 | + } | |
| 40 | + }, | |
| 41 | + zh: { | |
| 42 | + reportOweFeeDetail: { | |
| 43 | + all: '全部', | |
| 44 | + searchCondition: '查询条件', | |
| 45 | + feeType: '费用大类', | |
| 46 | + selectFeeType: '请选择费用大类', | |
| 47 | + roomNum: '房屋编号', | |
| 48 | + inputRoomNum: '请填写房屋编号', | |
| 49 | + startTime: '开始时间', | |
| 50 | + selectStartTime: '请选择开始时间', | |
| 51 | + endTime: '结束时间', | |
| 52 | + selectEndTime: '请选择结束时间', | |
| 53 | + community: '小区', | |
| 54 | + selectCommunity: '请选择小区', | |
| 55 | + search: '查询', | |
| 56 | + reset: '重置', | |
| 57 | + ownerName: '业主名称', | |
| 58 | + inputOwnerName: '请填写业主名称', | |
| 59 | + oweFeeDetail: '欠费明细表', | |
| 60 | + tooltip: '房屋与费用项关联的欠费明细', | |
| 61 | + updateDaily: '按天更新', | |
| 62 | + export: '导出', | |
| 63 | + feeNum: '费用编号', | |
| 64 | + owner: '业主', | |
| 65 | + ownerTel: '业主电话', | |
| 66 | + area: '面积', | |
| 67 | + feeItem: '费用项', | |
| 68 | + oweDays: '欠费时长(天)', | |
| 69 | + oweAmount: '欠费金额', | |
| 70 | + subtotal: '小计', | |
| 71 | + total: '大计', | |
| 72 | + owe: '欠费', | |
| 73 | + yuan: '元', | |
| 74 | + feeStartTimeDesc: '费用开始时间:所创建费用的计费起始时间', | |
| 75 | + oweDaysDesc1: '欠费时长(天):押金费用项欠费时长是费用开始时间到当天的天数', | |
| 76 | + oweDaysDesc2: '除押金外的费用项欠费时长是费用的开始时间到费用的结束时间的天数', | |
| 77 | + oweAmountDesc: '欠费金额:欠费周期内应缴费用' | |
| 78 | + } | |
| 79 | + } | |
| 80 | +} | |
| 0 | 81 | \ No newline at end of file | ... | ... |
src/views/report/reportOweFeeDetailList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="report-owe-fee-detail-container animated fadeInRight"> | |
| 3 | + <el-row :gutter="20"> | |
| 4 | + <el-col :span="3"> | |
| 5 | + <el-card class="floor-list-card"> | |
| 6 | + <ul class="floor-list"> | |
| 7 | + <li class="floor-item" @click="swatchFloor('')" | |
| 8 | + :class="{ 'active': reportOweFeeDetailInfo.conditions.floorId === '' }"> | |
| 9 | + {{ $t('reportOweFeeDetail.all') }} | |
| 10 | + </li> | |
| 11 | + <li class="floor-item" v-for="(item, index) in reportOweFeeDetailInfo.floors" :key="index" | |
| 12 | + @click="swatchFloor(item.floorId)" | |
| 13 | + :class="{ 'active': reportOweFeeDetailInfo.conditions.floorId === item.floorId }"> | |
| 14 | + {{ item.floorName }} | |
| 15 | + </li> | |
| 16 | + </ul> | |
| 17 | + </el-card> | |
| 18 | + </el-col> | |
| 19 | + <el-col :span="21"> | |
| 20 | + <el-card> | |
| 21 | + <div slot="header" class="flex justify-between"> | |
| 22 | + <span>{{ $t('reportOweFeeDetail.searchCondition') }}</span> | |
| 23 | + </div> | |
| 24 | + <el-form :inline="true" :model="reportOweFeeDetailInfo.conditions" class="search-form text-left"> | |
| 25 | + <el-form-item :label="$t('reportOweFeeDetail.feeType')"> | |
| 26 | + <el-select v-model="reportOweFeeDetailInfo.conditions.feeTypeCd" | |
| 27 | + :placeholder="$t('reportOweFeeDetail.selectFeeType')" style="width:100%"> | |
| 28 | + <el-option v-for="(item, index) in reportOweFeeDetailInfo.feeTypeCds" :key="index" :label="item.name" | |
| 29 | + :value="item.statusCd"> | |
| 30 | + </el-option> | |
| 31 | + </el-select> | |
| 32 | + </el-form-item> | |
| 33 | + | |
| 34 | + <el-form-item :label="$t('reportOweFeeDetail.roomNum')"> | |
| 35 | + <el-input v-model="reportOweFeeDetailInfo.conditions.objNameLike" | |
| 36 | + :placeholder="$t('reportOweFeeDetail.inputRoomNum')"> | |
| 37 | + </el-input> | |
| 38 | + </el-form-item> | |
| 39 | + | |
| 40 | + <el-form-item :label="$t('reportOweFeeDetail.startTime')"> | |
| 41 | + <el-date-picker v-model="reportOweFeeDetailInfo.conditions.startTime" type="date" | |
| 42 | + :placeholder="$t('reportOweFeeDetail.selectStartTime')"> | |
| 43 | + </el-date-picker> | |
| 44 | + </el-form-item> | |
| 45 | + | |
| 46 | + <el-form-item :label="$t('reportOweFeeDetail.endTime')"> | |
| 47 | + <el-date-picker v-model="reportOweFeeDetailInfo.conditions.endTime" type="date" | |
| 48 | + :placeholder="$t('reportOweFeeDetail.selectEndTime')"> | |
| 49 | + </el-date-picker> | |
| 50 | + </el-form-item> | |
| 51 | + | |
| 52 | + <el-form-item v-if="reportOweFeeDetailInfo.communitys.length > 1" :label="$t('reportOweFeeDetail.community')"> | |
| 53 | + <el-select v-model="reportOweFeeDetailInfo.conditions.communityId" @change="_changCommunity" | |
| 54 | + :placeholder="$t('reportOweFeeDetail.selectCommunity')" style="width:100%"> | |
| 55 | + <el-option v-for="(item, index) in reportOweFeeDetailInfo.communitys" :key="index" :label="item.name" | |
| 56 | + :value="item.communityId"> | |
| 57 | + </el-option> | |
| 58 | + </el-select> | |
| 59 | + </el-form-item> | |
| 60 | + | |
| 61 | + <el-form-item> | |
| 62 | + <el-button type="primary" @click="_queryMethod">{{ $t('reportOweFeeDetail.search') }}</el-button> | |
| 63 | + <el-button @click="_resetMethod" style="margin-left: 10px;">{{ $t('reportOweFeeDetail.reset') }}</el-button> | |
| 64 | + </el-form-item> | |
| 65 | + </el-form> | |
| 66 | + | |
| 67 | + <el-form :inline="true" class="search-form text-left"> | |
| 68 | + <el-form-item :label="$t('reportOweFeeDetail.ownerName')"> | |
| 69 | + <el-input v-model="reportOweFeeDetailInfo.conditions.ownerNameLike" | |
| 70 | + :placeholder="$t('reportOweFeeDetail.inputOwnerName')"> | |
| 71 | + </el-input> | |
| 72 | + </el-form-item> | |
| 73 | + </el-form> | |
| 74 | + </el-card> | |
| 75 | + | |
| 76 | + <el-card style="margin-top: 20px;"> | |
| 77 | + <div slot="header" class="flex justify-between"> | |
| 78 | + <div> | |
| 79 | + <span>{{ $t('reportOweFeeDetail.oweFeeDetail') }}</span> | |
| 80 | + <el-tooltip class="item" effect="dark" :content="$t('reportOweFeeDetail.tooltip')" placement="top"> | |
| 81 | + <i class="el-icon-info" style="margin-left: 10px; cursor: pointer;"></i> | |
| 82 | + </el-tooltip> | |
| 83 | + <span style="font-size: 12px; margin-left: 10px;">({{ $t('reportOweFeeDetail.updateDaily') }})</span> | |
| 84 | + </div> | |
| 85 | + <el-button type="primary" size="small" style="float: right;" @click="_exportExcel"> | |
| 86 | + <i class="el-icon-download"></i> | |
| 87 | + {{ $t('reportOweFeeDetail.export') }} | |
| 88 | + </el-button> | |
| 89 | + </div> | |
| 90 | + | |
| 91 | + <el-table :data="reportOweFeeDetailInfo.fees" border style="width: 100%" v-loading="loading"> | |
| 92 | + <el-table-column prop="index" :label="$t('reportOweFeeDetail.feeNum')" width="80" align="center"> | |
| 93 | + <template slot-scope="scope"> | |
| 94 | + {{ scope.$index + 1 }} | |
| 95 | + </template> | |
| 96 | + </el-table-column> | |
| 97 | + <el-table-column prop="objName" :label="$t('reportOweFeeDetail.roomNum')" align="center"> | |
| 98 | + </el-table-column> | |
| 99 | + <el-table-column prop="ownerName" :label="$t('reportOweFeeDetail.owner')" align="center"> | |
| 100 | + </el-table-column> | |
| 101 | + <el-table-column prop="ownerTel" :label="$t('reportOweFeeDetail.ownerTel')" align="center"> | |
| 102 | + </el-table-column> | |
| 103 | + <el-table-column prop="builtUpArea" :label="$t('reportOweFeeDetail.area')" align="center"> | |
| 104 | + </el-table-column> | |
| 105 | + <el-table-column prop="feeName" :label="$t('reportOweFeeDetail.feeItem')" align="center"> | |
| 106 | + </el-table-column> | |
| 107 | + <el-table-column prop="startTime" :label="$t('reportOweFeeDetail.startTime')" align="center"> | |
| 108 | + </el-table-column> | |
| 109 | + <el-table-column prop="endTime" :label="$t('reportOweFeeDetail.endTime')" align="center"> | |
| 110 | + </el-table-column> | |
| 111 | + <el-table-column prop="oweDay" :label="$t('reportOweFeeDetail.oweDays')" align="center"> | |
| 112 | + </el-table-column> | |
| 113 | + <el-table-column prop="oweAmount" :label="$t('reportOweFeeDetail.oweAmount')" align="center"> | |
| 114 | + </el-table-column> | |
| 115 | + </el-table> | |
| 116 | + | |
| 117 | + <div class="summary"> | |
| 118 | + <div class="summary-item"> | |
| 119 | + <span class="label">{{ $t('reportOweFeeDetail.subtotal') }}</span> | |
| 120 | + <span class="value"> | |
| 121 | + {{ $t('reportOweFeeDetail.owe') }}: {{ reportOweFeeDetailInfo.totalPreferentialAmount }} {{ | |
| 122 | + $t('reportOweFeeDetail.yuan') }} | |
| 123 | + </span> | |
| 124 | + </div> | |
| 125 | + <div class="summary-item"> | |
| 126 | + <span class="label">{{ $t('reportOweFeeDetail.total') }}</span> | |
| 127 | + <span class="value"> | |
| 128 | + {{ $t('reportOweFeeDetail.owe') }}: {{ reportOweFeeDetailInfo.allOweAmount }} {{ | |
| 129 | + $t('reportOweFeeDetail.yuan') }} | |
| 130 | + </span> | |
| 131 | + </div> | |
| 132 | + </div> | |
| 133 | + | |
| 134 | + <div class="footer"> | |
| 135 | + <div class="footer-left"> | |
| 136 | + <p>{{ $t('reportOweFeeDetail.feeStartTimeDesc') }}</p> | |
| 137 | + <p>{{ $t('reportOweFeeDetail.oweDaysDesc1') }}</p> | |
| 138 | + <p>{{ $t('reportOweFeeDetail.oweDaysDesc2') }}</p> | |
| 139 | + <p>{{ $t('reportOweFeeDetail.oweAmountDesc') }}</p> | |
| 140 | + </div> | |
| 141 | + <div class="footer-right"> | |
| 142 | + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" | |
| 143 | + :current-page="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size" | |
| 144 | + layout="total, sizes, prev, pager, next, jumper" :total="page.total"> | |
| 145 | + </el-pagination> | |
| 146 | + </div> | |
| 147 | + </div> | |
| 148 | + </el-card> | |
| 149 | + </el-col> | |
| 150 | + </el-row> | |
| 151 | + </div> | |
| 152 | +</template> | |
| 153 | + | |
| 154 | +<script> | |
| 155 | +import { getDict } from '@/api/community/communityApi' | |
| 156 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 157 | +import { queryOweFeeDetail, exportData } from '@/api/report/reportOweFeeDetailApi' | |
| 158 | +import {searchFloors} from '@/api/room/searchFloorApi' | |
| 159 | +import { | |
| 160 | + listMyEnteredCommunitys | |
| 161 | +} from '@/api/report/dataReportApi' | |
| 162 | + | |
| 163 | +export default { | |
| 164 | + name: 'ReportOweFeeDetailList', | |
| 165 | + data() { | |
| 166 | + return { | |
| 167 | + loading: false, | |
| 168 | + reportOweFeeDetailInfo: { | |
| 169 | + fees: [], | |
| 170 | + floors: [], | |
| 171 | + total: 0, | |
| 172 | + records: 1, | |
| 173 | + feeTypeCds: [], | |
| 174 | + communitys: [], | |
| 175 | + totalPreferentialAmount: 0.0, | |
| 176 | + allOweAmount: 0.0, | |
| 177 | + conditions: { | |
| 178 | + floorId: '', | |
| 179 | + floorName: '', | |
| 180 | + roomNum: '', | |
| 181 | + objNameLike: '', | |
| 182 | + feeTypeCd: '', | |
| 183 | + startTime: '', | |
| 184 | + endTime: '', | |
| 185 | + communityId: '', | |
| 186 | + ownerNameLike: '', | |
| 187 | + page: 1, | |
| 188 | + row: 10 | |
| 189 | + } | |
| 190 | + }, | |
| 191 | + page: { | |
| 192 | + current: 1, | |
| 193 | + size: 10, | |
| 194 | + total: 0 | |
| 195 | + } | |
| 196 | + } | |
| 197 | + }, | |
| 198 | + created() { | |
| 199 | + this.initData() | |
| 200 | + }, | |
| 201 | + methods: { | |
| 202 | + async initData() { | |
| 203 | + this.reportOweFeeDetailInfo.conditions.communityId = getCommunityId() | |
| 204 | + await this.getDictData() | |
| 205 | + await this._listFloors() | |
| 206 | + await this._listFees() | |
| 207 | + await this._loadStaffCommunitys() | |
| 208 | + }, | |
| 209 | + | |
| 210 | + async getDictData() { | |
| 211 | + try { | |
| 212 | + const data = await getDict('pay_fee_config', 'fee_type_cd') | |
| 213 | + this.reportOweFeeDetailInfo.feeTypeCds = data | |
| 214 | + } catch (error) { | |
| 215 | + console.error('获取字典数据失败:', error) | |
| 216 | + } | |
| 217 | + }, | |
| 218 | + | |
| 219 | + async _listFees() { | |
| 220 | + this.loading = true | |
| 221 | + try { | |
| 222 | + const params = { | |
| 223 | + ...this.reportOweFeeDetailInfo.conditions, | |
| 224 | + page: this.page.current, | |
| 225 | + row: this.page.size | |
| 226 | + } | |
| 227 | + const { data, total } = await queryOweFeeDetail(params) | |
| 228 | + this.reportOweFeeDetailInfo.fees = data | |
| 229 | + this.page.total = total | |
| 230 | + | |
| 231 | + // 计算小计 | |
| 232 | + let _totalPreferentialAmount = 0.0 | |
| 233 | + data.forEach(item => { | |
| 234 | + _totalPreferentialAmount += parseFloat(item.oweAmount) | |
| 235 | + }) | |
| 236 | + this.reportOweFeeDetailInfo.totalPreferentialAmount = _totalPreferentialAmount.toFixed(2) | |
| 237 | + | |
| 238 | + if (data.length > 0) { | |
| 239 | + this.reportOweFeeDetailInfo.allOweAmount = data[0].allOweAmount | |
| 240 | + } else { | |
| 241 | + this.reportOweFeeDetailInfo.allOweAmount = 0.0.toFixed(2) | |
| 242 | + } | |
| 243 | + } catch (error) { | |
| 244 | + console.error('获取欠费明细失败:', error) | |
| 245 | + } finally { | |
| 246 | + this.loading = false | |
| 247 | + } | |
| 248 | + }, | |
| 249 | + | |
| 250 | + async _listFloors() { | |
| 251 | + try { | |
| 252 | + const params = { | |
| 253 | + page: 1, | |
| 254 | + row: 100, | |
| 255 | + communityId: this.reportOweFeeDetailInfo.conditions.communityId | |
| 256 | + } | |
| 257 | + const { apiFloorDataVoList } = await searchFloors(params) | |
| 258 | + this.reportOweFeeDetailInfo.floors = apiFloorDataVoList | |
| 259 | + } catch (error) { | |
| 260 | + console.error('获取楼层列表失败:', error) | |
| 261 | + } | |
| 262 | + }, | |
| 263 | + | |
| 264 | + async _loadStaffCommunitys() { | |
| 265 | + try { | |
| 266 | + const params = { | |
| 267 | + _uid: '123mlkdinkldldijdhuudjdjkkd', | |
| 268 | + page: 1, | |
| 269 | + row: 100 | |
| 270 | + } | |
| 271 | + const data = await listMyEnteredCommunitys(params) | |
| 272 | + this.reportOweFeeDetailInfo.communitys = data.communitys | |
| 273 | + } catch (error) { | |
| 274 | + console.error('获取小区列表失败:', error) | |
| 275 | + } | |
| 276 | + }, | |
| 277 | + | |
| 278 | + _queryMethod() { | |
| 279 | + this.page.current = 1 | |
| 280 | + this._listFees() | |
| 281 | + }, | |
| 282 | + | |
| 283 | + _resetMethod() { | |
| 284 | + this.reportOweFeeDetailInfo.conditions = { | |
| 285 | + floorId: '', | |
| 286 | + floorName: '', | |
| 287 | + roomNum: '', | |
| 288 | + objNameLike: '', | |
| 289 | + feeTypeCd: '', | |
| 290 | + startTime: '', | |
| 291 | + endTime: '', | |
| 292 | + communityId: this.reportOweFeeDetailInfo.conditions.communityId, | |
| 293 | + ownerNameLike: '', | |
| 294 | + page: 1, | |
| 295 | + row: 10 | |
| 296 | + } | |
| 297 | + this._listFees() | |
| 298 | + }, | |
| 299 | + | |
| 300 | + swatchFloor(floorId) { | |
| 301 | + this.reportOweFeeDetailInfo.conditions.floorId = floorId | |
| 302 | + this._listFees() | |
| 303 | + }, | |
| 304 | + | |
| 305 | + _changCommunity() { | |
| 306 | + this.reportOweFeeDetailInfo.conditions.floorId = '' | |
| 307 | + this._listFloors() | |
| 308 | + this._listFees() | |
| 309 | + }, | |
| 310 | + | |
| 311 | + async _exportExcel() { | |
| 312 | + try { | |
| 313 | + const params = { | |
| 314 | + ...this.reportOweFeeDetailInfo.conditions, | |
| 315 | + pagePath: 'reportOweFeeDetail' | |
| 316 | + } | |
| 317 | + const { code, msg } = await exportData(params) | |
| 318 | + this.$message.success(msg) | |
| 319 | + if (code === 0) { | |
| 320 | + this.$router.push('/#/pages/property/downloadTempFile?tab=下载中心') | |
| 321 | + } | |
| 322 | + } catch (error) { | |
| 323 | + console.error('导出失败:', error) | |
| 324 | + } | |
| 325 | + }, | |
| 326 | + | |
| 327 | + handleSizeChange(val) { | |
| 328 | + this.page.size = val | |
| 329 | + this._listFees() | |
| 330 | + }, | |
| 331 | + | |
| 332 | + handleCurrentChange(val) { | |
| 333 | + this.page.current = val | |
| 334 | + this._listFees() | |
| 335 | + } | |
| 336 | + } | |
| 337 | +} | |
| 338 | +</script> | |
| 339 | + | |
| 340 | +<style lang="scss" scoped> | |
| 341 | +.report-owe-fee-detail-container { | |
| 342 | + padding: 20px; | |
| 343 | + | |
| 344 | + .floor-list-card { | |
| 345 | + height: 100%; | |
| 346 | + | |
| 347 | + .floor-list { | |
| 348 | + list-style: none; | |
| 349 | + padding: 0; | |
| 350 | + margin: 0; | |
| 351 | + | |
| 352 | + .floor-item { | |
| 353 | + padding: 10px; | |
| 354 | + margin-bottom: 5px; | |
| 355 | + cursor: pointer; | |
| 356 | + border-radius: 4px; | |
| 357 | + text-align: center; | |
| 358 | + | |
| 359 | + &:hover { | |
| 360 | + background-color: #f5f7fa; | |
| 361 | + } | |
| 362 | + | |
| 363 | + &.active { | |
| 364 | + background-color: #409eff; | |
| 365 | + color: white; | |
| 366 | + } | |
| 367 | + } | |
| 368 | + } | |
| 369 | + } | |
| 370 | + | |
| 371 | + .search-form { | |
| 372 | + margin-bottom: 20px; | |
| 373 | + | |
| 374 | + .el-form-item { | |
| 375 | + margin-right: 20px; | |
| 376 | + } | |
| 377 | + } | |
| 378 | + | |
| 379 | + .summary { | |
| 380 | + margin: 20px 0; | |
| 381 | + padding: 10px; | |
| 382 | + background-color: #f5f7fa; | |
| 383 | + border-radius: 4px; | |
| 384 | + | |
| 385 | + .summary-item { | |
| 386 | + display: flex; | |
| 387 | + align-items: center; | |
| 388 | + margin-bottom: 5px; | |
| 389 | + | |
| 390 | + .label { | |
| 391 | + font-weight: bold; | |
| 392 | + margin-right: 10px; | |
| 393 | + width: 60px; | |
| 394 | + } | |
| 395 | + } | |
| 396 | + } | |
| 397 | + | |
| 398 | + .footer { | |
| 399 | + display: flex; | |
| 400 | + justify-content: space-between; | |
| 401 | + margin-top: 20px; | |
| 402 | + | |
| 403 | + .footer-left { | |
| 404 | + width: 60%; | |
| 405 | + font-size: 12px; | |
| 406 | + color: #666; | |
| 407 | + | |
| 408 | + p { | |
| 409 | + margin: 5px 0; | |
| 410 | + } | |
| 411 | + } | |
| 412 | + | |
| 413 | + .footer-right { | |
| 414 | + width: 40%; | |
| 415 | + text-align: right; | |
| 416 | + } | |
| 417 | + } | |
| 418 | +} | |
| 419 | +</style> | |
| 0 | 420 | \ No newline at end of file | ... | ... |
src/views/report/reportOwnerPayFeeLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + reportOwnerPayFee: { | |
| 4 | + queryCondition: 'Query Conditions', | |
| 5 | + selectFeeType: 'Select Fee Type', | |
| 6 | + selectFeeItem: 'Select Fee Item', | |
| 7 | + inputRoomNum: 'Input Room Number', | |
| 8 | + inputOwnerName: 'Input Owner Name', | |
| 9 | + inputYear: 'Input Year', | |
| 10 | + paymentDetails: 'Owner Payment Details', | |
| 11 | + paymentDetailsTip: 'Details of owner payment records', | |
| 12 | + owner: 'Owner', | |
| 13 | + room: 'Room', | |
| 14 | + feeItem: 'Fee Item', | |
| 15 | + month: 'Month', | |
| 16 | + total: 'Total', | |
| 17 | + receivable: 'Receivable', | |
| 18 | + prepayment: 'Prepayment', | |
| 19 | + fetchError: 'Failed to fetch payment details' | |
| 20 | + } | |
| 21 | + }, | |
| 22 | + zh: { | |
| 23 | + reportOwnerPayFee: { | |
| 24 | + queryCondition: '查询条件', | |
| 25 | + selectFeeType: '请选择收费大类', | |
| 26 | + selectFeeItem: '请选择收费项', | |
| 27 | + inputRoomNum: '请输入房屋编号', | |
| 28 | + inputOwnerName: '请输入业主名称', | |
| 29 | + inputYear: '请输入年份', | |
| 30 | + paymentDetails: '业主缴费明细', | |
| 31 | + paymentDetailsTip: '业主缴费记录明细', | |
| 32 | + owner: '业主', | |
| 33 | + room: '房屋', | |
| 34 | + feeItem: '费用项目', | |
| 35 | + month: '月', | |
| 36 | + total: '合计', | |
| 37 | + receivable: '应收', | |
| 38 | + prepayment: '预收', | |
| 39 | + fetchError: '获取缴费明细失败' | |
| 40 | + } | |
| 41 | + } | |
| 42 | +} | |
| 0 | 43 | \ No newline at end of file | ... | ... |
src/views/report/reportOwnerPayFeeList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="report-owner-pay-fee-container animated fadeInRight"> | |
| 3 | + <el-row> | |
| 4 | + <el-col :span="24"> | |
| 5 | + <el-card> | |
| 6 | + <div slot="header" class="flex justify-between"> | |
| 7 | + <span>{{ $t('reportOwnerPayFee.queryCondition') }}</span> | |
| 8 | + <div style="float: right;"> | |
| 9 | + <el-button type="text" @click="_moreCondition()"> | |
| 10 | + {{ reportOwnerPayFeeInfo.moreCondition ? $t('common.hide') : $t('common.more') }} | |
| 11 | + </el-button> | |
| 12 | + </div> | |
| 13 | + </div> | |
| 14 | + <el-row :gutter="20"> | |
| 15 | + <el-col :span="4"> | |
| 16 | + <el-select v-model="reportOwnerPayFeeInfo.conditions.feeTypeCd" | |
| 17 | + :placeholder="$t('reportOwnerPayFee.selectFeeType')" @change="_changeReporficientFeeTypeCd" | |
| 18 | + style="width:100%"> | |
| 19 | + <el-option v-for="(item, index) in reportOwnerPayFeeInfo.feeTypeCds" :key="index" :label="item.name" | |
| 20 | + :value="item.statusCd"> | |
| 21 | + </el-option> | |
| 22 | + </el-select> | |
| 23 | + </el-col> | |
| 24 | + <el-col :span="4"> | |
| 25 | + <el-select v-model="reportOwnerPayFeeInfo.conditions.configId" | |
| 26 | + :placeholder="$t('reportOwnerPayFee.selectFeeItem')" style="width:100%"> | |
| 27 | + <el-option v-for="(item, index) in reportOwnerPayFeeInfo.feeConfigDtos" :key="index" :label="item.feeName" | |
| 28 | + :value="item.configId"> | |
| 29 | + </el-option> | |
| 30 | + </el-select> | |
| 31 | + </el-col> | |
| 32 | + <el-col :span="4"> | |
| 33 | + <el-input v-model="reportOwnerPayFeeInfo.conditions.roomName" | |
| 34 | + :placeholder="$t('reportOwnerPayFee.inputRoomNum')" @input="_meterInputRoom"> | |
| 35 | + <input-search-room slot="append" ref="inputSearchRoom"></input-search-room> | |
| 36 | + </el-input> | |
| 37 | + </el-col> | |
| 38 | + <el-col :span="4"> | |
| 39 | + <el-input v-model="reportOwnerPayFeeInfo.conditions.ownerName" | |
| 40 | + :placeholder="$t('reportOwnerPayFee.inputOwnerName')" @input="_meterInputOwner"> | |
| 41 | + <input-search-owner slot="append" ref="inputSearchOwner"></input-search-owner> | |
| 42 | + </el-input> | |
| 43 | + </el-col> | |
| 44 | + <el-col :span="4"> | |
| 45 | + <el-button type="primary" @click="_queryMethod"> | |
| 46 | + <i class="el-icon-search"></i> | |
| 47 | + {{ $t('common.search') }} | |
| 48 | + </el-button> | |
| 49 | + <el-button @click="_resetMethod"> | |
| 50 | + <i class="el-icon-refresh"></i> | |
| 51 | + {{ $t('common.reset') }} | |
| 52 | + </el-button> | |
| 53 | + </el-col> | |
| 54 | + </el-row> | |
| 55 | + <el-row :gutter="20" v-show="reportOwnerPayFeeInfo.moreCondition"> | |
| 56 | + <el-col :span="4"> | |
| 57 | + <el-input v-model="reportOwnerPayFeeInfo.conditions.pfYear" | |
| 58 | + :placeholder="$t('reportOwnerPayFee.inputYear')"> | |
| 59 | + </el-input> | |
| 60 | + </el-col> | |
| 61 | + </el-row> | |
| 62 | + </el-card> | |
| 63 | + </el-col> | |
| 64 | + </el-row> | |
| 65 | + | |
| 66 | + <el-row style="margin-top:20px;"> | |
| 67 | + <el-col :span="24"> | |
| 68 | + <el-card> | |
| 69 | + <div slot="header" class="flex justify-between"> | |
| 70 | + <div> | |
| 71 | + <span>{{ $t('reportOwnerPayFee.paymentDetails') }}</span> | |
| 72 | + <el-tooltip class="item" effect="dark" :content="$t('reportOwnerPayFee.paymentDetailsTip')" placement="top"> | |
| 73 | + <i class="el-icon-info" style="cursor:pointer;"></i> | |
| 74 | + </el-tooltip> | |
| 75 | + </div> | |
| 76 | + </div> | |
| 77 | + <el-table :data="reportOwnerPayFeeInfo.ownerPayFees" border style="width: 100%" v-loading="loading"> | |
| 78 | + <el-table-column prop="ownerName" :label="$t('reportOwnerPayFee.owner')" align="center"></el-table-column> | |
| 79 | + <el-table-column prop="roomName" :label="$t('reportOwnerPayFee.room')" align="center"></el-table-column> | |
| 80 | + <el-table-column prop="feeName" :label="$t('reportOwnerPayFee.feeItem')" align="center"></el-table-column> | |
| 81 | + <el-table-column v-for="month in 12" :key="month" :label="month + $t('reportOwnerPayFee.month')" | |
| 82 | + align="center"> | |
| 83 | + <template slot-scope="scope"> | |
| 84 | + {{ _getAmountByMonth(scope.row, month) }} | |
| 85 | + </template> | |
| 86 | + </el-table-column> | |
| 87 | + <el-table-column :label="$t('reportOwnerPayFee.total')" align="center"> | |
| 88 | + <template slot-scope="scope"> | |
| 89 | + {{ _getTotalAmount(scope.row) }} | |
| 90 | + </template> | |
| 91 | + </el-table-column> | |
| 92 | + <el-table-column :label="$t('reportOwnerPayFee.receivable')" align="center"> | |
| 93 | + <template slot-scope="scope"> | |
| 94 | + {{ _getReceivableTotalAmount(scope.row) }} | |
| 95 | + </template> | |
| 96 | + </el-table-column> | |
| 97 | + <el-table-column :label="$t('reportOwnerPayFee.prepayment')" align="center"> | |
| 98 | + <template slot-scope="scope"> | |
| 99 | + {{ _getCollectTotalAmount(scope.row) }} | |
| 100 | + </template> | |
| 101 | + </el-table-column> | |
| 102 | + </el-table> | |
| 103 | + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" | |
| 104 | + :current-page="pagination.current" :page-sizes="[10, 20, 30, 50]" :page-size="pagination.size" | |
| 105 | + layout="total, sizes, prev, pager, next, jumper" :total="pagination.total"> | |
| 106 | + </el-pagination> | |
| 107 | + </el-card> | |
| 108 | + </el-col> | |
| 109 | + </el-row> | |
| 110 | + </div> | |
| 111 | +</template> | |
| 112 | + | |
| 113 | +<script> | |
| 114 | +import { queryReportOwnerPayFee, listFeeConfigs } from '@/api/report/reportOwnerPayFeeApi' | |
| 115 | +import { getDict } from '@/api/community/communityApi' | |
| 116 | +import InputSearchRoom from '@/components/report/InputSearchRoom' | |
| 117 | +import InputSearchOwner from '@/components/report/InputSearchOwner' | |
| 118 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 119 | + | |
| 120 | +export default { | |
| 121 | + name: 'ReportOwnerPayFeeList', | |
| 122 | + components: { | |
| 123 | + InputSearchRoom, | |
| 124 | + InputSearchOwner | |
| 125 | + }, | |
| 126 | + data() { | |
| 127 | + return { | |
| 128 | + loading: false, | |
| 129 | + reportOwnerPayFeeInfo: { | |
| 130 | + ownerPayFees: [], | |
| 131 | + moreCondition: false, | |
| 132 | + feeTypeCds: [], | |
| 133 | + feeConfigDtos: [], | |
| 134 | + conditions: { | |
| 135 | + feeTypeCd: '', | |
| 136 | + configId: '', | |
| 137 | + roomName: '', | |
| 138 | + ownerName: '', | |
| 139 | + pfYear: '', | |
| 140 | + page: 1, | |
| 141 | + row: 10, | |
| 142 | + communityId: '' | |
| 143 | + }, | |
| 144 | + timer: null | |
| 145 | + }, | |
| 146 | + pagination: { | |
| 147 | + current: 1, | |
| 148 | + size: 10, | |
| 149 | + total: 0 | |
| 150 | + } | |
| 151 | + } | |
| 152 | + }, | |
| 153 | + created() { | |
| 154 | + this.communityId = getCommunityId() | |
| 155 | + this.reportOwnerPayFeeInfo.conditions.communityId = this.communityId | |
| 156 | + this._initData() | |
| 157 | + }, | |
| 158 | + methods: { | |
| 159 | + async _initData() { | |
| 160 | + try { | |
| 161 | + // 获取费用类型字典 | |
| 162 | + const feeTypeData = await getDict('pay_fee_config', 'fee_type_cd') | |
| 163 | + this.reportOwnerPayFeeInfo.feeTypeCds = feeTypeData | |
| 164 | + | |
| 165 | + // 获取初始列表数据 | |
| 166 | + this._listOwnerPayFees() | |
| 167 | + } catch (error) { | |
| 168 | + console.error('初始化数据失败:', error) | |
| 169 | + } | |
| 170 | + }, | |
| 171 | + async _listOwnerPayFees() { | |
| 172 | + this.loading = true | |
| 173 | + try { | |
| 174 | + const params = { | |
| 175 | + ...this.reportOwnerPayFeeInfo.conditions, | |
| 176 | + page: this.pagination.current, | |
| 177 | + row: this.pagination.size | |
| 178 | + } | |
| 179 | + | |
| 180 | + const { data, total } = await queryReportOwnerPayFee(params) | |
| 181 | + this.reportOwnerPayFeeInfo.ownerPayFees = data | |
| 182 | + this.pagination.total = total | |
| 183 | + } catch (error) { | |
| 184 | + console.error('获取业主缴费明细失败:', error) | |
| 185 | + this.$message.error(this.$t('reportOwnerPayFee.fetchError')) | |
| 186 | + } finally { | |
| 187 | + this.loading = false | |
| 188 | + } | |
| 189 | + }, | |
| 190 | + _queryMethod() { | |
| 191 | + this.pagination.current = 1 | |
| 192 | + this._listOwnerPayFees() | |
| 193 | + }, | |
| 194 | + _resetMethod() { | |
| 195 | + this.reportOwnerPayFeeInfo.conditions = { | |
| 196 | + feeTypeCd: '', | |
| 197 | + configId: '', | |
| 198 | + roomName: '', | |
| 199 | + ownerName: '', | |
| 200 | + pfYear: '', | |
| 201 | + page: 1, | |
| 202 | + row: 10, | |
| 203 | + communityId: this.communityId | |
| 204 | + } | |
| 205 | + this.reportOwnerPayFeeInfo.feeConfigDtos = [] | |
| 206 | + this.pagination.current = 1 | |
| 207 | + this._listOwnerPayFees() | |
| 208 | + }, | |
| 209 | + async _changeReporficientFeeTypeCd() { | |
| 210 | + try { | |
| 211 | + const params = { | |
| 212 | + page: 1, | |
| 213 | + row: 50, | |
| 214 | + communityId: this.communityId, | |
| 215 | + feeTypeCd: this.reportOwnerPayFeeInfo.conditions.feeTypeCd, | |
| 216 | + isDefault: '', | |
| 217 | + feeFlag: '', | |
| 218 | + valid: '1' | |
| 219 | + } | |
| 220 | + | |
| 221 | + const { data } = await listFeeConfigs(params) | |
| 222 | + this.reportOwnerPayFeeInfo.feeConfigDtos = data | |
| 223 | + } catch (error) { | |
| 224 | + console.error('获取收费项失败:', error) | |
| 225 | + } | |
| 226 | + }, | |
| 227 | + _meterInputRoom() { | |
| 228 | + if (this.reportOwnerPayFeeInfo.timer) { | |
| 229 | + clearTimeout(this.reportOwnerPayFeeInfo.timer) | |
| 230 | + } | |
| 231 | + this.reportOwnerPayFeeInfo.timer = setTimeout(() => { | |
| 232 | + this.$refs.inputSearchRoom.open({ | |
| 233 | + callComponent: 'reportOwnerPayFee', | |
| 234 | + roomName: this.reportOwnerPayFeeInfo.conditions.roomName | |
| 235 | + }) | |
| 236 | + }, 1500) | |
| 237 | + }, | |
| 238 | + _meterInputOwner() { | |
| 239 | + if (this.reportOwnerPayFeeInfo.timer) { | |
| 240 | + clearTimeout(this.reportOwnerPayFeeInfo.timer) | |
| 241 | + } | |
| 242 | + this.reportOwnerPayFeeInfo.timer = setTimeout(() => { | |
| 243 | + this.$refs.inputSearchOwner.open({ | |
| 244 | + callComponent: 'reportOwnerPayFee', | |
| 245 | + ownerTypeCd: '1001', | |
| 246 | + ownerName: this.reportOwnerPayFeeInfo.conditions.ownerName | |
| 247 | + }) | |
| 248 | + }, 1500) | |
| 249 | + }, | |
| 250 | + _getAmountByMonth(fee, month) { | |
| 251 | + let amount = 0 | |
| 252 | + if (!fee['reportOwnerPayFeeDtos']) { | |
| 253 | + return amount | |
| 254 | + } | |
| 255 | + const reportOwnerPayFeeDtos = fee.reportOwnerPayFeeDtos | |
| 256 | + if (reportOwnerPayFeeDtos.length === 0) { | |
| 257 | + return amount | |
| 258 | + } | |
| 259 | + reportOwnerPayFeeDtos.forEach(item => { | |
| 260 | + if (item.pfMonth == month) { | |
| 261 | + amount = item.amount | |
| 262 | + return | |
| 263 | + } | |
| 264 | + }) | |
| 265 | + return amount | |
| 266 | + }, | |
| 267 | + _getTotalAmount(fee) { | |
| 268 | + let amount = 0 | |
| 269 | + if (!fee['reportOwnerPayFeeDtos']) { | |
| 270 | + return amount.toFixed(2) | |
| 271 | + } | |
| 272 | + const reportOwnerPayFeeDtos = fee.reportOwnerPayFeeDtos | |
| 273 | + if (reportOwnerPayFeeDtos.length === 0) { | |
| 274 | + return amount.toFixed(2) | |
| 275 | + } | |
| 276 | + reportOwnerPayFeeDtos.forEach(item => { | |
| 277 | + amount += parseFloat(item.amount) | |
| 278 | + }) | |
| 279 | + return amount.toFixed(2) | |
| 280 | + }, | |
| 281 | + _getReceivableTotalAmount(fee) { | |
| 282 | + let amount = 0 | |
| 283 | + if (!fee['reportOwnerPayFeeDtos']) { | |
| 284 | + return amount.toFixed(2) | |
| 285 | + } | |
| 286 | + const reportOwnerPayFeeDtos = fee.reportOwnerPayFeeDtos | |
| 287 | + if (reportOwnerPayFeeDtos.length === 0) { | |
| 288 | + return amount.toFixed(2) | |
| 289 | + } | |
| 290 | + const now = new Date() | |
| 291 | + const month = now.getMonth() + 1 | |
| 292 | + reportOwnerPayFeeDtos.forEach(item => { | |
| 293 | + if (parseInt(item.pfMonth) <= month) { | |
| 294 | + amount += parseFloat(item.amount) | |
| 295 | + } | |
| 296 | + }) | |
| 297 | + return amount.toFixed(2) | |
| 298 | + }, | |
| 299 | + _getCollectTotalAmount(fee) { | |
| 300 | + let amount = 0 | |
| 301 | + if (!fee['reportOwnerPayFeeDtos']) { | |
| 302 | + return amount.toFixed(2) | |
| 303 | + } | |
| 304 | + const reportOwnerPayFeeDtos = fee.reportOwnerPayFeeDtos | |
| 305 | + if (reportOwnerPayFeeDtos.length === 0) { | |
| 306 | + return amount.toFixed(2) | |
| 307 | + } | |
| 308 | + const now = new Date() | |
| 309 | + const month = now.getMonth() + 1 | |
| 310 | + reportOwnerPayFeeDtos.forEach(item => { | |
| 311 | + if (parseInt(item.pfMonth) > month) { | |
| 312 | + amount += parseFloat(item.amount) | |
| 313 | + } | |
| 314 | + }) | |
| 315 | + return amount.toFixed(2) | |
| 316 | + }, | |
| 317 | + _moreCondition() { | |
| 318 | + this.reportOwnerPayFeeInfo.moreCondition = !this.reportOwnerPayFeeInfo.moreCondition | |
| 319 | + }, | |
| 320 | + handleSizeChange(val) { | |
| 321 | + this.pagination.size = val | |
| 322 | + this._listOwnerPayFees() | |
| 323 | + }, | |
| 324 | + handleCurrentChange(val) { | |
| 325 | + this.pagination.current = val | |
| 326 | + this._listOwnerPayFees() | |
| 327 | + } | |
| 328 | + } | |
| 329 | +} | |
| 330 | +</script> | |
| 331 | + | |
| 332 | +<style lang="scss" scoped> | |
| 333 | +.report-owner-pay-fee-container { | |
| 334 | + padding: 20px; | |
| 335 | + background-color: #f0f2f5; | |
| 336 | + | |
| 337 | + .el-card { | |
| 338 | + margin-bottom: 20px; | |
| 339 | + | |
| 340 | + .el-card__header { | |
| 341 | + padding: 18px 20px; | |
| 342 | + border-bottom: 1px solid #ebeef5; | |
| 343 | + box-sizing: border-box; | |
| 344 | + } | |
| 345 | + } | |
| 346 | + | |
| 347 | + .el-row { | |
| 348 | + margin-bottom: 20px; | |
| 349 | + | |
| 350 | + &:last-child { | |
| 351 | + margin-bottom: 0; | |
| 352 | + } | |
| 353 | + } | |
| 354 | + | |
| 355 | + .el-col { | |
| 356 | + border-radius: 4px; | |
| 357 | + } | |
| 358 | + | |
| 359 | + .el-pagination { | |
| 360 | + margin-top: 15px; | |
| 361 | + text-align: right; | |
| 362 | + } | |
| 363 | + | |
| 364 | + .el-icon-info { | |
| 365 | + margin-left: 10px; | |
| 366 | + color: #409EFF; | |
| 367 | + } | |
| 368 | +} | |
| 369 | +</style> | |
| 0 | 370 | \ No newline at end of file | ... | ... |
src/views/report/reportPayFeeDetailLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + reportPayFeeDetail: { | |
| 4 | + search: { | |
| 5 | + title: 'Search Conditions', | |
| 6 | + startTime: 'Please select payment start time', | |
| 7 | + endTime: 'Please select payment end time', | |
| 8 | + paymentMethod: 'Please select payment method', | |
| 9 | + feeStatus: 'Please select fee status', | |
| 10 | + roomOrCarNum: 'Room number or license plate number', | |
| 11 | + feeType: 'Please select fee type', | |
| 12 | + feeItem: 'Please select fee item', | |
| 13 | + feeStartTime: 'Please select fee start time', | |
| 14 | + feeEndTime: 'Please select fee end time', | |
| 15 | + community: 'Please select community' | |
| 16 | + }, | |
| 17 | + table: { | |
| 18 | + title: 'Payment Details', | |
| 19 | + tooltip: 'All house payment records details', | |
| 20 | + orderNum: 'Order Number', | |
| 21 | + roomOwner: 'Room/Owner', | |
| 22 | + feeTypeItem: 'Fee Type > Fee Item', | |
| 23 | + feeStatus: 'Fee Status', | |
| 24 | + paymentMethod: 'Payment Method', | |
| 25 | + paymentPeriod: 'Payment Period', | |
| 26 | + paymentTime: 'Payment Time', | |
| 27 | + cashier: 'Cashier', | |
| 28 | + payableAmount: 'Payable/Receivable Amount(Yuan)', | |
| 29 | + receivedAmount: 'Received Amount(Yuan)', | |
| 30 | + withholdAmount: 'Account Deduction(Yuan)', | |
| 31 | + preferentialAmount: 'Preferential/Deduction Amount(Yuan)', | |
| 32 | + giftAmount: 'Gift Amount(Yuan)', | |
| 33 | + lateFee: 'Late Fee(Yuan)', | |
| 34 | + area: 'Area(sqm)', | |
| 35 | + parkingSpace: 'Parking Space', | |
| 36 | + remark: 'Remark' | |
| 37 | + }, | |
| 38 | + summary: { | |
| 39 | + subtotal: 'Subtotal', | |
| 40 | + total: 'Total', | |
| 41 | + receivable: 'Receivable', | |
| 42 | + received: 'Received', | |
| 43 | + preferential: 'Preferential', | |
| 44 | + deduction: 'Deduction', | |
| 45 | + gift: 'Gift', | |
| 46 | + lateFee: 'Late Fee', | |
| 47 | + yuan: 'Yuan' | |
| 48 | + }, | |
| 49 | + explanation: { | |
| 50 | + preferential: 'Preferential amount: preferential amount generated under discount rules and no arrears discount rules', | |
| 51 | + deduction: 'Deduction amount: deduction amount generated under deduction rules', | |
| 52 | + gift: 'Gift amount: the payable amount of the gifted month under the gift rules', | |
| 53 | + lateFee: 'Late fee: the default late fee generated under the default late fee rules, which needs to be paid additionally' | |
| 54 | + }, | |
| 55 | + hide: 'Hide', | |
| 56 | + more: 'More', | |
| 57 | + fetchError: 'Failed to fetch payment details', | |
| 58 | + exportError: 'Failed to export data', | |
| 59 | + dateError: 'Payment end time must be greater than payment start time' | |
| 60 | + } | |
| 61 | + }, | |
| 62 | + zh: { | |
| 63 | + reportPayFeeDetail: { | |
| 64 | + search: { | |
| 65 | + title: '查询条件', | |
| 66 | + startTime: '请选择缴费开始时间', | |
| 67 | + endTime: '请选择缴费结束时间', | |
| 68 | + paymentMethod: '请选择支付方式', | |
| 69 | + feeStatus: '请选择费用状态', | |
| 70 | + roomOrCarNum: '房屋编号或者车牌号', | |
| 71 | + feeType: '请选择费用类型', | |
| 72 | + feeItem: '请选择收费项', | |
| 73 | + feeStartTime: '请选择收费开始时间', | |
| 74 | + feeEndTime: '请选择收费结束时间', | |
| 75 | + community: '请选择小区' | |
| 76 | + }, | |
| 77 | + table: { | |
| 78 | + title: '缴费明细表', | |
| 79 | + tooltip: '所有房屋缴费记录明细', | |
| 80 | + orderNum: '订单号', | |
| 81 | + roomOwner: '房号/业主', | |
| 82 | + feeTypeItem: '费用类型>费用项', | |
| 83 | + feeStatus: '费用状态', | |
| 84 | + paymentMethod: '支付方式', | |
| 85 | + paymentPeriod: '缴费时间段', | |
| 86 | + paymentTime: '缴费时间', | |
| 87 | + cashier: '收银员', | |
| 88 | + payableAmount: '应缴/应收金额(元)', | |
| 89 | + receivedAmount: '实收金额(元)', | |
| 90 | + withholdAmount: '账户抵扣(元)', | |
| 91 | + preferentialAmount: '优惠/减免金额(元)', | |
| 92 | + giftAmount: '赠送金额(元)', | |
| 93 | + lateFee: '滞纳金(元)', | |
| 94 | + area: '面积(平方米)', | |
| 95 | + parkingSpace: '车位', | |
| 96 | + remark: '说明' | |
| 97 | + }, | |
| 98 | + summary: { | |
| 99 | + subtotal: '小计', | |
| 100 | + total: '大计', | |
| 101 | + receivable: '应收', | |
| 102 | + received: '实收', | |
| 103 | + preferential: '优惠', | |
| 104 | + deduction: '减免', | |
| 105 | + gift: '赠送', | |
| 106 | + lateFee: '滞纳金', | |
| 107 | + yuan: '元' | |
| 108 | + }, | |
| 109 | + explanation: { | |
| 110 | + preferential: '优惠金额:打折规则和打折无欠费规则下产生的优惠金额', | |
| 111 | + deduction: '减免金额:减免规则下产生的减免金额', | |
| 112 | + gift: '赠送金额:赠送规则下赠送月份应缴的金额', | |
| 113 | + lateFee: '滞纳金:违约滞纳金规则下产生的违约金额,需额外缴纳的滞纳金' | |
| 114 | + }, | |
| 115 | + hide: '隐藏', | |
| 116 | + more: '更多', | |
| 117 | + fetchError: '获取缴费明细失败', | |
| 118 | + exportError: '导出数据失败', | |
| 119 | + dateError: '缴费结束时间必须大于缴费开始时间' | |
| 120 | + } | |
| 121 | + } | |
| 122 | +} | |
| 0 | 123 | \ No newline at end of file | ... | ... |
src/views/report/reportPayFeeDetailList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="report-pay-fee-detail-container animated fadeInRight"> | |
| 3 | + <!-- 查询条件 --> | |
| 4 | + <el-card class="search-card"> | |
| 5 | + <div slot="header" class="flex justify-between"> | |
| 6 | + <span>{{ $t('reportPayFeeDetail.search.title') }}</span> | |
| 7 | + <el-button type="text" style="float: right; padding: 3px 0" @click="_moreCondition()"> | |
| 8 | + {{ reportPayFeeDetailInfo.moreCondition ? $t('reportPayFeeDetail.hide') : $t('reportPayFeeDetail.more') }} | |
| 9 | + </el-button> | |
| 10 | + </div> | |
| 11 | + | |
| 12 | + <el-row :gutter="20"> | |
| 13 | + <el-col :span="4"> | |
| 14 | + <el-date-picker v-model="reportPayFeeDetailInfo.conditions.startTime" type="datetime" | |
| 15 | + :placeholder="$t('reportPayFeeDetail.search.startTime')" style="width: 100%" /> | |
| 16 | + </el-col> | |
| 17 | + | |
| 18 | + <el-col :span="4"> | |
| 19 | + <el-date-picker v-model="reportPayFeeDetailInfo.conditions.endTime" type="datetime" | |
| 20 | + :placeholder="$t('reportPayFeeDetail.search.endTime')" style="width: 100%" @change="validateDate" /> | |
| 21 | + </el-col> | |
| 22 | + | |
| 23 | + <el-col :span="4"> | |
| 24 | + <el-select v-model="reportPayFeeDetailInfo.conditions.primeRate" | |
| 25 | + :placeholder="$t('reportPayFeeDetail.search.paymentMethod')" style="width: 100%" clearable> | |
| 26 | + <el-option v-for="(item, index) in reportPayFeeDetailInfo.primeRates" :key="index" :label="item.name" | |
| 27 | + :value="item.statusCd" /> | |
| 28 | + </el-select> | |
| 29 | + </el-col> | |
| 30 | + | |
| 31 | + <el-col :span="4"> | |
| 32 | + <el-select v-model="reportPayFeeDetailInfo.conditions.state" | |
| 33 | + :placeholder="$t('reportPayFeeDetail.search.feeStatus')" style="width: 100%" clearable> | |
| 34 | + <el-option v-for="(item, index) in reportPayFeeDetailInfo.states" :key="index" :label="item.name" | |
| 35 | + :value="item.statusCd" /> | |
| 36 | + </el-select> | |
| 37 | + </el-col> | |
| 38 | + | |
| 39 | + <el-col :span="4"> | |
| 40 | + <el-input v-model="reportPayFeeDetailInfo.conditions.payerObjName" | |
| 41 | + :placeholder="$t('reportPayFeeDetail.search.roomOrCarNum')" clearable /> | |
| 42 | + </el-col> | |
| 43 | + | |
| 44 | + <el-col :span="4"> | |
| 45 | + <el-button type="primary" @click="_queryMethod()"> | |
| 46 | + {{ $t('common.search') }} | |
| 47 | + </el-button> | |
| 48 | + <el-button @click="_resetMethod()"> | |
| 49 | + <i class="el-icon-refresh"></i> | |
| 50 | + {{ $t('common.reset') }} | |
| 51 | + </el-button> | |
| 52 | + </el-col> | |
| 53 | + </el-row> | |
| 54 | + | |
| 55 | + <!-- 更多查询条件 --> | |
| 56 | + <el-row v-show="reportPayFeeDetailInfo.moreCondition" :gutter="20" style="margin-top: 20px"> | |
| 57 | + <el-col :span="4"> | |
| 58 | + <el-select v-model="reportPayFeeDetailInfo.conditions.feeTypeCd" | |
| 59 | + :placeholder="$t('reportPayFeeDetail.search.feeType')" style="width: 100%" clearable @change="_selectConfig"> | |
| 60 | + <el-option v-for="(item, index) in reportPayFeeDetailInfo.feeTypeCds" :key="index" :label="item.name" | |
| 61 | + :value="item.statusCd" /> | |
| 62 | + </el-select> | |
| 63 | + </el-col> | |
| 64 | + | |
| 65 | + <el-col :span="4"> | |
| 66 | + <el-select v-model="reportPayFeeDetailInfo.conditions.configId" | |
| 67 | + :placeholder="$t('reportPayFeeDetail.search.feeItem')" style="width: 100%" clearable> | |
| 68 | + <el-option v-for="(item, index) in reportPayFeeDetailInfo.feeConfigDtos" :key="index" :label="item.feeName" | |
| 69 | + :value="item.configId" /> | |
| 70 | + </el-select> | |
| 71 | + </el-col> | |
| 72 | + | |
| 73 | + <el-col :span="4"> | |
| 74 | + <el-date-picker v-model="reportPayFeeDetailInfo.conditions.feeStartTime" type="datetime" | |
| 75 | + :placeholder="$t('reportPayFeeDetail.search.feeStartTime')" style="width: 100%" /> | |
| 76 | + </el-col> | |
| 77 | + | |
| 78 | + <el-col :span="4"> | |
| 79 | + <el-date-picker v-model="reportPayFeeDetailInfo.conditions.feeEndTime" type="datetime" | |
| 80 | + :placeholder="$t('reportPayFeeDetail.search.feeEndTime')" style="width: 100%" /> | |
| 81 | + </el-col> | |
| 82 | + </el-row> | |
| 83 | + | |
| 84 | + <el-row v-show="reportPayFeeDetailInfo.moreCondition && reportPayFeeDetailInfo.communitys.length > 1" :gutter="20" | |
| 85 | + style="margin-top: 20px"> | |
| 86 | + <el-col :span="4"> | |
| 87 | + <el-select v-model="reportPayFeeDetailInfo.conditions.communityId" | |
| 88 | + :placeholder="$t('reportPayFeeDetail.search.community')" style="width: 100%" clearable | |
| 89 | + @change="_changCommunity"> | |
| 90 | + <el-option v-for="(item, index) in reportPayFeeDetailInfo.communitys" :key="index" :label="item.name" | |
| 91 | + :value="item.communityId" /> | |
| 92 | + </el-select> | |
| 93 | + </el-col> | |
| 94 | + </el-row> | |
| 95 | + </el-card> | |
| 96 | + | |
| 97 | + <!-- 缴费明细表 --> | |
| 98 | + <el-card class="table-card"> | |
| 99 | + <div slot="header" class="flex justify-between"> | |
| 100 | + <div> | |
| 101 | + <span>{{ $t('reportPayFeeDetail.table.title') }}</span> | |
| 102 | + <el-tooltip effect="dark" :content="$t('reportPayFeeDetail.table.tooltip')" placement="top"> | |
| 103 | + <i class="el-icon-info" style="margin-left: 10px; cursor: pointer"></i> | |
| 104 | + </el-tooltip> | |
| 105 | + </div> | |
| 106 | + <el-button type="primary" size="small" style="float: right" @click="_exportFee"> | |
| 107 | + {{ $t('common.export') }} | |
| 108 | + </el-button> | |
| 109 | + </div> | |
| 110 | + | |
| 111 | + <el-table :data="reportPayFeeDetailInfo.fees" border style="width: 100%" v-loading="loading"> | |
| 112 | + <el-table-column prop="oId" :label="$t('reportPayFeeDetail.table.orderNum')" align="center" /> | |
| 113 | + <el-table-column :label="$t('reportPayFeeDetail.table.roomOwner')" align="center" width="120"> | |
| 114 | + <template slot-scope="scope"> | |
| 115 | + <div>{{ scope.row.payerObjName }}/{{ scope.row.ownerName }}</div> | |
| 116 | + </template> | |
| 117 | + </el-table-column> | |
| 118 | + <el-table-column :label="$t('reportPayFeeDetail.table.feeTypeItem')" align="center"> | |
| 119 | + <template slot-scope="scope"> | |
| 120 | + {{ scope.row.feeTypeCdName }}>{{ scope.row.feeName }} | |
| 121 | + </template> | |
| 122 | + </el-table-column> | |
| 123 | + <el-table-column prop="stateName" :label="$t('reportPayFeeDetail.table.feeStatus')" align="center" /> | |
| 124 | + <el-table-column prop="primeRate" :label="$t('reportPayFeeDetail.table.paymentMethod')" align="center" /> | |
| 125 | + <el-table-column :label="$t('reportPayFeeDetail.table.paymentPeriod')" align="center" width="150"> | |
| 126 | + <template slot-scope="scope"> | |
| 127 | + <div>{{ dateFormat(scope.row.startTime) }}</div> | |
| 128 | + <div>~</div> | |
| 129 | + <div>{{ dateFormat(scope.row.endTime) }}</div> | |
| 130 | + </template> | |
| 131 | + </el-table-column> | |
| 132 | + <el-table-column prop="createTime" :label="$t('reportPayFeeDetail.table.paymentTime')" align="center" /> | |
| 133 | + <el-table-column prop="cashierName" :label="$t('reportPayFeeDetail.table.cashier')" align="center" /> | |
| 134 | + <el-table-column :label="$t('reportPayFeeDetail.table.payableAmount')" align="center"> | |
| 135 | + <template slot-scope="scope"> | |
| 136 | + {{ scope.row.payableAmount }}/{{ scope.row.receivableAmount }} | |
| 137 | + </template> | |
| 138 | + </el-table-column> | |
| 139 | + <el-table-column prop="receivedAmount" :label="$t('reportPayFeeDetail.table.receivedAmount')" align="center" /> | |
| 140 | + <el-table-column prop="withholdAmount" :label="$t('reportPayFeeDetail.table.withholdAmount')" align="center" /> | |
| 141 | + <el-table-column :label="$t('reportPayFeeDetail.table.preferentialAmount')" align="center"> | |
| 142 | + <template slot-scope="scope"> | |
| 143 | + {{ scope.row.preferentialAmount }}/{{ scope.row.deductionAmount }} | |
| 144 | + </template> | |
| 145 | + </el-table-column> | |
| 146 | + <el-table-column prop="giftAmount" :label="$t('reportPayFeeDetail.table.giftAmount')" align="center" /> | |
| 147 | + <el-table-column prop="lateFee" :label="$t('reportPayFeeDetail.table.lateFee')" align="center" /> | |
| 148 | + <el-table-column prop="builtUpArea" :label="$t('reportPayFeeDetail.table.area')" align="center" /> | |
| 149 | + <el-table-column prop="psName" :label="$t('reportPayFeeDetail.table.parkingSpace')" align="center" /> | |
| 150 | + <el-table-column prop="remark" :label="$t('reportPayFeeDetail.table.remark')" align="center" width="200" /> | |
| 151 | + </el-table> | |
| 152 | + | |
| 153 | + <!-- 统计信息 --> | |
| 154 | + <el-row class="summary-row"> | |
| 155 | + <el-col :span="24"> | |
| 156 | + <el-row> | |
| 157 | + <el-col :span="2">{{ $t('reportPayFeeDetail.summary.subtotal') }}</el-col> | |
| 158 | + <el-col :span="4"> | |
| 159 | + <div>{{ $t('reportPayFeeDetail.summary.receivable') }}: {{ reportPayFeeDetailInfo.totalReceivableAmount }} | |
| 160 | + {{ | |
| 161 | + $t('reportPayFeeDetail.summary.yuan') }}</div> | |
| 162 | + <div>{{ $t('reportPayFeeDetail.summary.received') }}: {{ reportPayFeeDetailInfo.totalReceivedAmount }} {{ | |
| 163 | + $t('reportPayFeeDetail.summary.yuan') }}</div> | |
| 164 | + </el-col> | |
| 165 | + <el-col :span="4"> | |
| 166 | + <div>{{ $t('reportPayFeeDetail.summary.preferential') }}: {{ reportPayFeeDetailInfo.totalPreferentialAmount | |
| 167 | + }} | |
| 168 | + {{ $t('reportPayFeeDetail.summary.yuan') }}</div> | |
| 169 | + <div>{{ $t('reportPayFeeDetail.summary.deduction') }}: {{ reportPayFeeDetailInfo.totalDeductionAmount }} {{ | |
| 170 | + $t('reportPayFeeDetail.summary.yuan') }}</div> | |
| 171 | + </el-col> | |
| 172 | + <el-col :span="4"> | |
| 173 | + <div>{{ $t('reportPayFeeDetail.summary.gift') }}: {{ reportPayFeeDetailInfo.totalGiftAmount }} {{ | |
| 174 | + $t('reportPayFeeDetail.summary.yuan') }}</div> | |
| 175 | + <div>{{ $t('reportPayFeeDetail.summary.lateFee') }}: {{ reportPayFeeDetailInfo.totalLateFee }} {{ | |
| 176 | + $t('reportPayFeeDetail.summary.yuan') }}</div> | |
| 177 | + </el-col> | |
| 178 | + </el-row> | |
| 179 | + <el-row style="margin-top: 10px"> | |
| 180 | + <el-col :span="2">{{ $t('reportPayFeeDetail.summary.total') }}</el-col> | |
| 181 | + <el-col :span="4"> | |
| 182 | + <div>{{ $t('reportPayFeeDetail.summary.receivable') }}: {{ reportPayFeeDetailInfo.allReceivableAmount }} {{ | |
| 183 | + $t('reportPayFeeDetail.summary.yuan') }}</div> | |
| 184 | + <div>{{ $t('reportPayFeeDetail.summary.received') }}: {{ reportPayFeeDetailInfo.allReceivedAmount }} {{ | |
| 185 | + $t('reportPayFeeDetail.summary.yuan') }}</div> | |
| 186 | + </el-col> | |
| 187 | + <el-col :span="4"> | |
| 188 | + <div>{{ $t('reportPayFeeDetail.summary.preferential') }}: {{ reportPayFeeDetailInfo.allPreferentialAmount }} | |
| 189 | + {{ $t('reportPayFeeDetail.summary.yuan') }}</div> | |
| 190 | + <div>{{ $t('reportPayFeeDetail.summary.deduction') }}: {{ reportPayFeeDetailInfo.allDeductionAmount }} {{ | |
| 191 | + $t('reportPayFeeDetail.summary.yuan') }}</div> | |
| 192 | + </el-col> | |
| 193 | + <el-col :span="4"> | |
| 194 | + <div>{{ $t('reportPayFeeDetail.summary.gift') }}: {{ reportPayFeeDetailInfo.allGiftAmount }} {{ | |
| 195 | + $t('reportPayFeeDetail.summary.yuan') }}</div> | |
| 196 | + <div>{{ $t('reportPayFeeDetail.summary.lateFee') }}: {{ reportPayFeeDetailInfo.allLateFee }} {{ | |
| 197 | + $t('reportPayFeeDetail.summary.yuan') }}</div> | |
| 198 | + </el-col> | |
| 199 | + </el-row> | |
| 200 | + </el-col> | |
| 201 | + </el-row> | |
| 202 | + | |
| 203 | + <!-- 说明 --> | |
| 204 | + <el-row class="explanation-row"> | |
| 205 | + <el-col :span="18"> | |
| 206 | + <div>{{ $t('reportPayFeeDetail.explanation.preferential') }}</div> | |
| 207 | + <div>{{ $t('reportPayFeeDetail.explanation.deduction') }}</div> | |
| 208 | + <div>{{ $t('reportPayFeeDetail.explanation.gift') }}</div> | |
| 209 | + <div>{{ $t('reportPayFeeDetail.explanation.lateFee') }}</div> | |
| 210 | + </el-col> | |
| 211 | + </el-row> | |
| 212 | + | |
| 213 | + <!-- 分页 --> | |
| 214 | + <el-pagination :current-page.sync="currentPage" :page-sizes="[10, 20, 30, 50]" :page-size="pageSize" | |
| 215 | + layout="total, sizes, prev, pager, next, jumper" :total="reportPayFeeDetailInfo.total" | |
| 216 | + @size-change="handleSizeChange" @current-change="handleCurrentChange" /> | |
| 217 | + </el-card> | |
| 218 | + </div> | |
| 219 | +</template> | |
| 220 | + | |
| 221 | +<script> | |
| 222 | +import { queryPayFeeDetail, exportData ,listFeeConfigs} from '@/api/report/reportPayFeeDetailApi' | |
| 223 | +import { getDict } from '@/api/community/communityApi' | |
| 224 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 225 | +import { | |
| 226 | + listMyEnteredCommunitys | |
| 227 | +} from '@/api/report/dataReportApi' | |
| 228 | +import {dateFormat} from '@/utils/dateUtil' | |
| 229 | + | |
| 230 | +export default { | |
| 231 | + name: 'ReportPayFeeDetailList', | |
| 232 | + data() { | |
| 233 | + return { | |
| 234 | + loading: false, | |
| 235 | + currentPage: 1, | |
| 236 | + pageSize: 10, | |
| 237 | + reportPayFeeDetailInfo: { | |
| 238 | + fees: [], | |
| 239 | + total: 0, | |
| 240 | + records: 1, | |
| 241 | + moreCondition: false, | |
| 242 | + primeRates: [], | |
| 243 | + feeConfigDtos: [], | |
| 244 | + states: [], | |
| 245 | + feeTypeCds: [], | |
| 246 | + floors: [], | |
| 247 | + communitys: [], | |
| 248 | + totalReceivableAmount: 0.0, | |
| 249 | + totalReceivedAmount: 0.0, | |
| 250 | + allReceivableAmount: 0.0, | |
| 251 | + allReceivedAmount: 0.0, | |
| 252 | + totalPreferentialAmount: 0.0, | |
| 253 | + totalDeductionAmount: 0.0, | |
| 254 | + totalLateFee: 0.0, | |
| 255 | + totalGiftAmount: 0.0, | |
| 256 | + allPreferentialAmount: 0.0, | |
| 257 | + allDeductionAmount: 0.0, | |
| 258 | + allLateFee: 0.0, | |
| 259 | + allGiftAmount: 0.0, | |
| 260 | + conditions: { | |
| 261 | + floorId: '', | |
| 262 | + roomNum: '', | |
| 263 | + payerObjName: '', | |
| 264 | + configId: '', | |
| 265 | + primeRate: '', | |
| 266 | + state: '', | |
| 267 | + feeTypeCd: '', | |
| 268 | + startTime: '', | |
| 269 | + endTime: '', | |
| 270 | + feeStartTime: '', | |
| 271 | + feeEndTime: '', | |
| 272 | + communityId: '' | |
| 273 | + } | |
| 274 | + } | |
| 275 | + } | |
| 276 | + }, | |
| 277 | + created() { | |
| 278 | + this._initMethod() | |
| 279 | + }, | |
| 280 | + methods: { | |
| 281 | + async _initMethod() { | |
| 282 | + this.reportPayFeeDetailInfo.conditions.communityId = getCommunityId() | |
| 283 | + await this._loadStaffCommunitys() | |
| 284 | + await this._listFees(1, this.pageSize) | |
| 285 | + | |
| 286 | + // 获取字典数据 | |
| 287 | + try { | |
| 288 | + this.reportPayFeeDetailInfo.primeRates = await getDict('pay_fee_detail', 'prime_rate') | |
| 289 | + this.reportPayFeeDetailInfo.states = await getDict('pay_fee_detail', 'state') | |
| 290 | + this.reportPayFeeDetailInfo.feeTypeCds = await getDict('pay_fee_config', 'fee_type_cd') | |
| 291 | + } catch (error) { | |
| 292 | + console.error('获取字典数据失败:', error) | |
| 293 | + } | |
| 294 | + }, | |
| 295 | + | |
| 296 | + async _listFees(page, rows) { | |
| 297 | + this.loading = true | |
| 298 | + try { | |
| 299 | + const params = { | |
| 300 | + ...this.reportPayFeeDetailInfo.conditions, | |
| 301 | + page, | |
| 302 | + row: rows | |
| 303 | + } | |
| 304 | + | |
| 305 | + const { data, total, records, sumTotal } = await queryPayFeeDetail(params) | |
| 306 | + | |
| 307 | + this.reportPayFeeDetailInfo.fees = data.map(item => ({ | |
| 308 | + ...item, | |
| 309 | + lateFee: (item.lateFee * -1).toFixed(2) | |
| 310 | + })) | |
| 311 | + this.reportPayFeeDetailInfo.total = total | |
| 312 | + this.reportPayFeeDetailInfo.records = records | |
| 313 | + | |
| 314 | + // 处理统计信息 | |
| 315 | + this._processSummaryData(sumTotal) | |
| 316 | + } catch (error) { | |
| 317 | + console.error('查询缴费明细失败:', error) | |
| 318 | + this.$message.error(this.$t('reportPayFeeDetail.fetchError')) | |
| 319 | + } finally { | |
| 320 | + this.loading = false | |
| 321 | + } | |
| 322 | + }, | |
| 323 | + | |
| 324 | + _processSummaryData(sumTotal) { | |
| 325 | + const fields = [ | |
| 326 | + 'totalReceivableAmount', 'totalReceivedAmount', 'allReceivableAmount', 'allReceivedAmount', | |
| 327 | + 'totalPreferentialAmount', 'totalDeductionAmount', 'totalLateFee', 'totalGiftAmount', | |
| 328 | + 'allPreferentialAmount', 'allDeductionAmount', 'allLateFee', 'allGiftAmount' | |
| 329 | + ] | |
| 330 | + | |
| 331 | + fields.forEach(field => { | |
| 332 | + this.reportPayFeeDetailInfo[field] = sumTotal[field] | |
| 333 | + ? parseFloat(sumTotal[field]).toFixed(2) | |
| 334 | + : '0.00' | |
| 335 | + }) | |
| 336 | + }, | |
| 337 | + | |
| 338 | + async _loadStaffCommunitys() { | |
| 339 | + try { | |
| 340 | + const params = { | |
| 341 | + _uid: '123mlkdinkldldijdhuudjdjkkd', | |
| 342 | + page: 1, | |
| 343 | + row: 100 | |
| 344 | + } | |
| 345 | + const { communitys } = await listMyEnteredCommunitys(params) | |
| 346 | + this.reportPayFeeDetailInfo.communitys = communitys | |
| 347 | + } catch (error) { | |
| 348 | + console.error('获取小区列表失败:', error) | |
| 349 | + } | |
| 350 | + }, | |
| 351 | + | |
| 352 | + async _selectConfig() { | |
| 353 | + try { | |
| 354 | + const params = { | |
| 355 | + page: 1, | |
| 356 | + row: 50, | |
| 357 | + communityId: this.reportPayFeeDetailInfo.conditions.communityId, | |
| 358 | + feeTypeCd: this.reportPayFeeDetailInfo.conditions.feeTypeCd, | |
| 359 | + isFlag: "0" | |
| 360 | + } | |
| 361 | + const { feeConfigs } = await listFeeConfigs( params) | |
| 362 | + this.reportPayFeeDetailInfo.feeConfigDtos = feeConfigs | |
| 363 | + } catch (error) { | |
| 364 | + console.error('获取费用项失败:', error) | |
| 365 | + } | |
| 366 | + }, | |
| 367 | + | |
| 368 | + _moreCondition() { | |
| 369 | + this.reportPayFeeDetailInfo.moreCondition = !this.reportPayFeeDetailInfo.moreCondition | |
| 370 | + }, | |
| 371 | + | |
| 372 | + async _exportFee() { | |
| 373 | + try { | |
| 374 | + const params = { | |
| 375 | + ...this.reportPayFeeDetailInfo.conditions, | |
| 376 | + pagePath: 'reportPayFeeDetail' | |
| 377 | + } | |
| 378 | + | |
| 379 | + const { code, msg } = await exportData(params) | |
| 380 | + | |
| 381 | + this.$message.success(msg) | |
| 382 | + if (code === 0) { | |
| 383 | + this.$router.push('/pages/property/downloadTempFile?tab=下载中心') | |
| 384 | + } | |
| 385 | + } catch (error) { | |
| 386 | + console.error('导出失败:', error) | |
| 387 | + this.$message.error(this.$t('reportPayFeeDetail.exportError')) | |
| 388 | + } | |
| 389 | + }, | |
| 390 | + | |
| 391 | + _changCommunity() { | |
| 392 | + this._listFees(1, this.pageSize) | |
| 393 | + }, | |
| 394 | + | |
| 395 | + _queryMethod() { | |
| 396 | + this._listFees(1, this.pageSize) | |
| 397 | + }, | |
| 398 | + | |
| 399 | + _resetMethod() { | |
| 400 | + this.reportPayFeeDetailInfo.conditions = { | |
| 401 | + floorId: '', | |
| 402 | + roomNum: '', | |
| 403 | + payerObjName: '', | |
| 404 | + configId: '', | |
| 405 | + primeRate: '', | |
| 406 | + state: '', | |
| 407 | + feeTypeCd: '', | |
| 408 | + startTime: '', | |
| 409 | + endTime: '', | |
| 410 | + feeStartTime: '', | |
| 411 | + feeEndTime: '', | |
| 412 | + communityId: this.reportPayFeeDetailInfo.conditions.communityId | |
| 413 | + } | |
| 414 | + this._listFees(1, this.pageSize) | |
| 415 | + }, | |
| 416 | + | |
| 417 | + validateDate() { | |
| 418 | + if (this.reportPayFeeDetailInfo.conditions.startTime && | |
| 419 | + this.reportPayFeeDetailInfo.conditions.endTime && | |
| 420 | + new Date(this.reportPayFeeDetailInfo.conditions.startTime) >= | |
| 421 | + new Date(this.reportPayFeeDetailInfo.conditions.endTime)) { | |
| 422 | + this.$message.error(this.$t('reportPayFeeDetail.dateError')) | |
| 423 | + this.reportPayFeeDetailInfo.conditions.endTime = '' | |
| 424 | + } | |
| 425 | + }, | |
| 426 | + | |
| 427 | + dateFormat, | |
| 428 | + | |
| 429 | + handleSizeChange(val) { | |
| 430 | + this.pageSize = val | |
| 431 | + this._listFees(this.currentPage, val) | |
| 432 | + }, | |
| 433 | + | |
| 434 | + handleCurrentChange(val) { | |
| 435 | + this.currentPage = val | |
| 436 | + this._listFees(val, this.pageSize) | |
| 437 | + } | |
| 438 | + } | |
| 439 | +} | |
| 440 | +</script> | |
| 441 | + | |
| 442 | +<style lang="scss" scoped> | |
| 443 | +.report-pay-fee-detail-container { | |
| 444 | + padding: 20px; | |
| 445 | + | |
| 446 | + .search-card { | |
| 447 | + margin-bottom: 20px; | |
| 448 | + } | |
| 449 | + | |
| 450 | + .table-card { | |
| 451 | + margin-bottom: 20px; | |
| 452 | + } | |
| 453 | + | |
| 454 | + .summary-row { | |
| 455 | + margin: 20px 0; | |
| 456 | + padding: 15px; | |
| 457 | + background-color: #f5f7fa; | |
| 458 | + border-radius: 4px; | |
| 459 | + } | |
| 460 | + | |
| 461 | + .explanation-row { | |
| 462 | + margin: 20px 0; | |
| 463 | + padding: 15px; | |
| 464 | + background-color: #f5f7fa; | |
| 465 | + border-radius: 4px; | |
| 466 | + color: #909399; | |
| 467 | + font-size: 14px; | |
| 468 | + } | |
| 469 | + | |
| 470 | + .el-pagination { | |
| 471 | + margin-top: 20px; | |
| 472 | + text-align: right; | |
| 473 | + } | |
| 474 | +}</style> | |
| 0 | 475 | \ No newline at end of file | ... | ... |
src/views/report/reportQuestionAnswerDetailLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + reportQuestionAnswerDetail: { | |
| 4 | + queryCondition: 'Query Condition', | |
| 5 | + selectQaType: 'Please select questionnaire type', | |
| 6 | + pleaseSelect: 'Please select', | |
| 7 | + ownerQuestionnaire: 'Owner Questionnaire', | |
| 8 | + ownerVote: 'Owner Vote', | |
| 9 | + staffVote: 'Staff Vote', | |
| 10 | + selectStartTime: 'Please select start time', | |
| 11 | + selectEndTime: 'Please select end time', | |
| 12 | + query: 'Query', | |
| 13 | + reset: 'Reset', | |
| 14 | + questionnaireDetail: 'Questionnaire Detail Table', | |
| 15 | + questionnaireAnswerDetail: 'Questionnaire answer details', | |
| 16 | + export: 'Export', | |
| 17 | + serialNumber: 'No.', | |
| 18 | + questionnairePerson: 'Questionnaire Person', | |
| 19 | + questionnaireType: 'Questionnaire Type', | |
| 20 | + questionnaireName: 'Questionnaire Name', | |
| 21 | + questionnaireQuestion: 'Questionnaire Question', | |
| 22 | + answer: 'Answer', | |
| 23 | + time: 'Time', | |
| 24 | + endTimeMustGreater: 'End time must be greater than start time', | |
| 25 | + fetchError: 'Failed to fetch questionnaire data', | |
| 26 | + exportSuccess: 'Export success', | |
| 27 | + exportError: 'Export failed' | |
| 28 | + } | |
| 29 | + }, | |
| 30 | + zh: { | |
| 31 | + reportQuestionAnswerDetail: { | |
| 32 | + queryCondition: '查询条件', | |
| 33 | + selectQaType: '请选择问卷类型', | |
| 34 | + pleaseSelect: '请选择', | |
| 35 | + ownerQuestionnaire: '业主问卷', | |
| 36 | + ownerVote: '业主投票', | |
| 37 | + staffVote: '员工投票', | |
| 38 | + selectStartTime: '请选择问卷开始时间', | |
| 39 | + selectEndTime: '请选择问卷结束时间', | |
| 40 | + query: '查询', | |
| 41 | + reset: '重置', | |
| 42 | + questionnaireDetail: '问卷明细表', | |
| 43 | + questionnaireAnswerDetail: '问卷回答明细', | |
| 44 | + export: '导出', | |
| 45 | + serialNumber: '序号', | |
| 46 | + questionnairePerson: '问卷人', | |
| 47 | + questionnaireType: '问卷类型', | |
| 48 | + questionnaireName: '问卷名称', | |
| 49 | + questionnaireQuestion: '问卷题目', | |
| 50 | + answer: '答案', | |
| 51 | + time: '时间', | |
| 52 | + endTimeMustGreater: '结束时间必须大于开始时间', | |
| 53 | + fetchError: '获取问卷数据失败', | |
| 54 | + exportSuccess: '导出成功', | |
| 55 | + exportError: '导出失败' | |
| 56 | + } | |
| 57 | + } | |
| 58 | +} | |
| 0 | 59 | \ No newline at end of file | ... | ... |
src/views/report/reportQuestionAnswerDetailList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="report-question-answer-detail-container animated fadeInRight"> | |
| 3 | + <el-row :gutter="20"> | |
| 4 | + <el-col :span="24"> | |
| 5 | + <el-card class="box-card"> | |
| 6 | + <div slot="header" class="flex justify-between"> | |
| 7 | + <span>{{ $t('reportQuestionAnswerDetail.queryCondition') }}</span> | |
| 8 | + </div> | |
| 9 | + <el-form :inline="true" :model="queryForm" class="demo-form-inline text-left"> | |
| 10 | + <el-form-item> | |
| 11 | + <el-select v-model="queryForm.qaType" :placeholder="$t('reportQuestionAnswerDetail.selectQaType')" | |
| 12 | + style="width:100%"> | |
| 13 | + <el-option :label="$t('reportQuestionAnswerDetail.pleaseSelect')" value="" /> | |
| 14 | + <el-option :label="$t('reportQuestionAnswerDetail.ownerQuestionnaire')" value="1001" /> | |
| 15 | + <el-option :label="$t('reportQuestionAnswerDetail.ownerVote')" value="3003" /> | |
| 16 | + <el-option :label="$t('reportQuestionAnswerDetail.staffVote')" value="4004" /> | |
| 17 | + </el-select> | |
| 18 | + </el-form-item> | |
| 19 | + <el-form-item> | |
| 20 | + <el-date-picker v-model="queryForm.startTime" type="date" | |
| 21 | + :placeholder="$t('reportQuestionAnswerDetail.selectStartTime')" style="width:100%" /> | |
| 22 | + </el-form-item> | |
| 23 | + <el-form-item> | |
| 24 | + <el-date-picker v-model="queryForm.endTime" type="date" | |
| 25 | + :placeholder="$t('reportQuestionAnswerDetail.selectEndTime')" style="width:100%" | |
| 26 | + @change="handleEndTimeChange" /> | |
| 27 | + </el-form-item> | |
| 28 | + <el-form-item> | |
| 29 | + <el-button type="primary" @click="handleQuery" icon="el-icon-search"> | |
| 30 | + {{ $t('reportQuestionAnswerDetail.query') }} | |
| 31 | + </el-button> | |
| 32 | + <el-button type="primary" @click="handleReset" icon="el-icon-refresh"> | |
| 33 | + {{ $t('reportQuestionAnswerDetail.reset') }} | |
| 34 | + </el-button> | |
| 35 | + </el-form-item> | |
| 36 | + </el-form> | |
| 37 | + </el-card> | |
| 38 | + </el-col> | |
| 39 | + </el-row> | |
| 40 | + | |
| 41 | + <el-row :gutter="20" style="margin-top:20px"> | |
| 42 | + <el-col :span="24"> | |
| 43 | + <el-card class="box-card"> | |
| 44 | + <div slot="header" class="flex justify-between"> | |
| 45 | + <div> | |
| 46 | + <span>{{ $t('reportQuestionAnswerDetail.questionnaireDetail') }}</span> | |
| 47 | + <el-tooltip class="item" effect="dark" :content="$t('reportQuestionAnswerDetail.questionnaireAnswerDetail')" | |
| 48 | + placement="top"> | |
| 49 | + <i class="el-icon-info" style="cursor:pointer;margin-left:10px"></i> | |
| 50 | + </el-tooltip> | |
| 51 | + </div> | |
| 52 | + <el-button type="primary" size="small" class="float-right" @click="handleExport" icon="el-icon-download"> | |
| 53 | + {{ $t('reportQuestionAnswerDetail.export') }} | |
| 54 | + </el-button> | |
| 55 | + </div> | |
| 56 | + <el-table :data="tableData" border style="width: 100%" v-loading="loading"> | |
| 57 | + <el-table-column prop="index" :label="$t('reportQuestionAnswerDetail.serialNumber')" width="80" | |
| 58 | + align="center" /> | |
| 59 | + <el-table-column prop="userName" :label="$t('reportQuestionAnswerDetail.questionnairePerson')" | |
| 60 | + align="center" /> | |
| 61 | + <el-table-column prop="qaTypeName" :label="$t('reportQuestionAnswerDetail.questionnaireType')" | |
| 62 | + align="center" /> | |
| 63 | + <el-table-column prop="qaName" :label="$t('reportQuestionAnswerDetail.questionnaireName')" align="center" /> | |
| 64 | + <el-table-column prop="qaTitle" :label="$t('reportQuestionAnswerDetail.questionnaireQuestion')" | |
| 65 | + align="center" /> | |
| 66 | + <el-table-column prop="qaValue" :label="$t('reportQuestionAnswerDetail.answer')" align="center" /> | |
| 67 | + <el-table-column prop="createTime" :label="$t('reportQuestionAnswerDetail.time')" align="center" /> | |
| 68 | + </el-table> | |
| 69 | + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" | |
| 70 | + :current-page="pagination.current" :page-sizes="[10, 20, 30, 50]" :page-size="pagination.size" | |
| 71 | + layout="total, sizes, prev, pager, next, jumper" :total="pagination.total" class="pagination-container" /> | |
| 72 | + </el-card> | |
| 73 | + </el-col> | |
| 74 | + </el-row> | |
| 75 | + </div> | |
| 76 | +</template> | |
| 77 | + | |
| 78 | +<script> | |
| 79 | +import { queryUserQuestionAnswerValue, exportData } from '@/api/report/reportQuestionAnswerDetailApi' | |
| 80 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 81 | + | |
| 82 | +export default { | |
| 83 | + name: 'ReportQuestionAnswerDetailList', | |
| 84 | + data() { | |
| 85 | + return { | |
| 86 | + loading: false, | |
| 87 | + queryForm: { | |
| 88 | + qaType: '', | |
| 89 | + startTime: '', | |
| 90 | + endTime: '', | |
| 91 | + communityId: '' | |
| 92 | + }, | |
| 93 | + tableData: [], | |
| 94 | + pagination: { | |
| 95 | + current: 1, | |
| 96 | + size: 10, | |
| 97 | + total: 0 | |
| 98 | + } | |
| 99 | + } | |
| 100 | + }, | |
| 101 | + created() { | |
| 102 | + this.queryForm.communityId = getCommunityId() | |
| 103 | + this.getList() | |
| 104 | + }, | |
| 105 | + methods: { | |
| 106 | + async getList() { | |
| 107 | + try { | |
| 108 | + this.loading = true | |
| 109 | + const params = { | |
| 110 | + page: this.pagination.current, | |
| 111 | + row: this.pagination.size, | |
| 112 | + ...this.queryForm | |
| 113 | + } | |
| 114 | + const { data, total } = await queryUserQuestionAnswerValue(params) | |
| 115 | + this.tableData = data.map((item, index) => { | |
| 116 | + return { | |
| 117 | + ...item, | |
| 118 | + index: index + 1 | |
| 119 | + } | |
| 120 | + }) | |
| 121 | + this.pagination.total = total | |
| 122 | + } catch (error) { | |
| 123 | + this.$message.error(this.$t('reportQuestionAnswerDetail.fetchError')) | |
| 124 | + } finally { | |
| 125 | + this.loading = false | |
| 126 | + } | |
| 127 | + }, | |
| 128 | + handleQuery() { | |
| 129 | + this.pagination.current = 1 | |
| 130 | + this.getList() | |
| 131 | + }, | |
| 132 | + handleReset() { | |
| 133 | + this.queryForm = { | |
| 134 | + qaType: '', | |
| 135 | + startTime: '', | |
| 136 | + endTime: '', | |
| 137 | + communityId: this.queryForm.communityId | |
| 138 | + } | |
| 139 | + this.handleQuery() | |
| 140 | + }, | |
| 141 | + handleEndTimeChange(val) { | |
| 142 | + if (this.queryForm.startTime && val) { | |
| 143 | + const start = new Date(this.queryForm.startTime).getTime() | |
| 144 | + const end = new Date(val).getTime() | |
| 145 | + if (start >= end) { | |
| 146 | + this.$message.error(this.$t('reportQuestionAnswerDetail.endTimeMustGreater')) | |
| 147 | + this.queryForm.endTime = '' | |
| 148 | + } | |
| 149 | + } | |
| 150 | + }, | |
| 151 | + handleSizeChange(val) { | |
| 152 | + this.pagination.size = val | |
| 153 | + this.getList() | |
| 154 | + }, | |
| 155 | + handleCurrentChange(val) { | |
| 156 | + this.pagination.current = val | |
| 157 | + this.getList() | |
| 158 | + }, | |
| 159 | + async handleExport() { | |
| 160 | + try { | |
| 161 | + const params = { | |
| 162 | + ...this.queryForm, | |
| 163 | + pagePath: 'reportQuestionAnswerDetail' | |
| 164 | + } | |
| 165 | + await exportData(params) | |
| 166 | + this.$message.success(this.$t('reportQuestionAnswerDetail.exportSuccess')) | |
| 167 | + } catch (error) { | |
| 168 | + this.$message.error(this.$t('reportQuestionAnswerDetail.exportError')) | |
| 169 | + } | |
| 170 | + } | |
| 171 | + } | |
| 172 | +} | |
| 173 | +</script> | |
| 174 | + | |
| 175 | +<style lang="scss" scoped> | |
| 176 | +.report-question-answer-detail-container { | |
| 177 | + padding: 20px; | |
| 178 | + | |
| 179 | + .box-card { | |
| 180 | + margin-bottom: 20px; | |
| 181 | + } | |
| 182 | + | |
| 183 | + .pagination-container { | |
| 184 | + margin-top: 20px; | |
| 185 | + text-align: right; | |
| 186 | + } | |
| 187 | + | |
| 188 | + .float-right { | |
| 189 | + float: right; | |
| 190 | + } | |
| 191 | +} | |
| 192 | +</style> | |
| 0 | 193 | \ No newline at end of file | ... | ... |
src/views/report/reportRepairLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + reportRepair: { | |
| 4 | + queryCondition: 'Query Conditions', | |
| 5 | + hide: 'Hide', | |
| 6 | + more: 'More', | |
| 7 | + beginStartTimePlaceholder: 'Please select creation start time', | |
| 8 | + beginEndTimePlaceholder: 'Please select creation end time', | |
| 9 | + finishStartTimePlaceholder: 'Please select completion start time', | |
| 10 | + finishEndTimePlaceholder: 'Please select completion end time', | |
| 11 | + communityPlaceholder: 'Please select community', | |
| 12 | + search: 'Search', | |
| 13 | + reset: 'Reset', | |
| 14 | + staffPlaceholder: 'Please select staff name', | |
| 15 | + statePlaceholder: 'Please select status', | |
| 16 | + reportTitle: 'Repair Summary Report', | |
| 17 | + tooltip: 'Display work order summary by staff dimension', | |
| 18 | + export: 'Export', | |
| 19 | + repairId: 'Repair ID', | |
| 20 | + staffId: 'Staff ID', | |
| 21 | + staffName: 'Staff Name', | |
| 22 | + dealing: 'Processing (count)', | |
| 23 | + dispatch: 'Dispatch (count)', | |
| 24 | + transfer: 'Transfer (count)', | |
| 25 | + chargeback: 'Chargeback (count)', | |
| 26 | + returnVisit: 'Return Visit (count)', | |
| 27 | + finished: 'Finished (count)', | |
| 28 | + score: 'Staff Score', | |
| 29 | + statistics: 'Statistics', | |
| 30 | + timeError: 'End time must be greater than start time' | |
| 31 | + } | |
| 32 | + }, | |
| 33 | + zh: { | |
| 34 | + reportRepair: { | |
| 35 | + queryCondition: '查询条件', | |
| 36 | + hide: '隐藏', | |
| 37 | + more: '更多', | |
| 38 | + beginStartTimePlaceholder: '请选择创建开始时间', | |
| 39 | + beginEndTimePlaceholder: '请选择创建结束时间', | |
| 40 | + finishStartTimePlaceholder: '请选择完结开始时间', | |
| 41 | + finishEndTimePlaceholder: '请选择完结结束时间', | |
| 42 | + communityPlaceholder: '请选择小区', | |
| 43 | + search: '查询', | |
| 44 | + reset: '重置', | |
| 45 | + staffPlaceholder: '请选择员工姓名', | |
| 46 | + statePlaceholder: '请选择状态', | |
| 47 | + reportTitle: '报修汇总表', | |
| 48 | + tooltip: '以员工为维度,展示员工处理工单情况汇总', | |
| 49 | + export: '导出', | |
| 50 | + repairId: '报修编号', | |
| 51 | + staffId: '员工ID', | |
| 52 | + staffName: '员工姓名', | |
| 53 | + dealing: '处理中(条)', | |
| 54 | + dispatch: '派单(条)', | |
| 55 | + transfer: '转单(条)', | |
| 56 | + chargeback: '退单(条)', | |
| 57 | + returnVisit: '已回访(条)', | |
| 58 | + finished: '已完结(条)', | |
| 59 | + score: '员工评分', | |
| 60 | + statistics: '统计', | |
| 61 | + timeError: '结束时间必须大于开始时间' | |
| 62 | + } | |
| 63 | + } | |
| 64 | +} | |
| 0 | 65 | \ No newline at end of file | ... | ... |
src/views/report/reportRepairList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="animated fadeInRight report-repair-container"> | |
| 3 | + <el-row :gutter="20"> | |
| 4 | + <el-col :span="24"> | |
| 5 | + <el-card class="box-card"> | |
| 6 | + <div slot="header" class="flex justify-between"> | |
| 7 | + <span>{{ $t('reportRepair.queryCondition') }}</span> | |
| 8 | + <div style="float: right;"> | |
| 9 | + <el-button type="text" @click="_moreCondition()"> | |
| 10 | + {{ reportRepairInfo.moreCondition ? $t('reportRepair.hide') : $t('reportRepair.more') }} | |
| 11 | + </el-button> | |
| 12 | + </div> | |
| 13 | + </div> | |
| 14 | + <div class="card-body"> | |
| 15 | + <el-row :gutter="20"> | |
| 16 | + <el-col :span="4"> | |
| 17 | + <el-date-picker v-model="reportRepairInfo.conditions.beginStartTime" type="date" | |
| 18 | + :placeholder="$t('reportRepair.beginStartTimePlaceholder')" style="width: 100%;" /> | |
| 19 | + </el-col> | |
| 20 | + <el-col :span="4"> | |
| 21 | + <el-date-picker v-model="reportRepairInfo.conditions.beginEndTime" type="date" | |
| 22 | + :placeholder="$t('reportRepair.beginEndTimePlaceholder')" style="width: 100%;" | |
| 23 | + @change="validateBeginTime" /> | |
| 24 | + </el-col> | |
| 25 | + <el-col :span="4"> | |
| 26 | + <el-date-picker v-model="reportRepairInfo.conditions.finishStartTime" type="date" | |
| 27 | + :placeholder="$t('reportRepair.finishStartTimePlaceholder')" style="width: 100%;" /> | |
| 28 | + </el-col> | |
| 29 | + <el-col :span="4"> | |
| 30 | + <el-date-picker v-model="reportRepairInfo.conditions.finishEndTime" type="date" | |
| 31 | + :placeholder="$t('reportRepair.finishEndTimePlaceholder')" style="width: 100%;" | |
| 32 | + @change="validateFinishTime" /> | |
| 33 | + </el-col> | |
| 34 | + <el-col :span="4" v-if="reportRepairInfo.communitys.length > 1"> | |
| 35 | + <el-select v-model="reportRepairInfo.conditions.communityId" | |
| 36 | + :placeholder="$t('reportRepair.communityPlaceholder')" style="width: 100%;" @change="_changCommunity"> | |
| 37 | + <el-option v-for="item in reportRepairInfo.communitys" :key="item.communityId" :label="item.name" | |
| 38 | + :value="item.communityId" /> | |
| 39 | + </el-select> | |
| 40 | + </el-col> | |
| 41 | + <el-col :span="4"> | |
| 42 | + <el-button type="primary" @click="_queryMethod"> | |
| 43 | + <i class="el-icon-search"></i> | |
| 44 | + {{ $t('reportRepair.search') }} | |
| 45 | + </el-button> | |
| 46 | + <el-button @click="_resetMethod" style="margin-left: 10px;"> | |
| 47 | + <i class="el-icon-refresh"></i> | |
| 48 | + {{ $t('reportRepair.reset') }} | |
| 49 | + </el-button> | |
| 50 | + </el-col> | |
| 51 | + </el-row> | |
| 52 | + | |
| 53 | + <el-row :gutter="20" v-show="reportRepairInfo.moreCondition"> | |
| 54 | + <el-col :span="4"> | |
| 55 | + <el-select v-model="reportRepairInfo.conditions.staffId" | |
| 56 | + :placeholder="$t('reportRepair.staffPlaceholder')" style="width: 100%;"> | |
| 57 | + <el-option v-for="item in reportRepairInfo.repairUsers" :key="item.staffId" :label="item.staffName" | |
| 58 | + :value="item.staffId" /> | |
| 59 | + </el-select> | |
| 60 | + </el-col> | |
| 61 | + <el-col :span="4"> | |
| 62 | + <el-select v-model="reportRepairInfo.conditions.state" :placeholder="$t('reportRepair.statePlaceholder')" | |
| 63 | + style="width: 100%;"> | |
| 64 | + <template v-for="item in reportRepairInfo.states"> | |
| 65 | + <el-option :key="item.statusCd" :label="item.name" | |
| 66 | + :value="item.statusCd" v-if="item.statusCd != '10005'" /> | |
| 67 | + </template> | |
| 68 | + </el-select> | |
| 69 | + </el-col> | |
| 70 | + </el-row> | |
| 71 | + </div> | |
| 72 | + </el-card> | |
| 73 | + </el-col> | |
| 74 | + </el-row> | |
| 75 | + | |
| 76 | + <el-row :gutter="20" style="margin-top: 20px;"> | |
| 77 | + <el-col :span="24"> | |
| 78 | + <el-card class="box-card"> | |
| 79 | + <div slot="header" class="flex justify-between"> | |
| 80 | + <div> | |
| 81 | + <span>{{ $t('reportRepair.reportTitle') }}</span> | |
| 82 | + <el-tooltip :content="$t('reportRepair.tooltip')" placement="top"> | |
| 83 | + <i class="el-icon-info" style="cursor: pointer; margin-left: 10px;"></i> | |
| 84 | + </el-tooltip> | |
| 85 | + </div> | |
| 86 | + <div style="float: right;"> | |
| 87 | + <el-button type="primary" size="small" @click="_exportFee"> | |
| 88 | + <i class="el-icon-download"></i> | |
| 89 | + {{ $t('reportRepair.export') }} | |
| 90 | + </el-button> | |
| 91 | + </div> | |
| 92 | + </div> | |
| 93 | + <div class="card-body"> | |
| 94 | + <el-table :data="reportRepairInfo.repairs" border style="width: 100%" v-loading="loading"> | |
| 95 | + <el-table-column prop="index" :label="$t('reportRepair.repairId')" align="center" width="80"> | |
| 96 | + <template slot-scope="scope"> | |
| 97 | + {{ scope.$index + 1 }} | |
| 98 | + </template> | |
| 99 | + </el-table-column> | |
| 100 | + <el-table-column prop="staffId" :label="$t('reportRepair.staffId')" align="center" /> | |
| 101 | + <el-table-column prop="staffName" :label="$t('reportRepair.staffName')" align="center" /> | |
| 102 | + <el-table-column prop="dealAmount" :label="$t('reportRepair.dealing')" align="center" /> | |
| 103 | + <el-table-column prop="dispatchAmount" :label="$t('reportRepair.dispatch')" align="center" /> | |
| 104 | + <el-table-column prop="transferOrderAmount" :label="$t('reportRepair.transfer')" align="center" /> | |
| 105 | + <el-table-column prop="chargebackAmount" :label="$t('reportRepair.chargeback')" align="center" /> | |
| 106 | + <el-table-column prop="returnAmount" :label="$t('reportRepair.returnVisit')" align="center" /> | |
| 107 | + <el-table-column prop="statementAmount" :label="$t('reportRepair.finished')" align="center" /> | |
| 108 | + <el-table-column prop="score" :label="$t('reportRepair.score')" align="center"> | |
| 109 | + <template slot-scope="scope"> | |
| 110 | + {{ scope.row.score || '-' }} | |
| 111 | + </template> | |
| 112 | + </el-table-column> | |
| 113 | + </el-table> | |
| 114 | + | |
| 115 | + <el-table :data="[{}]" border style="width: 100%; margin-top: 20px;"> | |
| 116 | + <el-table-column :label="$t('reportRepair.statistics')" align="center" width="80" | |
| 117 | + class-name="statistics-cell" /> | |
| 118 | + <el-table-column label="---" align="center" class-name="statistics-cell" /> | |
| 119 | + <el-table-column label="---" align="center" class-name="statistics-cell" /> | |
| 120 | + <el-table-column :label="reportRepairInfo.conditions.dealNumber" align="center" | |
| 121 | + class-name="statistics-cell" /> | |
| 122 | + <el-table-column :label="reportRepairInfo.conditions.dispatchNumber" align="center" | |
| 123 | + class-name="statistics-cell" /> | |
| 124 | + <el-table-column :label="reportRepairInfo.conditions.transferOrderNumber" align="center" | |
| 125 | + class-name="statistics-cell" /> | |
| 126 | + <el-table-column :label="reportRepairInfo.conditions.chargebackNumber" align="center" | |
| 127 | + class-name="statistics-cell" /> | |
| 128 | + <el-table-column :label="reportRepairInfo.conditions.returnNumber" align="center" | |
| 129 | + class-name="statistics-cell" /> | |
| 130 | + <el-table-column :label="reportRepairInfo.conditions.statementNumber" align="center" | |
| 131 | + class-name="statistics-cell" /> | |
| 132 | + <el-table-column label="---" align="center" class-name="statistics-cell" /> | |
| 133 | + </el-table> | |
| 134 | + | |
| 135 | + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" | |
| 136 | + :current-page="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size" | |
| 137 | + layout="total, sizes, prev, pager, next, jumper" :total="page.total" style="margin-top: 20px;" /> | |
| 138 | + </div> | |
| 139 | + </el-card> | |
| 140 | + </el-col> | |
| 141 | + </el-row> | |
| 142 | + </div> | |
| 143 | +</template> | |
| 144 | + | |
| 145 | +<script> | |
| 146 | +import { queryRepair, exportData, listMyEnteredCommunitys } from '@/api/report/reportRepairApi' | |
| 147 | +import { getDict } from '@/api/community/communityApi' | |
| 148 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 149 | + | |
| 150 | +export default { | |
| 151 | + name: 'ReportRepairList', | |
| 152 | + data() { | |
| 153 | + return { | |
| 154 | + loading: false, | |
| 155 | + reportRepairInfo: { | |
| 156 | + repairs: [], | |
| 157 | + communitys: [], | |
| 158 | + total: 0, | |
| 159 | + records: 1, | |
| 160 | + moreCondition: false, | |
| 161 | + states: [], | |
| 162 | + repairUsers: [], | |
| 163 | + conditions: { | |
| 164 | + staffId: '', | |
| 165 | + staffName: '', | |
| 166 | + state: '', | |
| 167 | + stateName: '', | |
| 168 | + amount: '', | |
| 169 | + beginStartTime: '', | |
| 170 | + beginEndTime: '', | |
| 171 | + finishStartTime: '', | |
| 172 | + finishEndTime: '', | |
| 173 | + dealNumber: '', | |
| 174 | + dispatchNumber: '', | |
| 175 | + transferOrderNumber: '', | |
| 176 | + chargebackNumber: '', | |
| 177 | + statementNumber: '', | |
| 178 | + returnNumber: '', | |
| 179 | + score: '', | |
| 180 | + communityId: '' | |
| 181 | + } | |
| 182 | + }, | |
| 183 | + page: { | |
| 184 | + current: 1, | |
| 185 | + size: 10, | |
| 186 | + total: 0 | |
| 187 | + } | |
| 188 | + } | |
| 189 | + }, | |
| 190 | + created() { | |
| 191 | + this._initMethod() | |
| 192 | + }, | |
| 193 | + methods: { | |
| 194 | + async _initMethod() { | |
| 195 | + this.reportRepairInfo.conditions.communityId = getCommunityId() | |
| 196 | + await this._loadStaffCommunitys() | |
| 197 | + await this._listRepairs(this.page.current, this.page.size) | |
| 198 | + | |
| 199 | + try { | |
| 200 | + const states = await getDict('r_repair_user', 'state') | |
| 201 | + this.reportRepairInfo.states = states | |
| 202 | + } catch (error) { | |
| 203 | + console.error('获取字典数据失败:', error) | |
| 204 | + } | |
| 205 | + }, | |
| 206 | + validateBeginTime() { | |
| 207 | + if (this.reportRepairInfo.conditions.beginStartTime && this.reportRepairInfo.conditions.beginEndTime) { | |
| 208 | + const start = new Date(this.reportRepairInfo.conditions.beginStartTime).getTime() | |
| 209 | + const end = new Date(this.reportRepairInfo.conditions.beginEndTime).getTime() | |
| 210 | + if (start > end) { | |
| 211 | + this.$message.error(this.$t('reportRepair.timeError')) | |
| 212 | + this.reportRepairInfo.conditions.beginEndTime = '' | |
| 213 | + } | |
| 214 | + } | |
| 215 | + }, | |
| 216 | + validateFinishTime() { | |
| 217 | + if (this.reportRepairInfo.conditions.finishStartTime && this.reportRepairInfo.conditions.finishEndTime) { | |
| 218 | + const start = new Date(this.reportRepairInfo.conditions.finishStartTime).getTime() | |
| 219 | + const end = new Date(this.reportRepairInfo.conditions.finishEndTime).getTime() | |
| 220 | + if (start > end) { | |
| 221 | + this.$message.error(this.$t('reportRepair.timeError')) | |
| 222 | + this.reportRepairInfo.conditions.finishEndTime = '' | |
| 223 | + } | |
| 224 | + } | |
| 225 | + }, | |
| 226 | + async _listRepairs(page, size) { | |
| 227 | + this.loading = true | |
| 228 | + try { | |
| 229 | + const params = { | |
| 230 | + page, | |
| 231 | + row: size, | |
| 232 | + ...this.reportRepairInfo.conditions | |
| 233 | + } | |
| 234 | + | |
| 235 | + const res = await queryRepair(params) | |
| 236 | + this.reportRepairInfo.repairs = res.data | |
| 237 | + this.reportRepairInfo.repairUsers = res.sumTotal | |
| 238 | + this.reportRepairInfo.conditions.dealNumber = res.rep.dealNumber | |
| 239 | + this.reportRepairInfo.conditions.dispatchNumber = res.rep.dispatchNumber | |
| 240 | + this.reportRepairInfo.conditions.transferOrderNumber = res.rep.transferOrderNumber | |
| 241 | + this.reportRepairInfo.conditions.chargebackNumber = res.rep.chargebackNumber | |
| 242 | + this.reportRepairInfo.conditions.statementNumber = res.rep.statementNumber | |
| 243 | + this.reportRepairInfo.conditions.returnNumber = res.rep.returnNumber | |
| 244 | + this.page.total = res.records | |
| 245 | + } catch (error) { | |
| 246 | + console.error('查询报修汇总失败:', error) | |
| 247 | + } finally { | |
| 248 | + this.loading = false | |
| 249 | + } | |
| 250 | + }, | |
| 251 | + _queryMethod() { | |
| 252 | + this.page.current = 1 | |
| 253 | + this._listRepairs(this.page.current, this.page.size) | |
| 254 | + }, | |
| 255 | + _resetMethod() { | |
| 256 | + this.reportRepairInfo.conditions = { | |
| 257 | + ...this.reportRepairInfo.conditions, | |
| 258 | + staffId: '', | |
| 259 | + staffName: '', | |
| 260 | + beginStartTime: '', | |
| 261 | + beginEndTime: '', | |
| 262 | + finishStartTime: '', | |
| 263 | + finishEndTime: '', | |
| 264 | + state: '', | |
| 265 | + stateName: '' | |
| 266 | + } | |
| 267 | + this._listRepairs(this.page.current, this.page.size) | |
| 268 | + }, | |
| 269 | + _moreCondition() { | |
| 270 | + this.reportRepairInfo.moreCondition = !this.reportRepairInfo.moreCondition | |
| 271 | + }, | |
| 272 | + async _exportFee() { | |
| 273 | + try { | |
| 274 | + const params = { | |
| 275 | + pagePath: 'reportRepairDetail', | |
| 276 | + ...this.reportRepairInfo.conditions | |
| 277 | + } | |
| 278 | + | |
| 279 | + const res = await exportData(params ) | |
| 280 | + this.$message.success(res.msg) | |
| 281 | + if (res.code === 0) { | |
| 282 | + this.$router.push('/pages/property/downloadTempFile?tab=下载中心') | |
| 283 | + } | |
| 284 | + } catch (error) { | |
| 285 | + console.error('导出失败:', error) | |
| 286 | + } | |
| 287 | + }, | |
| 288 | + async _loadStaffCommunitys() { | |
| 289 | + try { | |
| 290 | + const params = { | |
| 291 | + _uid: '123mlkdinkldldijdhuudjdjkkd', | |
| 292 | + page: 1, | |
| 293 | + row: 100 | |
| 294 | + } | |
| 295 | + | |
| 296 | + const res = await listMyEnteredCommunitys(params) | |
| 297 | + this.reportRepairInfo.communitys = res.communitys | |
| 298 | + } catch (error) { | |
| 299 | + console.error('获取小区列表失败:', error) | |
| 300 | + } | |
| 301 | + }, | |
| 302 | + _changCommunity() { | |
| 303 | + this._listRepairs(this.page.current, this.page.size) | |
| 304 | + }, | |
| 305 | + handleSizeChange(val) { | |
| 306 | + this.page.size = val | |
| 307 | + this._listRepairs(this.page.current, this.page.size) | |
| 308 | + }, | |
| 309 | + handleCurrentChange(val) { | |
| 310 | + this.page.current = val | |
| 311 | + this._listRepairs(this.page.current, this.page.size) | |
| 312 | + } | |
| 313 | + } | |
| 314 | +} | |
| 315 | +</script> | |
| 316 | + | |
| 317 | +<style lang="scss" scoped> | |
| 318 | +.report-repair-container { | |
| 319 | + padding: 20px; | |
| 320 | + | |
| 321 | + .box-card { | |
| 322 | + margin-bottom: 20px; | |
| 323 | + | |
| 324 | + .clearfix { | |
| 325 | + display: flex; | |
| 326 | + align-items: center; | |
| 327 | + justify-content: space-between; | |
| 328 | + } | |
| 329 | + | |
| 330 | + .card-body { | |
| 331 | + padding: 20px 0; | |
| 332 | + } | |
| 333 | + } | |
| 334 | + | |
| 335 | + .el-table { | |
| 336 | + margin-top: 20px; | |
| 337 | + | |
| 338 | + .statistics-cell { | |
| 339 | + font-size: 18px; | |
| 340 | + color: red; | |
| 341 | + } | |
| 342 | + } | |
| 343 | + | |
| 344 | + .el-pagination { | |
| 345 | + margin-top: 20px; | |
| 346 | + text-align: right; | |
| 347 | + } | |
| 348 | +} | |
| 349 | +</style> | |
| 0 | 350 | \ No newline at end of file | ... | ... |