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 | 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 | 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 | 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 | 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 | 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 | 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 | 112 | \ No newline at end of file | ... | ... |
src/components/fee/audit.vue
| 1 | 1 | <template> |
| 2 | 2 | <el-dialog |
| 3 | - :title="$t('audit.auditInfo')" | |
| 3 | + :title="$t('audit.title')" | |
| 4 | 4 | :visible.sync="visible" |
| 5 | 5 | width="50%" |
| 6 | 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 | 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 | 29 | value="1100" |
| 19 | 30 | /> |
| 20 | - <el-option | |
| 21 | - :label="$t('audit.reject')" | |
| 31 | + <el-option | |
| 32 | + :label="$t('audit.state.reject')" | |
| 22 | 33 | value="1200" |
| 23 | 34 | /> |
| 24 | 35 | </el-select> |
| 25 | 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 | 45 | <el-input |
| 28 | - v-model="form.remark" | |
| 46 | + v-model="formData.remark" | |
| 29 | 47 | type="textarea" |
| 30 | - :rows="4" | |
| 31 | - :placeholder="$t('audit.inputReason')" | |
| 48 | + :rows="3" | |
| 49 | + :placeholder="$t('audit.placeholder.remark')" | |
| 32 | 50 | /> |
| 33 | 51 | </el-form-item> |
| 34 | 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 | 61 | </el-dialog> |
| 40 | 62 | </template> |
| 41 | 63 | |
| 42 | 64 | <script> |
| 43 | 65 | export default { |
| 44 | - name: 'AuditModal', | |
| 66 | + name: 'Audit', | |
| 45 | 67 | data() { |
| 46 | 68 | return { |
| 47 | 69 | visible: false, |
| 48 | - form: { | |
| 70 | + formData: { | |
| 49 | 71 | state: '', |
| 50 | 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 | 76 | methods: { |
| 64 | 77 | open() { |
| 78 | + this.resetForm() | |
| 65 | 79 | this.visible = true |
| 66 | 80 | }, |
| 67 | 81 | handleClose() { |
| 68 | 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 | 91 | if (val === '1100') { |
| 72 | - this.form.remark = this.$t('audit.agree') | |
| 92 | + this.formData.remark = this.$t('audit.state.agree') | |
| 73 | 93 | } else { |
| 74 | - this.form.remark = '' | |
| 94 | + this.formData.remark = '' | |
| 75 | 95 | } |
| 76 | 96 | }, |
| 77 | 97 | handleSubmit() { |
| 78 | 98 | this.$refs.form.validate(valid => { |
| 79 | 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 | 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 | 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 | 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 | 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 | 98 | \ No newline at end of file | ... | ... |
src/i18n/feeI18n.js
| ... | ... | @@ -17,6 +17,12 @@ import { messages as shareReadingFeeMessages } from '../views/fee/shareReadingFe |
| 17 | 17 | import { messages as feeComboManageMessages } from '../views/fee/feeComboManageLang' |
| 18 | 18 | import { messages as payFeeAuditManageMessages } from '../views/fee/payFeeAuditManageLang' |
| 19 | 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 | 27 | export const messages = { |
| 22 | 28 | en: { |
| ... | ... | @@ -39,6 +45,12 @@ export const messages = { |
| 39 | 45 | ...feeComboManageMessages.en, |
| 40 | 46 | ...payFeeAuditManageMessages.en, |
| 41 | 47 | ...feeComboMemberManageMessages.en, |
| 48 | + ...payFeeBatchMessages.en, | |
| 49 | + ...listOweFeeMessages.en, | |
| 50 | + ...oweFeeCallableMessages.en, | |
| 51 | + ...addOweFeeCallableMessages.en, | |
| 52 | + ...staffFeeManageMessages.en, | |
| 53 | + ...feeSummaryMessages.en, | |
| 42 | 54 | }, |
| 43 | 55 | zh: { |
| 44 | 56 | ...contractCreateFeeMessages.zh, |
| ... | ... | @@ -60,5 +72,11 @@ export const messages = { |
| 60 | 72 | ...feeComboManageMessages.zh, |
| 61 | 73 | ...payFeeAuditManageMessages.zh, |
| 62 | 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 | 83 | \ No newline at end of file | ... | ... |
src/router/feeRouter.js
| ... | ... | @@ -79,5 +79,35 @@ export default [ |
| 79 | 79 | name: '/views/fee/feeComboMemberManage', |
| 80 | 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 | 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 | 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 | 356 | \ No newline at end of file | ... | ... |
src/views/fee/feeComboMemberManageList.vue
| ... | ... | @@ -14,80 +14,34 @@ |
| 14 | 14 | </div> |
| 15 | 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 | 22 | <template slot-scope="scope"> |
| 43 | 23 | {{ scope.row.paymentCd == '1200' ? $t('feeComboMemberManage.prepay') : $t('feeComboMemberManage.postpay') }} |
| 44 | 24 | </template> |
| 45 | 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 | 28 | <template slot-scope="scope"> |
| 56 | 29 | {{ scope.row.computingFormula == '2002' ? '-' : scope.row.squarePrice }} |
| 57 | 30 | </template> |
| 58 | 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 | 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 | 36 | {{ $t('common.delete') }} |
| 76 | 37 | </el-button> |
| 77 | 38 | </template> |
| 78 | 39 | </el-table-column> |
| 79 | 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 | 45 | </el-card> |
| 92 | 46 | |
| 93 | 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 | 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 | 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 | 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 | 418 | \ No newline at end of file | ... | ... |
src/views/fee/meterWaterManageList.vue
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 | 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 | 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 | 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 | 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 | 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 | 195 | \ No newline at end of file | ... | ... |