Commit 24d3590fc5bddf07c6a7d20044b8caa3577abff5

Authored by wuxw
1 parent 7a03ee5c

房屋收费页面开发完成

Showing 114 changed files with 10063 additions and 624 deletions
src/api/fee/addProxyFeeApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function saveProxyFee(data) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/meterWater.saveProxyFee',
  7 + method: 'post',
  8 + data
  9 + }).then(response => {
  10 + const res = response.data
  11 + if (res.code === 0) {
  12 + resolve(res)
  13 + } else {
  14 + reject(new Error(res.msg || 'Failed to save proxy fee'))
  15 + }
  16 + }).catch(error => {
  17 + reject(error)
  18 + })
  19 + })
  20 +}
  21 +
  22 +export function listFeeConfigs(params) {
  23 + return new Promise((resolve, reject) => {
  24 + request({
  25 + url: '/feeConfig.listFeeConfigs',
  26 + method: 'get',
  27 + params
  28 + }).then(response => {
  29 + const res = response.data
  30 + if (res.code === 0) {
  31 + resolve(res)
  32 + } else {
  33 + reject(new Error(res.msg || 'Failed to list fee configs'))
  34 + }
  35 + }).catch(error => {
  36 + reject(error)
  37 + })
  38 + })
  39 +}
0 \ No newline at end of file 40 \ No newline at end of file
src/api/fee/batchPayFeeOrderApi.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 +}
  18 +
  19 +// 查询费用对象
  20 +export function listFeeObj(params) {
  21 + return new Promise((resolve, reject) => {
  22 + request({
  23 + url: '/feeApi/listFeeObj',
  24 + method: 'get',
  25 + params
  26 + }).then(response => {
  27 + const res = response.data
  28 + resolve(res)
  29 + }).catch(error => {
  30 + reject(error)
  31 + })
  32 + })
  33 +}
  34 +
  35 +// 查询业主账户
  36 +export function queryCommunityOwnerAccount(params) {
  37 + return new Promise((resolve, reject) => {
  38 + request({
  39 + url: '/account.queryCommunityOwnerAccount',
  40 + method: 'get',
  41 + params
  42 + }).then(response => {
  43 + const res = response.data
  44 + resolve(res)
  45 + }).catch(error => {
  46 + reject(error)
  47 + })
  48 + })
  49 +}
  50 +
  51 +// 查询押金信息
  52 +export function queryFeeDeposit(params) {
  53 + return new Promise((resolve, reject) => {
  54 + request({
  55 + url: '/fee.queryFeeDeposit',
  56 + method: 'get',
  57 + params
  58 + }).then(response => {
  59 + const res = response.data
  60 + resolve(res)
  61 + }).catch(error => {
  62 + reject(error)
  63 + })
  64 + })
  65 +}
  66 +
  67 +// 退押金
  68 +export function refundFeeDeposit(data) {
  69 + return new Promise((resolve, reject) => {
  70 + request({
  71 + url: '/fee.refundFeeDeposit',
  72 + method: 'post',
  73 + data
  74 + }).then(response => {
  75 + const res = response.data
  76 + resolve(res)
  77 + }).catch(error => {
  78 + reject(error)
  79 + })
  80 + })
  81 +}
  82 +
  83 +// 批量缴费
  84 +export function payBatchFee(data) {
  85 + return new Promise((resolve, reject) => {
  86 + request({
  87 + url: '/fee.payBatchFee',
  88 + method: 'post',
  89 + data
  90 + }).then(response => {
  91 + const res = response.data
  92 + resolve(res)
  93 + }).catch(error => {
  94 + reject(error)
  95 + })
  96 + })
  97 +}
  98 +
  99 +// 扫码支付
  100 +export function qrCodePayment(data) {
  101 + return new Promise((resolve, reject) => {
  102 + request({
  103 + url: '/payment.qrCodePayment',
  104 + method: 'post',
  105 + data
  106 + }).then(response => {
  107 + const res = response.data
  108 + resolve(res)
  109 + }).catch(error => {
  110 + reject(error)
  111 + })
  112 + })
  113 +}
  114 +
  115 +// 检查支付状态
  116 +export function checkPayFinish(data) {
  117 + return new Promise((resolve, reject) => {
  118 + request({
  119 + url: '/payment.checkPayFinish',
  120 + method: 'post',
  121 + data
  122 + }).then(response => {
  123 + const res = response.data
  124 + resolve(res)
  125 + }).catch(error => {
  126 + reject(error)
  127 + })
  128 + })
  129 +}
  130 +
  131 +// 查询打印页面
  132 +export function listFeePrintPage(params) {
  133 + return new Promise((resolve, reject) => {
  134 + request({
  135 + url: '/feePrintPage.listFeePrintPage',
  136 + method: 'get',
  137 + params
  138 + }).then(response => {
  139 + const res = response.data
  140 + resolve(res)
  141 + }).catch(error => {
  142 + reject(error)
  143 + })
  144 + })
  145 +}
0 \ No newline at end of file 146 \ No newline at end of file
src/api/fee/carDetailOwnerApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function queryOwners(params) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/owner.queryOwners',
  7 + method: 'get',
  8 + params
  9 + }).then(response => {
  10 + const res = response.data
  11 + if (res.code == 0) {
  12 + resolve(res)
  13 + } else {
  14 + reject(new Error(res.msg || 'Failed to query owners'))
  15 + }
  16 + }).catch(error => {
  17 + reject(error)
  18 + })
  19 + })
  20 +}
0 \ No newline at end of file 21 \ No newline at end of file
src/api/fee/deleteFeeApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function deleteFee(data) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/fee.deleteFee',
  7 + method: 'post',
  8 + data
  9 + }).then(response => {
  10 + const res = response.data
  11 + if (res.code === 0) {
  12 + resolve(res)
  13 + } else {
  14 + reject(new Error(res.msg || '删除费用失败'))
  15 + }
  16 + }).catch(error => {
  17 + reject(error)
  18 + })
  19 + })
  20 +}
0 \ No newline at end of file 21 \ No newline at end of file
src/api/fee/deleteFeeRuleApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function deletePayFeeRule(data) {
  4 + return request({
  5 + url: '/payFeeRule.deletePayFeeRule',
  6 + method: 'post',
  7 + data
  8 + })
  9 +}
0 \ No newline at end of file 10 \ No newline at end of file
src/api/fee/deleteOweFeeCallableApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function deleteOweFeeCallable(data) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/oweFeeCallable.deleteOweFeeCallable',
  7 + method: 'post',
  8 + data
  9 + }).then(response => {
  10 + const res = response.data
  11 + if (res.code == 0) {
  12 + resolve(res)
  13 + } else {
  14 + reject(new Error(res.msg || 'Failed to delete owe fee callable'))
  15 + }
  16 + }).catch(error => {
  17 + reject(error)
  18 + })
  19 + })
  20 +}
0 \ No newline at end of file 21 \ No newline at end of file
src/api/fee/doImportCreateFeeApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function importData(data) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/assetImport/importData',
  7 + method: 'post',
  8 + data,
  9 + headers: {
  10 + 'Content-Type': 'multipart/form-data'
  11 + }
  12 + }).then(response => {
  13 + const res = response.data
  14 + if (res.code === 0) {
  15 + resolve(res)
  16 + } else {
  17 + reject(new Error(res.msg || 'Failed to import data'))
  18 + }
  19 + }).catch(error => {
  20 + reject(error)
  21 + })
  22 + })
  23 +}
0 \ No newline at end of file 24 \ No newline at end of file
src/api/fee/downloadCollectionLetterOrderApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function exportData(params) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/export.exportData',
  7 + method: 'get',
  8 + params
  9 + }).then(response => {
  10 + const res = response.data
  11 + if (res.code === 0) {
  12 + resolve(res)
  13 + } else {
  14 + reject(new Error(res.msg || 'Failed to export data'))
  15 + }
  16 + }).catch(error => {
  17 + reject(error)
  18 + })
  19 + })
  20 +}
  21 +
  22 +export function queryFloors(params) {
  23 + return new Promise((resolve, reject) => {
  24 + request({
  25 + url: '/floor.queryFloors',
  26 + method: 'get',
  27 + params
  28 + }).then(response => {
  29 + const res = response.data
  30 + if (res.code === 0) {
  31 + resolve(res)
  32 + } else {
  33 + reject(new Error(res.msg || 'Failed to query floors'))
  34 + }
  35 + }).catch(error => {
  36 + reject(error)
  37 + })
  38 + })
  39 +}
0 \ No newline at end of file 40 \ No newline at end of file
src/api/fee/editFeeApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function updateFee(data) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/fee.updateFee',
  7 + method: 'post',
  8 + data
  9 + }).then(response => {
  10 + const res = response.data
  11 + if (res.code === 0) {
  12 + resolve(res)
  13 + } else {
  14 + reject(new Error(res.msg || '更新费用失败'))
  15 + }
  16 + }).catch(error => {
  17 + reject(error)
  18 + })
  19 + })
  20 +}
0 \ No newline at end of file 21 \ No newline at end of file
src/api/fee/editFeeRuleApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function updatePayFeeRule(data) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/payFeeRule.updatePayFeeRule',
  7 + method: 'post',
  8 + data
  9 + }).then(response => {
  10 + const res = response.data
  11 + if (res.code === 0) {
  12 + resolve(res)
  13 + } else {
  14 + reject(new Error(res.msg || '更新费用规则失败'))
  15 + }
  16 + }).catch(error => {
  17 + reject(error)
  18 + })
  19 + })
  20 +}
0 \ No newline at end of file 21 \ No newline at end of file
src/api/fee/exportFeeImportExcelApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function exportData(params) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/export.exportData',
  7 + method: 'get',
  8 + params
  9 + }).then(response => {
  10 + const res = response.data
  11 + if (res.code === 0) {
  12 + resolve(res)
  13 + } else {
  14 + reject(new Error(res.msg || 'Failed to export data'))
  15 + }
  16 + }).catch(error => {
  17 + reject(error)
  18 + })
  19 + })
  20 +}
  21 +
  22 +export function listFeeConfigs(params) {
  23 + return new Promise((resolve, reject) => {
  24 + request({
  25 + url: '/feeConfig.listFeeConfigs',
  26 + method: 'get',
  27 + params
  28 + }).then(response => {
  29 + const res = response.data
  30 + if (res.code === 0) {
  31 + resolve(res)
  32 + } else {
  33 + reject(new Error(res.msg || 'Failed to list fee configs'))
  34 + }
  35 + }).catch(error => {
  36 + reject(error)
  37 + })
  38 + })
  39 +}
  40 +
  41 +export function queryFloors(params) {
  42 + return new Promise((resolve, reject) => {
  43 + request({
  44 + url: '/floor.queryFloors',
  45 + method: 'get',
  46 + params
  47 + }).then(response => {
  48 + const res = response.data
  49 + if (res.code === 0) {
  50 + resolve(res)
  51 + } else {
  52 + reject(new Error(res.msg || 'Failed to query floors'))
  53 + }
  54 + }).catch(error => {
  55 + reject(error)
  56 + })
  57 + })
  58 +}
0 \ No newline at end of file 59 \ No newline at end of file
src/api/fee/feeDetailFeeRuleApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function listPayFeeRule(params) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/payFeeRule.listPayFeeRule',
  7 + method: 'get',
  8 + params
  9 + }).then(response => {
  10 + const res = response.data
  11 + if (res.code === 0) {
  12 + resolve(res)
  13 + } else {
  14 + reject(new Error(res.msg || '获取费用规则列表失败'))
  15 + }
  16 + }).catch(error => {
  17 + reject(error)
  18 + })
  19 + })
  20 +}
0 \ No newline at end of file 21 \ No newline at end of file
src/api/fee/feeDetailRuleBillApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function listPayFeeRuleBill(params) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/payFeeRule.listPayFeeRuleBill',
  7 + method: 'get',
  8 + params
  9 + }).then(response => {
  10 + const res = response.data
  11 + if (res.code === 0) {
  12 + resolve(res)
  13 + } else {
  14 + reject(new Error(res.msg || '获取账单列表失败'))
  15 + }
  16 + }).catch(error => {
  17 + reject(error)
  18 + })
  19 + })
  20 +}
0 \ No newline at end of file 21 \ No newline at end of file
src/api/fee/finishFeeRuleApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function updatePayFeeRule(data) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/payFeeRule.updatePayFeeRule',
  7 + method: 'post',
  8 + data
  9 + }).then(response => {
  10 + const res = response.data
  11 + if (res.code === 0) {
  12 + resolve(res)
  13 + } else {
  14 + reject(new Error(res.msg || '结束费用规则失败'))
  15 + }
  16 + }).catch(error => {
  17 + reject(error)
  18 + })
  19 + })
  20 +}
0 \ No newline at end of file 21 \ No newline at end of file
src/api/fee/inputSearchRoomApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function queryRooms(params) {
  4 + return request({
  5 + url: '/room.queryRooms',
  6 + method: 'get',
  7 + params
  8 + })
  9 +}
0 \ No newline at end of file 10 \ No newline at end of file
src/api/fee/inputSearchRoomByOwnerApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function queryRoomsByOwner(params) {
  4 + return request({
  5 + url: '/room.queryRoomsByOwner',
  6 + method: 'get',
  7 + params
  8 + })
  9 +}
0 \ No newline at end of file 10 \ No newline at end of file
src/api/fee/ownerDetailAccountApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function queryCommunityOwnerAccount(params) {
  4 + return request({
  5 + url: '/account.queryCommunityOwnerAccount',
  6 + method: 'get',
  7 + params
  8 + })
  9 +}
0 \ No newline at end of file 10 \ No newline at end of file
src/api/fee/ownerDetailAccountReceiptApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function listAccountReceipt(params) {
  4 + return request({
  5 + url: '/receipt.listAccountReceipt',
  6 + method: 'get',
  7 + params
  8 + })
  9 +}
0 \ No newline at end of file 10 \ No newline at end of file
src/api/fee/prestoreAccountApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function ownerPrestoreAccount(data) {
  4 + return request({
  5 + url: '/account.ownerPrestoreAccount',
  6 + method: 'post',
  7 + data
  8 + })
  9 +}
  10 +
  11 +export function queryOwners(params) {
  12 + return request({
  13 + url: '/owner.queryOwners',
  14 + method: 'get',
  15 + params
  16 + })
  17 +}
  18 +
  19 +export function queryRoomsByOwner(params) {
  20 + return request({
  21 + url: '/room.queryRoomsByOwner',
  22 + method: 'get',
  23 + params
  24 + })
  25 +}
0 \ No newline at end of file 26 \ No newline at end of file
src/api/fee/propertyFeeApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 查询费用明细列表
  4 +export function queryFeeDetail(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/fee.queryFeeDetail',
  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 listFee(params) {
  21 + return new Promise((resolve, reject) => {
  22 + request({
  23 + url: '/fee.listFee',
  24 + method: 'get',
  25 + params
  26 + }).then(response => {
  27 + const res = response.data
  28 + resolve(res)
  29 + }).catch(error => {
  30 + reject(error)
  31 + })
  32 + })
  33 +}
  34 +
  35 +// 查询房间信息
  36 +export function queryRooms(params) {
  37 + return new Promise((resolve, reject) => {
  38 + request({
  39 + url: '/room.queryRooms',
  40 + method: 'get',
  41 + params
  42 + }).then(response => {
  43 + const res = response.data
  44 + resolve(res)
  45 + }).catch(error => {
  46 + reject(error)
  47 + })
  48 + })
  49 +}
  50 +
  51 +// 查询费用配置信息
  52 +export function listFeeConfigs(params) {
  53 + return new Promise((resolve, reject) => {
  54 + request({
  55 + url: '/feeConfig.listFeeConfigs',
  56 + method: 'get',
  57 + params
  58 + }).then(response => {
  59 + const res = response.data
  60 + resolve(res)
  61 + }).catch(error => {
  62 + reject(error)
  63 + })
  64 + })
  65 +}
  66 +
  67 +// 提交退费申请
  68 +export function saveReturnPayFee(data) {
  69 + return new Promise((resolve, reject) => {
  70 + request({
  71 + url: '/returnPayFee.saveReturnPayFee',
  72 + method: 'post',
  73 + data
  74 + }).then(response => {
  75 + const res = response.data
  76 + resolve(res)
  77 + }).catch(error => {
  78 + reject(error)
  79 + })
  80 + })
  81 +}
  82 +
  83 +// 查询费用折扣信息
  84 +export function queryFeeDetailDiscount(params) {
  85 + return new Promise((resolve, reject) => {
  86 + request({
  87 + url: '/feeDiscount/queryFeeDetailDiscount',
  88 + method: 'get',
  89 + params
  90 + }).then(response => {
  91 + const res = response.data
  92 + resolve(res)
  93 + }).catch(error => {
  94 + reject(error)
  95 + })
  96 + })
  97 +}
0 \ No newline at end of file 98 \ No newline at end of file
src/api/fee/roomCreateFeeAddApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function saveRoomCreateFee(data) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/fee.saveRoomCreateFee',
  7 + method: 'post',
  8 + data
  9 + }).then(response => {
  10 + const res = response.data
  11 + if (res.code === 0) {
  12 + resolve(res)
  13 + } else {
  14 + reject(new Error(res.msg || 'Failed to save room create fee'))
  15 + }
  16 + }).catch(error => {
  17 + reject(error)
  18 + })
  19 + })
  20 +}
  21 +
  22 +export function listFeeConfigs(params) {
  23 + return new Promise((resolve, reject) => {
  24 + request({
  25 + url: '/feeConfig.listFeeConfigs',
  26 + method: 'get',
  27 + params
  28 + }).then(response => {
  29 + const res = response.data
  30 + if (res.code === 0) {
  31 + resolve(res)
  32 + } else {
  33 + reject(new Error(res.msg || 'Failed to list fee configs'))
  34 + }
  35 + }).catch(error => {
  36 + reject(error)
  37 + })
  38 + })
  39 +}
0 \ No newline at end of file 40 \ No newline at end of file
src/api/fee/roomCreateFeeApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 查询房间列表
  4 +export function queryRooms(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/room.queryRooms',
  8 + method: 'get',
  9 + params
  10 + })
  11 + .then(response => {
  12 + const res = response.data
  13 + resolve(res)
  14 + })
  15 + .catch(error => {
  16 + reject(error)
  17 + })
  18 + })
  19 +}
  20 +
  21 +// 导出费用导入模板
  22 +export function exportFeeImportExcel(params) {
  23 + return new Promise((resolve, reject) => {
  24 + request({
  25 + url: '/export.exportData',
  26 + method: 'get',
  27 + params
  28 + })
  29 + .then(response => {
  30 + const res = response.data
  31 + if (res.code === 0) {
  32 + resolve(res)
  33 + } else {
  34 + reject(new Error(res.msg || '导出模板失败'))
  35 + }
  36 + })
  37 + .catch(error => {
  38 + reject(error)
  39 + })
  40 + })
  41 +}
  42 +
  43 +// 导入费用数据
  44 +export function importCreateFee(data) {
  45 + return new Promise((resolve, reject) => {
  46 + request({
  47 + url: '/fee.importCreateFee',
  48 + method: 'post',
  49 + data
  50 + })
  51 + .then(response => {
  52 + const res = response.data
  53 + if (res.code === 0) {
  54 + resolve(res)
  55 + } else {
  56 + reject(new Error(res.msg || '导入费用失败'))
  57 + }
  58 + })
  59 + .catch(error => {
  60 + reject(error)
  61 + })
  62 + })
  63 +}
  64 +
  65 +// 批量创建费用
  66 +export function batchCreateFee(data) {
  67 + return new Promise((resolve, reject) => {
  68 + request({
  69 + url: '/fee.batchCreateFee',
  70 + method: 'post',
  71 + data
  72 + })
  73 + .then(response => {
  74 + const res = response.data
  75 + if (res.code === 0) {
  76 + resolve(res)
  77 + } else {
  78 + reject(new Error(res.msg || '批量创建费用失败'))
  79 + }
  80 + })
  81 + .catch(error => {
  82 + reject(error)
  83 + })
  84 + })
  85 +}
  86 +
  87 +// 下载催缴单
  88 +export function downloadCollectionLetter(params) {
  89 + return new Promise((resolve, reject) => {
  90 + request({
  91 + url: '/fee.downloadCollectionLetter',
  92 + method: 'get',
  93 + params
  94 + })
  95 + .then(response => {
  96 + const res = response.data
  97 + if (res.code === 0) {
  98 + resolve(res)
  99 + } else {
  100 + reject(new Error(res.msg || '下载催缴单失败'))
  101 + }
  102 + })
  103 + .catch(error => {
  104 + reject(error)
  105 + })
  106 + })
  107 +}
0 \ No newline at end of file 108 \ No newline at end of file
src/api/fee/simplifyCallableApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function listOweFeeCallable(params) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/oweFeeCallable.listOweFeeCallable',
  7 + method: 'get',
  8 + params
  9 + }).then(response => {
  10 + const res = response.data
  11 + if (res.code == 0) {
  12 + resolve(res)
  13 + } else {
  14 + reject(new Error(res.msg || 'Failed to list owe fee callable'))
  15 + }
  16 + }).catch(error => {
  17 + reject(error)
  18 + })
  19 + })
  20 +}
0 \ No newline at end of file 21 \ No newline at end of file
src/api/fee/simplifyFeeReceiptApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function queryFeeReceipt(params) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/feeReceipt/queryFeeReceipt',
  7 + method: 'get',
  8 + params
  9 + }).then(response => {
  10 + const res = response.data
  11 + if (res.code == 0) {
  12 + resolve(res)
  13 + } else {
  14 + reject(new Error(res.msg || 'Failed to query fee receipt'))
  15 + }
  16 + }).catch(error => {
  17 + reject(error)
  18 + })
  19 + })
  20 +}
  21 +
  22 +export function listFeePrintPage(params) {
  23 + return new Promise((resolve, reject) => {
  24 + request({
  25 + url: '/feePrintPage.listFeePrintPage',
  26 + method: 'get',
  27 + params
  28 + }).then(response => {
  29 + const res = response.data
  30 + if (res.code == 0) {
  31 + resolve(res)
  32 + } else {
  33 + reject(new Error(res.msg || 'Failed to list fee print pages'))
  34 + }
  35 + }).catch(error => {
  36 + reject(error)
  37 + })
  38 + })
  39 +}
  40 +
  41 +export function queryOwnerCars(params) {
  42 + return new Promise((resolve, reject) => {
  43 + request({
  44 + url: '/owner.queryOwnerCars',
  45 + method: 'get',
  46 + params
  47 + }).then(response => {
  48 + const res = response.data
  49 + if (res.code == 0) {
  50 + resolve(res)
  51 + } else {
  52 + reject(new Error(res.msg || 'Failed to query owner cars'))
  53 + }
  54 + }).catch(error => {
  55 + reject(error)
  56 + })
  57 + })
  58 +}
  59 +
  60 +export function queryContract(params) {
  61 + return new Promise((resolve, reject) => {
  62 + request({
  63 + url: '/contract/queryContract',
  64 + method: 'get',
  65 + params
  66 + }).then(response => {
  67 + const res = response.data
  68 + if (res.code == 0) {
  69 + resolve(res)
  70 + } else {
  71 + reject(new Error(res.msg || 'Failed to query contract'))
  72 + }
  73 + }).catch(error => {
  74 + reject(error)
  75 + })
  76 + })
  77 +}
0 \ No newline at end of file 78 \ No newline at end of file
src/api/fee/simplifyHisFeeApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function queryFeeDetail(params) {
  4 + return request({
  5 + url: '/fee.queryFeeDetail',
  6 + method: 'get',
  7 + params
  8 + })
  9 +}
  10 +
  11 +export function generatorReceipt(data) {
  12 + return request({
  13 + url: '/receipt.generatorReceipt',
  14 + method: 'post',
  15 + data
  16 + })
  17 +}
0 \ No newline at end of file 18 \ No newline at end of file
src/api/fee/simplifyMeterWaterLogApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function listMeterWaters(params) {
  4 + return request({
  5 + url: '/meterWater.listMeterWaters',
  6 + method: 'get',
  7 + params
  8 + })
  9 +}
  10 +
  11 +export function listMeterTypes(params) {
  12 + return request({
  13 + url: '/meterType.listMeterType',
  14 + method: 'get',
  15 + params
  16 + })
  17 +}
0 \ No newline at end of file 18 \ No newline at end of file
src/api/fee/simplifyOwnerRoomsApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function queryRoomsByOwner(params) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/room.queryRoomsByOwner',
  7 + method: 'get',
  8 + params
  9 + }).then(response => {
  10 + const res = response.data
  11 +
  12 + resolve(res)
  13 +
  14 + }).catch(error => {
  15 + reject(error)
  16 + })
  17 + })
  18 +}
0 \ No newline at end of file 19 \ No newline at end of file
src/api/fee/simplifyRefundDepositApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function queryFeeDeposit(params) {
  4 + return request({
  5 + url: '/fee.queryFeeDeposit',
  6 + method: 'get',
  7 + params
  8 + })
  9 +}
0 \ No newline at end of file 10 \ No newline at end of file
src/api/fee/simplifyRoomFeeApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function listFee(params) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/fee.listFee',
  7 + method: 'get',
  8 + params
  9 + }).then(response => {
  10 + const res = response.data
  11 + resolve(res)
  12 +
  13 + }).catch(error => {
  14 + reject(error)
  15 + })
  16 + })
  17 +}
  18 +
  19 +export function listFeeConfigs(params) {
  20 + return new Promise((resolve, reject) => {
  21 + request({
  22 + url: '/feeConfig.listFeeConfigs',
  23 + method: 'get',
  24 + params
  25 + }).then(response => {
  26 + const res = response.data
  27 + resolve(res)
  28 +
  29 + }).catch(error => {
  30 + reject(error)
  31 + })
  32 + })
  33 +}
  34 +
  35 +export function listMonthFee(params) {
  36 + return new Promise((resolve, reject) => {
  37 + request({
  38 + url: '/fee.listMonthFee',
  39 + method: 'get',
  40 + params
  41 + }).then(response => {
  42 + const res = response.data
  43 +
  44 + resolve(res)
  45 +
  46 + }).catch(error => {
  47 + reject(error)
  48 + })
  49 + })
  50 +}
0 \ No newline at end of file 51 \ No newline at end of file
src/api/fee/tempImportRoomFeeApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function importTempData(data) {
  4 + return request({
  5 + url: '/importRoomFee/importTempData',
  6 + method: 'post',
  7 + data
  8 + })
  9 +}
0 \ No newline at end of file 10 \ No newline at end of file
src/api/fee/writeOweFeeCallableApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +export function writeOweFeeCallable(data) {
  4 + return new Promise((resolve, reject) => {
  5 + request({
  6 + url: '/oweFeeCallable.writeOweFeeCallable',
  7 + method: 'post',
  8 + data
  9 + }).then(response => {
  10 + const res = response.data
  11 + if (res.code == 0) {
  12 + resolve(res)
  13 + } else {
  14 + reject(new Error(res.msg || 'Failed to write owe fee callable'))
  15 + }
  16 + }).catch(error => {
  17 + reject(error)
  18 + })
  19 + })
  20 +}
  21 +
  22 +export function listFee(params) {
  23 + return new Promise((resolve, reject) => {
  24 + request({
  25 + url: '/fee.listFee',
  26 + method: 'get',
  27 + params
  28 + }).then(response => {
  29 + const res = response.data
  30 + if (res.code == 0) {
  31 + resolve(res)
  32 + } else {
  33 + reject(new Error(res.msg || 'Failed to list fees'))
  34 + }
  35 + }).catch(error => {
  36 + reject(error)
  37 + })
  38 + })
  39 +}
0 \ No newline at end of file 40 \ No newline at end of file
src/components/contract/searchOwner.vue
1 <template> 1 <template>
2 - <el-dialog  
3 - :title="$t('contract.selectOwner')"  
4 - :visible.sync="visible"  
5 - width="80%"  
6 - :before-close="handleClose">  
7 - 2 + <el-dialog :title="$t('contract.selectOwner')" :visible.sync="visible" width="80%" :before-close="handleClose">
  3 +
8 <div class="search-wrapper"> 4 <div class="search-wrapper">
9 <el-row :gutter="20"> 5 <el-row :gutter="20">
10 <el-col :span="8"> 6 <el-col :span="8">
11 - <el-input  
12 - v-model="searchOwnerInfo.roomName"  
13 - :placeholder="$t('contract.inputRoomFullNum')"> 7 + <el-input v-model="searchOwnerInfo.roomName" :placeholder="$t('contract.inputRoomFullNum')">
14 </el-input> 8 </el-input>
15 </el-col> 9 </el-col>
16 <el-col :span="8"> 10 <el-col :span="8">
17 - <el-input  
18 - v-model="searchOwnerInfo._currentOwnerName"  
19 - :placeholder="$t('contract.inputOwnerName')"> 11 + <el-input v-model="searchOwnerInfo._currentOwnerName" :placeholder="$t('contract.inputOwnerName')">
20 </el-input> 12 </el-input>
21 </el-col> 13 </el-col>
22 <el-col :span="8"> 14 <el-col :span="8">
@@ -27,65 +19,32 @@ @@ -27,65 +19,32 @@
27 </el-col> 19 </el-col>
28 </el-row> 20 </el-row>
29 </div> 21 </div>
30 -  
31 - <el-table  
32 - :data="searchOwnerInfo.owners"  
33 - border  
34 - style="width: 100%"  
35 - height="400">  
36 - <el-table-column  
37 - prop="memberId"  
38 - :label="$t('contract.ownerId')"  
39 - align="center"> 22 +
  23 + <el-table :data="searchOwnerInfo.owners" border style="width: 100%" height="400">
  24 + <el-table-column prop="memberId" :label="$t('contract.ownerId')" align="center">
40 </el-table-column> 25 </el-table-column>
41 - <el-table-column  
42 - prop="name"  
43 - :label="$t('contract.name')"  
44 - align="center"> 26 + <el-table-column prop="name" :label="$t('contract.name')" align="center">
45 </el-table-column> 27 </el-table-column>
46 - <el-table-column  
47 - prop="personTypeName"  
48 - :label="$t('contract.personType')"  
49 - align="center"> 28 + <el-table-column prop="personTypeName" :label="$t('contract.personType')" align="center">
50 </el-table-column> 29 </el-table-column>
51 - <el-table-column  
52 - prop="personRoleName"  
53 - :label="$t('contract.personRole')"  
54 - align="center"> 30 + <el-table-column prop="personRoleName" :label="$t('contract.personRole')" align="center">
55 </el-table-column> 31 </el-table-column>
56 - <el-table-column  
57 - prop="idCard"  
58 - :label="$t('contract.idCard')"  
59 - align="center"> 32 + <el-table-column prop="idCard" :label="$t('contract.idCard')" align="center">
60 </el-table-column> 33 </el-table-column>
61 - <el-table-column  
62 - prop="link"  
63 - :label="$t('contract.contact')"  
64 - align="center"> 34 + <el-table-column prop="link" :label="$t('contract.contact')" align="center">
65 </el-table-column> 35 </el-table-column>
66 - <el-table-column  
67 - :label="$t('common.operation')"  
68 - align="center"  
69 - width="120"> 36 + <el-table-column :label="$t('common.operation')" align="center" width="120">
70 <template slot-scope="scope"> 37 <template slot-scope="scope">
71 - <el-button  
72 - type="primary"  
73 - size="mini"  
74 - @click="chooseOwner(scope.row)"> 38 + <el-button type="primary" size="mini" @click="chooseOwner(scope.row)">
75 {{ $t('contract.select') }} 39 {{ $t('contract.select') }}
76 </el-button> 40 </el-button>
77 </template> 41 </template>
78 </el-table-column> 42 </el-table-column>
79 </el-table> 43 </el-table>
80 - 44 +
81 <div class="pagination-wrapper"> 45 <div class="pagination-wrapper">
82 - <el-pagination  
83 - @size-change="handleSizeChange"  
84 - @current-change="handleCurrentChange"  
85 - :current-page="page.current"  
86 - :page-sizes="[10, 20, 30, 50]"  
87 - :page-size="page.size"  
88 - layout="total, sizes, prev, pager, next, jumper" 46 + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page.current"
  47 + :page-sizes="[10, 20, 30, 50]" :page-size="page.size" layout="total, sizes, prev, pager, next, jumper"
89 :total="page.total"> 48 :total="page.total">
90 </el-pagination> 49 </el-pagination>
91 </div> 50 </div>
@@ -94,6 +53,7 @@ @@ -94,6 +53,7 @@
94 53
95 <script> 54 <script>
96 import { queryOwners } from '@/api/contract/addContractApi' 55 import { queryOwners } from '@/api/contract/addContractApi'
  56 +import { getCommunityId } from '@/api/community/communityApi'
97 57
98 export default { 58 export default {
99 name: 'SearchOwner', 59 name: 'SearchOwner',
@@ -133,12 +93,12 @@ export default { @@ -133,12 +93,12 @@ export default {
133 const params = { 93 const params = {
134 page: _page, 94 page: _page,
135 row: _row, 95 row: _row,
136 - communityId: this.$store.getters.communityId, 96 + communityId: getCommunityId(),
137 name: this.searchOwnerInfo._currentOwnerName.trim(), 97 name: this.searchOwnerInfo._currentOwnerName.trim(),
138 roomName: this.searchOwnerInfo.roomName.trim(), 98 roomName: this.searchOwnerInfo.roomName.trim(),
139 ownerTypeCd: this.searchOwnerInfo.ownerTypeCd 99 ownerTypeCd: this.searchOwnerInfo.ownerTypeCd
140 } 100 }
141 - 101 +
142 queryOwners(params).then(response => { 102 queryOwners(params).then(response => {
143 this.searchOwnerInfo.owners = response.data 103 this.searchOwnerInfo.owners = response.data
144 this.page.total = response.records 104 this.page.total = response.records
@@ -190,7 +150,7 @@ export default { @@ -190,7 +150,7 @@ export default {
190 text-align: right; 150 text-align: right;
191 } 151 }
192 152
193 -.el-button + .el-button { 153 +.el-button+.el-button {
194 margin-left: 10px; 154 margin-left: 10px;
195 } 155 }
196 </style> 156 </style>
197 \ No newline at end of file 157 \ No newline at end of file
src/components/fee/addApplyRoomDiscount.vue
@@ -66,6 +66,7 @@ @@ -66,6 +66,7 @@
66 <script> 66 <script>
67 import { queryApplyRoomDiscountType ,listRoomsWhereFeeSet} from '@/api/fee/applyRoomDiscountManageApi' 67 import { queryApplyRoomDiscountType ,listRoomsWhereFeeSet} from '@/api/fee/applyRoomDiscountManageApi'
68 import UploadImageUrl from '@/components/upload/UploadImageUrl' 68 import UploadImageUrl from '@/components/upload/UploadImageUrl'
  69 +import { getCommunityId } from '@/api/community/communityApi'
69 70
70 export default { 71 export default {
71 name: 'AddApplyRoomDiscount', 72 name: 'AddApplyRoomDiscount',
@@ -231,7 +232,7 @@ export default { @@ -231,7 +232,7 @@ export default {
231 }, 232 },
232 async saveApplyRoomDiscount() { 233 async saveApplyRoomDiscount() {
233 try { 234 try {
234 - this.form.communityId = this.$store.getters.communityId 235 + this.form.communityId = getCommunityId()
235 await this.$api.applyRoomDiscount.saveApplyRoomDiscount(this.form) 236 await this.$api.applyRoomDiscount.saveApplyRoomDiscount(this.form)
236 this.$message.success(this.$t('applyRoomDiscount.message.saveSuccess')) 237 this.$message.success(this.$t('applyRoomDiscount.message.saveSuccess'))
237 this.visible = false 238 this.visible = false
src/components/fee/addProxyFee.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('addProxyFee.title')" :visible.sync="visible" width="70%" :before-close="handleClose">
  3 + <el-form ref="form" :model="formData" label-width="120px">
  4 + <el-form-item :label="$t('addProxyFee.feeType')" prop="feeTypeCd">
  5 + <el-select v-model="formData.feeTypeCd" @change="handleFeeTypeChange"
  6 + :placeholder="$t('addProxyFee.feeTypePlaceholder')" style="width: 100%">
  7 + <el-option v-for="item in feeTypeOptions" :key="item.value" :label="item.label"
  8 + :value="item.value"></el-option>
  9 + </el-select>
  10 + </el-form-item>
  11 +
  12 + <el-form-item :label="$t('addProxyFee.feeItem')" prop="configId">
  13 + <el-select v-model="formData.configId" @change="handleConfigChange"
  14 + :placeholder="$t('addProxyFee.feeItemPlaceholder')" style="width: 100%">
  15 + <el-option v-for="item in feeConfigOptions" :key="item.configId" :label="item.feeName"
  16 + :value="item.configId"></el-option>
  17 + </el-select>
  18 + <span class="tip">{{ $t('addProxyFee.feeItemTip') }}</span>
  19 + </el-form-item>
  20 +
  21 + <el-form-item :label="$t('addProxyFee.chargeObject')">
  22 + <el-input v-model="formData.ownerName" disabled
  23 + :placeholder="$t('addProxyFee.chargeObjectPlaceholder')"></el-input>
  24 + </el-form-item>
  25 +
  26 + <template v-if="formData.feeTypeCd !== '888800010014'">
  27 + <el-form-item :label="$t('addProxyFee.consumption')" prop="consumption">
  28 + <el-input v-model="formData.consumption" @blur="handleConsumptionBlur"
  29 + :placeholder="$t('addProxyFee.consumptionPlaceholder')"></el-input>
  30 + </el-form-item>
  31 +
  32 + <el-form-item :label="$t('addProxyFee.amount')" prop="amount">
  33 + <el-input v-model="formData.amount" @blur="handleAmountBlur"
  34 + :placeholder="$t('addProxyFee.amountPlaceholder')"></el-input>
  35 + </el-form-item>
  36 + </template>
  37 +
  38 + <template v-else>
  39 + <el-form-item :label="$t('addProxyFee.quantity')" prop="consumption">
  40 + <el-input v-model="formData.consumption" @blur="handleConsumptionBlur"
  41 + :placeholder="$t('addProxyFee.consumptionPlaceholder')"></el-input>
  42 + </el-form-item>
  43 +
  44 + <el-form-item :label="$t('addProxyFee.amount')">
  45 + <el-input v-model="formData.amount" disabled :placeholder="$t('addProxyFee.amountPlaceholder')"></el-input>
  46 + </el-form-item>
  47 + </template>
  48 +
  49 + <el-form-item :label="$t('addProxyFee.startTime')" prop="startTime">
  50 + <el-date-picker v-model="formData.startTime" type="date" :placeholder="$t('addProxyFee.startTimePlaceholder')"
  51 + value-format="yyyy-MM-dd" @change="validateStartTime"></el-date-picker>
  52 + </el-form-item>
  53 +
  54 + <el-form-item :label="$t('addProxyFee.endTime')" prop="endTime">
  55 + <el-date-picker v-model="formData.endTime" type="date" :placeholder="$t('addProxyFee.endTimePlaceholder')"
  56 + value-format="yyyy-MM-dd" @change="validateEndTime"></el-date-picker>
  57 + </el-form-item>
  58 + </el-form>
  59 +
  60 + <span slot="footer" class="dialog-footer">
  61 + <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
  62 + <el-button type="primary" @click="handleSubmit">{{ $t('common.save') }}</el-button>
  63 + </span>
  64 + </el-dialog>
  65 +</template>
  66 +
  67 +<script>
  68 +import { saveProxyFee, listFeeConfigs } from '@/api/fee/addProxyFeeApi'
  69 +import { getCommunityId } from '@/api/community/communityApi'
  70 +import { dateFormat } from '@/utils/dateUtil'
  71 +
  72 +export default {
  73 + name: 'AddProxyFee',
  74 + props: {
  75 + callBackListener: String,
  76 + callBackFunction: String
  77 + },
  78 + data() {
  79 + return {
  80 + visible: false,
  81 + formData: {
  82 + remark: '',
  83 + roomId: '',
  84 + objId: '',
  85 + objName: '',
  86 + feeTypeCd: '',
  87 + feeConfigs: [],
  88 + amount: '',
  89 + consumption: '',
  90 + configId: '',
  91 + ownerName: '',
  92 + objType: '3333',
  93 + startTime: dateFormat(new Date()),
  94 + endTime: dateFormat(new Date())
  95 + },
  96 + feeTypeOptions: [
  97 + { value: '888800010015', label: this.$t('addProxyFee.waterFee') },
  98 + { value: '888800010016', label: this.$t('addProxyFee.electricityFee') },
  99 + { value: '888800010014', label: this.$t('addProxyFee.otherFee') }
  100 + ],
  101 + feeConfigOptions: [],
  102 + rules: {
  103 + amount: [
  104 + { required: true, message: this.$t('addProxyFee.validate.amountRequired'), trigger: 'blur' },
  105 + { pattern: /^\d+(\.\d{1,2})?$/, message: this.$t('addProxyFee.validate.amountFormat'), trigger: 'blur' }
  106 + ],
  107 + consumption: [
  108 + { required: true, message: this.$t('addProxyFee.validate.consumptionRequired'), trigger: 'blur' },
  109 + { pattern: /^\d+(\.\d{1,2})?$/, message: this.$t('addProxyFee.validate.consumptionFormat'), trigger: 'blur' }
  110 + ],
  111 + objId: [
  112 + { required: true, message: this.$t('addProxyFee.validate.roomRequired'), trigger: 'blur' }
  113 + ],
  114 + configId: [
  115 + { required: true, message: this.$t('addProxyFee.validate.feeRequired'), trigger: 'change' }
  116 + ],
  117 + startTime: [
  118 + { required: true, message: this.$t('addProxyFee.validate.startTimeRequired'), trigger: 'blur' }
  119 + ],
  120 + endTime: [
  121 + { required: true, message: this.$t('addProxyFee.validate.endTimeRequired'), trigger: 'blur' }
  122 + ]
  123 + }
  124 + }
  125 + },
  126 + methods: {
  127 + open(params) {
  128 + this.resetForm()
  129 + if (params.objType) {
  130 + this.formData.objType = params.objType
  131 + }
  132 + this.formData.roomId = params.roomId
  133 + this.formData.objId = params.roomId
  134 + this.formData.objName = params.roomName
  135 + this.formData.ownerName = `${params.roomName}(${params.ownerName})`
  136 + this.visible = true
  137 + },
  138 +
  139 + handleFeeTypeChange(value) {
  140 + this.formData.amount = ''
  141 + this.formData.consumption = ''
  142 + this.formData.configId = ''
  143 + this.loadFeeConfigs(value)
  144 + },
  145 +
  146 + loadFeeConfigs(feeTypeCd) {
  147 + listFeeConfigs({
  148 + page: 1,
  149 + row: 20,
  150 + communityId: getCommunityId(),
  151 + feeTypeCd,
  152 + isDefault: 'F',
  153 + computingFormula: '6006',
  154 + valid: '1'
  155 + }).then(response => {
  156 + this.feeConfigOptions = response.data.feeConfigs
  157 + })
  158 + },
  159 +
  160 + handleConfigChange() {
  161 + this.formData.amount = ''
  162 + this.formData.consumption = ''
  163 + },
  164 +
  165 + getCurrentConfig() {
  166 + return this.feeConfigOptions.find(
  167 + item => this.formData.configId === item.configId && item.computingFormula === '6006'
  168 + )
  169 + },
  170 +
  171 + handleAmountBlur() {
  172 + const config = this.getCurrentConfig()
  173 + const amount = parseFloat(this.formData.amount)
  174 +
  175 + if (!config) {
  176 + this.$message.error(this.$t('addProxyFee.validate.invalidConfig'))
  177 + this.formData.amount = ''
  178 + this.formData.consumption = ''
  179 + return
  180 + }
  181 +
  182 + if (amount < config.additionalAmount) {
  183 + this.$message.error(this.$t('addProxyFee.validate.amountTooSmall'))
  184 + this.formData.amount = ''
  185 + this.formData.consumption = ''
  186 + return
  187 + }
  188 +
  189 + const consumption = (amount - config.additionalAmount) / config.squarePrice
  190 + this.formData.consumption = consumption.toFixed(2)
  191 + },
  192 +
  193 + handleConsumptionBlur() {
  194 + const config = this.getCurrentConfig()
  195 + const consumption = parseFloat(this.formData.consumption)
  196 +
  197 + if (!config) {
  198 + this.$message.error(this.$t('addProxyFee.validate.invalidConfig'))
  199 + this.formData.amount = ''
  200 + this.formData.consumption = ''
  201 + return
  202 + }
  203 +
  204 + const amount = config.squarePrice * consumption + parseFloat(config.additionalAmount)
  205 + this.formData.amount = amount.toFixed(2)
  206 + },
  207 +
  208 + validateStartTime(value) {
  209 + const start = new Date(value)
  210 + const end = new Date(this.formData.endTime)
  211 + if (start >= end) {
  212 + this.$message.error(this.$t('addProxyFee.validate.startBeforeEnd'))
  213 + this.formData.startTime = ''
  214 + }
  215 + },
  216 +
  217 + validateEndTime(value) {
  218 + const start = new Date(this.formData.startTime)
  219 + const end = new Date(value)
  220 + if (start >= end) {
  221 + this.$message.error(this.$t('addProxyFee.validate.endAfterStart'))
  222 + this.formData.endTime = ''
  223 + }
  224 + },
  225 +
  226 + handleSubmit() {
  227 + this.$refs.form.validate(valid => {
  228 + if (!valid) return
  229 +
  230 + const params = {
  231 + ...this.formData,
  232 + communityId: getCommunityId()
  233 + }
  234 +
  235 +
  236 +
  237 + saveProxyFee(params).then(() => {
  238 + this.$message.success(this.$t('addProxyFee.successMessage'))
  239 + this.$emit('success')
  240 + this.handleClose()
  241 + }).catch(error => {
  242 + this.$message.error(error.message)
  243 + })
  244 + })
  245 + },
  246 +
  247 + resetForm() {
  248 + if (this.$refs.form) {
  249 + this.$refs.form.resetFields()
  250 + }
  251 + this.formData = {
  252 + remark: '',
  253 + roomId: '',
  254 + objId: '',
  255 + objName: '',
  256 + feeTypeCd: '',
  257 + feeConfigs: [],
  258 + amount: '',
  259 + consumption: '',
  260 + configId: '',
  261 + ownerName: '',
  262 + objType: '3333',
  263 + startTime: dateFormat(new Date()),
  264 + endTime: dateFormat(new Date())
  265 + }
  266 + },
  267 +
  268 + handleClose() {
  269 + this.visible = false
  270 + this.resetForm()
  271 + }
  272 + }
  273 +}
  274 +</script>
  275 +
  276 +<style scoped>
  277 +.tip {
  278 + font-size: 12px;
  279 + color: #909399;
  280 +}
  281 +</style>
0 \ No newline at end of file 282 \ No newline at end of file
src/components/fee/addProxyFeeDemo.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-button @click="openModal">{{ $t('addProxyFeeDemo.openModal') }}</el-button>
  4 + <add-proxy-fee ref="addProxyFee" @success="handleSuccess"></add-proxy-fee>
  5 + </div>
  6 +</template>
  7 +
  8 +<script>
  9 +import AddProxyFee from './addProxyFee'
  10 +
  11 +export default {
  12 + name: 'AddProxyFeeDemo',
  13 + components: {
  14 + AddProxyFee
  15 + },
  16 + methods: {
  17 + openModal() {
  18 + this.$refs.addProxyFee.open({
  19 + roomId: '123',
  20 + roomName: '1-2-101',
  21 + ownerName: 'Test Owner'
  22 + })
  23 + },
  24 + handleSuccess() {
  25 + this.$message.success(this.$t('addProxyFeeDemo.successMessage'))
  26 + }
  27 + }
  28 +}
  29 +</script>
0 \ No newline at end of file 30 \ No newline at end of file
src/components/fee/batchFeeCycle.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="batchFeeCycleInfo.fee.feeName"
  4 + :visible.sync="visible"
  5 + width="500px"
  6 + :before-close="handleClose"
  7 + >
  8 + <el-form label-width="120px">
  9 + <el-form-item :label="$t('batchFeeCycle.paymentCycle')">
  10 + <el-select
  11 + v-model="batchFeeCycleInfo.tempCycle"
  12 + @change="changeTempCycle"
  13 + style="width:100%"
  14 + :placeholder="$t('batchFeeCycle.selectCycleTip')"
  15 + >
  16 + <el-option
  17 + value="-100"
  18 + :label="$t('batchFeeCycle.default')"
  19 + ></el-option>
  20 + <el-option
  21 + value="-102"
  22 + :label="$t('batchFeeCycle.customCycle')"
  23 + ></el-option>
  24 + <el-option
  25 + value="-101"
  26 + :label="$t('batchFeeCycle.customAmount')"
  27 + ></el-option>
  28 + <el-option
  29 + value="-103"
  30 + :label="$t('batchFeeCycle.customEndTime')"
  31 + ></el-option>
  32 + </el-select>
  33 + </el-form-item>
  34 +
  35 + <el-form-item
  36 + v-if="batchFeeCycleInfo.tempCycle === '-101'"
  37 + :label="$t('batchFeeCycle.customAmount')"
  38 + >
  39 + <el-input
  40 + type="number"
  41 + v-model="batchFeeCycleInfo.receivedAmount"
  42 + :placeholder="$t('batchFeeCycle.enterCustomAmount')"
  43 + ></el-input>
  44 + </el-form-item>
  45 +
  46 + <el-form-item
  47 + v-if="batchFeeCycleInfo.tempCycle === '-102'"
  48 + :label="$t('batchFeeCycle.actualCycle')"
  49 + >
  50 + <el-input
  51 + type="number"
  52 + v-model="batchFeeCycleInfo.cycles"
  53 + :placeholder="$t('batchFeeCycle.enterActualCycle')"
  54 + ></el-input>
  55 + </el-form-item>
  56 +
  57 + <el-form-item
  58 + v-if="batchFeeCycleInfo.tempCycle === '-103'"
  59 + :label="$t('batchFeeCycle.endTime')"
  60 + >
  61 + <el-date-picker
  62 + v-model="batchFeeCycleInfo.custEndTime"
  63 + type="date"
  64 + style="width:100%"
  65 + :placeholder="$t('batchFeeCycle.selectEndTime')"
  66 + value-format="yyyy-MM-dd"
  67 + ></el-date-picker>
  68 + </el-form-item>
  69 + </el-form>
  70 +
  71 + <span slot="footer" class="dialog-footer">
  72 + <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
  73 + <el-button type="primary" @click="_doSubmitFeeCycle">{{ $t('common.confirm') }}</el-button>
  74 + </span>
  75 + </el-dialog>
  76 +</template>
  77 +
  78 +<script>
  79 +export default {
  80 + name: 'BatchFeeCycle',
  81 + data() {
  82 + return {
  83 + visible: false,
  84 + batchFeeCycleInfo: {
  85 + cycles: '',
  86 + tempCycle: '',
  87 + custEndTime: '',
  88 + receivedAmount: '',
  89 + fee: {}
  90 + }
  91 + }
  92 + },
  93 + methods: {
  94 + open(fee) {
  95 + this.batchFeeCycleInfo = {
  96 + cycles: fee.cycles,
  97 + tempCycle: fee.tempCycle,
  98 + receivedAmount: fee.receivedAmount,
  99 + fee: { ...fee }
  100 + }
  101 + this.visible = true
  102 + },
  103 +
  104 + handleClose() {
  105 + this.visible = false
  106 + },
  107 +
  108 + changeTempCycle() {
  109 + const tempCycle = this.batchFeeCycleInfo.tempCycle + ""
  110 + if (tempCycle !== '-100') {
  111 + this.batchFeeCycleInfo.cycles = "1"
  112 + }
  113 + },
  114 +
  115 + _doSubmitFeeCycle() {
  116 + const updatedFee = {
  117 + ...this.batchFeeCycleInfo.fee,
  118 + tempCycle: this.batchFeeCycleInfo.tempCycle,
  119 + cycles: this.batchFeeCycleInfo.cycles,
  120 + custEndTime: this.batchFeeCycleInfo.custEndTime,
  121 + receivedAmount: this.batchFeeCycleInfo.receivedAmount
  122 + }
  123 +
  124 + this.$emit('changeMonth', updatedFee)
  125 + this.handleClose()
  126 + }
  127 + }
  128 +}
  129 +</script>
  130 +
  131 +<style lang="scss" scoped>
  132 +::v-deep .el-dialog__body {
  133 + padding: 20px;
  134 +}
  135 +</style>
0 \ No newline at end of file 136 \ No newline at end of file
src/components/fee/batchPayConfirm.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-dialog :title="$t('batchPayConfirm.title')" :visible.sync="visible" width="600px" :before-close="handleClose">
  4 + <el-form label-width="120px">
  5 + <el-form-item :label="$t('batchPayConfirm.amount')">
  6 + <span>{{ batchPayConfirmInfo.feePrices }} {{ $t('batchPayConfirm.yuan') }}</span>
  7 + </el-form-item>
  8 + <el-form-item :label="$t('batchPayConfirm.accountAmount')">
  9 + <span>{{ batchPayConfirmInfo.accountAmount }} {{ $t('batchPayConfirm.yuan') }}</span>
  10 + </el-form-item>
  11 + <el-form-item :label="$t('batchPayConfirm.paymentMethod')">
  12 + <el-select v-model="batchPayConfirmInfo.primeRate" style="width:100%"
  13 + :placeholder="$t('batchPayConfirm.selectPaymentMethod')">
  14 + <el-option v-for="item in filteredPrimeRates" :key="item.statusCd" :label="item.name"
  15 + :value="item.statusCd"></el-option>
  16 + </el-select>
  17 + </el-form-item>
  18 + <el-form-item v-if="batchPayConfirmInfo.payType === 'qrCode'">
  19 + <el-input v-model="batchPayConfirmInfo.authCode" :placeholder="$t('batchPayConfirm.scanCodeTip')"
  20 + @keyup.enter.native="_qrCodePayFee"></el-input>
  21 + </el-form-item>
  22 + </el-form>
  23 + <span slot="footer" class="dialog-footer">
  24 + <el-button @click="handleClose">{{ $t('common.close') }}</el-button>
  25 + <el-button type="primary" @click="_doPayFee" v-if="batchPayConfirmInfo.payType === 'common'">{{
  26 + $t('batchPayConfirm.confirmPay') }}</el-button>
  27 + </span>
  28 + </el-dialog>
  29 +
  30 + <el-dialog :title="$t('batchPayConfirm.payResult')" :visible.sync="resultVisible" width="500px">
  31 + <div class="result-content">
  32 + <p>{{ $t('batchPayConfirm.paySuccess') }}</p>
  33 + </div>
  34 + <span slot="footer" class="dialog-footer">
  35 + <el-button @click="_back">{{ $t('common.back') }}</el-button>
  36 + <el-button type="primary" @click="_printAndBack('ON')">{{ $t('batchPayConfirm.mergePrint') }}</el-button>
  37 + <el-button type="primary" @click="_printAndBack('OFF')">{{ $t('batchPayConfirm.printReceipt') }}</el-button>
  38 + </span>
  39 + </el-dialog>
  40 + </div>
  41 +</template>
  42 +
  43 +<script>
  44 +import { getCommunityId, getDict } from '@/api/community/communityApi'
  45 +import { payBatchFee, qrCodePayment, checkPayFinish, listFeePrintPage } from '@/api/fee/batchPayFeeOrderApi'
  46 +
  47 +export default {
  48 + name: 'BatchPayConfirm',
  49 + data() {
  50 + return {
  51 + visible: false,
  52 + resultVisible: false,
  53 + batchPayConfirmInfo: {
  54 + payType: '',
  55 + fees: [],
  56 + primeRate: '',
  57 + primeRates: [],
  58 + payerObjName: '',
  59 + orderId: '',
  60 + paymentPoolId: '',
  61 + authCode: '',
  62 + feePrices: '',
  63 + detailIds: '',
  64 + printUrl: '/print.html#/pages/property/printPayFee',
  65 + accountAmount: '',
  66 + acctId: ''
  67 + }
  68 + }
  69 + },
  70 + computed: {
  71 + filteredPrimeRates() {
  72 + if (this.batchPayConfirmInfo.payType === 'qrCode') {
  73 + return this.batchPayConfirmInfo.primeRates.filter(
  74 + item => item.statusCd === '3' || item.statusCd === '4'
  75 + )
  76 + } else {
  77 + return this.batchPayConfirmInfo.primeRates.filter(
  78 + item => item.statusCd !== '5' && item.statusCd !== '6' && item.statusCd !== '8'
  79 + )
  80 + }
  81 + }
  82 + },
  83 + created() {
  84 + this._initDictData()
  85 + this._listFeePrintPages()
  86 + },
  87 + methods: {
  88 + async _initDictData() {
  89 + try {
  90 + const data = await getDict('pay_fee_detail', 'prime_rate')
  91 + this.batchPayConfirmInfo.primeRates = data
  92 + } catch (error) {
  93 + console.error('获取字典数据失败:', error)
  94 + }
  95 + },
  96 +
  97 + async _listFeePrintPages() {
  98 + try {
  99 + const params = {
  100 + page: 1,
  101 + row: 1,
  102 + state: 'T',
  103 + communityId: getCommunityId()
  104 + }
  105 + const res = await listFeePrintPage(params)
  106 + if (res.code === 0 && res.data && res.data.length > 0) {
  107 + this.batchPayConfirmInfo.printUrl = res.data[0].url
  108 + }
  109 + } catch (error) {
  110 + console.error('请求失败:', error)
  111 + }
  112 + },
  113 +
  114 + open(params) {
  115 + this.batchPayConfirmInfo = {
  116 + ...this.batchPayConfirmInfo,
  117 + ...params
  118 + }
  119 + this.visible = true
  120 +
  121 + if (params.payType === 'qrCode') {
  122 + this.$nextTick(() => {
  123 + document.getElementById("authCode").focus()
  124 + })
  125 + }
  126 + },
  127 +
  128 + handleClose() {
  129 + this.visible = false
  130 + },
  131 +
  132 + async _doPayFee() {
  133 + if (!this.batchPayConfirmInfo.primeRate) {
  134 + this.$message.warning(this.$t('batchPayConfirm.selectPaymentMethodTip'))
  135 + return
  136 + }
  137 +
  138 + const fees = this.batchPayConfirmInfo.fees.map(fee => ({
  139 + ...fee,
  140 + primeRate: this.batchPayConfirmInfo.primeRate
  141 + }))
  142 +
  143 + try {
  144 + const data = {
  145 + communityId: getCommunityId(),
  146 + fees,
  147 + acctId: this.batchPayConfirmInfo.acctId,
  148 + accountAmount: this.batchPayConfirmInfo.accountAmount
  149 + }
  150 +
  151 + const res = await payBatchFee(data)
  152 + if (res.code === 0) {
  153 + this._doDealPayResult(res)
  154 + } else {
  155 + this.$message.error(res.msg)
  156 + }
  157 + } catch (error) {
  158 + console.error('请求失败:', error)
  159 + this.handleClose()
  160 + this.$message.error('缴费失败')
  161 + }
  162 + },
  163 +
  164 + async _qrCodePayFee() {
  165 + if (!this.batchPayConfirmInfo.primeRate) {
  166 + this.$message.warning(this.$t('batchPayConfirm.selectPaymentMethodTip'))
  167 + return
  168 + }
  169 +
  170 + const fees = this.batchPayConfirmInfo.fees.map(fee => ({
  171 + ...fee,
  172 + primeRate: this.batchPayConfirmInfo.primeRate
  173 + }))
  174 +
  175 + try {
  176 + const data = {
  177 + communityId: getCommunityId(),
  178 + fees,
  179 + acctId: this.batchPayConfirmInfo.acctId,
  180 + accountAmount: this.batchPayConfirmInfo.accountAmount,
  181 + authCode: this.batchPayConfirmInfo.authCode,
  182 + receivedAmount: this.batchPayConfirmInfo.feePrices,
  183 + payerObjName: this.batchPayConfirmInfo.payerObjName,
  184 + subServiceCode: 'fee.payBatchFee'
  185 + }
  186 +
  187 + const res = await qrCodePayment(data)
  188 + if (res.code === 404) {
  189 + this.$message.warning(res.msg)
  190 + if (res.data && res.data.orderId) {
  191 + this.batchPayConfirmInfo.orderId = res.data.orderId
  192 + this.batchPayConfirmInfo.paymentPoolId = res.data.paymentPoolId
  193 + setTimeout(() => this._qrCodeCheckPayFinish(), 5000)
  194 + }
  195 + } else if (res.code === 0) {
  196 + this._doDealPayResult(res)
  197 + } else {
  198 + this.$message.error(res.msg)
  199 + }
  200 + } catch (error) {
  201 + console.error('请求失败:', error)
  202 + this.$message.error('扫码支付失败')
  203 + }
  204 + },
  205 +
  206 + async _qrCodeCheckPayFinish() {
  207 + const fees = this.batchPayConfirmInfo.fees.map(fee => ({
  208 + ...fee,
  209 + primeRate: this.batchPayConfirmInfo.primeRate
  210 + }))
  211 +
  212 + try {
  213 + const data = {
  214 + communityId: getCommunityId(),
  215 + fees,
  216 + acctId: this.batchPayConfirmInfo.acctId,
  217 + accountAmount: this.batchPayConfirmInfo.accountAmount,
  218 + authCode: this.batchPayConfirmInfo.authCode,
  219 + receivedAmount: this.batchPayConfirmInfo.feePrices,
  220 + subServiceCode: 'fee.payBatchFee',
  221 + orderId: this.batchPayConfirmInfo.orderId,
  222 + paymentPoolId: this.batchPayConfirmInfo.paymentPoolId
  223 + }
  224 +
  225 + const res = await checkPayFinish(data)
  226 + if (res.code === 404) {
  227 + this.$message.warning(res.msg)
  228 + } else if (res.code === 41) {
  229 + setTimeout(() => this._qrCodeCheckPayFinish(), 5000)
  230 + } else {
  231 + this._doDealPayResult(res)
  232 + }
  233 + } catch (error) {
  234 + console.error('请求失败:', error)
  235 + this.$message.error('支付状态查询失败')
  236 + }
  237 + },
  238 +
  239 + _doDealPayResult(res) {
  240 + this.handleClose()
  241 + const detailIds = res.data.details.join(',')
  242 + this.batchPayConfirmInfo.detailIds = detailIds
  243 +
  244 + setTimeout(() => {
  245 + this.resultVisible = true
  246 + }, 2000)
  247 + },
  248 +
  249 + _printAndBack(merge) {
  250 + this.resultVisible = false
  251 + window.open(`${this.batchPayConfirmInfo.printUrl}?detailIds=${this.batchPayConfirmInfo.detailIds}&merge=${merge}`)
  252 + },
  253 +
  254 + _back() {
  255 + this.resultVisible = false
  256 + this.$router.go(-1)
  257 + }
  258 + }
  259 +}
  260 +</script>
  261 +
  262 +<style lang="scss" scoped>
  263 +.result-content {
  264 + text-align: center;
  265 + font-size: 16px;
  266 + padding: 20px;
  267 +}
  268 +</style>
0 \ No newline at end of file 269 \ No newline at end of file
src/components/fee/carDetailOwner.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-row>
  4 + <el-col :span="24" class="text-right"></el-col>
  5 + </el-row>
  6 + <div class="margin-top">
  7 + <el-table :data="carDetailOwnerInfo.owners" border stripe>
  8 + <el-table-column :label="$t('carDetailOwner.ownerFace')" align="center">
  9 + <template slot-scope="scope">
  10 + <el-image
  11 + style="width: 60px; height: 60px; border-radius: 4px;"
  12 + :src="scope.row.url || '/img/noPhoto.jpg'"
  13 + :preview-src-list="[scope.row.url]"
  14 + v-if="scope.row.url"
  15 + ></el-image>
  16 + <el-image
  17 + style="width: 60px; height: 60px; border-radius: 4px;"
  18 + src="/img/noPhoto.jpg"
  19 + v-else
  20 + ></el-image>
  21 + </template>
  22 + </el-table-column>
  23 + <el-table-column :label="$t('carDetailOwner.name')" align="center">
  24 + <template slot-scope="scope">
  25 + {{scope.row.name}}({{scope.row.link}})
  26 + </template>
  27 + </el-table-column>
  28 + <el-table-column :label="$t('carDetailOwner.gender')" align="center">
  29 + <template slot-scope="scope">
  30 + {{scope.row.sex == 0 ? $t('carDetailOwner.male') : $t('carDetailOwner.female')}}
  31 + </template>
  32 + </el-table-column>
  33 + <el-table-column prop="idCard" :label="$t('carDetailOwner.idCard')" align="center">
  34 + <template slot-scope="scope">
  35 + {{scope.row.idCard || '-'}}
  36 + </template>
  37 + </el-table-column>
  38 + <el-table-column prop="address" :label="$t('carDetailOwner.address')" align="center">
  39 + <template slot-scope="scope">
  40 + {{scope.row.address || '-'}}
  41 + </template>
  42 + </el-table-column>
  43 + <el-table-column prop="roomCount" :label="$t('carDetailOwner.roomCount')" align="center">
  44 + <template slot-scope="scope">
  45 + {{scope.row.roomCount || 0}}
  46 + </template>
  47 + </el-table-column>
  48 + <el-table-column prop="memberCount" :label="$t('carDetailOwner.memberCount')" align="center">
  49 + <template slot-scope="scope">
  50 + {{scope.row.memberCount || 0}}
  51 + </template>
  52 + </el-table-column>
  53 + <el-table-column prop="carCount" :label="$t('carDetailOwner.carCount')" align="center">
  54 + <template slot-scope="scope">
  55 + {{scope.row.carCount || 0}}
  56 + </template>
  57 + </el-table-column>
  58 + <el-table-column prop="complaintCount" :label="$t('carDetailOwner.complaintCount')" align="center">
  59 + <template slot-scope="scope">
  60 + {{scope.row.complaintCount || 0}}
  61 + </template>
  62 + </el-table-column>
  63 + <el-table-column prop="repairCount" :label="$t('carDetailOwner.repairCount')" align="center">
  64 + <template slot-scope="scope">
  65 + {{scope.row.repairCount || 0}}
  66 + </template>
  67 + </el-table-column>
  68 + <el-table-column prop="oweFee" :label="$t('carDetailOwner.oweFee')" align="center">
  69 + <template slot-scope="scope">
  70 + {{scope.row.oweFee || '0.00'}}
  71 + </template>
  72 + </el-table-column>
  73 + <el-table-column prop="contractCount" :label="$t('carDetailOwner.contractCount')" align="center">
  74 + <template slot-scope="scope">
  75 + {{scope.row.contractCount || 0}}
  76 + </template>
  77 + </el-table-column>
  78 + <el-table-column :label="$t('carDetailOwner.actions')" align="center">
  79 + <template slot-scope="scope">
  80 + <el-button-group>
  81 + <el-button size="mini" @click="_toCarDetailOwnerDetail(scope.row)">
  82 + {{ $t('carDetailOwner.detail') }}
  83 + </el-button>
  84 + </el-button-group>
  85 + </template>
  86 + </el-table-column>
  87 + </el-table>
  88 + <el-pagination
  89 + @current-change="handleCurrentChange"
  90 + :current-page="currentPage"
  91 + :page-size="pageSize"
  92 + layout="total, prev, pager, next"
  93 + :total="total">
  94 + </el-pagination>
  95 + </div>
  96 + </div>
  97 +</template>
  98 +
  99 +<script>
  100 +import { getCommunityId } from '@/api/community/communityApi'
  101 +import { queryOwners } from '@/api/fee/carDetailOwnerApi'
  102 +
  103 +export default {
  104 + name: 'CarDetailOwner',
  105 + data() {
  106 + return {
  107 + DEFAULT_PAGE: 1,
  108 + DEFAULT_ROWS: 10,
  109 + carDetailOwnerInfo: {
  110 + owners: [],
  111 + ownerId: ''
  112 + },
  113 + currentPage: 1,
  114 + pageSize: 10,
  115 + total: 0
  116 + }
  117 + },
  118 + created() {
  119 + this._initEvent()
  120 + },
  121 + methods: {
  122 + _initEvent() {
  123 + this.$on('switch', this.handleSwitch)
  124 + this.$on('notify', this._loadCarDetailOwnerData)
  125 + },
  126 + handleSwitch(data) {
  127 + this.carDetailOwnerInfo.ownerId = data.ownerId
  128 + this._loadCarDetailOwnerData(this.DEFAULT_PAGE, this.DEFAULT_ROWS)
  129 + },
  130 + handleCurrentChange(val) {
  131 + this._loadCarDetailOwnerData(val, this.DEFAULT_ROWS)
  132 + },
  133 + async _loadCarDetailOwnerData(page, row) {
  134 + try {
  135 + const res = await queryOwners({
  136 + ownerId: this.carDetailOwnerInfo.ownerId,
  137 + communityId: getCommunityId(),
  138 + ownerTypeCd: '1001',
  139 + page,
  140 + row
  141 + })
  142 + this.carDetailOwnerInfo.owners = res.data
  143 + this.total = res.records
  144 + } catch (error) {
  145 + console.error('Request failed:', error)
  146 + }
  147 + },
  148 + _toCarDetailOwnerDetail(owner) {
  149 + window.open(`/#/pages/owner/ownerDetail?ownerId=${owner.ownerId}`)
  150 + },
  151 + open(params) {
  152 + this.handleSwitch(params)
  153 + }
  154 + }
  155 +}
  156 +</script>
  157 +
  158 +<style scoped>
  159 +.margin-top {
  160 + margin-top: 15px;
  161 +}
  162 +.text-right {
  163 + text-align: right;
  164 +}
  165 +</style>
0 \ No newline at end of file 166 \ No newline at end of file
src/components/fee/carDetailOwnerDemo.vue 0 → 100644
  1 +<template>
  2 + <car-detail-owner ref="carDetailOwner"></car-detail-owner>
  3 +</template>
  4 +
  5 +<script>
  6 +import CarDetailOwner from './carDetailOwner'
  7 +
  8 +export default {
  9 + name: 'CarDetailOwnerDemo',
  10 + components: {
  11 + CarDetailOwner
  12 + },
  13 + mounted() {
  14 + this.$refs.carDetailOwner.$emit('switch', {
  15 + ownerId: '123'
  16 + })
  17 + }
  18 +}
  19 +</script>
0 \ No newline at end of file 20 \ No newline at end of file
src/components/fee/deleteApplyRoomDiscount.vue
@@ -26,6 +26,7 @@ @@ -26,6 +26,7 @@
26 26
27 <script> 27 <script>
28 import { deleteApplyRoomDiscount } from '@/api/fee/applyRoomDiscountManageApi' 28 import { deleteApplyRoomDiscount } from '@/api/fee/applyRoomDiscountManageApi'
  29 +import { getCommunityId } from '@/api/community/communityApi'
29 30
30 export default { 31 export default {
31 name: 'DeleteApplyRoomDiscount', 32 name: 'DeleteApplyRoomDiscount',
@@ -43,7 +44,7 @@ export default { @@ -43,7 +44,7 @@ export default {
43 open(data) { 44 open(data) {
44 this.form = { 45 this.form = {
45 ardId: data.ardId, 46 ardId: data.ardId,
46 - communityId: this.$store.getters.communityId 47 + communityId: getCommunityId()
47 } 48 }
48 this.visible = true 49 this.visible = true
49 }, 50 },
src/components/fee/deleteFee.vue
1 <template> 1 <template>
2 - <el-dialog :title="$t('deleteFee.title')" :visible.sync="visible" width="30%">  
3 - <div>  
4 - <p>{{ $t('deleteFee.confirmDelete') }}</p>  
5 - </div> 2 + <el-dialog
  3 + :title="$t('deleteFee.title')"
  4 + :visible.sync="visible"
  5 + width="30%"
  6 + :before-close="handleClose"
  7 + >
  8 + <p>{{ $t('deleteFee.confirmMessage') }}</p>
6 <span slot="footer" class="dialog-footer"> 9 <span slot="footer" class="dialog-footer">
7 - <el-button @click="close">{{ $t('common.cancel') }}</el-button> 10 + <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
8 <el-button type="primary" @click="deleteFee">{{ $t('common.confirm') }}</el-button> 11 <el-button type="primary" @click="deleteFee">{{ $t('common.confirm') }}</el-button>
9 </span> 12 </span>
10 </el-dialog> 13 </el-dialog>
11 </template> 14 </template>
12 15
13 <script> 16 <script>
14 -import { deleteFee } from '@/api/fee/listCarFeeApi' 17 +import { deleteFee } from '@/api/fee/deleteFeeApi'
  18 +import { getCommunityId } from '@/api/community/communityApi'
15 19
16 export default { 20 export default {
17 name: 'DeleteFee', 21 name: 'DeleteFee',
@@ -22,25 +26,29 @@ export default { @@ -22,25 +26,29 @@ export default {
22 } 26 }
23 }, 27 },
24 methods: { 28 methods: {
25 - open(info) {  
26 - this.deleteFeeInfo = info 29 + open(params) {
  30 + this.deleteFeeInfo = params
27 this.visible = true 31 this.visible = true
28 }, 32 },
29 - close() { 33 + handleClose() {
30 this.visible = false 34 this.visible = false
31 }, 35 },
32 - deleteFee() {  
33 - deleteFee(this.deleteFeeInfo).then(response => {  
34 - if (response.code === 0) {  
35 - this.$message.success(this.$t('common.deleteSuccess')) 36 + async deleteFee() {
  37 + this.deleteFeeInfo.communityId = getCommunityId()
  38 +
  39 + try {
  40 + const res = await deleteFee(this.deleteFeeInfo)
  41 + if (res.code === 0) {
  42 + this.$message.success(this.$t('common.operateSuccess'))
36 this.$emit('success') 43 this.$emit('success')
37 - this.close() 44 + this.handleClose()
38 } else { 45 } else {
39 - this.$message.error(response.msg) 46 + this.$message.error(res.msg)
40 } 47 }
41 - }).catch(error => {  
42 - this.$message.error(error.message)  
43 - }) 48 + } catch (error) {
  49 + console.error('请求失败:', error)
  50 + this.$message.error(this.$t('common.operateFail'))
  51 + }
44 } 52 }
45 } 53 }
46 } 54 }
src/components/fee/deleteFeeDemo.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-button @click="openModal">{{ $t('deleteFeeDemo.openModal') }}</el-button>
  4 + <delete-fee ref="deleteFee" @success="handleSuccess"></delete-fee>
  5 + </div>
  6 +</template>
  7 +
  8 +<script>
  9 +import DeleteFee from './deleteFee'
  10 +
  11 +export default {
  12 + name: 'DeleteFeeDemo',
  13 + components: {
  14 + DeleteFee
  15 + },
  16 + methods: {
  17 + openModal() {
  18 + this.$refs.deleteFee.open({
  19 + feeId: '123'
  20 + })
  21 + },
  22 + handleSuccess() {
  23 + this.$message.success(this.$t('deleteFeeDemo.successMessage'))
  24 + }
  25 + }
  26 +}
  27 +</script>
0 \ No newline at end of file 28 \ No newline at end of file
src/components/fee/deleteFeeRule.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('deleteFeeRule.confirmTitle')"
  4 + :visible.sync="dialogVisible"
  5 + width="30%"
  6 + >
  7 + <div class="text-center">
  8 + <p>{{ $t('deleteFeeRule.confirmMessage') }}</p>
  9 + </div>
  10 + <span slot="footer" class="dialog-footer">
  11 + <el-button @click="closeDeleteFeeRuleModel">{{ $t('deleteFeeRule.cancel') }}</el-button>
  12 + <el-button type="primary" @click="deleteFeeRule">{{ $t('deleteFeeRule.confirmDelete') }}</el-button>
  13 + </span>
  14 + </el-dialog>
  15 +</template>
  16 +
  17 +<script>
  18 +import { deletePayFeeRule } from '@/api/fee/deleteFeeRuleApi'
  19 +import { getCommunityId } from '@/api/community/communityApi'
  20 +
  21 +export default {
  22 + name: 'DeleteFeeRule',
  23 + data() {
  24 + return {
  25 + dialogVisible: false,
  26 + deleteFeeRuleInfo: {},
  27 + communityId: ''
  28 + }
  29 + },
  30 + created() {
  31 + this.communityId = getCommunityId()
  32 + },
  33 + methods: {
  34 + open(params) {
  35 + this.deleteFeeRuleInfo = params
  36 + this.dialogVisible = true
  37 + },
  38 + deleteFeeRule() {
  39 + const params = {
  40 + ...this.deleteFeeRuleInfo,
  41 + communityId: this.communityId
  42 + }
  43 +
  44 + deletePayFeeRule(params).then(response => {
  45 + if (response.code === 0) {
  46 + this.dialogVisible = false
  47 + this.$emit('delete-success')
  48 + this.$message.success(this.$t('deleteFeeRule.deleteSuccess'))
  49 + } else {
  50 + this.$message.error(response.msg)
  51 + }
  52 + }).catch(error => {
  53 + console.error('请求失败:', error)
  54 + this.$message.error(this.$t('deleteFeeRule.deleteFailed'))
  55 + })
  56 + },
  57 + closeDeleteFeeRuleModel() {
  58 + this.dialogVisible = false
  59 + }
  60 + }
  61 +}
  62 +</script>
  63 +
  64 +<style scoped>
  65 +.text-center {
  66 + text-align: center;
  67 +}
  68 +</style>
0 \ No newline at end of file 69 \ No newline at end of file
src/components/fee/deleteFeeRuleDemo.vue 0 → 100644
  1 +<template>
  2 + <el-button @click="openModal">{{ $t('deleteFeeRuleDemo.openModal') }}</el-button>
  3 + <delete-fee-rule ref="deleteFeeRule" @delete-success="handleDeleteSuccess"></delete-fee-rule>
  4 +</template>
  5 +
  6 +<script>
  7 +import DeleteFeeRule from './deleteFeeRule'
  8 +
  9 +export default {
  10 + name: 'DeleteFeeRuleDemo',
  11 + components: {
  12 + DeleteFeeRule
  13 + },
  14 + methods: {
  15 + openModal() {
  16 + this.$refs.deleteFeeRule.open({
  17 + feeRuleId: '123'
  18 + })
  19 + },
  20 + handleDeleteSuccess() {
  21 + console.log('Delete success')
  22 + }
  23 + }
  24 +}
  25 +</script>
0 \ No newline at end of file 26 \ No newline at end of file
src/components/fee/deleteOweFeeCallable.vue
1 <template> 1 <template>
2 <el-dialog 2 <el-dialog
3 - :title="$t('oweFeeCallable.delete.title')" 3 + :title="$t('deleteOweFeeCallable.title')"
4 :visible.sync="dialogVisible" 4 :visible.sync="dialogVisible"
5 width="30%" 5 width="30%"
6 - @close="handleClose">  
7 - <div class="delete-content">  
8 - <p>{{ $t('oweFeeCallable.delete.confirm') }}</p> 6 + :before-close="handleClose"
  7 + >
  8 + <div align="center">
  9 + <h4>{{ $t('deleteOweFeeCallable.confirmDelete') }}</h4>
9 </div> 10 </div>
10 <span slot="footer" class="dialog-footer"> 11 <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> 12 + <el-button @click="closeDeleteOweFeeCallableModel">{{ $t('deleteOweFeeCallable.cancel') }}</el-button>
  13 + <el-button type="primary" @click="deleteOweFeeCallable">{{ $t('deleteOweFeeCallable.confirm') }}</el-button>
13 </span> 14 </span>
14 </el-dialog> 15 </el-dialog>
15 </template> 16 </template>
16 17
17 <script> 18 <script>
18 -import { deleteOweFeeCallable } from '@/api/fee/oweFeeCallableApi'  
19 import { getCommunityId } from '@/api/community/communityApi' 19 import { getCommunityId } from '@/api/community/communityApi'
  20 +import { deleteOweFeeCallable } from '@/api/fee/deleteOweFeeCallableApi'
20 21
21 export default { 22 export default {
22 name: 'DeleteOweFeeCallable', 23 name: 'DeleteOweFeeCallable',
23 data() { 24 data() {
24 return { 25 return {
25 dialogVisible: false, 26 dialogVisible: false,
26 - currentItem: null 27 + deleteOweFeeCallableInfo: {}
27 } 28 }
28 }, 29 },
  30 + created() {
  31 + this._initEvent()
  32 + },
29 methods: { 33 methods: {
30 - open(item) {  
31 - this.currentItem = {  
32 - ...item,  
33 - communityId: getCommunityId()  
34 - } 34 + _initEvent() {
  35 + this.$on('openDeleteOweFeeCallableModal', this.open)
  36 + },
  37 + open(params) {
  38 + this.deleteOweFeeCallableInfo = params
35 this.dialogVisible = true 39 this.dialogVisible = true
36 }, 40 },
37 - async handleConfirm() { 41 + handleClose(done) {
  42 + this.closeDeleteOweFeeCallableModel()
  43 + done()
  44 + },
  45 + async deleteOweFeeCallable() {
38 try { 46 try {
39 - await deleteOweFeeCallable(this.currentItem)  
40 - this.$message.success(this.$t('oweFeeCallable.delete.success'))  
41 - this.dialogVisible = false  
42 - this.$emit('success') 47 + const params = {
  48 + ...this.deleteOweFeeCallableInfo,
  49 + communityId: getCommunityId()
  50 + }
  51 + const res = await deleteOweFeeCallable(params)
  52 + if (res.code === 0) {
  53 + this.dialogVisible = false
  54 + this.$emit('listOweFeeCallable', {})
  55 + this.$emit('listOwnerData', {})
  56 + this.$message.success(this.$t('deleteOweFeeCallable.success'))
  57 + } else {
  58 + this.$message.error(res.msg)
  59 + }
43 } catch (error) { 60 } catch (error) {
44 - console.error('删除失败:', error)  
45 - this.$message.error(error.message || this.$t('oweFeeCallable.delete.error')) 61 + console.error('Request failed:', error)
  62 + this.$message.error(error.message)
46 } 63 }
47 }, 64 },
48 - handleClose() {  
49 - this.currentItem = null 65 + closeDeleteOweFeeCallableModel() {
  66 + this.dialogVisible = false
50 } 67 }
51 } 68 }
52 } 69 }
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>  
62 \ No newline at end of file 70 \ No newline at end of file
  71 +</script>
63 \ No newline at end of file 72 \ No newline at end of file
src/components/fee/deleteOweFeeCallableDemo.vue 0 → 100644
  1 +<template>
  2 + <el-button @click="openModal">{{$t('deleteOweFeeCallableDemo.openModal')}}</el-button>
  3 + <delete-owe-fee-callable ref="deleteOweFeeCallable"></delete-owe-fee-callable>
  4 +</template>
  5 +
  6 +<script>
  7 +import DeleteOweFeeCallable from './deleteOweFeeCallable'
  8 +
  9 +export default {
  10 + name: 'DeleteOweFeeCallableDemo',
  11 + components: {
  12 + DeleteOweFeeCallable
  13 + },
  14 + methods: {
  15 + openModal() {
  16 + this.$refs.deleteOweFeeCallable.open({
  17 + ofcId: '123'
  18 + })
  19 + }
  20 + }
  21 +}
  22 +</script>
0 \ No newline at end of file 23 \ No newline at end of file
src/components/fee/doImportCreateFee.vue
1 <template> 1 <template>
2 - <el-dialog  
3 - :title="$t('doImportCreateFee.customCreateFee')"  
4 - :visible.sync="visible"  
5 - width="50%" 2 + <el-dialog
  3 + :title="$t('doImportCreateFee.title')"
  4 + :visible.sync="visible"
  5 + width="70%"
  6 + :before-close="handleClose"
6 > 7 >
7 - <el-form label-width="150px"> 8 + <el-form label-width="120px">
8 <el-form-item :label="$t('doImportCreateFee.selectFile')"> 9 <el-form-item :label="$t('doImportCreateFee.selectFile')">
9 <el-upload 10 <el-upload
10 class="upload-demo" 11 class="upload-demo"
11 - :before-upload="beforeUpload" 12 + action=""
  13 + :auto-upload="false"
  14 + :on-change="handleFileChange"
12 :show-file-list="false" 15 :show-file-list="false"
  16 + accept=".xls,.xlsx"
13 > 17 >
14 - <el-button size="small" type="primary">  
15 - <i class="el-icon-upload"></i>  
16 - {{ $t('common.selectFile') }}  
17 - </el-button>  
18 - <div slot="tip" class="el-upload__tip" style="margin-top:10px">  
19 - {{ fileName || $t('doImportCreateFee.requiredFile') }} 18 + <el-button size="small" type="primary">{{ $t('doImportCreateFee.clickUpload') }}</el-button>
  19 + <div slot="tip" class="el-upload__tip">
  20 + {{ fileName || $t('doImportCreateFee.fileTip') }}
20 </div> 21 </div>
21 </el-upload> 22 </el-upload>
22 </el-form-item> 23 </el-form-item>
23 </el-form> 24 </el-form>
24 -  
25 - <div slot="footer" class="dialog-footer">  
26 - <el-button @click="visible = false">{{ $t('doImportCreateFee.cancel') }}</el-button>  
27 - <el-button type="primary" @click="handleImport" :disabled="!file">  
28 - {{ $t('doImportCreateFee.import') }}  
29 - </el-button>  
30 - </div> 25 +
  26 + <span slot="footer" class="dialog-footer">
  27 + <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
  28 + <el-button
  29 + type="primary"
  30 + @click="handleImport"
  31 + :disabled="!fileName"
  32 + >{{ $t('common.import') }}</el-button>
  33 + </span>
31 </el-dialog> 34 </el-dialog>
32 </template> 35 </template>
33 36
34 <script> 37 <script>
35 -import { importCustomFee } from '@/api/fee/carCreateFeeApi' 38 +import { importData } from '@/api/fee/doImportCreateFeeApi'
  39 +import { getCommunityId } from '@/api/community/communityApi'
36 40
37 export default { 41 export default {
38 name: 'DoImportCreateFee', 42 name: 'DoImportCreateFee',
@@ -43,52 +47,69 @@ export default { @@ -43,52 +47,69 @@ export default {
43 fileName: '' 47 fileName: ''
44 } 48 }
45 }, 49 },
  50 + computed: {
  51 + communityId() {
  52 + return getCommunityId()
  53 + }
  54 + },
46 methods: { 55 methods: {
47 open() { 56 open() {
48 this.visible = true 57 this.visible = true
49 - this.file = null  
50 - this.fileName = '' 58 + this.reset()
51 }, 59 },
52 - beforeUpload(file) {  
53 - const validTypes = ['xlsx', 'xls']  
54 - const fileType = file.name.split('.').pop().toLowerCase()  
55 - const isExcel = validTypes.includes(fileType)  
56 - const isLt2M = file.size / 1024 / 1024 < 2  
57 -  
58 - if (!isExcel) {  
59 - this.$message.error(this.$t('common.invalidExcelType')) 60 +
  61 + handleFileChange(file) {
  62 + if (!this.checkFileType(file.name)) {
  63 + this.$message.error(this.$t('doImportCreateFee.validate.invalidFileType'))
60 return false 64 return false
61 } 65 }
62 - if (!isLt2M) {  
63 - this.$message.error(this.$t('common.fileSizeExceed')) 66 +
  67 + if (!this.checkFileSize(file.size)) {
  68 + this.$message.error(this.$t('doImportCreateFee.validate.fileTooLarge'))
64 return false 69 return false
65 } 70 }
66 71
67 - this.file = file 72 + this.file = file.raw
68 this.fileName = file.name 73 this.fileName = file.name
69 - return false // 阻止自动上传  
70 }, 74 },
71 - async handleImport() {  
72 - if (!this.file) {  
73 - this.$message.warning(this.$t('doImportCreateFee.requiredFile'))  
74 - return  
75 - } 75 +
  76 + checkFileType(filename) {
  77 + const ext = filename.split('.').pop().toLowerCase()
  78 + return ['xls', 'xlsx'].includes(ext)
  79 + },
  80 +
  81 + checkFileSize(size) {
  82 + return size <= 2 * 1024 * 1024 // 2MB
  83 + },
  84 +
  85 + handleImport() {
  86 + const formData = new FormData()
  87 + formData.append('uploadFile', this.file)
  88 + formData.append('communityId', this.communityId)
  89 + formData.append('importAdapt', 'importCustomFee')
76 90
77 - try {  
78 - const res = await importCustomFee({  
79 - file: this.file  
80 - })  
81 - 91 + importData(formData).then(response => {
  92 + const res = response.data
82 if (res.code === 0) { 93 if (res.code === 0) {
83 - this.$message.success(this.$t('common.importSuccess'))  
84 - this.visible = false  
85 - this.$emit('success') 94 + this.$message.success(this.$t('doImportCreateFee.successMessage'))
  95 + this.handleClose()
  96 + this.$router.push(`/pages/property/assetImportLogDetail?logId=${res.data.logId}&logType=importCustomFee`)
86 } else { 97 } else {
87 - this.$message.error(res.msg || this.$t('common.importError')) 98 + this.$message.error(res.msg)
88 } 99 }
89 - } catch (error) {  
90 - this.$message.error(this.$t('common.importError'))  
91 - } 100 + }).catch(error => {
  101 + this.$message.error(error.message)
  102 + })
  103 + },
  104 +
  105 + handleClose() {
  106 + this.visible = false
  107 + this.reset()
  108 + },
  109 +
  110 + reset() {
  111 + this.file = null
  112 + this.fileName = ''
92 } 113 }
93 } 114 }
94 } 115 }
src/components/fee/doImportCreateFeeDemo.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-button @click="openModal">{{ $t('doImportCreateFeeDemo.openModal') }}</el-button>
  4 + <do-import-create-fee ref="doImportCreateFee"></do-import-create-fee>
  5 + </div>
  6 +</template>
  7 +
  8 +<script>
  9 +import DoImportCreateFee from './doImportCreateFee'
  10 +
  11 +export default {
  12 + name: 'DoImportCreateFeeDemo',
  13 + components: {
  14 + DoImportCreateFee
  15 + },
  16 + methods: {
  17 + openModal() {
  18 + this.$refs.doImportCreateFee.open()
  19 + }
  20 + }
  21 +}
  22 +</script>
0 \ No newline at end of file 23 \ No newline at end of file
src/components/fee/downloadCollectionLetterOrder.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('downloadCollectionLetterOrder.title')"
  4 + :visible.sync="visible"
  5 + width="70%"
  6 + :before-close="handleClose"
  7 + >
  8 + <el-form label-width="120px">
  9 + <template v-if="roomId">
  10 + <el-alert
  11 + :title="$t('downloadCollectionLetterOrder.confirmExport')"
  12 + type="info"
  13 + show-icon
  14 + ></el-alert>
  15 + </template>
  16 + <template v-else>
  17 + <el-form-item :label="$t('downloadCollectionLetterOrder.selectFloor')">
  18 + <el-select
  19 + v-model="floorId"
  20 + :placeholder="$t('downloadCollectionLetterOrder.floorPlaceholder')"
  21 + style="width: 100%"
  22 + >
  23 + <el-option
  24 + v-for="item in floors"
  25 + :key="item.floorId"
  26 + :label="item.floorNum"
  27 + :value="item.floorId"
  28 + ></el-option>
  29 + </el-select>
  30 + </el-form-item>
  31 + </template>
  32 + </el-form>
  33 +
  34 + <span slot="footer" class="dialog-footer">
  35 + <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
  36 + <el-button
  37 + type="primary"
  38 + @click="handleExport"
  39 + :disabled="!floorId && !roomId"
  40 + >{{ $t('common.export') }}</el-button>
  41 + </span>
  42 + </el-dialog>
  43 +</template>
  44 +
  45 +<script>
  46 +import { exportData, queryFloors } from '@/api/fee/downloadCollectionLetterOrderApi'
  47 +import { getCommunityId } from '@/api/community/communityApi'
  48 +
  49 +export default {
  50 + name: 'DownloadCollectionLetterOrder',
  51 + data() {
  52 + return {
  53 + visible: false,
  54 + roomId: '',
  55 + floorId: '',
  56 + floors: []
  57 + }
  58 + },
  59 + computed: {
  60 + communityId() {
  61 + return getCommunityId()
  62 + }
  63 + },
  64 + methods: {
  65 + open(params) {
  66 + this.visible = true
  67 + this.roomId = params.roomId || ''
  68 + this.loadFloors()
  69 + },
  70 +
  71 + loadFloors() {
  72 + queryFloors({
  73 + page: 1,
  74 + row: 100,
  75 + communityId: this.communityId
  76 + }).then(response => {
  77 + this.floors = response.data.apiFloorDataVoList
  78 + })
  79 + },
  80 +
  81 + handleExport() {
  82 + const params = {
  83 + communityId: this.communityId,
  84 + pagePath: 'dataFeeManualCollection',
  85 + floorId: this.floorId,
  86 + roomId: this.roomId
  87 + }
  88 +
  89 + exportData(params).then(response => {
  90 + const res = response.data
  91 + this.$message.success(res.msg)
  92 + if (res.code === 0) {
  93 + this.handleClose()
  94 + this.$router.push('/pages/property/downloadTempFile?tab=下载中心')
  95 + }
  96 + }).catch(error => {
  97 + this.$message.error(error.message)
  98 + })
  99 + },
  100 +
  101 + handleClose() {
  102 + this.visible = false
  103 + this.reset()
  104 + },
  105 +
  106 + reset() {
  107 + this.roomId = ''
  108 + this.floorId = ''
  109 + }
  110 + }
  111 +}
  112 +</script>
0 \ No newline at end of file 113 \ No newline at end of file
src/components/fee/downloadCollectionLetterOrderDemo.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-button @click="openModal">{{ $t('downloadCollectionLetterOrderDemo.openModal') }}</el-button>
  4 + <download-collection-letter-order ref="downloadCollectionLetterOrder"></download-collection-letter-order>
  5 + </div>
  6 +</template>
  7 +
  8 +<script>
  9 +import DownloadCollectionLetterOrder from './downloadCollectionLetterOrder'
  10 +
  11 +export default {
  12 + name: 'DownloadCollectionLetterOrderDemo',
  13 + components: {
  14 + DownloadCollectionLetterOrder
  15 + },
  16 + methods: {
  17 + openModal() {
  18 + this.$refs.downloadCollectionLetterOrder.open({
  19 + roomId: '123' // Optional, remove if you want to select floor
  20 + })
  21 + }
  22 + }
  23 +}
  24 +</script>
0 \ No newline at end of file 25 \ No newline at end of file
src/components/fee/editApplyRoomDiscount.vue
@@ -48,6 +48,7 @@ @@ -48,6 +48,7 @@
48 <script> 48 <script>
49 import { updateApplyRoomDiscount } from '@/api/fee/applyRoomDiscountManageApi' 49 import { updateApplyRoomDiscount } from '@/api/fee/applyRoomDiscountManageApi'
50 import UploadImageUrl from '@/components/upload/UploadImageUrl' 50 import UploadImageUrl from '@/components/upload/UploadImageUrl'
  51 +import { getCommunityId } from '@/api/community/communityApi'
51 52
52 export default { 53 export default {
53 name: 'EditApplyRoomDiscount', 54 name: 'EditApplyRoomDiscount',
@@ -90,7 +91,7 @@ export default { @@ -90,7 +91,7 @@ export default {
90 this.form = { 91 this.form = {
91 ...this.form, 92 ...this.form,
92 ...data, 93 ...data,
93 - communityId: this.$store.getters.communityId 94 + communityId: getCommunityId()
94 } 95 }
95 this.$nextTick(() => { 96 this.$nextTick(() => {
96 if (this.$refs.uploadImage) { 97 if (this.$refs.uploadImage) {
src/components/fee/editApplyRoomDiscountRecord.vue
@@ -113,6 +113,7 @@ @@ -113,6 +113,7 @@
113 113
114 <script> 114 <script>
115 import { updateApplyRoomDiscount } from '@/api/fee/applyRoomDiscountManageApi' 115 import { updateApplyRoomDiscount } from '@/api/fee/applyRoomDiscountManageApi'
  116 +import { getCommunityId } from '@/api/community/communityApi'
116 117
117 export default { 118 export default {
118 name: 'EditApplyRoomDiscountRecord', 119 name: 'EditApplyRoomDiscountRecord',
@@ -164,7 +165,7 @@ export default { @@ -164,7 +165,7 @@ export default {
164 this.form = { 165 this.form = {
165 ...this.form, 166 ...this.form,
166 ...data, 167 ...data,
167 - communityId: this.$store.getters.communityId 168 + communityId: getCommunityId()
168 } 169 }
169 this.visible = true 170 this.visible = true
170 }, 171 },
src/components/fee/editFee.vue
1 <template> 1 <template>
2 - <el-dialog :title="$t('editFee.title')" :visible.sync="visible" width="50%"> 2 + <el-dialog
  3 + :title="$t('editFee.title')"
  4 + :visible.sync="visible"
  5 + width="50%"
  6 + :before-close="handleClose"
  7 + >
3 <el-form :model="editFeeInfo" label-width="120px"> 8 <el-form :model="editFeeInfo" label-width="120px">
4 - <el-form-item :label="$t('editFee.startTime')" required>  
5 - <el-date-picker v-model="editFeeInfo.startTime" type="datetime" :placeholder="$t('editFee.startTimePlaceholder')"  
6 - value-format="yyyy-MM-dd HH:mm:ss" style="width:100%">  
7 - </el-date-picker> 9 + <el-form-item :label="$t('editFee.startTime')" prop="startTime">
  10 + <el-date-picker
  11 + v-model="editFeeInfo.startTime"
  12 + type="datetime"
  13 + :placeholder="$t('editFee.startTimePlaceholder')"
  14 + value-format="yyyy-MM-dd HH:mm:ss"
  15 + @change="validateStartTime"
  16 + ></el-date-picker>
8 </el-form-item> 17 </el-form-item>
9 - <el-form-item :label="$t('editFee.endTime')" required>  
10 - <el-date-picker v-model="editFeeInfo.endTime" type="datetime" :placeholder="$t('editFee.endTimePlaceholder')"  
11 - value-format="yyyy-MM-dd HH:mm:ss" style="width:100%">  
12 - </el-date-picker> 18 + <el-form-item :label="$t('editFee.endTime')" prop="endTime">
  19 + <el-date-picker
  20 + v-model="editFeeInfo.endTime"
  21 + type="date"
  22 + :placeholder="$t('editFee.endTimePlaceholder')"
  23 + value-format="yyyy-MM-dd"
  24 + @change="validateEndTime"
  25 + ></el-date-picker>
13 </el-form-item> 26 </el-form-item>
14 - <el-form-item :label="$t('editFee.maxEndTime')" required>  
15 - <el-date-picker v-model="editFeeInfo.maxEndTime" type="datetime"  
16 - :placeholder="$t('editFee.maxEndTimePlaceholder')" value-format="yyyy-MM-dd HH:mm:ss" style="width:100%">  
17 - </el-date-picker> 27 + <el-form-item :label="$t('editFee.maxEndTime')" prop="maxEndTime">
  28 + <el-date-picker
  29 + v-model="editFeeInfo.maxEndTime"
  30 + type="date"
  31 + :placeholder="$t('editFee.maxEndTimePlaceholder')"
  32 + value-format="yyyy-MM-dd"
  33 + @change="validateMaxEndTime"
  34 + ></el-date-picker>
18 </el-form-item> 35 </el-form-item>
19 - <template v-if="editFeeInfo.computingFormula == '1102'">  
20 - <el-form-item :label="$t('editFee.rateCycle')" required>  
21 - <el-input v-model="editFeeInfo.rateCycle" :placeholder="$t('editFee.rateCyclePlaceholder')"></el-input> 36 + <template v-if="editFeeInfo.computingFormula === '1102'">
  37 + <el-form-item :label="$t('editFee.rateCycle')" prop="rateCycle">
  38 + <el-input
  39 + v-model="editFeeInfo.rateCycle"
  40 + :placeholder="$t('editFee.rateCyclePlaceholder')"
  41 + ></el-input>
22 </el-form-item> 42 </el-form-item>
23 - <el-form-item :label="$t('editFee.rate')" required>  
24 - <el-input v-model="editFeeInfo.rate" :placeholder="$t('editFee.ratePlaceholder')"></el-input> 43 + <el-form-item :label="$t('editFee.rate')" prop="rate">
  44 + <el-input
  45 + v-model="editFeeInfo.rate"
  46 + :placeholder="$t('editFee.ratePlaceholder')"
  47 + ></el-input>
25 </el-form-item> 48 </el-form-item>
26 - <el-form-item :label="$t('editFee.rateStartTime')" required>  
27 - <el-date-picker v-model="editFeeInfo.rateStartTime" type="datetime"  
28 - :placeholder="$t('editFee.rateStartTimePlaceholder')" value-format="yyyy-MM-dd HH:mm:ss" style="width:100%">  
29 - </el-date-picker> 49 + <el-form-item :label="$t('editFee.rateStartTime')" prop="rateStartTime">
  50 + <el-date-picker
  51 + v-model="editFeeInfo.rateStartTime"
  52 + type="date"
  53 + :placeholder="$t('editFee.rateStartTimePlaceholder')"
  54 + value-format="yyyy-MM-dd"
  55 + @change="validateRateStartTime"
  56 + ></el-date-picker>
30 </el-form-item> 57 </el-form-item>
31 </template> 58 </template>
32 </el-form> 59 </el-form>
33 <span slot="footer" class="dialog-footer"> 60 <span slot="footer" class="dialog-footer">
34 - <el-button @click="close">{{ $t('common.cancel') }}</el-button> 61 + <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
35 <el-button type="primary" @click="_doEidtFee">{{ $t('common.submit') }}</el-button> 62 <el-button type="primary" @click="_doEidtFee">{{ $t('common.submit') }}</el-button>
36 </span> 63 </span>
37 </el-dialog> 64 </el-dialog>
38 </template> 65 </template>
39 66
40 <script> 67 <script>
41 -import { updateFee } from '@/api/fee/listCarFeeApi' 68 +import { updateFee } from '@/api/fee/editFeeApi'
  69 +import { getCommunityId } from '@/api/community/communityApi'
42 70
43 export default { 71 export default {
44 name: 'EditFee', 72 name: 'EditFee',
@@ -60,25 +88,97 @@ export default { @@ -60,25 +88,97 @@ export default {
60 }, 88 },
61 methods: { 89 methods: {
62 open(fee) { 90 open(fee) {
63 - this.editFeeInfo = { ...fee } 91 + this.editFeeInfo = {
  92 + feeId: fee.feeId,
  93 + startTime: fee.startTime.indexOf(":") === -1 ? fee.startTime + " 00:00:00" : fee.startTime,
  94 + endTime: fee.endTime.split(' ')[0],
  95 + feeFlag: fee.feeFlag,
  96 + maxEndTime: fee.maxEndTime,
  97 + computingFormula: fee.computingFormula,
  98 + rateCycle: fee.rateCycle,
  99 + rate: fee.rate,
  100 + rateStartTime: fee.rateStartTime
  101 + }
64 this.visible = true 102 this.visible = true
65 }, 103 },
66 - close() { 104 + handleClose() {
67 this.visible = false 105 this.visible = false
  106 + this.clearAddFeeConfigInfo()
  107 + },
  108 + validateStartTime(value) {
  109 + const start = new Date(value)
  110 + const end = new Date(this.editFeeInfo.endTime)
  111 + if (start >= end) {
  112 + this.$message.error(this.$t('editFee.startTimeError'))
  113 + this.editFeeInfo.startTime = ''
  114 + }
  115 + },
  116 + validateEndTime(value) {
  117 + const start = new Date(this.editFeeInfo.startTime)
  118 + const end = new Date(value)
  119 + if (start >= end) {
  120 + this.$message.error(this.$t('editFee.endTimeError'))
  121 + this.editFeeInfo.endTime = ''
  122 + }
  123 + },
  124 + validateMaxEndTime(value) {
  125 + const start = new Date(this.editFeeInfo.startTime)
  126 + const end = new Date(value)
  127 + if (start >= end) {
  128 + this.$message.error(this.$t('editFee.maxEndTimeError'))
  129 + this.editFeeInfo.maxEndTime = ''
  130 + }
  131 + },
  132 + validateRateStartTime(value) {
  133 + const start = new Date(this.editFeeInfo.startTime)
  134 + const end = new Date(value)
  135 + if (start >= end) {
  136 + this.$message.error(this.$t('editFee.rateStartTimeError'))
  137 + this.editFeeInfo.rateStartTime = ''
  138 + }
  139 + },
  140 + editFeeValidate() {
  141 + if (!this.editFeeInfo.startTime) {
  142 + this.$message.error(this.$t('editFee.startTimeRequired'))
  143 + return false
  144 + }
  145 + if (!this.editFeeInfo.endTime) {
  146 + this.$message.error(this.$t('editFee.endTimeRequired'))
  147 + return false
  148 + }
  149 + return true
68 }, 150 },
69 - _doEidtFee() {  
70 - // 验证逻辑  
71 - updateFee(this.editFeeInfo).then(response => {  
72 - if (response.code === 0) {  
73 - this.$message.success(this.$t('common.updateSuccess')) 151 + async _doEidtFee() {
  152 + if (!this.editFeeValidate()) return
  153 +
  154 + this.editFeeInfo.communityId = getCommunityId()
  155 +
  156 + try {
  157 + const res = await updateFee(this.editFeeInfo)
  158 + if (res.code === 0) {
  159 + this.$message.success(this.$t('common.operateSuccess'))
74 this.$emit('success') 160 this.$emit('success')
75 - this.close() 161 + this.handleClose()
76 } else { 162 } else {
77 - this.$message.error(response.msg) 163 + this.$message.error(res.msg)
78 } 164 }
79 - }).catch(error => {  
80 - this.$message.error(error.message)  
81 - }) 165 + } catch (error) {
  166 + console.error('请求失败:', error)
  167 + this.$message.error(this.$t('common.operateFail'))
  168 + }
  169 + },
  170 + clearAddFeeConfigInfo() {
  171 + this.editFeeInfo = {
  172 + feeId: '',
  173 + startTime: '',
  174 + endTime: '',
  175 + feeFlag: '',
  176 + maxEndTime: '',
  177 + computingFormula: '',
  178 + rateCycle: '',
  179 + rate: '',
  180 + rateStartTime: ''
  181 + }
82 } 182 }
83 } 183 }
84 } 184 }
src/components/fee/editFeeDemo.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-button @click="openModal">{{ $t('editFeeDemo.openModal') }}</el-button>
  4 + <edit-fee ref="editFee" @success="handleSuccess"></edit-fee>
  5 + </div>
  6 +</template>
  7 +
  8 +<script>
  9 +import EditFee from './editFee'
  10 +
  11 +export default {
  12 + name: 'EditFeeDemo',
  13 + components: {
  14 + EditFee
  15 + },
  16 + methods: {
  17 + openModal() {
  18 + this.$refs.editFee.open({
  19 + feeId: '123',
  20 + startTime: '2023-01-01 00:00:00',
  21 + endTime: '2023-01-01',
  22 + maxEndTime: '2023-12-31',
  23 + computingFormula: '1102',
  24 + rateCycle: '12',
  25 + rate: '0.05',
  26 + rateStartTime: '2023-01-01'
  27 + })
  28 + },
  29 + handleSuccess() {
  30 + this.$message.success(this.$t('editFeeDemo.successMessage'))
  31 + }
  32 + }
  33 +}
  34 +</script>
0 \ No newline at end of file 35 \ No newline at end of file
src/components/fee/editFeeRule.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('editFeeRule.title')"
  4 + :visible.sync="visible"
  5 + width="50%"
  6 + :before-close="handleClose"
  7 + >
  8 + <el-form :model="editFeeRuleInfo" label-width="120px">
  9 + <el-form-item :label="$t('editFeeRule.maxTime')" prop="maxTime">
  10 + <el-date-picker
  11 + v-model="editFeeRuleInfo.maxTime"
  12 + type="datetime"
  13 + :placeholder="$t('editFeeRule.maxTimePlaceholder')"
  14 + value-format="yyyy-MM-dd HH:mm:ss"
  15 + ></el-date-picker>
  16 + </el-form-item>
  17 + <el-form-item :label="$t('editFeeRule.curYearMonth')" prop="curYearMonth">
  18 + <el-date-picker
  19 + v-model="editFeeRuleInfo.curYearMonth"
  20 + type="date"
  21 + :placeholder="$t('editFeeRule.curYearMonthPlaceholder')"
  22 + value-format="yyyy-MM-dd"
  23 + @change="validateCurYearMonth"
  24 + ></el-date-picker>
  25 + </el-form-item>
  26 + </el-form>
  27 + <span slot="footer" class="dialog-footer">
  28 + <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
  29 + <el-button type="primary" @click="_doEidtFee">{{ $t('common.submit') }}</el-button>
  30 + </span>
  31 + </el-dialog>
  32 +</template>
  33 +
  34 +<script>
  35 +import { updatePayFeeRule } from '@/api/fee/editFeeRuleApi'
  36 +import { getCommunityId } from '@/api/community/communityApi'
  37 +
  38 +export default {
  39 + name: 'EditFeeRule',
  40 + data() {
  41 + return {
  42 + visible: false,
  43 + editFeeRuleInfo: {
  44 + ruleId: '',
  45 + maxTime: '',
  46 + curYearMonth: '',
  47 + oldCurYearMonth: ''
  48 + }
  49 + }
  50 + },
  51 + methods: {
  52 + open(fee) {
  53 + this.editFeeRuleInfo = {
  54 + ruleId: fee.ruleId,
  55 + maxTime: fee.maxTime,
  56 + curYearMonth: fee.curYearMonth,
  57 + oldCurYearMonth: fee.curYearMonth
  58 + }
  59 + this.visible = true
  60 + },
  61 + handleClose() {
  62 + this.visible = false
  63 + this.clearEditFeeRuleInfoData()
  64 + },
  65 + validateCurYearMonth(value) {
  66 + const start = new Date(this.editFeeRuleInfo.oldCurYearMonth)
  67 + const end = new Date(value)
  68 + if (start >= end) {
  69 + this.$message.error(this.$t('editFeeRule.dateError', { date: this.editFeeRuleInfo.oldCurYearMonth }))
  70 + this.editFeeRuleInfo.curYearMonth = ''
  71 + }
  72 + },
  73 + editFeeRuleValidate() {
  74 + if (!this.editFeeRuleInfo.maxTime) {
  75 + this.$message.error(this.$t('editFeeRule.maxTimeRequired'))
  76 + return false
  77 + }
  78 + if (!this.editFeeRuleInfo.curYearMonth) {
  79 + this.$message.error(this.$t('editFeeRule.curYearMonthRequired'))
  80 + return false
  81 + }
  82 + return true
  83 + },
  84 + async _doEidtFee() {
  85 + if (!this.editFeeRuleValidate()) return
  86 +
  87 + this.editFeeRuleInfo.communityId = getCommunityId()
  88 +
  89 + try {
  90 + const res = await updatePayFeeRule(this.editFeeRuleInfo)
  91 + if (res.code === 0) {
  92 + this.$message.success(this.$t('common.operateSuccess'))
  93 + this.$emit('success')
  94 + this.handleClose()
  95 + } else {
  96 + this.$message.error(res.msg)
  97 + }
  98 + } catch (error) {
  99 + console.error('请求失败:', error)
  100 + this.$message.error(this.$t('common.operateFail'))
  101 + }
  102 + },
  103 + clearEditFeeRuleInfoData() {
  104 + this.editFeeRuleInfo = {
  105 + ruleId: '',
  106 + maxTime: '',
  107 + curYearMonth: '',
  108 + oldCurYearMonth: ''
  109 + }
  110 + }
  111 + }
  112 +}
  113 +</script>
0 \ No newline at end of file 114 \ No newline at end of file
src/components/fee/editFeeRuleDemo.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-button @click="openModal">{{ $t('editFeeRuleDemo.openModal') }}</el-button>
  4 + <edit-fee-rule ref="editFeeRule" @success="handleSuccess"></edit-fee-rule>
  5 + </div>
  6 +</template>
  7 +
  8 +<script>
  9 +import EditFeeRule from './editFeeRule'
  10 +
  11 +export default {
  12 + name: 'EditFeeRuleDemo',
  13 + components: {
  14 + EditFeeRule
  15 + },
  16 + methods: {
  17 + openModal() {
  18 + this.$refs.editFeeRule.open({
  19 + ruleId: '123',
  20 + maxTime: '2023-12-31 23:59:59',
  21 + curYearMonth: '2023-01-01'
  22 + })
  23 + },
  24 + handleSuccess() {
  25 + this.$message.success(this.$t('editFeeRuleDemo.successMessage'))
  26 + }
  27 + }
  28 +}
  29 +</script>
0 \ No newline at end of file 30 \ No newline at end of file
src/components/fee/exportFeeImportExcel.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('exportFeeImportExcel.title')"
  4 + :visible.sync="visible"
  5 + width="70%"
  6 + :before-close="handleClose"
  7 + >
  8 + <el-form label-width="120px">
  9 + <el-form-item :label="$t('exportFeeImportExcel.floor')">
  10 + <div>
  11 + <el-checkbox
  12 + v-model="isFloorAll"
  13 + @change="toggleAllFloors"
  14 + >{{ $t('exportFeeImportExcel.all') }}</el-checkbox>
  15 + <el-checkbox
  16 + v-for="item in floors"
  17 + :key="item.floorId"
  18 + v-model="selectedFloorIds"
  19 + :label="item.floorId"
  20 + @change="handleFloorChange"
  21 + class="margin-left"
  22 + >{{ item.floorName }}</el-checkbox>
  23 + </div>
  24 + </el-form-item>
  25 +
  26 + <el-form-item :label="$t('exportFeeImportExcel.feeItem')">
  27 + <div>
  28 + <el-checkbox
  29 + v-model="isConfigAll"
  30 + @change="toggleAllConfigs"
  31 + >{{ $t('exportFeeImportExcel.all') }}</el-checkbox>
  32 + <el-checkbox
  33 + v-for="item in configs"
  34 + :key="item.configId"
  35 + v-model="selectedConfigIds"
  36 + :label="item.configId"
  37 + @change="handleConfigChange"
  38 + class="margin-left"
  39 + >{{ item.feeName }}</el-checkbox>
  40 + </div>
  41 + </el-form-item>
  42 + </el-form>
  43 +
  44 + <span slot="footer" class="dialog-footer">
  45 + <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
  46 + <el-button type="primary" @click="handleExport">{{ $t('common.export') }}</el-button>
  47 + </span>
  48 + </el-dialog>
  49 +</template>
  50 +
  51 +<script>
  52 +import { exportData, listFeeConfigs, queryFloors } from '@/api/fee/exportFeeImportExcelApi'
  53 +import { getCommunityId } from '@/api/community/communityApi'
  54 +
  55 +export default {
  56 + name: 'ExportFeeImportExcel',
  57 + data() {
  58 + return {
  59 + visible: false,
  60 + isFloorAll: true,
  61 + isConfigAll: true,
  62 + selectedFloorIds: [],
  63 + selectedConfigIds: [],
  64 + floors: [],
  65 + configs: []
  66 + }
  67 + },
  68 + computed: {
  69 + communityId() {
  70 + return getCommunityId()
  71 + }
  72 + },
  73 + methods: {
  74 + open() {
  75 + this.visible = true
  76 + this.loadFloors()
  77 + this.loadConfigs()
  78 + },
  79 +
  80 + loadFloors() {
  81 + queryFloors({
  82 + page: 1,
  83 + row: 150,
  84 + communityId: this.communityId
  85 + }).then(response => {
  86 + this.floors = response.data.apiFloorDataVoList
  87 + this.selectedFloorIds = this.floors.map(item => item.floorId)
  88 + })
  89 + },
  90 +
  91 + loadConfigs() {
  92 + listFeeConfigs({
  93 + page: 1,
  94 + row: 100,
  95 + communityId: this.communityId,
  96 + isDefault: 'F'
  97 + }).then(response => {
  98 + this.configs = response.data.feeConfigs
  99 + this.selectedConfigIds = this.configs.map(item => item.configId)
  100 + })
  101 + },
  102 +
  103 + toggleAllFloors() {
  104 + this.selectedFloorIds = this.isFloorAll
  105 + ? this.floors.map(item => item.floorId)
  106 + : []
  107 + },
  108 +
  109 + toggleAllConfigs() {
  110 + this.selectedConfigIds = this.isConfigAll
  111 + ? this.configs.map(item => item.configId)
  112 + : []
  113 + },
  114 +
  115 + handleFloorChange() {
  116 + this.isFloorAll = this.selectedFloorIds.length === this.floors.length
  117 + },
  118 +
  119 + handleConfigChange() {
  120 + this.isConfigAll = this.selectedConfigIds.length === this.configs.length
  121 + },
  122 +
  123 + handleExport() {
  124 + const params = {
  125 + floorIds: this.selectedFloorIds.join(','),
  126 + configIds: this.selectedConfigIds.join(','),
  127 + communityId: this.communityId,
  128 + type: '1001',
  129 + pagePath: 'exportCreateFeeTemplate'
  130 + }
  131 +
  132 + exportData(params).then(response => {
  133 + this.$message.success(response.data.msg)
  134 + if (response.data.code === 0) {
  135 + this.handleClose()
  136 + this.$router.push('/pages/property/downloadTempFile?tab=下载中心')
  137 + }
  138 + }).catch(error => {
  139 + this.$message.error(error.message)
  140 + })
  141 + },
  142 +
  143 + handleClose() {
  144 + this.visible = false
  145 + this.reset()
  146 + },
  147 +
  148 + reset() {
  149 + this.isFloorAll = true
  150 + this.isConfigAll = true
  151 + this.selectedFloorIds = []
  152 + this.selectedConfigIds = []
  153 + }
  154 + }
  155 +}
  156 +</script>
  157 +
  158 +<style scoped>
  159 +.margin-left {
  160 + margin-left: 15px;
  161 +}
  162 +</style>
0 \ No newline at end of file 163 \ No newline at end of file
src/components/fee/exportFeeImportExcelDemo.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-button @click="openModal">{{ $t('exportFeeImportExcelDemo.openModal') }}</el-button>
  4 + <export-fee-import-excel ref="exportFeeImportExcel"></export-fee-import-excel>
  5 + </div>
  6 +</template>
  7 +
  8 +<script>
  9 +import ExportFeeImportExcel from './exportFeeImportExcel'
  10 +
  11 +export default {
  12 + name: 'ExportFeeImportExcelDemo',
  13 + components: {
  14 + ExportFeeImportExcel
  15 + },
  16 + methods: {
  17 + openModal() {
  18 + this.$refs.exportFeeImportExcel.open()
  19 + }
  20 + }
  21 +}
  22 +</script>
0 \ No newline at end of file 23 \ No newline at end of file
src/components/fee/feeDetailFeeRule.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-table :data="feeDetailFeeRuleInfo.rules" border style="width: 100%">
  4 + <el-table-column prop="ruleId" :label="$t('feeDetailFeeRule.ruleId')" align="center"></el-table-column>
  5 + <el-table-column :label="$t('feeDetailFeeRule.feeItem')" align="center">
  6 + <template slot-scope="scope">
  7 + {{ scope.row.feeTypeCdName }}>{{ scope.row.feeName }}
  8 + </template>
  9 + </el-table-column>
  10 + <el-table-column prop="feeFlagName" :label="$t('feeDetailFeeRule.feeFlag')" align="center"></el-table-column>
  11 + <el-table-column prop="startTime" :label="$t('feeDetailFeeRule.createTime')" align="center"></el-table-column>
  12 + <el-table-column :label="$t('feeDetailFeeRule.validPeriod')" align="center">
  13 + <template slot-scope="scope">
  14 + {{ scope.row.endTime }}~{{ scope.row.maxTime }}
  15 + </template>
  16 + </el-table-column>
  17 + <el-table-column prop="computingFormulaName" :label="$t('feeDetailFeeRule.formula')" align="center"></el-table-column>
  18 + <el-table-column :label="$t('feeDetailFeeRule.price')" align="center">
  19 + <template slot-scope="scope">
  20 + {{ scope.row.computingFormula === '2002' ? '-' : scope.row.squarePrice }}
  21 + </template>
  22 + </el-table-column>
  23 + <el-table-column prop="additionalAmount" :label="$t('feeDetailFeeRule.additionalFee')" align="center"></el-table-column>
  24 + <el-table-column :label="$t('feeDetailFeeRule.status')" align="center">
  25 + <template slot-scope="scope">
  26 + {{ scope.row.state === '2008001' ? $t('common.valid') : $t('common.invalid') }}
  27 + </template>
  28 + </el-table-column>
  29 + <el-table-column prop="curYearMonth" :label="$t('feeDetailFeeRule.billDay')" align="center"></el-table-column>
  30 + <el-table-column :label="$t('feeDetailFeeRule.billCycle')" align="center">
  31 + <template>按月</template>
  32 + </el-table-column>
  33 + <el-table-column :label="$t('common.operation')" align="center" v-if="hasPrivilege">
  34 + <template slot-scope="scope">
  35 + <el-button
  36 + v-if="hasPrivilege('502020090427190001')"
  37 + type="text"
  38 + size="small"
  39 + @click="_updateFeeRule(scope.row)"
  40 + >
  41 + {{ $t('common.edit') }}
  42 + </el-button>
  43 + <el-button
  44 + v-if="hasPrivilege('502021070488970005')"
  45 + type="text"
  46 + size="small"
  47 + @click="_finishFeeRule(scope.row)"
  48 + >
  49 + {{ $t('common.manualFinish') }}
  50 + </el-button>
  51 + <el-button
  52 + v-if="hasPrivilege('502020090604200029')"
  53 + type="text"
  54 + size="small"
  55 + @click="_deleteFeeRule(scope.row)"
  56 + >
  57 + {{ $t('common.cancel') }}
  58 + </el-button>
  59 + </template>
  60 + </el-table-column>
  61 + </el-table>
  62 +
  63 + <el-pagination
  64 + @size-change="handleSizeChange"
  65 + @current-change="handleCurrentChange"
  66 + :current-page="currentPage"
  67 + :page-sizes="[10, 20, 30, 50]"
  68 + :page-size="pageSize"
  69 + layout="total, sizes, prev, pager, next, jumper"
  70 + :total="total"
  71 + ></el-pagination>
  72 +
  73 + <edit-fee-rule ref="editFeeRule" @success="loadData"></edit-fee-rule>
  74 + <finish-fee-rule ref="finishFeeRule" @success="loadData"></finish-fee-rule>
  75 + <delete-fee ref="deleteFee" @success="loadData"></delete-fee>
  76 + </div>
  77 +</template>
  78 +
  79 +<script>
  80 +import { listPayFeeRule } from '@/api/fee/feeDetailFeeRuleApi'
  81 +import EditFeeRule from './editFeeRule'
  82 +import FinishFeeRule from './finishFeeRule'
  83 +import DeleteFee from './deleteFee'
  84 +import { getCommunityId } from '@/api/community/communityApi'
  85 +
  86 +export default {
  87 + name: 'FeeDetailFeeRule',
  88 + components: {
  89 + EditFeeRule,
  90 + FinishFeeRule,
  91 + DeleteFee
  92 + },
  93 + props: {
  94 + feeId: {
  95 + type: String,
  96 + default: ''
  97 + },
  98 + roomId: {
  99 + type: String,
  100 + default: ''
  101 + }
  102 + },
  103 + data() {
  104 + return {
  105 + feeDetailFeeRuleInfo: {
  106 + rules: [],
  107 + feeId: '',
  108 + roomId: ''
  109 + },
  110 + currentPage: 1,
  111 + pageSize: 10,
  112 + total: 0
  113 + }
  114 + },
  115 + computed: {
  116 + },
  117 + methods: {
  118 + async loadData() {
  119 + const params = {
  120 + communityId: getCommunityId(),
  121 + feeId: this.feeDetailFeeRuleInfo.feeId,
  122 + payerObjId: this.feeDetailFeeRuleInfo.roomId,
  123 + detailId: '-1',
  124 + page: this.currentPage,
  125 + row: this.pageSize
  126 + }
  127 +
  128 + try {
  129 + const res = await listPayFeeRule(params)
  130 + if (res.code === 0) {
  131 + this.feeDetailFeeRuleInfo.rules = res.data
  132 + this.total = res.records
  133 + } else {
  134 + this.$message.error(res.msg)
  135 + }
  136 + } catch (error) {
  137 + console.error('请求失败:', error)
  138 + }
  139 + },
  140 + handleSizeChange(val) {
  141 + this.pageSize = val
  142 + this.loadData()
  143 + },
  144 + handleCurrentChange(val) {
  145 + this.currentPage = val
  146 + this.loadData()
  147 + },
  148 + _deleteFeeRule(fee) {
  149 + this.$refs.deleteFee.open(fee)
  150 + },
  151 + _updateFeeRule(fee) {
  152 + this.$refs.editFeeRule.open(fee)
  153 + },
  154 + _finishFeeRule(fee) {
  155 + this.$refs.finishFeeRule.open(fee)
  156 + },
  157 + open(params) {
  158 + // 这个方法用于接收参数并初始化组件
  159 + if (params.feeId) {
  160 + this.feeDetailFeeRuleInfo.feeId = params.feeId
  161 + }
  162 + if (params.roomId) {
  163 + this.feeDetailFeeRuleInfo.roomId = params.roomId
  164 + }
  165 + this.loadData()
  166 + }
  167 + },
  168 + watch: {
  169 + feeId(newVal) {
  170 + this.feeDetailFeeRuleInfo.feeId = newVal
  171 + this.loadData()
  172 + },
  173 + roomId(newVal) {
  174 + this.feeDetailFeeRuleInfo.roomId = newVal
  175 + this.loadData()
  176 + }
  177 + }
  178 +}
  179 +</script>
0 \ No newline at end of file 180 \ No newline at end of file
src/components/fee/feeDetailFeeRuleDemo.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-button @click="switchData">{{ $t('feeDetailFeeRuleDemo.switchData') }}</el-button>
  4 + <fee-detail-fee-rule ref="feeDetailFeeRule"></fee-detail-fee-rule>
  5 + </div>
  6 +</template>
  7 +
  8 +<script>
  9 +import FeeDetailFeeRule from './feeDetailFeeRule'
  10 +
  11 +export default {
  12 + name: 'FeeDetailFeeRuleDemo',
  13 + components: {
  14 + FeeDetailFeeRule
  15 + },
  16 + methods: {
  17 + switchData() {
  18 + this.$refs.feeDetailFeeRule.loadData({
  19 + feeId: '123',
  20 + roomId: '456'
  21 + })
  22 + }
  23 + }
  24 +}
  25 +</script>
0 \ No newline at end of file 26 \ No newline at end of file
src/components/fee/feeDetailRuleBill.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-table :data="feeDetailRuleBillInfo.bills" border style="width: 100%">
  4 + <el-table-column prop="billName" :label="$t('feeDetailRuleBill.billName')" align="center"></el-table-column>
  5 + <el-table-column :label="$t('feeDetailRuleBill.feeItem')" align="center">
  6 + <template slot-scope="scope">
  7 + {{ scope.row.feeTypeCdName }}>{{ scope.row.feeName }}
  8 + </template>
  9 + </el-table-column>
  10 + <el-table-column :label="$t('feeDetailRuleBill.receivablePeriod')" align="center">
  11 + <template slot-scope="scope">
  12 + {{ scope.row.endTime }}~{{ scope.row.deadlineTime }}
  13 + </template>
  14 + </el-table-column>
  15 + <el-table-column prop="feeTotalPrice" :label="$t('feeDetailRuleBill.receivableAmount')" align="center"></el-table-column>
  16 + <el-table-column prop="ruleId" :label="$t('feeDetailRuleBill.ruleId')" align="center"></el-table-column>
  17 + <el-table-column prop="feeId" :label="$t('feeDetailRuleBill.feeId')" align="center"></el-table-column>
  18 + <el-table-column prop="stateName" :label="$t('feeDetailRuleBill.status')" align="center"></el-table-column>
  19 + <el-table-column :label="$t('feeDetailRuleBill.description')" align="center">
  20 + <template slot-scope="scope">
  21 + <div>{{ $t('feeDetailRuleBill.price') }}: {{ scope.row.squarePrice }}</div>
  22 + <div>{{ $t('feeDetailRuleBill.fixedFee') }}: {{ scope.row.additionalAmount }}</div>
  23 + </template>
  24 + </el-table-column>
  25 + <el-table-column :label="$t('common.operation')" align="center">
  26 + <template slot-scope="scope">
  27 + <el-button type="text" size="small">
  28 + <a :href="'/#/pages/fee/feeDetail?feeId=' + scope.row.feeId" target="_blank">
  29 + {{ $t('common.detail') }}
  30 + </a>
  31 + </el-button>
  32 + </template>
  33 + </el-table-column>
  34 + </el-table>
  35 +
  36 + <el-pagination
  37 + @size-change="handleSizeChange"
  38 + @current-change="handleCurrentChange"
  39 + :current-page="currentPage"
  40 + :page-sizes="[10, 20, 30, 50]"
  41 + :page-size="pageSize"
  42 + layout="total, sizes, prev, pager, next, jumper"
  43 + :total="total"
  44 + ></el-pagination>
  45 + </div>
  46 +</template>
  47 +
  48 +<script>
  49 +import { listPayFeeRuleBill } from '@/api/fee/feeDetailRuleBillApi'
  50 +import { getCommunityId } from '@/api/community/communityApi'
  51 +
  52 +export default {
  53 + name: 'FeeDetailRuleBill',
  54 + props: {
  55 + feeId: {
  56 + type: String,
  57 + default: ''
  58 + },
  59 + roomId: {
  60 + type: String,
  61 + default: ''
  62 + }
  63 + },
  64 + data() {
  65 + return {
  66 + feeDetailRuleBillInfo: {
  67 + bills: [],
  68 + feeId: '',
  69 + roomId: ''
  70 + },
  71 + currentPage: 1,
  72 + pageSize: 10,
  73 + total: 0
  74 + }
  75 + },
  76 + methods: {
  77 + async loadData() {
  78 + const params = {
  79 + communityId: getCommunityId(),
  80 + feeId: this.feeDetailRuleBillInfo.feeId,
  81 + payerObjId: this.feeDetailRuleBillInfo.roomId,
  82 + page: this.currentPage,
  83 + row: this.pageSize
  84 + }
  85 +
  86 + try {
  87 + const res = await listPayFeeRuleBill(params)
  88 + if (res.code === 0) {
  89 + this.feeDetailRuleBillInfo.bills = res.data
  90 + this.total = res.records
  91 + } else {
  92 + this.$message.error(res.msg)
  93 + }
  94 + } catch (error) {
  95 + console.error('请求失败:', error)
  96 + }
  97 + },
  98 + handleSizeChange(val) {
  99 + this.pageSize = val
  100 + this.loadData()
  101 + },
  102 + handleCurrentChange(val) {
  103 + this.currentPage = val
  104 + this.loadData()
  105 + },
  106 + open(params) {
  107 + // 这个方法用于接收参数并初始化组件
  108 + if (params.feeId) {
  109 + this.feeDetailRuleBillInfo.feeId = params.feeId
  110 + }
  111 + if (params.roomId) {
  112 + this.feeDetailRuleBillInfo.roomId = params.roomId
  113 + }
  114 + this.loadData()
  115 + }
  116 + },
  117 + watch: {
  118 + feeId(newVal) {
  119 + this.feeDetailRuleBillInfo.feeId = newVal
  120 + this.loadData()
  121 + },
  122 + roomId(newVal) {
  123 + this.feeDetailRuleBillInfo.roomId = newVal
  124 + this.loadData()
  125 + }
  126 + }
  127 +}
  128 +</script>
0 \ No newline at end of file 129 \ No newline at end of file
src/components/fee/feeDetailRuleBillDemo.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-button @click="switchData">{{ $t('feeDetailRuleBillDemo.switchData') }}</el-button>
  4 + <fee-detail-rule-bill ref="feeDetailRuleBill"></fee-detail-rule-bill>
  5 + </div>
  6 +</template>
  7 +
  8 +<script>
  9 +import FeeDetailRuleBill from './feeDetailRuleBill'
  10 +
  11 +export default {
  12 + name: 'FeeDetailRuleBillDemo',
  13 + components: {
  14 + FeeDetailRuleBill
  15 + },
  16 + methods: {
  17 + switchData() {
  18 + this.$refs.feeDetailRuleBill.loadData({
  19 + feeId: '123',
  20 + roomId: '456'
  21 + })
  22 + }
  23 + }
  24 +}
  25 +</script>
0 \ No newline at end of file 26 \ No newline at end of file
src/components/fee/finishFeeRule.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('finishFeeRule.title')"
  4 + :visible.sync="visible"
  5 + width="30%"
  6 + :before-close="handleClose"
  7 + >
  8 + <p>{{ $t('finishFeeRule.confirmMessage') }}</p>
  9 + <span slot="footer" class="dialog-footer">
  10 + <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
  11 + <el-button type="primary" @click="finishFeeRule">{{ $t('common.confirm') }}</el-button>
  12 + </span>
  13 + </el-dialog>
  14 +</template>
  15 +
  16 +<script>
  17 +import { updatePayFeeRule } from '@/api/fee/finishFeeRuleApi'
  18 +import { getCommunityId } from '@/api/community/communityApi'
  19 +
  20 +export default {
  21 + name: 'FinishFeeRule',
  22 + data() {
  23 + return {
  24 + visible: false,
  25 + finishFeeRuleInfo: {}
  26 + }
  27 + },
  28 + methods: {
  29 + open(params) {
  30 + this.finishFeeRuleInfo = params
  31 + this.visible = true
  32 + },
  33 + handleClose() {
  34 + this.visible = false
  35 + },
  36 + async finishFeeRule() {
  37 + const data = {
  38 + ruleId: this.finishFeeRuleInfo.ruleId,
  39 + state: '2009001',
  40 + communityId: getCommunityId()
  41 + }
  42 +
  43 + try {
  44 + const res = await updatePayFeeRule(data)
  45 + if (res.code === 0) {
  46 + this.$message.success(this.$t('common.operateSuccess'))
  47 + this.$emit('success')
  48 + this.handleClose()
  49 + } else {
  50 + this.$message.error(res.msg)
  51 + }
  52 + } catch (error) {
  53 + console.error('请求失败:', error)
  54 + this.$message.error(this.$t('common.operateFail'))
  55 + }
  56 + }
  57 + }
  58 +}
  59 +</script>
0 \ No newline at end of file 60 \ No newline at end of file
src/components/fee/inputSearchRoom.vue 0 → 100644
  1 +<template>
  2 + <div
  3 + class="vc-input-search text-left"
  4 + @mouseleave="doInputSearchRoomClose"
  5 + v-if="rooms && rooms.length>0"
  6 + >
  7 + <div class="close">
  8 + <i class="el-icon-close" @click="doInputSearchRoomClose"></i>
  9 + </div>
  10 + <div
  11 + class="padding-left-sm padding-top-sm"
  12 + style="cursor:pointer;"
  13 + v-for="(item,index) in rooms"
  14 + :key="index"
  15 + @click="inputSearchRoomChooseRoom(item)"
  16 + >
  17 + <span>{{item.floorNum}}-{{item.unitNum}}-{{item.roomNum}}</span>
  18 + </div>
  19 + </div>
  20 +</template>
  21 +
  22 +<script>
  23 +import { queryRooms } from '@/api/fee/inputSearchRoomApi'
  24 +import { getCommunityId } from '@/api/community/communityApi'
  25 +
  26 +export default {
  27 + name: 'InputSearchRoom',
  28 + data() {
  29 + return {
  30 + rooms: [],
  31 + callComponent: '',
  32 + communityId: ''
  33 + }
  34 + },
  35 + created() {
  36 + this.communityId = getCommunityId()
  37 + this.$on('searchRoom', this.handleSearchRoom)
  38 + this.$on('close', this.handleClose)
  39 + },
  40 + methods: {
  41 + handleSearchRoom(param) {
  42 + if (!param.roomName) return
  43 + this.loadRoomInfo(param.roomName)
  44 + this.callComponent = param.callComponent
  45 + },
  46 + handleClose() {
  47 + this.rooms = []
  48 + },
  49 + async loadRoomInfo(roomName) {
  50 + try {
  51 + const res = await queryRooms({
  52 + page: 1,
  53 + row: 10,
  54 + flag: 1,
  55 + roomNum: roomName,
  56 + communityId: this.communityId
  57 + })
  58 + this.rooms = res.rooms
  59 + if (res.rooms.length <= 0) {
  60 + this.$message.warning(this.$t('inputSearchRoom.noRoomFound'))
  61 + }
  62 + } catch (error) {
  63 + console.error('请求失败:', error)
  64 + }
  65 + },
  66 + inputSearchRoomChooseRoom(room) {
  67 + this.$emit(this.callComponent, 'notifyRoom', room)
  68 + this.rooms = []
  69 + },
  70 + doInputSearchRoomClose() {
  71 + this.rooms = []
  72 + }
  73 + }
  74 +}
  75 +</script>
  76 +
  77 +<style scoped>
  78 +.vc-input-search {
  79 + position: absolute;
  80 + z-index: 999;
  81 + background: #fff;
  82 + border: 1px solid #dcdfe6;
  83 + border-radius: 4px;
  84 + box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
  85 + padding: 10px;
  86 +}
  87 +.close {
  88 + text-align: right;
  89 + cursor: pointer;
  90 +}
  91 +.padding-left-sm {
  92 + padding-left: 10px;
  93 +}
  94 +.padding-top-sm {
  95 + padding-top: 5px;
  96 +}
  97 +</style>
0 \ No newline at end of file 98 \ No newline at end of file
src/components/fee/inputSearchRoomByOwner.vue 0 → 100644
  1 +<template>
  2 + <div
  3 + class="vc-input-search text-left"
  4 + v-if="rooms && rooms.length>0"
  5 + >
  6 + <div class="close">
  7 + <i class="el-icon-close" @click="doInputSearchRoomByOwnerClose"></i>
  8 + </div>
  9 + <div
  10 + class="padding-left-sm padding-top-sm"
  11 + style="cursor:pointer;"
  12 + v-for="(item,index) in rooms"
  13 + :key="index"
  14 + @click="inputSearchRoomChooseRoomByOwner(item)"
  15 + >
  16 + <span>{{item.floorNum}}-{{item.unitNum}}-{{item.roomNum}}({{item.ownerName}})</span>
  17 + </div>
  18 + </div>
  19 +</template>
  20 +
  21 +<script>
  22 +import { queryRoomsByOwner } from '@/api/fee/inputSearchRoomByOwnerApi'
  23 +import { getCommunityId } from '@/api/community/communityApi'
  24 +
  25 +export default {
  26 + name: 'InputSearchRoomByOwner',
  27 + data() {
  28 + return {
  29 + rooms: [],
  30 + callComponent: '',
  31 + communityId: ''
  32 + }
  33 + },
  34 + created() {
  35 + this.communityId = getCommunityId()
  36 + this.$on('searchRoom', this.handleSearchRoom)
  37 + this.$on('close', this.handleClose)
  38 + },
  39 + methods: {
  40 + handleSearchRoom(param) {
  41 + if (!param.ownerName) return
  42 + this.loadRoomByOwnerInfo(param.ownerName)
  43 + this.callComponent = param.callComponent
  44 + },
  45 + handleClose() {
  46 + this.rooms = []
  47 + },
  48 + async loadRoomByOwnerInfo(ownerName) {
  49 + try {
  50 + const res = await queryRoomsByOwner({
  51 + page: 1,
  52 + row: 10,
  53 + ownerNameLike: ownerName,
  54 + communityId: this.communityId
  55 + })
  56 + this.rooms = res.rooms
  57 + } catch (error) {
  58 + console.error('请求失败:', error)
  59 + }
  60 + },
  61 + inputSearchRoomChooseRoomByOwner(room) {
  62 + this.$emit(this.callComponent, 'notifyRoomByOwner', room)
  63 + this.rooms = []
  64 + },
  65 + doInputSearchRoomByOwnerClose() {
  66 + this.rooms = []
  67 + }
  68 + }
  69 +}
  70 +</script>
  71 +
  72 +<style scoped>
  73 +.vc-input-search {
  74 + position: absolute;
  75 + z-index: 999;
  76 + background: #fff;
  77 + border: 1px solid #dcdfe6;
  78 + border-radius: 4px;
  79 + box-shadow: 0 2px 12px 0 rgba(0,0,0,.1);
  80 + padding: 10px;
  81 +}
  82 +.close {
  83 + text-align: right;
  84 + cursor: pointer;
  85 +}
  86 +.padding-left-sm {
  87 + padding-left: 10px;
  88 +}
  89 +.padding-top-sm {
  90 + padding-top: 5px;
  91 +}
  92 +</style>
0 \ No newline at end of file 93 \ No newline at end of file
src/components/fee/inputSearchRoomByOwnerDemo.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-input
  4 + v-model="ownerName"
  5 + :placeholder="$t('inputSearchRoomByOwnerDemo.searchPlaceholder')"
  6 + @input="handleSearch"
  7 + ></el-input>
  8 + <input-search-room-by-owner ref="inputSearchRoomByOwner"></input-search-room-by-owner>
  9 + </div>
  10 +</template>
  11 +
  12 +<script>
  13 +import InputSearchRoomByOwner from './inputSearchRoomByOwner'
  14 +
  15 +export default {
  16 + name: 'InputSearchRoomByOwnerDemo',
  17 + components: {
  18 + InputSearchRoomByOwner
  19 + },
  20 + data() {
  21 + return {
  22 + ownerName: ''
  23 + }
  24 + },
  25 + methods: {
  26 + handleSearch() {
  27 + this.$refs.inputSearchRoomByOwner.$emit('searchRoom', {
  28 + ownerName: this.ownerName,
  29 + callComponent: 'yourComponentName'
  30 + })
  31 + }
  32 + }
  33 +}
  34 +</script>
0 \ No newline at end of file 35 \ No newline at end of file
src/components/fee/inputSearchRoomDemo.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-input
  4 + v-model="roomName"
  5 + :placeholder="$t('inputSearchRoomDemo.searchPlaceholder')"
  6 + @input="handleSearch"
  7 + ></el-input>
  8 + <input-search-room ref="inputSearchRoom"></input-search-room>
  9 + </div>
  10 +</template>
  11 +
  12 +<script>
  13 +import InputSearchRoom from './inputSearchRoom'
  14 +
  15 +export default {
  16 + name: 'InputSearchRoomDemo',
  17 + components: {
  18 + InputSearchRoom
  19 + },
  20 + data() {
  21 + return {
  22 + roomName: ''
  23 + }
  24 + },
  25 + methods: {
  26 + handleSearch() {
  27 + this.$refs.inputSearchRoom.$emit('searchRoom', {
  28 + roomName: this.roomName,
  29 + callComponent: 'yourComponentName'
  30 + })
  31 + }
  32 + }
  33 +}
  34 +</script>
0 \ No newline at end of file 35 \ No newline at end of file
src/components/fee/payFeeDeposit.vue 0 → 100644
  1 +<template>
  2 + <el-card v-if="payFeeDepositInfo.fees.length > 0" class="deposit-card">
  3 + <div slot="header" class="clearfix">
  4 + <span>{{ $t('payFeeDeposit.title') }}</span>
  5 + <el-button type="primary" size="small" class="float-right" @click="_queryPayFeeDeposit">
  6 + <i class="el-icon-refresh"></i>
  7 + {{ $t('common.refresh') }}
  8 + </el-button>
  9 + </div>
  10 +
  11 + <el-table :data="payFeeDepositInfo.fees" border style="width: 100%" v-loading="loading">
  12 + <el-table-column prop="payerObjName" :label="$t('payFeeDeposit.payerObj')" align="center"></el-table-column>
  13 + <el-table-column prop="feeName" :label="$t('payFeeDeposit.feeItem')" align="center"></el-table-column>
  14 + <el-table-column :label="$t('payFeeDeposit.timePeriod')" align="center" width="220">
  15 + <template slot-scope="scope">
  16 + {{ scope.row.startTime }} ~ {{ scope.row.endTime }}
  17 + </template>
  18 + </el-table-column>
  19 + <el-table-column prop="receivedAmount" :label="$t('payFeeDeposit.amount')" align="center"></el-table-column>
  20 + <el-table-column prop="createTime" :label="$t('payFeeDeposit.payTime')" align="center"
  21 + width="180"></el-table-column>
  22 + <el-table-column :label="$t('common.operation')" align="center" width="120">
  23 + <template slot-scope="scope">
  24 + <el-button type="primary" size="mini" @click="_openRefundDeposit(scope.row)">
  25 + {{ $t('payFeeDeposit.refund') }}
  26 + </el-button>
  27 + </template>
  28 + </el-table-column>
  29 + </el-table>
  30 +
  31 + <refund-deposit-fee ref="refundDepositFee"></refund-deposit-fee>
  32 + </el-card>
  33 +</template>
  34 +
  35 +<script>
  36 +import { getCommunityId } from '@/api/community/communityApi'
  37 +import { queryFeeDeposit } from '@/api/fee/batchPayFeeOrderApi'
  38 +import RefundDepositFee from './refundDepositFee'
  39 +
  40 +export default {
  41 + name: 'PayFeeDeposit',
  42 + components: {
  43 + RefundDepositFee
  44 + },
  45 + data() {
  46 + return {
  47 + loading: false,
  48 + payFeeDepositInfo: {
  49 + fees: [],
  50 + payerObjId: '',
  51 + payerObjType: '',
  52 + ownerId: '',
  53 + communityId: ''
  54 + }
  55 + }
  56 + },
  57 + created() {
  58 + this.payFeeDepositInfo.communityId = getCommunityId()
  59 + },
  60 + methods: {
  61 + async _listFeeDeposit(page = 1, rows = 20) {
  62 + this.loading = true
  63 + try {
  64 + const params = {
  65 + page,
  66 + row: rows,
  67 + payerObjId: this.payFeeDepositInfo.payerObjId,
  68 + ownerId: this.payFeeDepositInfo.ownerId,
  69 + communityId: this.payFeeDepositInfo.communityId,
  70 + state: '1400'
  71 + }
  72 +
  73 + const res = await queryFeeDeposit(params)
  74 + if (res.code === 0) {
  75 + this.payFeeDepositInfo.fees = res.data || []
  76 + }
  77 + } catch (error) {
  78 + console.error('请求失败:', error)
  79 + } finally {
  80 + this.loading = false
  81 + }
  82 + },
  83 +
  84 + _queryPayFeeDeposit() {
  85 + this._listFeeDeposit()
  86 + },
  87 +
  88 + _openRefundDeposit(fee) {
  89 + this.$refs.refundDepositFee.open(fee)
  90 + },
  91 +
  92 + open(params) {
  93 + this.payFeeDepositInfo = {
  94 + ...this.payFeeDepositInfo,
  95 + ...params
  96 + }
  97 + this._listFeeDeposit()
  98 + },
  99 +
  100 + refresh() {
  101 + this._listFeeDeposit()
  102 + }
  103 + }
  104 +}
  105 +</script>
  106 +
  107 +<style lang="scss" scoped>
  108 +.deposit-card {
  109 + margin-bottom: 20px;
  110 +}
  111 +</style>
0 \ No newline at end of file 112 \ No newline at end of file
src/components/fee/payFeeUserAccount.vue 0 → 100644
  1 +<template>
  2 + <el-card v-if="payFeeUserAccountInfo.accountList.length > 0" class="account-card">
  3 + <div slot="header" class="flex justify-between">
  4 + <span>{{ $t('payFeeUserAccount.title') }}</span>
  5 + <el-button type="primary" size="small" class="float-right" @click="_queryPayFeeUserAccount">
  6 + <i class="el-icon-refresh"></i>
  7 + {{ $t('common.refresh') }}
  8 + </el-button>
  9 + </div>
  10 +
  11 + <el-table :data="payFeeUserAccountInfo.accountList" border style="width: 100%" v-loading="loading">
  12 + <el-table-column width="55" align="center">
  13 + <template slot-scope="scope">
  14 + <el-radio v-model="payFeeUserAccountInfo.selectAccountIds" :label="scope.row.acctId"
  15 + @change="_computeFeeUserAmount(scope.row)"></el-radio>
  16 + </template>
  17 + </el-table-column>
  18 + <el-table-column prop="acctTypeName" :label="$t('payFeeUserAccount.accountType')"
  19 + align="center"></el-table-column>
  20 + <el-table-column prop="acctName" :label="$t('payFeeUserAccount.accountName')" align="center"></el-table-column>
  21 + <el-table-column :label="$t('payFeeUserAccount.accountAmount')" align="center">
  22 + <template slot-scope="scope">
  23 + {{ scope.row.amount }} {{ $t('payFeeUserAccount.yuan') }}
  24 + </template>
  25 + </el-table-column>
  26 + <el-table-column :label="$t('common.operation')" align="center" width="150">
  27 + <template slot-scope="scope">
  28 + <el-button type="primary" size="mini" @click="_openAddUserAmountModal(scope.row)">
  29 + <i class="el-icon-plus"></i>
  30 + {{ $t('payFeeUserAccount.preSave') }}
  31 + </el-button>
  32 + </template>
  33 + </el-table-column>
  34 + </el-table>
  35 + </el-card>
  36 +</template>
  37 +
  38 +<script>
  39 +import { getCommunityId } from '@/api/community/communityApi'
  40 +import { queryCommunityOwnerAccount } from '@/api/fee/batchPayFeeOrderApi'
  41 +
  42 +export default {
  43 + name: 'PayFeeUserAccount',
  44 + data() {
  45 + return {
  46 + loading: false,
  47 + payFeeUserAccountInfo: {
  48 + accountList: [],
  49 + feeId: '',
  50 + ownerId: '',
  51 + communityId: '',
  52 + quanAccount: false,
  53 + selectAccountIds: [],
  54 + integralAmount: '',
  55 + cashAmount: '',
  56 + couponAmount: ''
  57 + }
  58 + }
  59 + },
  60 + created() {
  61 + this.payFeeUserAccountInfo.communityId = getCommunityId()
  62 + },
  63 + methods: {
  64 + async _listUserAccount(page = 1, rows = 20) {
  65 + this.loading = true
  66 + try {
  67 + const params = {
  68 + page,
  69 + row: rows,
  70 + feeId: this.payFeeUserAccountInfo.feeId,
  71 + ownerId: this.payFeeUserAccountInfo.ownerId,
  72 + communityId: this.payFeeUserAccountInfo.communityId
  73 + }
  74 +
  75 + const res = await queryCommunityOwnerAccount(params)
  76 + if (res.code === 0) {
  77 + this.payFeeUserAccountInfo.accountList = res.data || []
  78 + }
  79 + } catch (error) {
  80 + console.error('请求失败:', error)
  81 + } finally {
  82 + this.loading = false
  83 + }
  84 + },
  85 +
  86 + _queryPayFeeUserAccount() {
  87 + this._listUserAccount()
  88 + },
  89 +
  90 + _openAddUserAmountModal(userAccount) {
  91 + window.open(`/#/pages/owner/ownerDetail?ownerId=${userAccount.objId}&currentTab=ownerDetailAccount`)
  92 + },
  93 +
  94 + _computeFeeUserAmount(acct) {
  95 + let _totalUserAmount = 0.0
  96 + let _selectAccount = []
  97 +
  98 + this.payFeeUserAccountInfo.accountList.forEach(item => {
  99 + if (acct.acctId === item.acctId && item.amount != 0) {
  100 + _totalUserAmount += parseFloat(item.amount)
  101 + _selectAccount.push(item)
  102 + this.payFeeUserAccountInfo.cashAmount = item.amount
  103 + }
  104 + })
  105 +
  106 + this.$emit('changeUserAmountPrice', {
  107 + totalUserAmount: _totalUserAmount,
  108 + accountList: this.payFeeUserAccountInfo.accountList,
  109 + integralAmount: 0,
  110 + cashAmount: this.payFeeUserAccountInfo.cashAmount,
  111 + couponAmount: 0,
  112 + selectAccount: _selectAccount
  113 + })
  114 + },
  115 +
  116 + open(params) {
  117 + this.payFeeUserAccountInfo = {
  118 + ...this.payFeeUserAccountInfo,
  119 + ...params
  120 + }
  121 + this._listUserAccount()
  122 + },
  123 +
  124 + refresh() {
  125 + this._listUserAccount()
  126 + },
  127 +
  128 + refreshAndChoose() {
  129 + this.payFeeUserAccountInfo.accountList = []
  130 + this.payFeeUserAccountInfo.selectAccountIds = []
  131 + this._listUserAccount()
  132 + setTimeout(() => {
  133 + this.payFeeUserAccountInfo.accountList.forEach(item => {
  134 + if (item.acctType === '2003') {
  135 + this.payFeeUserAccountInfo.selectAccountIds.push(item.acctId)
  136 + }
  137 + })
  138 + }, 2000)
  139 + },
  140 +
  141 + clear() {
  142 + this.payFeeUserAccountInfo.accountList = []
  143 + this.payFeeUserAccountInfo.selectAccountIds = []
  144 + }
  145 + }
  146 +}
  147 +</script>
  148 +
  149 +<style lang="scss" scoped>
  150 +.account-card {
  151 + margin-bottom: 20px;
  152 +}
  153 +</style>
0 \ No newline at end of file 154 \ No newline at end of file
src/components/fee/prestoreAccount.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('prestoreAccount.title')"
  4 + :visible.sync="dialogVisible"
  5 + width="50%"
  6 + >
  7 + <el-form :model="prestoreAccountInfo" label-width="120px">
  8 + <el-form-item :label="$t('prestoreAccount.accountType')" required>
  9 + <el-select
  10 + v-model="prestoreAccountInfo.acctType"
  11 + style="width: 100%"
  12 + >
  13 + <el-option
  14 + :label="$t('prestoreAccount.selectAccountType')"
  15 + value=""
  16 + disabled
  17 + ></el-option>
  18 + <el-option
  19 + v-for="(type,index) in prestoreAccountInfo.acctTypes"
  20 + :key="index"
  21 + :label="type.name"
  22 + :value="type.statusCd"
  23 + ></el-option>
  24 + </el-select>
  25 + </el-form-item>
  26 +
  27 + <el-form-item :label="$t('prestoreAccount.ownerPhone')" required>
  28 + <el-input
  29 + v-model="prestoreAccountInfo.tel"
  30 + :placeholder="$t('prestoreAccount.ownerPhonePlaceholder')"
  31 + @blur="_changeTel"
  32 + ></el-input>
  33 + </el-form-item>
  34 +
  35 + <el-form-item :label="$t('prestoreAccount.ownerName')" required>
  36 + <el-select
  37 + v-model="prestoreAccountInfo.ownerId"
  38 + style="width: 100%"
  39 + @change="_loadOwnerRooms"
  40 + >
  41 + <el-option
  42 + :label="$t('prestoreAccount.selectOwner')"
  43 + value=""
  44 + disabled
  45 + ></el-option>
  46 + <el-option
  47 + v-for="(owner,index) in prestoreAccountInfo.owners"
  48 + :key="index"
  49 + :label="owner.name"
  50 + :value="owner.ownerId"
  51 + ></el-option>
  52 + </el-select>
  53 + </el-form-item>
  54 +
  55 + <el-form-item
  56 + v-if="prestoreAccountInfo.acctType == '2004' || prestoreAccountInfo.acctType == '2005'"
  57 + :label="$t('prestoreAccount.deductionRoom')"
  58 + required
  59 + >
  60 + <el-select v-model="prestoreAccountInfo.roomId" style="width: 100%">
  61 + <el-option
  62 + :label="$t('prestoreAccount.selectRoom')"
  63 + value=""
  64 + disabled
  65 + ></el-option>
  66 + <el-option
  67 + v-for="(room,index) in prestoreAccountInfo.rooms"
  68 + :key="index"
  69 + :label="room.roomName"
  70 + :value="room.roomId"
  71 + ></el-option>
  72 + </el-select>
  73 + </el-form-item>
  74 +
  75 + <el-form-item :label="$t('prestoreAccount.prestoreAmount')" required>
  76 + <el-input
  77 + v-model="prestoreAccountInfo.amount"
  78 + :placeholder="$t('prestoreAccount.prestoreAmountPlaceholder')"
  79 + ></el-input>
  80 + </el-form-item>
  81 +
  82 + <el-form-item :label="$t('prestoreAccount.paymentMethod')" required>
  83 + <el-select v-model="prestoreAccountInfo.primeRate" style="width: 100%">
  84 + <el-option
  85 + :label="$t('prestoreAccount.selectPaymentMethod')"
  86 + value=""
  87 + disabled
  88 + ></el-option>
  89 + <el-option
  90 + v-for="(item,index) in prestoreAccountInfo.primeRates"
  91 + v-if="item.statusCd != '5' && item.statusCd != '6'"
  92 + :key="index"
  93 + :label="item.name"
  94 + :value="item.statusCd"
  95 + ></el-option>
  96 + </el-select>
  97 + </el-form-item>
  98 +
  99 + <el-form-item :label="$t('prestoreAccount.remark')">
  100 + <el-input
  101 + type="textarea"
  102 + :rows="3"
  103 + v-model="prestoreAccountInfo.remark"
  104 + :placeholder="$t('prestoreAccount.remarkPlaceholder')"
  105 + ></el-input>
  106 + </el-form-item>
  107 + </el-form>
  108 +
  109 + <span slot="footer" class="dialog-footer">
  110 + <el-button @click="dialogVisible = false">{{ $t('prestoreAccount.cancel') }}</el-button>
  111 + <el-button type="primary" @click="savePrestoreAccountInfo">{{ $t('prestoreAccount.save') }}</el-button>
  112 + </span>
  113 + </el-dialog>
  114 +</template>
  115 +
  116 +<script>
  117 +import { ownerPrestoreAccount, queryOwners, queryRoomsByOwner } from '@/api/fee/prestoreAccountApi'
  118 +import { getDict } from '@/api/community/communityApi'
  119 +import { getCommunityId } from '@/api/community/communityApi'
  120 +
  121 +export default {
  122 + name: 'PrestoreAccount',
  123 + data() {
  124 + return {
  125 + dialogVisible: false,
  126 + prestoreAccountInfo: {
  127 + tel: '',
  128 + ownerId: '',
  129 + owners: [],
  130 + amount: '',
  131 + remark: '',
  132 + acctTypes: [],
  133 + acctType: '2003',
  134 + primeRate: '',
  135 + primeRates: [],
  136 + rooms: [],
  137 + roomId: '',
  138 + },
  139 + communityId: ''
  140 + }
  141 + },
  142 + created() {
  143 + this.communityId = getCommunityId()
  144 + this._initPrimeRates()
  145 + },
  146 + methods: {
  147 + open(params) {
  148 + this.dialogVisible = true
  149 + this._initAcctTypes()
  150 +
  151 + if (params) {
  152 + this.prestoreAccountInfo.tel = params.tel || ''
  153 + this.prestoreAccountInfo.ownerId = params.ownerId || ''
  154 + this.prestoreAccountInfo.acctType = params.acctType || '2003'
  155 + this.prestoreAccountInfo.roomId = params.roomId || ''
  156 +
  157 + if (params.tel) {
  158 + this._changeTel()
  159 + this._loadOwnerRooms()
  160 + }
  161 + }
  162 + },
  163 + _initPrimeRates() {
  164 + getDict('pay_fee_detail', 'prime_rate').then(data => {
  165 + this.prestoreAccountInfo.primeRates = data
  166 + })
  167 + },
  168 + _initAcctTypes() {
  169 + getDict('account', 'acct_type').then(data => {
  170 + this.prestoreAccountInfo.acctTypes = data
  171 + })
  172 + },
  173 + prestoreAccountValidate() {
  174 + if (!this.prestoreAccountInfo.ownerId) {
  175 + this.$message.error(this.$t('prestoreAccount.validateOwner'))
  176 + return false
  177 + }
  178 + if (!this.prestoreAccountInfo.amount) {
  179 + this.$message.error(this.$t('prestoreAccount.validateAmount'))
  180 + return false
  181 + }
  182 + if (!this.prestoreAccountInfo.acctType) {
  183 + this.$message.error(this.$t('prestoreAccount.validateAccountType'))
  184 + return false
  185 + }
  186 + if (this.prestoreAccountInfo.remark && this.prestoreAccountInfo.remark.length > 200) {
  187 + this.$message.error(this.$t('prestoreAccount.validateRemark'))
  188 + return false
  189 + }
  190 + return true
  191 + },
  192 + savePrestoreAccountInfo() {
  193 + if (!this.prestoreAccountValidate()) return
  194 +
  195 + const params = {
  196 + ...this.prestoreAccountInfo,
  197 + communityId: this.communityId
  198 + }
  199 +
  200 + ownerPrestoreAccount(params).then(response => {
  201 + if (response.code === 0) {
  202 + this.$message.success(this.$t('prestoreAccount.saveSuccess'))
  203 + this.dialogVisible = false
  204 + this.clearPrestoreAccountInfo()
  205 + this.$emit('save-success')
  206 + } else {
  207 + this.$message.error(response.msg)
  208 + }
  209 + }).catch(error => {
  210 + console.error('请求失败:', error)
  211 + this.$message.error(this.$t('prestoreAccount.saveFailed'))
  212 + })
  213 + },
  214 + clearPrestoreAccountInfo() {
  215 + const primeRates = this.prestoreAccountInfo.primeRates
  216 + this.prestoreAccountInfo = {
  217 + tel: '',
  218 + ownerId: '',
  219 + owners: [],
  220 + amount: '',
  221 + remark: '',
  222 + acctTypes: [],
  223 + acctType: '2003',
  224 + primeRate: '',
  225 + primeRates: primeRates,
  226 + rooms: [],
  227 + roomId: '',
  228 + }
  229 + },
  230 + _changeTel() {
  231 + if (!this.prestoreAccountInfo.tel) return
  232 +
  233 + const params = {
  234 + communityId: this.communityId,
  235 + row: 50,
  236 + page: 1,
  237 + link: this.prestoreAccountInfo.tel,
  238 + ownerTypeCd: '1001'
  239 + }
  240 +
  241 + queryOwners(params).then(response => {
  242 + this.prestoreAccountInfo.owners = response.data
  243 + }).catch(error => {
  244 + console.error('请求失败:', error)
  245 + this.prestoreAccountInfo.owners = []
  246 + })
  247 + },
  248 + _loadOwnerRooms() {
  249 + if (!this.prestoreAccountInfo.ownerId) return
  250 +
  251 + const params = {
  252 + communityId: this.communityId,
  253 + row: 50,
  254 + page: 1,
  255 + ownerId: this.prestoreAccountInfo.ownerId,
  256 + }
  257 +
  258 + queryRoomsByOwner(params).then(response => {
  259 + this.prestoreAccountInfo.rooms = response.rooms
  260 + }).catch(error => {
  261 + console.error('请求失败:', error)
  262 + this.prestoreAccountInfo.rooms = []
  263 + })
  264 + }
  265 + }
  266 +}
  267 +</script>
0 \ No newline at end of file 268 \ No newline at end of file
src/components/fee/prestoreAccountDemo.vue 0 → 100644
  1 +<template>
  2 + <el-button @click="openModal">{{ $t('prestoreAccountDemo.openModal') }}</el-button>
  3 + <prestore-account ref="prestoreAccount"></prestore-account>
  4 +</template>
  5 +
  6 +<script>
  7 +import PrestoreAccount from './prestoreAccount'
  8 +
  9 +export default {
  10 + name: 'PrestoreAccountDemo',
  11 + components: {
  12 + PrestoreAccount
  13 + },
  14 + methods: {
  15 + openModal() {
  16 + this.$refs.prestoreAccount.open({
  17 + tel: '13800138000',
  18 + ownerId: '123',
  19 + acctType: '2003',
  20 + roomId: '456'
  21 + })
  22 + }
  23 + }
  24 +}
  25 +</script>
0 \ No newline at end of file 26 \ No newline at end of file
src/components/fee/refundDepositFee.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('refundDepositFee.title')"
  4 + :visible.sync="visible"
  5 + width="500px"
  6 + :before-close="handleClose"
  7 + >
  8 + <div class="dialog-content">
  9 + <p>{{ $t('refundDepositFee.confirmText') }}</p>
  10 + </div>
  11 + <span slot="footer" class="dialog-footer">
  12 + <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
  13 + <el-button type="primary" @click="refundDepositFee">{{ $t('common.confirm') }}</el-button>
  14 + </span>
  15 + </el-dialog>
  16 +</template>
  17 +
  18 +<script>
  19 +import { getCommunityId } from '@/api/community/communityApi'
  20 +import { refundFeeDeposit } from '@/api/fee/batchPayFeeOrderApi'
  21 +
  22 +export default {
  23 + name: 'RefundDepositFee',
  24 + data() {
  25 + return {
  26 + visible: false,
  27 + refundDepositFeeInfo: {}
  28 + }
  29 + },
  30 + methods: {
  31 + open(fee) {
  32 + this.refundDepositFeeInfo = { ...fee }
  33 + this.visible = true
  34 + },
  35 +
  36 + handleClose() {
  37 + this.visible = false
  38 + },
  39 +
  40 + async refundDepositFee() {
  41 + try {
  42 + const params = {
  43 + ...this.refundDepositFeeInfo,
  44 + communityId: getCommunityId()
  45 + }
  46 +
  47 + const res = await refundFeeDeposit(params)
  48 + if (res.code === 0) {
  49 + this.$message.success('退押金成功')
  50 + this.visible = false
  51 + this.$emit('success')
  52 + this.$emit('refresh')
  53 + } else {
  54 + this.$message.error(res.msg)
  55 + }
  56 + } catch (error) {
  57 + console.error('请求失败:', error)
  58 + this.$message.error('退押金失败')
  59 + }
  60 + }
  61 + }
  62 +}
  63 +</script>
  64 +
  65 +<style lang="scss" scoped>
  66 +.dialog-content {
  67 + padding: 20px;
  68 + text-align: center;
  69 + font-size: 16px;
  70 + line-height: 1.6;
  71 +}
  72 +</style>
0 \ No newline at end of file 73 \ No newline at end of file
src/components/fee/returnPayFee.vue
1 <template> 1 <template>
2 - <el-dialog  
3 - :title="$t('returnPayFee.refundTitle')" 2 + <el-dialog
  3 + :title="$t('returnPayFee.fillRefundReason')"
4 :visible.sync="visible" 4 :visible.sync="visible"
5 width="50%" 5 width="50%"
6 - @close="handleClose" 6 + center
7 > 7 >
8 - <el-form ref="form" :model="form" :rules="rules" label-width="150px">  
9 - <el-form-item :label="`${$t('returnPayFee.fee')}ID`">  
10 - <el-input v-model="form.detailId" readonly /> 8 + <el-form :model="returnFeeDetailInfo" label-width="120px">
  9 + <el-form-item :label="$t('returnPayFee.paymentId')">
  10 + <el-input v-model="returnFeeDetailInfo.detailId" readonly />
11 </el-form-item> 11 </el-form-item>
12 - <el-form-item :label="`${$t('returnPayFee.cycle')}(${$t('returnPayFee.month')})`">  
13 - <el-input v-model="form.cycles" readonly /> 12 +
  13 + <el-form-item :label="`${$t('returnPayFee.cycle')}(单位月)`">
  14 + <el-input v-model="returnFeeDetailInfo.cycles" readonly />
14 </el-form-item> 15 </el-form-item>
  16 +
15 <el-form-item :label="$t('returnPayFee.receivableAmount')"> 17 <el-form-item :label="$t('returnPayFee.receivableAmount')">
16 - <el-input v-model="form.receivableAmount" readonly /> 18 + <el-input v-model="returnFeeDetailInfo.receivableAmount" readonly />
17 </el-form-item> 19 </el-form-item>
  20 +
18 <el-form-item :label="$t('returnPayFee.receivedAmount')"> 21 <el-form-item :label="$t('returnPayFee.receivedAmount')">
19 - <el-input v-model="form.receivedAmount" readonly /> 22 + <el-input v-model="returnFeeDetailInfo.receivedAmount" readonly />
20 </el-form-item> 23 </el-form-item>
21 - <el-form-item :label="$t('returnPayFee.payTime')">  
22 - <el-input v-model="form.payTime" readonly /> 24 +
  25 + <el-form-item :label="$t('returnPayFee.paymentTime')">
  26 + <el-input v-model="returnFeeDetailInfo.payTime" readonly />
23 </el-form-item> 27 </el-form-item>
24 - <el-form-item  
25 - :label="`<span style='color:red'>*</span>${$t('returnPayFee.refundReason')}`"  
26 - prop="reason"  
27 - > 28 +
  29 + <el-form-item :label="$t('returnPayFee.refundReason')" required>
28 <el-input 30 <el-input
29 - v-model="form.reason"  
30 type="textarea" 31 type="textarea"
31 - :rows="4"  
32 - :placeholder="$t('returnPayFee.inputReason')"  
33 - /> 32 + :rows="3"
  33 + v-model="returnFeeDetailInfo.reason"
  34 + :placeholder="$t('returnPayFee.enterRefundReason')"
  35 + ></el-input>
34 </el-form-item> 36 </el-form-item>
35 </el-form> 37 </el-form>
  38 +
36 <span slot="footer" class="dialog-footer"> 39 <span slot="footer" class="dialog-footer">
37 <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button> 40 <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
38 - <el-button type="primary" @click="handleSubmit">{{ $t('returnPayFee.submitRefund') }}</el-button> 41 + <el-button type="primary" @click="submitReturnPayFee">{{ $t('returnPayFee.submitRefund') }}</el-button>
39 </span> 42 </span>
40 </el-dialog> 43 </el-dialog>
41 </template> 44 </template>
42 45
43 <script> 46 <script>
44 -import { saveReturnPayFee } from '@/api/fee/payFeeAuditManageApi'  
45 import { getCommunityId } from '@/api/community/communityApi' 47 import { getCommunityId } from '@/api/community/communityApi'
  48 +import { saveReturnPayFee } from '@/api/fee/propertyFeeApi'
46 49
47 export default { 50 export default {
48 - name: 'ReturnPayFeeModal', 51 + name: 'ReturnPayFee',
49 data() { 52 data() {
50 return { 53 return {
51 visible: false, 54 visible: false,
52 - form: { 55 + returnFeeDetailInfo: {
53 detailId: '', 56 detailId: '',
54 cycles: '', 57 cycles: '',
55 receivableAmount: '', 58 receivableAmount: '',
@@ -61,47 +64,63 @@ export default { @@ -61,47 +64,63 @@ export default {
61 feeTypeCd: '', 64 feeTypeCd: '',
62 configId: '' 65 configId: ''
63 }, 66 },
64 - rules: {  
65 - reason: [  
66 - { required: true, message: this.$t('returnPayFee.reasonRequired'), trigger: 'blur' },  
67 - { min: 1, max: 200, message: this.$t('returnPayFee.reasonLength'), trigger: 'blur' }  
68 - ]  
69 - } 67 + communityId: ''
70 } 68 }
71 }, 69 },
  70 + created() {
  71 + this.communityId = getCommunityId()
  72 + },
72 methods: { 73 methods: {
73 - open(row) {  
74 - this.form = {  
75 - detailId: row.detailId,  
76 - cycles: row.cycles,  
77 - receivableAmount: row.receivableAmount,  
78 - receivedAmount: row.receivedAmount,  
79 - payTime: row.createTime,  
80 - reason: '',  
81 - communityId: row.communityId,  
82 - feeId: row.feeId,  
83 - feeTypeCd: row.feeTypeCd,  
84 - configId: row.configId 74 + open(params) {
  75 + this.returnFeeDetailInfo = {
  76 + ...this.returnFeeDetailInfo,
  77 + communityId: params.communityId || this.communityId,
  78 + payTime: params.createTime,
  79 + detailId: params.detailId,
  80 + cycles: params.cycles,
  81 + receivableAmount: params.receivableAmount,
  82 + receivedAmount: params.receivedAmount,
  83 + feeId: params.mainFeeInfo.feeId || '',
  84 + feeTypeCd: params.mainFeeInfo.feeTypeCd || '',
  85 + configId: params.mainFeeInfo.configId || '',
  86 + remark: params.remark || ''
85 } 87 }
86 this.visible = true 88 this.visible = true
87 }, 89 },
88 - handleClose() {  
89 - this.$refs.form.resetFields() 90 + returnPayFeeValidate() {
  91 + if (!this.returnFeeDetailInfo.reason) {
  92 + this.$message.error(this.$t('returnPayFee.refundReasonRequired'))
  93 + return false
  94 + }
  95 + if (this.returnFeeDetailInfo.reason.length > 200) {
  96 + this.$message.error(this.$t('returnPayFee.refundReasonTooLong'))
  97 + return false
  98 + }
  99 + return true
90 }, 100 },
91 - async handleSubmit() { 101 + async submitReturnPayFee() {
  102 + if (!this.returnPayFeeValidate()) return
  103 +
92 try { 104 try {
93 - await this.$refs.form.validate()  
94 - this.form.communityId = getCommunityId()  
95 - await saveReturnPayFee(this.form)  
96 - this.$message.success(this.$t('common.operateSuccess'))  
97 - this.$emit('success')  
98 - this.visible = false  
99 - } catch (error) {  
100 - if (error.message) {  
101 - this.$message.error(error.message) 105 + const res = await saveReturnPayFee(this.returnFeeDetailInfo)
  106 + if (res.code === 0) {
  107 + this.$message.success(this.$t('common.operateSuccess'))
  108 + this.visible = false
  109 + this.$emit('success')
  110 + } else {
  111 + this.$message.error(res.msg || this.$t('common.operateFailed'))
102 } 112 }
  113 + } catch (error) {
  114 + console.error('提交退费申请失败:', error)
  115 + this.$message.error(this.$t('common.operateFailed'))
103 } 116 }
104 } 117 }
105 } 118 }
106 } 119 }
107 -</script>  
108 \ No newline at end of file 120 \ No newline at end of file
  121 +</script>
  122 +
  123 +<style scoped>
  124 +.el-input, .el-textarea {
  125 + width: 100%;
  126 +}
  127 +</style>
109 \ No newline at end of file 128 \ No newline at end of file
src/components/fee/reviewApplyRoomDiscount.vue
@@ -102,6 +102,7 @@ @@ -102,6 +102,7 @@
102 //import { getDict } from '@/api/community/communityApi' 102 //import { getDict } from '@/api/community/communityApi'
103 import { queryFeeDiscount, updateReviewApplyRoomDiscount } from '@/api/fee/applyRoomDiscountManageApi' 103 import { queryFeeDiscount, updateReviewApplyRoomDiscount } from '@/api/fee/applyRoomDiscountManageApi'
104 import ViewImage from '@/components/system/viewImage' 104 import ViewImage from '@/components/system/viewImage'
  105 +import { getCommunityId } from '@/api/community/communityApi'
105 106
106 export default { 107 export default {
107 name: 'ReviewApplyRoomDiscount', 108 name: 'ReviewApplyRoomDiscount',
@@ -182,7 +183,7 @@ export default { @@ -182,7 +183,7 @@ export default {
182 this.form = { 183 this.form = {
183 ...this.form, 184 ...this.form,
184 ...data, 185 ...data,
185 - communityId: this.$store.getters.communityId, 186 + communityId: getCommunityId(),
186 selectedFees: [], 187 selectedFees: [],
187 refundAmount: '' 188 refundAmount: ''
188 } 189 }
src/components/fee/roomCreateFeeAdd.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('roomCreateFeeAdd.title')"
  4 + :visible.sync="visible"
  5 + width="70%"
  6 + :before-close="handleClose"
  7 + >
  8 + <el-form ref="form" :model="formData" label-width="120px">
  9 + <el-form-item :label="$t('roomCreateFeeAdd.location')">
  10 + <el-input
  11 + v-model="formData.locationTypeCdName"
  12 + disabled
  13 + :placeholder="$t('roomCreateFeeAdd.locationPlaceholder')"
  14 + ></el-input>
  15 + </el-form-item>
  16 +
  17 + <el-form-item :label="$t('roomCreateFeeAdd.feeType')" prop="feeTypeCd">
  18 + <el-select
  19 + v-model="formData.feeTypeCd"
  20 + @change="handleFeeTypeChange"
  21 + :placeholder="$t('roomCreateFeeAdd.feeTypePlaceholder')"
  22 + style="width: 100%"
  23 + >
  24 + <template v-for="item in feeTypeOptions">
  25 + <el-option
  26 + v-if="item.statusCd !='888800010017'"
  27 + :key="item.statusCd"
  28 + :label="item.name"
  29 + :value="item.statusCd"
  30 + ></el-option>
  31 + </template>
  32 + </el-select>
  33 + </el-form-item>
  34 +
  35 + <el-form-item
  36 + v-if="formData.feeTypeCd"
  37 + :label="$t('roomCreateFeeAdd.feeItem')"
  38 + prop="configId"
  39 + >
  40 + <el-select
  41 + v-model="formData.configId"
  42 + @change="handleConfigChange"
  43 + :placeholder="$t('roomCreateFeeAdd.feeItemPlaceholder')"
  44 + style="width: 100%"
  45 + >
  46 + <el-option
  47 + v-for="item in feeConfigOptions"
  48 + :key="item.configId"
  49 + :label="item.feeName"
  50 + :value="item.configId"
  51 + ></el-option>
  52 + </el-select>
  53 + </el-form-item>
  54 +
  55 + <el-form-item
  56 + v-if="formData.computingFormula == '4004'"
  57 + :label="$t('roomCreateFeeAdd.amount')"
  58 + prop="amount"
  59 + >
  60 + <el-input
  61 + v-model="formData.amount"
  62 + :placeholder="$t('roomCreateFeeAdd.amountPlaceholder')"
  63 + ></el-input>
  64 + </el-form-item>
  65 +
  66 + <el-form-item :label="$t('roomCreateFeeAdd.startTime')" prop="startTime">
  67 + <el-date-picker
  68 + v-model="formData.startTime"
  69 + type="date"
  70 + :placeholder="$t('roomCreateFeeAdd.startTimePlaceholder')"
  71 + value-format="yyyy-MM-dd"
  72 + @change="validateStartTime"
  73 + ></el-date-picker>
  74 + </el-form-item>
  75 +
  76 + <el-form-item :label="$t('roomCreateFeeAdd.endTime')" prop="endTime">
  77 + <el-date-picker
  78 + v-model="formData.endTime"
  79 + type="date"
  80 + :placeholder="$t('roomCreateFeeAdd.endTimePlaceholder')"
  81 + value-format="yyyy-MM-dd"
  82 + @change="validateEndTime"
  83 + ></el-date-picker>
  84 + </el-form-item>
  85 +
  86 + <el-form-item
  87 + v-show="formData.computingFormula == '1102'"
  88 + :label="$t('roomCreateFeeAdd.rateCycle')"
  89 + prop="rateCycle"
  90 + >
  91 + <el-input
  92 + v-model="formData.rateCycle"
  93 + :placeholder="$t('roomCreateFeeAdd.rateCyclePlaceholder')"
  94 + ></el-input>
  95 + </el-form-item>
  96 +
  97 + <el-form-item
  98 + v-show="formData.computingFormula == '1102'"
  99 + :label="$t('roomCreateFeeAdd.rate')"
  100 + prop="rate"
  101 + >
  102 + <el-input
  103 + v-model="formData.rate"
  104 + :placeholder="$t('roomCreateFeeAdd.ratePlaceholder')"
  105 + ></el-input>
  106 + </el-form-item>
  107 +
  108 + <el-form-item
  109 + v-show="formData.computingFormula == '1102'"
  110 + :label="$t('roomCreateFeeAdd.rateStartTime')"
  111 + prop="rateStartTime"
  112 + >
  113 + <el-date-picker
  114 + v-model="formData.rateStartTime"
  115 + type="date"
  116 + :placeholder="$t('roomCreateFeeAdd.rateStartTimePlaceholder')"
  117 + value-format="yyyy-MM-dd"
  118 + ></el-date-picker>
  119 + </el-form-item>
  120 + </el-form>
  121 +
  122 + <span slot="footer" class="dialog-footer">
  123 + <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
  124 + <el-button type="primary" @click="handleSubmit">{{ $t('common.submit') }}</el-button>
  125 + </span>
  126 + </el-dialog>
  127 +</template>
  128 +
  129 +<script>
  130 +import { saveRoomCreateFee, listFeeConfigs } from '@/api/fee/roomCreateFeeAddApi'
  131 +import { getDict, getCommunityId } from '@/api/community/communityApi'
  132 +
  133 +export default {
  134 + name: 'RoomCreateFeeAdd',
  135 + data() {
  136 + return {
  137 + visible: false,
  138 + formData: {
  139 + feeTypeCds: [],
  140 + feeConfigs: [],
  141 + locationTypeCd: '',
  142 + locationObjId: '',
  143 + feeTypeCd: '',
  144 + configId: '',
  145 + locationTypeCdName: '',
  146 + startTime: '',
  147 + endTime: '2050-01-01',
  148 + computingFormula: '',
  149 + amount: '',
  150 + rateCycle: '',
  151 + rate: '',
  152 + rateStartTime: '',
  153 + feeFlag: ''
  154 + },
  155 + feeTypeOptions: [],
  156 + feeConfigOptions: [],
  157 + rules: {
  158 + locationObjId: [
  159 + { required: true, message: this.$t('roomCreateFeeAdd.validate.locationRequired'), trigger: 'blur' }
  160 + ],
  161 + feeTypeCd: [
  162 + { required: true, message: this.$t('roomCreateFeeAdd.validate.feeTypeRequired'), trigger: 'change' }
  163 + ],
  164 + configId: [
  165 + { required: true, message: this.$t('roomCreateFeeAdd.validate.feeItemRequired'), trigger: 'change' }
  166 + ],
  167 + startTime: [
  168 + { required: true, message: this.$t('roomCreateFeeAdd.validate.startTimeRequired'), trigger: 'blur' }
  169 + ]
  170 + }
  171 + }
  172 + },
  173 + methods: {
  174 + open(room) {
  175 + this.resetForm()
  176 + this.formData.locationObjId = room.roomId
  177 + this.formData.locationTypeCdName = `${room.floorNum}-${room.unitNum}-${room.roomNum}(${room.ownerName})`
  178 +
  179 + if (room.roomName) {
  180 + this.formData.locationTypeCdName = room.roomName
  181 + }
  182 +
  183 + this.formData.roomType = room.roomType
  184 + if (room.roomType === '2020602') {
  185 + this.formData.locationTypeCdName = `${room.floorNum}-${room.roomNum}(${room.ownerName})`
  186 + }
  187 +
  188 + this.loadFeeTypes()
  189 + this.visible = true
  190 + },
  191 +
  192 + loadFeeTypes() {
  193 + getDict('pay_fee_config', 'fee_type_cd').then(data => {
  194 + this.feeTypeOptions = data.filter(item =>
  195 + item.statusCd !== '888800010015' && item.statusCd !== '888800010016'
  196 + )
  197 + })
  198 + },
  199 +
  200 + handleFeeTypeChange(value) {
  201 + if (value === '888800010006' || value === '888800010014') {
  202 + this.formData.startTime = this.$dayjs().format('YYYY-MM-DD')
  203 + this.formData.endTime = this.$dayjs().add(1, 'month').format('YYYY-MM-DD')
  204 + }
  205 +
  206 + this.formData.configId = ''
  207 + this.loadFeeConfigs(value)
  208 + },
  209 +
  210 + loadFeeConfigs(feeTypeCd) {
  211 + listFeeConfigs({
  212 + page: 1,
  213 + row: 500,
  214 + communityId: getCommunityId(),
  215 + feeTypeCd,
  216 + isDefault: 'F',
  217 + state: 'Y'
  218 + }).then(response => {
  219 + this.feeConfigOptions = response.data.feeConfigs
  220 + })
  221 + },
  222 +
  223 + handleConfigChange(configId) {
  224 + if (this.formData.feeTypeCd !== '888800010006' &&
  225 + this.formData.feeTypeCd !== '888800010014' &&
  226 + this.formData.feeFlag === '1003006') {
  227 + this.formData.endTime = ''
  228 + }
  229 +
  230 + const config = this.feeConfigOptions.find(item => item.configId === configId)
  231 + if (config) {
  232 + this.formData.feeFlag = config.feeFlag
  233 + this.formData.computingFormula = config.computingFormula
  234 + }
  235 + },
  236 +
  237 + validateStartTime(value) {
  238 + if (!this.formData.feeFlag && !this.formData.feeTypeCd) {
  239 + const start = new Date(value)
  240 + const end = new Date(this.formData.endTime)
  241 + if (start >= end) {
  242 + this.$message.error(this.$t('roomCreateFeeAdd.validate.startBeforeEnd'))
  243 + this.formData.startTime = ''
  244 + }
  245 + }
  246 + },
  247 +
  248 + validateEndTime(value) {
  249 + const start = new Date(this.formData.startTime)
  250 + const end = new Date(value)
  251 + if (start >= end) {
  252 + this.$message.error(this.$t('roomCreateFeeAdd.validate.endAfterStart'))
  253 + this.formData.endTime = ''
  254 + }
  255 + },
  256 +
  257 + handleSubmit() {
  258 + this.$refs.form.validate(valid => {
  259 + if (!valid) return
  260 +
  261 + if (this.formData.feeTypeCd !== '888800010006' && this.formData.feeFlag !== '1003006') {
  262 + if (!this.formData.endTime) {
  263 + this.$message.error(this.$t('roomCreateFeeAdd.validate.endTimeRequired'))
  264 + return
  265 + }
  266 + }
  267 +
  268 + const params = {
  269 + ...this.formData,
  270 + communityId: getCommunityId()
  271 + }
  272 +
  273 + saveRoomCreateFee(params).then(() => {
  274 + this.$message.success(this.$t('roomCreateFeeAdd.successMessage'))
  275 + this.$emit('success')
  276 + this.handleClose()
  277 + }).catch(error => {
  278 + this.$message.error(error.message)
  279 + })
  280 + })
  281 + },
  282 +
  283 + resetForm() {
  284 + if (this.$refs.form) {
  285 + this.$refs.form.resetFields()
  286 + }
  287 + this.formData = {
  288 + feeTypeCds: [],
  289 + feeConfigs: [],
  290 + locationTypeCd: '',
  291 + locationObjId: '',
  292 + feeTypeCd: '',
  293 + configId: '',
  294 + locationTypeCdName: '',
  295 + startTime: '',
  296 + endTime: '2050-01-01',
  297 + computingFormula: '',
  298 + amount: '',
  299 + rateCycle: '',
  300 + rate: '',
  301 + rateStartTime: '',
  302 + feeFlag: ''
  303 + }
  304 + },
  305 +
  306 + handleClose() {
  307 + this.visible = false
  308 + this.resetForm()
  309 + }
  310 + }
  311 +}
  312 +</script>
0 \ No newline at end of file 313 \ No newline at end of file
src/components/fee/roomCreateFeeAddDemo.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-button @click="openModal">{{ $t('roomCreateFeeAddDemo.openModal') }}</el-button>
  4 + <room-create-fee-add ref="roomCreateFeeAdd" @success="handleSuccess"></room-create-fee-add>
  5 + </div>
  6 +</template>
  7 +
  8 +<script>
  9 +import RoomCreateFeeAdd from './roomCreateFeeAdd'
  10 +
  11 +export default {
  12 + name: 'RoomCreateFeeAddDemo',
  13 + components: {
  14 + RoomCreateFeeAdd
  15 + },
  16 + methods: {
  17 + openModal() {
  18 + this.$refs.roomCreateFeeAdd.open({
  19 + roomId: '123',
  20 + floorNum: '1',
  21 + unitNum: '2',
  22 + roomNum: '101',
  23 + ownerName: 'Test Owner',
  24 + roomType: '2020601'
  25 + })
  26 + },
  27 + handleSuccess() {
  28 + this.$message.success(this.$t('roomCreateFeeAddDemo.successMessage'))
  29 + }
  30 + }
  31 +}
  32 +</script>
0 \ No newline at end of file 33 \ No newline at end of file
src/components/fee/roomTreeDiv.vue deleted
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>  
152 \ No newline at end of file 0 \ No newline at end of file
src/components/fee/simplifyCallable.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-row class="margin-top">
  4 + <el-col :span="24" class="text-right">
  5 + <el-button
  6 + type="primary"
  7 + size="small"
  8 + v-if="simplifyCallableInfo.roomId"
  9 + @click="_openWritePrintOweFeeCallableModal"
  10 + >
  11 + <i class="el-icon-plus"></i>
  12 + {{ $t('simplifyCallable.register') }}
  13 + </el-button>
  14 + <el-button
  15 + type="primary"
  16 + size="small"
  17 + v-if="simplifyCallableInfo.roomId"
  18 + @click="_openAddOweFeeCallableModal"
  19 + >
  20 + <i class="el-icon-plus"></i>
  21 + {{ $t('simplifyCallable.callable') }}
  22 + </el-button>
  23 + <el-button
  24 + type="primary"
  25 + size="small"
  26 + v-if="simplifyCallableInfo.roomId"
  27 + @click="_printOwnOrder"
  28 + >
  29 + <i class="el-icon-plus"></i>
  30 + {{ $t('simplifyCallable.callableOrder') }}
  31 + </el-button>
  32 + </el-col>
  33 + </el-row>
  34 + <div>
  35 + <el-table
  36 + :data="simplifyCallableInfo.callables"
  37 + style="margin-top:10px"
  38 + border
  39 + stripe
  40 + >
  41 + <el-table-column prop="ofcId" :label="$t('simplifyCallable.id')" align="center"></el-table-column>
  42 + <el-table-column prop="ownerName" :label="$t('simplifyCallable.ownerName')" align="center"></el-table-column>
  43 + <el-table-column prop="payerObjName" :label="$t('simplifyCallable.payerObjName')" align="center"></el-table-column>
  44 + <el-table-column prop="feeName" :label="$t('simplifyCallable.feeName')" align="center"></el-table-column>
  45 + <el-table-column prop="amountdOwed" :label="$t('simplifyCallable.amount')" align="center"></el-table-column>
  46 + <el-table-column :label="$t('simplifyCallable.timePeriod')" align="center">
  47 + <template slot-scope="scope">
  48 + {{scope.row.startTime}}<br>~{{scope.row.endTime}}
  49 + </template>
  50 + </el-table-column>
  51 + <el-table-column prop="callableWayName" :label="$t('simplifyCallable.callableWay')" align="center"></el-table-column>
  52 + <el-table-column prop="staffName" :label="$t('simplifyCallable.staffName')" align="center"></el-table-column>
  53 + <el-table-column prop="stateName" :label="$t('simplifyCallable.status')" align="center"></el-table-column>
  54 + <el-table-column prop="remark" :label="$t('simplifyCallable.remark')" align="center">
  55 + <template slot-scope="scope">
  56 + <div class="textAuto" style="max-width: 200px;">{{scope.row.remark}}</div>
  57 + </template>
  58 + </el-table-column>
  59 + <el-table-column prop="createTime" :label="$t('simplifyCallable.createTime')" align="center"></el-table-column>
  60 + <el-table-column :label="$t('simplifyCallable.actions')" align="center">
  61 + <template slot-scope="scope">
  62 + <el-button-group>
  63 + <el-button size="mini" @click="_openDeleteOweFeeCallableModel(scope.row)">
  64 + {{ $t('simplifyCallable.delete') }}
  65 + </el-button>
  66 + </el-button-group>
  67 + </template>
  68 + </el-table-column>
  69 + </el-table>
  70 + <el-pagination
  71 + @current-change="handleCurrentChange"
  72 + :current-page="currentPage"
  73 + :page-size="pageSize"
  74 + layout="total, prev, pager, next"
  75 + :total="total">
  76 + </el-pagination>
  77 + </div>
  78 + <write-owe-fee-callable ref="writeOweFeeCallable"></write-owe-fee-callable>
  79 + <delete-owe-fee-callable ref="deleteOweFeeCallable"></delete-owe-fee-callable>
  80 + </div>
  81 +</template>
  82 +
  83 +<script>
  84 +import { getCommunityId } from '@/api/community/communityApi'
  85 +import { listOweFeeCallable } from '@/api/fee/simplifyCallableApi'
  86 +import WriteOweFeeCallable from './writeOweFeeCallable'
  87 +import DeleteOweFeeCallable from './deleteOweFeeCallable'
  88 +
  89 +export default {
  90 + name: 'SimplifyCallable',
  91 + components: {
  92 + WriteOweFeeCallable,
  93 + DeleteOweFeeCallable
  94 + },
  95 + data() {
  96 + return {
  97 + DEFAULT_PAGE: 1,
  98 + DEFAULT_ROWS: 10,
  99 + simplifyCallableInfo: {
  100 + callables: [],
  101 + ownerId: '',
  102 + roomId: '',
  103 + roomName: '',
  104 + total: 0,
  105 + records: 0
  106 + },
  107 + currentPage: 1,
  108 + pageSize: 10,
  109 + total: 0
  110 + }
  111 + },
  112 + created() {
  113 + this._initEvent()
  114 + },
  115 + methods: {
  116 + _initEvent() {
  117 + this.$on('switch', this.handleSwitch)
  118 + this.$on('listOwnerData', this._listSimplifyCallable)
  119 + },
  120 + handleSwitch(param) {
  121 + if (!param.roomId) return
  122 + this.clearSimplifyCallableInfo()
  123 + Object.assign(this.simplifyCallableInfo, param)
  124 + this._listSimplifyCallable(this.DEFAULT_PAGE, this.DEFAULT_ROWS)
  125 + },
  126 + handleCurrentChange(val) {
  127 + this._listSimplifyCallable(val, this.DEFAULT_ROWS)
  128 + },
  129 + async _listSimplifyCallable(page, row) {
  130 + try {
  131 + const res = await listOweFeeCallable({
  132 + page,
  133 + row,
  134 + payerObjId: this.simplifyCallableInfo.roomId,
  135 + communityId: getCommunityId()
  136 + })
  137 + this.simplifyCallableInfo.total = res.total
  138 + this.simplifyCallableInfo.records = res.records
  139 + this.simplifyCallableInfo.callables = res.data
  140 + this.total = res.records
  141 + } catch (error) {
  142 + console.error('Request failed:', error)
  143 + }
  144 + },
  145 + clearSimplifyCallableInfo() {
  146 + this.simplifyCallableInfo = {
  147 + callables: [],
  148 + ownerId: '',
  149 + roomId: '',
  150 + roomName: '',
  151 + total: 0,
  152 + records: 0
  153 + }
  154 + },
  155 + _printOwnOrder() {
  156 + window.open(`/print.html#/pages/property/printOweFee?payObjId=${this.simplifyCallableInfo.roomId}&payObjType=3333&payObjName=${this.simplifyCallableInfo.roomName}`)
  157 + },
  158 + _openWritePrintOweFeeCallableModal() {
  159 + if (!this.simplifyCallableInfo.roomId) {
  160 + this.$message.warning(this.$t('simplifyCallable.noRoomSelected'))
  161 + return
  162 + }
  163 + this.$refs.writeOweFeeCallable.open({
  164 + roomId: this.simplifyCallableInfo.roomId,
  165 + roomName: this.simplifyCallableInfo.roomName
  166 + })
  167 + },
  168 + _openAddOweFeeCallableModal() {
  169 + this.$router.push(`/fee/roomOweFeeCallable?roomId=${this.simplifyCallableInfo.roomId}`)
  170 + },
  171 + _openDeleteOweFeeCallableModel(oweFeeCallable) {
  172 + this.$refs.deleteOweFeeCallable.open(oweFeeCallable)
  173 + },
  174 + open(params) {
  175 + this.handleSwitch(params)
  176 + }
  177 + }
  178 +}
  179 +</script>
  180 +
  181 +<style scoped>
  182 +.margin-top {
  183 + margin-top: 15px;
  184 +}
  185 +.text-right {
  186 + text-align: right;
  187 +}
  188 +.textAuto {
  189 + white-space: nowrap;
  190 + overflow: hidden;
  191 + text-overflow: ellipsis;
  192 +}
  193 +</style>
0 \ No newline at end of file 194 \ No newline at end of file
src/components/fee/simplifyCallableDemo.vue 0 → 100644
  1 +<template>
  2 + <simplify-callable ref="simplifyCallable"></simplify-callable>
  3 +</template>
  4 +
  5 +<script>
  6 +import SimplifyCallable from './simplifyCallable'
  7 +
  8 +export default {
  9 + name: 'SimplifyCallableDemo',
  10 + components: {
  11 + SimplifyCallable
  12 + },
  13 + mounted() {
  14 + this.$refs.simplifyCallable.$emit('switch', {
  15 + roomId: '123',
  16 + roomName: 'Test Room',
  17 + ownerId: '456'
  18 + })
  19 + }
  20 +}
  21 +</script>
0 \ No newline at end of file 22 \ No newline at end of file
src/components/fee/simplifyFeeReceipt.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-row class="margin-top-lg">
  4 + <el-col :span="4" class="padding-right-xs padding-left-xl">
  5 + <el-select v-model="simplifyFeeReceiptInfo.objType" size="small" @change="_changeSimplifyFeeReceiptFeeTypeCd"
  6 + :placeholder="$t('simplifyFeeReceipt.selectFeeType')">
  7 + <el-option v-for="(item, index) in simplifyFeeReceiptInfo.objTypes" :key="index" :label="item.name"
  8 + :value="item.statusCd"></el-option>
  9 + </el-select>
  10 + </el-col>
  11 + <el-col :span="4" class="padding-right-xs padding-left-xl" v-if="simplifyFeeReceiptInfo.objType == '6666'">
  12 + <el-select v-model="simplifyFeeReceiptInfo.carId" size="small" @change="changeSimplifyFeeReceiptCar"
  13 + :placeholder="$t('simplifyFeeReceipt.selectCar')">
  14 + <el-option v-for="(item, index) in simplifyFeeReceiptInfo.ownerCars" :key="index" :label="item.carNum"
  15 + :value="item.carId"></el-option>
  16 + </el-select>
  17 + </el-col>
  18 + <el-col :span="4" class="padding-right-xs padding-left-xl" v-else-if="simplifyFeeReceiptInfo.objType == '7777'">
  19 + <el-select v-model="simplifyFeeReceiptInfo.contractId" size="small" @change="changeSimplifyFeeReceiptCar"
  20 + :placeholder="$t('simplifyFeeReceipt.selectContract')">
  21 + <el-option v-for="(item, index) in simplifyFeeReceiptInfo.ownerContracts" :key="index"
  22 + :label="item.contractCode" :value="item.contractId"></el-option>
  23 + </el-select>
  24 + </el-col>
  25 + <el-col :span="4" class="padding-right-xs padding-left-xl" v-if="simplifyFeeReceiptInfo.objType != '7777'">
  26 + <el-select v-model="simplifyFeeReceiptInfo.ownerFlag" size="small" @change="_queryFeeReceiptMethod">
  27 + <el-option
  28 + :label="$t('simplifyFeeReceipt.current') + (simplifyFeeReceiptInfo.objType == '6666' ? $t('simplifyFeeReceipt.car') : $t('simplifyFeeReceipt.room'))"
  29 + value="F"></el-option>
  30 + <el-option
  31 + :label="$t('simplifyFeeReceipt.all') + (simplifyFeeReceiptInfo.objType == '6666' ? $t('simplifyFeeReceipt.car') : $t('simplifyFeeReceipt.room'))"
  32 + value="T"></el-option>
  33 + </el-select>
  34 + </el-col>
  35 + <el-col :span="4" class="padding-right-xs padding-left-xl">
  36 + <el-input v-model="simplifyFeeReceiptInfo.receiptCode" size="small"
  37 + :placeholder="$t('simplifyFeeReceipt.receiptCode')"></el-input>
  38 + </el-col>
  39 + <el-col :span="4" class="padding-right-xs padding-left-xl">
  40 + <el-button type="primary" size="small" @click="_queryFeeReceiptMethod">
  41 + {{ $t('simplifyFeeReceipt.query') }}
  42 + </el-button>
  43 + </el-col>
  44 + <el-col :span="8" class="text-right padding-right-lg">
  45 + <el-button type="primary" size="small" @click="_printFeeReceipt('OFF')">
  46 + {{ $t('simplifyFeeReceipt.print') }}
  47 + </el-button>
  48 + <el-button type="primary" size="small" @click="_printFeeReceipt('ON')">
  49 + {{ $t('simplifyFeeReceipt.mergePrint') }}
  50 + </el-button>
  51 + <el-button type="primary" size="small" @click="_printFeeSmallReceipt">
  52 + {{ $t('simplifyFeeReceipt.printSmall') }}
  53 + </el-button>
  54 + <el-button type="primary" size="small" @click="_printApplyFeeReceipt">
  55 + {{ $t('simplifyFeeReceipt.apply') }}
  56 + </el-button>
  57 + </el-col>
  58 + </el-row>
  59 + <div class="margin-top">
  60 + <el-table :data="simplifyFeeReceiptInfo.feeReceipts" border stripe>
  61 + <el-table-column type="selection" width="55" align="center"></el-table-column>
  62 + <el-table-column prop="receiptCode" :label="$t('simplifyFeeReceipt.receiptCode')"
  63 + align="center"></el-table-column>
  64 + <el-table-column :label="$t('simplifyFeeReceipt.feeType')" align="center">
  65 + <template slot-scope="scope">
  66 + {{ _getFeeObjName(scope.row.objType) }}{{ $t('simplifyFeeReceipt.fee') }}
  67 + </template>
  68 + </el-table-column>
  69 + <el-table-column prop="objName" :label="_getFeeObjName(simplifyFeeReceiptInfo.objType)"
  70 + align="center"></el-table-column>
  71 + <el-table-column prop="payObjName" :label="$t('simplifyFeeReceipt.owner')" align="center"></el-table-column>
  72 + <el-table-column prop="feeName" :label="$t('simplifyFeeReceipt.feeItem')" align="center"></el-table-column>
  73 + <el-table-column :label="$t('simplifyFeeReceipt.timePeriod')" align="center">
  74 + <template slot-scope="scope">
  75 + {{ dateFormat(scope.row.startTime) }}~<br>
  76 + <span v-if="scope.row.startTime >= scope.row.endTime">
  77 + {{ dateFormat(scope.row.endTime) }}
  78 + </span>
  79 + <span v-else>
  80 + {{ dateFormat(scope.row.endTime) }}
  81 + </span>
  82 + </template>
  83 + </el-table-column>
  84 + <el-table-column prop="amount" :label="$t('simplifyFeeReceipt.totalAmount')" align="center">
  85 + <template slot-scope="scope">
  86 + {{ scope.row.amount }}{{ $t('simplifyFeeReceipt.yuan') }}
  87 + </template>
  88 + </el-table-column>
  89 + <el-table-column prop="createTime" :label="$t('simplifyFeeReceipt.payTime')" align="center"></el-table-column>
  90 + <el-table-column prop="receiptId" :label="$t('simplifyFeeReceipt.receiptId')" align="center"></el-table-column>
  91 + </el-table>
  92 + <el-pagination @current-change="handleCurrentChange" :current-page="currentPage" :page-size="pageSize"
  93 + layout="total, prev, pager, next" :total="total">
  94 + </el-pagination>
  95 + </div>
  96 + </div>
  97 +</template>
  98 +
  99 +<script>
  100 +import { getCommunityId, getDict } from '@/api/community/communityApi'
  101 +import { queryFeeReceipt, listFeePrintPage } from '@/api/fee/simplifyFeeReceiptApi'
  102 +import { queryOwnerCars } from '@/api/room/ownerCarsApi'
  103 +import { queryContract } from '@/api/contract/contractChangeDetailApi'
  104 +import { dateFormat } from '@/utils/dateUtil'
  105 +
  106 +export default {
  107 + name: 'SimplifyFeeReceipt',
  108 + data() {
  109 + return {
  110 + DEFAULT_PAGE: 1,
  111 + DEFAULT_ROWS: 50,
  112 + simplifyFeeReceiptInfo: {
  113 + feeReceipts: [],
  114 + objType: '3333',
  115 + objId: '',
  116 + payObjId: '',
  117 + roomId: '',
  118 + carId: '',
  119 + receiptCode: '',
  120 + total: '',
  121 + records: '',
  122 + ownerId: '',
  123 + objTypes: [],
  124 + ownerCars: [],
  125 + ownerContracts: [],
  126 + selectReceipts: [],
  127 + ownerFlag: 'F',
  128 + contractId: '',
  129 + quan: false,
  130 + printUrl: '/print.html#/pages/property/printPayFee'
  131 + },
  132 + currentPage: 1,
  133 + pageSize: 10,
  134 + total: 0
  135 + }
  136 + },
  137 + watch: {
  138 + 'simplifyFeeReceiptInfo.selectReceipts': {
  139 + handler(newVal) {
  140 + this.simplifyFeeReceiptInfo.quan = newVal.length === this.simplifyFeeReceiptInfo.feeReceipts.length
  141 + },
  142 + deep: true
  143 + }
  144 + },
  145 + created() {
  146 + this._loadDictData()
  147 + },
  148 + methods: {
  149 + handleSwitch(param) {
  150 + if (param.roomId === '') return
  151 + this.clearSimplifyFeeReceiptInfo()
  152 + this._listFeePrintPages()
  153 + Object.assign(this.simplifyFeeReceiptInfo, param)
  154 + this.simplifyFeeReceiptInfo.objId = param.roomId
  155 + this.simplifyFeeReceiptInfo.payObjId = param.ownerId
  156 + this._listSimplifyFeeReceipt(this.DEFAULT_PAGE, this.DEFAULT_ROWS)
  157 + },
  158 + handleCurrentChange(val) {
  159 + this._listSimplifyFeeReceipt(val, this.DEFAULT_ROWS)
  160 + },
  161 + async _loadDictData() {
  162 + try {
  163 + const data = await getDict('fee_receipt', 'obj_type')
  164 + this.simplifyFeeReceiptInfo.objTypes = data
  165 + } catch (error) {
  166 + console.error('Failed to load dict data:', error)
  167 + }
  168 + },
  169 + async _listSimplifyFeeReceipt(page, rows) {
  170 + this.simplifyFeeReceiptInfo.selectReceipts = []
  171 + this.simplifyFeeReceiptInfo.quan = false
  172 + let objId = ''
  173 + if (this.simplifyFeeReceiptInfo.objType === '3333') {
  174 + objId = this.simplifyFeeReceiptInfo.roomId
  175 + } else if (this.simplifyFeeReceiptInfo.objType === '6666') {
  176 + objId = this.simplifyFeeReceiptInfo.carId
  177 + } else {
  178 + objId = this.simplifyFeeReceiptInfo.contractId
  179 + }
  180 +
  181 + const params = {
  182 + page,
  183 + row: rows,
  184 + objType: this.simplifyFeeReceiptInfo.objType,
  185 + objId,
  186 + receiptCode: this.simplifyFeeReceiptInfo.receiptCode,
  187 + communityId: getCommunityId()
  188 + }
  189 +
  190 + if (this.simplifyFeeReceiptInfo.ownerFlag === 'T') {
  191 + params.objId = ''
  192 + params.payObjId = this.simplifyFeeReceiptInfo.payObjId
  193 + }
  194 +
  195 + try {
  196 + const res = await queryFeeReceipt(params)
  197 + this.simplifyFeeReceiptInfo.total = res.total
  198 + this.simplifyFeeReceiptInfo.records = res.records
  199 + this.simplifyFeeReceiptInfo.feeReceipts = res.data
  200 + this.total = res.records
  201 + } catch (error) {
  202 + console.error('Request failed:', error)
  203 + }
  204 + },
  205 + _queryFeeReceiptMethod() {
  206 + this._listSimplifyFeeReceipt(this.DEFAULT_PAGE, this.DEFAULT_ROWS)
  207 + },
  208 + _printFeeReceipt(merge) {
  209 + if (this.simplifyFeeReceiptInfo.selectReceipts.length < 1) {
  210 + this.$message.warning(this.$t('simplifyFeeReceipt.selectReceipt'))
  211 + return
  212 + }
  213 + const receiptids = this.simplifyFeeReceiptInfo.selectReceipts.join(',')
  214 + window.open(`${this.simplifyFeeReceiptInfo.printUrl}?receiptIds=${receiptids}&apply=N&merge=${merge}`)
  215 + },
  216 + _printApplyFeeReceipt() {
  217 + if (this.simplifyFeeReceiptInfo.selectReceipts.length < 1) {
  218 + this.$message.warning(this.$t('simplifyFeeReceipt.selectReceipt'))
  219 + return
  220 + }
  221 + const receiptids = this.simplifyFeeReceiptInfo.selectReceipts.join(',')
  222 + window.open(`/print.html#/pages/property/printPayFee?receiptIds=${receiptids}&apply=Y`)
  223 + },
  224 + _printFeeSmallReceipt() {
  225 + if (this.simplifyFeeReceiptInfo.selectReceipts.length < 1) {
  226 + this.$message.warning(this.$t('simplifyFeeReceipt.selectReceipt'))
  227 + return
  228 + }
  229 + const receiptids = this.simplifyFeeReceiptInfo.selectReceipts.join(',')
  230 + window.open(`/smallPrint.html#/pages/property/printSmallPayFee?receiptIds=${receiptids}`)
  231 + },
  232 + clearSimplifyFeeReceiptInfo() {
  233 + this.simplifyFeeReceiptInfo = {
  234 + feeReceipts: [],
  235 + objType: '3333',
  236 + objId: '',
  237 + roomId: '',
  238 + carId: '',
  239 + receiptCode: '',
  240 + total: '',
  241 + records: '',
  242 + ownerId: '',
  243 + objTypes: [],
  244 + ownerCars: [],
  245 + ownerContracts: [],
  246 + selectReceipts: [],
  247 + ownerFlag: 'F',
  248 + contractId: '',
  249 + quan: false,
  250 + printUrl: '/print.html#/pages/property/printPayFee'
  251 + }
  252 + },
  253 + async _changeSimplifyFeeReceiptFeeTypeCd(objType) {
  254 + if (objType === '3333') {
  255 + this.$emit('notify', {})
  256 + } else if (objType === '6666') {
  257 + try {
  258 + await this._listSimplifyFeeReceiptOwnerCar()
  259 + this.$emit('notify', {})
  260 + } catch (error) {
  261 + console.error(error)
  262 + }
  263 + } else {
  264 + try {
  265 + await this._listSimplifyFeeReceiptOwnerContract()
  266 + this.$emit('notify', {})
  267 + } catch (error) {
  268 + console.error(error)
  269 + }
  270 + }
  271 + },
  272 + changeSimplifyFeeReceiptCar() {
  273 + this._changeSimplifyFeeReceiptFeeTypeCd(this.simplifyFeeReceiptInfo.objType)
  274 + },
  275 + async _listSimplifyFeeReceiptOwnerCar() {
  276 + try {
  277 + const res = await queryOwnerCars({
  278 + page: 1,
  279 + row: 50,
  280 + ownerId: this.simplifyFeeReceiptInfo.ownerId,
  281 + carTypeCd: '1001',
  282 + communityId: getCommunityId()
  283 + })
  284 + this.simplifyFeeReceiptInfo.ownerCars = res.data
  285 + if (res.data.length > 0) {
  286 + this.simplifyFeeReceiptInfo.carId = res.data[0].carId
  287 + return res.data
  288 + }
  289 + throw new Error(this.$t('simplifyFeeReceipt.noCar'))
  290 + } catch (error) {
  291 + console.error('Request failed:', error)
  292 + throw error
  293 + }
  294 + },
  295 + async _listSimplifyFeeReceiptOwnerContract() {
  296 + try {
  297 + const res = await queryContract({
  298 + page: 1,
  299 + row: 50,
  300 + objId: this.simplifyFeeReceiptInfo.ownerId,
  301 + communityId: getCommunityId()
  302 + })
  303 + this.simplifyFeeReceiptInfo.ownerContracts = res.data
  304 + if (res.data.length > 0) {
  305 + this.simplifyFeeReceiptInfo.contractId = res.data[0].contractId
  306 + return res.data
  307 + }
  308 + throw new Error(this.$t('simplifyFeeReceipt.noContract'))
  309 + } catch (error) {
  310 + console.error('Request failed:', error)
  311 + throw error
  312 + }
  313 + },
  314 + checkAllReceipt(e) {
  315 + const checkObj = document.querySelectorAll('.checReceiptItem')
  316 + if (e.target.checked) {
  317 + checkObj.forEach(item => {
  318 + if (!item.checked) {
  319 + this.simplifyFeeReceiptInfo.selectReceipts.push(item.value)
  320 + }
  321 + })
  322 + } else {
  323 + this.simplifyFeeReceiptInfo.selectReceipts = []
  324 + }
  325 + },
  326 + _getFeeObjName(feeTypeCd) {
  327 + if (feeTypeCd === '3333') {
  328 + return this.$t('simplifyFeeReceipt.room')
  329 + } else if (feeTypeCd === '6666') {
  330 + return this.$t('simplifyFeeReceipt.car')
  331 + } else {
  332 + return this.$t('simplifyFeeReceipt.contract')
  333 + }
  334 + },
  335 + async _listFeePrintPages() {
  336 + try {
  337 + const res = await listFeePrintPage({
  338 + page: 1,
  339 + row: 1,
  340 + state: 'T',
  341 + communityId: getCommunityId()
  342 + })
  343 + const feePrintPages = res.data
  344 + if (feePrintPages && feePrintPages.length > 0) {
  345 + this.simplifyFeeReceiptInfo.printUrl = feePrintPages[0].url
  346 + }
  347 + } catch (error) {
  348 + console.error('Request failed:', error)
  349 + }
  350 + },
  351 + open(params) {
  352 + this.handleSwitch(params)
  353 + },
  354 + dateFormat(date) {
  355 + return dateFormat(date)
  356 + }
  357 + }
  358 +}
  359 +</script>
  360 +
  361 +<style scoped>
  362 +.margin-top-lg {
  363 + margin-top: 20px;
  364 +}
  365 +
  366 +.padding-right-xs {
  367 + padding-right: 5px;
  368 +}
  369 +
  370 +.padding-left-xl {
  371 + padding-left: 20px;
  372 +}
  373 +
  374 +.text-right {
  375 + text-align: right;
  376 +}
  377 +
  378 +.padding-right-lg {
  379 + padding-right: 20px;
  380 +}
  381 +</style>
0 \ No newline at end of file 382 \ No newline at end of file
src/components/fee/simplifyFeeReceiptDemo.vue 0 → 100644
  1 +<template>
  2 + <simplify-fee-receipt ref="simplifyFeeReceipt"></simplify-fee-receipt>
  3 +</template>
  4 +
  5 +<script>
  6 +import SimplifyFeeReceipt from './simplifyFeeReceipt'
  7 +
  8 +export default {
  9 + name: 'SimplifyFeeReceiptDemo',
  10 + components: {
  11 + SimplifyFeeReceipt
  12 + },
  13 + mounted() {
  14 + this.$refs.simplifyFeeReceipt.$emit('switch', {
  15 + roomId: '123',
  16 + ownerId: '456'
  17 + })
  18 + }
  19 +}
  20 +</script>
0 \ No newline at end of file 21 \ No newline at end of file
src/components/fee/simplifyHisFee.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-row class="margin-top">
  4 + <el-col :span="24">
  5 + <el-table
  6 + :data="simplifyHisFeeInfo.feeDetails"
  7 + style="width: 100%; margin-top: 10px"
  8 + border
  9 + stripe
  10 + >
  11 + <el-table-column prop="feeName" :label="$t('simplifyHisFee.feeItem')" align="center"></el-table-column>
  12 + <el-table-column prop="payerObjName" :label="$t('simplifyHisFee.payerObject')" align="center"></el-table-column>
  13 + <el-table-column :label="$t('simplifyHisFee.receiptNumber')" align="center">
  14 + <template slot-scope="scope">
  15 + <div v-if="scope.row.receiptCode">{{ scope.row.receiptCode }}</div>
  16 + <div v-else>
  17 + <el-link
  18 + v-if="scope.row.state === '1400'"
  19 + type="primary"
  20 + @click="_openGeneratorReceiptCode(scope.row)"
  21 + >
  22 + {{ $t('simplifyHisFee.manualGenerate') }}
  23 + </el-link>
  24 + <span v-else>-</span>
  25 + </div>
  26 + </template>
  27 + </el-table-column>
  28 + <el-table-column prop="cycles" :label="$t('simplifyHisFee.cycle')" align="center"></el-table-column>
  29 + <el-table-column :label="$t('simplifyHisFee.receivableReceived')" align="center">
  30 + <template slot-scope="scope">
  31 + <div v-if="scope.row.state === '1500'">
  32 + {{ scope.row.payerObjName }}{{ $t('simplifyHisFee.viewInFee') }}
  33 + </div>
  34 + <div v-else>
  35 + {{ scope.row.receivableAmount }}/{{ scope.row.receivedAmount }}<br>
  36 + <div v-if="scope.row.acctAmount > 0">
  37 + {{ $t('simplifyHisFee.accountDeduction') }}: {{ scope.row.acctAmount }}<br>
  38 + </div>
  39 + <div
  40 + v-for="(item, index) in scope.row.payFeeDetailDiscountDtoList"
  41 + :key="index"
  42 + >
  43 + {{ item.discountName }}: {{ Math.abs(item.discountPrice) }}<br>
  44 + </div>
  45 + </div>
  46 + </template>
  47 + </el-table-column>
  48 + <el-table-column prop="primeRateName" :label="$t('simplifyHisFee.paymentMethod')" align="center"></el-table-column>
  49 + <el-table-column :label="$t('simplifyHisFee.paymentPeriod')" align="center">
  50 + <template slot-scope="scope">
  51 + {{ formatDate(scope.row.startTime) }}~<br>
  52 + {{ formatDate(scope.row.endTime) }}
  53 + </template>
  54 + </el-table-column>
  55 + <el-table-column prop="createTime" :label="$t('simplifyHisFee.paymentTime')" align="center"></el-table-column>
  56 + <el-table-column prop="cashierName" :label="$t('simplifyHisFee.cashier')" align="center">
  57 + <template slot-scope="scope">
  58 + {{ scope.row.cashierName || '-' }}
  59 + </template>
  60 + </el-table-column>
  61 + <el-table-column prop="stateName" :label="$t('simplifyHisFee.status')" align="center"></el-table-column>
  62 + <el-table-column prop="remark" :label="$t('simplifyHisFee.remark')" align="center"></el-table-column>
  63 + <el-table-column :label="$t('simplifyHisFee.operation')" align="center">
  64 + <template slot-scope="scope">
  65 + <el-button
  66 + size="mini"
  67 + type="primary"
  68 + plain
  69 + @click="_toHisFeeDetail(scope.row)"
  70 + >
  71 + {{ $t('simplifyHisFee.detail') }}
  72 + </el-button>
  73 + </template>
  74 + </el-table-column>
  75 + </el-table>
  76 + <el-pagination
  77 + @current-change="handleCurrentChange"
  78 + :current-page="currentPage"
  79 + :page-size="pageSize"
  80 + layout="total, prev, pager, next"
  81 + :total="simplifyHisFeeInfo.total"
  82 + class="pagination-container"
  83 + ></el-pagination>
  84 + </el-col>
  85 + </el-row>
  86 +
  87 + <el-dialog
  88 + :title="$t('simplifyHisFee.generateReceipt')"
  89 + :visible.sync="receiptDialogVisible"
  90 + width="50%"
  91 + >
  92 + <el-form label-position="left" label-width="120px">
  93 + <el-form-item :label="$t('simplifyHisFee.receiptNumber')">
  94 + <el-select
  95 + v-model="simplifyHisFeeInfo.receiptType"
  96 + class="w-100"
  97 + :placeholder="$t('simplifyHisFee.receiptNumberRequired')"
  98 + >
  99 + <el-option disabled value="">{{ $t('simplifyHisFee.receiptNumberRequired') }}</el-option>
  100 + <el-option value="Y" :label="$t('simplifyHisFee.systemGenerate')"></el-option>
  101 + <el-option value="N" :label="$t('simplifyHisFee.custom')"></el-option>
  102 + </el-select>
  103 + </el-form-item>
  104 + <el-form-item
  105 + v-if="simplifyHisFeeInfo.receiptType === 'N'"
  106 + :label="$t('simplifyHisFee.receiptNumber')"
  107 + >
  108 + <el-input
  109 + v-model="simplifyHisFeeInfo.receiptCode"
  110 + :placeholder="$t('simplifyHisFee.receiptNumberRequired')"
  111 + ></el-input>
  112 + </el-form-item>
  113 + </el-form>
  114 + <div slot="footer" class="dialog-footer">
  115 + <el-button @click="receiptDialogVisible = false">{{ $t('simplifyHisFee.cancel') }}</el-button>
  116 + <el-button type="primary" @click="_generatorReceiptCode">{{ $t('simplifyHisFee.generate') }}</el-button>
  117 + </div>
  118 + </el-dialog>
  119 + </div>
  120 +</template>
  121 +
  122 +<script>
  123 +import { queryFeeDetail, generatorReceipt } from '@/api/fee/simplifyHisFeeApi'
  124 +import { getCommunityId } from '@/api/community/communityApi'
  125 +import { dateFormat } from '@/utils/dateUtil'
  126 +
  127 +export default {
  128 + name: 'SimplifyHisFee',
  129 + data() {
  130 + return {
  131 + DEFAULT_PAGE: 1,
  132 + DEFAULT_ROWS: 10,
  133 + currentPage: 1,
  134 + pageSize: 10,
  135 + receiptDialogVisible: false,
  136 + simplifyHisFeeInfo: {
  137 + total: 0,
  138 + records: 1,
  139 + feeDetails: [],
  140 + ownerId: '',
  141 + feeDetail: {},
  142 + receiptType: 'Y',
  143 + receiptCode: ''
  144 + }
  145 + }
  146 + },
  147 + created() {
  148 + this.communityId = getCommunityId()
  149 + },
  150 + methods: {
  151 + open(param) {
  152 + this.handleSwitch(param)
  153 + },
  154 + handleSwitch(param) {
  155 + this.clearSimplifyHisFeeInfo()
  156 + if (!param.ownerId) {
  157 + return
  158 + }
  159 + Object.assign(this.simplifyHisFeeInfo, param)
  160 + this._listSimplifyFeeDetails(this.DEFAULT_PAGE, this.DEFAULT_ROWS)
  161 + },
  162 + handleNotify() {
  163 + this._listSimplifyFeeDetails(this.DEFAULT_PAGE, this.DEFAULT_ROWS)
  164 + },
  165 + handleCurrentChange(page) {
  166 + this._listSimplifyFeeDetails(page, this.DEFAULT_ROWS)
  167 + },
  168 + formatDate(date) {
  169 + if (!date) return ''
  170 + return dateFormat(date)
  171 + },
  172 + _listSimplifyFeeDetails(page, row) {
  173 + const params = {
  174 + page,
  175 + row,
  176 + communityId: this.communityId,
  177 + ownerId: this.simplifyHisFeeInfo.ownerId
  178 + }
  179 +
  180 + queryFeeDetail(params)
  181 + .then(response => {
  182 + const res = response.data
  183 + this.simplifyHisFeeInfo.total = res.total
  184 + this.simplifyHisFeeInfo.records = res.records
  185 + this.simplifyHisFeeInfo.feeDetails = res.feeDetails
  186 + this.currentPage = page
  187 + })
  188 + .catch(error => {
  189 + console.error('请求失败处理', error)
  190 + })
  191 + },
  192 + clearSimplifyHisFeeInfo() {
  193 + this.simplifyHisFeeInfo = {
  194 + total: 0,
  195 + records: 1,
  196 + feeDetails: [],
  197 + ownerId: '',
  198 + feeDetail: {},
  199 + receiptType: 'Y',
  200 + receiptCode: ''
  201 + }
  202 + },
  203 + _toHisFeeDetail(detail) {
  204 + this.$router.push(`/views/fee/propertyFee?feeId=${detail.feeId}`)
  205 + },
  206 + _openGeneratorReceiptCode(detail) {
  207 + this.simplifyHisFeeInfo.feeDetail = detail
  208 + this.receiptDialogVisible = true
  209 + },
  210 + _generatorReceiptCode() {
  211 + const data = {
  212 + detailId: this.simplifyHisFeeInfo.feeDetail.detailId,
  213 + communityId: this.communityId,
  214 + receiptCode: this.simplifyHisFeeInfo.receiptCode
  215 + }
  216 +
  217 + generatorReceipt(data)
  218 + .then(response => {
  219 + const res = response.data
  220 + this.$message.success(res.msg)
  221 + if (res.code !== '0') {
  222 + return
  223 + }
  224 + this.receiptDialogVisible = false
  225 + setTimeout(() => {
  226 + this.$emit('doSearch')
  227 + }, 1000)
  228 + })
  229 + .catch(error => {
  230 + console.error('请求失败处理', error)
  231 + this.$message.error(error.message || '操作失败')
  232 + })
  233 + }
  234 + }
  235 +}
  236 +</script>
  237 +
  238 +<style scoped>
  239 +.margin-top {
  240 + margin-top: 20px;
  241 +}
  242 +.w-100 {
  243 + width: 100%;
  244 +}
  245 +.pagination-container {
  246 + margin-top: 20px;
  247 + text-align: right;
  248 +}
  249 +</style>
0 \ No newline at end of file 250 \ No newline at end of file
src/components/fee/simplifyHisFeeDemo.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <simplify-his-fee ref="simplifyHisFee"></simplify-his-fee>
  4 + </div>
  5 +</template>
  6 +
  7 +<script>
  8 +import SimplifyHisFee from './simplifyHisFee'
  9 +
  10 +export default {
  11 + name: 'SimplifyHisFeeDemo',
  12 + components: {
  13 + SimplifyHisFee
  14 + },
  15 + mounted() {
  16 + this.$refs.simplifyHisFee.$emit('switch', {
  17 + ownerId: '123'
  18 + })
  19 + }
  20 +}
  21 +</script>
0 \ No newline at end of file 22 \ No newline at end of file
src/components/fee/simplifyMeterWaterLog.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-row class="margin-top-lg">
  4 + <el-col :span="4" class="padding-right-xs padding-left-xl">
  5 + <el-select v-model="simplifyMeterWaterFeeInfo.meterType" size="small" @change="_listSimplifyMeterWaterFee(1, 10)">
  6 + <el-option :label="$t('simplifyMeterWaterLog.selectMeterType')" value=""></el-option>
  7 + <el-option v-for="(item, index) in simplifyMeterWaterFeeInfo.meterTypes" :key="index" :label="item.typeName"
  8 + :value="item.typeId"></el-option>
  9 + </el-select>
  10 + </el-col>
  11 + <el-col :span="20" class="text-right" v-if="simplifyMeterWaterFeeInfo.roomId">
  12 + <el-button type="primary" size="small" style="margin-left:10px" @click="_openAddMeterWaterModal()">
  13 + <i class="el-icon-plus"></i> {{ $t('simplifyMeterWaterLog.addMeterReading') }}
  14 + </el-button>
  15 + </el-col>
  16 + </el-row>
  17 +
  18 + <div class="margin-top">
  19 + <el-table :data="simplifyMeterWaterFeeInfo.meterWaters" style="width: 100%; margin-top:10px" border>
  20 + <el-table-column prop="meterTypeName" :label="$t('simplifyMeterWaterLog.meterType')"
  21 + align="center"></el-table-column>
  22 + <el-table-column prop="objName" :label="$t('simplifyMeterWaterLog.objectName')" align="center"></el-table-column>
  23 + <el-table-column prop="preDegrees" :label="$t('simplifyMeterWaterLog.previousReading')"
  24 + align="center"></el-table-column>
  25 + <el-table-column prop="curDegrees" :label="$t('simplifyMeterWaterLog.currentReading')"
  26 + align="center"></el-table-column>
  27 + <el-table-column prop="preReadingTime" :label="$t('simplifyMeterWaterLog.previousReadingTime')"
  28 + align="center"></el-table-column>
  29 + <el-table-column prop="curReadingTime" :label="$t('simplifyMeterWaterLog.currentReadingTime')"
  30 + align="center"></el-table-column>
  31 + <el-table-column prop="createTime" :label="$t('simplifyMeterWaterLog.createTime')"
  32 + align="center"></el-table-column>
  33 + </el-table>
  34 +
  35 + <el-row>
  36 + <el-col :span="12"></el-col>
  37 + <el-col :span="12" class="text-right">
  38 + <el-pagination @current-change="handleCurrentChange" :current-page="currentPage" :page-size="pageSize"
  39 + layout="total, prev, pager, next" :total="simplifyMeterWaterFeeInfo.total"></el-pagination>
  40 + </el-col>
  41 + </el-row>
  42 + </div>
  43 + </div>
  44 +</template>
  45 +
  46 +<script>
  47 +import { listMeterWaters, listMeterTypes } from '@/api/fee/simplifyMeterWaterLogApi'
  48 +import { getCommunityId } from '@/api/community/communityApi'
  49 +
  50 +export default {
  51 + name: 'SimplifyMeterWaterLog',
  52 + data() {
  53 + return {
  54 + simplifyMeterWaterFeeInfo: {
  55 + meterTypes: [],
  56 + meterWaters: [],
  57 + total: 0,
  58 + records: 1,
  59 + roomId: '',
  60 + roomName: '',
  61 + ownerName: '',
  62 + floorNum: '',
  63 + unitNum: '',
  64 + roomNum: '',
  65 + meterType: ""
  66 + },
  67 + currentPage: 1,
  68 + pageSize: 10
  69 + }
  70 + },
  71 + created() {
  72 + this.communityId = getCommunityId()
  73 + },
  74 + methods: {
  75 + handleCurrentChange(val) {
  76 + this.currentPage = val
  77 + this._listSimplifyMeterWaterFee(val, this.pageSize)
  78 + },
  79 + _listSimplifyMeterWaterFee(page, row) {
  80 + const param = {
  81 + page,
  82 + row,
  83 + communityId: this.communityId,
  84 + roomNum: `${this.simplifyMeterWaterFeeInfo.floorNum}-${this.simplifyMeterWaterFeeInfo.unitNum}-${this.simplifyMeterWaterFeeInfo.roomNum}`,
  85 + meterType: this.simplifyMeterWaterFeeInfo.meterType
  86 + }
  87 +
  88 + listMeterWaters(param).then(response => {
  89 + const data = response.data
  90 + this.simplifyMeterWaterFeeInfo.total = data.total
  91 + this.simplifyMeterWaterFeeInfo.records = data.records
  92 + this.simplifyMeterWaterFeeInfo.meterWaters = data.data
  93 + }).catch(error => {
  94 + console.error('请求失败:', error)
  95 + })
  96 + },
  97 + _openAddMeterWaterModal() {
  98 + this.$emit('openAddModal', {
  99 + roomId: this.simplifyMeterWaterFeeInfo.roomId,
  100 + roomName: this.simplifyMeterWaterFeeInfo.roomName,
  101 + ownerName: this.simplifyMeterWaterFeeInfo.ownerName
  102 + })
  103 + },
  104 + clearSimplifyMeterWaterFeeInfo() {
  105 + this.simplifyMeterWaterFeeInfo = {
  106 + meterTypes: [],
  107 + meterWaters: [],
  108 + total: 0,
  109 + records: 1,
  110 + roomId: '',
  111 + ownerName: '',
  112 + roomName: '',
  113 + floorNum: '',
  114 + unitNum: '',
  115 + roomNum: '',
  116 + meterType: ""
  117 + }
  118 + },
  119 + _listMeterTypes() {
  120 + const param = {
  121 + page: 1,
  122 + row: 100,
  123 + communityId: this.communityId
  124 + }
  125 +
  126 + listMeterTypes(param).then(response => {
  127 + const data = response.data
  128 + this.simplifyMeterWaterFeeInfo.meterTypes = data.data
  129 + }).catch(error => {
  130 + console.error('请求失败:', error)
  131 + })
  132 + },
  133 + switchData(param) {
  134 + if (param.roomId === '') return
  135 + this.clearSimplifyMeterWaterFeeInfo()
  136 + Object.assign(this.simplifyMeterWaterFeeInfo, param)
  137 + this._listMeterTypes()
  138 + this._listSimplifyMeterWaterFee(1, 10)
  139 + },
  140 + open(params) {
  141 + this.switchData(params)
  142 + }
  143 + }
  144 +}
  145 +</script>
  146 +
  147 +<style scoped>
  148 +.margin-top-lg {
  149 + margin-top: 20px;
  150 +}
  151 +
  152 +.margin-top {
  153 + margin-top: 15px;
  154 +}
  155 +
  156 +.padding-right-xs {
  157 + padding-right: 5px;
  158 +}
  159 +
  160 +.padding-left-xl {
  161 + padding-left: 20px;
  162 +}
  163 +
  164 +.text-right {
  165 + text-align: right;
  166 +}
  167 +</style>
0 \ No newline at end of file 168 \ No newline at end of file
src/components/fee/simplifyMeterWaterLogDemo.vue 0 → 100644
  1 +<template>
  2 + <simplify-meter-water-log ref="simplifyMeterWaterLog"></simplify-meter-water-log>
  3 +</template>
  4 +
  5 +<script>
  6 +import SimplifyMeterWaterLog from './simplifyMeterWaterLog'
  7 +
  8 +export default {
  9 + name: 'SimplifyMeterWaterLogDemo',
  10 + components: {
  11 + SimplifyMeterWaterLog
  12 + },
  13 + mounted() {
  14 + this.$refs.simplifyMeterWaterLog.switchData({
  15 + roomId: '123',
  16 + roomName: 'Test Room',
  17 + ownerName: 'Test Owner',
  18 + floorNum: '1',
  19 + unitNum: '2',
  20 + roomNum: '101'
  21 + })
  22 + }
  23 +}
  24 +</script>
0 \ No newline at end of file 25 \ No newline at end of file
src/components/fee/simplifyOwnerRooms.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-row class="margin-top">
  4 + <el-col :span="22" class="text-right"></el-col>
  5 + <el-col :span="2" class="text-right">
  6 + <el-button
  7 + type="primary"
  8 + size="small"
  9 + style="margin-left:10px"
  10 + v-if="hasPrivilege('502020082314267912') && simplifyOwnerRoomsInfo.ownerId"
  11 + @click="_openSimplifyOwnerRoomsBatchPayFeeModal()"
  12 + >
  13 + <i class="el-icon-plus"></i>
  14 + <span>{{ $t('simplifyOwnerRooms.batchPay') }}</span>
  15 + </el-button>
  16 + </el-col>
  17 + </el-row>
  18 + <div>
  19 + <el-table
  20 + :data="simplifyOwnerRoomsInfo.rooms"
  21 + style="margin-top:10px"
  22 + border
  23 + stripe
  24 + >
  25 + <el-table-column :label="$t('simplifyOwnerRooms.roomCode')" align="center">
  26 + <template slot-scope="scope">
  27 + {{scope.row.floorNum}}-{{scope.row.unitNum}}-{{scope.row.roomNum}}
  28 + </template>
  29 + </el-table-column>
  30 + <el-table-column prop="layer" :label="$t('simplifyOwnerRooms.floor')" align="center"></el-table-column>
  31 + <el-table-column prop="roomSubTypeName" :label="$t('simplifyOwnerRooms.type')" align="center"></el-table-column>
  32 + <el-table-column :label="$t('simplifyOwnerRooms.area')" align="center">
  33 + <template slot-scope="scope">
  34 + {{scope.row.builtUpArea}}/{{scope.row.roomArea}}
  35 + </template>
  36 + </el-table-column>
  37 + <el-table-column prop="roomRent" :label="$t('simplifyOwnerRooms.rent')" align="center"></el-table-column>
  38 + <el-table-column :label="$t('simplifyOwnerRooms.validity')" align="center">
  39 + <template slot-scope="scope">
  40 + {{scope.row.startTime}}<br>~{{scope.row.endTime}}
  41 + </template>
  42 + </el-table-column>
  43 + <el-table-column prop="stateName" :label="$t('simplifyOwnerRooms.roomStatus')" align="center"></el-table-column>
  44 + <el-table-column :label="$t('simplifyOwnerRooms.roomOweFee')" align="center">
  45 + <template slot-scope="scope">
  46 + {{scope.row.roomOweFee || '0.00'}}({{$t('simplifyOwnerRooms.updateDaily')}})
  47 + </template>
  48 + </el-table-column>
  49 + <el-table-column :label="$t('simplifyOwnerRooms.actions')" align="center">
  50 + <template slot-scope="scope">
  51 + <el-button-group v-if="simplifyOwnerRoomsInfo.roomId != scope.row.roomId">
  52 + <el-button size="mini" @click="_toChooseOwnerRoomModel(scope.row)">
  53 + {{ $t('simplifyOwnerRooms.choose') }}
  54 + </el-button>
  55 + </el-button-group>
  56 + <div v-else>
  57 + {{ $t('simplifyOwnerRooms.currentRoom') }}
  58 + </div>
  59 + </template>
  60 + </el-table-column>
  61 + </el-table>
  62 + <el-row>
  63 + <el-col :span="16"></el-col>
  64 + <el-col :span="8" class="float-right">
  65 + <span>{{ $t('simplifyOwnerRooms.subtotalOweFee') }}:{{simplifyOwnerRoomsInfo.allOweFeeAmount}}</span>
  66 + </el-col>
  67 + </el-row>
  68 + <el-pagination
  69 + @current-change="handleCurrentChange"
  70 + :current-page="currentPage"
  71 + :page-size="pageSize"
  72 + layout="total, prev, pager, next"
  73 + :total="total">
  74 + </el-pagination>
  75 + </div>
  76 + </div>
  77 +</template>
  78 +
  79 +<script>
  80 +import { getCommunityId } from '@/api/community/communityApi'
  81 +import { queryRoomsByOwner } from '@/api/fee/simplifyOwnerRoomsApi'
  82 +
  83 +export default {
  84 + name: 'SimplifyOwnerRooms',
  85 + data() {
  86 + return {
  87 + DEFAULT_PAGE: 1,
  88 + DEFAULT_ROWS: 10,
  89 + simplifyOwnerRoomsInfo: {
  90 + rooms: [],
  91 + ownerId: '',
  92 + roomId: '',
  93 + total: 0,
  94 + records: 1,
  95 + allOweFeeAmount: 0
  96 + },
  97 + currentPage: 1,
  98 + pageSize: 10,
  99 + total: 0
  100 + }
  101 + },
  102 + created() {
  103 + this._initEvent()
  104 + },
  105 + methods: {
  106 + _initEvent() {
  107 + },
  108 + handleSwitch(param) {
  109 + if (!param.ownerId) return
  110 + this.clearSimplifyOwnerRoomsInfo()
  111 + Object.assign(this.simplifyOwnerRoomsInfo, param)
  112 + this._listSimplifyOwnerRooms(this.DEFAULT_PAGE, this.DEFAULT_ROWS)
  113 + },
  114 + handleCurrentChange(val) {
  115 + this._listSimplifyOwnerRooms(val, this.DEFAULT_ROWS)
  116 + },
  117 + async _listSimplifyOwnerRooms() {
  118 + try {
  119 + const res = await queryRoomsByOwner({
  120 + ownerId: this.simplifyOwnerRoomsInfo.ownerId,
  121 + communityId: getCommunityId()
  122 + })
  123 + this.simplifyOwnerRoomsInfo.rooms = res.rooms
  124 + this._computeOwnerRoomOweFeeAmount()
  125 + this.simplifyOwnerRoomsInfo.total = res.total
  126 + this.simplifyOwnerRoomsInfo.records = res.records
  127 + this.total = res.records
  128 + } catch (error) {
  129 + console.error('Request failed:', error)
  130 + }
  131 + },
  132 + _toChooseOwnerRoomModel(room) {
  133 + this.$emit('notifyRoom', room)
  134 + },
  135 + _computeOwnerRoomOweFeeAmount() {
  136 + let total = 0
  137 + this.simplifyOwnerRoomsInfo.allOweFeeAmount = 0
  138 + if (!this.simplifyOwnerRoomsInfo.rooms || this.simplifyOwnerRoomsInfo.rooms.length < 1) return
  139 +
  140 + this.simplifyOwnerRoomsInfo.rooms.forEach(room => {
  141 + if (room.roomOweFee) {
  142 + total += parseFloat(room.roomOweFee)
  143 + }
  144 + })
  145 + this.simplifyOwnerRoomsInfo.allOweFeeAmount = total.toFixed(2)
  146 + },
  147 + clearSimplifyOwnerRoomsInfo() {
  148 + this.simplifyOwnerRoomsInfo = {
  149 + rooms: [],
  150 + ownerId: '',
  151 + roomId: '',
  152 + total: 0,
  153 + records: 1,
  154 + allOweFeeAmount: 0
  155 + }
  156 + },
  157 + _openSimplifyOwnerRoomsBatchPayFeeModal() {
  158 + this.$router.push(`/property/batchPayFeeOrder?ownerId=${this.simplifyOwnerRoomsInfo.ownerId}&payerObjType=3333`)
  159 + },
  160 + hasPrivilege(code) {
  161 + void code; // 占位,消除未使用警告
  162 + return true;
  163 + },
  164 + open(params) {
  165 + this.handleSwitch(params)
  166 + }
  167 + }
  168 +}
  169 +</script>
  170 +
  171 +<style scoped>
  172 +.margin-top {
  173 + margin-top: 15px;
  174 +}
  175 +.float-right {
  176 + float: right;
  177 +}
  178 +.text-right {
  179 + text-align: right;
  180 +}
  181 +</style>
0 \ No newline at end of file 182 \ No newline at end of file
src/components/fee/simplifyOwnerRoomsDemo.vue 0 → 100644
  1 +<template>
  2 + <simplify-owner-rooms ref="simplifyOwnerRooms"></simplify-owner-rooms>
  3 +</template>
  4 +
  5 +<script>
  6 +import SimplifyOwnerRooms from './simplifyOwnerRooms'
  7 +
  8 +export default {
  9 + name: 'SimplifyOwnerRoomsDemo',
  10 + components: {
  11 + SimplifyOwnerRooms
  12 + },
  13 + mounted() {
  14 + this.$refs.simplifyOwnerRooms.$emit('switch', {
  15 + ownerId: '123',
  16 + roomId: '456'
  17 + })
  18 + }
  19 +}
  20 +</script>
0 \ No newline at end of file 21 \ No newline at end of file
src/components/fee/simplifyRefundDeposit.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-row class="margin-top">
  4 + <el-col :span="20"></el-col>
  5 + <el-col :span="4" class="text-right"></el-col>
  6 + </el-row>
  7 +
  8 + <el-table :data="simplifyRefundDepositInfo.fees" border style="width: 100%; margin-top:10px">
  9 + <el-table-column prop="payerObjName" :label="$t('simplifyRefundDeposit.chargeObject')"
  10 + align="center"></el-table-column>
  11 + <el-table-column prop="feeName" :label="$t('simplifyRefundDeposit.feeItem')" align="center"></el-table-column>
  12 + <el-table-column :label="$t('simplifyRefundDeposit.timePeriod')" align="center">
  13 + <template slot-scope="scope">
  14 + {{ scope.row.startTime }}~{{ scope.row.endTime }}
  15 + </template>
  16 + </el-table-column>
  17 + <el-table-column prop="receivedAmount" :label="$t('simplifyRefundDeposit.amount')"
  18 + align="center"></el-table-column>
  19 + <el-table-column prop="createTime" :label="$t('simplifyRefundDeposit.paymentTime')"
  20 + align="center"></el-table-column>
  21 + <el-table-column prop="stateName" :label="$t('simplifyRefundDeposit.status')" align="center"></el-table-column>
  22 + <el-table-column :label="$t('simplifyRefundDeposit.operation')" align="center">
  23 + <template slot-scope="scope">
  24 + <el-button-group>
  25 + <el-button v-if="scope.row.state == '1400'" size="mini" @click="_openRefundModel(scope.row)">
  26 + {{ $t('simplifyRefundDeposit.refundDeposit') }}
  27 + </el-button>
  28 + <el-button size="mini" @click="_toSimplifyFeeDepositFeeDetail(scope.row)">
  29 + {{ $t('simplifyRefundDeposit.detail') }}
  30 + </el-button>
  31 + </el-button-group>
  32 + </template>
  33 + </el-table-column>
  34 + </el-table>
  35 +
  36 + <el-row class="margin-top">
  37 + <el-col :span="24" class="text-right">
  38 + <el-pagination @current-change="handleCurrentChange" :current-page="currentPage" :page-size="pageSize"
  39 + layout="total, prev, pager, next" :total="simplifyRefundDepositInfo.total"></el-pagination>
  40 + </el-col>
  41 + </el-row>
  42 + </div>
  43 +</template>
  44 +
  45 +<script>
  46 +import { queryFeeDeposit } from '@/api/fee/simplifyRefundDepositApi'
  47 +import { getCommunityId } from '@/api/community/communityApi'
  48 +
  49 +export default {
  50 + name: 'SimplifyRefundDeposit',
  51 + data() {
  52 + return {
  53 + simplifyRefundDepositInfo: {
  54 + fees: [],
  55 + ownerId: '',
  56 + roomId: '',
  57 + roomName: '',
  58 + total: 0,
  59 + records: 0
  60 + },
  61 + currentPage: 1,
  62 + pageSize: 10,
  63 + communityId: ''
  64 + }
  65 + },
  66 + created() {
  67 + this.communityId = getCommunityId()
  68 + },
  69 + methods: {
  70 + handleCurrentChange(val) {
  71 + this.currentPage = val
  72 + this._listSimplifyFeeDeposit(val, this.pageSize)
  73 + },
  74 + _listSimplifyFeeDeposit(page, rows) {
  75 + const params = {
  76 + page,
  77 + row: rows,
  78 + payerObjId: this.simplifyRefundDepositInfo.roomId,
  79 + ownerId: this.simplifyRefundDepositInfo.ownerId,
  80 + communityId: this.communityId,
  81 + state: '1400'
  82 + }
  83 +
  84 + queryFeeDeposit(params).then(response => {
  85 + if (response.code !== 0) return
  86 + this.simplifyRefundDepositInfo.total = response.total
  87 + this.simplifyRefundDepositInfo.records = response.records
  88 + this.simplifyRefundDepositInfo.fees = response.data
  89 + }).catch(error => {
  90 + console.error('请求失败:', error)
  91 + })
  92 + },
  93 + clearSimplifyFeeDepositInfo() {
  94 + this.simplifyRefundDepositInfo = {
  95 + fees: [],
  96 + ownerId: '',
  97 + roomId: '',
  98 + roomName: '',
  99 + total: 0,
  100 + records: 0
  101 + }
  102 + },
  103 + _openRefundModel() {
  104 + const roomId = this.simplifyRefundDepositInfo.roomId
  105 + this.$router.push(`/pages/fee/refundDepositFee?roomId=${roomId}`)
  106 + },
  107 + _toSimplifyFeeDepositFeeDetail(fee) {
  108 + this.$router.push(`/pages/property/propertyFee?feeId=${fee.feeId}`)
  109 + },
  110 + switchData(param) {
  111 + if (!param.roomId) return
  112 + this.clearSimplifyFeeDepositInfo()
  113 + Object.assign(this.simplifyRefundDepositInfo, param)
  114 + this._listSimplifyFeeDeposit(1, 10)
  115 + },
  116 + open(params) {
  117 + this.switchData(params)
  118 + }
  119 + }
  120 +}
  121 +</script>
  122 +
  123 +<style scoped>
  124 +.margin-top {
  125 + margin-top: 15px;
  126 +}
  127 +
  128 +.text-right {
  129 + text-align: right;
  130 +}
  131 +</style>
0 \ No newline at end of file 132 \ No newline at end of file
src/components/fee/simplifyRefundDepositDemo.vue 0 → 100644
  1 +<template>
  2 + <simplify-refund-deposit ref="simplifyRefundDeposit"></simplify-refund-deposit>
  3 +</template>
  4 +
  5 +<script>
  6 +import SimplifyRefundDeposit from './simplifyRefundDeposit'
  7 +
  8 +export default {
  9 + name: 'SimplifyRefundDepositDemo',
  10 + components: {
  11 + SimplifyRefundDeposit
  12 + },
  13 + mounted() {
  14 + this.$refs.simplifyRefundDeposit.switchData({
  15 + roomId: '123',
  16 + ownerId: '456',
  17 + roomName: 'Test Room'
  18 + })
  19 + }
  20 +}
  21 +</script>
0 \ No newline at end of file 22 \ No newline at end of file
src/components/fee/simplifyRoomFee.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-row class="margin-top-lg">
  4 + <el-col :span="2" >
  5 + <el-select v-model="simplifyRoomFeeInfo.feeTypeCd" @change="changeSimplifyRoomFeeFeeTypeCd" size="small"
  6 + :placeholder="$t('simplifyRoomFee.selectFeeType')">
  7 + <template v-for="item in simplifyRoomFeeInfo.feeTypeCds">
  8 + <el-option :key="item.statusCd" :label="item.name" :value="item.statusCd"
  9 + v-if="item.statusCd != '888800010008'"></el-option>
  10 + </template>
  11 + </el-select>
  12 + </el-col>
  13 + <el-col :span="2" >
  14 + <el-select v-model="simplifyRoomFeeInfo.configId" @change="changeSimplifyRoomConfigId" size="small"
  15 + :placeholder="$t('simplifyRoomFee.selectFeeItem')">
  16 + <el-option v-for="item in simplifyRoomFeeInfo.feeConfigs" :key="item.configId" :label="item.feeName"
  17 + :value="item.configId"></el-option>
  18 + </el-select>
  19 + </el-col>
  20 + <el-col :span="2" >
  21 + <el-select v-model="simplifyRoomFeeInfo.state" @change="changeSimplifyRoomConfigId" size="small"
  22 + :placeholder="$t('simplifyRoomFee.selectStatus')">
  23 + <el-option :label="$t('simplifyRoomFee.valid')" value="2008001"></el-option>
  24 + <el-option :label="$t('simplifyRoomFee.feeEnd')" value="2009001"></el-option>
  25 + </el-select>
  26 + </el-col>
  27 + <el-col :span="2" >
  28 + <el-select v-model="simplifyRoomFeeInfo.ownerFee" @change="changeSimplifyRoomConfigId" size="small">
  29 + <el-option :label="$t('simplifyRoomFee.currentRoom')" value="N"></el-option>
  30 + <el-option :label="$t('simplifyRoomFee.currentOwner')" value="Y"></el-option>
  31 + </el-select>
  32 + </el-col>
  33 + <el-col :span="2" v-if="simplifyRoomFeeInfo.roomId && simplifyRoomFeeInfo.state == '2008001'">
  34 + <el-select v-model="simplifyRoomFeeInfo.showFlag" @change="changeSimplifyRoomShowFlag" size="small">
  35 + <el-option :label="$t('simplifyRoomFee.default')" value="DEFAULT"></el-option>
  36 + <el-option :label="$t('simplifyRoomFee.monthly')" value="MONTH"></el-option>
  37 + </el-select>
  38 + </el-col>
  39 + <el-col :span="2" v-else></el-col>
  40 + <el-col :span="13" class="text-right">
  41 + <el-button type="primary" size="small" v-if="hasPrivilege('502020082314267912')"
  42 + @click="openBatchPayRoomFeeModal">
  43 + <i class="el-icon-plus"></i>
  44 + {{ $t('simplifyRoomFee.batchPayment') }}
  45 + </el-button>
  46 + <el-button type="primary" size="small" v-if="hasPrivilege('502022073007100003')"
  47 + @click="openTempImportRoomFeeModal">
  48 + <i class="el-icon-plus"></i>
  49 + {{ $t('simplifyRoomFee.tempFee') }}
  50 + </el-button>
  51 + <el-button type="primary" size="small" v-if="hasPrivilege('502022073049300004')" @click="openProxyFeeModal">
  52 + <i class="el-icon-plus"></i>
  53 + {{ $t('simplifyRoomFee.quantityPayment') }}
  54 + </el-button>
  55 + <el-button type="primary" size="small" v-if="hasPrivilege('502022073042960005')"
  56 + @click="openAddMeterWaterSimplifyModal">
  57 + <i class="el-icon-plus"></i>
  58 + {{ $t('simplifyRoomFee.waterElectricity') }}
  59 + </el-button>
  60 + <el-button type="primary" size="small" v-if="hasPrivilege('502022073006890006')"
  61 + @click="openRoomCreateFeeComboModal">
  62 + <i class="el-icon-plus"></i>
  63 + {{ $t('simplifyRoomFee.feePackage') }}
  64 + </el-button>
  65 + <el-button type="primary" size="small" v-if="hasPrivilege('502022073096990007')"
  66 + @click="openRoomCreateFeeAddModal">
  67 + <i class="el-icon-plus"></i>
  68 + {{ $t('simplifyRoomFee.createFee') }}
  69 + </el-button>
  70 + <el-button type="primary" size="small" v-if="hasPrivilege('502020080570210194')" @click="toOwnerPayFee">
  71 + <i class="el-icon-plus"></i>
  72 + {{ $t('simplifyRoomFee.arrearsPayment') }}
  73 + </el-button>
  74 + </el-col>
  75 + </el-row>
  76 +
  77 + <div class="margin-top" v-show="simplifyRoomFeeInfo.showFlag == 'DEFAULT'">
  78 + <el-table :data="simplifyRoomFeeInfo.fees" style="width: 100%" border stripe>
  79 + <el-table-column prop="feeName" :label="$t('simplifyRoomFee.feeItem')" align="center">
  80 + <template slot-scope="scope">
  81 + <span class="hand" @click="viewRoomFeeConfig(scope.row)">
  82 + {{ scope.row.feeName }}{{ getSimplifyRoomFeeRoomName(scope.row) }}
  83 + <i class="el-icon-info"></i>
  84 + </span>
  85 + </template>
  86 + </el-table-column>
  87 + <el-table-column prop="feeFlagName" :label="$t('simplifyRoomFee.feeFlag')" align="center"></el-table-column>
  88 + <el-table-column prop="feeTypeCdName" :label="$t('simplifyRoomFee.feeType')" align="center"></el-table-column>
  89 + <el-table-column prop="amountOwed" :label="$t('simplifyRoomFee.receivableAmount')"
  90 + align="center"></el-table-column>
  91 + <el-table-column :label="$t('simplifyRoomFee.accountTime')" align="center">
  92 + <template slot-scope="scope">
  93 + {{ scope.row.startTime }}
  94 + </template>
  95 + </el-table-column>
  96 + <el-table-column :label="$t('simplifyRoomFee.receivablePeriod')" align="center">
  97 + <template slot-scope="scope">
  98 + {{ getEndTime(scope.row) }}~<br />{{ getDeadlineTime(scope.row) }}
  99 + </template>
  100 + </el-table-column>
  101 + <el-table-column :label="$t('simplifyRoomFee.description')" align="center" width="150">
  102 + <template slot-scope="scope">
  103 + <div v-if="scope.row.computingFormula == '5005' || scope.row.computingFormula == '9009'">
  104 + <span>{{ $t('simplifyRoomFee.preDegrees') }}</span>{{ scope.row.preDegrees }}
  105 + </div>
  106 + <div v-if="scope.row.computingFormula == '5005' || scope.row.computingFormula == '9009'">
  107 + <span>{{ $t('simplifyRoomFee.curDegrees') }}</span>{{ scope.row.curDegrees }}
  108 + </div>
  109 + <div v-if="scope.row.computingFormula == '5005' || scope.row.computingFormula == '9009'">
  110 + <span>{{ $t('simplifyRoomFee.unitPrice') }}</span>{{ getOnePrice1(scope.row) }}
  111 + </div>
  112 + <div v-if="scope.row.computingFormula == '5005' || scope.row.computingFormula == '9009'">
  113 + <span>{{ $t('simplifyRoomFee.additionalFee') }}</span>{{ scope.row.additionalAmount }}
  114 + </div>
  115 + <div v-else-if="scope.row.computingFormula == '6006'">
  116 + <span>{{ $t('simplifyRoomFee.usage') }}</span>{{ getAttrValue(scope.row.feeAttrs, '390006') }}
  117 + </div>
  118 + <div v-else-if="scope.row.computingFormula == '6006'">
  119 + <span>{{ $t('simplifyRoomFee.unitPrice') }}</span>{{ scope.row.squarePrice }}
  120 + </div>
  121 + <div v-else-if="scope.row.computingFormula == '6006'">
  122 + <span>{{ $t('simplifyRoomFee.additionalFee') }}</span>{{ scope.row.additionalAmount }}
  123 + </div>
  124 + <div v-else-if="scope.row.feeTypeCd == '888800010017'">
  125 + <span>{{ $t('simplifyRoomFee.algorithm') }}</span>{{ getAttrValue(scope.row.feeAttrs, '390005') }}
  126 + </div>
  127 + <div v-else-if="scope.row.feeTypeCd == '888800010017'">
  128 + <span>{{ $t('simplifyRoomFee.usage') }}</span>{{ getAttrValue(scope.row.feeAttrs, '390003') }}
  129 + </div>
  130 + <div v-else>
  131 + <span>{{ $t('simplifyRoomFee.unitPrice') }}</span>{{ scope.row.squarePrice }}
  132 + </div>
  133 + <div v-if="scope.row.feeFlag == '1003006'">
  134 + <span>{{ $t('simplifyRoomFee.additionalFee') }}</span>{{ scope.row.additionalAmount }}
  135 + </div>
  136 + <div v-else>
  137 + <span>{{ $t('simplifyRoomFee.fixedFee') }}</span>{{ scope.row.additionalAmount }}
  138 + </div>
  139 + </template>
  140 + </el-table-column>
  141 + <el-table-column prop="stateName" :label="$t('simplifyRoomFee.status')" align="center"></el-table-column>
  142 + <el-table-column :label="$t('simplifyRoomFee.operation')" align="center" width="200">
  143 + <template slot-scope="scope">
  144 + <el-button type="text" v-if="scope.row.state != '2009001' && hasPrivilege('502020082314267912')"
  145 + @click="payFee(scope.row)">
  146 + {{ $t('simplifyRoomFee.payment') }}
  147 + </el-button>
  148 + <el-button type="text" @click="payFeeHis(scope.row)">
  149 + {{ $t('simplifyRoomFee.paymentHistory') }}
  150 + </el-button>
  151 + <el-dropdown
  152 + v-if="hasPrivilege('502020090604200029') || hasPrivilege('502021070488970005') || hasPrivilege('502020090427190001')">
  153 + <span class="el-dropdown-link">
  154 + {{ $t('simplifyRoomFee.moreOperations') }}<i class="el-icon-arrow-down el-icon--right"></i>
  155 + </span>
  156 + <el-dropdown-menu slot="dropdown">
  157 + <el-dropdown-item v-if="hasPrivilege('502020090604200029')" @click.native="deleteFee(scope.row)">
  158 + {{ $t('simplifyRoomFee.cancelFee') }}
  159 + </el-dropdown-item>
  160 + <el-dropdown-item v-if="hasPrivilege('502021070488970005')" @click.native="finishFee(scope.row)">
  161 + {{ $t('simplifyRoomFee.manualEnd') }}
  162 + </el-dropdown-item>
  163 + <el-dropdown-item v-if="scope.row.state != '2009001' && hasPrivilege('502020090427190001')"
  164 + @click.native="editFee(scope.row)">
  165 + {{ $t('simplifyRoomFee.feeChange') }}
  166 + </el-dropdown-item>
  167 + <el-dropdown-item>
  168 + <a target="_blank" :href="'/#/pages/fee/feeDetail?feeId=' + scope.row.feeId">
  169 + {{ $t('simplifyRoomFee.details') }}
  170 + </a>
  171 + </el-dropdown-item>
  172 + </el-dropdown-menu>
  173 + </el-dropdown>
  174 + </template>
  175 + </el-table-column>
  176 + </el-table>
  177 + <el-pagination @current-change="handleCurrentChange" :current-page="currentPage" :page-size="pageSize"
  178 + layout="total, prev, pager, next" :total="total" class="pagination text-right"></el-pagination>
  179 + </div>
  180 +
  181 + <div class="margin-top" v-show="simplifyRoomFeeInfo.showFlag == 'MONTH'">
  182 + <el-table :data="simplifyRoomFeeInfo.monthFees" style="width: 100%" border stripe>
  183 + <el-table-column prop="feeName" :label="$t('simplifyRoomFee.feeItem')" align="center">
  184 + <template slot-scope="scope">
  185 + <span class="hand" @click="viewRoomFeeConfig(scope.row)">
  186 + {{ scope.row.feeName }}{{ getSimplifyRoomFeeRoomName(scope.row) }}
  187 + <i class="el-icon-info"></i>
  188 + </span>
  189 + </template>
  190 + </el-table-column>
  191 + <el-table-column prop="feeFlagName" :label="$t('simplifyRoomFee.feeFlag')" align="center"></el-table-column>
  192 + <el-table-column prop="feeTypeCdName" :label="$t('simplifyRoomFee.feeType')" align="center"></el-table-column>
  193 + <el-table-column :label="$t('simplifyRoomFee.chargeYearMonth')" align="center">
  194 + <template slot-scope="scope">
  195 + {{ scope.row.detailYear }}-{{ scope.row.detailMonth }}
  196 + </template>
  197 + </el-table-column>
  198 + <el-table-column prop="receivableAmount" :label="$t('simplifyRoomFee.receivableAmount')"
  199 + align="center"></el-table-column>
  200 + <el-table-column :label="$t('simplifyRoomFee.description')" align="center" width="150">
  201 + <template slot-scope="scope">
  202 + <div v-if="scope.row.computingFormula == '5005' || scope.row.computingFormula == '9009'">
  203 + <span>{{ $t('simplifyRoomFee.preDegrees') }}</span>{{ scope.row.preDegrees }}
  204 + </div>
  205 + <div v-if="scope.row.computingFormula == '5005' || scope.row.computingFormula == '9009'">
  206 + <span>{{ $t('simplifyRoomFee.curDegrees') }}</span>{{ scope.row.curDegrees }}
  207 + </div>
  208 + <div v-if="scope.row.computingFormula == '5005' || scope.row.computingFormula == '9009'">
  209 + <span>{{ $t('simplifyRoomFee.unitPrice') }}</span>{{ getOnePrice1(scope.row) }}
  210 + </div>
  211 + <div v-if="scope.row.computingFormula == '5005' || scope.row.computingFormula == '9009'">
  212 + <span>{{ $t('simplifyRoomFee.additionalFee') }}</span>{{ scope.row.additionalAmount }}
  213 + </div>
  214 + <div v-else-if="scope.row.computingFormula == '6006'">
  215 + <span>{{ $t('simplifyRoomFee.usage') }}</span>{{ getAttrValue(scope.row.feeAttrs, '390006') }}
  216 + </div>
  217 + <div v-else-if="scope.row.computingFormula == '6006'">
  218 + <span>{{ $t('simplifyRoomFee.unitPrice') }}</span>{{ scope.row.squarePrice }}
  219 + </div>
  220 + <div v-else-if="scope.row.computingFormula == '6006'">
  221 + <span>{{ $t('simplifyRoomFee.additionalFee') }}</span>{{ scope.row.additionalAmount }}
  222 + </div>
  223 + <div v-else-if="scope.row.feeTypeCd == '888800010017'">
  224 + <span>{{ $t('simplifyRoomFee.algorithm') }}</span>{{ getAttrValue(scope.row.feeAttrs, '390005') }}
  225 + </div>
  226 + <div v-else-if="scope.row.feeTypeCd == '888800010017'">
  227 + <span>{{ $t('simplifyRoomFee.usage') }}</span>{{ getAttrValue(scope.row.feeAttrs, '390003') }}
  228 + </div>
  229 + <div v-else>
  230 + <span>{{ $t('simplifyRoomFee.unitPrice') }}</span>{{ scope.row.squarePrice }}
  231 + </div>
  232 + <div v-if="scope.row.feeFlag == '1003006'">
  233 + <span>{{ $t('simplifyRoomFee.additionalFee') }}</span>{{ scope.row.additionalAmount }}
  234 + </div>
  235 + <div v-else>
  236 + <span>{{ $t('simplifyRoomFee.fixedFee') }}</span>{{ scope.row.additionalAmount }}
  237 + </div>
  238 + </template>
  239 + </el-table-column>
  240 + <el-table-column :label="$t('simplifyRoomFee.operation')" align="center">
  241 + <template slot-scope="scope">
  242 + <a target="_blank" :href="'/#/pages/fee/feeDetail?feeId=' + scope.row.feeId">
  243 + {{ $t('simplifyRoomFee.details') }}
  244 + </a>
  245 + </template>
  246 + </el-table-column>
  247 + </el-table>
  248 + </div>
  249 +
  250 + <el-row>
  251 + <el-col :span="12" class="text-left">
  252 + <div>{{ $t('simplifyRoomFee.note1') }}</div>
  253 + <div>{{ $t('simplifyRoomFee.note2') }}</div>
  254 + </el-col>
  255 + <el-col :span="6">
  256 + <span>
  257 + <span>{{ $t('simplifyRoomFee.arrearsSubtotal') }}</span>{{ simplifyRoomFeeInfo.totalAmount }}
  258 + </span>
  259 + </el-col>
  260 + </el-row>
  261 + <!-- Modal Components -->
  262 + <delete-fee ref="deleteFee"></delete-fee>
  263 + <edit-fee ref="editFee"></edit-fee>
  264 + <temp-import-room-fee ref="tempImportRoomFee"></temp-import-room-fee>
  265 + </div>
  266 +</template>
  267 +
  268 +<script>
  269 +import { listFee, listFeeConfigs, listMonthFee } from '@/api/fee/simplifyRoomFeeApi'
  270 +import { getDict } from '@/api/community/communityApi'
  271 +import { getCommunityId } from '@/api/community/communityApi'
  272 +//import { listFeeConfigs } from '@/api/fee/feeConfigManageApi'
  273 +import TempImportRoomFee from './tempImportRoomFee'
  274 +import { dateFormat } from '@/utils/dateUtil'
  275 +import DeleteFee from '@/components/fee/deleteFee'
  276 +import EditFee from '@/components/fee/editFee'
  277 +
  278 +export default {
  279 + name: 'SimplifyRoomFee',
  280 + components: {
  281 + TempImportRoomFee,
  282 + DeleteFee,
  283 + EditFee,
  284 + },
  285 + data() {
  286 + return {
  287 + simplifyRoomFeeInfo: {
  288 + total: 0,
  289 + records: 1,
  290 + fees: [],
  291 + monthFees: [],
  292 + roomId: '',
  293 + roomName: '',
  294 + name: '',
  295 + floorNum: '',
  296 + unitNum: '',
  297 + roomNum: '',
  298 + configId: '',
  299 + feeTypeCds: [],
  300 + feeTypeCd: '',
  301 + state: '2008001',
  302 + totalAmount: 0.0,
  303 + roomType: '',
  304 + ownerFee: 'N',
  305 + ownerId: '',
  306 + showFlag: 'DEFAULT',
  307 + feeConfigs: []
  308 + },
  309 + currentPage: 1,
  310 + pageSize: 10,
  311 + total: 0
  312 + }
  313 + },
  314 + computed: {
  315 + filteredFeeTypeCds() {
  316 + return this.simplifyRoomFeeInfo.feeTypeCds.filter(item => item.statusCd !== '888800010008')
  317 + }
  318 + },
  319 + created() {
  320 + this.communityId = getCommunityId()
  321 + //this.loadDictData()
  322 + },
  323 + methods: {
  324 + open(params) {
  325 + this.handleSwitch(params)
  326 + },
  327 + handleSwitch(param) {
  328 + this.clearSimplifyRoomFeeInfo()
  329 + if (param.roomId === '') return
  330 +
  331 + Object.assign(this.simplifyRoomFeeInfo, param)
  332 + this.listSimplifyRoomFee(1, this.pageSize)
  333 +
  334 + getDict('pay_fee_config', 'fee_type_cd').then(data => {
  335 + this.simplifyRoomFeeInfo.feeTypeCds = data
  336 + })
  337 + },
  338 + handleNotify() {
  339 + this.listSimplifyRoomFee(this.currentPage, this.pageSize)
  340 + },
  341 + getOnePrice1(fee) {
  342 + let price = fee.mwPrice
  343 + if (!price) return fee.squarePrice
  344 + if (parseFloat(price) > 0) return price
  345 + return fee.squarePrice
  346 + },
  347 + async listSimplifyRoomFee(page, row) {
  348 + const params = {
  349 + page,
  350 + row,
  351 + communityId: getCommunityId(),
  352 + payerObjId: this.simplifyRoomFeeInfo.roomId,
  353 + payerObjType: '3333',
  354 + configId: this.simplifyRoomFeeInfo.configId,
  355 + state: this.simplifyRoomFeeInfo.state,
  356 + feeTypeCd: this.simplifyRoomFeeInfo.feeTypeCd
  357 + }
  358 +
  359 + if (this.simplifyRoomFeeInfo.ownerFee === 'Y') {
  360 + params.payerObjId = ''
  361 + params.ownerId = this.simplifyRoomFeeInfo.ownerId
  362 + }
  363 +
  364 + try {
  365 + const res = await listFee(params)
  366 + this.simplifyRoomFeeInfo.total = res.total
  367 + this.simplifyRoomFeeInfo.records = res.records
  368 + let totalAmount = 0.0
  369 +
  370 + res.fees.forEach(item => {
  371 + totalAmount += parseFloat(item.amountOwed)
  372 + })
  373 +
  374 + this.simplifyRoomFeeInfo.totalAmount = totalAmount.toFixed(2)
  375 + this.simplifyRoomFeeInfo.fees = res.fees.sort(this.roomFeeCompare)
  376 + this.total = res.records
  377 + } catch (error) {
  378 + console.error('Failed to fetch fee list:', error)
  379 + }
  380 + },
  381 + roomFeeCompare(a, b) {
  382 + if (a.payerObjName < b.payerObjName) return -1
  383 + if (a.payerObjName > b.payerObjName) return 1
  384 + return 0
  385 + },
  386 + toOwnerPayFee() {
  387 + this.$router.push({
  388 + path: '/property/owePayFeeOrder',
  389 + query: {
  390 + payObjId: this.simplifyRoomFeeInfo.roomId,
  391 + payObjType: '3333',
  392 + roomName: this.simplifyRoomFeeInfo.roomName
  393 + }
  394 + })
  395 + },
  396 + openRoomCreateFeeAddModal() {
  397 + this.simplifyRoomFeeInfo.ownerName = this.simplifyRoomFeeInfo.name
  398 + this.$emit('openRoomCreateFeeAddModal', {
  399 + isMore: false,
  400 + room: this.simplifyRoomFeeInfo,
  401 + ownerName: this.simplifyRoomFeeInfo.name
  402 + })
  403 + },
  404 + openAddMeterWaterSimplifyModal() {
  405 + this.$emit('openAddMeterWaterModal', {
  406 + roomId: this.simplifyRoomFeeInfo.roomId,
  407 + roomName: this.simplifyRoomFeeInfo.roomName,
  408 + ownerName: this.simplifyRoomFeeInfo.name
  409 + })
  410 + },
  411 + getAttrValue(attrs, specCd) {
  412 + const attr = attrs.find(item => item.specCd === specCd)
  413 + return attr ? attr.value : ""
  414 + },
  415 + getDeadlineTime(fee) {
  416 + if (fee.amountOwed == 0 && fee.endTime == fee.deadlineTime) return "-"
  417 + if (fee.state == '2009001') return "-"
  418 + return dateFormat(fee.deadlineTime)
  419 + },
  420 + getEndTime(fee) {
  421 + if (fee.state == '2009001') return "-"
  422 + return dateFormat(fee.endTime)
  423 + },
  424 + openProxyFeeModal() {
  425 + this.$emit('openAddProxyFeeModal', {
  426 + roomId: this.simplifyRoomFeeInfo.roomId,
  427 + roomName: this.simplifyRoomFeeInfo.roomName,
  428 + ownerName: this.simplifyRoomFeeInfo.name
  429 + })
  430 + },
  431 + payFee(fee) {
  432 + fee.roomName = this.simplifyRoomFeeInfo.roomName
  433 + fee.builtUpArea = this.simplifyRoomFeeInfo.builtUpArea
  434 + this.$router.push({
  435 + path: '/property/payFeeOrder',
  436 + query: { feeId: fee.feeId }
  437 + })
  438 + },
  439 + editFee(fee) {
  440 + fee.maxEndTime = this.getAttrValue(fee.feeAttrs, '390010')
  441 + this.$refs.editFee.open(fee)
  442 + },
  443 + payFeeHis(fee) {
  444 + fee.builtUpArea = this.simplifyRoomFeeInfo.builtUpArea
  445 + this.$router.push({
  446 + path: '/views/fee/propertyFee',
  447 + query: fee
  448 + })
  449 + },
  450 + deleteFee(fee) {
  451 + this.$emit('openDeleteFeeModal', {
  452 + communityId: getCommunityId(),
  453 + feeId: fee.feeId
  454 + })
  455 + },
  456 + finishFee(fee) {
  457 + this.$emit('openFinishFeeModal', {
  458 + communityId: getCommunityId(),
  459 + feeId: fee.feeId
  460 + })
  461 + },
  462 + openTempImportRoomFeeModal() {
  463 + this.$refs.tempImportRoomFee.open({
  464 + roomId: this.simplifyRoomFeeInfo.roomId,
  465 + roomName: this.simplifyRoomFeeInfo.roomName,
  466 + ownerName: this.simplifyRoomFeeInfo.name
  467 + })
  468 + },
  469 + clearSimplifyRoomFeeInfo() {
  470 + const feeConfigs = this.simplifyRoomFeeInfo.feeConfigs
  471 + this.simplifyRoomFeeInfo = {
  472 + total: 0,
  473 + records: 1,
  474 + fees: [],
  475 + monthFees: [],
  476 + accounts: [],
  477 + roomId: '',
  478 + name: '',
  479 + roomName: '',
  480 + floorNum: '',
  481 + unitNum: '',
  482 + roomNum: '',
  483 + feeConfigs: feeConfigs,
  484 + feeTypeCd: '',
  485 + configId: '',
  486 + state: '2008001',
  487 + totalAmount: 0.0,
  488 + roomType: '',
  489 + ownerFee: 'N',
  490 + ownerId: '',
  491 + showFlag: 'DEFAULT'
  492 + }
  493 + },
  494 + changeSimplifyRoomFeeFeeTypeCd(feeTypeCd) {
  495 + this.simplifyRoomFeeInfo.configId = ''
  496 + this.$emit('notify', {})
  497 +
  498 + const params = {
  499 + page: 1,
  500 + row: 50,
  501 + communityId: getCommunityId(),
  502 + feeTypeCd: feeTypeCd,
  503 + isDefault: '',
  504 + valid: '1'
  505 + }
  506 +
  507 + listFeeConfigs(params).then(res => {
  508 + this.simplifyRoomFeeInfo.feeConfigs = res.feeConfigs
  509 + }).catch(error => {
  510 + console.error('Failed to fetch fee configs:', error)
  511 + })
  512 + },
  513 + changeSimplifyRoomConfigId() {
  514 + this.$emit('notify', {})
  515 + },
  516 + simplifyRoomGetFeeOwnerInfo(attrs) {
  517 + const ownerName = this.getAttrValue(attrs, '390008')
  518 + const ownerLink = this.getAttrValue(attrs, '390009')
  519 + return `业主:${ownerName},电话:${ownerLink}`
  520 + },
  521 + getSimplifyRoomFeeRoomName(fee) {
  522 + if (this.simplifyRoomFeeInfo.ownerFee != 'Y') return ''
  523 +
  524 + const attr = fee.feeAttrs.find(item => item.specCd === '390012')
  525 + return attr ? `(${attr.value})` : ''
  526 + },
  527 + openBatchPayRoomFeeModal() {
  528 + this.$router.push({
  529 + path: '/views/fee/batchPayFeeOrder',
  530 + query: {
  531 + ownerId: this.simplifyRoomFeeInfo.ownerId,
  532 + payerObjType: '3333'
  533 + }
  534 + })
  535 + },
  536 + openMonthPayRoomFeeModal() {
  537 + this.$router.push({
  538 + path: '/property/payFeeMonthOrder',
  539 + query: {
  540 + payerObjId: this.simplifyRoomFeeInfo.roomId,
  541 + payerObjType: '3333'
  542 + }
  543 + })
  544 + },
  545 + openRoomCreateFeeComboModal() {
  546 + this.$router.push({
  547 + path: '/property/createFeeByCombo',
  548 + query: {
  549 + payerObjId: this.simplifyRoomFeeInfo.roomId,
  550 + payerObjName: this.simplifyRoomFeeInfo.roomName,
  551 + payerObjType: '3333'
  552 + }
  553 + })
  554 + },
  555 + viewRoomFeeConfig(fee) {
  556 + const params = {
  557 + page: 1,
  558 + row: 1,
  559 + communityId: getCommunityId(),
  560 + configId: fee.configId
  561 + }
  562 +
  563 + listFeeConfigs(params).then(res => {
  564 + const feeConfig = res.feeConfigs[0]
  565 + this.$emit('openViewDataModal', {
  566 + title: `${fee.feeName} 费用项`,
  567 + data: {
  568 + "费用项ID": feeConfig.configId,
  569 + "费用类型": feeConfig.feeTypeCdName,
  570 + "收费项目": feeConfig.feeName,
  571 + "费用标识": feeConfig.feeFlagName,
  572 + "催缴类型": feeConfig.billTypeName,
  573 + "付费类型": feeConfig.paymentCd == '1200' ? '预付费' : '后付费',
  574 + "缴费周期": feeConfig.paymentCycle,
  575 + "应收开始时间": feeConfig.startTime,
  576 + "应收结束时间": feeConfig.endTime,
  577 + "公式": feeConfig.computingFormulaName,
  578 + "计费单价": feeConfig.computingFormula == '2002' ? '-' : feeConfig.squarePrice,
  579 + "附加/固定费用": feeConfig.additionalAmount
  580 + }
  581 + })
  582 + }).catch(error => {
  583 + console.error('Failed to fetch fee config:', error)
  584 + })
  585 + },
  586 + viewRoomFee(fee) {
  587 + const data = {
  588 + "费用ID": fee.feeId,
  589 + "费用标识": fee.feeFlagName,
  590 + "费用类型": fee.feeTypeCdName,
  591 + "付费对象": fee.payerObjName,
  592 + "费用项": fee.feeName,
  593 + "费用状态": fee.stateName,
  594 + "建账时间": fee.startTime,
  595 + "应收开始时间": this.getEndTime(fee),
  596 + "应收结束时间": this.getDeadlineTime(fee),
  597 + "批次": fee.batchId
  598 + }
  599 +
  600 + fee.feeAttrs.forEach(attr => {
  601 + data[attr.specCdName] = attr.value
  602 + })
  603 +
  604 + this.$emit('openViewDataModal', {
  605 + title: `${fee.feeName} 详情`,
  606 + data: data
  607 + })
  608 + },
  609 + changeSimplifyRoomShowFlag() {
  610 + if (this.simplifyRoomFeeInfo.showFlag == 'MONTH') {
  611 + this.listSimplifyRoomMonthFee(1, this.pageSize)
  612 + } else {
  613 + this.listSimplifyRoomFee(1, this.pageSize)
  614 + }
  615 + },
  616 + async listSimplifyRoomMonthFee(page, row) {
  617 + const params = {
  618 + page,
  619 + row,
  620 + communityId: getCommunityId(),
  621 + objId: this.simplifyRoomFeeInfo.roomId,
  622 + payerObjType: '3333',
  623 + configId: this.simplifyRoomFeeInfo.configId,
  624 + feeTypeCd: this.simplifyRoomFeeInfo.feeTypeCd,
  625 + detailId: '-1',
  626 + feeState: '2008001'
  627 + }
  628 +
  629 + if (this.simplifyRoomFeeInfo.ownerFee == 'Y') {
  630 + params.payerObjId = ''
  631 + params.ownerId = this.simplifyRoomFeeInfo.ownerId
  632 + }
  633 +
  634 + try {
  635 + const res = await listMonthFee(params)
  636 + this.simplifyRoomFeeInfo.total = res.total
  637 + this.simplifyRoomFeeInfo.records = res.records
  638 + let totalAmount = 0.0
  639 +
  640 + res.data.forEach(item => {
  641 + totalAmount += parseFloat(item.receivableAmount)
  642 + })
  643 +
  644 + this.simplifyRoomFeeInfo.totalAmount = totalAmount.toFixed(2)
  645 + this.simplifyRoomFeeInfo.monthFees = res.data
  646 + } catch (error) {
  647 + console.error('Failed to fetch month fee list:', error)
  648 + }
  649 + },
  650 + handleCurrentChange(page) {
  651 + this.currentPage = page
  652 + if (this.simplifyRoomFeeInfo.showFlag == 'MONTH') {
  653 + this.listSimplifyRoomMonthFee(page, this.pageSize)
  654 + } else {
  655 + this.listSimplifyRoomFee(page, this.pageSize)
  656 + }
  657 + },
  658 + // 其他方法类似
  659 + }
  660 +}
  661 +</script>
  662 +
  663 +<style scoped>
  664 +.margin-top-lg {
  665 + margin-top: 20px;
  666 +}
  667 +
  668 +.margin-top {
  669 + margin-top: 15px;
  670 +}
  671 +
  672 +.text-right {
  673 + text-align: right;
  674 +}
  675 +
  676 +.hand {
  677 + cursor: pointer;
  678 +}
  679 +</style>
0 \ No newline at end of file 680 \ No newline at end of file
src/components/fee/simplifyRoomFeeDemo.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <simplify-room-fee ref="simplifyRoomFee"></simplify-room-fee>
  4 + </div>
  5 +</template>
  6 +
  7 +<script>
  8 +import SimplifyRoomFee from './simplifyRoomFee'
  9 +
  10 +export default {
  11 + name: 'SimplifyRoomFeeDemo',
  12 + components: {
  13 + SimplifyRoomFee
  14 + },
  15 + mounted() {
  16 + this.$refs.simplifyRoomFee.$emit('switch', {
  17 + roomId: '123',
  18 + roomName: '测试房间',
  19 + name: '测试业主'
  20 + })
  21 + }
  22 +}
  23 +</script>
0 \ No newline at end of file 24 \ No newline at end of file
src/components/fee/tempImportRoomFee.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('tempImportRoomFee.title')"
  4 + :visible.sync="dialogVisible"
  5 + width="70%"
  6 + @close="clearTempImportRoomFeeInfo"
  7 + >
  8 + <el-form :model="form" label-width="120px">
  9 + <el-form-item :label="$t('tempImportRoomFee.feeType')">
  10 + <el-select
  11 + v-model="form.feeTypeCd"
  12 + @change="changeFeeTypeCd"
  13 + :placeholder="$t('tempImportRoomFee.selectFeeType')"
  14 + >
  15 + <el-option
  16 + v-for="(item,index) in feeTypeCds"
  17 + :key="index"
  18 + :label="item.name"
  19 + :value="item.statusCd"
  20 + ></el-option>
  21 + </el-select>
  22 + </el-form-item>
  23 +
  24 + <el-form-item :label="$t('tempImportRoomFee.feeObj')">
  25 + <el-input
  26 + v-model="form.objName"
  27 + disabled
  28 + :placeholder="$t('tempImportRoomFee.inputFeeObj')"
  29 + ></el-input>
  30 + </el-form-item>
  31 +
  32 + <el-form-item :label="$t('tempImportRoomFee.feeName')" v-if="form.feeNameFlag === 'S'">
  33 + <el-select
  34 + v-model="form.configId"
  35 + :placeholder="$t('tempImportRoomFee.selectFeeItem')"
  36 + >
  37 + <el-option
  38 + v-for="(item,index) in feeConfigs"
  39 + :key="index"
  40 + :label="item.feeName"
  41 + :value="item.configId"
  42 + ></el-option>
  43 + </el-select>
  44 + <span>{{$t('tempImportRoomFee.feeItemDesc')}}</span>
  45 + </el-form-item>
  46 +
  47 + <el-form-item :label="$t('tempImportRoomFee.feeName')" v-else>
  48 + <el-col :span="18">
  49 + <el-input
  50 + v-model="form.feeName"
  51 + :placeholder="$t('tempImportRoomFee.inputFeeName')"
  52 + ></el-input>
  53 + </el-col>
  54 + <el-col :span="6">
  55 + <el-button @click="toggleFeeNameFlag">{{$t('tempImportRoomFee.select')}}</el-button>
  56 + </el-col>
  57 + </el-form-item>
  58 +
  59 + <el-form-item :label="$t('tempImportRoomFee.amount')">
  60 + <el-input
  61 + v-model="form.amount"
  62 + :placeholder="$t('tempImportRoomFee.inputAmount')"
  63 + ></el-input>
  64 + </el-form-item>
  65 +
  66 + <el-form-item :label="$t('tempImportRoomFee.startTime')">
  67 + <el-date-picker
  68 + v-model="form.startTime"
  69 + type="datetime"
  70 + :placeholder="$t('tempImportRoomFee.selectStartTime')"
  71 + value-format="yyyy-MM-dd HH:mm:ss"
  72 + ></el-date-picker>
  73 + </el-form-item>
  74 +
  75 + <el-form-item :label="$t('tempImportRoomFee.endTime')">
  76 + <el-date-picker
  77 + v-model="form.endTime"
  78 + type="datetime"
  79 + :placeholder="$t('tempImportRoomFee.selectEndTime')"
  80 + value-format="yyyy-MM-dd HH:mm:ss"
  81 + ></el-date-picker>
  82 + </el-form-item>
  83 + </el-form>
  84 +
  85 + <div slot="footer" class="dialog-footer">
  86 + <el-button @click="dialogVisible = false">{{$t('tempImportRoomFee.cancel')}}</el-button>
  87 + <el-button type="primary" @click="saveTempImportFeeInfo">{{$t('tempImportRoomFee.submit')}}</el-button>
  88 + </div>
  89 + </el-dialog>
  90 +</template>
  91 +
  92 +<script>
  93 +import { importTempData } from '@/api/fee/tempImportRoomFeeApi'
  94 +import { getDict } from '@/api/community/communityApi'
  95 +import { getCommunityId } from '@/api/community/communityApi'
  96 +import { listFeeConfigs } from '@/api/fee/feeConfigManageApi'
  97 +export default {
  98 + name: 'TempImportRoomFee',
  99 + data() {
  100 + return {
  101 + dialogVisible: false,
  102 + form: {
  103 + communityId: '',
  104 + feeTypeCd: '',
  105 + objType: '',
  106 + feeTypeCds: [],
  107 + configId: '',
  108 + objName: '',
  109 + objId: '',
  110 + amount: '',
  111 + startTime: this.formatDate(new Date()),
  112 + endTime: this.addMonth(new Date(), 1),
  113 + feeConfigs: [],
  114 + feeNameFlag: 'S'
  115 + },
  116 + feeTypeCds: [],
  117 + feeConfigs: [],
  118 + communityId: ''
  119 + }
  120 + },
  121 + created() {
  122 + this.communityId = getCommunityId()
  123 + this.loadDictData()
  124 + },
  125 + methods: {
  126 + open(room) {
  127 + this.clearTempImportRoomFeeInfo()
  128 + this.form.objId = room.roomId
  129 + this.form.objName = room.roomName
  130 + this.form.objType = room.objType
  131 + this.dialogVisible = true
  132 + },
  133 + async loadDictData() {
  134 + try {
  135 + const data = await getDict('pay_fee_config', 'fee_type_cd')
  136 + this.feeTypeCds = data
  137 + this.form.feeTypeCds = data
  138 + } catch (error) {
  139 + console.error('获取字典数据失败:', error)
  140 + }
  141 + },
  142 + async changeFeeTypeCd(feeTypeCd) {
  143 + try {
  144 + const res = await listFeeConfigs({
  145 + page: 1,
  146 + row: 500,
  147 + communityId: this.communityId,
  148 + feeTypeCd: feeTypeCd,
  149 + isDefault: 'F',
  150 + computingFormula: '4004',
  151 + valid: '1'
  152 + })
  153 + this.feeConfigs = res.feeConfigs
  154 + } catch (error) {
  155 + console.error('获取费用配置失败:', error)
  156 + }
  157 + },
  158 + toggleFeeNameFlag() {
  159 + this.form.feeNameFlag = this.form.feeNameFlag === 'S' ? 'I' : 'S'
  160 + },
  161 + validateForm() {
  162 + if (!this.form.feeTypeCd) {
  163 + this.$message.warning(this.$t('tempImportRoomFee.feeTypeRequired'))
  164 + return false
  165 + }
  166 + if (!this.form.configId && this.form.feeNameFlag === 'S') {
  167 + this.$message.warning(this.$t('tempImportRoomFee.feeNameRequired'))
  168 + return false
  169 + }
  170 + if (!this.form.objId) {
  171 + this.$message.warning(this.$t('tempImportRoomFee.feeObjRequired'))
  172 + return false
  173 + }
  174 + if (!this.form.startTime) {
  175 + this.$message.warning(this.$t('tempImportRoomFee.startTimeRequired'))
  176 + return false
  177 + }
  178 + if (!this.form.endTime) {
  179 + this.$message.warning(this.$t('tempImportRoomFee.endTimeRequired'))
  180 + return false
  181 + }
  182 + if (new Date(this.form.startTime) >= new Date(this.form.endTime)) {
  183 + this.$message.warning(this.$t('tempImportRoomFee.endTimeMustAfterStart'))
  184 + return false
  185 + }
  186 + if (!this.form.amount) {
  187 + this.$message.warning(this.$t('tempImportRoomFee.amountRequired'))
  188 + return false
  189 + }
  190 + return true
  191 + },
  192 + async saveTempImportFeeInfo() {
  193 + if (!this.validateForm()) return
  194 +
  195 + try {
  196 + const res = await importTempData({
  197 + ...this.form,
  198 + communityId: this.communityId
  199 + })
  200 + if (res.code === 0) {
  201 + this.dialogVisible = false
  202 + this.$emit('notify')
  203 + this.$message.success(this.$t('tempImportRoomFee.createSuccess'))
  204 + } else {
  205 + this.$message.error(res.msg)
  206 + }
  207 + } catch (error) {
  208 + console.error('请求失败:', error)
  209 + this.$message.error(this.$t('tempImportRoomFee.createFailed'))
  210 + }
  211 + },
  212 + clearTempImportRoomFeeInfo() {
  213 + this.form = {
  214 + communityId: this.communityId,
  215 + feeTypeCd: '',
  216 + feeTypeCds: this.feeTypeCds,
  217 + configId: '',
  218 + objName: '',
  219 + objId: '',
  220 + amount: '',
  221 + startTime: this.formatDate(new Date()),
  222 + endTime: this.addMonth(new Date(), 1),
  223 + feeNameFlag: 'S',
  224 + feeConfigs: []
  225 + }
  226 + },
  227 + formatDate(date) {
  228 + const year = date.getFullYear()
  229 + const month = String(date.getMonth() + 1).padStart(2, '0')
  230 + const day = String(date.getDate()).padStart(2, '0')
  231 + const hours = String(date.getHours()).padStart(2, '0')
  232 + const minutes = String(date.getMinutes()).padStart(2, '0')
  233 + const seconds = String(date.getSeconds()).padStart(2, '0')
  234 + return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
  235 + },
  236 + addMonth(date, months) {
  237 + const newDate = new Date(date)
  238 + newDate.setMonth(newDate.getMonth() + months)
  239 + return this.formatDate(newDate)
  240 + }
  241 + }
  242 +}
  243 +</script>
0 \ No newline at end of file 244 \ No newline at end of file
src/components/fee/tempImportRoomFeeDemo.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 + <el-button @click="openModal">{{$t('tempImportRoomFeeDemo.openModal')}}</el-button>
  4 + <temp-import-room-fee ref="tempImportRoomFee"></temp-import-room-fee>
  5 + </div>
  6 +</template>
  7 +
  8 +<script>
  9 +import TempImportRoomFee from './tempImportRoomFee'
  10 +
  11 +export default {
  12 + name: 'TempImportRoomFeeDemo',
  13 + components: {
  14 + TempImportRoomFee
  15 + },
  16 + methods: {
  17 + openModal() {
  18 + this.$refs.tempImportRoomFee.open({
  19 + roomId: '123',
  20 + roomName: '测试房间',
  21 + ownerName: '测试业主'
  22 + })
  23 + }
  24 + }
  25 +}
  26 +</script>
0 \ No newline at end of file 27 \ No newline at end of file
src/components/fee/viewFeeConfigData.vue 0 → 100644
  1 +<template>
  2 + <el-tooltip effect="dark" content="查看详情" placement="top">
  3 + <i class="el-icon-info hand" @click="open"></i>
  4 + </el-tooltip>
  5 +</template>
  6 +
  7 +<script>
  8 +import { getCommunityId } from '@/api/community/communityApi'
  9 +import { listFeeConfigs } from '@/api/fee/propertyFeeApi'
  10 +
  11 +export default {
  12 + name: 'ViewFeeConfigData',
  13 + data() {
  14 + return {
  15 + configId: '',
  16 + communityId: ''
  17 + }
  18 + },
  19 + created() {
  20 + this.communityId = getCommunityId()
  21 + },
  22 + methods: {
  23 + open(params) {
  24 + this.configId = params.configId
  25 + this._loadFeeConfigData()
  26 + },
  27 + async _loadFeeConfigData() {
  28 + try {
  29 + const res = await listFeeConfigs({
  30 + page: 1,
  31 + row: 1,
  32 + communityId: this.communityId,
  33 + configId: this.configId
  34 + })
  35 +
  36 + if (res.data && res.data.length > 0) {
  37 + const feeConfig = res.data[0]
  38 + const configData = {
  39 + "费用项ID": feeConfig.configId,
  40 + "费用类型": feeConfig.feeTypeCdName,
  41 + "收费项目": feeConfig.feeName,
  42 + "费用标识": feeConfig.feeFlagName,
  43 + "催缴类型": feeConfig.billTypeName,
  44 + "付费类型": feeConfig.paymentCd === '1200' ? this.$t('viewFeeConfigData.prepaid') : this.$t('viewFeeConfigData.postpaid'),
  45 + "缴费周期": feeConfig.paymentCycle,
  46 + "计费起始时间": feeConfig.startTime,
  47 + "计费终止时间": feeConfig.endTime,
  48 + "公式": feeConfig.computingFormulaName,
  49 + "计费单价": feeConfig.computingFormula === '2002' ? '-' : feeConfig.squarePrice,
  50 + "附加/固定费用": feeConfig.additionalAmount
  51 + }
  52 +
  53 + this.$emit('openViewDataModal', {
  54 + title: `${feeConfig.feeName} ${this.$t('viewFeeConfigData.feeItem')}`,
  55 + data: configData
  56 + })
  57 + }
  58 + } catch (error) {
  59 + console.error('加载费用配置数据失败:', error)
  60 + }
  61 + }
  62 + }
  63 +}
  64 +</script>
  65 +
  66 +<style scoped>
  67 +.hand {
  68 + cursor: pointer;
  69 + color: #409EFF;
  70 + margin-left: 5px;
  71 +}
  72 +</style>
0 \ No newline at end of file 73 \ No newline at end of file
src/components/fee/viewFeeDetailDiscount.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('viewFeeDetailDiscount.discount')"
  4 + :visible.sync="visible"
  5 + width="70%"
  6 + center
  7 + >
  8 + <el-table
  9 + :data="viewFeeDetailDiscountInfo.feeDetailDiscounts"
  10 + border
  11 + stripe
  12 + style="width: 100%"
  13 + >
  14 + <el-table-column
  15 + prop="discountName"
  16 + :label="$t('viewFeeDetailDiscount.discountName')"
  17 + align="center"
  18 + />
  19 + <el-table-column
  20 + :label="$t('viewFeeDetailDiscount.discountType')"
  21 + align="center"
  22 + >
  23 + <template slot-scope="scope">
  24 + {{ scope.row.discountType === '1001' ? $t('viewFeeDetailDiscount.discount') : $t('viewFeeDetailDiscount.breach') }}
  25 + </template>
  26 + </el-table-column>
  27 + <el-table-column
  28 + prop="ruleName"
  29 + :label="$t('viewFeeDetailDiscount.ruleName')"
  30 + align="center"
  31 + />
  32 + <el-table-column
  33 + :label="$t('viewFeeDetailDiscount.discountRule')"
  34 + align="center"
  35 + >
  36 + <template slot-scope="scope">
  37 + <div v-for="(item,index) in scope.row.feeDiscountSpecs" :key="index">
  38 + {{item.specName}}:{{item.specValue}}
  39 + </div>
  40 + </template>
  41 + </el-table-column>
  42 + <el-table-column
  43 + prop="discountPrice"
  44 + :label="$t('viewFeeDetailDiscount.discountAmount')"
  45 + align="center"
  46 + />
  47 + </el-table>
  48 + </el-dialog>
  49 +</template>
  50 +
  51 +<script>
  52 +import { getCommunityId } from '@/api/community/communityApi'
  53 +import { queryFeeDetailDiscount } from '@/api/fee/propertyFeeApi'
  54 +
  55 +export default {
  56 + name: 'ViewFeeDetailDiscount',
  57 + data() {
  58 + return {
  59 + visible: false,
  60 + viewFeeDetailDiscountInfo: {
  61 + feeDetailDiscounts: []
  62 + },
  63 + communityId: ''
  64 + }
  65 + },
  66 + created() {
  67 + this.communityId = getCommunityId()
  68 + },
  69 + methods: {
  70 + open(params) {
  71 + this.visible = true
  72 + this._loadAllFeeDetailDiscountInfo(params)
  73 + },
  74 + async _loadAllFeeDetailDiscountInfo(params) {
  75 + try {
  76 + const res = await queryFeeDetailDiscount({
  77 + page: 1,
  78 + row: 30,
  79 + communityId: this.communityId,
  80 + detailId: params.detailId
  81 + })
  82 +
  83 + this.viewFeeDetailDiscountInfo.feeDetailDiscounts = res.data || []
  84 + } catch (error) {
  85 + console.error('加载折扣信息失败:', error)
  86 + }
  87 + }
  88 + }
  89 +}
  90 +</script>
  91 +
  92 +<style scoped>
  93 +.el-table {
  94 + margin-top: 15px;
  95 +}
  96 +</style>
0 \ No newline at end of file 97 \ No newline at end of file
src/components/fee/viewMainFee.vue 0 → 100644
  1 +<template>
  2 + <el-card class="box-card">
  3 + <div slot="header" class="clearfix">
  4 + <span>{{ $t('viewMainFee.feeInfo') }}</span>
  5 + <el-button
  6 + type="primary"
  7 + size="small"
  8 + style="float: right; margin-left: 10px;"
  9 + @click="_openCallBackOwner"
  10 + >
  11 + {{ $t('common.back') }}
  12 + </el-button>
  13 + </div>
  14 +
  15 + <el-row :gutter="20">
  16 + <el-col :span="6">
  17 + <div class="form-item">
  18 + <label>{{ $t('viewMainFee.feeId') }}</label>
  19 + <div>{{ mainFeeInfo.feeId }}</div>
  20 + </div>
  21 + </el-col>
  22 + <el-col :span="6">
  23 + <div class="form-item">
  24 + <label>{{ $t('viewMainFee.feeFlag') }}</label>
  25 + <div>{{ mainFeeInfo.feeFlagName }}</div>
  26 + </div>
  27 + </el-col>
  28 + <el-col :span="6">
  29 + <div class="form-item">
  30 + <label>{{ $t('viewMainFee.feeType') }}</label>
  31 + <div>{{ mainFeeInfo.feeTypeCdName }}</div>
  32 + </div>
  33 + </el-col>
  34 + <el-col :span="6">
  35 + <div class="form-item">
  36 + <label>{{ $t('viewMainFee.payerObj') }}</label>
  37 + <div>
  38 + {{ mainFeeInfo.payerObjName }}
  39 + <view-room-data
  40 + v-if="mainFeeInfo.payerObjType == '3333'"
  41 + ref="viewRoomData"
  42 + />
  43 + </div>
  44 + </div>
  45 + </el-col>
  46 +
  47 + <el-col :span="6">
  48 + <div class="form-item">
  49 + <label>{{ $t('viewMainFee.feeItem') }}</label>
  50 + <div class="hand" @click="_viewFeeConfig">
  51 + {{ mainFeeInfo.feeName }}
  52 + <view-fee-config-data ref="viewFeeConfigData" />
  53 + </div>
  54 + </div>
  55 + </el-col>
  56 + <el-col :span="6">
  57 + <div class="form-item">
  58 + <label>{{ $t('viewMainFee.feeStatus') }}</label>
  59 + <div>{{ mainFeeInfo.stateName }}</div>
  60 + </div>
  61 + </el-col>
  62 + <el-col :span="6">
  63 + <div class="form-item">
  64 + <label>{{ $t('viewMainFee.startTime') }}</label>
  65 + <div>{{ mainFeeInfo.startTime }}</div>
  66 + </div>
  67 + </el-col>
  68 + <el-col :span="6">
  69 + <div class="form-item">
  70 + <label>{{ $t('viewMainFee.billingStartTime') }}</label>
  71 + <div>{{ _getEndTime(mainFeeInfo) }}</div>
  72 + </div>
  73 + </el-col>
  74 +
  75 + <el-col :span="6">
  76 + <div class="form-item">
  77 + <label>{{ $t('viewMainFee.billingEndTime') }}</label>
  78 + <div>{{ _getDeadlineTime(mainFeeInfo) }}</div>
  79 + </div>
  80 + </el-col>
  81 + <el-col :span="6" v-if="mainFeeInfo.amount != '-1.00'">
  82 + <div class="form-item">
  83 + <label>{{ $t('viewMainFee.feeAmount') }}</label>
  84 + <div>{{ mainFeeInfo.amount }}</div>
  85 + </div>
  86 + </el-col>
  87 + <el-col :span="6">
  88 + <div class="form-item">
  89 + <label>{{ $t('viewMainFee.batch') }}</label>
  90 + <div>{{ mainFeeInfo.batchId }}</div>
  91 + </div>
  92 + </el-col>
  93 +
  94 + <template v-for="(item,index) in mainFeeInfo.feeAttrs">
  95 + <el-col :span="6" :key="index">
  96 + <div class="form-item">
  97 + <label>{{ item.specCdName }}:</label>
  98 + <div>{{ item.value }}</div>
  99 + </div>
  100 + </el-col>
  101 + </template>
  102 + </el-row>
  103 +
  104 + <el-row :gutter="20" v-if="mainFeeInfo.payerObjType == '3333'">
  105 + <el-col :span="6">
  106 + <div class="form-item">
  107 + <label>{{ $t('viewMainFee.area') }}</label>
  108 + <div>{{ mainFeeInfo.builtUpArea }}</div>
  109 + </div>
  110 + </el-col>
  111 + <el-col :span="6">
  112 + <div class="form-item">
  113 + <label>{{ $t('viewMainFee.unitPrice') }}</label>
  114 + <div>{{ mainFeeInfo.squarePrice }}</div>
  115 + </div>
  116 + </el-col>
  117 + <el-col :span="6">
  118 + <div class="form-item">
  119 + <label>{{ $t('viewMainFee.additionalFee') }}</label>
  120 + <div>{{ mainFeeInfo.additionalAmount }}</div>
  121 + </div>
  122 + </el-col>
  123 + </el-row>
  124 +
  125 + <el-row :gutter="20" v-else>
  126 + <el-col :span="6">
  127 + <div class="form-item">
  128 + <label>{{ $t('viewMainFee.fixedFee') }}</label>
  129 + <div>{{ mainFeeInfo.additionalAmount }}</div>
  130 + </div>
  131 + </el-col>
  132 + </el-row>
  133 + </el-card>
  134 +</template>
  135 +
  136 +<script>
  137 +import { getCommunityId } from '@/api/community/communityApi'
  138 +import { listFee } from '@/api/fee/propertyFeeApi'
  139 +import ViewRoomData from './viewRoomData'
  140 +import ViewFeeConfigData from './viewFeeConfigData'
  141 +
  142 +export default {
  143 + name: 'ViewMainFee',
  144 + components: {
  145 + ViewRoomData,
  146 + ViewFeeConfigData
  147 + },
  148 + props: {
  149 + feeName: {
  150 + type: String,
  151 + required: true
  152 + },
  153 + feeTypeCd: {
  154 + type: String,
  155 + required: true
  156 + },
  157 + payName: {
  158 + type: String,
  159 + required: true
  160 + }
  161 + },
  162 + data() {
  163 + return {
  164 + mainFeeInfo: {
  165 + feeName: this.feeName,
  166 + feeId: "",
  167 + feeTypeCd: '',
  168 + builtUpArea: "",
  169 + startTime: "",
  170 + endTime: "",
  171 + amount: "-1.00",
  172 + feeFlagName: '',
  173 + feeTypeCdName: '',
  174 + configId: '',
  175 + stateName: '',
  176 + additionalAmount: 0.0,
  177 + squarePrice: 0,
  178 + deadlineTime: '',
  179 + payerObjType: '',
  180 + payerObjId: '',
  181 + payerObjName: '',
  182 + feeAttrs: [],
  183 + batchId: ''
  184 + },
  185 + communityId: ''
  186 + }
  187 + },
  188 + created() {
  189 + this.communityId = getCommunityId()
  190 + const feeId = this.$route.query.feeId
  191 + if (feeId) {
  192 + this.loadMainFeeInfo({ feeId })
  193 + }
  194 + },
  195 + methods: {
  196 + async loadMainFeeInfo(params) {
  197 + try {
  198 + const res = await listFee({
  199 + ...params,
  200 + communityId: this.communityId,
  201 + page: 1,
  202 + row: 1
  203 + })
  204 +
  205 + if (res.data && res.data.length > 0) {
  206 + Object.assign(this.mainFeeInfo, res.data[0])
  207 + this.mainFeeInfo.feeAttrs = res.data[0].feeAttrs || []
  208 +
  209 + if (this.mainFeeInfo.payerObjType === '3333') {
  210 + this._loadRoomAndOwnerByRoomId()
  211 + } else if (this.mainFeeInfo.payerObjType === '6666') {
  212 + this._loadRoomAndOwnerByCarId()
  213 + } else {
  214 + this._loadContractAndOwnerByContractId()
  215 + }
  216 +
  217 + this.$emit('listFeeDetail', { feeId: this.mainFeeInfo.feeId })
  218 + }
  219 + } catch (error) {
  220 + console.error('加载主费用信息失败:', error)
  221 + }
  222 + },
  223 + _openCallBackOwner() {
  224 + this.$router.go(-1)
  225 + },
  226 + _getDeadlineTime(fee) {
  227 + if (fee.endTime === fee.deadlineTime || fee.state === '2009001') {
  228 + return "-"
  229 + }
  230 + return fee.deadlineTime
  231 + },
  232 + _getEndTime(fee) {
  233 + if (fee.state === '2009001') {
  234 + return "-"
  235 + }
  236 + return fee.endTime
  237 + },
  238 + _viewFeeConfig() {
  239 + this.$refs.viewFeeConfigData.open({ configId: this.mainFeeInfo.configId })
  240 + },
  241 + _viewRoomData() {
  242 + this.$refs.viewRoomData.open({ roomId: this.mainFeeInfo.payerObjId })
  243 + },
  244 + async _loadRoomAndOwnerByRoomId() {
  245 + // 实现获取房间和业主信息的逻辑
  246 + },
  247 + async _loadRoomAndOwnerByCarId() {
  248 + // 实现获取车位和业主信息的逻辑
  249 + },
  250 + async _loadContractAndOwnerByContractId() {
  251 + // 实现获取合同和业主信息的逻辑
  252 + }
  253 + }
  254 +}
  255 +</script>
  256 +
  257 +<style scoped>
  258 +.form-item {
  259 + margin-bottom: 20px;
  260 +
  261 + label {
  262 + display: block;
  263 + margin-bottom: 5px;
  264 + font-weight: bold;
  265 + }
  266 +
  267 + div {
  268 + padding: 8px 0;
  269 + }
  270 +}
  271 +
  272 +.hand {
  273 + cursor: pointer;
  274 + color: #409EFF;
  275 +
  276 + &:hover {
  277 + text-decoration: underline;
  278 + }
  279 +}
  280 +</style>
0 \ No newline at end of file 281 \ No newline at end of file
src/components/fee/viewRoomData.vue 0 → 100644
  1 +<template>
  2 + <el-tooltip effect="dark" content="查看详情" placement="top">
  3 + <i class="el-icon-info hand" @click="open"></i>
  4 + </el-tooltip>
  5 +</template>
  6 +
  7 +<script>
  8 +import { getCommunityId } from '@/api/community/communityApi'
  9 +import { queryRooms } from '@/api/fee/propertyFeeApi'
  10 +
  11 +export default {
  12 + name: 'ViewRoomData',
  13 + data() {
  14 + return {
  15 + roomId: '',
  16 + communityId: ''
  17 + }
  18 + },
  19 + created() {
  20 + this.communityId = getCommunityId()
  21 + },
  22 + methods: {
  23 + open(params) {
  24 + this.roomId = params.roomId
  25 + this._loadViewRoomData()
  26 + },
  27 + async _loadViewRoomData() {
  28 + try {
  29 + const res = await queryRooms({
  30 + page: 1,
  31 + row: 1,
  32 + communityId: this.communityId,
  33 + roomId: this.roomId
  34 + })
  35 +
  36 + if (res.data && res.data.length > 0) {
  37 + const room = res.data[0]
  38 + const roomData = {
  39 + "房屋": `${room.floorNum}-${room.unitNum}-${room.roomNum}`,
  40 + "楼层": room.layer,
  41 + "业主": room.ownerName || '-',
  42 + "电话": room.link || '-',
  43 + "类型": room.roomSubTypeName,
  44 + "建筑面积": room.builtUpArea,
  45 + "室内面积": room.roomArea,
  46 + "租金": room.roomRent,
  47 + "房屋状态": room.stateName,
  48 + "入住时间": room.startTime
  49 + }
  50 +
  51 + if (room.roomAttrDto) {
  52 + room.roomAttrDto.forEach(attr => {
  53 + roomData[attr.specName] = attr.valueName
  54 + })
  55 + }
  56 +
  57 + this.$emit('openViewDataModal', {
  58 + title: `${room.floorNum}-${room.unitNum}-${room.roomNum} 详情`,
  59 + data: roomData
  60 + })
  61 + }
  62 + } catch (error) {
  63 + console.error('加载房间数据失败:', error)
  64 + }
  65 + }
  66 + }
  67 +}
  68 +</script>
  69 +
  70 +<style scoped>
  71 +.hand {
  72 + cursor: pointer;
  73 + color: #409EFF;
  74 + margin-left: 5px;
  75 +}
  76 +</style>
0 \ No newline at end of file 77 \ No newline at end of file
src/components/fee/writeOweFeeCallable.vue
1 <template> 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> 2 + <el-dialog
  3 + :title="$t('writeOweFeeCallable.title')"
  4 + :visible.sync="dialogVisible"
  5 + width="70%"
  6 + :before-close="handleClose"
  7 + >
  8 + <div class="ibox-content">
  9 + <el-form label-width="120px">
  10 + <el-form-item :label="$t('writeOweFeeCallable.room')">
  11 + <el-input
  12 + v-model="writeOweFeeCallableInfo.roomName"
  13 + readonly
  14 + :placeholder="$t('writeOweFeeCallable.roomPlaceholder')"
  15 + ></el-input>
  16 + </el-form-item>
  17 + <el-form-item :label="$t('writeOweFeeCallable.fees')">
  18 + <el-checkbox-group v-model="writeOweFeeCallableInfo.feeIds">
  19 + <el-checkbox
  20 + v-for="(item,index) in writeOweFeeCallableInfo.fees"
  21 + :key="index"
  22 + :label="item.feeId"
  23 + >
  24 + {{item.feeName}}
  25 + </el-checkbox>
  26 + </el-checkbox-group>
  27 + </el-form-item>
  28 + <el-form-item :label="$t('writeOweFeeCallable.remark')">
  29 + <el-input
  30 + type="textarea"
  31 + :rows="5"
  32 + v-model="writeOweFeeCallableInfo.remark"
  33 + :placeholder="$t('writeOweFeeCallable.remarkPlaceholder')"
  34 + ></el-input>
  35 + </el-form-item>
  36 + </el-form>
  37 + </div>
20 <span slot="footer" class="dialog-footer"> 38 <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> 39 + <el-button @click="dialogVisible = false">{{ $t('writeOweFeeCallable.cancel') }}</el-button>
  40 + <el-button type="primary" @click="_wirteCallable">{{ $t('writeOweFeeCallable.submit') }}</el-button>
23 </span> 41 </span>
24 </el-dialog> 42 </el-dialog>
25 </template> 43 </template>
26 44
27 <script> 45 <script>
28 -import { listFee } from '@/api/fee/feeApi'  
29 -import { writeOweFeeCallable } from '@/api/fee/oweFeeCallableApi'  
30 import { getCommunityId } from '@/api/community/communityApi' 46 import { getCommunityId } from '@/api/community/communityApi'
  47 +import { writeOweFeeCallable, listFee } from '@/api/fee/writeOweFeeCallableApi'
31 48
32 export default { 49 export default {
33 name: 'WriteOweFeeCallable', 50 name: 'WriteOweFeeCallable',
34 data() { 51 data() {
35 return { 52 return {
36 dialogVisible: false, 53 dialogVisible: false,
37 - form: { 54 + writeOweFeeCallableInfo: {
38 roomId: '', 55 roomId: '',
39 roomName: '', 56 roomName: '',
40 fees: [], 57 fees: [],
41 feeIds: [], 58 feeIds: [],
42 - remark: '',  
43 - communityId: '' 59 + remark: ''
44 } 60 }
45 } 61 }
46 }, 62 },
  63 + created() {
  64 + this._initEvent()
  65 + },
47 methods: { 66 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() 67 + _initEvent() {
  68 + this.$on('openWriteOweFeeCallableModal', this.open)
  69 + },
  70 + open(param) {
  71 + Object.assign(this.writeOweFeeCallableInfo, param)
  72 + this._loadWriteOweRoomFees()
58 this.dialogVisible = true 73 this.dialogVisible = true
59 }, 74 },
60 - async loadFees() { 75 + handleClose(done) {
  76 + this.clearWriteOweFeeCallable()
  77 + done()
  78 + },
  79 + async _wirteCallable() {
61 try { 80 try {
62 const params = { 81 const params = {
63 - communityId: this.form.communityId,  
64 - payerObjId: this.form.roomId,  
65 - state: '2008001',  
66 - page: 1,  
67 - row: 100 82 + ...this.writeOweFeeCallableInfo,
  83 + communityId: getCommunityId()
  84 + }
  85 + const res = await writeOweFeeCallable(params)
  86 + if (res.code === 0) {
  87 + this.dialogVisible = false
  88 + this.clearWriteOweFeeCallable()
  89 + this.$emit('listOweFeeCallable', {})
  90 + this.$emit('listOwnerData', {})
  91 + this.$message.success(this.$t('writeOweFeeCallable.success'))
  92 + } else {
  93 + this.$message.error(res.msg)
68 } 94 }
69 - const response = await listFee(params)  
70 - this.form.fees = response.data.fees || []  
71 } catch (error) { 95 } catch (error) {
72 - console.error('加载费用数据失败:', error) 96 + console.error('Request failed:', error)
  97 + this.$message.error(error.message)
  98 + }
  99 + },
  100 + clearWriteOweFeeCallable() {
  101 + this.writeOweFeeCallableInfo = {
  102 + roomId: '',
  103 + roomName: '',
  104 + fees: [],
  105 + feeIds: [],
  106 + remark: ''
73 } 107 }
74 }, 108 },
75 - async handleSubmit() { 109 + async _loadWriteOweRoomFees() {
76 try { 110 try {
77 - await writeOweFeeCallable(this.form)  
78 - this.$message.success(this.$t('oweFeeCallable.write.success'))  
79 - this.dialogVisible = false  
80 - this.$emit('success') 111 + const res = await listFee({
  112 + page: 1,
  113 + row: 100,
  114 + communityId: getCommunityId(),
  115 + payerObjId: this.writeOweFeeCallableInfo.roomId,
  116 + state: '2008001'
  117 + })
  118 + this.writeOweFeeCallableInfo.fees = res.fees
81 } catch (error) { 119 } catch (error) {
82 - console.error('提交失败:', error)  
83 - this.$message.error(error.message || this.$t('oweFeeCallable.write.error')) 120 + console.error('Request failed:', error)
84 } 121 }
85 - },  
86 - handleClose() {  
87 - this.$refs.form.resetFields()  
88 } 122 }
89 } 123 }
90 } 124 }
91 -</script>  
92 -  
93 -<style lang="scss" scoped>  
94 -.el-checkbox {  
95 - margin-right: 15px;  
96 -}  
97 -</style>  
98 \ No newline at end of file 125 \ No newline at end of file
  126 +</script>
99 \ No newline at end of file 127 \ No newline at end of file
src/components/fee/writeOweFeeCallableDemo.vue 0 → 100644
  1 +<template>
  2 + <el-button @click="openModal">{{$t('writeOweFeeCallableDemo.openModal')}}</el-button>
  3 + <write-owe-fee-callable ref="writeOweFeeCallable"></write-owe-fee-callable>
  4 +</template>
  5 +
  6 +<script>
  7 +import WriteOweFeeCallable from './writeOweFeeCallable'
  8 +
  9 +export default {
  10 + name: 'WriteOweFeeCallableDemo',
  11 + components: {
  12 + WriteOweFeeCallable
  13 + },
  14 + methods: {
  15 + openModal() {
  16 + this.$refs.writeOweFeeCallable.open({
  17 + roomId: '123',
  18 + roomName: 'Test Room'
  19 + })
  20 + }
  21 + }
  22 +}
  23 +</script>
0 \ No newline at end of file 24 \ No newline at end of file
src/components/owner/ownerDetailAccount.vue
@@ -109,10 +109,6 @@ export default { @@ -109,10 +109,6 @@ export default {
109 }, 109 },
110 }, 110 },
111 created() { 111 created() {
112 - this.$on('switch', (data) => {  
113 - this.ownerDetailAccountInfo.ownerId = data.ownerId  
114 - this._loadOwnerDetailAccountData(1, this.pagination.pageSize)  
115 - })  
116 } 112 }
117 } 113 }
118 </script> 114 </script>
src/components/owner/ownerDetailAccountReceipt.vue
@@ -85,7 +85,7 @@ export default { @@ -85,7 +85,7 @@ export default {
85 } 85 }
86 86
87 listAccountReceipt(param).then(response => { 87 listAccountReceipt(param).then(response => {
88 - this.ownerDetailAccountReceiptInfo.feeReceipts = response.data.data.map(item => { 88 + this.ownerDetailAccountReceiptInfo.feeReceipts = response.data.map(item => {
89 return { ...item, checked: false } 89 return { ...item, checked: false }
90 }) 90 })
91 this.total = response.data.total 91 this.total = response.data.total
src/components/room/roomTreeDiv.vue
@@ -72,6 +72,21 @@ export default { @@ -72,6 +72,21 @@ export default {
72 }) 72 })
73 73
74 this.treeData = Object.values(floorMap) 74 this.treeData = Object.values(floorMap)
  75 + this.$nextTick(() => {
  76 + this.expandAndSelectFirstRoom()
  77 + })
  78 + },
  79 + async expandAndSelectFirstRoom() {
  80 + if (!this.treeData.length) return
  81 + const firstFloor = this.treeData[0]
  82 + if (!firstFloor.children || !firstFloor.children.length) return
  83 + const firstUnit = firstFloor.children[0]
  84 + const treeRef = this.$refs.tree
  85 + if (treeRef && treeRef.store) {
  86 + treeRef.store.nodesMap[firstFloor.id] && (treeRef.store.nodesMap[firstFloor.id].expanded = true)
  87 + treeRef.store.nodesMap[firstUnit.id] && (treeRef.store.nodesMap[firstUnit.id].expanded = true)
  88 + }
  89 + await this.loadRooms(firstUnit, { data: firstUnit })
75 }, 90 },
76 async handleNodeClick(data, node) { 91 async handleNodeClick(data, node) {
77 if (data.id.startsWith('u_')) { 92 if (data.id.startsWith('u_')) {
@@ -108,6 +123,10 @@ export default { @@ -108,6 +123,10 @@ export default {
108 123
109 // Update the node's children 124 // Update the node's children
110 this.$set(node.data, 'children', roomNodes) 125 this.$set(node.data, 'children', roomNodes)
  126 + this.$emit('selectRoom', {
  127 + roomId: roomNodes[0].roomId,
  128 + roomName: roomNodes[0].roomName
  129 + })
111 } 130 }
112 } catch (error) { 131 } catch (error) {
113 console.error('Failed to load rooms:', error) 132 console.error('Failed to load rooms:', error)
src/components/room/uploadImageUrl.vue
@@ -34,6 +34,7 @@ @@ -34,6 +34,7 @@
34 34
35 <script> 35 <script>
36 import { uploadFile } from '@/api/common' 36 import { uploadFile } from '@/api/common'
  37 +import { getCommunityId } from '@/api/community/communityApi'
37 38
38 export default { 39 export default {
39 name: 'UploadImageUrl', 40 name: 'UploadImageUrl',
@@ -88,7 +89,7 @@ export default { @@ -88,7 +89,7 @@ export default {
88 uploadFile(file) { 89 uploadFile(file) {
89 const formData = new FormData() 90 const formData = new FormData()
90 formData.append('uploadFile', file) 91 formData.append('uploadFile', file)
91 - formData.append('communityId', this.$store.getters.communityId) 92 + formData.append('communityId', getCommunityId())
92 93
93 uploadFile(formData) 94 uploadFile(formData)
94 .then(response => { 95 .then(response => {
src/components/staff/chooseOrgTree.vue
@@ -21,6 +21,7 @@ @@ -21,6 +21,7 @@
21 21
22 <script> 22 <script>
23 import { listOrgTree } from '@/api/staff/staffCommunityApi' 23 import { listOrgTree } from '@/api/staff/staffCommunityApi'
  24 +import { getCommunityId } from '@/api/community/communityApi'
24 25
25 export default { 26 export default {
26 name: 'ChooseOrgTree', 27 name: 'ChooseOrgTree',
@@ -43,7 +44,7 @@ export default { @@ -43,7 +44,7 @@ export default {
43 async loadOrgs() { 44 async loadOrgs() {
44 try { 45 try {
45 const { data } = await listOrgTree({ 46 const { data } = await listOrgTree({
46 - communityId: this.$store.getters.communityId 47 + communityId: getCommunityId()
47 }) 48 })
48 this.orgs = data 49 this.orgs = data
49 } catch (error) { 50 } catch (error) {
src/i18n/feeI18n.js
@@ -23,6 +23,9 @@ import { messages as oweFeeCallableMessages } from &#39;../views/fee/oweFeeCallableL @@ -23,6 +23,9 @@ import { messages as oweFeeCallableMessages } from &#39;../views/fee/oweFeeCallableL
23 import { messages as addOweFeeCallableMessages } from '../views/fee/addOweFeeCallableLang' 23 import { messages as addOweFeeCallableMessages } from '../views/fee/addOweFeeCallableLang'
24 import { messages as staffFeeManageMessages } from '../views/fee/staffFeeManageLang' 24 import { messages as staffFeeManageMessages } from '../views/fee/staffFeeManageLang'
25 import { messages as feeSummaryMessages } from '../views/fee/feeSummaryLang' 25 import { messages as feeSummaryMessages } from '../views/fee/feeSummaryLang'
  26 +import { messages as roomCreateFeeMessages } from '../views/fee/roomCreateFeeLang.js'
  27 +import { messages as propertyFeeMessages } from '../views/fee/propertyFeeLang'
  28 +import { messages as batchPayFeeOrderMessages } from '../views/fee/batchPayFeeOrderLang'
26 29
27 export const messages = { 30 export const messages = {
28 en: { 31 en: {
@@ -51,6 +54,9 @@ export const messages = { @@ -51,6 +54,9 @@ export const messages = {
51 ...addOweFeeCallableMessages.en, 54 ...addOweFeeCallableMessages.en,
52 ...staffFeeManageMessages.en, 55 ...staffFeeManageMessages.en,
53 ...feeSummaryMessages.en, 56 ...feeSummaryMessages.en,
  57 + ...roomCreateFeeMessages.en,
  58 + ...propertyFeeMessages.en,
  59 + ...batchPayFeeOrderMessages.en,
54 }, 60 },
55 zh: { 61 zh: {
56 ...contractCreateFeeMessages.zh, 62 ...contractCreateFeeMessages.zh,
@@ -78,5 +84,8 @@ export const messages = { @@ -78,5 +84,8 @@ export const messages = {
78 ...addOweFeeCallableMessages.zh, 84 ...addOweFeeCallableMessages.zh,
79 ...staffFeeManageMessages.zh, 85 ...staffFeeManageMessages.zh,
80 ...feeSummaryMessages.zh, 86 ...feeSummaryMessages.zh,
  87 + ...roomCreateFeeMessages.zh,
  88 + ...propertyFeeMessages.zh,
  89 + ...batchPayFeeOrderMessages.zh,
81 } 90 }
82 } 91 }
83 \ No newline at end of file 92 \ No newline at end of file
src/router/feeRouter.js
@@ -109,5 +109,20 @@ export default [ @@ -109,5 +109,20 @@ export default [
109 name: '/pages/property/feeSummary', 109 name: '/pages/property/feeSummary',
110 component: () => import('@/views/fee/feeSummaryList.vue') 110 component: () => import('@/views/fee/feeSummaryList.vue')
111 }, 111 },
  112 + {
  113 + path: '/pages/property/roomCreateFee',
  114 + name: '/pages/property/roomCreateFee',
  115 + component: () => import('@/views/fee/roomCreateFeeList.vue')
  116 + },
  117 + {
  118 + path: '/views/fee/propertyFee',
  119 + name: '/views/fee/propertyFee',
  120 + component: () => import('@/views/fee/propertyFeeList.vue')
  121 + },
  122 + {
  123 + path:'/views/fee/batchPayFeeOrder',
  124 + name:'/views/fee/batchPayFeeOrder',
  125 + component: () => import('@/views/fee/batchPayFeeOrderList.vue')
  126 + },
112 127
113 ] 128 ]
114 \ No newline at end of file 129 \ No newline at end of file
src/views/fee/addProxyFeeLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + addProxyFee: {
  4 + title: 'Pay by Quantity',
  5 + feeType: 'Fee Type',
  6 + feeTypePlaceholder: 'Required, please select fee type',
  7 + feeItem: 'Fee Item',
  8 + feeItemPlaceholder: 'Required, please select fee item',
  9 + feeItemTip: 'Note: Display items with formula (usage * unit price + additional fee)',
  10 + chargeObject: 'Charge Object',
  11 + chargeObjectPlaceholder: 'Required, please fill in room',
  12 + consumption: 'Consumption',
  13 + consumptionPlaceholder: 'Required, please fill in consumption',
  14 + quantity: 'Quantity',
  15 + amount: 'Amount',
  16 + amountPlaceholder: 'Required, please fill in amount',
  17 + startTime: 'Start Time',
  18 + startTimePlaceholder: 'Required, please fill in start time',
  19 + endTime: 'End Time',
  20 + endTimePlaceholder: 'Required, please fill in end time',
  21 + waterFee: 'Water Fee',
  22 + electricityFee: 'Electricity Fee',
  23 + otherFee: 'Other',
  24 + validate: {
  25 + amountRequired: 'Amount is required',
  26 + amountFormat: 'Invalid amount format, e.g. 3.00',
  27 + consumptionRequired: 'Consumption is required',
  28 + consumptionFormat: 'Invalid consumption format, e.g. 3.00',
  29 + roomRequired: 'Room is required',
  30 + feeRequired: 'Fee is required',
  31 + startTimeRequired: 'Start time is required',
  32 + endTimeRequired: 'End time is required',
  33 + startBeforeEnd: 'Start time must be before end time',
  34 + endAfterStart: 'End time must be after start time',
  35 + invalidConfig: 'Invalid fee item or formula error',
  36 + amountTooSmall: 'Amount is too small'
  37 + },
  38 + successMessage: 'Saved successfully'
  39 + },
  40 + addProxyFeeDemo: {
  41 + openModal: 'Open Pay by Quantity Modal',
  42 + successMessage: 'Saved successfully'
  43 + }
  44 + },
  45 + zh: {
  46 + addProxyFee: {
  47 + title: '按量缴费',
  48 + feeType: '费用类型',
  49 + feeTypePlaceholder: '必填,请选择费用类型',
  50 + feeItem: '收费项目',
  51 + feeItemPlaceholder: '必填,请选择收费项目',
  52 + feeItemTip: '说明:显示公式为(用量*单价+附加费)的费用项',
  53 + chargeObject: '收费对象',
  54 + chargeObjectPlaceholder: '必填,请填写房屋',
  55 + consumption: '用量',
  56 + consumptionPlaceholder: '必填,请填写用量',
  57 + quantity: '个数',
  58 + amount: '金额',
  59 + amountPlaceholder: '必填,请填写金额',
  60 + startTime: '开始时间',
  61 + startTimePlaceholder: '必填,请填写开始时间',
  62 + endTime: '结束时间',
  63 + endTimePlaceholder: '必填,请填写结束时间',
  64 + waterFee: '水费',
  65 + electricityFee: '电费',
  66 + otherFee: '其他',
  67 + validate: {
  68 + amountRequired: '金额不能为空',
  69 + amountFormat: '金额格式错误,如3.00',
  70 + consumptionRequired: '用量不能为空',
  71 + consumptionFormat: '用量格式错误,如3.00',
  72 + roomRequired: '房屋必填',
  73 + feeRequired: '费用必填',
  74 + startTimeRequired: '开始时间不能为空',
  75 + endTimeRequired: '结束时间不能为空',
  76 + startBeforeEnd: '开始时间必须小于结束时间',
  77 + endAfterStart: '结束时间必须大于开始时间',
  78 + invalidConfig: '未选择收费项目或者收费项目公式错误',
  79 + amountTooSmall: '输入金额太小'
  80 + },
  81 + successMessage: '保存成功'
  82 + },
  83 + addProxyFeeDemo: {
  84 + openModal: '打开按量缴费弹窗',
  85 + successMessage: '保存成功'
  86 + }
  87 + }
  88 +}
0 \ No newline at end of file 89 \ No newline at end of file
src/views/fee/batchPayFeeOrderLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + batchPayFeeOrder: {
  4 + title: 'Batch Payment',
  5 + feeType: 'Fee Type',
  6 + feeItem: 'Fee Item',
  7 + feeFlag: 'Fee Flag',
  8 + payerObj: 'Payer Object',
  9 + receivablePeriod: 'Receivable Period',
  10 + receivable: 'Receivable/Owed',
  11 + paymentCycle: 'Payment Cycle',
  12 + actualAmount: 'Actual Amount',
  13 + remark: 'Remark',
  14 + month: 'months',
  15 + enterActualAmount: 'Enter actual amount',
  16 + enterRemark: 'Enter remark',
  17 + scanPay: 'Scan Payment',
  18 + submitPay: 'Submit Payment'
  19 + },
  20 + payFeeUserAccount: {
  21 + title: 'Account Information',
  22 + accountType: 'Account Type',
  23 + accountName: 'Account Name',
  24 + accountAmount: 'Account Amount',
  25 + operation: 'Operation',
  26 + preSave: 'Pre-save',
  27 + yuan: 'yuan'
  28 + },
  29 + payFeeDeposit: {
  30 + title: 'Deposit Information',
  31 + payerObj: 'Payer Object',
  32 + feeItem: 'Fee Item',
  33 + timePeriod: 'Time Period',
  34 + amount: 'Amount',
  35 + payTime: 'Payment Time',
  36 + refund: 'Refund Deposit'
  37 + },
  38 + refundDepositFee: {
  39 + title: 'Confirm Operation',
  40 + confirmText: 'After the deposit is refunded, it will be automatically deposited into the account. You can choose to pay from the account. If you refund cash to the owner, please go to the business homepage to refund the deposit!'
  41 + },
  42 + batchPayConfirm: {
  43 + title: 'Payment Confirmation',
  44 + amount: 'Amount:',
  45 + accountAmount: 'Account Amount:',
  46 + paymentMethod: 'Payment Method:',
  47 + selectPaymentMethod: 'Please select payment method',
  48 + scanCodeTip: 'Please scan with scanner',
  49 + confirmPay: 'Confirm Payment',
  50 + payResult: 'Payment Result',
  51 + paySuccess: 'Payment Successful',
  52 + mergePrint: 'Merge Print',
  53 + printReceipt: 'Print Receipt',
  54 + yuan: 'yuan'
  55 + },
  56 + batchFeeCycle: {
  57 + paymentCycle: 'Payment Cycle',
  58 + selectCycleTip: 'Please select payment cycle',
  59 + default: 'Default',
  60 + customCycle: 'Custom Cycle',
  61 + customAmount: 'Custom Amount',
  62 + customEndTime: 'Custom End Time',
  63 + actualCycle: 'Actual Cycle',
  64 + enterActualCycle: 'Enter actual cycle',
  65 + endTime: 'End Time',
  66 + selectEndTime: 'Select end time',
  67 + enterCustomAmount: 'Enter custom amount'
  68 + }
  69 + },
  70 + zh: {
  71 + batchPayFeeOrder: {
  72 + title: '批量缴费',
  73 + feeType: '费用类型',
  74 + feeItem: '费用项目',
  75 + feeFlag: '费用标识',
  76 + payerObj: '收费对象',
  77 + receivablePeriod: '应收时间段',
  78 + receivable: '应收/欠费',
  79 + paymentCycle: '缴费周期',
  80 + actualAmount: '实收',
  81 + remark: '备注',
  82 + month: '个月',
  83 + enterActualAmount: '请输入实际金额',
  84 + enterRemark: '请输入备注',
  85 + scanPay: '扫码收费',
  86 + submitPay: '提交收费'
  87 + },
  88 + payFeeUserAccount: {
  89 + title: '账户信息',
  90 + accountType: '账户类型',
  91 + accountName: '账户名',
  92 + accountAmount: '账户金额',
  93 + operation: '操作',
  94 + preSave: '预存',
  95 + yuan: '元'
  96 + },
  97 + payFeeDeposit: {
  98 + title: '押金信息',
  99 + payerObj: '收费对象',
  100 + feeItem: '费用项',
  101 + timePeriod: '时间段',
  102 + amount: '金额',
  103 + payTime: '缴费时间',
  104 + refund: '退押金'
  105 + },
  106 + refundDepositFee: {
  107 + title: '请确认您的操作!',
  108 + confirmText: '押金退款后自动存到账户中,您可以从账户中选择缴费,如果退现金给业主,请到业务首页面退押金!'
  109 + },
  110 + batchPayConfirm: {
  111 + title: '收费确认',
  112 + amount: '金额:',
  113 + accountAmount: '账户金额:',
  114 + paymentMethod: '支付方式:',
  115 + selectPaymentMethod: '必填,请选择支付方式',
  116 + scanCodeTip: '请用扫码枪扫码',
  117 + confirmPay: '确定收费',
  118 + payResult: '缴费提示',
  119 + paySuccess: '缴费成功',
  120 + mergePrint: '合并打印',
  121 + printReceipt: '打印收据',
  122 + yuan: '元'
  123 + },
  124 + batchFeeCycle: {
  125 + paymentCycle: '缴费周期',
  126 + selectCycleTip: '必填,请选择缴费周期',
  127 + default: '默认',
  128 + customCycle: '自定义周期',
  129 + customAmount: '自定义金额',
  130 + customEndTime: '自定义结束时间',
  131 + actualCycle: '实际周期',
  132 + enterActualCycle: '请输入实际周期',
  133 + endTime: '缴费结束时间',
  134 + selectEndTime: '缴费结束时间',
  135 + enterCustomAmount: '请输入自定义金额'
  136 + }
  137 + }
  138 +}
0 \ No newline at end of file 139 \ No newline at end of file
src/views/fee/batchPayFeeOrderList.vue 0 → 100644
  1 +<template>
  2 + <div class="batch-pay-fee-order-container">
  3 + <el-row :gutter="20">
  4 + <el-col :span="4">
  5 + <el-card class="payer-object-card">
  6 + <div class="card-title">收费对象</div>
  7 + <div class="checkbox-list">
  8 + <el-checkbox-group v-model="batchPayFeeOrderInfo.payerObjNames" @change="_chanagePayerObjName">
  9 + <el-checkbox v-for="(item, index) in batchPayFeeOrderInfo.payObjs" :key="index" :label="item"
  10 + class="checkbox-item">{{ item }}</el-checkbox>
  11 + </el-checkbox-group>
  12 + </div>
  13 + </el-card>
  14 + </el-col>
  15 + <el-col :span="20">
  16 + <el-card>
  17 + <div slot="header" class="flex justify-between">
  18 + <span>{{ $t('batchPayFeeOrder.title') }}</span>
  19 + <el-button type="primary" size="small" class="float-right" @click="_goBack">{{ $t('common.back')
  20 + }}</el-button>
  21 + </div>
  22 +
  23 + <el-table :data="batchPayFeeOrderInfo.batchFees" border style="width: 100%" v-loading="loading">
  24 + <el-table-column type="selection" width="55" align="center"></el-table-column>
  25 + <el-table-column prop="feeTypeCdName" :label="$t('batchPayFeeOrder.feeType')"
  26 + align="center"></el-table-column>
  27 + <el-table-column prop="feeName" :label="$t('batchPayFeeOrder.feeItem')" align="center"></el-table-column>
  28 + <el-table-column prop="feeFlagName" :label="$t('batchPayFeeOrder.feeFlag')"
  29 + align="center"></el-table-column>
  30 + <el-table-column :label="$t('batchPayFeeOrder.payerObj')" align="center">
  31 + <template slot-scope="scope">
  32 + {{ _getBatchPayFeeRoomName(scope.row) }}
  33 + </template>
  34 + </el-table-column>
  35 + <el-table-column :label="$t('batchPayFeeOrder.receivablePeriod')" align="center" width="180">
  36 + <template slot-scope="scope">
  37 + <div>{{ _getEndTime(scope.row) }}</div>
  38 + <div>{{ _getDeadlineTime(scope.row) }}</div>
  39 + </template>
  40 + </el-table-column>
  41 + <el-table-column :label="$t('batchPayFeeOrder.receivable')" align="center">
  42 + <template slot-scope="scope">
  43 + {{ scope.row.receivableAmount }}/{{ scope.row.amountOwed }}
  44 + </template>
  45 + </el-table-column>
  46 + <el-table-column :label="$t('batchPayFeeOrder.paymentCycle')" align="center" width="150">
  47 + <template slot-scope="scope">
  48 + <div v-if="scope.row.feeFlag != '2006012'">
  49 + <div v-if="scope.row.tempCycle == '-102'" class="cycle-text">周期:{{ scope.row.cycles }}个月</div>
  50 + <div v-else-if="scope.row.tempCycle == '-101'" class="custom-amount">
  51 + 自定义金额<br>{{ scope.row.receivedAmount }}</div>
  52 + <div v-else-if="scope.row.tempCycle == '-103'" class="custom-end-time">
  53 + 结束时间<br>{{ scope.row.custEndTime }}</div>
  54 + <el-select v-else v-model="scope.row.cycles" @change="_changeMonth(scope.row.cycles, scope.row)"
  55 + style="width:100%">
  56 + <el-option v-for="item in _getBatchPaymentCycles(scope.row)" :key="item"
  57 + :label="`${item}${$t('batchPayFeeOrder.month')}`" :value="item"></el-option>
  58 + </el-select>
  59 + <el-button type="text" icon="el-icon-setting" @click="_settingsFeeCycle(scope.row)"></el-button>
  60 + </div>
  61 + <div v-else>-</div>
  62 + </template>
  63 + </el-table-column>
  64 + <el-table-column :label="$t('batchPayFeeOrder.actualAmount')" align="center" width="150">
  65 + <template slot-scope="scope">
  66 + <el-input v-if="scope.row.receivedAmountSwitch == '1'" v-model="scope.row.receivedAmount"
  67 + :placeholder="$t('batchPayFeeOrder.enterActualAmount')" @change="_doComputeTotalFee"></el-input>
  68 + <span v-else>{{ scope.row.receivedAmount }}</span>
  69 + </template>
  70 + </el-table-column>
  71 + <el-table-column :label="$t('batchPayFeeOrder.remark')" align="center" width="200">
  72 + <template slot-scope="scope">
  73 + <el-input v-model="scope.row.remark" :placeholder="$t('batchPayFeeOrder.enterRemark')"></el-input>
  74 + </template>
  75 + </el-table-column>
  76 + </el-table>
  77 + </el-card>
  78 + <div class="margin-top">
  79 + <pay-fee-user-account ref="payFeeUserAccount"></pay-fee-user-account>
  80 + </div>
  81 + <pay-fee-deposit ref="payFeeDeposit"></pay-fee-deposit>
  82 +
  83 + <el-row class="footer-row text-left">
  84 + <el-col :span="16">
  85 + <div class="tips">
  86 + <p>温馨提示:批量缴费不支持优惠折扣和优惠券抵扣功能,如需要请到缴费页面缴费</p>
  87 + <p><b>缴费金额:缴费金额等于所有实收</b></p>
  88 + </div>
  89 + </el-col>
  90 + <el-col :span="4">
  91 + <div class="total-amount">
  92 + 缴费金额:<span class="amount">{{ batchPayFeeOrderInfo.feePrices }}元</span>
  93 + </div>
  94 + </el-col>
  95 + <el-col :span="4" class="text-right">
  96 + <el-button type="success" size="medium" @click="_openPayFee('qrCode')">{{ $t('batchPayFeeOrder.scanPay')
  97 + }}</el-button>
  98 + <el-button type="primary" size="medium" @click="_openPayFee('common')">{{ $t('batchPayFeeOrder.submitPay')
  99 + }}</el-button>
  100 + </el-col>
  101 + </el-row>
  102 +
  103 + </el-col>
  104 + </el-row>
  105 +
  106 + <batch-pay-confirm ref="batchPayConfirm"></batch-pay-confirm>
  107 + <batch-fee-cycle ref="batchFeeCycle"></batch-fee-cycle>
  108 + </div>
  109 +</template>
  110 +
  111 +<script>
  112 +import { getCommunityId } from '@/api/community/communityApi'
  113 +import PayFeeUserAccount from '@/components/fee/payFeeUserAccount'
  114 +import PayFeeDeposit from '@/components/fee/payFeeDeposit'
  115 +import BatchPayConfirm from '@/components/fee/batchPayConfirm'
  116 +import BatchFeeCycle from '@/components/fee/batchFeeCycle'
  117 +import { listFee, listFeeObj } from '@/api/fee/batchPayFeeOrderApi'
  118 +import {dateFormat,dateAdd} from '@/utils/dateUtil'
  119 +
  120 +export default {
  121 + name: 'BatchPayFeeOrderList',
  122 + components: {
  123 + PayFeeUserAccount,
  124 + PayFeeDeposit,
  125 + BatchPayConfirm,
  126 + BatchFeeCycle
  127 + },
  128 + data() {
  129 + return {
  130 + loading: false,
  131 + batchPayFeeOrderInfo: {
  132 + batchFees: [],
  133 + allBatchFees: [],
  134 + selectPayFeeIds: [],
  135 + feePrices: 0.00,
  136 + communityId: '',
  137 + ownerId: '',
  138 + payerObjType: '',
  139 + remark: '',
  140 + payerObjNames: [],
  141 + payObjs: [],
  142 + accountAmount: 0.0,
  143 + acctId: ''
  144 + }
  145 + }
  146 + },
  147 + created() {
  148 + this.communityId = getCommunityId()
  149 + this._initData()
  150 + },
  151 + methods: {
  152 + async _initData() {
  153 + const ownerId = this.$route.query.ownerId
  154 + const payerObjType = this.$route.query.payerObjType
  155 +
  156 + if (!ownerId) {
  157 + this.$message.error('非法操作')
  158 + this.$router.go(-1)
  159 + return
  160 + }
  161 +
  162 + this.batchPayFeeOrderInfo.ownerId = ownerId
  163 + this.batchPayFeeOrderInfo.payerObjType = payerObjType
  164 +
  165 + await this._loadBatchFees()
  166 +
  167 + this.$refs.payFeeUserAccount._listUserAccount(1, 20)
  168 + this.$refs.payFeeDeposit._listFeeDeposit(1, 20)
  169 + },
  170 +
  171 + async _loadBatchFees() {
  172 + this.loading = true
  173 + try {
  174 + const params = {
  175 + page: 1,
  176 + row: 500,
  177 + communityId: this.communityId,
  178 + ownerId: this.batchPayFeeOrderInfo.ownerId,
  179 + payerObjType: this.batchPayFeeOrderInfo.payerObjType,
  180 + state: '2008001'
  181 + }
  182 +
  183 + const res = await listFee(params)
  184 +
  185 + let _batchFees = []
  186 + let _selectPayFeeIds = []
  187 +
  188 + res.fees.sort(this._batchRoomFeeCompare).forEach(feeItem => {
  189 + _batchFees.push({
  190 + ...feeItem,
  191 + cycles: feeItem.paymentCycle,
  192 + receivableAmount: feeItem.feeTotalPrice,
  193 + receivedAmount: feeItem.feeTotalPrice,
  194 + tempCycle: '-100'
  195 + })
  196 + _selectPayFeeIds.push(feeItem.feeId)
  197 + })
  198 +
  199 + this.batchPayFeeOrderInfo = {
  200 + ...this.batchPayFeeOrderInfo,
  201 + allBatchFees: _batchFees,
  202 + selectPayFeeIds: _selectPayFeeIds,
  203 + batchFees: _batchFees
  204 + }
  205 +
  206 + this._pushPayObjs()
  207 + this._doComputeTotalFee()
  208 + } catch (error) {
  209 + console.error('请求失败:', error)
  210 + } finally {
  211 + this.loading = false
  212 + }
  213 + },
  214 +
  215 + _batchRoomFeeCompare(a, b) {
  216 + if (a.payerObjName < b.payerObjName) return -1
  217 + if (a.payerObjName > b.payerObjName) return 1
  218 + return 0
  219 + },
  220 +
  221 + _pushPayObjs() {
  222 + const _allBatchFees = this.batchPayFeeOrderInfo.allBatchFees
  223 + const _payObjs = []
  224 + const _payerObjNames = []
  225 +
  226 + _allBatchFees.forEach(fee => {
  227 + if (!fee.feeAttrs) return
  228 +
  229 + let _payerObjName = ''
  230 + fee.feeAttrs.forEach(item => {
  231 + if (item.specCd === '390012') {
  232 + _payerObjName = item.value
  233 + }
  234 + })
  235 +
  236 + if (_payerObjName && !this._hasPayObjsIn(_payerObjName, _payObjs)) {
  237 + _payObjs.push(_payerObjName)
  238 + _payerObjNames.push(_payerObjName)
  239 + }
  240 + })
  241 +
  242 + this.batchPayFeeOrderInfo.payObjs = _payObjs
  243 + this.batchPayFeeOrderInfo.payerObjNames = _payerObjNames
  244 + },
  245 +
  246 + _hasPayObjsIn(payerObjName, payObjs) {
  247 + return payObjs.includes(payerObjName)
  248 + },
  249 +
  250 + _hasPayObjNamesIn(payerObjName) {
  251 + return this.batchPayFeeOrderInfo.payerObjNames.includes(payerObjName)
  252 + },
  253 +
  254 + _chanagePayerObjName() {
  255 + const _allBatchFees = this.batchPayFeeOrderInfo.allBatchFees
  256 + const _batchFees = []
  257 +
  258 + _allBatchFees.forEach(fee => {
  259 + let _payerObjName = ''
  260 + if (fee.feeAttrs) {
  261 + fee.feeAttrs.forEach(item => {
  262 + if (item.specCd === '390012') {
  263 + _payerObjName = item.value
  264 + }
  265 + })
  266 + }
  267 +
  268 + if (_payerObjName && this._hasPayObjNamesIn(_payerObjName)) {
  269 + _batchFees.push(fee)
  270 + }
  271 + })
  272 +
  273 + this.batchPayFeeOrderInfo.batchFees = _batchFees
  274 + this._doComputeTotalFee()
  275 + },
  276 +
  277 + _openPayFee(payType) {
  278 + if (this.batchPayFeeOrderInfo.selectPayFeeIds.length <= 0) {
  279 + this.$message.warning('未选择费用')
  280 + return
  281 + }
  282 +
  283 + const _payerObjName = this.batchPayFeeOrderInfo.payerObjNames.join(',')
  284 + const params = {
  285 + fees: this._getPayFees(),
  286 + payType: payType,
  287 + feePrices: this.batchPayFeeOrderInfo.feePrices,
  288 + payerObjName: _payerObjName,
  289 + acctId: this.batchPayFeeOrderInfo.acctId,
  290 + accountAmount: this.batchPayFeeOrderInfo.accountAmount
  291 + }
  292 +
  293 + this.$refs.batchPayConfirm.open(params)
  294 + },
  295 +
  296 + _getPayFees() {
  297 + const _selectPayFeeIds = this.batchPayFeeOrderInfo.selectPayFeeIds
  298 + const _batchFees = this.batchPayFeeOrderInfo.batchFees
  299 + const _fees = []
  300 +
  301 + _selectPayFeeIds.forEach(id => {
  302 + _batchFees.forEach(fee => {
  303 + if (id === fee.feeId) {
  304 + _fees.push(fee)
  305 + }
  306 + })
  307 + })
  308 +
  309 + return _fees
  310 + },
  311 +
  312 + _goBack() {
  313 + this.$router.go(-1)
  314 + },
  315 +
  316 + _getDeadlineTime(fee) {
  317 + if (fee.amountOwed === 0 && fee.endTime === fee.deadlineTime) return "-"
  318 + if (fee.state === '2009001') return "-"
  319 + return dateFormat(fee.deadlineTime)
  320 + },
  321 +
  322 + _getEndTime(fee) {
  323 + if (fee.state === '2009001') return "-"
  324 + return dateFormat(fee.endTime)
  325 + },
  326 +
  327 + _getBatchPayFeeRoomName(fee) {
  328 + if (!fee.feeAttrs) return ""
  329 +
  330 + let _feeName = ''
  331 + fee.feeAttrs.forEach(item => {
  332 + if (item.specCd === '390012') {
  333 + _feeName = item.value
  334 + }
  335 + })
  336 +
  337 + return _feeName
  338 + },
  339 +
  340 + _getBatchPaymentCycles(fee) {
  341 + const paymentCycles = []
  342 + for (let i = 1; i < 13; i++) {
  343 + paymentCycles.push(i * parseFloat(fee.paymentCycle))
  344 + }
  345 + return paymentCycles
  346 + },
  347 +
  348 + _doComputeTotalFee() {
  349 + const _selectPayFeeIds = this.batchPayFeeOrderInfo.selectPayFeeIds
  350 + const _batchFees = this.batchPayFeeOrderInfo.batchFees
  351 + const _accountAmount = this.batchPayFeeOrderInfo.accountAmount
  352 +
  353 + let _totalFee = 0
  354 +
  355 + _selectPayFeeIds.forEach(id => {
  356 + _batchFees.forEach(fee => {
  357 + if (id === fee.feeId && fee.receivedAmount) {
  358 + _totalFee += parseFloat(fee.receivedAmount)
  359 + }
  360 + })
  361 + })
  362 +
  363 + if (_accountAmount) {
  364 + _totalFee = _totalFee - parseFloat(_accountAmount)
  365 + }
  366 +
  367 + this.batchPayFeeOrderInfo.feePrices = Math.max(0, _totalFee).toFixed(2)
  368 + },
  369 +
  370 + async _changeMonth(cycles, fee) {
  371 + if (!cycles) {
  372 + cycles = fee.cycles
  373 + }
  374 +
  375 + if (fee.tempCycle === '-101') {
  376 + this._doComputeTotalFee()
  377 + return
  378 + }
  379 +
  380 + try {
  381 + const params = {
  382 + communityId: this.communityId,
  383 + feeId: fee.feeId,
  384 + page: 1,
  385 + row: 1,
  386 + cycle: cycles
  387 + }
  388 +
  389 + if (fee.tempCycle === '-103') {
  390 + params.custEndTime = dateAdd(fee.custEndTime)
  391 + }
  392 +
  393 + const res = await listFeeObj(params)
  394 + if (res.code === 0) {
  395 + fee.receivableAmount = res.data.feeTotalPrice
  396 + fee.receivedAmount = fee.receivableAmount
  397 + this._doComputeTotalFee()
  398 + }
  399 + } catch (error) {
  400 + console.error('请求失败:', error)
  401 + }
  402 + },
  403 +
  404 + _settingsFeeCycle(batchFee) {
  405 + this.$refs.batchFeeCycle.open(batchFee)
  406 + }
  407 + }
  408 +}
  409 +</script>
  410 +
  411 +<style lang="scss" scoped>
  412 +.batch-pay-fee-order-container {
  413 + padding: 20px;
  414 +
  415 + .payer-object-card {
  416 + height: 100%;
  417 +
  418 + .card-title {
  419 + padding: 10px;
  420 + font-weight: bold;
  421 + }
  422 +
  423 + .checkbox-list {
  424 + padding: 10px;
  425 +
  426 + .checkbox-item {
  427 + display: block;
  428 + margin: 5px 0;
  429 + }
  430 + }
  431 + }
  432 +
  433 + .footer-row {
  434 + margin-top: 20px;
  435 + padding: 20px;
  436 + background: #f5f7fa;
  437 + border-radius: 4px;
  438 +
  439 + .tips {
  440 + color: #666;
  441 + line-height: 1.6;
  442 + }
  443 +
  444 + .total-amount {
  445 + font-size: 16px;
  446 +
  447 + .amount {
  448 + font-size: 30px;
  449 + color: #f56c6c;
  450 + margin-left: 5px;
  451 + }
  452 + }
  453 + }
  454 +
  455 + .cycle-text,
  456 + .custom-amount,
  457 + .custom-end-time {
  458 + line-height: 1.5;
  459 + padding: 5px 0;
  460 + }
  461 +}
  462 +</style>
0 \ No newline at end of file 463 \ No newline at end of file
src/views/fee/payFeeAuditManageList.vue
@@ -6,46 +6,22 @@ @@ -6,46 +6,22 @@
6 </div> 6 </div>
7 <el-row :gutter="20"> 7 <el-row :gutter="20">
8 <el-col :span="6"> 8 <el-col :span="6">
9 - <el-select  
10 - v-model="searchForm.payObjType"  
11 - :placeholder="$t('payFeeAuditManage.selectPayObj')"  
12 - style="width:100%"  
13 - >  
14 - <el-option  
15 - v-for="item in payObjTypes"  
16 - :key="item.statusCd"  
17 - :label="item.name"  
18 - :value="item.statusCd"  
19 - /> 9 + <el-select v-model="searchForm.payObjType" :placeholder="$t('payFeeAuditManage.selectPayObj')"
  10 + style="width:100%">
  11 + <el-option v-for="item in payObjTypes" :key="item.statusCd" :label="item.name" :value="item.statusCd" />
20 </el-select> 12 </el-select>
21 </el-col> 13 </el-col>
22 <el-col :span="6"> 14 <el-col :span="6">
23 - <el-select  
24 - v-model="searchForm.state"  
25 - :placeholder="$t('payFeeAuditManage.selectStatus')"  
26 - style="width:100%"  
27 - >  
28 - <el-option  
29 - :label="$t('payFeeAuditManage.pendingReview')"  
30 - value="1010"  
31 - />  
32 - <el-option  
33 - :label="$t('payFeeAuditManage.approved')"  
34 - value="2020"  
35 - />  
36 - <el-option  
37 - :label="$t('payFeeAuditManage.rejected')"  
38 - value="3030"  
39 - /> 15 + <el-select v-model="searchForm.state" :placeholder="$t('payFeeAuditManage.selectStatus')" style="width:100%">
  16 + <el-option :label="$t('payFeeAuditManage.pendingReview')" value="1010" />
  17 + <el-option :label="$t('payFeeAuditManage.approved')" value="2020" />
  18 + <el-option :label="$t('payFeeAuditManage.rejected')" value="3030" />
40 </el-select> 19 </el-select>
41 </el-col> 20 </el-col>
42 <el-col :span="6"> 21 <el-col :span="6">
43 - <el-input  
44 - v-model="searchForm.payerObjId"  
45 - :placeholder="searchForm.payObjType === '666'  
46 - ? $t('payFeeAuditManage.inputPlateNumber')  
47 - : $t('payFeeAuditManage.inputRoomInfo')"  
48 - /> 22 + <el-input v-model="searchForm.payerObjId" :placeholder="searchForm.payObjType === '666'
  23 + ? $t('payFeeAuditManage.inputPlateNumber')
  24 + : $t('payFeeAuditManage.inputRoomInfo')" />
49 </el-col> 25 </el-col>
50 <el-col :span="6"> 26 <el-col :span="6">
51 <el-button type="primary" @click="handleSearch"> 27 <el-button type="primary" @click="handleSearch">
@@ -63,123 +39,46 @@ @@ -63,123 +39,46 @@
63 <el-card class="table-card"> 39 <el-card class="table-card">
64 <div slot="header" class="flex justify-between"> 40 <div slot="header" class="flex justify-between">
65 <span>{{ $t('payFeeAuditManage.tableTitle') }}</span> 41 <span>{{ $t('payFeeAuditManage.tableTitle') }}</span>
66 - <el-button  
67 - type="primary"  
68 - size="small"  
69 - style="float:right"  
70 - @click="handleBatchAudit"  
71 - > 42 + <el-button type="primary" size="small" style="float:right" @click="handleBatchAudit">
72 <i class="el-icon-plus"></i> 43 <i class="el-icon-plus"></i>
73 {{ $t('payFeeAuditManage.batchAudit') }} 44 {{ $t('payFeeAuditManage.batchAudit') }}
74 </el-button> 45 </el-button>
75 </div> 46 </div>
76 -  
77 - <el-table  
78 - :data="tableData"  
79 - border  
80 - style="width:100%"  
81 - @selection-change="handleSelectionChange"  
82 - > 47 +
  48 + <el-table :data="tableData" border style="width:100%" @selection-change="handleSelectionChange">
83 <el-table-column type="selection" width="55" align="center" /> 49 <el-table-column type="selection" width="55" align="center" />
84 - <el-table-column  
85 - prop="payerObjName"  
86 - :label="$t('payFeeAuditManage.house')"  
87 - align="center"  
88 - />  
89 - <el-table-column  
90 - prop="feeName"  
91 - :label="$t('payFeeAuditManage.feeItem')"  
92 - align="center"  
93 - />  
94 - <el-table-column  
95 - prop="cycles"  
96 - :label="$t('payFeeAuditManage.payCycle')"  
97 - align="center"  
98 - > 50 + <el-table-column prop="payerObjName" :label="$t('payFeeAuditManage.house')" align="center" />
  51 + <el-table-column prop="feeName" :label="$t('payFeeAuditManage.feeItem')" align="center" />
  52 + <el-table-column prop="cycles" :label="$t('payFeeAuditManage.payCycle')" align="center">
99 <template slot-scope="scope"> 53 <template slot-scope="scope">
100 {{ scope.row.cycles }} {{ $t('payFeeAuditManage.month') }} 54 {{ scope.row.cycles }} {{ $t('payFeeAuditManage.month') }}
101 </template> 55 </template>
102 </el-table-column> 56 </el-table-column>
103 - <el-table-column  
104 - prop="startTime"  
105 - :label="$t('payFeeAuditManage.startTime')"  
106 - align="center"  
107 - />  
108 - <el-table-column  
109 - prop="endTime"  
110 - :label="$t('payFeeAuditManage.endTime')"  
111 - align="center"  
112 - />  
113 - <el-table-column  
114 - prop="receivableAmount"  
115 - :label="$t('payFeeAuditManage.receivableAmount')"  
116 - align="center"  
117 - />  
118 - <el-table-column  
119 - prop="receivedAmount"  
120 - :label="$t('payFeeAuditManage.receivedAmount')"  
121 - align="center"  
122 - />  
123 - <el-table-column  
124 - prop="userName"  
125 - :label="$t('payFeeAuditManage.operator')"  
126 - align="center"  
127 - />  
128 - <el-table-column  
129 - prop="createTime"  
130 - :label="$t('payFeeAuditManage.payTime')"  
131 - align="center"  
132 - />  
133 - <el-table-column  
134 - prop="state"  
135 - :label="$t('payFeeAuditManage.auditStatus')"  
136 - align="center"  
137 - > 57 + <el-table-column prop="startTime" :label="$t('payFeeAuditManage.startTime')" align="center" />
  58 + <el-table-column prop="endTime" :label="$t('payFeeAuditManage.endTime')" align="center" />
  59 + <el-table-column prop="receivableAmount" :label="$t('payFeeAuditManage.receivableAmount')" align="center" />
  60 + <el-table-column prop="receivedAmount" :label="$t('payFeeAuditManage.receivedAmount')" align="center" />
  61 + <el-table-column prop="userName" :label="$t('payFeeAuditManage.operator')" align="center" />
  62 + <el-table-column prop="createTime" :label="$t('payFeeAuditManage.payTime')" align="center" />
  63 + <el-table-column prop="state" :label="$t('payFeeAuditManage.auditStatus')" align="center">
138 <template slot-scope="scope"> 64 <template slot-scope="scope">
139 - <el-tag  
140 - :type="getStatusTagType(scope.row.state)"  
141 - > 65 + <el-tag :type="getStatusTagType(scope.row.state)">
142 {{ getStatusText(scope.row.state) }} 66 {{ getStatusText(scope.row.state) }}
143 </el-tag> 67 </el-tag>
144 </template> 68 </template>
145 </el-table-column> 69 </el-table-column>
146 - <el-table-column  
147 - prop="message"  
148 - :label="$t('payFeeAuditManage.auditRemark')"  
149 - align="center"  
150 - />  
151 - <el-table-column  
152 - prop="remark"  
153 - :label="$t('payFeeAuditManage.payRemark')"  
154 - align="center"  
155 - />  
156 - <el-table-column  
157 - :label="$t('common.operation')"  
158 - align="center"  
159 - width="200"  
160 - > 70 + <el-table-column prop="message" :label="$t('payFeeAuditManage.auditRemark')" align="center" />
  71 + <el-table-column prop="remark" :label="$t('payFeeAuditManage.payRemark')" align="center" />
  72 + <el-table-column :label="$t('common.operation')" align="center" width="200">
161 <template slot-scope="scope"> 73 <template slot-scope="scope">
162 - <el-button  
163 - type="text"  
164 - size="small"  
165 - @click="handleDetail(scope.row)"  
166 - > 74 + <el-button type="text" size="small" @click="handleDetail(scope.row)">
167 {{ $t('common.detail') }} 75 {{ $t('common.detail') }}
168 </el-button> 76 </el-button>
169 - <el-button  
170 - v-if="scope.row.state !== '2020' && scope.row.state !== '3030'"  
171 - type="text"  
172 - size="small"  
173 - @click="handleAudit(scope.row)"  
174 - > 77 + <el-button v-if="scope.row.state !== '2020' && scope.row.state !== '3030'" type="text" size="small"
  78 + @click="handleAudit(scope.row)">
175 {{ $t('payFeeAuditManage.auditFee') }} 79 {{ $t('payFeeAuditManage.auditFee') }}
176 </el-button> 80 </el-button>
177 - <el-button  
178 - v-if="scope.row.state === '3030'"  
179 - type="text"  
180 - size="small"  
181 - @click="handleRefund(scope.row)"  
182 - > 81 + <el-button v-if="scope.row.state === '3030'" type="text" size="small" @click="handleRefund(scope.row)">
183 {{ $t('payFeeAuditManage.refund') }} 82 {{ $t('payFeeAuditManage.refund') }}
184 </el-button> 83 </el-button>
185 </template> 84 </template>
@@ -190,15 +89,9 @@ @@ -190,15 +89,9 @@
190 <div class="tip-text"> 89 <div class="tip-text">
191 {{ $t('payFeeAuditManage.auditTip') }} 90 {{ $t('payFeeAuditManage.auditTip') }}
192 </div> 91 </div>
193 - <el-pagination  
194 - :current-page="pagination.current"  
195 - :page-sizes="[10, 20, 30, 50]"  
196 - :page-size="pagination.size"  
197 - :total="pagination.total"  
198 - layout="total, sizes, prev, pager, next, jumper"  
199 - @size-change="handleSizeChange"  
200 - @current-change="handleCurrentChange"  
201 - /> 92 + <el-pagination :current-page="pagination.current" :page-sizes="[10, 20, 30, 50]" :page-size="pagination.size"
  93 + :total="pagination.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
  94 + @current-change="handleCurrentChange" />
202 </div> 95 </div>
203 </el-card> 96 </el-card>
204 97
@@ -316,8 +209,8 @@ export default { @@ -316,8 +209,8 @@ export default {
316 const params = { 209 const params = {
317 state: auditInfo.state === '1100' ? '2020' : '3030', 210 state: auditInfo.state === '1100' ? '2020' : '3030',
318 message: auditInfo.remark, 211 message: auditInfo.remark,
319 - feeDetailId: this.currentRow  
320 - ? this.currentRow.detailId 212 + feeDetailId: this.currentRow
  213 + ? this.currentRow.detailId
321 : this.multipleSelection.map(item => item.detailId).join(','), 214 : this.multipleSelection.map(item => item.detailId).join(','),
322 communityId: this.searchForm.communityId 215 communityId: this.searchForm.communityId
323 } 216 }
@@ -332,14 +225,14 @@ export default { @@ -332,14 +225,14 @@ export default {
332 this.getList() 225 this.getList()
333 }, 226 },
334 getStatusTagType(state) { 227 getStatusTagType(state) {
335 - switch(state) { 228 + switch (state) {
336 case '2020': return 'success' 229 case '2020': return 'success'
337 case '3030': return 'danger' 230 case '3030': return 'danger'
338 default: return 'info' 231 default: return 'info'
339 } 232 }
340 }, 233 },
341 getStatusText(state) { 234 getStatusText(state) {
342 - switch(state) { 235 + switch (state) {
343 case '2020': return this.$t('payFeeAuditManage.approved') 236 case '2020': return this.$t('payFeeAuditManage.approved')
344 case '3030': return this.$t('payFeeAuditManage.rejected') 237 case '3030': return this.$t('payFeeAuditManage.rejected')
345 default: return this.$t('payFeeAuditManage.pendingReview') 238 default: return this.$t('payFeeAuditManage.pendingReview')
@@ -352,17 +245,17 @@ export default { @@ -352,17 +245,17 @@ export default {
352 <style lang="scss" scoped> 245 <style lang="scss" scoped>
353 .pay-fee-audit-manage-container { 246 .pay-fee-audit-manage-container {
354 padding: 20px; 247 padding: 20px;
355 - 248 +
356 .search-card { 249 .search-card {
357 margin-bottom: 20px; 250 margin-bottom: 20px;
358 } 251 }
359 - 252 +
360 .pagination-wrapper { 253 .pagination-wrapper {
361 display: flex; 254 display: flex;
362 justify-content: space-between; 255 justify-content: space-between;
363 align-items: center; 256 align-items: center;
364 margin-top: 20px; 257 margin-top: 20px;
365 - 258 +
366 .tip-text { 259 .tip-text {
367 color: #999; 260 color: #999;
368 font-size: 12px; 261 font-size: 12px;
src/views/fee/propertyFeeLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + propertyFee: {
  4 + title: 'Property Fee Management',
  5 + feeName: 'Property Fee',
  6 + paymentHistory: 'Payment History',
  7 + selectStartTime: 'Select start time',
  8 + selectEndTime: 'Select end time',
  9 + searchNow: 'Search Now',
  10 + reset: 'Reset',
  11 + paymentId: 'Payment ID',
  12 + cycle: 'Cycle(Month)',
  13 + paymentMethod: 'Payment Method',
  14 + receivableAmount: 'Receivable Amount(Yuan)',
  15 + receivedAmount: 'Received Amount(Yuan)',
  16 + paymentTime: 'Payment Time',
  17 + startTime: 'Start Time',
  18 + endTime: 'End Time',
  19 + cashier: 'Cashier',
  20 + status: 'Status',
  21 + remark: 'Remark',
  22 + operation: 'Operation',
  23 + applyRefund: 'Apply Refund',
  24 + discount: 'Discount',
  25 + viewInFee: 'view in fee',
  26 + accountDeduction: 'Account Deduction'
  27 + },
  28 + viewMainFee: {
  29 + feeInfo: 'Fee Information',
  30 + feeId: 'Fee ID',
  31 + feeFlag: 'Fee Flag',
  32 + feeType: 'Fee Type',
  33 + payerObj: 'Payer Object',
  34 + feeItem: 'Fee Item',
  35 + feeStatus: 'Fee Status',
  36 + startTime: 'Create Time',
  37 + billingStartTime: 'Billing Start Time',
  38 + billingEndTime: 'Billing End Time',
  39 + feeAmount: 'Fee Amount(Yuan)',
  40 + batch: 'Batch',
  41 + area: 'Area(㎡)',
  42 + unitPrice: 'Unit Price(Yuan/㎡)',
  43 + additionalFee: 'Additional Fee(Yuan)',
  44 + fixedFee: 'Fixed Fee(Yuan)'
  45 + },
  46 + returnPayFee: {
  47 + fillRefundReason: 'Fill Refund Reason',
  48 + paymentId: 'Payment',
  49 + cycle: 'Cycle',
  50 + receivableAmount: 'Receivable Amount',
  51 + receivedAmount: 'Received Amount',
  52 + paymentTime: 'Payment Time',
  53 + refundReason: 'Refund Reason',
  54 + enterRefundReason: 'Please enter refund reason',
  55 + submitRefund: 'Submit Refund Application',
  56 + refundReasonRequired: 'Refund reason is required',
  57 + refundReasonTooLong: 'Refund reason cannot exceed 200 characters'
  58 + },
  59 + viewFeeDetailDiscount: {
  60 + discount: 'Discount',
  61 + discountName: 'Discount Name',
  62 + discountType: 'Discount Type',
  63 + ruleName: 'Rule Name',
  64 + discountRule: 'Discount Rule',
  65 + discountAmount: 'Discount Amount(Yuan)',
  66 + breach: 'Breach'
  67 + }
  68 + },
  69 + zh: {
  70 + propertyFee: {
  71 + title: '物业费管理',
  72 + feeName: '物业费',
  73 + paymentHistory: '缴费历史',
  74 + selectStartTime: '请选择开始时间',
  75 + selectEndTime: '请选择结束时间',
  76 + searchNow: '马上查询',
  77 + reset: '重置',
  78 + paymentId: '缴费ID',
  79 + cycle: '周期(单位:月)',
  80 + paymentMethod: '缴费方式',
  81 + receivableAmount: '应收金额(单位:元)',
  82 + receivedAmount: '实收金额(单位:元)',
  83 + paymentTime: '缴费时间',
  84 + startTime: '缴费起始时间',
  85 + endTime: '缴费结束时间',
  86 + cashier: '收银员',
  87 + status: '状态',
  88 + remark: '备注',
  89 + operation: '操作',
  90 + applyRefund: '申请退费',
  91 + discount: '折扣',
  92 + viewInFee: '费用中查看',
  93 + accountDeduction: '账户扣款'
  94 + },
  95 + viewMainFee: {
  96 + feeInfo: '费用信息',
  97 + feeId: '费用ID',
  98 + feeFlag: '费用标识',
  99 + feeType: '费用类型',
  100 + payerObj: '付费对象',
  101 + feeItem: '费用项',
  102 + feeStatus: '费用状态',
  103 + startTime: '建账时间',
  104 + billingStartTime: '计费开始时间',
  105 + billingEndTime: '计费结束时间',
  106 + feeAmount: '费用金额(单位:元)',
  107 + batch: '批次',
  108 + area: '面积(㎡)',
  109 + unitPrice: '单价(元/㎡)',
  110 + additionalFee: '附加费(元)',
  111 + fixedFee: '固定费(元)'
  112 + },
  113 + returnPayFee: {
  114 + fillRefundReason: '填写退费原因',
  115 + paymentId: '缴费',
  116 + cycle: '周期',
  117 + receivableAmount: '应收金额',
  118 + receivedAmount: '实收金额',
  119 + paymentTime: '缴费时间',
  120 + refundReason: '退费原因',
  121 + enterRefundReason: '请输入退费原因',
  122 + submitRefund: '提交退费申请',
  123 + refundReasonRequired: '退费原因不能为空',
  124 + refundReasonTooLong: '退费原因不能超过200位'
  125 + },
  126 + viewFeeDetailDiscount: {
  127 + discount: '折扣',
  128 + discountName: '折扣名称',
  129 + discountType: '折扣类型',
  130 + ruleName: '规则名称',
  131 + discountRule: '折扣规则',
  132 + discountAmount: '折扣金额(元)',
  133 + breach: '违约'
  134 + }
  135 + }
  136 +}
0 \ No newline at end of file 137 \ No newline at end of file
src/views/fee/propertyFeeList.vue 0 → 100644
  1 +<template>
  2 + <div class="property-fee-container">
  3 + <el-card class="box-card">
  4 + <div slot="header" class="clearfix">
  5 + <span>{{ $t('propertyFee.title') }}</span>
  6 + </div>
  7 +
  8 + <!-- 主费用信息组件 -->
  9 + <view-main-fee
  10 + ref="viewMainFee"
  11 + :fee-name="$t('propertyFee.feeName')"
  12 + fee-type-cd="888800010001"
  13 + pay-name="propertyPay"
  14 + />
  15 +
  16 + <el-card class="box-card" style="margin-top: 20px;">
  17 + <div slot="header" class="clearfix">
  18 + <span>{{ $t('propertyFee.paymentHistory') }}</span>
  19 + </div>
  20 +
  21 + <el-row :gutter="20">
  22 + <el-col :span="6">
  23 + <el-date-picker
  24 + v-model="feeDetailInfo.startTime"
  25 + type="date"
  26 + :placeholder="$t('propertyFee.selectStartTime')"
  27 + style="width: 100%;"
  28 + />
  29 + </el-col>
  30 + <el-col :span="6">
  31 + <el-date-picker
  32 + v-model="feeDetailInfo.endTime"
  33 + type="date"
  34 + :placeholder="$t('propertyFee.selectEndTime')"
  35 + style="width: 100%;"
  36 + />
  37 + </el-col>
  38 + <el-col :span="12">
  39 + <el-button type="primary" @click="queryFeeDetailMethod()">
  40 + <i class="el-icon-search"></i>
  41 + {{ $t('propertyFee.searchNow') }}
  42 + </el-button>
  43 + <el-button type="info" @click="resetFeeDetailMethod()" style="margin-left: 20px;">
  44 + <i class="el-icon-refresh"></i>
  45 + {{ $t('propertyFee.reset') }}
  46 + </el-button>
  47 + </el-col>
  48 + </el-row>
  49 +
  50 + <el-table
  51 + :data="feeDetailInfo.feeDetails"
  52 + style="width: 100%; margin-top: 20px;"
  53 + border
  54 + stripe
  55 + >
  56 + <el-table-column prop="detailId" :label="$t('propertyFee.paymentId')" align="center" />
  57 + <el-table-column prop="cycles" :label="$t('propertyFee.cycle')" align="center" />
  58 + <el-table-column prop="primeRateName" :label="$t('propertyFee.paymentMethod')" align="center" />
  59 + <el-table-column :label="$t('propertyFee.receivableAmount')" align="center">
  60 + <template slot-scope="scope">
  61 + <span v-if="scope.row.state=='1500'">{{scope.row.payerObjName}}{{$t('propertyFee.viewInFee')}}</span>
  62 + <span v-else>{{scope.row.receivableAmount}}</span>
  63 + </template>
  64 + </el-table-column>
  65 + <el-table-column :label="$t('propertyFee.receivedAmount')" align="center">
  66 + <template slot-scope="scope">
  67 + {{scope.row.receivedAmount}}<br>
  68 + <div v-if="scope.row.acctAmount>0">
  69 + {{$t('propertyFee.accountDeduction')}}: {{scope.row.acctAmount}}<br>
  70 + </div>
  71 + <div v-for="(item,index) in scope.row.payFeeDetailDiscountDtoList" :key="index">
  72 + {{item.discountName}}: {{Math.abs(item.discountPrice)}}<br>
  73 + </div>
  74 + </template>
  75 + </el-table-column>
  76 + <el-table-column prop="createTime" :label="$t('propertyFee.paymentTime')" align="center" />
  77 + <el-table-column :label="$t('propertyFee.startTime')" align="center">
  78 + <template slot-scope="scope">
  79 + {{dateFormat(scope.row.startTime)}}
  80 + </template>
  81 + </el-table-column>
  82 + <el-table-column :label="$t('propertyFee.endTime')" align="center">
  83 + <template slot-scope="scope">
  84 + {{dateFormat(scope.row.endTime)}}
  85 + </template>
  86 + </el-table-column>
  87 + <el-table-column prop="cashierName" :label="$t('propertyFee.cashier')" align="center" />
  88 + <el-table-column prop="stateName" :label="$t('propertyFee.status')" align="center" />
  89 + <el-table-column prop="remark" :label="$t('propertyFee.remark')" align="center" />
  90 + <el-table-column :label="$t('propertyFee.operation')" align="center">
  91 + <template slot-scope="scope">
  92 + <el-button-group>
  93 + <el-button
  94 + v-if="scope.row.state=='1400' || scope.row.state== '1200' || scope.row.state== ''"
  95 + size="mini"
  96 + @click="_openRefundModel(scope.row)"
  97 + >
  98 + {{ $t('propertyFee.applyRefund') }}
  99 + </el-button>
  100 + <el-button
  101 + v-if="scope.row.state!='1500'"
  102 + size="mini"
  103 + @click="_openFeeDetailDiscountModal(scope.row)"
  104 + >
  105 + {{ $t('propertyFee.discount') }}
  106 + </el-button>
  107 + </el-button-group>
  108 + </template>
  109 + </el-table-column>
  110 + </el-table>
  111 +
  112 + <el-pagination
  113 + :current-page.sync="page.current"
  114 + :page-sizes="[10, 20, 30, 50]"
  115 + :page-size="page.size"
  116 + :total="page.total"
  117 + layout="total, sizes, prev, pager, next, jumper"
  118 + @size-change="handleSizeChange"
  119 + @current-change="handleCurrentChange"
  120 + style="margin-top: 20px;"
  121 + />
  122 + </el-card>
  123 +
  124 + <!-- 子组件 -->
  125 + <return-pay-fee ref="returnPayFee" />
  126 + <view-fee-detail-discount ref="viewFeeDetailDiscount" />
  127 + </el-card>
  128 + </div>
  129 +</template>
  130 +
  131 +<script>
  132 +import { getCommunityId } from '@/api/community/communityApi'
  133 +import { queryFeeDetail } from '@/api/fee/propertyFeeApi'
  134 +import ViewMainFee from '@/components/fee/viewMainFee'
  135 +import ReturnPayFee from '@/components/fee/returnPayFee'
  136 +import ViewFeeDetailDiscount from '@/components/fee/viewFeeDetailDiscount'
  137 +
  138 +export default {
  139 + name: 'PropertyFeeList',
  140 + components: {
  141 + ViewMainFee,
  142 + ReturnPayFee,
  143 + ViewFeeDetailDiscount
  144 + },
  145 + data() {
  146 + return {
  147 + feeDetailInfo: {
  148 + feeDetails: [],
  149 + total: 0,
  150 + records: 1,
  151 + feeId: '',
  152 + startTime: '',
  153 + endTime: ''
  154 + },
  155 + page: {
  156 + current: 1,
  157 + size: 10,
  158 + total: 0
  159 + },
  160 + communityId: ''
  161 + }
  162 + },
  163 + created() {
  164 + this.communityId = getCommunityId()
  165 + },
  166 + methods: {
  167 + dateFormat(date) {
  168 + if (!date) return ''
  169 + return this.$moment(date).format('YYYY-MM-DD')
  170 + },
  171 + async listFeeDetail(page = 1, row = 10) {
  172 + try {
  173 + const params = {
  174 + page,
  175 + row,
  176 + communityId: this.communityId,
  177 + feeId: this.feeDetailInfo.feeId,
  178 + startTime: this.feeDetailInfo.startTime,
  179 + endTime: this.feeDetailInfo.endTime
  180 + }
  181 +
  182 + const { data, total, records } = await queryFeeDetail(params)
  183 + this.feeDetailInfo.feeDetails = data
  184 + this.feeDetailInfo.total = total
  185 + this.feeDetailInfo.records = records
  186 + this.page.total = records
  187 + } catch (error) {
  188 + console.error('获取费用明细失败:', error)
  189 + }
  190 + },
  191 + queryFeeDetailMethod() {
  192 + this.page.current = 1
  193 + this.listFeeDetail()
  194 + },
  195 + resetFeeDetailMethod() {
  196 + this.feeDetailInfo.startTime = ''
  197 + this.feeDetailInfo.endTime = ''
  198 + this.queryFeeDetailMethod()
  199 + },
  200 + _openRefundModel(feeDetail) {
  201 + this.$refs.returnPayFee.open(feeDetail)
  202 + },
  203 + _openFeeDetailDiscountModal(detail) {
  204 + this.$refs.viewFeeDetailDiscount.open(detail)
  205 + },
  206 + handleSizeChange(val) {
  207 + this.page.size = val
  208 + this.listFeeDetail(this.page.current, val)
  209 + },
  210 + handleCurrentChange(val) {
  211 + this.page.current = val
  212 + this.listFeeDetail(val, this.page.size)
  213 + }
  214 + }
  215 +}
  216 +</script>
  217 +
  218 +<style lang="scss" scoped>
  219 +.property-fee-container {
  220 + padding: 20px;
  221 +
  222 + .box-card {
  223 + margin-bottom: 20px;
  224 + }
  225 +
  226 + .clearfix {
  227 + font-size: 18px;
  228 + font-weight: bold;
  229 + }
  230 +}
  231 +</style>
0 \ No newline at end of file 232 \ No newline at end of file
src/views/fee/roomCreateFeeLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + roomCreateFee: {
  4 + customTemplate: 'Custom Template',
  5 + customImport: 'Custom Import',
  6 + batchCreate: 'Batch Create',
  7 + batchCollectionLetter: 'Batch Collection Letter',
  8 + roomNumPlaceholder: 'Room number, e.g. 1-1-1123',
  9 + ownerNamePlaceholder: 'Please enter owner name',
  10 + roomFee: 'Room Fee',
  11 + paymentHistory: 'Payment History',
  12 + rooms: 'Rooms',
  13 + owner: 'Owner',
  14 + callable: 'Callable',
  15 + receiptReprint: 'Receipt Reprint',
  16 + meterReadingRecords: 'Meter Reading Records',
  17 + prepaidAccount: 'Prepaid Account',
  18 + prepaidReprint: 'Prepaid Reprint',
  19 + deposit: 'Deposit',
  20 + billingRules: 'Billing Rules',
  21 + feeBills: 'Fee Bills'
  22 + },
  23 + inputSearchRoom: {
  24 + noRoomFound: 'No room found'
  25 + },
  26 + inputSearchRoomDemo: {
  27 + searchPlaceholder: 'Search by room number'
  28 + },
  29 + inputSearchRoomByOwnerDemo: {
  30 + searchPlaceholder: 'Search by owner name'
  31 + },
  32 + tempImportRoomFee: {
  33 + title: 'Temporary Fee',
  34 + feeType: 'Fee Type',
  35 + selectFeeType: 'Required, please select fee type',
  36 + feeObj: 'Fee Object',
  37 + inputFeeObj: 'Required, please fill in fee object',
  38 + feeName: 'Fee Name',
  39 + selectFeeItem: 'Required, please select fee item',
  40 + feeItemDesc: 'Description: Items with formulas are dynamic fee items',
  41 + inputFeeName: 'Required, please fill in fee name',
  42 + select: 'Select',
  43 + amount: 'Amount',
  44 + inputAmount: 'Required, please fill in amount',
  45 + startTime: 'Start Time',
  46 + selectStartTime: 'Required, please select start time',
  47 + endTime: 'End Time',
  48 + selectEndTime: 'Required, please select end time',
  49 + cancel: 'Cancel',
  50 + submit: 'Submit',
  51 + feeTypeRequired: 'Fee type cannot be empty',
  52 + feeNameRequired: 'Fee name cannot be empty',
  53 + feeObjRequired: 'Fee object cannot be empty',
  54 + startTimeRequired: 'Start time cannot be empty',
  55 + endTimeRequired: 'End time cannot be empty',
  56 + endTimeMustAfterStart: 'End time must be after start time',
  57 + amountRequired: 'Amount cannot be empty',
  58 + createSuccess: 'Created successfully',
  59 + createFailed: 'Creation failed'
  60 + },
  61 + tempImportRoomFeeDemo: {
  62 + openModal: 'Open Temporary Fee Modal'
  63 + },
  64 + simplifyRoomFee: {
  65 + selectFeeType: 'Select Fee Type',
  66 + selectFeeItem: 'Select Fee Item',
  67 + selectStatus: 'Select Status',
  68 + currentRoom: 'Current Room',
  69 + currentOwner: 'Current Owner',
  70 + default: 'Default',
  71 + monthly: 'Monthly',
  72 + batchPayment: 'Batch Payment',
  73 + tempFee: 'Temporary Fee',
  74 + quantityPayment: 'Quantity Payment',
  75 + waterElectricity: 'Water & Electricity',
  76 + feePackage: 'Fee Package',
  77 + createFee: 'Create Fee',
  78 + arrearsPayment: 'Arrears Payment',
  79 + feeItem: 'Fee Item',
  80 + feeFlag: 'Fee Flag',
  81 + feeType: 'Fee Type',
  82 + receivableAmount: 'Receivable Amount',
  83 + accountTime: 'Account Time',
  84 + receivablePeriod: 'Receivable Period',
  85 + description: 'Description',
  86 + status: 'Status',
  87 + operation: 'Operation',
  88 + preDegrees: 'Previous Degrees:',
  89 + curDegrees: 'Current Degrees:',
  90 + unitPrice: 'Unit Price:',
  91 + additionalFee: 'Additional Fee:',
  92 + usage: 'Usage:',
  93 + algorithm: 'Algorithm:',
  94 + fixedFee: 'Fixed Fee:',
  95 + moreOperations: 'More Operations',
  96 + cancelFee: 'Cancel Fee',
  97 + manualEnd: 'Manual End',
  98 + feeChange: 'Fee Change',
  99 + details: 'Details',
  100 + chargeYearMonth: 'Charge Year-Month',
  101 + note1: 'Note: The receivable end time "-" means not yet receivable or fee collection has ended',
  102 + note2: 'Receivable amount -1 generally indicates an error in the fee item formula setting, please check',
  103 + arrearsSubtotal: 'Arrears Subtotal:',
  104 + valid: 'Valid',
  105 + feeEnd: 'Fee End',
  106 + payment: 'Payment',
  107 + paymentHistory: 'Payment History'
  108 + },
  109 + simplifyHisFee: {
  110 + feeItem: 'Fee Item',
  111 + payerObject: 'Payer Object',
  112 + receiptNumber: 'Receipt Number',
  113 + manualGenerate: 'Manual Generate',
  114 + cycle: 'Cycle(Month)',
  115 + receivableReceived: 'Receivable/Received(Yuan)',
  116 + accountDeduction: 'Account Deduction',
  117 + paymentMethod: 'Payment Method',
  118 + paymentPeriod: 'Payment Period',
  119 + paymentTime: 'Payment Time',
  120 + cashier: 'Cashier',
  121 + status: 'Status',
  122 + remark: 'Remark',
  123 + operation: 'Operation',
  124 + detail: 'Detail',
  125 + generateReceipt: 'Generate Receipt',
  126 + systemGenerate: 'System Generate',
  127 + custom: 'Custom',
  128 + receiptNumberRequired: 'Required, please select receipt number generation method',
  129 + cancel: 'Cancel',
  130 + generate: 'Generate',
  131 + viewInFee: 'view in fee'
  132 + },
  133 + simplifyOwnerRooms: {
  134 + batchPay: 'Batch Payment',
  135 + roomCode: 'Room Code',
  136 + floor: 'Floor',
  137 + type: 'Type',
  138 + area: 'Built/Indoor Area',
  139 + rent: 'Rent',
  140 + validity: 'Validity',
  141 + roomStatus: 'Room Status',
  142 + roomOweFee: 'Room Owe Fee',
  143 + updateDaily: 'Update Daily',
  144 + actions: 'Actions',
  145 + choose: 'Choose',
  146 + currentRoom: 'Current Room',
  147 + subtotalOweFee: 'Subtotal Owe Fee'
  148 + },
  149 + carDetailOwner: {
  150 + ownerFace: 'Owner Face',
  151 + name: 'Name',
  152 + gender: 'Gender',
  153 + male: 'Male',
  154 + female: 'Female',
  155 + idCard: 'ID Card',
  156 + address: 'Address',
  157 + roomCount: 'Room Count',
  158 + memberCount: 'Member Count',
  159 + carCount: 'Car Count',
  160 + complaintCount: 'Complaint',
  161 + repairCount: 'Repair',
  162 + oweFee: 'Owe Fee',
  163 + contractCount: 'Contract',
  164 + actions: 'Actions',
  165 + detail: 'Detail'
  166 + },
  167 + writeOweFeeCallable: {
  168 + title: 'Callable Registration',
  169 + room: 'Registration Room',
  170 + roomPlaceholder: 'Required, please fill in the room',
  171 + fees: 'Callable Fees',
  172 + remark: 'Callable Remark',
  173 + remarkPlaceholder: 'Please enter remark',
  174 + cancel: 'Cancel',
  175 + submit: 'Submit',
  176 + success: 'Registration successful'
  177 + },
  178 + deleteOweFeeCallable: {
  179 + title: 'Please confirm your operation!',
  180 + confirmDelete: 'Confirm to delete owe fee callable',
  181 + cancel: 'Cancel',
  182 + confirm: 'Confirm Delete!',
  183 + success: 'Delete successful'
  184 + },
  185 + simplifyCallable: {
  186 + register: 'Register',
  187 + callable: 'Callable',
  188 + callableOrder: 'Callable Order',
  189 + noRoomSelected: 'No room selected',
  190 + id: 'ID',
  191 + ownerName: 'Owner Name',
  192 + payerObjName: 'Payer Object Name',
  193 + feeName: 'Fee Name',
  194 + amount: 'Amount',
  195 + timePeriod: 'Time Period',
  196 + callableWay: 'Callable Way',
  197 + staffName: 'Staff Name',
  198 + status: 'Status',
  199 + remark: 'Remark',
  200 + createTime: 'Create Time',
  201 + actions: 'Operations',
  202 + delete: 'Delete'
  203 + },
  204 + simplifyFeeReceipt: {
  205 + selectFeeType: 'Please select fee type',
  206 + selectCar: 'Please select car',
  207 + selectContract: 'Please select contract',
  208 + current: 'Current ',
  209 + car: 'Car',
  210 + room: 'Room',
  211 + all: 'All ',
  212 + receiptCode: 'Receipt Code',
  213 + query: 'Query',
  214 + print: 'Print',
  215 + mergePrint: 'Merge Print',
  216 + printSmall: 'Print Small',
  217 + apply: 'Apply',
  218 + feeType: 'Fee Type',
  219 + owner: 'Owner',
  220 + feeItem: 'Fee Item',
  221 + timePeriod: 'Time Period',
  222 + totalAmount: 'Total Amount',
  223 + payTime: 'Pay Time',
  224 + receiptId: 'Receipt ID',
  225 + yuan: 'Yuan',
  226 + fee: 'Fee',
  227 + noCar: 'No car',
  228 + noContract: 'No contract',
  229 + selectReceipt: 'Please select receipt',
  230 + contract: 'Contract'
  231 + },
  232 + simplifyMeterWaterLog: {
  233 + selectMeterType: 'Select meter type',
  234 + addMeterReading: 'Add meter reading',
  235 + meterType: 'Meter Type',
  236 + objectName: 'Object Name',
  237 + previousReading: 'Previous Reading',
  238 + currentReading: 'Current Reading',
  239 + previousReadingTime: 'Previous Reading Time',
  240 + currentReadingTime: 'Current Reading Time',
  241 + createTime: 'Create Time'
  242 + },
  243 + prestoreAccount: {
  244 + title: 'Prestore',
  245 + accountType: 'Account Type',
  246 + selectAccountType: 'Please select account type',
  247 + ownerPhone: 'Owner Phone',
  248 + ownerPhonePlaceholder: 'Required, please enter owner phone',
  249 + ownerName: 'Owner Name',
  250 + selectOwner: 'Required, please select owner',
  251 + deductionRoom: 'Deduction Room',
  252 + selectRoom: 'Required, please select room',
  253 + prestoreAmount: 'Prestore Amount',
  254 + prestoreAmountPlaceholder: 'Required, please enter prestore amount',
  255 + paymentMethod: 'Payment Method',
  256 + selectPaymentMethod: 'Required, please select payment method',
  257 + remark: 'Remark',
  258 + remarkPlaceholder: 'Optional, please enter remark',
  259 + cancel: 'Cancel',
  260 + save: 'Save',
  261 + validateOwner: 'Owner cannot be empty',
  262 + validateAmount: 'Amount cannot be empty',
  263 + validateAccountType: 'Please select account type',
  264 + validateRemark: 'Remark cannot exceed 200 characters',
  265 + saveSuccess: 'Prestore success',
  266 + saveFailed: 'Prestore failed'
  267 + },
  268 +
  269 + simplifyRefundDeposit: {
  270 + chargeObject: 'Charge Object',
  271 + feeItem: 'Fee Item',
  272 + timePeriod: 'Time Period',
  273 + amount: 'Amount',
  274 + paymentTime: 'Payment Time',
  275 + status: 'Status',
  276 + operation: 'Operation',
  277 + refundDeposit: 'Refund Deposit',
  278 + detail: 'Detail'
  279 + },
  280 + deleteFeeRule: {
  281 + confirmTitle: 'Please confirm your operation',
  282 + confirmMessage: 'Confirm to delete the fee rule? When deleting the fee rule, related fees and payment records will also be deleted!',
  283 + cancel: 'Cancel',
  284 + confirmDelete: 'Confirm Delete',
  285 + deleteSuccess: 'Delete success',
  286 + deleteFailed: 'Delete failed'
  287 + },
  288 + editFeeRule: {
  289 + title: 'Bill Change',
  290 + maxTime: 'Bill End Time',
  291 + maxTimePlaceholder: 'Required, please fill in the bill end time',
  292 + curYearMonth: 'Bill Day',
  293 + curYearMonthPlaceholder: 'Required, please fill in the bill day',
  294 + dateError: 'Bill day should be greater than {date}',
  295 + maxTimeRequired: 'Bill end time is required',
  296 + curYearMonthRequired: 'Bill day is required'
  297 + },
  298 + finishFeeRule: {
  299 + title: 'Please confirm your operation',
  300 + confirmMessage: 'End the fee bill, no new bill fees will be generated on the bill day!'
  301 + },
  302 + feeDetailFeeRule: {
  303 + ruleId: 'Rule ID',
  304 + feeItem: 'Fee Item',
  305 + feeFlag: 'Fee Flag',
  306 + createTime: 'Create Time',
  307 + validPeriod: 'Valid Period',
  308 + formula: 'Bill Formula',
  309 + price: 'Price',
  310 + additionalFee: 'Additional/Fixed Fee',
  311 + status: 'Status',
  312 + billDay: 'Bill Day',
  313 + billCycle: 'Bill Cycle'
  314 + },
  315 + feeDetailRuleBill: {
  316 + billName: 'Bill Name',
  317 + feeItem: 'Fee Item',
  318 + receivablePeriod: 'Receivable Period',
  319 + receivableAmount: 'Receivable Amount',
  320 + ruleId: 'Rule ID',
  321 + feeId: 'Fee ID',
  322 + status: 'Status',
  323 + description: 'Description',
  324 + price: 'Price',
  325 + fixedFee: 'Fixed Fee'
  326 + },
  327 + deleteFee: {
  328 + title: 'Please confirm your operation',
  329 + confirmMessage: 'Confirm to delete the fee'
  330 + },
  331 + editFee: {
  332 + title: 'Fee Change',
  333 + startTime: 'Create Time',
  334 + startTimePlaceholder: 'Required, please fill in the create time',
  335 + endTime: 'Receivable Start Time',
  336 + endTimePlaceholder: 'Required, please fill in the receivable start time',
  337 + maxEndTime: 'Receivable End Time',
  338 + maxEndTimePlaceholder: 'Required, please fill in the receivable end time',
  339 + rateCycle: 'Rate Cycle',
  340 + rateCyclePlaceholder: 'Required, please fill in the rate cycle (months)',
  341 + rate: 'Rate',
  342 + ratePlaceholder: 'Required, please fill in the rate',
  343 + rateStartTime: 'Rate Start Time',
  344 + rateStartTimePlaceholder: 'Required, please fill in the rate start time',
  345 + startTimeError: 'Create time must be less than receivable start time',
  346 + endTimeError: 'Receivable start time must be greater than create time',
  347 + maxEndTimeError: 'Receivable end time must be greater than create time',
  348 + rateStartTimeError: 'Rate start time must be greater than create time',
  349 + startTimeRequired: 'Create time is required',
  350 + endTimeRequired: 'Receivable start time is required'
  351 + },
  352 + roomCreateFeeAdd: {
  353 + title: 'Create Fee',
  354 + location: 'Room',
  355 + locationPlaceholder: 'Required, please fill in the charge scope',
  356 + feeType: 'Fee Type',
  357 + feeTypePlaceholder: 'Required, please select fee type',
  358 + feeItem: 'Fee Item',
  359 + feeItemPlaceholder: 'Required, please select fee item',
  360 + amount: 'Amount',
  361 + amountPlaceholder: 'Required, please fill in the amount',
  362 + startTime: 'Start Time',
  363 + startTimePlaceholder: 'Required, please fill in start time',
  364 + endTime: 'End Time',
  365 + endTimePlaceholder: 'Required, please fill in end time',
  366 + rateCycle: 'Rate Cycle',
  367 + rateCyclePlaceholder: 'Required, please fill in rate cycle (months)',
  368 + rate: 'Rate',
  369 + ratePlaceholder: 'Required, please fill in rate',
  370 + rateStartTime: 'Rate Start Time',
  371 + rateStartTimePlaceholder: 'Required, please fill in rate start time',
  372 + validate: {
  373 + locationRequired: 'Room is required',
  374 + feeTypeRequired: 'Fee type is required',
  375 + feeItemRequired: 'Fee item is required',
  376 + startTimeRequired: 'Start time is required',
  377 + endTimeRequired: 'End time is required',
  378 + startBeforeEnd: 'Start time must be before end time',
  379 + endAfterStart: 'End time must be after start time'
  380 + },
  381 + successMessage: 'Fee created successfully'
  382 + },
  383 + roomCreateFeeAddDemo: {
  384 + openModal: 'Open Create Fee Modal',
  385 + successMessage: 'Fee created successfully'
  386 + },
  387 + addProxyFee: {
  388 + title: 'Pay by Quantity',
  389 + feeType: 'Fee Type',
  390 + feeTypePlaceholder: 'Required, please select fee type',
  391 + feeItem: 'Fee Item',
  392 + feeItemPlaceholder: 'Required, please select fee item',
  393 + feeItemTip: 'Note: Display items with formula (usage * unit price + additional fee)',
  394 + chargeObject: 'Charge Object',
  395 + chargeObjectPlaceholder: 'Required, please fill in room',
  396 + consumption: 'Consumption',
  397 + consumptionPlaceholder: 'Required, please fill in consumption',
  398 + quantity: 'Quantity',
  399 + amount: 'Amount',
  400 + amountPlaceholder: 'Required, please fill in amount',
  401 + startTime: 'Start Time',
  402 + startTimePlaceholder: 'Required, please fill in start time',
  403 + endTime: 'End Time',
  404 + endTimePlaceholder: 'Required, please fill in end time',
  405 + waterFee: 'Water Fee',
  406 + electricityFee: 'Electricity Fee',
  407 + otherFee: 'Other',
  408 + validate: {
  409 + amountRequired: 'Amount is required',
  410 + amountFormat: 'Invalid amount format, e.g. 3.00',
  411 + consumptionRequired: 'Consumption is required',
  412 + consumptionFormat: 'Invalid consumption format, e.g. 3.00',
  413 + roomRequired: 'Room is required',
  414 + feeRequired: 'Fee is required',
  415 + startTimeRequired: 'Start time is required',
  416 + endTimeRequired: 'End time is required',
  417 + startBeforeEnd: 'Start time must be before end time',
  418 + endAfterStart: 'End time must be after start time',
  419 + invalidConfig: 'Invalid fee item or formula error',
  420 + amountTooSmall: 'Amount is too small'
  421 + },
  422 + successMessage: 'Saved successfully'
  423 + },
  424 + addProxyFeeDemo: {
  425 + openModal: 'Open Pay by Quantity Modal',
  426 + successMessage: 'Saved successfully'
  427 + },
  428 + exportFeeImportExcel: {
  429 + title: 'Template Export',
  430 + floor: 'Floor',
  431 + feeItem: 'Fee Item',
  432 + all: 'All',
  433 + successMessage: 'Export successful'
  434 + },
  435 + exportFeeImportExcelDemo: {
  436 + openModal: 'Open Template Export Modal'
  437 + },
  438 + doImportCreateFee: {
  439 + title: 'Custom Create Fee',
  440 + selectFile: 'Select File',
  441 + clickUpload: 'Click to upload',
  442 + fileTip: 'Required, please select data file',
  443 + validate: {
  444 + invalidFileType: 'Invalid Excel format',
  445 + fileTooLarge: 'Excel file size cannot exceed 2MB'
  446 + },
  447 + successMessage: 'Import successful'
  448 + },
  449 + doImportCreateFeeDemo: {
  450 + openModal: 'Open Custom Create Fee Modal'
  451 + },
  452 + downloadCollectionLetterOrder: {
  453 + title: 'Batch Collection Letter',
  454 + confirmExport: 'Confirm to export collection letter',
  455 + selectFloor: 'Select Floor',
  456 + floorPlaceholder: 'Required, please select floor'
  457 + },
  458 + downloadCollectionLetterOrderDemo: {
  459 + openModal: 'Open Collection Letter Modal'
  460 + }
  461 + },
  462 + zh: {
  463 + roomCreateFee: {
  464 + customTemplate: '自定义模板',
  465 + customImport: '自定义导入',
  466 + batchCreate: '批量创建',
  467 + batchCollectionLetter: '批量催缴单',
  468 + roomNumPlaceholder: '房屋编号,如1-1-1123',
  469 + ownerNamePlaceholder: '请填写业主名称',
  470 + roomFee: '房屋费用',
  471 + paymentHistory: '缴费历史',
  472 + rooms: '房屋',
  473 + owner: '业主',
  474 + callable: '催缴',
  475 + receiptReprint: '补打收据',
  476 + meterReadingRecords: '抄表记录',
  477 + prepaidAccount: '预存账户',
  478 + prepaidReprint: '预存补打',
  479 + deposit: '押金',
  480 + billingRules: '账单规则',
  481 + feeBills: '费用账单'
  482 + },
  483 + inputSearchRoom: {
  484 + noRoomFound: '未查询到房屋'
  485 + },
  486 + inputSearchRoomDemo: {
  487 + searchPlaceholder: '按房号搜索'
  488 + },
  489 + inputSearchRoomByOwnerDemo: {
  490 + searchPlaceholder: '按业主姓名搜索'
  491 + },
  492 + tempImportRoomFee: {
  493 + title: '临时收费',
  494 + feeType: '费用类型',
  495 + selectFeeType: '必填,请选择费用类型',
  496 + feeObj: '费用对象',
  497 + inputFeeObj: '必填,请填写费用对象',
  498 + feeName: '费用名称',
  499 + selectFeeItem: '必填,请选择收费项目',
  500 + feeItemDesc: '说明:显示公式为动态费用的费用项',
  501 + inputFeeName: '必填,请填写费用名称',
  502 + select: '选择',
  503 + amount: '收费金额',
  504 + inputAmount: '必填,请填写收费金额',
  505 + startTime: '开始时间',
  506 + selectStartTime: '必填,请填写开始时间',
  507 + endTime: '结束时间',
  508 + selectEndTime: '必填,请填写结束时间',
  509 + cancel: '取消',
  510 + submit: '提交',
  511 + feeTypeRequired: '费用类型不能为空',
  512 + feeNameRequired: '费用名称不能为空',
  513 + feeObjRequired: '费用对象不能为空',
  514 + startTimeRequired: '开始时间不能为空',
  515 + endTimeRequired: '结束时间不能为空',
  516 + endTimeMustAfterStart: '结束时间必须大于开始时间',
  517 + amountRequired: '金额不能为空',
  518 + createSuccess: '创建成功',
  519 + createFailed: '创建失败'
  520 + },
  521 + tempImportRoomFeeDemo: {
  522 + openModal: '打开临时收费模态框'
  523 + },
  524 + simplifyRoomFee: {
  525 + selectFeeType: '请选择费用类型',
  526 + selectFeeItem: '请选择收费项目',
  527 + selectStatus: '请选择状态',
  528 + currentRoom: '当前房屋',
  529 + currentOwner: '当前业主',
  530 + default: '默认',
  531 + monthly: '按月',
  532 + batchPayment: '批量缴费',
  533 + tempFee: '临时收费',
  534 + quantityPayment: '按量缴费',
  535 + waterElectricity: '水电抄表',
  536 + feePackage: '费用套餐',
  537 + createFee: '创建费用',
  538 + arrearsPayment: '欠费缴费',
  539 + feeItem: '费用项目',
  540 + feeFlag: '费用标识',
  541 + feeType: '费用类型',
  542 + receivableAmount: '应收金额',
  543 + accountTime: '建账时间',
  544 + receivablePeriod: '应收时间段',
  545 + description: '说明',
  546 + status: '状态',
  547 + operation: '操作',
  548 + preDegrees: '上期度数:',
  549 + curDegrees: '本期度数:',
  550 + unitPrice: '单价:',
  551 + additionalFee: '附加费:',
  552 + usage: '用量:',
  553 + algorithm: '算法:',
  554 + fixedFee: '固定费:',
  555 + moreOperations: '更多操作',
  556 + cancelFee: '取消费用',
  557 + manualEnd: '手工结束',
  558 + feeChange: '费用变更',
  559 + details: '详情',
  560 + chargeYearMonth: '收费年月',
  561 + note1: '注意:应收结束时间 "-" 表示未到应收时间或收费已结束',
  562 + note2: '应收金额为-1一般为费用项公式设置出错请检查',
  563 + arrearsSubtotal: '欠费小计:',
  564 + valid: '有效',
  565 + feeEnd: '收费结束',
  566 + payment: '缴费',
  567 + paymentHistory: '缴费历史'
  568 + },
  569 + simplifyHisFee: {
  570 + feeItem: '费用项',
  571 + payerObject: '收费对象',
  572 + receiptNumber: '收据编号',
  573 + manualGenerate: '手工生成',
  574 + cycle: '周期(单位:月)',
  575 + receivableReceived: '应收/实收(单位:元)',
  576 + accountDeduction: '账户扣款',
  577 + paymentMethod: '缴费方式',
  578 + paymentPeriod: '缴费起始段',
  579 + paymentTime: '缴费时间',
  580 + cashier: '收银员',
  581 + status: '状态',
  582 + remark: '备注',
  583 + operation: '操作',
  584 + detail: '详情',
  585 + generateReceipt: '生成收据',
  586 + systemGenerate: '系统生成',
  587 + custom: '自定义',
  588 + receiptNumberRequired: '必填,请选择收据编号生成方式',
  589 + cancel: '取消',
  590 + generate: '生成',
  591 + viewInFee: '费用中查看'
  592 + },
  593 + simplifyOwnerRooms: {
  594 + batchPay: '批量缴费',
  595 + roomCode: '房屋编号',
  596 + floor: '楼层',
  597 + type: '类型',
  598 + area: '建筑/室内面积',
  599 + rent: '租金',
  600 + validity: '有效期',
  601 + roomStatus: '房屋状态',
  602 + roomOweFee: '房屋欠费',
  603 + updateDaily: '按天更新',
  604 + actions: '操作',
  605 + choose: '选择',
  606 + currentRoom: '当前房屋',
  607 + subtotalOweFee: '欠费小计'
  608 + },
  609 + carDetailOwner: {
  610 + ownerFace: '业主人脸',
  611 + name: '姓名',
  612 + gender: '性别',
  613 + male: '男',
  614 + female: '女',
  615 + idCard: '身份证',
  616 + address: '家庭住址',
  617 + roomCount: '房屋数',
  618 + memberCount: '业主成员',
  619 + carCount: '车辆数',
  620 + complaintCount: '投诉',
  621 + repairCount: '报修',
  622 + oweFee: '欠费',
  623 + contractCount: '业主合同',
  624 + actions: '操作',
  625 + detail: '详情'
  626 + },
  627 + writeOweFeeCallable: {
  628 + title: '催缴登记',
  629 + room: '登记房屋',
  630 + roomPlaceholder: '必填,请填写房屋',
  631 + fees: '催缴费用',
  632 + remark: '催缴说明',
  633 + remarkPlaceholder: '请输入备注',
  634 + cancel: '取消',
  635 + submit: '提交',
  636 + success: '登记成功'
  637 + },
  638 + deleteOweFeeCallable: {
  639 + title: '请确认您的操作!',
  640 + confirmDelete: '确定删除欠费催缴',
  641 + cancel: '点错了',
  642 + confirm: '确认删除!',
  643 + success: '删除成功'
  644 + },
  645 + simplifyCallable: {
  646 + register: '登记',
  647 + callable: '催缴',
  648 + callableOrder: '催缴单',
  649 + noRoomSelected: '未选择房屋',
  650 + id: '编号',
  651 + ownerName: '业主名称',
  652 + payerObjName: '付费对象名称',
  653 + feeName: '费用名称',
  654 + amount: '催缴金额',
  655 + timePeriod: '欠费时间段',
  656 + callableWay: '催缴方式',
  657 + staffName: '催缴人',
  658 + status: '状态',
  659 + remark: '说明',
  660 + createTime: '创建时间',
  661 + actions: '操作',
  662 + delete: '删除'
  663 + },
  664 + simplifyFeeReceipt: {
  665 + selectFeeType: '请选择收费类型',
  666 + selectCar: '请选择车辆',
  667 + selectContract: '请选择合同',
  668 + current: '当前',
  669 + car: '车辆',
  670 + room: '房屋',
  671 + all: '全部',
  672 + receiptCode: '收据编号',
  673 + query: '查询',
  674 + print: '打印',
  675 + mergePrint: '合并打印',
  676 + printSmall: '打印小票',
  677 + apply: '申请单',
  678 + feeType: '费用类型',
  679 + owner: '业主',
  680 + feeItem: '费用项目',
  681 + timePeriod: '收费时间段',
  682 + totalAmount: '总金额',
  683 + payTime: '缴费时间',
  684 + receiptId: '收据ID',
  685 + yuan: '元',
  686 + fee: '费',
  687 + noCar: '没有车位',
  688 + noContract: '没有合同',
  689 + selectReceipt: '请选择收据',
  690 + contract: '合同'
  691 + },
  692 + simplifyMeterWaterLog: {
  693 + selectMeterType: '请选择表类型',
  694 + addMeterReading: '水电抄表',
  695 + meterType: '表类型',
  696 + objectName: '对象名称',
  697 + previousReading: '上期度数',
  698 + currentReading: '本期度数',
  699 + previousReadingTime: '上期读表时间',
  700 + currentReadingTime: '本期读表时间',
  701 + createTime: '创建时间'
  702 + },
  703 + prestoreAccount: {
  704 + title: '预存',
  705 + accountType: '账户类型',
  706 + selectAccountType: '必填,请选择账户类型',
  707 + ownerPhone: '业主手机',
  708 + ownerPhonePlaceholder: '必填,请填写业主手机号',
  709 + ownerName: '业主名称',
  710 + selectOwner: '必填,请选择业主',
  711 + deductionRoom: '扣款房屋',
  712 + selectRoom: '必填,请选择房屋',
  713 + prestoreAmount: '预存金额',
  714 + prestoreAmountPlaceholder: '必填,请填写预存金额',
  715 + paymentMethod: '支付方式',
  716 + selectPaymentMethod: '必填,请选择支付方式',
  717 + remark: '备注',
  718 + remarkPlaceholder: '可填,请填写备注',
  719 + cancel: '取消',
  720 + save: '保存',
  721 + validateOwner: '业主不能为空',
  722 + validateAmount: '金额不能为空',
  723 + validateAccountType: '请选择账户类型',
  724 + validateRemark: '备注长度不能超过200位',
  725 + saveSuccess: '预存成功',
  726 + saveFailed: '预存失败'
  727 + },
  728 +
  729 + simplifyRefundDeposit: {
  730 + chargeObject: '收费对象',
  731 + feeItem: '费用项',
  732 + timePeriod: '时间段',
  733 + amount: '金额',
  734 + paymentTime: '缴费时间',
  735 + status: '状态',
  736 + operation: '操作',
  737 + refundDeposit: '退押金',
  738 + detail: '详情'
  739 + },
  740 + deleteFeeRule: {
  741 + confirmTitle: '请确认您的操作',
  742 + confirmMessage: '确定删除账单规则,删除账单规则时,相关费用及缴费记录也会被删除!',
  743 + cancel: '点错了',
  744 + confirmDelete: '确认删除',
  745 + deleteSuccess: '删除成功',
  746 + deleteFailed: '删除失败'
  747 + },
  748 + editFeeRule: {
  749 + title: '账单变更',
  750 + maxTime: '账单结束时间',
  751 + maxTimePlaceholder: '必填,请填写账单结束时间',
  752 + curYearMonth: '账单日',
  753 + curYearMonthPlaceholder: '必填,请填写账单日',
  754 + dateError: '账单日应大于{date}',
  755 + maxTimeRequired: '账单结束时间不能为空',
  756 + curYearMonthRequired: '账单日不能为空'
  757 + },
  758 + finishFeeRule: {
  759 + title: '请确认您的操作',
  760 + confirmMessage: '结束费用账单,账单日不在产生新的账单费用!'
  761 + },
  762 + feeDetailFeeRule: {
  763 + ruleId: '规则编号',
  764 + feeItem: '费用项',
  765 + feeFlag: '费用标识',
  766 + createTime: '建账时间',
  767 + validPeriod: '账单有效期',
  768 + formula: '账单公式',
  769 + price: '计费单价',
  770 + additionalFee: '附加/固定费用',
  771 + status: '状态',
  772 + billDay: '账单日',
  773 + billCycle: '账单周期'
  774 + },
  775 + feeDetailRuleBill: {
  776 + billName: '账单名称',
  777 + feeItem: '费用项',
  778 + receivablePeriod: '应收时间段',
  779 + receivableAmount: '应收金额',
  780 + ruleId: '规则编号',
  781 + feeId: '费用编号',
  782 + status: '状态',
  783 + description: '说明',
  784 + price: '单价',
  785 + fixedFee: '固定费'
  786 + },
  787 + deleteFee: {
  788 + title: '请确认您的操作',
  789 + confirmMessage: '确定删除费用'
  790 + },
  791 + editFee: {
  792 + title: '费用变更',
  793 + startTime: '建账时间',
  794 + startTimePlaceholder: '必填,请填写建账时间',
  795 + endTime: '应收开始时间',
  796 + endTimePlaceholder: '必填,请填写应收开始时间',
  797 + maxEndTime: '应收结束时间',
  798 + maxEndTimePlaceholder: '必填,请填写应收结束时间',
  799 + rateCycle: '递增周期',
  800 + rateCyclePlaceholder: '必填,请填写递增周期,请填写月份',
  801 + rate: '计费递增率',
  802 + ratePlaceholder: '必填,请填写递增率',
  803 + rateStartTime: '递增开始时间',
  804 + rateStartTimePlaceholder: '必填,请填写递增开始时间',
  805 + startTimeError: '建账时间必须小于计费起始时间',
  806 + endTimeError: '计费起始时间必须大于建账时间',
  807 + maxEndTimeError: '计费结束时间必须大于开始时间',
  808 + rateStartTimeError: '递增开始时间必须大于开始时间',
  809 + startTimeRequired: '建账时间不能为空',
  810 + endTimeRequired: '计费起始时间不能为空'
  811 + },
  812 + roomCreateFeeAdd: {
  813 + title: '创建费用',
  814 + location: '房屋',
  815 + locationPlaceholder: '必填,请填写收费范围',
  816 + feeType: '费用类型',
  817 + feeTypePlaceholder: '必填,请选择费用类型',
  818 + feeItem: '收费项目',
  819 + feeItemPlaceholder: '必填,请选择收费项目',
  820 + amount: '收费金额',
  821 + amountPlaceholder: '必填,请填写收费金额',
  822 + startTime: '计费起始时间',
  823 + startTimePlaceholder: '必填,请填写计费起始时间',
  824 + endTime: '计费结束时间',
  825 + endTimePlaceholder: '必填,请填写计费结束时间',
  826 + rateCycle: '递增周期',
  827 + rateCyclePlaceholder: '必填,请填写递增周期,请填写月份',
  828 + rate: '计费递增率',
  829 + ratePlaceholder: '必填,请填写递增率',
  830 + rateStartTime: '递增开始时间',
  831 + rateStartTimePlaceholder: '必填,请填写递增开始时间',
  832 + validate: {
  833 + locationRequired: '收费对象不能为空',
  834 + feeTypeRequired: '费用类型不能为空',
  835 + feeItemRequired: '费用项目不能为空',
  836 + startTimeRequired: '计费起始时间不能为空',
  837 + endTimeRequired: '计费终止时间不能为空',
  838 + startBeforeEnd: '计费起始时间必须小于计费终止时间',
  839 + endAfterStart: '计费终止时间必须大于计费起始时间'
  840 + },
  841 + successMessage: '创建收费成功'
  842 + },
  843 + roomCreateFeeAddDemo: {
  844 + openModal: '打开创建费用弹窗',
  845 + successMessage: '费用创建成功'
  846 + },
  847 + addProxyFee: {
  848 + title: '按量缴费',
  849 + feeType: '费用类型',
  850 + feeTypePlaceholder: '必填,请选择费用类型',
  851 + feeItem: '收费项目',
  852 + feeItemPlaceholder: '必填,请选择收费项目',
  853 + feeItemTip: '说明:显示公式为(用量*单价+附加费)的费用项',
  854 + chargeObject: '收费对象',
  855 + chargeObjectPlaceholder: '必填,请填写房屋',
  856 + consumption: '用量',
  857 + consumptionPlaceholder: '必填,请填写用量',
  858 + quantity: '个数',
  859 + amount: '金额',
  860 + amountPlaceholder: '必填,请填写金额',
  861 + startTime: '开始时间',
  862 + startTimePlaceholder: '必填,请填写开始时间',
  863 + endTime: '结束时间',
  864 + endTimePlaceholder: '必填,请填写结束时间',
  865 + waterFee: '水费',
  866 + electricityFee: '电费',
  867 + otherFee: '其他',
  868 + validate: {
  869 + amountRequired: '金额不能为空',
  870 + amountFormat: '金额格式错误,如3.00',
  871 + consumptionRequired: '用量不能为空',
  872 + consumptionFormat: '用量格式错误,如3.00',
  873 + roomRequired: '房屋必填',
  874 + feeRequired: '费用必填',
  875 + startTimeRequired: '开始时间不能为空',
  876 + endTimeRequired: '结束时间不能为空',
  877 + startBeforeEnd: '开始时间必须小于结束时间',
  878 + endAfterStart: '结束时间必须大于开始时间',
  879 + invalidConfig: '未选择收费项目或者收费项目公式错误',
  880 + amountTooSmall: '输入金额太小'
  881 + },
  882 + successMessage: '保存成功'
  883 + },
  884 + addProxyFeeDemo: {
  885 + openModal: '打开按量缴费弹窗',
  886 + successMessage: '保存成功'
  887 + },
  888 + exportFeeImportExcel: {
  889 + title: '模板导出',
  890 + floor: '楼栋',
  891 + feeItem: '费用项',
  892 + all: '全部',
  893 + successMessage: '导出成功'
  894 + },
  895 + exportFeeImportExcelDemo: {
  896 + openModal: '打开模板导出弹窗'
  897 + },
  898 + doImportCreateFee: {
  899 + title: '自定义创建费用',
  900 + selectFile: '选择文件',
  901 + clickUpload: '点击上传',
  902 + fileTip: '必填,请选择数据文件',
  903 + validate: {
  904 + invalidFileType: '不是有效的Excel格式',
  905 + fileTooLarge: 'Excel文件大小不能超过2M'
  906 + },
  907 + successMessage: '导入成功'
  908 + },
  909 + doImportCreateFeeDemo: {
  910 + openModal: '打开自定义创建费用弹窗'
  911 + },
  912 + downloadCollectionLetterOrder: {
  913 + title: '批量催缴单',
  914 + confirmExport: '确认导出催缴单',
  915 + selectFloor: '选择楼栋',
  916 + floorPlaceholder: '必填,请选择楼栋'
  917 + },
  918 + downloadCollectionLetterOrderDemo: {
  919 + openModal: '打开催缴单弹窗'
  920 + }
  921 + }
  922 +}
0 \ No newline at end of file 923 \ No newline at end of file
src/views/fee/roomCreateFeeList.vue 0 → 100644
  1 +<template>
  2 + <div class="app-container">
  3 + <el-row :gutter="20">
  4 + <el-col :span="4" class="tree-container">
  5 + <room-tree-div ref="roomTreeDiv" @selectRoom="handleSelectRoom"></room-tree-div>
  6 + </el-col>
  7 + <el-col :span="20">
  8 + <el-card class="box-card">
  9 + <div slot="header" class="flex justify-between">
  10 + <span>{{ roomCreateFeeInfo.roomName }}</span>
  11 + <div class="header-tools">
  12 + <el-button v-if="hasPrivilege('502022073096990007')" size="small" @click="_openFeeImportExcel">
  13 + <i class="el-icon-download"></i>
  14 + {{ $t('roomCreateFee.customTemplate') }}
  15 + </el-button>
  16 + <el-button v-if="hasPrivilege('502022073096990007')" size="small" @click="_openDoCreateRoomFee">
  17 + <i class="el-icon-plus"></i>
  18 + {{ $t('roomCreateFee.customImport') }}
  19 + </el-button>
  20 + <el-button v-if="hasPrivilege('502022073096990007')" size="small" @click="_toBatchCreateFee(null, true)">
  21 + <i class="el-icon-plus"></i>
  22 + {{ $t('roomCreateFee.batchCreate') }}
  23 + </el-button>
  24 + <el-button size="small" @click="_downloadCollectionLetterOrder">
  25 + <i class="el-icon-download"></i>
  26 + {{ $t('roomCreateFee.batchCollectionLetter') }}
  27 + </el-button>
  28 + </div>
  29 + </div>
  30 +
  31 + <div class="filter-container">
  32 + <el-row :gutter="20">
  33 + <el-col :span="6">
  34 + <el-input v-model="roomCreateFeeInfo.condition.roomNum"
  35 + :placeholder="$t('roomCreateFee.roomNumPlaceholder')" clearable
  36 + @blur="listRoomInRoomCreateFee"></el-input>
  37 + <input-search-room ref="inputSearchRoom"></input-search-room>
  38 + </el-col>
  39 + <el-col :span="6">
  40 + <el-input v-model="roomCreateFeeInfo.condition.ownerName"
  41 + :placeholder="$t('roomCreateFee.ownerNamePlaceholder')" clearable
  42 + @input="_inputRoomByOwner"></el-input>
  43 + <input-search-room-by-owner ref="inputSearchRoomByOwner"></input-search-room-by-owner>
  44 + </el-col>
  45 + <el-col :span="6">
  46 + <el-button type="primary" size="small" @click="_queryRoomCreateFeeMethod">
  47 + {{ $t('common.query') }}
  48 + </el-button>
  49 + <el-button size="small" @click="_resetRoomCreateFeeMethod">
  50 + {{ $t('common.reset') }}
  51 + </el-button>
  52 + </el-col>
  53 + </el-row>
  54 + </div>
  55 +
  56 + <el-tabs v-model="roomCreateFeeInfo._currentTab" @tab-click="changeTab(roomCreateFeeInfo._currentTab)">
  57 + <el-tab-pane label="房屋费用" name="simplifyRoomFee">
  58 + <simplify-room-fee v-if="roomCreateFeeInfo._currentTab === 'simplifyRoomFee'"
  59 + ref="simplifyRoomFee"></simplify-room-fee>
  60 + </el-tab-pane>
  61 + <el-tab-pane v-if="roomCreateFeeInfo.ownerId" label="缴费历史" name="simplifyHisFee">
  62 + <simplify-his-fee v-if="roomCreateFeeInfo._currentTab === 'simplifyHisFee'"
  63 + ref="simplifyHisFee"></simplify-his-fee>
  64 + </el-tab-pane>
  65 + <el-tab-pane v-if="roomCreateFeeInfo.ownerId" label="房屋" name="simplifyOwnerRooms">
  66 + <simplify-owner-rooms v-if="roomCreateFeeInfo._currentTab === 'simplifyOwnerRooms'"
  67 + ref="simplifyOwnerRooms"></simplify-owner-rooms>
  68 + </el-tab-pane>
  69 + <el-tab-pane v-if="roomCreateFeeInfo.ownerId" label="业主" name="carDetailOwner">
  70 + <car-detail-owner v-if="roomCreateFeeInfo._currentTab === 'carDetailOwner'"
  71 + ref="carDetailOwner"></car-detail-owner>
  72 + </el-tab-pane>
  73 + <el-tab-pane label="催缴" name="simplifyCallable">
  74 + <simplify-callable v-if="roomCreateFeeInfo._currentTab === 'simplifyCallable'"
  75 + ref="simplifyCallable"></simplify-callable>
  76 + </el-tab-pane>
  77 + <el-tab-pane v-if="hasPrivilege('502020092373407363')" label="补打收据" name="simplifyFeeReceipt">
  78 + <simplify-fee-receipt v-if="roomCreateFeeInfo._currentTab === 'simplifyFeeReceipt'"
  79 + ref="simplifyFeeReceipt"></simplify-fee-receipt>
  80 + </el-tab-pane>
  81 + <el-tab-pane label="抄表记录" name="simplifyMeterWaterLog">
  82 + <simplify-meter-water-log v-if="roomCreateFeeInfo._currentTab === 'simplifyMeterWaterLog'"
  83 + ref="simplifyMeterWaterLog"></simplify-meter-water-log>
  84 + </el-tab-pane>
  85 + <el-tab-pane v-if="roomCreateFeeInfo.ownerId" label="预存账户" name="ownerDetailAccount">
  86 + <owner-detail-account v-if="roomCreateFeeInfo._currentTab === 'ownerDetailAccount'"
  87 + ref="ownerDetailAccount"></owner-detail-account>
  88 + </el-tab-pane>
  89 + <el-tab-pane v-if="roomCreateFeeInfo.ownerId" label="预存补打" name="ownerDetailAccountReceipt">
  90 + <owner-detail-account-receipt v-if="roomCreateFeeInfo._currentTab === 'ownerDetailAccountReceipt'"
  91 + ref="ownerDetailAccountReceipt"></owner-detail-account-receipt>
  92 + </el-tab-pane>
  93 + <el-tab-pane label="押金" name="simplifyRefundDeposit">
  94 + <simplify-refund-deposit v-if="roomCreateFeeInfo._currentTab === 'simplifyRefundDeposit'"
  95 + ref="simplifyRefundDeposit"></simplify-refund-deposit>
  96 + </el-tab-pane>
  97 + <el-tab-pane label="账单规则" name="feeDetailFeeRule">
  98 + <fee-detail-fee-rule v-if="roomCreateFeeInfo._currentTab === 'feeDetailFeeRule'"
  99 + ref="feeDetailFeeRule"></fee-detail-fee-rule>
  100 + </el-tab-pane>
  101 + <el-tab-pane label="费用账单" name="feeDetailRuleBill">
  102 + <fee-detail-rule-bill v-if="roomCreateFeeInfo._currentTab === 'feeDetailRuleBill'"
  103 + ref="feeDetailRuleBill"></fee-detail-rule-bill>
  104 + </el-tab-pane>
  105 + </el-tabs>
  106 + </el-card>
  107 + </el-col>
  108 + </el-row>
  109 +
  110 +
  111 + <room-create-fee-add ref="roomCreateFeeAdd"></room-create-fee-add>
  112 + <add-meter-water ref="addMeterWater"></add-meter-water>
  113 + <add-proxy-fee ref="addProxyFee"></add-proxy-fee>
  114 + <export-fee-import-excel ref="exportFeeImportExcel"></export-fee-import-excel>
  115 + <do-import-create-fee ref="doImportCreateFee"></do-import-create-fee>
  116 + <download-collection-letter-order ref="downloadCollectionLetterOrder"></download-collection-letter-order>
  117 + </div>
  118 +</template>
  119 +
  120 +<script>
  121 +import RoomTreeDiv from '@/components/room/roomTreeDiv'
  122 +import InputSearchRoom from '@/components/fee/inputSearchRoom'
  123 +import InputSearchRoomByOwner from '@/components/fee/inputSearchRoomByOwner'
  124 +import SimplifyRoomFee from '@/components/fee/simplifyRoomFee'
  125 +import SimplifyHisFee from '@/components/fee/simplifyHisFee'
  126 +import SimplifyOwnerRooms from '@/components/fee/simplifyOwnerRooms'
  127 +import CarDetailOwner from '@/components/fee/carDetailOwner'
  128 +import SimplifyCallable from '@/components/fee/simplifyCallable'
  129 +import SimplifyFeeReceipt from '@/components/fee/simplifyFeeReceipt'
  130 +import SimplifyMeterWaterLog from '@/components/fee/simplifyMeterWaterLog'
  131 +import OwnerDetailAccount from '@/components/owner/ownerDetailAccount'
  132 +import OwnerDetailAccountReceipt from '@/components/owner/ownerDetailAccountReceipt'
  133 +import SimplifyRefundDeposit from '@/components/fee/simplifyRefundDeposit'
  134 +import FeeDetailFeeRule from '@/components/fee/feeDetailFeeRule'
  135 +import FeeDetailRuleBill from '@/components/fee/feeDetailRuleBill'
  136 +
  137 +import RoomCreateFeeAdd from '@/components/fee/roomCreateFeeAdd'
  138 +import AddMeterWater from '@/components/fee/addMeterWater'
  139 +import AddProxyFee from '@/components/fee/addProxyFee'
  140 +import ExportFeeImportExcel from '@/components/fee/exportFeeImportExcel'
  141 +import DoImportCreateFee from '@/components/fee/doImportCreateFee'
  142 +import DownloadCollectionLetterOrder from '@/components/fee/downloadCollectionLetterOrder'
  143 +import { getCommunityId } from '@/api/community/communityApi'
  144 +import { queryRooms } from '@/api/fee/roomCreateFeeApi'
  145 +
  146 +export default {
  147 + name: 'RoomCreateFeeList',
  148 + components: {
  149 + RoomTreeDiv,
  150 + InputSearchRoom,
  151 + InputSearchRoomByOwner,
  152 + SimplifyRoomFee,
  153 + SimplifyHisFee,
  154 + SimplifyOwnerRooms,
  155 + CarDetailOwner,
  156 + SimplifyCallable,
  157 + SimplifyFeeReceipt,
  158 + SimplifyMeterWaterLog,
  159 + OwnerDetailAccount,
  160 + OwnerDetailAccountReceipt,
  161 + SimplifyRefundDeposit,
  162 + FeeDetailFeeRule,
  163 + FeeDetailRuleBill,
  164 +
  165 + RoomCreateFeeAdd,
  166 + AddMeterWater,
  167 + AddProxyFee,
  168 + ExportFeeImportExcel,
  169 + DoImportCreateFee,
  170 + DownloadCollectionLetterOrder
  171 + },
  172 + data() {
  173 + return {
  174 + roomCreateFeeInfo: {
  175 + roomName: '',
  176 + roomId: '',
  177 + ownerId: '',
  178 + ownerName: '',
  179 + roomType: '',
  180 + _currentTab: 'simplifyRoomFee',
  181 + condition: {
  182 + roomNum: '',
  183 + ownerName: ''
  184 + },
  185 + timer: null
  186 + },
  187 + communityId: ''
  188 + }
  189 + },
  190 + created() {
  191 + this.communityId = getCommunityId()
  192 + this.initRoomTree()
  193 + },
  194 + methods: {
  195 + initRoomTree() {
  196 + // this.$refs.roomTreeDiv.initRoomTreeDiv({
  197 + // callName: 'roomCreateFee'
  198 + // })
  199 + },
  200 + handleSelectRoom(param) {
  201 + this.roomCreateFeeInfo.ownerName = ''
  202 + this.roomCreateFeeInfo.ownerId = ''
  203 + this.roomCreateFeeInfo.roomId = param.roomId
  204 + this.roomCreateFeeInfo.roomName = param.roomName
  205 +
  206 + this.roomCreateFeeInfo.condition.ownerName = ''
  207 + this.roomCreateFeeInfo.condition.roomNum = ''
  208 + this.listRoomInRoomCreateFee()
  209 + },
  210 + notifyRoomByOwner(room) {
  211 + this.$set(this.roomCreateFeeInfo, 'ownerName', room.ownerName)
  212 + this.$set(this.roomCreateFeeInfo, 'ownerId', room.ownerId)
  213 + this.$set(this.roomCreateFeeInfo, 'roomId', room.roomId)
  214 + this.$set(
  215 + this.roomCreateFeeInfo,
  216 + 'roomName',
  217 + `${room.floorNum}-${room.unitNum}-${room.roomNum}`
  218 + )
  219 + this.listRoomInRoomCreateFee()
  220 + },
  221 + async listRoomInRoomCreateFee() {
  222 + const param = {
  223 + page: 1,
  224 + row: 1,
  225 + communityId: this.communityId,
  226 + roomId: this.roomCreateFeeInfo.roomId
  227 + }
  228 +
  229 + if (this.roomCreateFeeInfo.condition.roomNum) {
  230 + param.flag = '1'
  231 + param.roomNum = this.roomCreateFeeInfo.condition.roomNum
  232 + param.roomId = ''
  233 + this.roomCreateFeeInfo.roomName = ''
  234 + this.roomCreateFeeInfo.ownerName = ''
  235 + this.roomCreateFeeInfo.ownerId = ''
  236 + this.roomCreateFeeInfo.roomId = ''
  237 + }
  238 +
  239 + try {
  240 + const response = await queryRooms(param)
  241 + const room = response.rooms[0]
  242 + Object.assign(this.roomCreateFeeInfo, room)
  243 + this.changeTab('simplifyRoomFee')
  244 + } catch (error) {
  245 + console.error('请求失败:', error)
  246 + }
  247 + },
  248 + _inputRoomByOwner() {
  249 + if (this.roomCreateFeeInfo.timer) {
  250 + clearTimeout(this.roomCreateFeeInfo.timer)
  251 + }
  252 + this.roomCreateFeeInfo.timer = setTimeout(() => {
  253 + this.$refs.inputSearchRoomByOwner.$emit('searchRoom', {
  254 + callComponent: 'roomCreateFee',
  255 + ownerName: this.roomCreateFeeInfo.condition.ownerName
  256 + })
  257 + }, 1500)
  258 + },
  259 + _queryRoomCreateFeeMethod() {
  260 + this.listRoomInRoomCreateFee()
  261 + },
  262 + _resetRoomCreateFeeMethod() {
  263 + this.$refs.inputSearchRoom.$emit('close', {})
  264 + this.$refs.inputSearchRoomByOwner.$emit('close', {})
  265 + this.roomCreateFeeInfo.roomNum = ''
  266 + this.roomCreateFeeInfo.ownerName = ''
  267 + this.roomCreateFeeInfo.ownerId = ''
  268 + this.roomCreateFeeInfo.condition.ownerName = ''
  269 + this.roomCreateFeeInfo.condition.roomNum = ''
  270 + this.changeTab('simplifyRoomFee')
  271 + },
  272 + changeTab(tab) {
  273 + this.roomCreateFeeInfo._currentTab = tab
  274 + setTimeout(() => {
  275 + if (this.$refs[tab]) {
  276 + if(tab === 'ownerDetailAccount' || tab === 'ownerDetailAccountReceipt') {
  277 + this.$refs[tab].open(this.roomCreateFeeInfo.ownerId, this.roomCreateFeeInfo.ownerName, this.roomCreateFeeInfo.roomId)
  278 + return;
  279 + }
  280 + this.$refs[tab].open({
  281 + ownerId: this.roomCreateFeeInfo.ownerId,
  282 + ownerName: this.roomCreateFeeInfo.ownerName,
  283 + roomId: this.roomCreateFeeInfo.roomId,
  284 + roomName: this.roomCreateFeeInfo.roomName
  285 + })
  286 + }
  287 + }, 500)
  288 + },
  289 + _roomCreateFeetoSimplifyAcceptance() {
  290 + const date = new Date()
  291 + localStorage.setItem('JAVA110_IS_BACK', date.getTime())
  292 + localStorage.setItem(
  293 + 'simplifyAcceptanceSearch',
  294 + JSON.stringify({
  295 + searchType: '1',
  296 + searchValue: `${this.roomCreateFeeInfo.floorNum}-${this.roomCreateFeeInfo.unitNum}-${this.roomCreateFeeInfo.roomNum}`,
  297 + searchPlaceholder: '请输入房屋编号 楼栋-单元-房屋 如1-1-1'
  298 + })
  299 + )
  300 + this.$router.push('/pages/property/simplifyAcceptance?tab=业务受理')
  301 + },
  302 + _toBatchCreateFee() {
  303 + this.$router.push('/pages/fee/roomCreatePayFee')
  304 + },
  305 + _downloadCollectionLetterOrder() {
  306 + this.$router.push('/pages/fee/addOweFeeCallable?callableWay=EXCEL')
  307 + },
  308 + _downloadRoomCollectionLetterOrder(room) {
  309 + this.$refs.downloadCollectionLetterOrder.open({
  310 + roomId: room.roomId
  311 + })
  312 + },
  313 + _openFeeImportExcel() {
  314 + this.$refs.exportFeeImportExcel.open()
  315 + },
  316 + _openDoCreateRoomFee() {
  317 + this.$refs.doImportCreateFee.open()
  318 + },
  319 + _openRoomCreateFeeComboModal() {
  320 + this.$router.push(
  321 + `/pages/property/createFeeByCombo?payerObjId=${this.roomCreateFeeInfo.roomId}&payerObjName=${this.roomCreateFeeInfo.roomName}&payerObjType=3333`
  322 + )
  323 + },
  324 + }
  325 +}
  326 +</script>
  327 +
  328 +<style scoped>
  329 +.app-container {
  330 + padding: 20px;
  331 +}
  332 + .tree-container {
  333 + min-height: 450px;
  334 + overflow-y: auto;
  335 + background: #fff;
  336 + padding: 10px;
  337 + border-radius: 4px;
  338 + }
  339 +
  340 +.header-tools {
  341 + float: right;
  342 +}
  343 +
  344 +.filter-container {
  345 + margin-bottom: 20px;
  346 +}
  347 +</style>
0 \ No newline at end of file 348 \ No newline at end of file