Commit 95629508a2c5d0ad943f1f3fde8bf73e93e045e3

Authored by wuxw
1 parent 51f9221a

继续开发报表功能

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 &#39;../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
... ...