Commit f61bd6e8e4c3243544baca8a00a4f0a334c5ea87
1 parent
a6fd0349
费用下功能基本搞定
Showing
29 changed files
with
3224 additions
and
99 deletions
src/api/fee/addOweFeeCallableApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | + | ||
| 3 | +// 保存催缴欠费 | ||
| 4 | +export function saveOweFeeCallable(data) { | ||
| 5 | + return new Promise((resolve, reject) => { | ||
| 6 | + request({ | ||
| 7 | + url: '/oweFeeCallable.saveOweFeeCallable', | ||
| 8 | + method: 'post', | ||
| 9 | + data | ||
| 10 | + }).then(response => { | ||
| 11 | + const res = response.data | ||
| 12 | + if (res.code === 0) { | ||
| 13 | + resolve(res) | ||
| 14 | + } else { | ||
| 15 | + reject(new Error(res.msg)) | ||
| 16 | + } | ||
| 17 | + }).catch(error => { | ||
| 18 | + reject(error) | ||
| 19 | + }) | ||
| 20 | + }) | ||
| 21 | +} | ||
| 22 | + | ||
| 23 | +// 导出催缴函Excel | ||
| 24 | +export function exportCollectionLetterExcel(params) { | ||
| 25 | + return new Promise((resolve, reject) => { | ||
| 26 | + request({ | ||
| 27 | + url: '/export.exportData', | ||
| 28 | + method: 'get', | ||
| 29 | + params | ||
| 30 | + }).then(response => { | ||
| 31 | + const res = response.data | ||
| 32 | + if (res.code === 0) { | ||
| 33 | + resolve(res) | ||
| 34 | + } else { | ||
| 35 | + reject(new Error(res.msg)) | ||
| 36 | + } | ||
| 37 | + }).catch(error => { | ||
| 38 | + reject(error) | ||
| 39 | + }) | ||
| 40 | + }) | ||
| 41 | +} | ||
| 42 | + | ||
| 43 | +// 获取费用配置列表 | ||
| 44 | +export function listFeeConfigs(params) { | ||
| 45 | + return new Promise((resolve, reject) => { | ||
| 46 | + request({ | ||
| 47 | + url: '/feeConfig.listFeeConfigs', | ||
| 48 | + method: 'get', | ||
| 49 | + params | ||
| 50 | + }).then(response => { | ||
| 51 | + const res = response.data | ||
| 52 | + if (res.code === 0) { | ||
| 53 | + resolve(res) | ||
| 54 | + } else { | ||
| 55 | + reject(new Error(res.msg)) | ||
| 56 | + } | ||
| 57 | + }).catch(error => { | ||
| 58 | + reject(error) | ||
| 59 | + }) | ||
| 60 | + }) | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +// 查询楼栋列表 | ||
| 64 | +export function queryFloors(params) { | ||
| 65 | + return new Promise((resolve, reject) => { | ||
| 66 | + request({ | ||
| 67 | + url: '/floor.queryFloors', | ||
| 68 | + method: 'get', | ||
| 69 | + params | ||
| 70 | + }).then(response => { | ||
| 71 | + const res = response.data | ||
| 72 | + if (res.code === 0) { | ||
| 73 | + resolve(res) | ||
| 74 | + } else { | ||
| 75 | + reject(new Error(res.msg)) | ||
| 76 | + } | ||
| 77 | + }).catch(error => { | ||
| 78 | + reject(error) | ||
| 79 | + }) | ||
| 80 | + }) | ||
| 81 | +} | ||
| 82 | + | ||
| 83 | +// 查询欠费房屋报表 | ||
| 84 | +export function queryReportOweFee(params) { | ||
| 85 | + return new Promise((resolve, reject) => { | ||
| 86 | + request({ | ||
| 87 | + url: '/reportOweFee/queryReportOweFee', | ||
| 88 | + method: 'get', | ||
| 89 | + params | ||
| 90 | + }).then(response => { | ||
| 91 | + const res = response.data | ||
| 92 | + if (res.code === 0) { | ||
| 93 | + resolve(res) | ||
| 94 | + } else { | ||
| 95 | + reject(new Error(res.msg)) | ||
| 96 | + } | ||
| 97 | + }).catch(error => { | ||
| 98 | + reject(error) | ||
| 99 | + }) | ||
| 100 | + }) | ||
| 101 | +} | ||
| 0 | \ No newline at end of file | 102 | \ No newline at end of file |
src/api/fee/feeApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | + | ||
| 3 | +// 查询费用列表 | ||
| 4 | +export function listFee(params) { | ||
| 5 | + return new Promise((resolve, reject) => { | ||
| 6 | + request({ | ||
| 7 | + url: '/fee.listFee', | ||
| 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 | +} |
src/api/fee/feeSummaryApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | + | ||
| 3 | +// 获取缴费汇总列表 | ||
| 4 | +export function listFeeSummarys(params) { | ||
| 5 | + return new Promise((resolve, reject) => { | ||
| 6 | + request({ | ||
| 7 | + url: '/callComponent/feeSummary/list', | ||
| 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 | +// 导出Excel | ||
| 20 | +export function exportFeeSummary(params) { | ||
| 21 | + return new Promise((resolve, reject) => { | ||
| 22 | + request({ | ||
| 23 | + url: '/feeSummary/export', | ||
| 24 | + method: 'get', | ||
| 25 | + params, | ||
| 26 | + responseType: 'blob' | ||
| 27 | + }).then(response => { | ||
| 28 | + resolve(response) | ||
| 29 | + }).catch(error => { | ||
| 30 | + reject(error) | ||
| 31 | + }) | ||
| 32 | + }) | ||
| 33 | +} | ||
| 0 | \ No newline at end of file | 34 | \ No newline at end of file |
src/api/fee/listOweFeeApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 3 | + | ||
| 4 | +// 查询欠费信息 | ||
| 5 | +export function queryReportOweFee(params) { | ||
| 6 | + return new Promise((resolve, reject) => { | ||
| 7 | + request({ | ||
| 8 | + url: '/reportOweFee/queryReportOweFee', | ||
| 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 | + records: res.records | ||
| 20 | + }) | ||
| 21 | + }).catch(error => { | ||
| 22 | + reject(error) | ||
| 23 | + }) | ||
| 24 | + }) | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +// 查询收费项列表 | ||
| 28 | +export function listFeeConfigs(params) { | ||
| 29 | + return new Promise((resolve, reject) => { | ||
| 30 | + request({ | ||
| 31 | + url: '/feeConfig.listFeeConfigs', | ||
| 32 | + method: 'get', | ||
| 33 | + params: { | ||
| 34 | + ...params, | ||
| 35 | + communityId: params.communityId || getCommunityId() | ||
| 36 | + } | ||
| 37 | + }).then(response => { | ||
| 38 | + const res = response.data | ||
| 39 | + resolve({ | ||
| 40 | + data: res.feeConfigs | ||
| 41 | + }) | ||
| 42 | + }).catch(error => { | ||
| 43 | + reject(error) | ||
| 44 | + }) | ||
| 45 | + }) | ||
| 46 | +} | ||
| 47 | + | ||
| 48 | +// 查询楼栋列表 | ||
| 49 | +export function queryFloors(params) { | ||
| 50 | + return new Promise((resolve, reject) => { | ||
| 51 | + request({ | ||
| 52 | + url: '/floor.queryFloors', | ||
| 53 | + method: 'get', | ||
| 54 | + params: { | ||
| 55 | + ...params, | ||
| 56 | + communityId: params.communityId || getCommunityId() | ||
| 57 | + } | ||
| 58 | + }).then(response => { | ||
| 59 | + const res = response.data | ||
| 60 | + resolve({ | ||
| 61 | + data: res.apiFloorDataVoList, | ||
| 62 | + total: res.records | ||
| 63 | + }) | ||
| 64 | + }).catch(error => { | ||
| 65 | + reject(error) | ||
| 66 | + }) | ||
| 67 | + }) | ||
| 68 | +} | ||
| 69 | + | ||
| 70 | +// 查询单元列表 | ||
| 71 | +export function queryUnits(params) { | ||
| 72 | + return new Promise((resolve, reject) => { | ||
| 73 | + request({ | ||
| 74 | + url: '/unit.queryUnits', | ||
| 75 | + method: 'get', | ||
| 76 | + params: { | ||
| 77 | + ...params, | ||
| 78 | + communityId: params.communityId || getCommunityId() | ||
| 79 | + } | ||
| 80 | + }).then(response => { | ||
| 81 | + const res = response.data | ||
| 82 | + resolve({ | ||
| 83 | + data: res | ||
| 84 | + }) | ||
| 85 | + }).catch(error => { | ||
| 86 | + reject(error) | ||
| 87 | + }) | ||
| 88 | + }) | ||
| 89 | +} | ||
| 90 | + | ||
| 91 | +// 导出数据 | ||
| 92 | +export function exportData(params) { | ||
| 93 | + return new Promise((resolve, reject) => { | ||
| 94 | + request({ | ||
| 95 | + url: '/export.exportData', | ||
| 96 | + method: 'get', | ||
| 97 | + params: { | ||
| 98 | + ...params, | ||
| 99 | + communityId: params.communityId || getCommunityId() | ||
| 100 | + } | ||
| 101 | + }).then(response => { | ||
| 102 | + const res = response.data | ||
| 103 | + resolve(res) | ||
| 104 | + }).catch(error => { | ||
| 105 | + reject(error) | ||
| 106 | + }) | ||
| 107 | + }) | ||
| 108 | +} | ||
| 0 | \ No newline at end of file | 109 | \ No newline at end of file |
src/api/fee/oweFeeCallableApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | + | ||
| 3 | +/** | ||
| 4 | + * 获取欠费催缴列表 | ||
| 5 | + * @param {Object} params 查询参数 | ||
| 6 | + * @returns {Promise} | ||
| 7 | + */ | ||
| 8 | +export function listOweFeeCallable(params) { | ||
| 9 | + return new Promise((resolve, reject) => { | ||
| 10 | + request({ | ||
| 11 | + url: '/oweFeeCallable.listOweFeeCallable', | ||
| 12 | + method: 'get', | ||
| 13 | + params | ||
| 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 | + * 登记欠费催缴 | ||
| 28 | + * @param {Object} data 登记数据 | ||
| 29 | + * @returns {Promise} | ||
| 30 | + */ | ||
| 31 | +export function writeOweFeeCallable(data) { | ||
| 32 | + return new Promise((resolve, reject) => { | ||
| 33 | + request({ | ||
| 34 | + url: '/oweFeeCallable.writeOweFeeCallable', | ||
| 35 | + method: 'post', | ||
| 36 | + data | ||
| 37 | + }).then(response => { | ||
| 38 | + const res = response.data | ||
| 39 | + if (res.code === 0) { | ||
| 40 | + resolve(res) | ||
| 41 | + } else { | ||
| 42 | + reject(new Error(res.msg)) | ||
| 43 | + } | ||
| 44 | + }).catch(error => { | ||
| 45 | + reject(error) | ||
| 46 | + }) | ||
| 47 | + }) | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +/** | ||
| 51 | + * 删除欠费催缴记录 | ||
| 52 | + * @param {Object} data 删除数据 | ||
| 53 | + * @returns {Promise} | ||
| 54 | + */ | ||
| 55 | +export function deleteOweFeeCallable(data) { | ||
| 56 | + return new Promise((resolve, reject) => { | ||
| 57 | + request({ | ||
| 58 | + url: '/oweFeeCallable.deleteOweFeeCallable', | ||
| 59 | + method: 'post', | ||
| 60 | + data | ||
| 61 | + }).then(response => { | ||
| 62 | + const res = response.data | ||
| 63 | + if (res.code === 0) { | ||
| 64 | + resolve(res) | ||
| 65 | + } else { | ||
| 66 | + reject(new Error(res.msg)) | ||
| 67 | + } | ||
| 68 | + }).catch(error => { | ||
| 69 | + reject(error) | ||
| 70 | + }) | ||
| 71 | + }) | ||
| 72 | +} | ||
| 73 | + | ||
| 74 | +/** | ||
| 75 | + * 获取欠费催缴详情 | ||
| 76 | + * @param {String} ofcId 催缴ID | ||
| 77 | + * @returns {Promise} | ||
| 78 | + */ | ||
| 79 | +export function getOweFeeCallableDetail(ofcId) { | ||
| 80 | + return new Promise((resolve, reject) => { | ||
| 81 | + request({ | ||
| 82 | + url: '/oweFeeCallable.getOweFeeCallable', | ||
| 83 | + method: 'get', | ||
| 84 | + params: { ofcId } | ||
| 85 | + }).then(response => { | ||
| 86 | + const res = response.data | ||
| 87 | + if (res.code === 0) { | ||
| 88 | + resolve(res.data) | ||
| 89 | + } else { | ||
| 90 | + reject(new Error(res.msg)) | ||
| 91 | + } | ||
| 92 | + }).catch(error => { | ||
| 93 | + reject(error) | ||
| 94 | + }) | ||
| 95 | + }) | ||
| 96 | +} | ||
| 97 | + | ||
| 98 | +/** | ||
| 99 | + * 更新欠费催缴状态 | ||
| 100 | + * @param {Object} data 更新数据 | ||
| 101 | + * @returns {Promise} | ||
| 102 | + */ | ||
| 103 | +export function updateOweFeeCallableState(data) { | ||
| 104 | + return new Promise((resolve, reject) => { | ||
| 105 | + request({ | ||
| 106 | + url: '/oweFeeCallable.updateOweFeeCallableState', | ||
| 107 | + method: 'post', | ||
| 108 | + data | ||
| 109 | + }).then(response => { | ||
| 110 | + const res = response.data | ||
| 111 | + if (res.code === 0) { | ||
| 112 | + resolve(res) | ||
| 113 | + } else { | ||
| 114 | + reject(new Error(res.msg)) | ||
| 115 | + } | ||
| 116 | + }).catch(error => { | ||
| 117 | + reject(error) | ||
| 118 | + }) | ||
| 119 | + }) | ||
| 120 | +} | ||
| 0 | \ No newline at end of file | 121 | \ No newline at end of file |
src/api/fee/payFeeBatchApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 3 | + | ||
| 4 | +// 获取费用批次列表 | ||
| 5 | +export function listPayFeeBatch(params) { | ||
| 6 | + return new Promise((resolve, reject) => { | ||
| 7 | + request({ | ||
| 8 | + url: '/payFeeBatch.listPayFeeBatch', | ||
| 9 | + method: 'get', | ||
| 10 | + params: { | ||
| 11 | + ...params, | ||
| 12 | + 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 applyDeletePayFeeBatch(data) { | ||
| 25 | + return new Promise((resolve, reject) => { | ||
| 26 | + request({ | ||
| 27 | + url: '/payFeeBatch.applyDeletePayFeeBatchCmd', | ||
| 28 | + method: 'post', | ||
| 29 | + data | ||
| 30 | + }).then(response => { | ||
| 31 | + const res = response.data | ||
| 32 | + resolve(res) | ||
| 33 | + }).catch(error => { | ||
| 34 | + reject(error) | ||
| 35 | + }) | ||
| 36 | + }) | ||
| 37 | +} | ||
| 38 | + | ||
| 39 | +// 更新费用批次状态 | ||
| 40 | +export function updatePayFeeBatch(data) { | ||
| 41 | + return new Promise((resolve, reject) => { | ||
| 42 | + request({ | ||
| 43 | + url: '/payFeeBatch.updatePayFeeBatch', | ||
| 44 | + method: 'post', | ||
| 45 | + data | ||
| 46 | + }).then(response => { | ||
| 47 | + const res = response.data | ||
| 48 | + resolve(res) | ||
| 49 | + }).catch(error => { | ||
| 50 | + reject(error) | ||
| 51 | + }) | ||
| 52 | + }) | ||
| 53 | +} | ||
| 0 | \ No newline at end of file | 54 | \ No newline at end of file |
src/api/fee/staffFeeManageApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | + | ||
| 3 | +// 获取员工收费列表 | ||
| 4 | +export function getStaffFeeList(params) { | ||
| 5 | + return new Promise((resolve, reject) => { | ||
| 6 | + request({ | ||
| 7 | + url: '/api.getStaffFee', | ||
| 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 exportStaffFee(data) { | ||
| 21 | + return new Promise((resolve, reject) => { | ||
| 22 | + request({ | ||
| 23 | + url: '/callComponent/exportReportFee/exportData', | ||
| 24 | + method: 'post', | ||
| 25 | + data | ||
| 26 | + }).then(response => { | ||
| 27 | + const res = response.data | ||
| 28 | + resolve(res) | ||
| 29 | + }).catch(error => { | ||
| 30 | + reject(error) | ||
| 31 | + }) | ||
| 32 | + }) | ||
| 33 | +} | ||
| 0 | \ No newline at end of file | 34 | \ No newline at end of file |
src/components/fee/applyDeleteFeeBatch.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('applyDeleteFeeBatch.title')" | ||
| 4 | + :visible.sync="visible" | ||
| 5 | + width="50%" | ||
| 6 | + @close="handleClose" | ||
| 7 | + > | ||
| 8 | + <el-form | ||
| 9 | + ref="form" | ||
| 10 | + :model="formData" | ||
| 11 | + label-width="120px" | ||
| 12 | + label-position="right" | ||
| 13 | + > | ||
| 14 | + <el-form-item :label="$t('applyDeleteFeeBatch.form.batchId')"> | ||
| 15 | + <el-input | ||
| 16 | + v-model="formData.batchId" | ||
| 17 | + disabled | ||
| 18 | + /> | ||
| 19 | + </el-form-item> | ||
| 20 | + <el-form-item :label="$t('applyDeleteFeeBatch.form.createUserName')"> | ||
| 21 | + <el-input | ||
| 22 | + v-model="formData.createUserName" | ||
| 23 | + disabled | ||
| 24 | + /> | ||
| 25 | + </el-form-item> | ||
| 26 | + <el-form-item :label="$t('applyDeleteFeeBatch.form.createTime')"> | ||
| 27 | + <el-input | ||
| 28 | + v-model="formData.createTime" | ||
| 29 | + disabled | ||
| 30 | + /> | ||
| 31 | + </el-form-item> | ||
| 32 | + <el-form-item | ||
| 33 | + :label="$t('applyDeleteFeeBatch.form.remark')" | ||
| 34 | + prop="remark" | ||
| 35 | + :rules="[ | ||
| 36 | + { required: true, message: $t('applyDeleteFeeBatch.rules.remarkRequired'), trigger: 'blur' } | ||
| 37 | + ]" | ||
| 38 | + > | ||
| 39 | + <el-input | ||
| 40 | + v-model="formData.remark" | ||
| 41 | + type="textarea" | ||
| 42 | + :rows="3" | ||
| 43 | + :placeholder="$t('applyDeleteFeeBatch.placeholder.remark')" | ||
| 44 | + /> | ||
| 45 | + </el-form-item> | ||
| 46 | + </el-form> | ||
| 47 | + <div slot="footer" class="dialog-footer"> | ||
| 48 | + <el-button @click="visible = false"> | ||
| 49 | + {{ $t('common.cancel') }} | ||
| 50 | + </el-button> | ||
| 51 | + <el-button type="primary" @click="handleSubmit"> | ||
| 52 | + {{ $t('common.save') }} | ||
| 53 | + </el-button> | ||
| 54 | + </div> | ||
| 55 | + </el-dialog> | ||
| 56 | +</template> | ||
| 57 | + | ||
| 58 | +<script> | ||
| 59 | +import { applyDeletePayFeeBatch } from '@/api/fee/payFeeBatchApi' | ||
| 60 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 61 | + | ||
| 62 | +export default { | ||
| 63 | + name: 'ApplyDeleteFeeBatch', | ||
| 64 | + data() { | ||
| 65 | + return { | ||
| 66 | + visible: false, | ||
| 67 | + formData: { | ||
| 68 | + batchId: '', | ||
| 69 | + createUserName: '', | ||
| 70 | + createTime: '', | ||
| 71 | + remark: '', | ||
| 72 | + communityId: '' | ||
| 73 | + } | ||
| 74 | + } | ||
| 75 | + }, | ||
| 76 | + methods: { | ||
| 77 | + open(data) { | ||
| 78 | + this.resetForm() | ||
| 79 | + Object.assign(this.formData, data) | ||
| 80 | + this.formData.communityId = getCommunityId() | ||
| 81 | + this.visible = true | ||
| 82 | + }, | ||
| 83 | + handleClose() { | ||
| 84 | + this.$refs.form.resetFields() | ||
| 85 | + }, | ||
| 86 | + resetForm() { | ||
| 87 | + this.formData = { | ||
| 88 | + batchId: '', | ||
| 89 | + createUserName: '', | ||
| 90 | + createTime: '', | ||
| 91 | + remark: '', | ||
| 92 | + communityId: '' | ||
| 93 | + } | ||
| 94 | + }, | ||
| 95 | + handleSubmit() { | ||
| 96 | + this.$refs.form.validate(async valid => { | ||
| 97 | + if (valid) { | ||
| 98 | + try { | ||
| 99 | + await applyDeletePayFeeBatch(this.formData) | ||
| 100 | + this.$message.success(this.$t('applyDeleteFeeBatch.message.success')) | ||
| 101 | + this.visible = false | ||
| 102 | + this.$emit('success') | ||
| 103 | + } catch (error) { | ||
| 104 | + console.error('申请取消失败:', error) | ||
| 105 | + } | ||
| 106 | + } | ||
| 107 | + }) | ||
| 108 | + } | ||
| 109 | + } | ||
| 110 | +} | ||
| 111 | +</script> | ||
| 0 | \ No newline at end of file | 112 | \ No newline at end of file |
src/components/fee/audit.vue
| 1 | <template> | 1 | <template> |
| 2 | <el-dialog | 2 | <el-dialog |
| 3 | - :title="$t('audit.auditInfo')" | 3 | + :title="$t('audit.title')" |
| 4 | :visible.sync="visible" | 4 | :visible.sync="visible" |
| 5 | width="50%" | 5 | width="50%" |
| 6 | @close="handleClose" | 6 | @close="handleClose" |
| 7 | > | 7 | > |
| 8 | - <el-form ref="form" :model="form" :rules="rules" label-width="120px"> | ||
| 9 | - <el-form-item :label="$t('audit.auditStatus')" prop="state"> | ||
| 10 | - <el-select | ||
| 11 | - v-model="form.state" | ||
| 12 | - :placeholder="$t('audit.selectAudit')" | 8 | + <el-form |
| 9 | + ref="form" | ||
| 10 | + :model="formData" | ||
| 11 | + label-width="120px" | ||
| 12 | + label-position="right" | ||
| 13 | + > | ||
| 14 | + <el-form-item | ||
| 15 | + :label="$t('audit.form.state')" | ||
| 16 | + prop="state" | ||
| 17 | + :rules="[ | ||
| 18 | + { required: true, message: $t('audit.rules.stateRequired'), trigger: 'change' } | ||
| 19 | + ]" | ||
| 20 | + > | ||
| 21 | + <el-select | ||
| 22 | + v-model="formData.state" | ||
| 23 | + :placeholder="$t('audit.placeholder.state')" | ||
| 13 | style="width:100%" | 24 | style="width:100%" |
| 14 | - @change="handleStatusChange" | 25 | + @change="handleStateChange" |
| 15 | > | 26 | > |
| 16 | - <el-option | ||
| 17 | - :label="$t('audit.agree')" | 27 | + <el-option |
| 28 | + :label="$t('audit.state.agree')" | ||
| 18 | value="1100" | 29 | value="1100" |
| 19 | /> | 30 | /> |
| 20 | - <el-option | ||
| 21 | - :label="$t('audit.reject')" | 31 | + <el-option |
| 32 | + :label="$t('audit.state.reject')" | ||
| 22 | value="1200" | 33 | value="1200" |
| 23 | /> | 34 | /> |
| 24 | </el-select> | 35 | </el-select> |
| 25 | </el-form-item> | 36 | </el-form-item> |
| 26 | - <el-form-item :label="$t('audit.reason')" prop="remark"> | 37 | + <el-form-item |
| 38 | + :label="$t('audit.form.remark')" | ||
| 39 | + prop="remark" | ||
| 40 | + :rules="[ | ||
| 41 | + { required: true, message: $t('audit.rules.remarkRequired'), trigger: 'blur' }, | ||
| 42 | + { max: 200, message: $t('audit.rules.remarkMaxLength'), trigger: 'blur' } | ||
| 43 | + ]" | ||
| 44 | + > | ||
| 27 | <el-input | 45 | <el-input |
| 28 | - v-model="form.remark" | 46 | + v-model="formData.remark" |
| 29 | type="textarea" | 47 | type="textarea" |
| 30 | - :rows="4" | ||
| 31 | - :placeholder="$t('audit.inputReason')" | 48 | + :rows="3" |
| 49 | + :placeholder="$t('audit.placeholder.remark')" | ||
| 32 | /> | 50 | /> |
| 33 | </el-form-item> | 51 | </el-form-item> |
| 34 | </el-form> | 52 | </el-form> |
| 35 | - <span slot="footer" class="dialog-footer"> | ||
| 36 | - <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button> | ||
| 37 | - <el-button type="primary" @click="handleSubmit">{{ $t('common.submit') }}</el-button> | ||
| 38 | - </span> | 53 | + <div slot="footer" class="dialog-footer"> |
| 54 | + <el-button @click="visible = false"> | ||
| 55 | + {{ $t('common.cancel') }} | ||
| 56 | + </el-button> | ||
| 57 | + <el-button type="primary" @click="handleSubmit"> | ||
| 58 | + {{ $t('common.submit') }} | ||
| 59 | + </el-button> | ||
| 60 | + </div> | ||
| 39 | </el-dialog> | 61 | </el-dialog> |
| 40 | </template> | 62 | </template> |
| 41 | 63 | ||
| 42 | <script> | 64 | <script> |
| 43 | export default { | 65 | export default { |
| 44 | - name: 'AuditModal', | 66 | + name: 'Audit', |
| 45 | data() { | 67 | data() { |
| 46 | return { | 68 | return { |
| 47 | visible: false, | 69 | visible: false, |
| 48 | - form: { | 70 | + formData: { |
| 49 | state: '', | 71 | state: '', |
| 50 | remark: '' | 72 | remark: '' |
| 51 | - }, | ||
| 52 | - rules: { | ||
| 53 | - state: [ | ||
| 54 | - { required: true, message: this.$t('audit.stateRequired'), trigger: 'change' } | ||
| 55 | - ], | ||
| 56 | - remark: [ | ||
| 57 | - { required: true, message: this.$t('audit.reasonRequired'), trigger: 'blur' }, | ||
| 58 | - { max: 200, message: this.$t('audit.reasonMaxLength'), trigger: 'blur' } | ||
| 59 | - ] | ||
| 60 | } | 73 | } |
| 61 | } | 74 | } |
| 62 | }, | 75 | }, |
| 63 | methods: { | 76 | methods: { |
| 64 | open() { | 77 | open() { |
| 78 | + this.resetForm() | ||
| 65 | this.visible = true | 79 | this.visible = true |
| 66 | }, | 80 | }, |
| 67 | handleClose() { | 81 | handleClose() { |
| 68 | this.$refs.form.resetFields() | 82 | this.$refs.form.resetFields() |
| 69 | }, | 83 | }, |
| 70 | - handleStatusChange(val) { | 84 | + resetForm() { |
| 85 | + this.formData = { | ||
| 86 | + state: '', | ||
| 87 | + remark: '' | ||
| 88 | + } | ||
| 89 | + }, | ||
| 90 | + handleStateChange(val) { | ||
| 71 | if (val === '1100') { | 91 | if (val === '1100') { |
| 72 | - this.form.remark = this.$t('audit.agree') | 92 | + this.formData.remark = this.$t('audit.state.agree') |
| 73 | } else { | 93 | } else { |
| 74 | - this.form.remark = '' | 94 | + this.formData.remark = '' |
| 75 | } | 95 | } |
| 76 | }, | 96 | }, |
| 77 | handleSubmit() { | 97 | handleSubmit() { |
| 78 | this.$refs.form.validate(valid => { | 98 | this.$refs.form.validate(valid => { |
| 79 | if (valid) { | 99 | if (valid) { |
| 80 | - const auditInfo = { | ||
| 81 | - state: this.form.state, | ||
| 82 | - remark: this.form.state === '1200' | ||
| 83 | - ? `${this.$t('audit.reject')}: ${this.form.remark}` | ||
| 84 | - : this.form.remark | 100 | + if (this.formData.state === '1200') { |
| 101 | + this.formData.remark = `${this.$t('audit.state.reject')}:${this.formData.remark}` | ||
| 85 | } | 102 | } |
| 86 | - this.$emit('success', auditInfo) | 103 | + this.$emit('success', this.formData) |
| 87 | this.visible = false | 104 | this.visible = false |
| 88 | } | 105 | } |
| 89 | }) | 106 | }) |
src/components/fee/deleteOweFeeCallable.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('oweFeeCallable.delete.title')" | ||
| 4 | + :visible.sync="dialogVisible" | ||
| 5 | + width="30%" | ||
| 6 | + @close="handleClose"> | ||
| 7 | + <div class="delete-content"> | ||
| 8 | + <p>{{ $t('oweFeeCallable.delete.confirm') }}</p> | ||
| 9 | + </div> | ||
| 10 | + <span slot="footer" class="dialog-footer"> | ||
| 11 | + <el-button @click="dialogVisible = false">{{ $t('common.cancel') }}</el-button> | ||
| 12 | + <el-button type="primary" @click="handleConfirm">{{ $t('common.confirm') }}</el-button> | ||
| 13 | + </span> | ||
| 14 | + </el-dialog> | ||
| 15 | +</template> | ||
| 16 | + | ||
| 17 | +<script> | ||
| 18 | +import { deleteOweFeeCallable } from '@/api/fee/oweFeeCallableApi' | ||
| 19 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 20 | + | ||
| 21 | +export default { | ||
| 22 | + name: 'DeleteOweFeeCallable', | ||
| 23 | + data() { | ||
| 24 | + return { | ||
| 25 | + dialogVisible: false, | ||
| 26 | + currentItem: null | ||
| 27 | + } | ||
| 28 | + }, | ||
| 29 | + methods: { | ||
| 30 | + open(item) { | ||
| 31 | + this.currentItem = { | ||
| 32 | + ...item, | ||
| 33 | + communityId: getCommunityId() | ||
| 34 | + } | ||
| 35 | + this.dialogVisible = true | ||
| 36 | + }, | ||
| 37 | + async handleConfirm() { | ||
| 38 | + try { | ||
| 39 | + await deleteOweFeeCallable(this.currentItem) | ||
| 40 | + this.$message.success(this.$t('oweFeeCallable.delete.success')) | ||
| 41 | + this.dialogVisible = false | ||
| 42 | + this.$emit('success') | ||
| 43 | + } catch (error) { | ||
| 44 | + console.error('删除失败:', error) | ||
| 45 | + this.$message.error(error.message || this.$t('oweFeeCallable.delete.error')) | ||
| 46 | + } | ||
| 47 | + }, | ||
| 48 | + handleClose() { | ||
| 49 | + this.currentItem = null | ||
| 50 | + } | ||
| 51 | + } | ||
| 52 | +} | ||
| 53 | +</script> | ||
| 54 | + | ||
| 55 | +<style lang="scss" scoped> | ||
| 56 | +.delete-content { | ||
| 57 | + text-align: center; | ||
| 58 | + font-size: 16px; | ||
| 59 | + padding: 20px 0; | ||
| 60 | +} | ||
| 61 | +</style> | ||
| 0 | \ No newline at end of file | 62 | \ No newline at end of file |
src/components/fee/roomTreeDiv.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-card class="tree-card"> | ||
| 3 | + <el-tree | ||
| 4 | + :data="treeData" | ||
| 5 | + :props="defaultProps" | ||
| 6 | + node-key="id" | ||
| 7 | + default-expand-all | ||
| 8 | + highlight-current | ||
| 9 | + @node-click="handleNodeClick" | ||
| 10 | + :expand-on-click-node="false"> | ||
| 11 | + <span class="custom-tree-node" slot-scope="{ node, data }"> | ||
| 12 | + <span>{{ node.label }}</span> | ||
| 13 | + </span> | ||
| 14 | + </el-tree> | ||
| 15 | + </el-card> | ||
| 16 | +</template> | ||
| 17 | + | ||
| 18 | +<script> | ||
| 19 | +import { queryUnits, queryRoomsTree } from '@/api/property/roomApi' | ||
| 20 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 21 | + | ||
| 22 | +export default { | ||
| 23 | + name: 'RoomTreeDiv', | ||
| 24 | + data() { | ||
| 25 | + return { | ||
| 26 | + treeData: [], | ||
| 27 | + defaultProps: { | ||
| 28 | + children: 'children', | ||
| 29 | + label: 'text' | ||
| 30 | + }, | ||
| 31 | + communityId: '' | ||
| 32 | + } | ||
| 33 | + }, | ||
| 34 | + created() { | ||
| 35 | + this.communityId = getCommunityId() | ||
| 36 | + this.loadTreeData() | ||
| 37 | + }, | ||
| 38 | + methods: { | ||
| 39 | + async loadTreeData() { | ||
| 40 | + try { | ||
| 41 | + const units = await this.getUnits() | ||
| 42 | + this.treeData = this.buildTreeData(units) | ||
| 43 | + } catch (error) { | ||
| 44 | + console.error('加载树数据失败:', error) | ||
| 45 | + } | ||
| 46 | + }, | ||
| 47 | + async getUnits() { | ||
| 48 | + const params = { | ||
| 49 | + communityId: this.communityId | ||
| 50 | + } | ||
| 51 | + const response = await queryUnits(params) | ||
| 52 | + return response.data | ||
| 53 | + }, | ||
| 54 | + buildTreeData(units) { | ||
| 55 | + const floors = {} | ||
| 56 | + | ||
| 57 | + // 按楼层分组 | ||
| 58 | + units.forEach(unit => { | ||
| 59 | + if (!floors[unit.floorId]) { | ||
| 60 | + floors[unit.floorId] = { | ||
| 61 | + id: `f_${unit.floorId}`, | ||
| 62 | + floorId: unit.floorId, | ||
| 63 | + floorNum: unit.floorNum, | ||
| 64 | + text: `${unit.floorNum}栋`, | ||
| 65 | + icon: 'el-icon-office-building', | ||
| 66 | + children: [] | ||
| 67 | + } | ||
| 68 | + } | ||
| 69 | + | ||
| 70 | + floors[unit.floorId].children.push({ | ||
| 71 | + id: `u_${unit.unitId}`, | ||
| 72 | + unitId: unit.unitId, | ||
| 73 | + text: `${unit.unitNum}单元`, | ||
| 74 | + icon: 'el-icon-collection', | ||
| 75 | + children: [] | ||
| 76 | + }) | ||
| 77 | + }) | ||
| 78 | + | ||
| 79 | + return Object.values(floors) | ||
| 80 | + }, | ||
| 81 | + async handleNodeClick(data) { | ||
| 82 | + if (data.id.startsWith('u_')) { | ||
| 83 | + await this.loadRooms(data.unitId, data) | ||
| 84 | + } else if (data.id.startsWith('r_')) { | ||
| 85 | + this.$emit('selectRoom', { | ||
| 86 | + roomId: data.roomId, | ||
| 87 | + roomName: data.text | ||
| 88 | + }) | ||
| 89 | + } | ||
| 90 | + }, | ||
| 91 | + async loadRooms(unitId, node) { | ||
| 92 | + try { | ||
| 93 | + if (node.children && node.children.length > 0) return | ||
| 94 | + | ||
| 95 | + const params = { | ||
| 96 | + unitId: unitId, | ||
| 97 | + communityId: this.communityId, | ||
| 98 | + page: 1, | ||
| 99 | + row: 1000 | ||
| 100 | + } | ||
| 101 | + | ||
| 102 | + const response = await queryRoomsTree(params) | ||
| 103 | + const rooms = response.data.rooms || [] | ||
| 104 | + | ||
| 105 | + rooms.forEach(room => { | ||
| 106 | + let label = room.roomNum | ||
| 107 | + if (room.ownerName) { | ||
| 108 | + label += `(${room.ownerName})` | ||
| 109 | + } | ||
| 110 | + | ||
| 111 | + node.children.push({ | ||
| 112 | + id: `r_${room.roomId}`, | ||
| 113 | + roomId: room.roomId, | ||
| 114 | + text: label, | ||
| 115 | + icon: 'el-icon-house', | ||
| 116 | + roomName: `${room.floorNum}-${room.unitNum}-${room.roomNum}` | ||
| 117 | + }) | ||
| 118 | + }) | ||
| 119 | + | ||
| 120 | + // 默认选择第一个房间 | ||
| 121 | + if (rooms.length > 0) { | ||
| 122 | + const firstRoom = rooms[0] | ||
| 123 | + this.$emit('selectRoom', { | ||
| 124 | + roomId: firstRoom.roomId, | ||
| 125 | + roomName: `${firstRoom.floorNum}-${firstRoom.unitNum}-${firstRoom.roomNum}` | ||
| 126 | + }) | ||
| 127 | + } | ||
| 128 | + } catch (error) { | ||
| 129 | + console.error('加载房间数据失败:', error) | ||
| 130 | + } | ||
| 131 | + } | ||
| 132 | + } | ||
| 133 | +} | ||
| 134 | +</script> | ||
| 135 | + | ||
| 136 | +<style lang="scss" scoped> | ||
| 137 | +.tree-card { | ||
| 138 | + height: 100%; | ||
| 139 | + /deep/ .el-card__body { | ||
| 140 | + padding: 10px; | ||
| 141 | + } | ||
| 142 | + .custom-tree-node { | ||
| 143 | + flex: 1; | ||
| 144 | + display: flex; | ||
| 145 | + align-items: center; | ||
| 146 | + justify-content: space-between; | ||
| 147 | + font-size: 14px; | ||
| 148 | + padding-right: 8px; | ||
| 149 | + } | ||
| 150 | +} | ||
| 151 | +</style> | ||
| 0 | \ No newline at end of file | 152 | \ No newline at end of file |
src/components/fee/searchFloor.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('searchFloor.title')" | ||
| 4 | + :visible.sync="dialogVisible" | ||
| 5 | + width="70%" | ||
| 6 | + @close="handleClose" | ||
| 7 | + > | ||
| 8 | + <el-row :gutter="20"> | ||
| 9 | + <el-col :span="6"> | ||
| 10 | + <el-input | ||
| 11 | + v-model.trim="searchFloorInfo.floorId" | ||
| 12 | + :placeholder="$t('searchFloor.floorId')" | ||
| 13 | + clearable | ||
| 14 | + ></el-input> | ||
| 15 | + </el-col> | ||
| 16 | + <el-col :span="6"> | ||
| 17 | + <el-input | ||
| 18 | + v-model.trim="searchFloorInfo.floorName" | ||
| 19 | + :placeholder="$t('searchFloor.floorName')" | ||
| 20 | + clearable | ||
| 21 | + ></el-input> | ||
| 22 | + </el-col> | ||
| 23 | + <el-col :span="8"> | ||
| 24 | + <el-input | ||
| 25 | + v-model.trim="searchFloorInfo.floorNum" | ||
| 26 | + :placeholder="$t('searchFloor.floorNum')" | ||
| 27 | + clearable | ||
| 28 | + style="margin-right: 10px" | ||
| 29 | + ></el-input> | ||
| 30 | + <el-button type="primary" @click="searchFloors"> | ||
| 31 | + <i class="el-icon-search"></i> | ||
| 32 | + {{ $t('common.search') }} | ||
| 33 | + </el-button> | ||
| 34 | + <el-button type="info" @click="resetFloors"> | ||
| 35 | + <i class="el-icon-refresh"></i> | ||
| 36 | + {{ $t('common.reset') }} | ||
| 37 | + </el-button> | ||
| 38 | + </el-col> | ||
| 39 | + </el-row> | ||
| 40 | + | ||
| 41 | + <el-table | ||
| 42 | + :data="searchFloorInfo.floors" | ||
| 43 | + border | ||
| 44 | + style="width: 100%; margin-top: 20px" | ||
| 45 | + v-loading="loading" | ||
| 46 | + > | ||
| 47 | + <el-table-column | ||
| 48 | + prop="floorId" | ||
| 49 | + :label="$t('searchFloor.table.floorId')" | ||
| 50 | + align="center" | ||
| 51 | + ></el-table-column> | ||
| 52 | + <el-table-column | ||
| 53 | + prop="floorName" | ||
| 54 | + :label="$t('searchFloor.table.floorName')" | ||
| 55 | + align="center" | ||
| 56 | + ></el-table-column> | ||
| 57 | + <el-table-column | ||
| 58 | + prop="floorNum" | ||
| 59 | + :label="$t('searchFloor.table.floorNum')" | ||
| 60 | + align="center" | ||
| 61 | + ></el-table-column> | ||
| 62 | + <el-table-column | ||
| 63 | + prop="userName" | ||
| 64 | + :label="$t('searchFloor.table.userName')" | ||
| 65 | + align="center" | ||
| 66 | + ></el-table-column> | ||
| 67 | + <el-table-column | ||
| 68 | + :label="$t('common.operation')" | ||
| 69 | + align="center" | ||
| 70 | + width="120" | ||
| 71 | + > | ||
| 72 | + <template slot-scope="scope"> | ||
| 73 | + <el-button | ||
| 74 | + type="primary" | ||
| 75 | + size="mini" | ||
| 76 | + @click="chooseFloor(scope.row)" | ||
| 77 | + > | ||
| 78 | + {{ $t('common.select') }} | ||
| 79 | + </el-button> | ||
| 80 | + </template> | ||
| 81 | + </el-table-column> | ||
| 82 | + </el-table> | ||
| 83 | + | ||
| 84 | + <el-pagination | ||
| 85 | + @size-change="handleSizeChange" | ||
| 86 | + @current-change="handleCurrentChange" | ||
| 87 | + :current-page="page.current" | ||
| 88 | + :page-sizes="[10, 20, 30, 50]" | ||
| 89 | + :page-size="page.size" | ||
| 90 | + layout="total, sizes, prev, pager, next, jumper" | ||
| 91 | + :total="page.total" | ||
| 92 | + style="margin-top: 20px;" | ||
| 93 | + ></el-pagination> | ||
| 94 | + </el-dialog> | ||
| 95 | +</template> | ||
| 96 | + | ||
| 97 | +<script> | ||
| 98 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 99 | +import { queryFloors } from '@/api/fee/listOweFeeApi' | ||
| 100 | + | ||
| 101 | +export default { | ||
| 102 | + name: 'SearchFloor', | ||
| 103 | + data() { | ||
| 104 | + return { | ||
| 105 | + dialogVisible: false, | ||
| 106 | + loading: false, | ||
| 107 | + searchFloorInfo: { | ||
| 108 | + floors: [], | ||
| 109 | + floorId: '', | ||
| 110 | + floorName: '', | ||
| 111 | + floorNum: '' | ||
| 112 | + }, | ||
| 113 | + page: { | ||
| 114 | + current: 1, | ||
| 115 | + size: 10, | ||
| 116 | + total: 0 | ||
| 117 | + } | ||
| 118 | + } | ||
| 119 | + }, | ||
| 120 | + methods: { | ||
| 121 | + open() { | ||
| 122 | + this.dialogVisible = true | ||
| 123 | + this.refreshSearchFloorData() | ||
| 124 | + this.loadAllFloorInfo() | ||
| 125 | + }, | ||
| 126 | + async loadAllFloorInfo() { | ||
| 127 | + try { | ||
| 128 | + this.loading = true | ||
| 129 | + const params = { | ||
| 130 | + page: this.page.current, | ||
| 131 | + row: this.page.size, | ||
| 132 | + communityId: getCommunityId(), | ||
| 133 | + floorId: this.searchFloorInfo.floorId, | ||
| 134 | + floorName: this.searchFloorInfo.floorName, | ||
| 135 | + floorNum: this.searchFloorInfo.floorNum | ||
| 136 | + } | ||
| 137 | + const { data, total } = await queryFloors(params) | ||
| 138 | + this.searchFloorInfo.floors = data | ||
| 139 | + this.page.total = total | ||
| 140 | + } catch (error) { | ||
| 141 | + console.error('获取楼栋信息失败:', error) | ||
| 142 | + } finally { | ||
| 143 | + this.loading = false | ||
| 144 | + } | ||
| 145 | + }, | ||
| 146 | + chooseFloor(floor) { | ||
| 147 | + this.$emit('chooseFloor', floor) | ||
| 148 | + this.dialogVisible = false | ||
| 149 | + }, | ||
| 150 | + searchFloors() { | ||
| 151 | + this.page.current = 1 | ||
| 152 | + this.loadAllFloorInfo() | ||
| 153 | + }, | ||
| 154 | + resetFloors() { | ||
| 155 | + this.searchFloorInfo.floorId = '' | ||
| 156 | + this.searchFloorInfo.floorName = '' | ||
| 157 | + this.searchFloorInfo.floorNum = '' | ||
| 158 | + this.page.current = 1 | ||
| 159 | + this.loadAllFloorInfo() | ||
| 160 | + }, | ||
| 161 | + refreshSearchFloorData() { | ||
| 162 | + this.searchFloorInfo.floorId = '' | ||
| 163 | + this.searchFloorInfo.floorName = '' | ||
| 164 | + this.searchFloorInfo.floorNum = '' | ||
| 165 | + }, | ||
| 166 | + handleClose() { | ||
| 167 | + this.refreshSearchFloorData() | ||
| 168 | + }, | ||
| 169 | + handleSizeChange(val) { | ||
| 170 | + this.page.size = val | ||
| 171 | + this.loadAllFloorInfo() | ||
| 172 | + }, | ||
| 173 | + handleCurrentChange(val) { | ||
| 174 | + this.page.current = val | ||
| 175 | + this.loadAllFloorInfo() | ||
| 176 | + } | ||
| 177 | + } | ||
| 178 | +} | ||
| 179 | +</script> | ||
| 180 | + | ||
| 181 | +<style lang="scss" scoped> | ||
| 182 | +.el-dialog { | ||
| 183 | + .el-row { | ||
| 184 | + margin-bottom: 20px; | ||
| 185 | + } | ||
| 186 | +} | ||
| 187 | +</style> | ||
| 0 | \ No newline at end of file | 188 | \ No newline at end of file |
src/components/fee/writeOweFeeCallable.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog :title="$t('oweFeeCallable.write.title')" :visible.sync="dialogVisible" width="50%" @close="handleClose"> | ||
| 3 | + <el-form :model="form" label-width="120px" ref="form"> | ||
| 4 | + <el-form-item :label="$t('oweFeeCallable.write.roomName')" prop="roomName"> | ||
| 5 | + <el-input v-model="form.roomName" disabled></el-input> | ||
| 6 | + </el-form-item> | ||
| 7 | + <el-form-item :label="$t('oweFeeCallable.write.feeName')" prop="feeIds"> | ||
| 8 | + <el-checkbox-group v-model="form.feeIds"> | ||
| 9 | + <el-checkbox v-for="fee in form.fees" :key="fee.feeId" :label="fee.feeId"> | ||
| 10 | + {{ fee.feeName }} | ||
| 11 | + </el-checkbox> | ||
| 12 | + </el-checkbox-group> | ||
| 13 | + </el-form-item> | ||
| 14 | + <el-form-item :label="$t('oweFeeCallable.write.remark')" prop="remark"> | ||
| 15 | + <el-input type="textarea" :rows="5" v-model="form.remark" | ||
| 16 | + :placeholder="$t('oweFeeCallable.write.remarkPlaceholder')"> | ||
| 17 | + </el-input> | ||
| 18 | + </el-form-item> | ||
| 19 | + </el-form> | ||
| 20 | + <span slot="footer" class="dialog-footer"> | ||
| 21 | + <el-button @click="dialogVisible = false">{{ $t('common.cancel') }}</el-button> | ||
| 22 | + <el-button type="primary" @click="handleSubmit">{{ $t('common.submit') }}</el-button> | ||
| 23 | + </span> | ||
| 24 | + </el-dialog> | ||
| 25 | +</template> | ||
| 26 | + | ||
| 27 | +<script> | ||
| 28 | +import { listFee } from '@/api/fee/feeApi' | ||
| 29 | +import { writeOweFeeCallable } from '@/api/fee/oweFeeCallableApi' | ||
| 30 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 31 | + | ||
| 32 | +export default { | ||
| 33 | + name: 'WriteOweFeeCallable', | ||
| 34 | + data() { | ||
| 35 | + return { | ||
| 36 | + dialogVisible: false, | ||
| 37 | + form: { | ||
| 38 | + roomId: '', | ||
| 39 | + roomName: '', | ||
| 40 | + fees: [], | ||
| 41 | + feeIds: [], | ||
| 42 | + remark: '', | ||
| 43 | + communityId: '' | ||
| 44 | + } | ||
| 45 | + } | ||
| 46 | + }, | ||
| 47 | + methods: { | ||
| 48 | + open(data) { | ||
| 49 | + this.form = { | ||
| 50 | + roomId: data.roomId, | ||
| 51 | + roomName: data.roomName, | ||
| 52 | + fees: [], | ||
| 53 | + feeIds: [], | ||
| 54 | + remark: '', | ||
| 55 | + communityId: getCommunityId() | ||
| 56 | + } | ||
| 57 | + this.loadFees() | ||
| 58 | + this.dialogVisible = true | ||
| 59 | + }, | ||
| 60 | + async loadFees() { | ||
| 61 | + try { | ||
| 62 | + const params = { | ||
| 63 | + communityId: this.form.communityId, | ||
| 64 | + payerObjId: this.form.roomId, | ||
| 65 | + state: '2008001', | ||
| 66 | + page: 1, | ||
| 67 | + row: 100 | ||
| 68 | + } | ||
| 69 | + const response = await listFee(params) | ||
| 70 | + this.form.fees = response.data.fees || [] | ||
| 71 | + } catch (error) { | ||
| 72 | + console.error('加载费用数据失败:', error) | ||
| 73 | + } | ||
| 74 | + }, | ||
| 75 | + async handleSubmit() { | ||
| 76 | + try { | ||
| 77 | + await writeOweFeeCallable(this.form) | ||
| 78 | + this.$message.success(this.$t('oweFeeCallable.write.success')) | ||
| 79 | + this.dialogVisible = false | ||
| 80 | + this.$emit('success') | ||
| 81 | + } catch (error) { | ||
| 82 | + console.error('提交失败:', error) | ||
| 83 | + this.$message.error(error.message || this.$t('oweFeeCallable.write.error')) | ||
| 84 | + } | ||
| 85 | + }, | ||
| 86 | + handleClose() { | ||
| 87 | + this.$refs.form.resetFields() | ||
| 88 | + } | ||
| 89 | + } | ||
| 90 | +} | ||
| 91 | +</script> | ||
| 92 | + | ||
| 93 | +<style lang="scss" scoped> | ||
| 94 | +.el-checkbox { | ||
| 95 | + margin-right: 15px; | ||
| 96 | +} | ||
| 97 | +</style> | ||
| 0 | \ No newline at end of file | 98 | \ No newline at end of file |
src/i18n/feeI18n.js
| @@ -17,6 +17,12 @@ import { messages as shareReadingFeeMessages } from '../views/fee/shareReadingFe | @@ -17,6 +17,12 @@ import { messages as shareReadingFeeMessages } from '../views/fee/shareReadingFe | ||
| 17 | import { messages as feeComboManageMessages } from '../views/fee/feeComboManageLang' | 17 | import { messages as feeComboManageMessages } from '../views/fee/feeComboManageLang' |
| 18 | import { messages as payFeeAuditManageMessages } from '../views/fee/payFeeAuditManageLang' | 18 | import { messages as payFeeAuditManageMessages } from '../views/fee/payFeeAuditManageLang' |
| 19 | import { messages as feeComboMemberManageMessages } from '../views/fee/feeComboMemberManageLang' | 19 | import { messages as feeComboMemberManageMessages } from '../views/fee/feeComboMemberManageLang' |
| 20 | +import { messages as payFeeBatchMessages } from '../views/fee/payFeeBatchLang' | ||
| 21 | +import { messages as listOweFeeMessages } from '../views/fee/listOweFeeLang' | ||
| 22 | +import { messages as oweFeeCallableMessages } from '../views/fee/oweFeeCallableLang' | ||
| 23 | +import { messages as addOweFeeCallableMessages } from '../views/fee/addOweFeeCallableLang' | ||
| 24 | +import { messages as staffFeeManageMessages } from '../views/fee/staffFeeManageLang' | ||
| 25 | +import { messages as feeSummaryMessages } from '../views/fee/feeSummaryLang' | ||
| 20 | 26 | ||
| 21 | export const messages = { | 27 | export const messages = { |
| 22 | en: { | 28 | en: { |
| @@ -39,6 +45,12 @@ export const messages = { | @@ -39,6 +45,12 @@ export const messages = { | ||
| 39 | ...feeComboManageMessages.en, | 45 | ...feeComboManageMessages.en, |
| 40 | ...payFeeAuditManageMessages.en, | 46 | ...payFeeAuditManageMessages.en, |
| 41 | ...feeComboMemberManageMessages.en, | 47 | ...feeComboMemberManageMessages.en, |
| 48 | + ...payFeeBatchMessages.en, | ||
| 49 | + ...listOweFeeMessages.en, | ||
| 50 | + ...oweFeeCallableMessages.en, | ||
| 51 | + ...addOweFeeCallableMessages.en, | ||
| 52 | + ...staffFeeManageMessages.en, | ||
| 53 | + ...feeSummaryMessages.en, | ||
| 42 | }, | 54 | }, |
| 43 | zh: { | 55 | zh: { |
| 44 | ...contractCreateFeeMessages.zh, | 56 | ...contractCreateFeeMessages.zh, |
| @@ -60,5 +72,11 @@ export const messages = { | @@ -60,5 +72,11 @@ export const messages = { | ||
| 60 | ...feeComboManageMessages.zh, | 72 | ...feeComboManageMessages.zh, |
| 61 | ...payFeeAuditManageMessages.zh, | 73 | ...payFeeAuditManageMessages.zh, |
| 62 | ...feeComboMemberManageMessages.zh, | 74 | ...feeComboMemberManageMessages.zh, |
| 75 | + ...payFeeBatchMessages.zh, | ||
| 76 | + ...listOweFeeMessages.zh, | ||
| 77 | + ...oweFeeCallableMessages.zh, | ||
| 78 | + ...addOweFeeCallableMessages.zh, | ||
| 79 | + ...staffFeeManageMessages.zh, | ||
| 80 | + ...feeSummaryMessages.zh, | ||
| 63 | } | 81 | } |
| 64 | } | 82 | } |
| 65 | \ No newline at end of file | 83 | \ No newline at end of file |
src/router/feeRouter.js
| @@ -79,5 +79,35 @@ export default [ | @@ -79,5 +79,35 @@ export default [ | ||
| 79 | name: '/views/fee/feeComboMemberManage', | 79 | name: '/views/fee/feeComboMemberManage', |
| 80 | component: () => import('@/views/fee/feeComboMemberManageList.vue') | 80 | component: () => import('@/views/fee/feeComboMemberManageList.vue') |
| 81 | }, | 81 | }, |
| 82 | + { | ||
| 83 | + path: '/pages/property/payFeeBatch', | ||
| 84 | + name: '/pages/property/payFeeBatch', | ||
| 85 | + component: () => import('@/views/fee/payFeeBatchList.vue') | ||
| 86 | + }, | ||
| 87 | + { | ||
| 88 | + path: '/pages/property/listOweFee', | ||
| 89 | + name: '/pages/property/listOweFee', | ||
| 90 | + component: () => import('@/views/fee/listOweFeeList.vue') | ||
| 91 | + }, | ||
| 92 | + { | ||
| 93 | + path: '/pages/fee/oweFeeCallable', | ||
| 94 | + name: '/pages/fee/oweFeeCallable', | ||
| 95 | + component: () => import('@/views/fee/oweFeeCallableList.vue') | ||
| 96 | + }, | ||
| 97 | + { | ||
| 98 | + path: '/views/fee/addOweFeeCallable', | ||
| 99 | + name: '/views/fee/addOweFeeCallable', | ||
| 100 | + component: () => import('@/views/fee/addOweFeeCallableList.vue') | ||
| 101 | + }, | ||
| 102 | + { | ||
| 103 | + path: '/pages/property/staffFeeManage', | ||
| 104 | + name: '/pages/property/staffFeeManage', | ||
| 105 | + component: () => import('@/views/fee/staffFeeManageList.vue') | ||
| 106 | + }, | ||
| 107 | + { | ||
| 108 | + path: '/pages/property/feeSummary', | ||
| 109 | + name: '/pages/property/feeSummary', | ||
| 110 | + component: () => import('@/views/fee/feeSummaryList.vue') | ||
| 111 | + }, | ||
| 82 | 112 | ||
| 83 | ] | 113 | ] |
| 84 | \ No newline at end of file | 114 | \ No newline at end of file |
src/views/fee/addOweFeeCallableLang.js
0 → 100644
| 1 | +export const messages = { | ||
| 2 | + en: { | ||
| 3 | + addOweFeeCallable: { | ||
| 4 | + title: 'Collection of Arrears', | ||
| 5 | + callableWay: 'Collection Method', | ||
| 6 | + selectCallableWay: 'Please select collection method', | ||
| 7 | + feeConfigs: 'Collection Fees', | ||
| 8 | + floor: 'Building', | ||
| 9 | + selectFloor: 'Please select building', | ||
| 10 | + timeRange: 'Time Range', | ||
| 11 | + selectTimeRange: 'Please select time range', | ||
| 12 | + startTime: 'Start Time', | ||
| 13 | + selectStartTime: 'Please select start time', | ||
| 14 | + endTime: 'End Time', | ||
| 15 | + selectEndTime: 'Please select end time', | ||
| 16 | + oweRooms: 'Arrears Rooms', | ||
| 17 | + noOweRooms: 'No arrears rooms', | ||
| 18 | + checkAll: 'Select All', | ||
| 19 | + ttsCall: 'Voice Collection', | ||
| 20 | + callableWayRequired: 'Collection method is required', | ||
| 21 | + roomsRequired: 'Please select arrears rooms', | ||
| 22 | + noOweRoomsSelected: 'No arrears rooms selected' | ||
| 23 | + } | ||
| 24 | + }, | ||
| 25 | + zh: { | ||
| 26 | + addOweFeeCallable: { | ||
| 27 | + title: '催缴欠费', | ||
| 28 | + callableWay: '催缴方式', | ||
| 29 | + selectCallableWay: '请选择催缴方式', | ||
| 30 | + feeConfigs: '催缴费用', | ||
| 31 | + floor: '楼栋', | ||
| 32 | + selectFloor: '请选择楼栋', | ||
| 33 | + timeRange: '应收时间段', | ||
| 34 | + selectTimeRange: '请选择应收时间段', | ||
| 35 | + startTime: '开始时间', | ||
| 36 | + selectStartTime: '请选择开始时间', | ||
| 37 | + endTime: '结束时间', | ||
| 38 | + selectEndTime: '请选择结束时间', | ||
| 39 | + oweRooms: '欠费房屋', | ||
| 40 | + noOweRooms: '没有欠费房屋', | ||
| 41 | + checkAll: '全选', | ||
| 42 | + ttsCall: '语音催缴', | ||
| 43 | + callableWayRequired: '催缴方式不能为空', | ||
| 44 | + roomsRequired: '请选择欠费房屋', | ||
| 45 | + noOweRoomsSelected: '未选择欠费房屋' | ||
| 46 | + } | ||
| 47 | + } | ||
| 48 | +} | ||
| 0 | \ No newline at end of file | 49 | \ No newline at end of file |
src/views/fee/addOweFeeCallableList.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="add-owe-fee-callable-container"> | ||
| 3 | + <el-card> | ||
| 4 | + <div slot="header" class="clearfix"> | ||
| 5 | + <span>{{ $t('addOweFeeCallable.title') }}</span> | ||
| 6 | + </div> | ||
| 7 | + | ||
| 8 | + <el-form label-position="right" label-width="120px"> | ||
| 9 | + <el-row :gutter="20"> | ||
| 10 | + <el-col :span="24"> | ||
| 11 | + <el-form-item :label="$t('addOweFeeCallable.callableWay')"> | ||
| 12 | + <el-select | ||
| 13 | + v-model="addOweFeeCallableInfo.callableWay" | ||
| 14 | + style="width:100%" | ||
| 15 | + :placeholder="$t('addOweFeeCallable.selectCallableWay')"> | ||
| 16 | + <el-option | ||
| 17 | + v-for="item in callableWayOptions" | ||
| 18 | + :key="item.value" | ||
| 19 | + :label="item.label" | ||
| 20 | + :value="item.value"> | ||
| 21 | + </el-option> | ||
| 22 | + </el-select> | ||
| 23 | + </el-form-item> | ||
| 24 | + </el-col> | ||
| 25 | + </el-row> | ||
| 26 | + | ||
| 27 | + <el-row :gutter="20"> | ||
| 28 | + <el-col :span="24"> | ||
| 29 | + <el-form-item :label="$t('addOweFeeCallable.feeConfigs')"> | ||
| 30 | + <el-checkbox-group v-model="addOweFeeCallableInfo.configIds" @change="loadOweFeeRooms"> | ||
| 31 | + <el-checkbox | ||
| 32 | + v-for="item in addOweFeeCallableInfo.feeConfigs" | ||
| 33 | + :key="item.configId" | ||
| 34 | + :label="item.configId"> | ||
| 35 | + {{item.feeName}} | ||
| 36 | + </el-checkbox> | ||
| 37 | + </el-checkbox-group> | ||
| 38 | + </el-form-item> | ||
| 39 | + </el-col> | ||
| 40 | + </el-row> | ||
| 41 | + | ||
| 42 | + <el-row :gutter="20"> | ||
| 43 | + <el-col :span="24"> | ||
| 44 | + <el-form-item :label="$t('addOweFeeCallable.floor')"> | ||
| 45 | + <el-select | ||
| 46 | + v-model="addOweFeeCallableInfo.floorId" | ||
| 47 | + style="width:100%" | ||
| 48 | + @change="loadOweFeeRooms" | ||
| 49 | + :placeholder="$t('addOweFeeCallable.selectFloor')"> | ||
| 50 | + <el-option | ||
| 51 | + v-for="item in addOweFeeCallableInfo.floors" | ||
| 52 | + :key="item.floorId" | ||
| 53 | + :label="item.floorNum" | ||
| 54 | + :value="item.floorId"> | ||
| 55 | + </el-option> | ||
| 56 | + </el-select> | ||
| 57 | + </el-form-item> | ||
| 58 | + </el-col> | ||
| 59 | + </el-row> | ||
| 60 | + | ||
| 61 | + <el-row :gutter="20"> | ||
| 62 | + <el-col :span="24"> | ||
| 63 | + <el-form-item :label="$t('addOweFeeCallable.timeRange')"> | ||
| 64 | + <el-select | ||
| 65 | + v-model="addOweFeeCallableInfo.hasTime" | ||
| 66 | + style="width:100%" | ||
| 67 | + @change="loadOweFeeRooms" | ||
| 68 | + :placeholder="$t('addOweFeeCallable.selectTimeRange')"> | ||
| 69 | + <el-option | ||
| 70 | + v-for="item in timeRangeOptions" | ||
| 71 | + :key="item.value" | ||
| 72 | + :label="item.label" | ||
| 73 | + :value="item.value"> | ||
| 74 | + </el-option> | ||
| 75 | + </el-select> | ||
| 76 | + </el-form-item> | ||
| 77 | + </el-col> | ||
| 78 | + </el-row> | ||
| 79 | + | ||
| 80 | + <el-row :gutter="20" v-show="addOweFeeCallableInfo.hasTime === 'ON'"> | ||
| 81 | + <el-col :span="12"> | ||
| 82 | + <el-form-item :label="$t('addOweFeeCallable.startTime')"> | ||
| 83 | + <el-date-picker | ||
| 84 | + v-model="addOweFeeCallableInfo.startTime" | ||
| 85 | + type="datetime" | ||
| 86 | + style="width:100%" | ||
| 87 | + :placeholder="$t('addOweFeeCallable.selectStartTime')"> | ||
| 88 | + </el-date-picker> | ||
| 89 | + </el-form-item> | ||
| 90 | + </el-col> | ||
| 91 | + <el-col :span="12"> | ||
| 92 | + <el-form-item :label="$t('addOweFeeCallable.endTime')"> | ||
| 93 | + <el-date-picker | ||
| 94 | + v-model="addOweFeeCallableInfo.endTime" | ||
| 95 | + type="datetime" | ||
| 96 | + style="width:100%" | ||
| 97 | + :placeholder="$t('addOweFeeCallable.selectEndTime')"> | ||
| 98 | + </el-date-picker> | ||
| 99 | + </el-form-item> | ||
| 100 | + </el-col> | ||
| 101 | + </el-row> | ||
| 102 | + | ||
| 103 | + <el-row :gutter="20"> | ||
| 104 | + <el-col :span="24"> | ||
| 105 | + <el-form-item :label="$t('addOweFeeCallable.oweRooms')"> | ||
| 106 | + <div v-if="addOweFeeCallableInfo.rooms && addOweFeeCallableInfo.rooms.length > 0"> | ||
| 107 | + <el-checkbox | ||
| 108 | + v-model="checkAllStatus" | ||
| 109 | + @change="handleCheckAllChange"> | ||
| 110 | + {{ $t('addOweFeeCallable.checkAll') }} | ||
| 111 | + </el-checkbox> | ||
| 112 | + <el-checkbox-group | ||
| 113 | + v-model="addOweFeeCallableInfo.roomIds" | ||
| 114 | + @change="handleCheckedRoomsChange"> | ||
| 115 | + <el-checkbox | ||
| 116 | + v-for="item in addOweFeeCallableInfo.rooms" | ||
| 117 | + :key="item.payerObjId" | ||
| 118 | + :label="item.payerObjId"> | ||
| 119 | + {{item.payerObjName}} | ||
| 120 | + </el-checkbox> | ||
| 121 | + </el-checkbox-group> | ||
| 122 | + </div> | ||
| 123 | + <div v-else> | ||
| 124 | + {{ $t('addOweFeeCallable.noOweRooms') }} | ||
| 125 | + </div> | ||
| 126 | + </el-form-item> | ||
| 127 | + </el-col> | ||
| 128 | + </el-row> | ||
| 129 | + | ||
| 130 | + <el-row :gutter="20"> | ||
| 131 | + <el-col :span="24" class="text-right"> | ||
| 132 | + <el-button @click="goBack">{{ $t('common.back') }}</el-button> | ||
| 133 | + <el-button | ||
| 134 | + v-if="addOweFeeCallableInfo.callableWay === 'EXCEL'" | ||
| 135 | + type="primary" | ||
| 136 | + @click="exportCollectionLetterExcel"> | ||
| 137 | + {{ $t('common.export') }} | ||
| 138 | + </el-button> | ||
| 139 | + <el-button | ||
| 140 | + v-else-if="addOweFeeCallableInfo.callableWay === 'TTS'" | ||
| 141 | + type="primary" | ||
| 142 | + @click="ttsOweFee"> | ||
| 143 | + {{ $t('addOweFeeCallable.ttsCall') }} | ||
| 144 | + </el-button> | ||
| 145 | + <el-button | ||
| 146 | + v-else | ||
| 147 | + type="primary" | ||
| 148 | + @click="saveOweFeeCallable"> | ||
| 149 | + {{ $t('common.submit') }} | ||
| 150 | + </el-button> | ||
| 151 | + </el-col> | ||
| 152 | + </el-row> | ||
| 153 | + </el-form> | ||
| 154 | + </el-card> | ||
| 155 | + </div> | ||
| 156 | +</template> | ||
| 157 | + | ||
| 158 | +<script> | ||
| 159 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 160 | +import { | ||
| 161 | + saveOweFeeCallable, | ||
| 162 | + exportCollectionLetterExcel, | ||
| 163 | + listFeeConfigs, | ||
| 164 | + queryFloors, | ||
| 165 | + queryReportOweFee | ||
| 166 | +} from '@/api/fee/addOweFeeCallableApi' | ||
| 167 | + | ||
| 168 | +export default { | ||
| 169 | + name: 'AddOweFeeCallableList', | ||
| 170 | + data() { | ||
| 171 | + return { | ||
| 172 | + addOweFeeCallableInfo: { | ||
| 173 | + callableWay: '', | ||
| 174 | + remark: '', | ||
| 175 | + floorId: '', | ||
| 176 | + communityId: '', | ||
| 177 | + configIds: [], | ||
| 178 | + roomId: '', | ||
| 179 | + roomIds: [], | ||
| 180 | + rooms: [], | ||
| 181 | + feeConfigs: [], | ||
| 182 | + hasTime: 'OFF', | ||
| 183 | + startTime: '', | ||
| 184 | + endTime: '', | ||
| 185 | + floors: [] | ||
| 186 | + }, | ||
| 187 | + callableWayOptions: [ | ||
| 188 | + { value: 'WECHAT', label: '微信模板消息' }, | ||
| 189 | + { value: 'SMS', label: '短信' }, | ||
| 190 | + { value: 'EXCEL', label: '导出' }, | ||
| 191 | + { value: 'TTS', label: '呼电话催缴' } | ||
| 192 | + ], | ||
| 193 | + timeRangeOptions: [ | ||
| 194 | + { value: 'OFF', label: '否' }, | ||
| 195 | + { value: 'ON', label: '是' } | ||
| 196 | + ], | ||
| 197 | + checkAllStatus: false, | ||
| 198 | + loading: false | ||
| 199 | + } | ||
| 200 | + }, | ||
| 201 | + created() { | ||
| 202 | + this.addOweFeeCallableInfo.communityId = getCommunityId() | ||
| 203 | + this.listFeeConfigs() | ||
| 204 | + this.loadOweFeeFloors() | ||
| 205 | + }, | ||
| 206 | + methods: { | ||
| 207 | + async listFeeConfigs() { | ||
| 208 | + try { | ||
| 209 | + const params = { | ||
| 210 | + page: 1, | ||
| 211 | + row: 100, | ||
| 212 | + communityId: this.addOweFeeCallableInfo.communityId, | ||
| 213 | + isDefault: 'F' | ||
| 214 | + } | ||
| 215 | + const { data } = await listFeeConfigs(params) | ||
| 216 | + this.addOweFeeCallableInfo.feeConfigs = data.feeConfigs | ||
| 217 | + } catch (error) { | ||
| 218 | + console.error('获取费用配置失败:', error) | ||
| 219 | + } | ||
| 220 | + }, | ||
| 221 | + async loadOweFeeFloors() { | ||
| 222 | + try { | ||
| 223 | + const params = { | ||
| 224 | + page: 1, | ||
| 225 | + row: 100, | ||
| 226 | + communityId: this.addOweFeeCallableInfo.communityId | ||
| 227 | + } | ||
| 228 | + const { data } = await queryFloors(params) | ||
| 229 | + this.addOweFeeCallableInfo.floors = data.apiFloorDataVoList | ||
| 230 | + } catch (error) { | ||
| 231 | + console.error('获取楼栋失败:', error) | ||
| 232 | + } | ||
| 233 | + }, | ||
| 234 | + async loadOweFeeRooms() { | ||
| 235 | + if (!this.addOweFeeCallableInfo.floorId || | ||
| 236 | + !this.addOweFeeCallableInfo.configIds || | ||
| 237 | + this.addOweFeeCallableInfo.configIds.length === 0) { | ||
| 238 | + return | ||
| 239 | + } | ||
| 240 | + | ||
| 241 | + try { | ||
| 242 | + const params = { | ||
| 243 | + page: 1, | ||
| 244 | + row: 500, | ||
| 245 | + configIds: this.addOweFeeCallableInfo.configIds.join(','), | ||
| 246 | + communityId: this.addOweFeeCallableInfo.communityId, | ||
| 247 | + floorId: this.addOweFeeCallableInfo.floorId | ||
| 248 | + } | ||
| 249 | + const { data } = await queryReportOweFee(params) | ||
| 250 | + this.addOweFeeCallableInfo.rooms = data.data || [] | ||
| 251 | + this.addOweFeeCallableInfo.roomIds = this.addOweFeeCallableInfo.rooms.map(item => item.payerObjId) | ||
| 252 | + this.checkAllStatus = this.addOweFeeCallableInfo.rooms.length > 0 | ||
| 253 | + } catch (error) { | ||
| 254 | + console.error('获取欠费房屋失败:', error) | ||
| 255 | + } | ||
| 256 | + }, | ||
| 257 | + handleCheckAllChange(val) { | ||
| 258 | + this.addOweFeeCallableInfo.roomIds = val ? | ||
| 259 | + this.addOweFeeCallableInfo.rooms.map(item => item.payerObjId) : [] | ||
| 260 | + }, | ||
| 261 | + handleCheckedRoomsChange(value) { | ||
| 262 | + const checkedCount = value.length | ||
| 263 | + this.checkAllStatus = checkedCount === this.addOweFeeCallableInfo.rooms.length | ||
| 264 | + }, | ||
| 265 | + validateForm() { | ||
| 266 | + if (!this.addOweFeeCallableInfo.callableWay) { | ||
| 267 | + this.$message.error(this.$t('addOweFeeCallable.callableWayRequired')) | ||
| 268 | + return false | ||
| 269 | + } | ||
| 270 | + if (!this.addOweFeeCallableInfo.roomIds || this.addOweFeeCallableInfo.roomIds.length === 0) { | ||
| 271 | + this.$message.error(this.$t('addOweFeeCallable.roomsRequired')) | ||
| 272 | + return false | ||
| 273 | + } | ||
| 274 | + return true | ||
| 275 | + }, | ||
| 276 | + async saveOweFeeCallable() { | ||
| 277 | + if (!this.validateForm()) return | ||
| 278 | + | ||
| 279 | + try { | ||
| 280 | + await saveOweFeeCallable(this.addOweFeeCallableInfo) | ||
| 281 | + this.$message.success(this.$t('common.submitSuccess')) | ||
| 282 | + this.goBack() | ||
| 283 | + } catch (error) { | ||
| 284 | + console.error('提交失败:', error) | ||
| 285 | + this.$message.error(error.message || this.$t('common.submitFailed')) | ||
| 286 | + } | ||
| 287 | + }, | ||
| 288 | + async exportCollectionLetterExcel() { | ||
| 289 | + if (!this.validateForm()) return | ||
| 290 | + | ||
| 291 | + try { | ||
| 292 | + const params = { | ||
| 293 | + communityId: this.addOweFeeCallableInfo.communityId, | ||
| 294 | + pagePath: 'dataFeeManualCollection', | ||
| 295 | + configIds: this.addOweFeeCallableInfo.configIds.join(','), | ||
| 296 | + roomIds: this.addOweFeeCallableInfo.roomIds.join(','), | ||
| 297 | + startTime: this.addOweFeeCallableInfo.startTime, | ||
| 298 | + endTime: this.addOweFeeCallableInfo.endTime | ||
| 299 | + } | ||
| 300 | + await exportCollectionLetterExcel(params) | ||
| 301 | + this.$message.success(this.$t('common.exportSuccess')) | ||
| 302 | + this.$router.push('/pages/property/downloadTempFile?tab=下载中心') | ||
| 303 | + } catch (error) { | ||
| 304 | + console.error('导出失败:', error) | ||
| 305 | + this.$message.error(error.message || this.$t('common.exportFailed')) | ||
| 306 | + } | ||
| 307 | + }, | ||
| 308 | + ttsOweFee() { | ||
| 309 | + if (!this.validateForm()) return | ||
| 310 | + | ||
| 311 | + const oweFee = this.addOweFeeCallableInfo.rooms | ||
| 312 | + .filter(room => this.addOweFeeCallableInfo.roomIds.includes(room.payerObjId)) | ||
| 313 | + .map(room => ({ ...room, state: 'W' })) | ||
| 314 | + | ||
| 315 | + if (oweFee.length === 0) { | ||
| 316 | + this.$message.error(this.$t('addOweFeeCallable.noOweRoomsSelected')) | ||
| 317 | + return | ||
| 318 | + } | ||
| 319 | + | ||
| 320 | + const data = { | ||
| 321 | + configIds: this.addOweFeeCallableInfo.configIds, | ||
| 322 | + oweFee, | ||
| 323 | + startTime: this.addOweFeeCallableInfo.startTime, | ||
| 324 | + endTime: this.addOweFeeCallableInfo.endTime | ||
| 325 | + } | ||
| 326 | + | ||
| 327 | + localStorage.setItem('TTS_OWE_FEE_DATA', JSON.stringify(data)) | ||
| 328 | + this.$router.push('/fee/ttsOweFeeCallable') | ||
| 329 | + }, | ||
| 330 | + goBack() { | ||
| 331 | + this.$router.go(-1) | ||
| 332 | + } | ||
| 333 | + } | ||
| 334 | +} | ||
| 335 | +</script> | ||
| 336 | + | ||
| 337 | +<style lang="scss" scoped> | ||
| 338 | +.add-owe-fee-callable-container { | ||
| 339 | + padding: 20px; | ||
| 340 | + | ||
| 341 | + .el-checkbox-group { | ||
| 342 | + display: flex; | ||
| 343 | + flex-wrap: wrap; | ||
| 344 | + gap: 15px; | ||
| 345 | + } | ||
| 346 | + | ||
| 347 | + .el-checkbox { | ||
| 348 | + margin-right: 0; | ||
| 349 | + } | ||
| 350 | + | ||
| 351 | + .text-right { | ||
| 352 | + text-align: right; | ||
| 353 | + } | ||
| 354 | +} | ||
| 355 | +</style> | ||
| 0 | \ No newline at end of file | 356 | \ No newline at end of file |
src/views/fee/feeComboMemberManageList.vue
| @@ -14,80 +14,34 @@ | @@ -14,80 +14,34 @@ | ||
| 14 | </div> | 14 | </div> |
| 15 | </div> | 15 | </div> |
| 16 | 16 | ||
| 17 | - <el-table | ||
| 18 | - :data="feeComboMemberManageInfo.feeComboMembers" | ||
| 19 | - border | ||
| 20 | - style="width: 100%" | ||
| 21 | - v-loading="loading" | ||
| 22 | - > | ||
| 23 | - <el-table-column | ||
| 24 | - prop="feeTypeCdName" | ||
| 25 | - :label="$t('feeComboMemberManage.feeType')" | ||
| 26 | - align="center" | ||
| 27 | - /> | ||
| 28 | - <el-table-column | ||
| 29 | - prop="feeName" | ||
| 30 | - :label="$t('feeComboMemberManage.feeItem')" | ||
| 31 | - align="center" | ||
| 32 | - /> | ||
| 33 | - <el-table-column | ||
| 34 | - prop="feeFlagName" | ||
| 35 | - :label="$t('feeComboMemberManage.feeFlag')" | ||
| 36 | - align="center" | ||
| 37 | - /> | ||
| 38 | - <el-table-column | ||
| 39 | - :label="$t('feeComboMemberManage.paymentType')" | ||
| 40 | - align="center" | ||
| 41 | - > | 17 | + <el-table :data="feeComboMemberManageInfo.feeComboMembers" border style="width: 100%" v-loading="loading"> |
| 18 | + <el-table-column prop="feeTypeCdName" :label="$t('feeComboMemberManage.feeType')" align="center" /> | ||
| 19 | + <el-table-column prop="feeName" :label="$t('feeComboMemberManage.feeItem')" align="center" /> | ||
| 20 | + <el-table-column prop="feeFlagName" :label="$t('feeComboMemberManage.feeFlag')" align="center" /> | ||
| 21 | + <el-table-column :label="$t('feeComboMemberManage.paymentType')" align="center"> | ||
| 42 | <template slot-scope="scope"> | 22 | <template slot-scope="scope"> |
| 43 | {{ scope.row.paymentCd == '1200' ? $t('feeComboMemberManage.prepay') : $t('feeComboMemberManage.postpay') }} | 23 | {{ scope.row.paymentCd == '1200' ? $t('feeComboMemberManage.prepay') : $t('feeComboMemberManage.postpay') }} |
| 44 | </template> | 24 | </template> |
| 45 | </el-table-column> | 25 | </el-table-column> |
| 46 | - <el-table-column | ||
| 47 | - prop="paymentCycle" | ||
| 48 | - :label="$t('feeComboMemberManage.paymentCycle')" | ||
| 49 | - align="center" | ||
| 50 | - /> | ||
| 51 | - <el-table-column | ||
| 52 | - :label="$t('feeComboMemberManage.unitPrice')" | ||
| 53 | - align="center" | ||
| 54 | - > | 26 | + <el-table-column prop="paymentCycle" :label="$t('feeComboMemberManage.paymentCycle')" align="center" /> |
| 27 | + <el-table-column :label="$t('feeComboMemberManage.unitPrice')" align="center"> | ||
| 55 | <template slot-scope="scope"> | 28 | <template slot-scope="scope"> |
| 56 | {{ scope.row.computingFormula == '2002' ? '-' : scope.row.squarePrice }} | 29 | {{ scope.row.computingFormula == '2002' ? '-' : scope.row.squarePrice }} |
| 57 | </template> | 30 | </template> |
| 58 | </el-table-column> | 31 | </el-table-column> |
| 59 | - <el-table-column | ||
| 60 | - prop="additionalAmount" | ||
| 61 | - :label="$t('feeComboMemberManage.additionalFee')" | ||
| 62 | - align="center" | ||
| 63 | - /> | ||
| 64 | - <el-table-column | ||
| 65 | - :label="$t('common.operation')" | ||
| 66 | - align="center" | ||
| 67 | - width="150" | ||
| 68 | - > | 32 | + <el-table-column prop="additionalAmount" :label="$t('feeComboMemberManage.additionalFee')" align="center" /> |
| 33 | + <el-table-column :label="$t('common.operation')" align="center" width="150"> | ||
| 69 | <template slot-scope="scope"> | 34 | <template slot-scope="scope"> |
| 70 | - <el-button | ||
| 71 | - type="danger" | ||
| 72 | - size="mini" | ||
| 73 | - @click="_openDeleteFeeComboMemberModel(scope.row)" | ||
| 74 | - > | 35 | + <el-button type="danger" size="mini" @click="_openDeleteFeeComboMemberModel(scope.row)"> |
| 75 | {{ $t('common.delete') }} | 36 | {{ $t('common.delete') }} |
| 76 | </el-button> | 37 | </el-button> |
| 77 | </template> | 38 | </template> |
| 78 | </el-table-column> | 39 | </el-table-column> |
| 79 | </el-table> | 40 | </el-table> |
| 80 | 41 | ||
| 81 | - <el-pagination | ||
| 82 | - @size-change="handleSizeChange" | ||
| 83 | - @current-change="handleCurrentChange" | ||
| 84 | - :current-page="page.current" | ||
| 85 | - :page-sizes="[10, 20, 30, 50]" | ||
| 86 | - :page-size="page.size" | ||
| 87 | - layout="total, sizes, prev, pager, next, jumper" | ||
| 88 | - :total="page.total" | ||
| 89 | - class="pagination" | ||
| 90 | - /> | 42 | + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page.current" |
| 43 | + :page-sizes="[10, 20, 30, 50]" :page-size="page.size" layout="total, sizes, prev, pager, next, jumper" | ||
| 44 | + :total="page.total" class="pagination" /> | ||
| 91 | </el-card> | 45 | </el-card> |
| 92 | 46 | ||
| 93 | <add-fee-combo-member ref="addFeeComboMember" @success="handleSuccess" /> | 47 | <add-fee-combo-member ref="addFeeComboMember" @success="handleSuccess" /> |
src/views/fee/feeSummaryLang.js
0 → 100644
| 1 | +export const messages = { | ||
| 2 | + en: { | ||
| 3 | + feeSummary: { | ||
| 4 | + title: 'Fee Summary', | ||
| 5 | + day: 'Day', | ||
| 6 | + month: 'Month', | ||
| 7 | + year: 'Year', | ||
| 8 | + time: 'Time', | ||
| 9 | + feeItemId: 'Fee Item ID', | ||
| 10 | + feeItemName: 'Fee Item Name', | ||
| 11 | + receivableAmount: 'Receivable Amount', | ||
| 12 | + receivedAmount: 'Received Amount', | ||
| 13 | + yuan: 'yuan', | ||
| 14 | + fetchError: 'Failed to fetch fee summary data' | ||
| 15 | + } | ||
| 16 | + }, | ||
| 17 | + zh: { | ||
| 18 | + feeSummary: { | ||
| 19 | + title: '缴费汇总表', | ||
| 20 | + day: '日', | ||
| 21 | + month: '月', | ||
| 22 | + year: '年', | ||
| 23 | + time: '时间', | ||
| 24 | + feeItemId: '费用项ID', | ||
| 25 | + feeItemName: '费用项名称', | ||
| 26 | + receivableAmount: '应收金额', | ||
| 27 | + receivedAmount: '实收金额', | ||
| 28 | + yuan: '元', | ||
| 29 | + fetchError: '获取缴费汇总数据失败' | ||
| 30 | + } | ||
| 31 | + } | ||
| 32 | +} | ||
| 0 | \ No newline at end of file | 33 | \ No newline at end of file |
src/views/fee/feeSummaryList.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="fee-summary-container animated fadeInRight"> | ||
| 3 | + <el-row> | ||
| 4 | + <el-col :span="24"> | ||
| 5 | + <el-card> | ||
| 6 | + <div slot="header" class="clearfix"> | ||
| 7 | + <span>{{ $t('feeSummary.title') }}</span> | ||
| 8 | + <div class="card-header-right"> | ||
| 9 | + <el-button-group> | ||
| 10 | + <el-button size="small" :type="feeSummaryInfo.feeSummaryType === 1001 ? 'primary' : ''" | ||
| 11 | + @click="_switchFeeSummaryType(1001)"> | ||
| 12 | + {{ $t('feeSummary.day') }} | ||
| 13 | + </el-button> | ||
| 14 | + <el-button size="small" :type="feeSummaryInfo.feeSummaryType === 1101 ? 'primary' : ''" | ||
| 15 | + @click="_switchFeeSummaryType(1101)"> | ||
| 16 | + {{ $t('feeSummary.month') }} | ||
| 17 | + </el-button> | ||
| 18 | + <el-button size="small" :type="feeSummaryInfo.feeSummaryType === 1111 ? 'primary' : ''" | ||
| 19 | + @click="_switchFeeSummaryType(1111)"> | ||
| 20 | + {{ $t('feeSummary.year') }} | ||
| 21 | + </el-button> | ||
| 22 | + </el-button-group> | ||
| 23 | + </div> | ||
| 24 | + </div> | ||
| 25 | + | ||
| 26 | + <el-table :data="feeSummaryInfo.fees" border style="width: 100%" v-loading="loading"> | ||
| 27 | + <el-table-column prop="createTime" :label="$t('feeSummary.time')" align="center" /> | ||
| 28 | + <el-table-column prop="configId" :label="$t('feeSummary.feeItemId')" align="center" /> | ||
| 29 | + <el-table-column prop="feeName" :label="$t('feeSummary.feeItemName')" align="center" /> | ||
| 30 | + <el-table-column prop="receivableAmounts" :label="$t('feeSummary.receivableAmount')" align="center"> | ||
| 31 | + <template slot-scope="scope"> | ||
| 32 | + {{ scope.row.receivableAmounts }} {{ $t('feeSummary.yuan') }} | ||
| 33 | + </template> | ||
| 34 | + </el-table-column> | ||
| 35 | + <el-table-column prop="receivedAmounts" :label="$t('feeSummary.receivedAmount')" align="center"> | ||
| 36 | + <template slot-scope="scope"> | ||
| 37 | + {{ scope.row.receivedAmounts }} {{ $t('feeSummary.yuan') }} | ||
| 38 | + </template> | ||
| 39 | + </el-table-column> | ||
| 40 | + </el-table> | ||
| 41 | + | ||
| 42 | + <el-pagination class="pagination-wrapper" :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" | ||
| 43 | + :page-size="page.size" :total="page.total" layout="total, sizes, prev, pager, next, jumper" | ||
| 44 | + @size-change="handleSizeChange" @current-change="handleCurrentChange" /> | ||
| 45 | + </el-card> | ||
| 46 | + </el-col> | ||
| 47 | + </el-row> | ||
| 48 | + </div> | ||
| 49 | +</template> | ||
| 50 | + | ||
| 51 | +<script> | ||
| 52 | +import { listFeeSummarys } from '@/api/fee/feeSummaryApi' | ||
| 53 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 54 | + | ||
| 55 | +export default { | ||
| 56 | + name: 'FeeSummaryList', | ||
| 57 | + data() { | ||
| 58 | + return { | ||
| 59 | + loading: false, | ||
| 60 | + feeSummaryInfo: { | ||
| 61 | + fees: [], | ||
| 62 | + feeSummaryType: '1001', | ||
| 63 | + total: 0 | ||
| 64 | + }, | ||
| 65 | + page: { | ||
| 66 | + current: 1, | ||
| 67 | + size: 10, | ||
| 68 | + total: 0 | ||
| 69 | + }, | ||
| 70 | + communityId: '' | ||
| 71 | + } | ||
| 72 | + }, | ||
| 73 | + created() { | ||
| 74 | + this.communityId = getCommunityId() | ||
| 75 | + this._listFeeSummarys(this.page.current, this.page.size) | ||
| 76 | + }, | ||
| 77 | + methods: { | ||
| 78 | + async _listFeeSummarys(page, size) { | ||
| 79 | + try { | ||
| 80 | + this.loading = true | ||
| 81 | + const params = { | ||
| 82 | + page, | ||
| 83 | + row: size, | ||
| 84 | + feeSummaryType: this.feeSummaryInfo.feeSummaryType, | ||
| 85 | + communityId: this.communityId | ||
| 86 | + } | ||
| 87 | + const { fees, total } = await listFeeSummarys(params) | ||
| 88 | + this.feeSummaryInfo.fees = fees | ||
| 89 | + this.page.total = total | ||
| 90 | + } catch (error) { | ||
| 91 | + this.$message.error(this.$t('feeSummary.fetchError')) | ||
| 92 | + } finally { | ||
| 93 | + this.loading = false | ||
| 94 | + } | ||
| 95 | + }, | ||
| 96 | + _switchFeeSummaryType(feeSummaryType) { | ||
| 97 | + this.feeSummaryInfo.feeSummaryType = feeSummaryType | ||
| 98 | + this.page.current = 1 | ||
| 99 | + this._listFeeSummarys(this.page.current, this.page.size) | ||
| 100 | + }, | ||
| 101 | + handleSizeChange(val) { | ||
| 102 | + this.page.size = val | ||
| 103 | + this._listFeeSummarys(this.page.current, this.page.size) | ||
| 104 | + }, | ||
| 105 | + handleCurrentChange(val) { | ||
| 106 | + this.page.current = val | ||
| 107 | + this._listFeeSummarys(this.page.current, this.page.size) | ||
| 108 | + } | ||
| 109 | + } | ||
| 110 | +} | ||
| 111 | +</script> | ||
| 112 | + | ||
| 113 | +<style lang="scss" scoped> | ||
| 114 | +.fee-summary-container { | ||
| 115 | + padding: 20px; | ||
| 116 | + | ||
| 117 | + .clearfix { | ||
| 118 | + display: flex; | ||
| 119 | + justify-content: space-between; | ||
| 120 | + align-items: center; | ||
| 121 | + } | ||
| 122 | + | ||
| 123 | + .card-header-right { | ||
| 124 | + display: flex; | ||
| 125 | + align-items: center; | ||
| 126 | + } | ||
| 127 | + | ||
| 128 | + .pagination-wrapper { | ||
| 129 | + margin-top: 20px; | ||
| 130 | + text-align: right; | ||
| 131 | + } | ||
| 132 | + | ||
| 133 | + .el-button-group { | ||
| 134 | + margin-left: 10px; | ||
| 135 | + } | ||
| 136 | +} | ||
| 137 | +</style> | ||
| 0 | \ No newline at end of file | 138 | \ No newline at end of file |
src/views/fee/listOweFeeLang.js
0 → 100644
| 1 | +export const messages = { | ||
| 2 | + en: { | ||
| 3 | + listOweFee: { | ||
| 4 | + search: { | ||
| 5 | + title: 'Search Conditions', | ||
| 6 | + floorName: 'Please select building', | ||
| 7 | + unit: 'Please select unit', | ||
| 8 | + roomNum: 'Please enter room number', | ||
| 9 | + roomType: 'Please select room type', | ||
| 10 | + ownerName: 'Please enter owner name', | ||
| 11 | + payObjType: 'Please select payment object type', | ||
| 12 | + roomNumFormat: 'Please enter room number, e.g. 1-1-1123', | ||
| 13 | + carportNum: 'Please enter parking space number, e.g. 6-8', | ||
| 14 | + feeConfig: 'Please select fee items' | ||
| 15 | + }, | ||
| 16 | + table: { | ||
| 17 | + title: 'Arrears Information', | ||
| 18 | + index: 'No.', | ||
| 19 | + payerObjName: 'Payment Object', | ||
| 20 | + ownerName: 'Owner Name', | ||
| 21 | + ownerTel: 'Phone Number', | ||
| 22 | + endTime: 'Start Time', | ||
| 23 | + deadlineTime: 'End Time', | ||
| 24 | + total: 'Total (Unit: Yuan)', | ||
| 25 | + updateTime: 'Update Time' | ||
| 26 | + }, | ||
| 27 | + summary: { | ||
| 28 | + subtotal: 'Subtotal', | ||
| 29 | + total: 'Total' | ||
| 30 | + }, | ||
| 31 | + exportSuccess: 'Export initiated successfully', | ||
| 32 | + exportError: 'Export failed' | ||
| 33 | + }, | ||
| 34 | + searchFloor: { | ||
| 35 | + title: 'Building Selection', | ||
| 36 | + floorId: 'Please enter building ID', | ||
| 37 | + floorName: 'Please enter building name', | ||
| 38 | + floorNum: 'Please enter building number', | ||
| 39 | + table: { | ||
| 40 | + floorId: 'Building ID', | ||
| 41 | + floorName: 'Name', | ||
| 42 | + floorNum: 'Number', | ||
| 43 | + userName: 'Creator' | ||
| 44 | + } | ||
| 45 | + } | ||
| 46 | + }, | ||
| 47 | + zh: { | ||
| 48 | + listOweFee: { | ||
| 49 | + search: { | ||
| 50 | + title: '查询条件', | ||
| 51 | + floorName: '请选择楼栋', | ||
| 52 | + unit: '单元', | ||
| 53 | + roomNum: '请填写房屋编号', | ||
| 54 | + roomType: '请选择房屋类型', | ||
| 55 | + ownerName: '请填写业主名称', | ||
| 56 | + payObjType: '请选择付费对象类型', | ||
| 57 | + roomNumFormat: '请填写房屋编号,如1-1-1123', | ||
| 58 | + carportNum: '请填写车位编号,如6-8', | ||
| 59 | + feeConfig: '请选择收费项' | ||
| 60 | + }, | ||
| 61 | + table: { | ||
| 62 | + title: '欠费信息', | ||
| 63 | + index: '序号', | ||
| 64 | + payerObjName: '收费对象', | ||
| 65 | + ownerName: '业主名称', | ||
| 66 | + ownerTel: '手机号', | ||
| 67 | + endTime: '开始时间', | ||
| 68 | + deadlineTime: '结束时间', | ||
| 69 | + total: '合计(单位:元)', | ||
| 70 | + updateTime: '更新时间' | ||
| 71 | + }, | ||
| 72 | + summary: { | ||
| 73 | + subtotal: '小计', | ||
| 74 | + total: '合计' | ||
| 75 | + }, | ||
| 76 | + exportSuccess: '导出成功', | ||
| 77 | + exportError: '导出失败' | ||
| 78 | + }, | ||
| 79 | + searchFloor: { | ||
| 80 | + title: '小区楼栋', | ||
| 81 | + floorId: '请输入楼栋ID', | ||
| 82 | + floorName: '请输入楼栋名称', | ||
| 83 | + floorNum: '请输入楼栋编号', | ||
| 84 | + table: { | ||
| 85 | + floorId: '楼栋ID', | ||
| 86 | + floorName: '名称', | ||
| 87 | + floorNum: '编号', | ||
| 88 | + userName: '创建人' | ||
| 89 | + } | ||
| 90 | + } | ||
| 91 | + } | ||
| 92 | +} | ||
| 0 | \ No newline at end of file | 93 | \ No newline at end of file |
src/views/fee/listOweFeeList.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="list-owe-fee-container"> | ||
| 3 | + <!-- 查询条件 --> | ||
| 4 | + <el-card class="search-card"> | ||
| 5 | + <div slot="header" class="flex justify-between"> | ||
| 6 | + <span>{{ $t('listOweFee.search.title') }}</span> | ||
| 7 | + <el-button type="text" style="float: right; padding: 3px 0" @click="toggleMoreCondition"> | ||
| 8 | + {{ listOweFeeInfo.moreCondition ? $t('common.hide') : $t('common.more') }} | ||
| 9 | + </el-button> | ||
| 10 | + </div> | ||
| 11 | + <el-row :gutter="20"> | ||
| 12 | + <el-col :span="6"> | ||
| 13 | + <el-input v-model="listOweFeeInfo.conditions.floorName" :placeholder="$t('listOweFee.search.floorName')" | ||
| 14 | + class="search-item"> | ||
| 15 | + <el-button slot="append" type="primary" @click="openChooseFloor"> | ||
| 16 | + <i class="el-icon-search"></i> | ||
| 17 | + {{ $t('common.select') }} | ||
| 18 | + </el-button> | ||
| 19 | + </el-input> | ||
| 20 | + </el-col> | ||
| 21 | + <el-col :span="6"> | ||
| 22 | + <el-select v-model="listOweFeeInfo.conditions.unitId" :placeholder="$t('listOweFee.search.unit')" | ||
| 23 | + style="width:100%"> | ||
| 24 | + <el-option :label="$t('listOweFee.search.unit')" value=""></el-option> | ||
| 25 | + <el-option v-for="(unit, index) in listOweFeeInfo.roomUnits" :key="index" | ||
| 26 | + :label="unit.unitNum + $t('listOweFee.search.unit')" :value="unit.unitId"></el-option> | ||
| 27 | + </el-select> | ||
| 28 | + </el-col> | ||
| 29 | + <el-col :span="6"> | ||
| 30 | + <el-input v-model.trim="listOweFeeInfo.conditions.roomNum" | ||
| 31 | + :placeholder="$t('listOweFee.search.roomNum')"></el-input> | ||
| 32 | + </el-col> | ||
| 33 | + <el-col :span="6"> | ||
| 34 | + <el-button type="primary" @click="queryOweFee"> | ||
| 35 | + <i class="el-icon-search"></i> | ||
| 36 | + {{ $t('common.search') }} | ||
| 37 | + </el-button> | ||
| 38 | + <el-button type="info" @click="resetOweFee"> | ||
| 39 | + <i class="el-icon-refresh"></i> | ||
| 40 | + {{ $t('common.reset') }} | ||
| 41 | + </el-button> | ||
| 42 | + </el-col> | ||
| 43 | + </el-row> | ||
| 44 | + | ||
| 45 | + <!-- 更多查询条件 --> | ||
| 46 | + <el-row v-show="listOweFeeInfo.moreCondition" :gutter="20"> | ||
| 47 | + <el-col :span="6"> | ||
| 48 | + <el-select v-model="listOweFeeInfo.conditions.roomSubType" :placeholder="$t('listOweFee.search.roomType')" | ||
| 49 | + style="width:100%"> | ||
| 50 | + <el-option :label="$t('common.selectRoomType')" value=""></el-option> | ||
| 51 | + <el-option v-for="(item, index) in listOweFeeInfo.roomSubTypes" :key="index" :label="item.name" | ||
| 52 | + :value="item.statusCd"></el-option> | ||
| 53 | + </el-select> | ||
| 54 | + </el-col> | ||
| 55 | + <el-col :span="6"> | ||
| 56 | + <el-input v-model.trim="listOweFeeInfo.conditions.ownerName" | ||
| 57 | + :placeholder="$t('listOweFee.search.ownerName')"></el-input> | ||
| 58 | + </el-col> | ||
| 59 | + <el-col :span="6"> | ||
| 60 | + <el-select v-model="listOweFeeInfo.conditions.payObjType" :placeholder="$t('listOweFee.search.payObjType')" | ||
| 61 | + style="width:100%"> | ||
| 62 | + <el-option :label="$t('common.selectPayObjType')" value=""></el-option> | ||
| 63 | + <el-option v-for="(item, index) in listOweFeeInfo.payObjTypes" :key="index" :label="item.name" | ||
| 64 | + :value="item.statusCd"></el-option> | ||
| 65 | + </el-select> | ||
| 66 | + </el-col> | ||
| 67 | + </el-row> | ||
| 68 | + | ||
| 69 | + <el-row v-show="listOweFeeInfo.moreCondition" :gutter="20"> | ||
| 70 | + <el-col v-if="listOweFeeInfo.conditions.payObjType === '3333'" :span="6"> | ||
| 71 | + <el-input v-model.trim="listOweFeeInfo.conditions.num" | ||
| 72 | + :placeholder="$t('listOweFee.search.roomNumFormat')"></el-input> | ||
| 73 | + </el-col> | ||
| 74 | + <el-col v-if="listOweFeeInfo.conditions.payObjType === '6666'" :span="6"> | ||
| 75 | + <el-input v-model.trim="listOweFeeInfo.conditions.num" | ||
| 76 | + :placeholder="$t('listOweFee.search.carportNum')"></el-input> | ||
| 77 | + </el-col> | ||
| 78 | + <el-col :span="6"> | ||
| 79 | + <el-select v-model="selectedFeeConfigs" multiple :placeholder="$t('listOweFee.search.feeConfig')" | ||
| 80 | + style="width:100%"> | ||
| 81 | + <el-option v-for="(item, index) in listOweFeeInfo.feeConfigs" :key="index" :label="item.feeName" | ||
| 82 | + :value="item.configId"></el-option> | ||
| 83 | + </el-select> | ||
| 84 | + </el-col> | ||
| 85 | + </el-row> | ||
| 86 | + </el-card> | ||
| 87 | + | ||
| 88 | + <!-- 欠费信息表格 --> | ||
| 89 | + <el-card class="table-card"> | ||
| 90 | + <div slot="header" class="flex justify-between"> | ||
| 91 | + <span>{{ $t('listOweFee.table.title') }}</span> | ||
| 92 | + <el-button type="primary" size="small" @click="exportFee"> | ||
| 93 | + <i class="el-icon-download"></i> | ||
| 94 | + {{ $t('common.export') }} | ||
| 95 | + </el-button> | ||
| 96 | + </div> | ||
| 97 | + <el-table :data="listOweFeeInfo.fees" border style="width: 100%" v-loading="loading"> | ||
| 98 | + <el-table-column prop="index" :label="$t('listOweFee.table.index')" width="80" align="center"> | ||
| 99 | + <template slot-scope="scope"> | ||
| 100 | + {{ scope.$index + 1 }} | ||
| 101 | + </template> | ||
| 102 | + </el-table-column> | ||
| 103 | + <el-table-column prop="payerObjName" :label="$t('listOweFee.table.payerObjName')" | ||
| 104 | + align="center"></el-table-column> | ||
| 105 | + <el-table-column prop="ownerName" :label="$t('listOweFee.table.ownerName')" align="center"></el-table-column> | ||
| 106 | + <el-table-column prop="ownerTel" :label="$t('listOweFee.table.ownerTel')" align="center"></el-table-column> | ||
| 107 | + <el-table-column prop="endTime" :label="$t('listOweFee.table.endTime')" align="center"></el-table-column> | ||
| 108 | + <el-table-column prop="deadlineTime" :label="$t('listOweFee.table.deadlineTime')" | ||
| 109 | + align="center"></el-table-column> | ||
| 110 | + <el-table-column v-for="(item, index) in listOweFeeInfo.feeConfigNames" :key="index" :label="item.configName" | ||
| 111 | + align="center"> | ||
| 112 | + <template slot-scope="scope"> | ||
| 113 | + {{ getFeeOweAmount(item, scope.row) }} | ||
| 114 | + </template> | ||
| 115 | + </el-table-column> | ||
| 116 | + <el-table-column :label="$t('listOweFee.table.total')" align="center"> | ||
| 117 | + <template slot-scope="scope"> | ||
| 118 | + {{ getAllFeeOweAmount(scope.row) }} | ||
| 119 | + </template> | ||
| 120 | + </el-table-column> | ||
| 121 | + <el-table-column prop="updateTime" :label="$t('listOweFee.table.updateTime')" align="center"></el-table-column> | ||
| 122 | + </el-table> | ||
| 123 | + | ||
| 124 | + <!-- 分页 --> | ||
| 125 | + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page.current" | ||
| 126 | + :page-sizes="[10, 20, 30, 50]" :page-size="page.size" layout="total, sizes, prev, pager, next, jumper" | ||
| 127 | + :total="page.total" style="margin-top: 20px;"></el-pagination> | ||
| 128 | + | ||
| 129 | + <!-- 小计和合计 --> | ||
| 130 | + <div class="summary-wrapper"> | ||
| 131 | + <div class="summary-item"> | ||
| 132 | + <span class="summary-title">{{ $t('listOweFee.summary.subtotal') }}</span> | ||
| 133 | + <div v-for="(item, index) in listOweFeeInfo.feeConfigNames" :key="index" class="summary-content"> | ||
| 134 | + {{ item.configName }}: {{ getFeeOweAllAmount(item) }} {{ $t('common.yuan') }} | ||
| 135 | + </div> | ||
| 136 | + <div class="summary-content"> | ||
| 137 | + {{ $t('listOweFee.summary.total') }}: {{ getFeeOweAllAmounts() }} {{ $t('common.yuan') }} | ||
| 138 | + </div> | ||
| 139 | + </div> | ||
| 140 | + </div> | ||
| 141 | + </el-card> | ||
| 142 | + | ||
| 143 | + <!-- 选择楼栋组件 --> | ||
| 144 | + <search-floor ref="searchFloor" @chooseFloor="handleChooseFloor"></search-floor> | ||
| 145 | + </div> | ||
| 146 | +</template> | ||
| 147 | + | ||
| 148 | +<script> | ||
| 149 | +import { getDict } from '@/api/community/communityApi' | ||
| 150 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 151 | +import { queryReportOweFee, listFeeConfigs, exportData,queryUnits } from '@/api/fee/listOweFeeApi' | ||
| 152 | +import SearchFloor from '@/components/fee/searchFloor' | ||
| 153 | + | ||
| 154 | +export default { | ||
| 155 | + name: 'ListOweFee', | ||
| 156 | + components: { | ||
| 157 | + SearchFloor | ||
| 158 | + }, | ||
| 159 | + data() { | ||
| 160 | + return { | ||
| 161 | + loading: false, | ||
| 162 | + listOweFeeInfo: { | ||
| 163 | + fees: [], | ||
| 164 | + moreCondition: false, | ||
| 165 | + roomUnits: [], | ||
| 166 | + conditions: { | ||
| 167 | + configIds: '', | ||
| 168 | + payObjType: '', | ||
| 169 | + num: '', | ||
| 170 | + billType: '00123', | ||
| 171 | + floorId: '', | ||
| 172 | + floorName: '', | ||
| 173 | + roomNum: '', | ||
| 174 | + unitId: '', | ||
| 175 | + roomSubType: '', | ||
| 176 | + ownerName: '', | ||
| 177 | + communityId: '' | ||
| 178 | + }, | ||
| 179 | + feeConfigs: [], | ||
| 180 | + feeConfigNames: [], | ||
| 181 | + payObjTypes: [], | ||
| 182 | + roomSubTypes: [] | ||
| 183 | + }, | ||
| 184 | + selectedFeeConfigs: [], | ||
| 185 | + page: { | ||
| 186 | + current: 1, | ||
| 187 | + size: 10, | ||
| 188 | + total: 0 | ||
| 189 | + } | ||
| 190 | + } | ||
| 191 | + }, | ||
| 192 | + created() { | ||
| 193 | + this.listOweFeeInfo.conditions.communityId = getCommunityId() | ||
| 194 | + this.initData() | ||
| 195 | + }, | ||
| 196 | + watch: { | ||
| 197 | + selectedFeeConfigs(newVal) { | ||
| 198 | + this.listOweFeeInfo.feeConfigNames = newVal.map(configId => { | ||
| 199 | + const config = this.listOweFeeInfo.feeConfigs.find(item => item.configId === configId) | ||
| 200 | + return { | ||
| 201 | + configId, | ||
| 202 | + configName: config ? config.feeName : '' | ||
| 203 | + } | ||
| 204 | + }) | ||
| 205 | + } | ||
| 206 | + }, | ||
| 207 | + methods: { | ||
| 208 | + async initData() { | ||
| 209 | + try { | ||
| 210 | + this.loading = true | ||
| 211 | + await Promise.all([ | ||
| 212 | + this.getPayObjTypes(), | ||
| 213 | + this.getRoomSubTypes(), | ||
| 214 | + this.loadListOweFeeInfo(), | ||
| 215 | + this.listFeeConfigs() | ||
| 216 | + ]) | ||
| 217 | + } catch (error) { | ||
| 218 | + console.error('初始化数据失败:', error) | ||
| 219 | + } finally { | ||
| 220 | + this.loading = false | ||
| 221 | + } | ||
| 222 | + }, | ||
| 223 | + async getPayObjTypes() { | ||
| 224 | + try { | ||
| 225 | + const data = await getDict('report_owe_fee', 'payer_obj_type') | ||
| 226 | + this.listOweFeeInfo.payObjTypes = data | ||
| 227 | + } catch (error) { | ||
| 228 | + console.error('获取付费对象类型失败:', error) | ||
| 229 | + } | ||
| 230 | + }, | ||
| 231 | + async getRoomSubTypes() { | ||
| 232 | + try { | ||
| 233 | + const data = await getDict('building_room', 'room_sub_type') | ||
| 234 | + this.listOweFeeInfo.roomSubTypes = data | ||
| 235 | + } catch (error) { | ||
| 236 | + console.error('获取房屋类型失败:', error) | ||
| 237 | + } | ||
| 238 | + }, | ||
| 239 | + async loadListOweFeeInfo() { | ||
| 240 | + try { | ||
| 241 | + const params = { | ||
| 242 | + ...this.listOweFeeInfo.conditions, | ||
| 243 | + page: this.page.current, | ||
| 244 | + row: this.page.size, | ||
| 245 | + configIds: this.listOweFeeInfo.feeConfigNames.map(item => item.configId).join(',') | ||
| 246 | + } | ||
| 247 | + const { data, total } = await queryReportOweFee(params) | ||
| 248 | + this.listOweFeeInfo.fees = data | ||
| 249 | + this.page.total = total | ||
| 250 | + } catch (error) { | ||
| 251 | + console.error('获取欠费信息失败:', error) | ||
| 252 | + } | ||
| 253 | + }, | ||
| 254 | + async listFeeConfigs() { | ||
| 255 | + try { | ||
| 256 | + const params = { | ||
| 257 | + page: 1, | ||
| 258 | + row: 100, | ||
| 259 | + communityId: this.listOweFeeInfo.conditions.communityId | ||
| 260 | + } | ||
| 261 | + const { data } = await listFeeConfigs(params) | ||
| 262 | + this.listOweFeeInfo.feeConfigs = data | ||
| 263 | + } catch (error) { | ||
| 264 | + console.error('获取收费项失败:', error) | ||
| 265 | + } | ||
| 266 | + }, | ||
| 267 | + toggleMoreCondition() { | ||
| 268 | + this.listOweFeeInfo.moreCondition = !this.listOweFeeInfo.moreCondition | ||
| 269 | + }, | ||
| 270 | + queryOweFee() { | ||
| 271 | + this.page.current = 1 | ||
| 272 | + this.loadListOweFeeInfo() | ||
| 273 | + }, | ||
| 274 | + resetOweFee() { | ||
| 275 | + this.listOweFeeInfo.conditions = { | ||
| 276 | + configIds: '', | ||
| 277 | + payObjType: '', | ||
| 278 | + num: '', | ||
| 279 | + billType: '00123', | ||
| 280 | + floorId: '', | ||
| 281 | + floorName: '', | ||
| 282 | + roomNum: '', | ||
| 283 | + unitId: '', | ||
| 284 | + roomSubType: '', | ||
| 285 | + ownerName: '', | ||
| 286 | + communityId: this.listOweFeeInfo.conditions.communityId | ||
| 287 | + } | ||
| 288 | + this.selectedFeeConfigs = [] | ||
| 289 | + this.loadListOweFeeInfo() | ||
| 290 | + }, | ||
| 291 | + getFeeOweAmount(item, fee) { | ||
| 292 | + if (!fee.items) return 0 | ||
| 293 | + const found = fee.items.find(tmp => tmp.configId === item.configId) | ||
| 294 | + return found ? found.amountOwed : 0 | ||
| 295 | + }, | ||
| 296 | + getFeeOweAllAmount(item) { | ||
| 297 | + let amountOwed = 0.0 | ||
| 298 | + this.listOweFeeInfo.fees.forEach(feeItem => { | ||
| 299 | + if (!feeItem.items) return | ||
| 300 | + feeItem.items.forEach(tmp => { | ||
| 301 | + if (tmp.configId === item.configId) { | ||
| 302 | + amountOwed += parseFloat(tmp.amountOwed) | ||
| 303 | + } | ||
| 304 | + }) | ||
| 305 | + }) | ||
| 306 | + return amountOwed.toFixed(2) | ||
| 307 | + }, | ||
| 308 | + getAllFeeOweAmount(fee) { | ||
| 309 | + if (this.listOweFeeInfo.feeConfigNames.length < 1) { | ||
| 310 | + return fee.amountOwed | ||
| 311 | + } | ||
| 312 | + let amountOwed = 0.0 | ||
| 313 | + this.listOweFeeInfo.feeConfigNames.forEach(feeItem => { | ||
| 314 | + if (!fee.items) return | ||
| 315 | + fee.items.forEach(item => { | ||
| 316 | + if (feeItem.configId === item.configId) { | ||
| 317 | + amountOwed += parseFloat(item.amountOwed) | ||
| 318 | + } | ||
| 319 | + }) | ||
| 320 | + }) | ||
| 321 | + return amountOwed.toFixed(2) | ||
| 322 | + }, | ||
| 323 | + getFeeOweAllAmounts() { | ||
| 324 | + let amountOwed = 0.0 | ||
| 325 | + this.listOweFeeInfo.fees.forEach(feeItem => { | ||
| 326 | + const rowAmount = this.getAllFeeOweAmount(feeItem) | ||
| 327 | + amountOwed += parseFloat(rowAmount) | ||
| 328 | + }) | ||
| 329 | + return amountOwed.toFixed(2) | ||
| 330 | + }, | ||
| 331 | + async exportFee() { | ||
| 332 | + try { | ||
| 333 | + const params = { | ||
| 334 | + ...this.listOweFeeInfo.conditions, | ||
| 335 | + pagePath: 'reportListOweFee', | ||
| 336 | + configIds: this.listOweFeeInfo.feeConfigNames.map(item => item.configId).join(',') | ||
| 337 | + } | ||
| 338 | + await exportData(params) | ||
| 339 | + this.$message.success(this.$t('listOweFee.exportSuccess')) | ||
| 340 | + this.$router.push('/pages/property/downloadTempFile?tab=下载中心') | ||
| 341 | + } catch (error) { | ||
| 342 | + console.error('导出失败:', error) | ||
| 343 | + this.$message.error(this.$t('listOweFee.exportError')) | ||
| 344 | + } | ||
| 345 | + }, | ||
| 346 | + handleSizeChange(val) { | ||
| 347 | + this.page.size = val | ||
| 348 | + this.loadListOweFeeInfo() | ||
| 349 | + }, | ||
| 350 | + handleCurrentChange(val) { | ||
| 351 | + this.page.current = val | ||
| 352 | + this.loadListOweFeeInfo() | ||
| 353 | + }, | ||
| 354 | + openChooseFloor() { | ||
| 355 | + this.$refs.searchFloor.open() | ||
| 356 | + }, | ||
| 357 | + handleChooseFloor(floor) { | ||
| 358 | + this.listOweFeeInfo.conditions.floorId = floor.floorId | ||
| 359 | + this.listOweFeeInfo.conditions.floorName = floor.floorName | ||
| 360 | + this.loadUnits(floor.floorId) | ||
| 361 | + }, | ||
| 362 | + async loadUnits(floorId) { | ||
| 363 | + try { | ||
| 364 | + const params = { | ||
| 365 | + floorId, | ||
| 366 | + communityId: this.listOweFeeInfo.conditions.communityId | ||
| 367 | + } | ||
| 368 | + const { data } = await queryUnits(params) | ||
| 369 | + this.listOweFeeInfo.roomUnits = data | ||
| 370 | + } catch (error) { | ||
| 371 | + console.error('获取单元信息失败:', error) | ||
| 372 | + } | ||
| 373 | + } | ||
| 374 | + } | ||
| 375 | +} | ||
| 376 | +</script> | ||
| 377 | + | ||
| 378 | +<style lang="scss" scoped> | ||
| 379 | +.list-owe-fee-container { | ||
| 380 | + padding: 20px; | ||
| 381 | + | ||
| 382 | + .search-card { | ||
| 383 | + margin-bottom: 20px; | ||
| 384 | + | ||
| 385 | + .search-item { | ||
| 386 | + margin-bottom: 15px; | ||
| 387 | + } | ||
| 388 | + } | ||
| 389 | + | ||
| 390 | + .table-card { | ||
| 391 | + margin-bottom: 20px; | ||
| 392 | + } | ||
| 393 | + | ||
| 394 | + .summary-wrapper { | ||
| 395 | + margin-top: 20px; | ||
| 396 | + padding: 15px; | ||
| 397 | + background-color: #f5f7fa; | ||
| 398 | + border-radius: 4px; | ||
| 399 | + | ||
| 400 | + .summary-item { | ||
| 401 | + display: flex; | ||
| 402 | + flex-wrap: wrap; | ||
| 403 | + align-items: center; | ||
| 404 | + } | ||
| 405 | + | ||
| 406 | + .summary-title { | ||
| 407 | + font-weight: bold; | ||
| 408 | + margin-right: 20px; | ||
| 409 | + } | ||
| 410 | + | ||
| 411 | + .summary-content { | ||
| 412 | + margin-right: 30px; | ||
| 413 | + margin-bottom: 10px; | ||
| 414 | + } | ||
| 415 | + } | ||
| 416 | +} | ||
| 417 | +</style> | ||
| 0 | \ No newline at end of file | 418 | \ No newline at end of file |
src/views/fee/meterWaterManageList.vue
| @@ -223,7 +223,7 @@ export default { | @@ -223,7 +223,7 @@ export default { | ||
| 223 | padding: 20px; | 223 | padding: 20px; |
| 224 | 224 | ||
| 225 | .tree-container { | 225 | .tree-container { |
| 226 | - height: calc(100vh - 120px); | 226 | + min-height: 450px; |
| 227 | overflow-y: auto; | 227 | overflow-y: auto; |
| 228 | background: #fff; | 228 | background: #fff; |
| 229 | padding: 10px; | 229 | padding: 10px; |
src/views/fee/oweFeeCallableLang.js
0 → 100644
| 1 | +export const messages = { | ||
| 2 | + en: { | ||
| 3 | + oweFeeCallable: { | ||
| 4 | + search: { | ||
| 5 | + title: 'Search Conditions', | ||
| 6 | + ownerName: 'Owner Name', | ||
| 7 | + ownerNamePlaceholder: 'Please enter owner name', | ||
| 8 | + feeName: 'Fee Name', | ||
| 9 | + feeNamePlaceholder: 'Please enter fee name', | ||
| 10 | + callableWay: 'Callable Way', | ||
| 11 | + callableWayPlaceholder: 'Please select callable way', | ||
| 12 | + staffName: 'Staff Name', | ||
| 13 | + staffNamePlaceholder: 'Please enter staff name', | ||
| 14 | + state: 'State', | ||
| 15 | + statePlaceholder: 'Please select state' | ||
| 16 | + }, | ||
| 17 | + list: { | ||
| 18 | + title: 'Call Records', | ||
| 19 | + register: 'Register', | ||
| 20 | + call: 'Call' | ||
| 21 | + }, | ||
| 22 | + table: { | ||
| 23 | + id: 'ID', | ||
| 24 | + ownerName: 'Owner Name', | ||
| 25 | + payerObjName: 'Payer Object', | ||
| 26 | + feeName: 'Fee Name', | ||
| 27 | + amountdOwed: 'Amount Owed', | ||
| 28 | + timeRange: 'Time Range', | ||
| 29 | + callableWayName: 'Callable Way', | ||
| 30 | + staffName: 'Staff Name', | ||
| 31 | + stateName: 'State', | ||
| 32 | + remark: 'Remark', | ||
| 33 | + createTime: 'Create Time' | ||
| 34 | + }, | ||
| 35 | + write: { | ||
| 36 | + title: 'Call Registration', | ||
| 37 | + roomName: 'Room', | ||
| 38 | + feeName: 'Call Fees', | ||
| 39 | + remark: 'Remark', | ||
| 40 | + remarkPlaceholder: 'Please enter remark', | ||
| 41 | + success: 'Registration successful', | ||
| 42 | + error: 'Registration failed' | ||
| 43 | + }, | ||
| 44 | + delete: { | ||
| 45 | + title: 'Delete Confirmation', | ||
| 46 | + confirm: 'Are you sure to delete this call record?', | ||
| 47 | + success: 'Delete successful', | ||
| 48 | + error: 'Delete failed' | ||
| 49 | + }, | ||
| 50 | + fetchError: 'Failed to fetch data', | ||
| 51 | + selectRoomFirst: 'Please select a room first' | ||
| 52 | + } | ||
| 53 | + }, | ||
| 54 | + zh: { | ||
| 55 | + oweFeeCallable: { | ||
| 56 | + search: { | ||
| 57 | + title: '查询条件', | ||
| 58 | + ownerName: '业主名称', | ||
| 59 | + ownerNamePlaceholder: '请输入业主名称', | ||
| 60 | + feeName: '费用名称', | ||
| 61 | + feeNamePlaceholder: '请输入费用名称', | ||
| 62 | + callableWay: '催缴方式', | ||
| 63 | + callableWayPlaceholder: '请选择催缴方式', | ||
| 64 | + staffName: '催缴人', | ||
| 65 | + staffNamePlaceholder: '请输入催缴人', | ||
| 66 | + state: '状态', | ||
| 67 | + statePlaceholder: '请选择状态' | ||
| 68 | + }, | ||
| 69 | + list: { | ||
| 70 | + title: '催缴记录', | ||
| 71 | + register: '登记', | ||
| 72 | + call: '催缴' | ||
| 73 | + }, | ||
| 74 | + table: { | ||
| 75 | + id: '编号', | ||
| 76 | + ownerName: '业主名称', | ||
| 77 | + payerObjName: '付费对象', | ||
| 78 | + feeName: '费用名称', | ||
| 79 | + amountdOwed: '催缴金额', | ||
| 80 | + timeRange: '欠费时间段', | ||
| 81 | + callableWayName: '催缴方式', | ||
| 82 | + staffName: '催缴人', | ||
| 83 | + stateName: '状态', | ||
| 84 | + remark: '说明', | ||
| 85 | + createTime: '创建时间' | ||
| 86 | + }, | ||
| 87 | + write: { | ||
| 88 | + title: '催缴登记', | ||
| 89 | + roomName: '登记房屋', | ||
| 90 | + feeName: '催缴费用', | ||
| 91 | + remark: '催缴说明', | ||
| 92 | + remarkPlaceholder: '请输入备注', | ||
| 93 | + success: '登记成功', | ||
| 94 | + error: '登记失败' | ||
| 95 | + }, | ||
| 96 | + delete: { | ||
| 97 | + title: '删除确认', | ||
| 98 | + confirm: '确定删除欠费催缴记录吗?', | ||
| 99 | + success: '删除成功', | ||
| 100 | + error: '删除失败' | ||
| 101 | + }, | ||
| 102 | + fetchError: '获取数据失败', | ||
| 103 | + selectRoomFirst: '请先选择房屋' | ||
| 104 | + } | ||
| 105 | + } | ||
| 106 | +} | ||
| 0 | \ No newline at end of file | 107 | \ No newline at end of file |
src/views/fee/oweFeeCallableList.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="owe-fee-callable-container"> | ||
| 3 | + <el-row :gutter="20"> | ||
| 4 | + <el-col :span="4" class="tree-container"> | ||
| 5 | + <room-tree-div ref="roomTree" @selectRoom="handleSelectRoom"></room-tree-div> | ||
| 6 | + </el-col> | ||
| 7 | + <el-col :span="20"> | ||
| 8 | + <el-card class="search-card"> | ||
| 9 | + <div slot="header" class="flex justify-between"> | ||
| 10 | + <span>{{ $t('oweFeeCallable.search.title') }}</span> | ||
| 11 | + </div> | ||
| 12 | + <el-form :inline="true" :model="searchForm" class="search-form text-left"> | ||
| 13 | + <el-form-item :label="$t('oweFeeCallable.search.ownerName')"> | ||
| 14 | + <el-input v-model="searchForm.ownerName" | ||
| 15 | + :placeholder="$t('oweFeeCallable.search.ownerNamePlaceholder')"></el-input> | ||
| 16 | + </el-form-item> | ||
| 17 | + <el-form-item :label="$t('oweFeeCallable.search.feeName')"> | ||
| 18 | + <el-input v-model="searchForm.feeName" | ||
| 19 | + :placeholder="$t('oweFeeCallable.search.feeNamePlaceholder')"></el-input> | ||
| 20 | + </el-form-item> | ||
| 21 | + <el-form-item :label="$t('oweFeeCallable.search.callableWay')"> | ||
| 22 | + <el-select v-model="searchForm.callableWay" | ||
| 23 | + :placeholder="$t('oweFeeCallable.search.callableWayPlaceholder')" style="width:100%"> | ||
| 24 | + <el-option label="全部" value=""></el-option> | ||
| 25 | + <el-option label="微信模板消息" value="WECHAT"></el-option> | ||
| 26 | + <el-option label="短信" value="SMS"></el-option> | ||
| 27 | + <el-option label="上门催缴" value="PRINT"></el-option> | ||
| 28 | + </el-select> | ||
| 29 | + </el-form-item> | ||
| 30 | + <el-form-item :label="$t('oweFeeCallable.search.staffName')"> | ||
| 31 | + <el-input v-model="searchForm.staffName" | ||
| 32 | + :placeholder="$t('oweFeeCallable.search.staffNamePlaceholder')"></el-input> | ||
| 33 | + </el-form-item> | ||
| 34 | + <el-form-item :label="$t('oweFeeCallable.search.state')"> | ||
| 35 | + <el-select v-model="searchForm.state" :placeholder="$t('oweFeeCallable.search.statePlaceholder')" | ||
| 36 | + style="width:100%"> | ||
| 37 | + <el-option label="全部" value=""></el-option> | ||
| 38 | + <el-option label="待催缴" value="W"></el-option> | ||
| 39 | + <el-option label="催缴完成" value="C"></el-option> | ||
| 40 | + <el-option label="催缴失败" value="F"></el-option> | ||
| 41 | + <el-option label="催缴中" value="D"></el-option> | ||
| 42 | + </el-select> | ||
| 43 | + </el-form-item> | ||
| 44 | + <el-form-item> | ||
| 45 | + <el-button type="primary" @click="handleSearch">{{ $t('common.search') }}</el-button> | ||
| 46 | + <el-button @click="handleReset">{{ $t('common.reset') }}</el-button> | ||
| 47 | + </el-form-item> | ||
| 48 | + </el-form> | ||
| 49 | + </el-card> | ||
| 50 | + | ||
| 51 | + <el-card class="list-card"> | ||
| 52 | + <div slot="header" class="flex justify-between"> | ||
| 53 | + <span>{{ roomName || $t('oweFeeCallable.list.title') }}</span> | ||
| 54 | + <div style="float: right;"> | ||
| 55 | + <el-button type="primary" size="small" @click="handleWritePrint">{{ $t('oweFeeCallable.list.register') | ||
| 56 | + }}</el-button> | ||
| 57 | + <el-button type="primary" size="small" @click="handleAdd">{{ $t('oweFeeCallable.list.call') }}</el-button> | ||
| 58 | + </div> | ||
| 59 | + </div> | ||
| 60 | + <el-table :data="tableData" border style="width: 100%" v-loading="loading"> | ||
| 61 | + <el-table-column prop="ofcId" :label="$t('oweFeeCallable.table.id')" align="center"> | ||
| 62 | + </el-table-column> | ||
| 63 | + <el-table-column prop="ownerName" :label="$t('oweFeeCallable.table.ownerName')" align="center"> | ||
| 64 | + </el-table-column> | ||
| 65 | + <el-table-column prop="payerObjName" :label="$t('oweFeeCallable.table.payerObjName')" align="center"> | ||
| 66 | + </el-table-column> | ||
| 67 | + <el-table-column prop="feeName" :label="$t('oweFeeCallable.table.feeName')" align="center"> | ||
| 68 | + </el-table-column> | ||
| 69 | + <el-table-column prop="amountdOwed" :label="$t('oweFeeCallable.table.amountdOwed')" align="center"> | ||
| 70 | + </el-table-column> | ||
| 71 | + <el-table-column :label="$t('oweFeeCallable.table.timeRange')" align="center"> | ||
| 72 | + <template slot-scope="scope"> | ||
| 73 | + {{ scope.row.startTime }} ~ {{ scope.row.endTime }} | ||
| 74 | + </template> | ||
| 75 | + </el-table-column> | ||
| 76 | + <el-table-column prop="callableWayName" :label="$t('oweFeeCallable.table.callableWayName')" align="center"> | ||
| 77 | + </el-table-column> | ||
| 78 | + <el-table-column prop="staffName" :label="$t('oweFeeCallable.table.staffName')" align="center"> | ||
| 79 | + </el-table-column> | ||
| 80 | + <el-table-column prop="stateName" :label="$t('oweFeeCallable.table.stateName')" align="center"> | ||
| 81 | + </el-table-column> | ||
| 82 | + <el-table-column prop="remark" :label="$t('oweFeeCallable.table.remark')" align="center" width="200"> | ||
| 83 | + <template slot-scope="scope"> | ||
| 84 | + <el-tooltip :content="scope.row.remark" placement="top"> | ||
| 85 | + <div class="text-ellipsis">{{ scope.row.remark }}</div> | ||
| 86 | + </el-tooltip> | ||
| 87 | + </template> | ||
| 88 | + </el-table-column> | ||
| 89 | + <el-table-column prop="createTime" :label="$t('oweFeeCallable.table.createTime')" align="center"> | ||
| 90 | + </el-table-column> | ||
| 91 | + <el-table-column :label="$t('common.operation')" align="center" width="150"> | ||
| 92 | + <template slot-scope="scope"> | ||
| 93 | + <el-button size="mini" type="danger" @click="handleDelete(scope.row)">{{ $t('common.delete') | ||
| 94 | + }}</el-button> | ||
| 95 | + </template> | ||
| 96 | + </el-table-column> | ||
| 97 | + </el-table> | ||
| 98 | + <el-pagination @size-change="handleSizeChange" @current-change="handlePageChange" | ||
| 99 | + :current-page="pagination.current" :page-sizes="[10, 20, 30, 50]" :page-size="pagination.size" | ||
| 100 | + layout="total, sizes, prev, pager, next, jumper" :total="pagination.total" class="pagination"> | ||
| 101 | + </el-pagination> | ||
| 102 | + </el-card> | ||
| 103 | + </el-col> | ||
| 104 | + </el-row> | ||
| 105 | + | ||
| 106 | + <write-owe-fee-callable ref="writeOweFeeCallable" @success="handleSuccess"></write-owe-fee-callable> | ||
| 107 | + <delete-owe-fee-callable ref="deleteOweFeeCallable" @success="handleSuccess"></delete-owe-fee-callable> | ||
| 108 | + </div> | ||
| 109 | +</template> | ||
| 110 | + | ||
| 111 | +<script> | ||
| 112 | +import { listOweFeeCallable } from '@/api/fee/oweFeeCallableApi' | ||
| 113 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 114 | +import RoomTreeDiv from '@/components/room/roomTreeDiv' | ||
| 115 | +import WriteOweFeeCallable from '@/components/fee/writeOweFeeCallable' | ||
| 116 | +import DeleteOweFeeCallable from '@/components/fee/deleteOweFeeCallable' | ||
| 117 | + | ||
| 118 | +export default { | ||
| 119 | + name: 'OweFeeCallableList', | ||
| 120 | + components: { | ||
| 121 | + RoomTreeDiv, | ||
| 122 | + WriteOweFeeCallable, | ||
| 123 | + DeleteOweFeeCallable | ||
| 124 | + }, | ||
| 125 | + data() { | ||
| 126 | + return { | ||
| 127 | + loading: false, | ||
| 128 | + roomName: '', | ||
| 129 | + roomId: '', | ||
| 130 | + searchForm: { | ||
| 131 | + ownerName: '', | ||
| 132 | + feeName: '', | ||
| 133 | + callableWay: '', | ||
| 134 | + staffName: '', | ||
| 135 | + state: '', | ||
| 136 | + payerObjId: '' | ||
| 137 | + }, | ||
| 138 | + tableData: [], | ||
| 139 | + pagination: { | ||
| 140 | + current: 1, | ||
| 141 | + size: 10, | ||
| 142 | + total: 0 | ||
| 143 | + } | ||
| 144 | + } | ||
| 145 | + }, | ||
| 146 | + created() { | ||
| 147 | + this.communityId = getCommunityId() | ||
| 148 | + this.getList() | ||
| 149 | + }, | ||
| 150 | + methods: { | ||
| 151 | + async getList() { | ||
| 152 | + try { | ||
| 153 | + this.loading = true | ||
| 154 | + const params = { | ||
| 155 | + page: this.pagination.current, | ||
| 156 | + row: this.pagination.size, | ||
| 157 | + communityId: this.communityId, | ||
| 158 | + ...this.searchForm | ||
| 159 | + } | ||
| 160 | + const { data, total } = await listOweFeeCallable(params) | ||
| 161 | + this.tableData = data | ||
| 162 | + this.pagination.total = total | ||
| 163 | + } catch (error) { | ||
| 164 | + this.$message.error(this.$t('oweFeeCallable.fetchError')) | ||
| 165 | + } finally { | ||
| 166 | + this.loading = false | ||
| 167 | + } | ||
| 168 | + }, | ||
| 169 | + handleSearch() { | ||
| 170 | + this.pagination.current = 1 | ||
| 171 | + this.getList() | ||
| 172 | + }, | ||
| 173 | + handleReset() { | ||
| 174 | + this.searchForm = { | ||
| 175 | + ownerName: '', | ||
| 176 | + feeName: '', | ||
| 177 | + callableWay: '', | ||
| 178 | + staffName: '', | ||
| 179 | + state: '', | ||
| 180 | + payerObjId: this.searchForm.payerObjId | ||
| 181 | + } | ||
| 182 | + this.handleSearch() | ||
| 183 | + }, | ||
| 184 | + handleSelectRoom({ roomId, roomName }) { | ||
| 185 | + this.roomId = roomId | ||
| 186 | + this.roomName = roomName | ||
| 187 | + this.searchForm.payerObjId = roomId | ||
| 188 | + this.handleSearch() | ||
| 189 | + }, | ||
| 190 | + handleWritePrint() { | ||
| 191 | + if (!this.roomId) { | ||
| 192 | + this.$message.warning(this.$t('oweFeeCallable.selectRoomFirst')) | ||
| 193 | + return | ||
| 194 | + } | ||
| 195 | + this.$refs.writeOweFeeCallable.open({ | ||
| 196 | + roomId: this.roomId, | ||
| 197 | + roomName: this.roomName | ||
| 198 | + }) | ||
| 199 | + }, | ||
| 200 | + handleAdd() { | ||
| 201 | + this.$router.push('/views/fee/addOweFeeCallable') | ||
| 202 | + }, | ||
| 203 | + handleDelete(row) { | ||
| 204 | + this.$refs.deleteOweFeeCallable.open(row) | ||
| 205 | + }, | ||
| 206 | + handleSuccess() { | ||
| 207 | + this.getList() | ||
| 208 | + }, | ||
| 209 | + handleSizeChange(val) { | ||
| 210 | + this.pagination.size = val | ||
| 211 | + this.getList() | ||
| 212 | + }, | ||
| 213 | + handlePageChange(val) { | ||
| 214 | + this.pagination.current = val | ||
| 215 | + this.getList() | ||
| 216 | + } | ||
| 217 | + } | ||
| 218 | +} | ||
| 219 | +</script> | ||
| 220 | + | ||
| 221 | +<style lang="scss" scoped> | ||
| 222 | +.owe-fee-callable-container { | ||
| 223 | + padding: 20px; | ||
| 224 | + | ||
| 225 | + .tree-container { | ||
| 226 | + min-height: 450px; | ||
| 227 | + overflow-y: auto; | ||
| 228 | + background: #fff; | ||
| 229 | + padding: 10px; | ||
| 230 | + border-radius: 4px; | ||
| 231 | + } | ||
| 232 | + | ||
| 233 | + .search-card { | ||
| 234 | + margin-bottom: 20px; | ||
| 235 | + | ||
| 236 | + .search-form { | ||
| 237 | + .el-form-item { | ||
| 238 | + margin-bottom: 0; | ||
| 239 | + } | ||
| 240 | + } | ||
| 241 | + } | ||
| 242 | + | ||
| 243 | + .list-card { | ||
| 244 | + .pagination { | ||
| 245 | + margin-top: 20px; | ||
| 246 | + text-align: right; | ||
| 247 | + } | ||
| 248 | + } | ||
| 249 | + | ||
| 250 | + .text-ellipsis { | ||
| 251 | + white-space: nowrap; | ||
| 252 | + overflow: hidden; | ||
| 253 | + text-overflow: ellipsis; | ||
| 254 | + } | ||
| 255 | +} | ||
| 256 | +</style> | ||
| 0 | \ No newline at end of file | 257 | \ No newline at end of file |
src/views/fee/payFeeBatchLang.js
0 → 100644
| 1 | +export const messages = { | ||
| 2 | + en: { | ||
| 3 | + payFeeBatch: { | ||
| 4 | + search: { | ||
| 5 | + title: 'Search Conditions', | ||
| 6 | + batchId: 'Please enter batch number', | ||
| 7 | + state: 'Please select status', | ||
| 8 | + createUserName: 'Please enter creator' | ||
| 9 | + }, | ||
| 10 | + list: { | ||
| 11 | + title: 'Fee Cancellation' | ||
| 12 | + }, | ||
| 13 | + table: { | ||
| 14 | + batchId: 'Batch Number', | ||
| 15 | + createUserName: 'Employee', | ||
| 16 | + createTime: 'Time', | ||
| 17 | + remark: 'Cancellation Reason', | ||
| 18 | + noRemark: 'None', | ||
| 19 | + stateName: 'Audit Status', | ||
| 20 | + msg: 'Audit Opinion', | ||
| 21 | + operation: 'Operation' | ||
| 22 | + }, | ||
| 23 | + state: { | ||
| 24 | + normal: 'Normal', | ||
| 25 | + applyCancel: 'Apply for Cancellation', | ||
| 26 | + auditPass: 'Audit Passed', | ||
| 27 | + auditFail: 'Audit Failed' | ||
| 28 | + }, | ||
| 29 | + button: { | ||
| 30 | + applyCancel: 'Apply for Cancellation', | ||
| 31 | + audit: 'Audit' | ||
| 32 | + }, | ||
| 33 | + message: { | ||
| 34 | + auditSuccess: 'Audit successful' | ||
| 35 | + } | ||
| 36 | + }, | ||
| 37 | + applyDeleteFeeBatch: { | ||
| 38 | + title: 'Fee Cancellation Application', | ||
| 39 | + form: { | ||
| 40 | + batchId: 'Batch Number', | ||
| 41 | + createUserName: 'Employee', | ||
| 42 | + createTime: 'Creation Time', | ||
| 43 | + remark: 'Cancellation Reason' | ||
| 44 | + }, | ||
| 45 | + rules: { | ||
| 46 | + remarkRequired: 'Cancellation reason cannot be empty' | ||
| 47 | + }, | ||
| 48 | + placeholder: { | ||
| 49 | + remark: 'Please enter the cancellation reason' | ||
| 50 | + }, | ||
| 51 | + message: { | ||
| 52 | + success: 'Cancellation application submitted successfully' | ||
| 53 | + } | ||
| 54 | + }, | ||
| 55 | + audit: { | ||
| 56 | + title: 'Audit Information', | ||
| 57 | + form: { | ||
| 58 | + state: 'Audit Status', | ||
| 59 | + remark: 'Reason' | ||
| 60 | + }, | ||
| 61 | + state: { | ||
| 62 | + agree: 'Agree', | ||
| 63 | + reject: 'Reject' | ||
| 64 | + }, | ||
| 65 | + rules: { | ||
| 66 | + stateRequired: 'Audit status cannot be empty', | ||
| 67 | + remarkRequired: 'Reason cannot be empty', | ||
| 68 | + remarkMaxLength: 'Reason cannot exceed 200 characters' | ||
| 69 | + }, | ||
| 70 | + placeholder: { | ||
| 71 | + state: 'Please audit', | ||
| 72 | + remark: 'Please enter the reason (required)' | ||
| 73 | + } | ||
| 74 | + } | ||
| 75 | + }, | ||
| 76 | + zh: { | ||
| 77 | + payFeeBatch: { | ||
| 78 | + search: { | ||
| 79 | + title: '查询条件', | ||
| 80 | + batchId: '请输入批次号', | ||
| 81 | + state: '请选择状态', | ||
| 82 | + createUserName: '请填写创建员工' | ||
| 83 | + }, | ||
| 84 | + list: { | ||
| 85 | + title: '取消费用' | ||
| 86 | + }, | ||
| 87 | + table: { | ||
| 88 | + batchId: '批次号', | ||
| 89 | + createUserName: '员工', | ||
| 90 | + createTime: '时间', | ||
| 91 | + remark: '取消原因', | ||
| 92 | + noRemark: '无', | ||
| 93 | + stateName: '审核状态', | ||
| 94 | + msg: '审核意见', | ||
| 95 | + operation: '操作' | ||
| 96 | + }, | ||
| 97 | + state: { | ||
| 98 | + normal: '正常', | ||
| 99 | + applyCancel: '申请取消', | ||
| 100 | + auditPass: '审核通过', | ||
| 101 | + auditFail: '审核失败' | ||
| 102 | + }, | ||
| 103 | + button: { | ||
| 104 | + applyCancel: '申请取消', | ||
| 105 | + audit: '审核' | ||
| 106 | + }, | ||
| 107 | + message: { | ||
| 108 | + auditSuccess: '审核成功' | ||
| 109 | + } | ||
| 110 | + }, | ||
| 111 | + applyDeleteFeeBatch: { | ||
| 112 | + title: '费用取消申请', | ||
| 113 | + form: { | ||
| 114 | + batchId: '批次号', | ||
| 115 | + createUserName: '员工', | ||
| 116 | + createTime: '创建时间', | ||
| 117 | + remark: '取消原因' | ||
| 118 | + }, | ||
| 119 | + rules: { | ||
| 120 | + remarkRequired: '取消原因不能为空' | ||
| 121 | + }, | ||
| 122 | + placeholder: { | ||
| 123 | + remark: '请填写取消原因' | ||
| 124 | + }, | ||
| 125 | + message: { | ||
| 126 | + success: '取消申请提交成功' | ||
| 127 | + } | ||
| 128 | + }, | ||
| 129 | + audit: { | ||
| 130 | + title: '审核信息', | ||
| 131 | + form: { | ||
| 132 | + state: '审核状态', | ||
| 133 | + remark: '原因' | ||
| 134 | + }, | ||
| 135 | + state: { | ||
| 136 | + agree: '同意', | ||
| 137 | + reject: '拒绝' | ||
| 138 | + }, | ||
| 139 | + rules: { | ||
| 140 | + stateRequired: '审核状态不能为空', | ||
| 141 | + remarkRequired: '原因内容不能为空', | ||
| 142 | + remarkMaxLength: '原因内容不能超过200字' | ||
| 143 | + }, | ||
| 144 | + placeholder: { | ||
| 145 | + state: '请审核', | ||
| 146 | + remark: '请填写原因(必填)' | ||
| 147 | + } | ||
| 148 | + } | ||
| 149 | + } | ||
| 150 | +} | ||
| 0 | \ No newline at end of file | 151 | \ No newline at end of file |
src/views/fee/payFeeBatchList.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="pay-fee-batch-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('payFeeBatch.search.title') }}</span> | ||
| 8 | + </div> | ||
| 9 | + <div class="search-content"> | ||
| 10 | + <el-row :gutter="20"> | ||
| 11 | + <el-col :span="6"> | ||
| 12 | + <el-input v-model="payFeeBatchInfo.conditions.batchId" :placeholder="$t('payFeeBatch.search.batchId')" | ||
| 13 | + clearable /> | ||
| 14 | + </el-col> | ||
| 15 | + <el-col :span="6"> | ||
| 16 | + <el-select v-model="payFeeBatchInfo.conditions.state" :placeholder="$t('payFeeBatch.search.state')" | ||
| 17 | + style="width:100%"> | ||
| 18 | + <el-option :label="$t('payFeeBatch.state.normal')" value="2006001" /> | ||
| 19 | + <el-option :label="$t('payFeeBatch.state.applyCancel')" value="2007001" /> | ||
| 20 | + <el-option :label="$t('payFeeBatch.state.auditPass')" value="2008001" /> | ||
| 21 | + <el-option :label="$t('payFeeBatch.state.auditFail')" value="2009001" /> | ||
| 22 | + </el-select> | ||
| 23 | + </el-col> | ||
| 24 | + <el-col :span="6"> | ||
| 25 | + <el-input v-model="payFeeBatchInfo.conditions.createUserName" | ||
| 26 | + :placeholder="$t('payFeeBatch.search.createUserName')" clearable /> | ||
| 27 | + </el-col> | ||
| 28 | + <el-col :span="6"> | ||
| 29 | + <el-button type="primary" @click="_queryPayFeeBatchMethod"> | ||
| 30 | + <i class="el-icon-search"></i> | ||
| 31 | + {{ $t('common.search') }} | ||
| 32 | + </el-button> | ||
| 33 | + <el-button @click="_resetPayFeeBatchMethod"> | ||
| 34 | + <i class="el-icon-refresh"></i> | ||
| 35 | + {{ $t('common.reset') }} | ||
| 36 | + </el-button> | ||
| 37 | + </el-col> | ||
| 38 | + </el-row> | ||
| 39 | + </div> | ||
| 40 | + </el-card> | ||
| 41 | + </el-col> | ||
| 42 | + </el-row> | ||
| 43 | + | ||
| 44 | + <el-row :gutter="20" style="margin-top:20px"> | ||
| 45 | + <el-col :span="24"> | ||
| 46 | + <el-card class="box-card"> | ||
| 47 | + <div slot="header" class="flex justify-between"> | ||
| 48 | + <span>{{ $t('payFeeBatch.list.title') }}</span> | ||
| 49 | + </div> | ||
| 50 | + <el-table :data="payFeeBatchInfo.payFeeBatchs" border style="width:100%"> | ||
| 51 | + <el-table-column prop="batchId" :label="$t('payFeeBatch.table.batchId')" align="center" /> | ||
| 52 | + <el-table-column prop="createUserName" :label="$t('payFeeBatch.table.createUserName')" align="center" /> | ||
| 53 | + <el-table-column prop="createTime" :label="$t('payFeeBatch.table.createTime')" align="center" /> | ||
| 54 | + <el-table-column prop="remark" :label="$t('payFeeBatch.table.remark')" align="center"> | ||
| 55 | + <template slot-scope="scope"> | ||
| 56 | + {{ scope.row.remark || $t('payFeeBatch.table.noRemark') }} | ||
| 57 | + </template> | ||
| 58 | + </el-table-column> | ||
| 59 | + <el-table-column prop="stateName" :label="$t('payFeeBatch.table.stateName')" align="center" /> | ||
| 60 | + <el-table-column prop="msg" :label="$t('payFeeBatch.table.msg')" align="center" /> | ||
| 61 | + <el-table-column :label="$t('common.operation')" align="center" width="200"> | ||
| 62 | + <template slot-scope="scope"> | ||
| 63 | + <el-button v-if="scope.row.state === '2006001'" size="mini" @click="_openApply(scope.row)"> | ||
| 64 | + {{ $t('payFeeBatch.button.applyCancel') }} | ||
| 65 | + </el-button> | ||
| 66 | + <el-button v-if="scope.row.state === '2007001'" size="mini" type="primary" | ||
| 67 | + @click="_openPayFeeBatchAuditModel(scope.row)"> | ||
| 68 | + {{ $t('payFeeBatch.button.audit') }} | ||
| 69 | + </el-button> | ||
| 70 | + </template> | ||
| 71 | + </el-table-column> | ||
| 72 | + </el-table> | ||
| 73 | + | ||
| 74 | + <el-pagination :current-page.sync="pagination.current" :page-sizes="[10, 20, 30, 50]" | ||
| 75 | + :page-size="pagination.size" :total="pagination.total" layout="total, sizes, prev, pager, next, jumper" | ||
| 76 | + @size-change="handleSizeChange" @current-change="handleCurrentChange" /> | ||
| 77 | + </el-card> | ||
| 78 | + </el-col> | ||
| 79 | + </el-row> | ||
| 80 | + | ||
| 81 | + <apply-delete-fee-batch ref="applyDeleteFeeBatch" @success="handleSuccess" /> | ||
| 82 | + <audit ref="audit" @success="handleSuccess" /> | ||
| 83 | + </div> | ||
| 84 | +</template> | ||
| 85 | + | ||
| 86 | +<script> | ||
| 87 | +import { listPayFeeBatch, updatePayFeeBatch } from '@/api/fee/payFeeBatchApi' | ||
| 88 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 89 | +import ApplyDeleteFeeBatch from '@/components/fee/applyDeleteFeeBatch' | ||
| 90 | +import Audit from '@/components/fee/audit' | ||
| 91 | + | ||
| 92 | +export default { | ||
| 93 | + name: 'PayFeeBatchList', | ||
| 94 | + components: { | ||
| 95 | + ApplyDeleteFeeBatch, | ||
| 96 | + Audit | ||
| 97 | + }, | ||
| 98 | + data() { | ||
| 99 | + return { | ||
| 100 | + payFeeBatchInfo: { | ||
| 101 | + payFeeBatchs: [], | ||
| 102 | + conditions: { | ||
| 103 | + communityId: '', | ||
| 104 | + state: '', | ||
| 105 | + batchId: '', | ||
| 106 | + createUserName: '' | ||
| 107 | + } | ||
| 108 | + }, | ||
| 109 | + pagination: { | ||
| 110 | + current: 1, | ||
| 111 | + size: 10, | ||
| 112 | + total: 0 | ||
| 113 | + } | ||
| 114 | + } | ||
| 115 | + }, | ||
| 116 | + created() { | ||
| 117 | + this.payFeeBatchInfo.conditions.communityId = getCommunityId() | ||
| 118 | + this._listPayFeeBatchs(this.pagination.current, this.pagination.size) | ||
| 119 | + }, | ||
| 120 | + methods: { | ||
| 121 | + async _listPayFeeBatchs(page, size) { | ||
| 122 | + try { | ||
| 123 | + const params = { | ||
| 124 | + ...this.payFeeBatchInfo.conditions, | ||
| 125 | + page, | ||
| 126 | + row: size | ||
| 127 | + } | ||
| 128 | + const { data, total } = await listPayFeeBatch(params) | ||
| 129 | + this.payFeeBatchInfo.payFeeBatchs = data | ||
| 130 | + this.pagination.total = total | ||
| 131 | + } catch (error) { | ||
| 132 | + console.error('获取数据失败:', error) | ||
| 133 | + } | ||
| 134 | + }, | ||
| 135 | + _queryPayFeeBatchMethod() { | ||
| 136 | + this.pagination.current = 1 | ||
| 137 | + this._listPayFeeBatchs(this.pagination.current, this.pagination.size) | ||
| 138 | + }, | ||
| 139 | + _resetPayFeeBatchMethod() { | ||
| 140 | + this.payFeeBatchInfo.conditions = { | ||
| 141 | + ...this.payFeeBatchInfo.conditions, | ||
| 142 | + state: '', | ||
| 143 | + batchId: '', | ||
| 144 | + createUserName: '' | ||
| 145 | + } | ||
| 146 | + this._queryPayFeeBatchMethod() | ||
| 147 | + }, | ||
| 148 | + _openApply(payFee) { | ||
| 149 | + this.$refs.applyDeleteFeeBatch.open(payFee) | ||
| 150 | + }, | ||
| 151 | + _openPayFeeBatchAuditModel(payFee) { | ||
| 152 | + this.payFeeBatchInfo.payFeeBatch = payFee | ||
| 153 | + this.$refs.audit.open() | ||
| 154 | + }, | ||
| 155 | + async _auditPayFeeBatchState(auditInfo) { | ||
| 156 | + try { | ||
| 157 | + const payFeeBatch = { | ||
| 158 | + ...this.payFeeBatchInfo.payFeeBatch, | ||
| 159 | + state: auditInfo.state, | ||
| 160 | + msg: auditInfo.remark | ||
| 161 | + } | ||
| 162 | + await updatePayFeeBatch(payFeeBatch) | ||
| 163 | + this.$message.success(this.$t('payFeeBatch.message.auditSuccess')) | ||
| 164 | + this._listPayFeeBatchs(this.pagination.current, this.pagination.size) | ||
| 165 | + } catch (error) { | ||
| 166 | + console.error('审核失败:', error) | ||
| 167 | + } | ||
| 168 | + }, | ||
| 169 | + handleSuccess() { | ||
| 170 | + this._listPayFeeBatchs(this.pagination.current, this.pagination.size) | ||
| 171 | + }, | ||
| 172 | + handleSizeChange(val) { | ||
| 173 | + this.pagination.size = val | ||
| 174 | + this._listPayFeeBatchs(this.pagination.current, this.pagination.size) | ||
| 175 | + }, | ||
| 176 | + handleCurrentChange(val) { | ||
| 177 | + this.pagination.current = val | ||
| 178 | + this._listPayFeeBatchs(this.pagination.current, this.pagination.size) | ||
| 179 | + } | ||
| 180 | + } | ||
| 181 | +} | ||
| 182 | +</script> | ||
| 183 | + | ||
| 184 | +<style lang="scss" scoped> | ||
| 185 | +.pay-fee-batch-container { | ||
| 186 | + padding: 20px; | ||
| 187 | + | ||
| 188 | + .search-content { | ||
| 189 | + margin-bottom: 20px; | ||
| 190 | + } | ||
| 191 | + | ||
| 192 | + .el-pagination { | ||
| 193 | + margin-top: 20px; | ||
| 194 | + text-align: right; | ||
| 195 | + } | ||
| 196 | +} | ||
| 197 | +</style> | ||
| 0 | \ No newline at end of file | 198 | \ No newline at end of file |
src/views/fee/staffFeeManageLang.js
0 → 100644
| 1 | +export const messages = { | ||
| 2 | + en: { | ||
| 3 | + staffFeeManage: { | ||
| 4 | + search: { | ||
| 5 | + title: 'Search Conditions', | ||
| 6 | + userCode: 'Staff Code', | ||
| 7 | + userCodePlaceholder: 'Please enter staff code', | ||
| 8 | + startTime: 'Start Time', | ||
| 9 | + startTimePlaceholder: 'Please select start time', | ||
| 10 | + endTime: 'End Time', | ||
| 11 | + endTimePlaceholder: 'Please select end time' | ||
| 12 | + }, | ||
| 13 | + list: { | ||
| 14 | + title: 'Staff Fee Management' | ||
| 15 | + }, | ||
| 16 | + table: { | ||
| 17 | + userCode: 'Staff Code', | ||
| 18 | + userName: 'Staff Name', | ||
| 19 | + receivableAmount: 'Receivable Amount', | ||
| 20 | + receivedAmount: 'Received Amount', | ||
| 21 | + yuan: 'Yuan' | ||
| 22 | + }, | ||
| 23 | + fetchError: 'Failed to fetch staff fee data' | ||
| 24 | + } | ||
| 25 | + }, | ||
| 26 | + zh: { | ||
| 27 | + staffFeeManage: { | ||
| 28 | + search: { | ||
| 29 | + title: '查询条件', | ||
| 30 | + userCode: '员工编码', | ||
| 31 | + userCodePlaceholder: '请填写员工编码', | ||
| 32 | + startTime: '开始时间', | ||
| 33 | + startTimePlaceholder: '请选择开始时间', | ||
| 34 | + endTime: '结束时间', | ||
| 35 | + endTimePlaceholder: '请选择结束时间' | ||
| 36 | + }, | ||
| 37 | + list: { | ||
| 38 | + title: '员工收费管理' | ||
| 39 | + }, | ||
| 40 | + table: { | ||
| 41 | + userCode: '员工编码', | ||
| 42 | + userName: '员工名称', | ||
| 43 | + receivableAmount: '应收金额', | ||
| 44 | + receivedAmount: '实收金额', | ||
| 45 | + yuan: '元' | ||
| 46 | + }, | ||
| 47 | + fetchError: '获取员工收费数据失败' | ||
| 48 | + } | ||
| 49 | + } | ||
| 50 | +} | ||
| 0 | \ No newline at end of file | 51 | \ No newline at end of file |
src/views/fee/staffFeeManageList.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="staff-fee-manage-container animated fadeInRight"> | ||
| 3 | + <el-row :gutter="20" class="mb-20"> | ||
| 4 | + <el-col :span="24"> | ||
| 5 | + <el-card> | ||
| 6 | + <div slot="header" class="flex justify-between"> | ||
| 7 | + <span>{{ $t('staffFeeManage.search.title') }}</span> | ||
| 8 | + </div> | ||
| 9 | + <el-form :inline="true" :model="searchForm" class="demo-form-inline"> | ||
| 10 | + <el-form-item :label="$t('staffFeeManage.search.userCode')"> | ||
| 11 | + <el-input | ||
| 12 | + v-model="searchForm.userCode" | ||
| 13 | + :placeholder="$t('staffFeeManage.search.userCodePlaceholder')" | ||
| 14 | + clearable | ||
| 15 | + /> | ||
| 16 | + </el-form-item> | ||
| 17 | + <el-form-item :label="$t('staffFeeManage.search.startTime')"> | ||
| 18 | + <el-date-picker | ||
| 19 | + v-model="searchForm.startTime" | ||
| 20 | + type="datetime" | ||
| 21 | + :placeholder="$t('staffFeeManage.search.startTimePlaceholder')" | ||
| 22 | + value-format="yyyy-MM-dd HH:mm:ss" | ||
| 23 | + /> | ||
| 24 | + </el-form-item> | ||
| 25 | + <el-form-item :label="$t('staffFeeManage.search.endTime')"> | ||
| 26 | + <el-date-picker | ||
| 27 | + v-model="searchForm.endTime" | ||
| 28 | + type="datetime" | ||
| 29 | + :placeholder="$t('staffFeeManage.search.endTimePlaceholder')" | ||
| 30 | + value-format="yyyy-MM-dd HH:mm:ss" | ||
| 31 | + /> | ||
| 32 | + </el-form-item> | ||
| 33 | + <el-form-item> | ||
| 34 | + <el-button type="primary" @click="handleSearch"> | ||
| 35 | + {{ $t('common.search') }} | ||
| 36 | + </el-button> | ||
| 37 | + <el-button @click="handleReset"> | ||
| 38 | + {{ $t('common.reset') }} | ||
| 39 | + </el-button> | ||
| 40 | + </el-form-item> | ||
| 41 | + </el-form> | ||
| 42 | + </el-card> | ||
| 43 | + </el-col> | ||
| 44 | + </el-row> | ||
| 45 | + | ||
| 46 | + <el-row :gutter="20"> | ||
| 47 | + <el-col :span="24"> | ||
| 48 | + <el-card> | ||
| 49 | + <div slot="header" class="flex justify-between"> | ||
| 50 | + <span>{{ $t('staffFeeManage.list.title') }}</span> | ||
| 51 | + <el-button | ||
| 52 | + type="primary" | ||
| 53 | + size="small" | ||
| 54 | + class="float-right" | ||
| 55 | + @click="handleExport" | ||
| 56 | + > | ||
| 57 | + {{ $t('common.export') }} | ||
| 58 | + </el-button> | ||
| 59 | + </div> | ||
| 60 | + <el-table | ||
| 61 | + v-loading="loading" | ||
| 62 | + :data="tableData" | ||
| 63 | + border | ||
| 64 | + style="width: 100%" | ||
| 65 | + > | ||
| 66 | + <el-table-column | ||
| 67 | + prop="userId" | ||
| 68 | + :label="$t('staffFeeManage.table.userCode')" | ||
| 69 | + align="center" | ||
| 70 | + /> | ||
| 71 | + <el-table-column | ||
| 72 | + prop="userName" | ||
| 73 | + :label="$t('staffFeeManage.table.userName')" | ||
| 74 | + align="center" | ||
| 75 | + /> | ||
| 76 | + <el-table-column | ||
| 77 | + prop="receivableAmount" | ||
| 78 | + :label="$t('staffFeeManage.table.receivableAmount')" | ||
| 79 | + align="center" | ||
| 80 | + > | ||
| 81 | + <template slot-scope="scope"> | ||
| 82 | + {{ scope.row.receivableAmount }} {{ $t('staffFeeManage.table.yuan') }} | ||
| 83 | + </template> | ||
| 84 | + </el-table-column> | ||
| 85 | + <el-table-column | ||
| 86 | + prop="receivedAmount" | ||
| 87 | + :label="$t('staffFeeManage.table.receivedAmount')" | ||
| 88 | + align="center" | ||
| 89 | + > | ||
| 90 | + <template slot-scope="scope"> | ||
| 91 | + {{ scope.row.receivedAmount }} {{ $t('staffFeeManage.table.yuan') }} | ||
| 92 | + </template> | ||
| 93 | + </el-table-column> | ||
| 94 | + </el-table> | ||
| 95 | + <el-pagination | ||
| 96 | + :current-page="pagination.current" | ||
| 97 | + :page-sizes="[10, 20, 30, 50]" | ||
| 98 | + :page-size="pagination.size" | ||
| 99 | + layout="total, sizes, prev, pager, next, jumper" | ||
| 100 | + :total="pagination.total" | ||
| 101 | + @size-change="handleSizeChange" | ||
| 102 | + @current-change="handleCurrentChange" | ||
| 103 | + /> | ||
| 104 | + </el-card> | ||
| 105 | + </el-col> | ||
| 106 | + </el-row> | ||
| 107 | + </div> | ||
| 108 | +</template> | ||
| 109 | + | ||
| 110 | +<script> | ||
| 111 | +import { getStaffFeeList } from '@/api/fee/staffFeeManageApi' | ||
| 112 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 113 | + | ||
| 114 | +export default { | ||
| 115 | + name: 'StaffFeeManageList', | ||
| 116 | + data() { | ||
| 117 | + return { | ||
| 118 | + loading: false, | ||
| 119 | + searchForm: { | ||
| 120 | + communityId: '', | ||
| 121 | + userCode: '', | ||
| 122 | + startTime: '', | ||
| 123 | + endTime: '' | ||
| 124 | + }, | ||
| 125 | + tableData: [], | ||
| 126 | + pagination: { | ||
| 127 | + current: 1, | ||
| 128 | + size: 10, | ||
| 129 | + total: 0 | ||
| 130 | + } | ||
| 131 | + } | ||
| 132 | + }, | ||
| 133 | + created() { | ||
| 134 | + this.searchForm.communityId = getCommunityId() | ||
| 135 | + this.getList() | ||
| 136 | + }, | ||
| 137 | + methods: { | ||
| 138 | + async getList() { | ||
| 139 | + try { | ||
| 140 | + this.loading = true | ||
| 141 | + const params = { | ||
| 142 | + page: this.pagination.current, | ||
| 143 | + row: this.pagination.size, | ||
| 144 | + ...this.searchForm | ||
| 145 | + } | ||
| 146 | + const { data, total } = await getStaffFeeList(params) | ||
| 147 | + this.tableData = data | ||
| 148 | + this.pagination.total = total | ||
| 149 | + } catch (error) { | ||
| 150 | + this.$message.error(this.$t('staffFeeManage.fetchError')) | ||
| 151 | + } finally { | ||
| 152 | + this.loading = false | ||
| 153 | + } | ||
| 154 | + }, | ||
| 155 | + handleSearch() { | ||
| 156 | + this.pagination.current = 1 | ||
| 157 | + this.getList() | ||
| 158 | + }, | ||
| 159 | + handleReset() { | ||
| 160 | + this.searchForm = { | ||
| 161 | + communityId: getCommunityId(), | ||
| 162 | + userCode: '', | ||
| 163 | + startTime: '', | ||
| 164 | + endTime: '' | ||
| 165 | + } | ||
| 166 | + this.pagination.current = 1 | ||
| 167 | + this.getList() | ||
| 168 | + }, | ||
| 169 | + handleExport() { | ||
| 170 | + // 导出逻辑 | ||
| 171 | + }, | ||
| 172 | + handleSizeChange(val) { | ||
| 173 | + this.pagination.size = val | ||
| 174 | + this.getList() | ||
| 175 | + }, | ||
| 176 | + handleCurrentChange(val) { | ||
| 177 | + this.pagination.current = val | ||
| 178 | + this.getList() | ||
| 179 | + } | ||
| 180 | + } | ||
| 181 | +} | ||
| 182 | +</script> | ||
| 183 | + | ||
| 184 | +<style lang="scss" scoped> | ||
| 185 | +.staff-fee-manage-container { | ||
| 186 | + padding: 20px; | ||
| 187 | + .mb-20 { | ||
| 188 | + margin-bottom: 20px; | ||
| 189 | + } | ||
| 190 | + .float-right { | ||
| 191 | + float: right; | ||
| 192 | + } | ||
| 193 | +} | ||
| 194 | +</style> | ||
| 0 | \ No newline at end of file | 195 | \ No newline at end of file |