Commit f8a053e12394a2875e202529f8095c53dcc7322c
1 parent
fc9bd1db
支持交房和退房功能
Showing
11 changed files
with
1315 additions
and
2 deletions
src/api/room/handoverApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | + | |
| 3 | +// 保存交接信息 | |
| 4 | +export function saveHandover(data) { | |
| 5 | + return new Promise((resolve, reject) => { | |
| 6 | + request({ | |
| 7 | + url: '/owner.saveHandover', | |
| 8 | + method: 'post', | |
| 9 | + data | |
| 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 queryOwners(params) { | |
| 21 | + return new Promise((resolve, reject) => { | |
| 22 | + request({ | |
| 23 | + url: '/owner.queryOwners', | |
| 24 | + method: 'get', | |
| 25 | + params | |
| 26 | + }).then(response => { | |
| 27 | + const res = response.data | |
| 28 | + resolve({ | |
| 29 | + data: res.data, | |
| 30 | + total: res.total | |
| 31 | + }) | |
| 32 | + }).catch(error => { | |
| 33 | + reject(error) | |
| 34 | + }) | |
| 35 | + }) | |
| 36 | +} | |
| 37 | + | |
| 38 | +// 查询房屋列表 | |
| 39 | +export function queryRooms(params) { | |
| 40 | + return new Promise((resolve, reject) => { | |
| 41 | + request({ | |
| 42 | + url: '/room.queryRooms', | |
| 43 | + method: 'get', | |
| 44 | + params | |
| 45 | + }).then(response => { | |
| 46 | + const res = response.data | |
| 47 | + resolve({ | |
| 48 | + data: res, | |
| 49 | + total: res.total | |
| 50 | + }) | |
| 51 | + }).catch(error => { | |
| 52 | + reject(error) | |
| 53 | + }) | |
| 54 | + }) | |
| 55 | +} | |
| 56 | + | |
| 57 | +// 查询费用配置列表 | |
| 58 | +export function listFeeConfigs(params) { | |
| 59 | + return new Promise((resolve, reject) => { | |
| 60 | + request({ | |
| 61 | + url: '/feeConfig.listFeeConfigs', | |
| 62 | + method: 'get', | |
| 63 | + params | |
| 64 | + }).then(response => { | |
| 65 | + const res = response.data | |
| 66 | + resolve({ | |
| 67 | + data: res, | |
| 68 | + total: res.total | |
| 69 | + }) | |
| 70 | + }).catch(error => { | |
| 71 | + reject(error) | |
| 72 | + }) | |
| 73 | + }) | |
| 74 | +} | |
| 0 | 75 | \ No newline at end of file | ... | ... |
src/api/room/ownerExitRoomApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | |
| 2 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 3 | + | |
| 4 | +// 业主退房 | |
| 5 | +export function ownerExitRoom(data) { | |
| 6 | + return new Promise((resolve, reject) => { | |
| 7 | + request({ | |
| 8 | + url: '/owner.ownerExitRoom', | |
| 9 | + method: 'post', | |
| 10 | + data, | |
| 11 | + headers: { | |
| 12 | + 'Content-Type': 'application/json' | |
| 13 | + } | |
| 14 | + }).then(response => { | |
| 15 | + const res = response.data | |
| 16 | + resolve(res) | |
| 17 | + }).catch(error => { | |
| 18 | + reject(error) | |
| 19 | + }) | |
| 20 | + }) | |
| 21 | +} | |
| 22 | + | |
| 23 | +// 查询业主房屋 | |
| 24 | +export function queryRoomsByOwner(params) { | |
| 25 | + return new Promise((resolve, reject) => { | |
| 26 | + const defaultParams = { | |
| 27 | + communityId: getCommunityId(), | |
| 28 | + page: 1, | |
| 29 | + row: 100 | |
| 30 | + } | |
| 31 | + request({ | |
| 32 | + url: '/room.queryRoomsByOwner', | |
| 33 | + method: 'get', | |
| 34 | + params: { ...defaultParams, ...params } | |
| 35 | + }).then(response => { | |
| 36 | + const res = response.data | |
| 37 | + resolve(res) | |
| 38 | + }).catch(error => { | |
| 39 | + reject(error) | |
| 40 | + }) | |
| 41 | + }) | |
| 42 | +} | |
| 43 | + | |
| 44 | +// 查询业主列表 | |
| 45 | +export function queryOwners(params) { | |
| 46 | + return new Promise((resolve, reject) => { | |
| 47 | + const defaultParams = { | |
| 48 | + communityId: getCommunityId(), | |
| 49 | + page: 1, | |
| 50 | + row: 10 | |
| 51 | + } | |
| 52 | + request({ | |
| 53 | + url: '/owner.queryOwners', | |
| 54 | + method: 'get', | |
| 55 | + params: { ...defaultParams, ...params } | |
| 56 | + }).then(response => { | |
| 57 | + const res = response.data | |
| 58 | + resolve(res) | |
| 59 | + }).catch(error => { | |
| 60 | + reject(error) | |
| 61 | + }) | |
| 62 | + }) | |
| 63 | +} | |
| 64 | + | |
| 65 | +// 查询费用列表 | |
| 66 | +export function listFee(params) { | |
| 67 | + return new Promise((resolve, reject) => { | |
| 68 | + const defaultParams = { | |
| 69 | + communityId: getCommunityId(), | |
| 70 | + page: 1, | |
| 71 | + row: 500 | |
| 72 | + } | |
| 73 | + request({ | |
| 74 | + url: '/fee.listFee', | |
| 75 | + method: 'get', | |
| 76 | + params: { ...defaultParams, ...params } | |
| 77 | + }).then(response => { | |
| 78 | + const res = response.data | |
| 79 | + resolve(res) | |
| 80 | + }).catch(error => { | |
| 81 | + reject(error) | |
| 82 | + }) | |
| 83 | + }) | |
| 84 | +} | |
| 85 | + | |
| 86 | +// 查询费用配置 | |
| 87 | +export function listFeeConfigs(params) { | |
| 88 | + return new Promise((resolve, reject) => { | |
| 89 | + const defaultParams = { | |
| 90 | + communityId: getCommunityId(), | |
| 91 | + page: 1, | |
| 92 | + row: 500 | |
| 93 | + } | |
| 94 | + request({ | |
| 95 | + url: '/feeConfig.listFeeConfigs', | |
| 96 | + method: 'get', | |
| 97 | + params: { ...defaultParams, ...params } | |
| 98 | + }).then(response => { | |
| 99 | + const res = response.data | |
| 100 | + resolve(res) | |
| 101 | + }).catch(error => { | |
| 102 | + reject(error) | |
| 103 | + }) | |
| 104 | + }) | |
| 105 | +} | |
| 0 | 106 | \ No newline at end of file | ... | ... |
src/components/room/searchOwner.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <el-dialog | |
| 3 | + :title="$t('searchOwner.title')" | |
| 4 | + :visible.sync="visible" | |
| 5 | + width="80%" | |
| 6 | + @close="handleClose" | |
| 7 | + > | |
| 8 | + <div class="search-container"> | |
| 9 | + <el-row :gutter="20"> | |
| 10 | + <el-col :span="8"> | |
| 11 | + <el-input | |
| 12 | + v-model="searchForm.roomName" | |
| 13 | + :placeholder="$t('searchOwner.roomPlaceholder')" | |
| 14 | + clearable | |
| 15 | + ></el-input> | |
| 16 | + </el-col> | |
| 17 | + <el-col :span="8"> | |
| 18 | + <el-input | |
| 19 | + v-model="searchForm.currentOwnerName" | |
| 20 | + :placeholder="$t('searchOwner.namePlaceholder')" | |
| 21 | + clearable | |
| 22 | + ></el-input> | |
| 23 | + </el-col> | |
| 24 | + <el-col :span="8"> | |
| 25 | + <el-button type="primary" @click="searchOwners">{{ $t('common.search') }}</el-button> | |
| 26 | + <el-button @click="resetOwners">{{ $t('common.reset') }}</el-button> | |
| 27 | + </el-col> | |
| 28 | + </el-row> | |
| 29 | + | |
| 30 | + <el-table | |
| 31 | + :data="tableData" | |
| 32 | + border | |
| 33 | + style="width: 100%; margin-top: 20px" | |
| 34 | + > | |
| 35 | + <el-table-column | |
| 36 | + prop="memberId" | |
| 37 | + :label="$t('searchOwner.memberId')" | |
| 38 | + align="center" | |
| 39 | + ></el-table-column> | |
| 40 | + <el-table-column | |
| 41 | + prop="name" | |
| 42 | + :label="$t('searchOwner.name')" | |
| 43 | + align="center" | |
| 44 | + ></el-table-column> | |
| 45 | + <el-table-column | |
| 46 | + prop="personTypeName" | |
| 47 | + :label="$t('searchOwner.personType')" | |
| 48 | + align="center" | |
| 49 | + ></el-table-column> | |
| 50 | + <el-table-column | |
| 51 | + prop="personRoleName" | |
| 52 | + :label="$t('searchOwner.personRole')" | |
| 53 | + align="center" | |
| 54 | + ></el-table-column> | |
| 55 | + <el-table-column | |
| 56 | + prop="idCard" | |
| 57 | + :label="$t('searchOwner.idCard')" | |
| 58 | + align="center" | |
| 59 | + ></el-table-column> | |
| 60 | + <el-table-column | |
| 61 | + prop="link" | |
| 62 | + :label="$t('searchOwner.contact')" | |
| 63 | + align="center" | |
| 64 | + ></el-table-column> | |
| 65 | + <el-table-column | |
| 66 | + :label="$t('common.operation')" | |
| 67 | + align="center" | |
| 68 | + width="120" | |
| 69 | + > | |
| 70 | + <template slot-scope="scope"> | |
| 71 | + <el-button | |
| 72 | + type="primary" | |
| 73 | + size="mini" | |
| 74 | + @click="chooseOwner(scope.row)" | |
| 75 | + >{{ $t('common.select') }}</el-button> | |
| 76 | + </template> | |
| 77 | + </el-table-column> | |
| 78 | + </el-table> | |
| 79 | + | |
| 80 | + <el-pagination | |
| 81 | + :current-page="pagination.current" | |
| 82 | + :page-sizes="[10, 20, 30, 50]" | |
| 83 | + :page-size="pagination.size" | |
| 84 | + layout="total, sizes, prev, pager, next, jumper" | |
| 85 | + :total="pagination.total" | |
| 86 | + @size-change="handleSizeChange" | |
| 87 | + @current-change="handleCurrentChange" | |
| 88 | + ></el-pagination> | |
| 89 | + </div> | |
| 90 | + </el-dialog> | |
| 91 | +</template> | |
| 92 | + | |
| 93 | +<script> | |
| 94 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 95 | +import { queryOwners } from '@/api/room/ownerExitRoomApi' | |
| 96 | + | |
| 97 | +export default { | |
| 98 | + name: 'SearchOwner', | |
| 99 | + data() { | |
| 100 | + return { | |
| 101 | + visible: false, | |
| 102 | + searchForm: { | |
| 103 | + roomName: '', | |
| 104 | + currentOwnerName: '', | |
| 105 | + ownerTypeCd: '1001' | |
| 106 | + }, | |
| 107 | + tableData: [], | |
| 108 | + pagination: { | |
| 109 | + current: 1, | |
| 110 | + size: 10, | |
| 111 | + total: 0 | |
| 112 | + } | |
| 113 | + } | |
| 114 | + }, | |
| 115 | + methods: { | |
| 116 | + open() { | |
| 117 | + this.visible = true | |
| 118 | + this.refreshData() | |
| 119 | + this.loadAllOwnerInfo() | |
| 120 | + }, | |
| 121 | + handleClose() { | |
| 122 | + this.resetOwners() | |
| 123 | + }, | |
| 124 | + async loadAllOwnerInfo() { | |
| 125 | + try { | |
| 126 | + const params = { | |
| 127 | + page: this.pagination.current, | |
| 128 | + row: this.pagination.size, | |
| 129 | + communityId: getCommunityId(), | |
| 130 | + name: this.searchForm.currentOwnerName.trim(), | |
| 131 | + roomName: this.searchForm.roomName.trim(), | |
| 132 | + ownerTypeCd: this.searchForm.ownerTypeCd | |
| 133 | + } | |
| 134 | + const res = await queryOwners(params) | |
| 135 | + this.tableData = res.data | |
| 136 | + this.pagination.total = res.records | |
| 137 | + } catch (error) { | |
| 138 | + console.error('获取业主列表失败:', error) | |
| 139 | + } | |
| 140 | + }, | |
| 141 | + chooseOwner(owner) { | |
| 142 | + this.$emit('chooseOwner', owner) | |
| 143 | + this.visible = false | |
| 144 | + }, | |
| 145 | + searchOwners() { | |
| 146 | + this.pagination.current = 1 | |
| 147 | + this.loadAllOwnerInfo() | |
| 148 | + }, | |
| 149 | + resetOwners() { | |
| 150 | + this.searchForm = { | |
| 151 | + roomName: '', | |
| 152 | + currentOwnerName: '', | |
| 153 | + ownerTypeCd: '1001' | |
| 154 | + } | |
| 155 | + this.loadAllOwnerInfo() | |
| 156 | + }, | |
| 157 | + refreshData() { | |
| 158 | + this.searchForm = { | |
| 159 | + roomName: '', | |
| 160 | + currentOwnerName: '', | |
| 161 | + ownerTypeCd: '1001' | |
| 162 | + } | |
| 163 | + this.pagination = { | |
| 164 | + current: 1, | |
| 165 | + size: 10, | |
| 166 | + total: 0 | |
| 167 | + } | |
| 168 | + }, | |
| 169 | + handleSizeChange(val) { | |
| 170 | + this.pagination.size = val | |
| 171 | + this.loadAllOwnerInfo() | |
| 172 | + }, | |
| 173 | + handleCurrentChange(val) { | |
| 174 | + this.pagination.current = val | |
| 175 | + this.loadAllOwnerInfo() | |
| 176 | + } | |
| 177 | + } | |
| 178 | +} | |
| 179 | +</script> | |
| 180 | + | |
| 181 | +<style lang="scss" scoped> | |
| 182 | +.search-container { | |
| 183 | + padding: 20px; | |
| 184 | + | |
| 185 | + .el-row { | |
| 186 | + margin-bottom: 20px; | |
| 187 | + } | |
| 188 | +} | |
| 189 | +</style> | |
| 0 | 190 | \ No newline at end of file | ... | ... |
src/components/room/selectFeeConfig.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <el-dialog | |
| 3 | + :title="$t('selectFeeConfig.title')" | |
| 4 | + :visible.sync="visible" | |
| 5 | + width="60%" | |
| 6 | + @close="handleClose" | |
| 7 | + > | |
| 8 | + <div class="fee-config-container"> | |
| 9 | + <el-form :model="form" label-width="120px"> | |
| 10 | + <el-form-item :label="$t('selectFeeConfig.feeType')" required> | |
| 11 | + <el-select | |
| 12 | + v-model="form.feeTypeCd" | |
| 13 | + style="width: 100%" | |
| 14 | + @change="changeFeeType" | |
| 15 | + > | |
| 16 | + <el-option | |
| 17 | + v-for="item in feeTypes" | |
| 18 | + :key="item.statusCd" | |
| 19 | + :label="item.name" | |
| 20 | + :value="item.statusCd" | |
| 21 | + :disabled="item.statusCd === '888800010008' || item.statusCd === '888800010017'" | |
| 22 | + ></el-option> | |
| 23 | + </el-select> | |
| 24 | + </el-form-item> | |
| 25 | + | |
| 26 | + <el-form-item :label="$t('selectFeeConfig.feeItem')" required> | |
| 27 | + <el-select | |
| 28 | + v-model="form.configId" | |
| 29 | + style="width: 100%" | |
| 30 | + @change="selectFeeConfig" | |
| 31 | + > | |
| 32 | + <el-option | |
| 33 | + v-for="item in feeConfigs" | |
| 34 | + :key="item.configId" | |
| 35 | + :label="item.feeName" | |
| 36 | + :value="item.configId" | |
| 37 | + ></el-option> | |
| 38 | + </el-select> | |
| 39 | + </el-form-item> | |
| 40 | + | |
| 41 | + <el-form-item | |
| 42 | + v-if="form.computingFormula === '4004'" | |
| 43 | + :label="$t('selectFeeConfig.amount')" | |
| 44 | + required | |
| 45 | + > | |
| 46 | + <el-input | |
| 47 | + v-model="form.amount" | |
| 48 | + :placeholder="$t('selectFeeConfig.amountPlaceholder')" | |
| 49 | + ></el-input> | |
| 50 | + </el-form-item> | |
| 51 | + | |
| 52 | + <el-form-item :label="$t('selectFeeConfig.startTime')" required> | |
| 53 | + <el-date-picker | |
| 54 | + v-model="form.startTime" | |
| 55 | + type="datetime" | |
| 56 | + style="width: 100%" | |
| 57 | + :placeholder="$t('selectFeeConfig.startTimePlaceholder')" | |
| 58 | + value-format="yyyy-MM-dd HH:mm:ss" | |
| 59 | + ></el-date-picker> | |
| 60 | + </el-form-item> | |
| 61 | + | |
| 62 | + <el-form-item | |
| 63 | + v-if="form.feeFlag === '2006012'" | |
| 64 | + :label="$t('selectFeeConfig.endTime')" | |
| 65 | + required | |
| 66 | + > | |
| 67 | + <el-date-picker | |
| 68 | + v-model="form.endTime" | |
| 69 | + type="datetime" | |
| 70 | + style="width: 100%" | |
| 71 | + :placeholder="$t('selectFeeConfig.endTimePlaceholder')" | |
| 72 | + value-format="yyyy-MM-dd HH:mm:ss" | |
| 73 | + ></el-date-picker> | |
| 74 | + </el-form-item> | |
| 75 | + </el-form> | |
| 76 | + | |
| 77 | + <div class="dialog-footer"> | |
| 78 | + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button> | |
| 79 | + <el-button type="primary" @click="saveFeeConfig">{{ $t('common.submit') }}</el-button> | |
| 80 | + </div> | |
| 81 | + </div> | |
| 82 | + </el-dialog> | |
| 83 | +</template> | |
| 84 | + | |
| 85 | +<script> | |
| 86 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 87 | +import { getDict } from '@/api/community/communityApi' | |
| 88 | +import { listFeeConfigs } from '@/api/room/ownerExitRoomApi' | |
| 89 | + | |
| 90 | +export default { | |
| 91 | + name: 'SelectFeeConfig', | |
| 92 | + data() { | |
| 93 | + return { | |
| 94 | + visible: false, | |
| 95 | + form: { | |
| 96 | + feeTypeCd: '', | |
| 97 | + configId: '', | |
| 98 | + configName: '', | |
| 99 | + locationTypeCdName: '', | |
| 100 | + startTime: '', | |
| 101 | + endTime: '', | |
| 102 | + computingFormula: '', | |
| 103 | + amount: '', | |
| 104 | + feeFlag: '', | |
| 105 | + call: null | |
| 106 | + }, | |
| 107 | + feeTypes: [], | |
| 108 | + feeConfigs: [] | |
| 109 | + } | |
| 110 | + }, | |
| 111 | + created() { | |
| 112 | + this.getDictData() | |
| 113 | + }, | |
| 114 | + methods: { | |
| 115 | + open(call) { | |
| 116 | + this.form.call = call | |
| 117 | + this.visible = true | |
| 118 | + }, | |
| 119 | + handleClose() { | |
| 120 | + this.clearForm() | |
| 121 | + }, | |
| 122 | + async getDictData() { | |
| 123 | + try { | |
| 124 | + const data = await getDict('pay_fee_config', 'fee_type_cd') | |
| 125 | + this.feeTypes = data.filter(item => | |
| 126 | + item.statusCd !== '888800010015' && item.statusCd !== '888800010016' | |
| 127 | + ) | |
| 128 | + } catch (error) { | |
| 129 | + console.error('获取字典数据失败:', error) | |
| 130 | + } | |
| 131 | + }, | |
| 132 | + async changeFeeType(feeTypeCd) { | |
| 133 | + this.form.configId = '' | |
| 134 | + try { | |
| 135 | + const params = { | |
| 136 | + page: 1, | |
| 137 | + row: 500, | |
| 138 | + communityId: getCommunityId(), | |
| 139 | + feeTypeCd: feeTypeCd, | |
| 140 | + isDefault: 'F', | |
| 141 | + valid: '1' | |
| 142 | + } | |
| 143 | + const res = await listFeeConfigs(params) | |
| 144 | + this.feeConfigs = res.feeConfigs | |
| 145 | + } catch (error) { | |
| 146 | + console.error('获取费用配置失败:', error) | |
| 147 | + } | |
| 148 | + }, | |
| 149 | + selectFeeConfig(configId) { | |
| 150 | + this.form.endTime = '' | |
| 151 | + const selectedConfig = this.feeConfigs.find(item => item.configId === configId) | |
| 152 | + if (selectedConfig) { | |
| 153 | + this.form.feeName = selectedConfig.feeName | |
| 154 | + this.form.feeFlag = selectedConfig.feeFlag | |
| 155 | + this.form.computingFormula = selectedConfig.computingFormula | |
| 156 | + } | |
| 157 | + }, | |
| 158 | + saveFeeConfig() { | |
| 159 | + if (!this.form.feeTypeCd) { | |
| 160 | + this.$message.error(this.$t('selectFeeConfig.validate.feeTypeRequired')) | |
| 161 | + return | |
| 162 | + } | |
| 163 | + if (!this.form.configId) { | |
| 164 | + this.$message.error(this.$t('selectFeeConfig.validate.feeItemRequired')) | |
| 165 | + return | |
| 166 | + } | |
| 167 | + if (!this.form.startTime) { | |
| 168 | + this.$message.error(this.$t('selectFeeConfig.validate.startTimeRequired')) | |
| 169 | + return | |
| 170 | + } | |
| 171 | + if (this.form.computingFormula === '4004' && !this.form.amount) { | |
| 172 | + this.$message.error(this.$t('selectFeeConfig.validate.amountRequired')) | |
| 173 | + return | |
| 174 | + } | |
| 175 | + | |
| 176 | + this.$emit('notifyFeeConfig', this.form) | |
| 177 | + this.visible = false | |
| 178 | + }, | |
| 179 | + clearForm() { | |
| 180 | + this.form = { | |
| 181 | + feeTypeCd: '', | |
| 182 | + configId: '', | |
| 183 | + configName: '', | |
| 184 | + locationTypeCdName: '', | |
| 185 | + startTime: '', | |
| 186 | + endTime: '', | |
| 187 | + computingFormula: '', | |
| 188 | + amount: '', | |
| 189 | + feeFlag: '', | |
| 190 | + call: null | |
| 191 | + } | |
| 192 | + this.feeConfigs = [] | |
| 193 | + } | |
| 194 | + } | |
| 195 | +} | |
| 196 | +</script> | |
| 197 | + | |
| 198 | +<style lang="scss" scoped> | |
| 199 | +.fee-config-container { | |
| 200 | + padding: 20px; | |
| 201 | + | |
| 202 | + .dialog-footer { | |
| 203 | + text-align: right; | |
| 204 | + margin-top: 20px; | |
| 205 | + } | |
| 206 | +} | |
| 207 | +</style> | |
| 0 | 208 | \ No newline at end of file | ... | ... |
src/i18n/communityI18n.js
| ... | ... | @@ -5,6 +5,8 @@ import { messages as listPropertyRightRegistrationDetailMessages } from '../view |
| 5 | 5 | import { messages as communityPublicityManageMessages } from '../views/community/communityPublicityManageLang' |
| 6 | 6 | import { messages as addCommunityPublicityMessages } from '../views/community/addCommunityPublicityLang' |
| 7 | 7 | import { messages as editCommunityPublicityMessages } from '../views/community/editCommunityPublicityLang' |
| 8 | +import { messages as handoverMessages } from '../views/room/handoverLang' | |
| 9 | +import { messages as ownerExitRoomMessages } from '../views/room/ownerExitRoomLang' | |
| 8 | 10 | export const messages = { |
| 9 | 11 | en: { |
| 10 | 12 | ...roomStructureMessages.en, |
| ... | ... | @@ -14,6 +16,8 @@ export const messages = { |
| 14 | 16 | ...communityPublicityManageMessages.en, |
| 15 | 17 | ...addCommunityPublicityMessages.en, |
| 16 | 18 | ...editCommunityPublicityMessages.en, |
| 19 | + ...handoverMessages.en, | |
| 20 | + ...ownerExitRoomMessages.en, | |
| 17 | 21 | }, |
| 18 | 22 | zh: { |
| 19 | 23 | ...roomStructureMessages.zh, |
| ... | ... | @@ -23,5 +27,7 @@ export const messages = { |
| 23 | 27 | ...communityPublicityManageMessages.zh, |
| 24 | 28 | ...addCommunityPublicityMessages.zh, |
| 25 | 29 | ...editCommunityPublicityMessages.zh, |
| 30 | + ...handoverMessages.zh, | |
| 31 | + ...ownerExitRoomMessages.zh, | |
| 26 | 32 | } |
| 27 | 33 | } |
| 28 | 34 | \ No newline at end of file | ... | ... |
src/router/communityRouter.js
| ... | ... | @@ -34,4 +34,14 @@ export default [ |
| 34 | 34 | name: '/views/community/editCommunityPublicity', |
| 35 | 35 | component: () => import('@/views/community/editCommunityPublicityList.vue') |
| 36 | 36 | }, |
| 37 | + { | |
| 38 | + path: '/views/room/handover', | |
| 39 | + name: '/views/room/handover', | |
| 40 | + component: () => import('@/views/room/handoverList.vue') | |
| 41 | + }, | |
| 42 | + { | |
| 43 | + path: '/views/room/ownerExitRoom', | |
| 44 | + name: '/views/room/ownerExitRoom', | |
| 45 | + component: () => import('@/views/room/ownerExitRoomList.vue') | |
| 46 | + }, | |
| 37 | 47 | ] |
| 38 | 48 | \ No newline at end of file | ... | ... |
src/views/room/handoverLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + handover: { | |
| 4 | + ownerInfo: 'Owner Information', | |
| 5 | + select: 'Select', | |
| 6 | + back: 'Back', | |
| 7 | + name: 'Name', | |
| 8 | + namePlaceholder: 'Required, please enter name', | |
| 9 | + gender: 'Gender', | |
| 10 | + genderPlaceholder: 'Required, please select gender', | |
| 11 | + male: 'Male', | |
| 12 | + female: 'Female', | |
| 13 | + age: 'Age', | |
| 14 | + agePlaceholder: 'Optional, please enter age', | |
| 15 | + idCard: 'ID Card', | |
| 16 | + idCardPlaceholder: 'Optional, please enter ID card', | |
| 17 | + phone: 'Phone', | |
| 18 | + phonePlaceholder: 'Required, please enter phone number', | |
| 19 | + remark: 'Remark', | |
| 20 | + remarkPlaceholder: 'Optional, please enter remark', | |
| 21 | + houseInfo: 'House Information', | |
| 22 | + selectHouse: 'Select House', | |
| 23 | + createFee: 'Create Fee', | |
| 24 | + house: 'House', | |
| 25 | + area: 'Area', | |
| 26 | + squareMeter: 'Square Meter', | |
| 27 | + houseStatus: 'House Status', | |
| 28 | + operation: 'Operation', | |
| 29 | + delete: 'Delete', | |
| 30 | + feeInfo: 'Fee Information', | |
| 31 | + feeItem: 'Fee Item', | |
| 32 | + startTime: 'Start Time', | |
| 33 | + endTime: 'End Time', | |
| 34 | + submit: 'Submit', | |
| 35 | + submitSuccess: 'Submit successfully', | |
| 36 | + submitError: 'Submit failed', | |
| 37 | + houseNotUnsold: 'The house is not unsold, please return it first', | |
| 38 | + fetchRoomError: 'Failed to get room information' | |
| 39 | + }, | |
| 40 | + searchOwner: { | |
| 41 | + title: 'Select Owner', | |
| 42 | + roomPlaceholder: 'Enter house number building-unit-house', | |
| 43 | + namePlaceholder: 'Enter owner name', | |
| 44 | + memberId: 'Owner ID', | |
| 45 | + name: 'Name', | |
| 46 | + personType: 'Person Type', | |
| 47 | + personRole: 'Person Role', | |
| 48 | + idCard: 'ID Card', | |
| 49 | + phone: 'Phone', | |
| 50 | + fetchError: 'Failed to get owner list' | |
| 51 | + }, | |
| 52 | + selectFeeConfig: { | |
| 53 | + title: 'Create Fee', | |
| 54 | + feeType: 'Fee Type', | |
| 55 | + feeTypePlaceholder: 'Required, please select fee type', | |
| 56 | + feeItem: 'Fee Item', | |
| 57 | + feeItemPlaceholder: 'Required, please select fee item', | |
| 58 | + amount: 'Amount', | |
| 59 | + amountPlaceholder: 'Required, please enter amount', | |
| 60 | + startTime: 'Start Time', | |
| 61 | + startTimePlaceholder: 'Required, please select start time', | |
| 62 | + endTime: 'End Time', | |
| 63 | + endTimePlaceholder: 'Required, please select end time', | |
| 64 | + feeTypeRequired: 'Fee type is required', | |
| 65 | + feeItemRequired: 'Fee item is required', | |
| 66 | + startTimeRequired: 'Start time is required', | |
| 67 | + fetchFeeTypeError: 'Failed to get fee types', | |
| 68 | + fetchFeeConfigError: 'Failed to get fee configs' | |
| 69 | + } | |
| 70 | + }, | |
| 71 | + zh: { | |
| 72 | + handover: { | |
| 73 | + ownerInfo: '业主信息', | |
| 74 | + select: '选择', | |
| 75 | + back: '返回', | |
| 76 | + name: '姓名', | |
| 77 | + namePlaceholder: '必填,请填写姓名', | |
| 78 | + gender: '性别', | |
| 79 | + genderPlaceholder: '必填,请选择性别', | |
| 80 | + male: '男', | |
| 81 | + female: '女', | |
| 82 | + age: '年龄', | |
| 83 | + agePlaceholder: '可填,请填写年龄', | |
| 84 | + idCard: '身份证', | |
| 85 | + idCardPlaceholder: '可选,请填写身份证', | |
| 86 | + phone: '手机', | |
| 87 | + phonePlaceholder: '必填,请填写联系方式', | |
| 88 | + remark: '备注', | |
| 89 | + remarkPlaceholder: '可填,请填写备注', | |
| 90 | + houseInfo: '房屋信息', | |
| 91 | + selectHouse: '选择房屋', | |
| 92 | + createFee: '创建费用', | |
| 93 | + house: '房屋', | |
| 94 | + area: '建筑面积', | |
| 95 | + squareMeter: '平方米', | |
| 96 | + houseStatus: '房屋状态', | |
| 97 | + operation: '操作', | |
| 98 | + delete: '删除', | |
| 99 | + feeInfo: '费用信息', | |
| 100 | + feeItem: '费用项目', | |
| 101 | + startTime: '开始时间', | |
| 102 | + endTime: '结束时间', | |
| 103 | + submit: '提交', | |
| 104 | + submitSuccess: '提交成功', | |
| 105 | + submitError: '提交失败', | |
| 106 | + houseNotUnsold: '房屋不是未销售状态,请先退房', | |
| 107 | + fetchRoomError: '获取房屋信息失败' | |
| 108 | + }, | |
| 109 | + searchOwner: { | |
| 110 | + title: '选择业主', | |
| 111 | + roomPlaceholder: '输入房屋编号楼栋-单元-房屋', | |
| 112 | + namePlaceholder: '输入业主名称', | |
| 113 | + memberId: '业主编号', | |
| 114 | + name: '名称', | |
| 115 | + personType: '人员类型', | |
| 116 | + personRole: '人员角色', | |
| 117 | + idCard: '证件号', | |
| 118 | + phone: '联系方式', | |
| 119 | + fetchError: '获取业主列表失败' | |
| 120 | + }, | |
| 121 | + selectFeeConfig: { | |
| 122 | + title: '创建费用', | |
| 123 | + feeType: '费用类型', | |
| 124 | + feeTypePlaceholder: '必填,请选择费用类型', | |
| 125 | + feeItem: '收费项目', | |
| 126 | + feeItemPlaceholder: '必填,请选择收费项目', | |
| 127 | + amount: '收费金额', | |
| 128 | + amountPlaceholder: '必填,请填写收费金额', | |
| 129 | + startTime: '计费起始时间', | |
| 130 | + startTimePlaceholder: '必填,请填写计费起始时间', | |
| 131 | + endTime: '计费结束时间', | |
| 132 | + endTimePlaceholder: '必填,请填写计费结束时间', | |
| 133 | + feeTypeRequired: '费用类型不能为空', | |
| 134 | + feeItemRequired: '收费项目不能为空', | |
| 135 | + startTimeRequired: '计费起始时间不能为空', | |
| 136 | + fetchFeeTypeError: '获取费用类型失败', | |
| 137 | + fetchFeeConfigError: '获取收费项目失败' | |
| 138 | + } | |
| 139 | + } | |
| 140 | +} | |
| 0 | 141 | \ No newline at end of file | ... | ... |
src/views/room/handoverList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="handover-container"> | |
| 3 | + <el-card class="box-card"> | |
| 4 | + <div slot="header" class="flex justify-between"> | |
| 5 | + <span>{{ $t('handover.ownerInfo') }}</span> | |
| 6 | + <div class="card-header-right"> | |
| 7 | + <el-button type="primary" size="small" @click="selectOwner">{{ $t('handover.select') }}</el-button> | |
| 8 | + <el-button size="small" @click="goBack">{{ $t('handover.back') }}</el-button> | |
| 9 | + </div> | |
| 10 | + </div> | |
| 11 | + <el-form> | |
| 12 | + <el-row :gutter="20"> | |
| 13 | + <el-col :span="8"> | |
| 14 | + <el-form-item :label="$t('handover.name')"> | |
| 15 | + <el-input v-model="handoverInfo.name" :placeholder="$t('handover.namePlaceholder')" clearable /> | |
| 16 | + </el-form-item> | |
| 17 | + </el-col> | |
| 18 | + <el-col :span="8"> | |
| 19 | + <el-form-item :label="$t('handover.gender')"> | |
| 20 | + <el-select v-model="handoverInfo.sex" :placeholder="$t('handover.genderPlaceholder')" style="width:100%"> | |
| 21 | + <el-option :label="$t('handover.male')" value="0" /> | |
| 22 | + <el-option :label="$t('handover.female')" value="1" /> | |
| 23 | + </el-select> | |
| 24 | + </el-form-item> | |
| 25 | + </el-col> | |
| 26 | + <el-col :span="8"> | |
| 27 | + <el-form-item :label="$t('handover.age')"> | |
| 28 | + <el-input v-model="handoverInfo.age" type="number" :placeholder="$t('handover.agePlaceholder')" | |
| 29 | + clearable /> | |
| 30 | + </el-form-item> | |
| 31 | + </el-col> | |
| 32 | + </el-row> | |
| 33 | + <el-row :gutter="20"> | |
| 34 | + <el-col :span="8"> | |
| 35 | + <el-form-item :label="$t('handover.idCard')"> | |
| 36 | + <el-input v-model="handoverInfo.idCard" :placeholder="$t('handover.idCardPlaceholder')" clearable /> | |
| 37 | + </el-form-item> | |
| 38 | + </el-col> | |
| 39 | + <el-col :span="8"> | |
| 40 | + <el-form-item :label="$t('handover.phone')"> | |
| 41 | + <el-input v-model="handoverInfo.link" type="number" :placeholder="$t('handover.phonePlaceholder')" | |
| 42 | + clearable /> | |
| 43 | + </el-form-item> | |
| 44 | + </el-col> | |
| 45 | + <el-col :span="8"> | |
| 46 | + <el-form-item :label="$t('handover.remark')"> | |
| 47 | + <el-input v-model="handoverInfo.remark" :placeholder="$t('handover.remarkPlaceholder')" clearable /> | |
| 48 | + </el-form-item> | |
| 49 | + </el-col> | |
| 50 | + </el-row> | |
| 51 | + </el-form> | |
| 52 | + </el-card> | |
| 53 | + | |
| 54 | + <el-card class="box-card" style="margin-top:20px"> | |
| 55 | + <div slot="header" class="flex justify-between"> | |
| 56 | + <span>{{ $t('handover.houseInfo') }}</span> | |
| 57 | + <div class="card-header-right"> | |
| 58 | + <el-button type="primary" size="small" @click="selectRoom">{{ $t('handover.selectHouse') }}</el-button> | |
| 59 | + <el-button size="small" @click="createFeeOrder">{{ $t('handover.createFee') }}</el-button> | |
| 60 | + </div> | |
| 61 | + </div> | |
| 62 | + <el-table :data="handoverInfo.rooms" border style="width:100%"> | |
| 63 | + <el-table-column prop="roomInfo" :label="$t('handover.house')" align="center"> | |
| 64 | + <template slot-scope="scope"> | |
| 65 | + {{ scope.row.floorNum }}-{{ scope.row.unitNum }}-{{ scope.row.roomNum }} | |
| 66 | + </template> | |
| 67 | + </el-table-column> | |
| 68 | + <el-table-column prop="builtUpArea" :label="$t('handover.area')" align="center"> | |
| 69 | + <template slot-scope="scope"> | |
| 70 | + {{ scope.row.builtUpArea }} {{ $t('handover.squareMeter') }} | |
| 71 | + </template> | |
| 72 | + </el-table-column> | |
| 73 | + <el-table-column prop="stateName" :label="$t('handover.houseStatus')" align="center" /> | |
| 74 | + <el-table-column :label="$t('handover.operation')" align="center"> | |
| 75 | + <template slot-scope="scope"> | |
| 76 | + <el-button size="mini" @click="openDelRoomModel(scope.row)"> | |
| 77 | + {{ $t('handover.delete') }} | |
| 78 | + </el-button> | |
| 79 | + </template> | |
| 80 | + </el-table-column> | |
| 81 | + </el-table> | |
| 82 | + </el-card> | |
| 83 | + | |
| 84 | + <el-card v-if="handoverInfo.fees && handoverInfo.fees.length > 0" class="box-card" style="margin-top:20px"> | |
| 85 | + <div slot="header" class="clearfix"> | |
| 86 | + <span>{{ $t('handover.feeInfo') }}</span> | |
| 87 | + </div> | |
| 88 | + <el-table :data="handoverInfo.fees" border style="width:100%"> | |
| 89 | + <el-table-column prop="feeName" :label="$t('handover.feeItem')" align="center" /> | |
| 90 | + <el-table-column prop="startTime" :label="$t('handover.startTime')" align="center" /> | |
| 91 | + <el-table-column prop="endTime" :label="$t('handover.endTime')" align="center"> | |
| 92 | + <template slot-scope="scope"> | |
| 93 | + {{ scope.row.endTime || '-' }} | |
| 94 | + </template> | |
| 95 | + </el-table-column> | |
| 96 | + <el-table-column :label="$t('handover.operation')" align="center"> | |
| 97 | + <template slot-scope="scope"> | |
| 98 | + <el-button size="mini" @click="openDelFeeModel(scope.row)"> | |
| 99 | + {{ $t('handover.delete') }} | |
| 100 | + </el-button> | |
| 101 | + </template> | |
| 102 | + </el-table-column> | |
| 103 | + </el-table> | |
| 104 | + </el-card> | |
| 105 | + | |
| 106 | + <div class="submit-btn"> | |
| 107 | + <el-button type="primary" @click="saveHandoverInfo"> | |
| 108 | + <i class="el-icon-check"></i> {{ $t('handover.submit') }} | |
| 109 | + </el-button> | |
| 110 | + </div> | |
| 111 | + | |
| 112 | + <search-owner ref="searchOwner" @chooseOwner="handleChooseOwner" /> | |
| 113 | + <select-fee-config ref="selectFeeConfig" @notifyFeeConfig="handleNotifyFeeConfig" /> | |
| 114 | + <room-tree ref="roomTree" @selectRoom="handleChooseRoom" /> | |
| 115 | + </div> | |
| 116 | +</template> | |
| 117 | + | |
| 118 | +<script> | |
| 119 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 120 | +import { saveHandover, queryRooms } from '@/api/room/handoverApi' | |
| 121 | +import SearchOwner from '@/components/owner/SearchOwner' | |
| 122 | +import SelectFeeConfig from '@/components/room/selectFeeConfig' | |
| 123 | +import RoomTree from '@/components/room/roomTree' | |
| 124 | + | |
| 125 | +export default { | |
| 126 | + name: 'HandoverList', | |
| 127 | + components: { | |
| 128 | + SearchOwner, | |
| 129 | + SelectFeeConfig, | |
| 130 | + RoomTree | |
| 131 | + }, | |
| 132 | + data() { | |
| 133 | + return { | |
| 134 | + handoverInfo: { | |
| 135 | + name: '', | |
| 136 | + age: '', | |
| 137 | + link: '', | |
| 138 | + sex: '', | |
| 139 | + remark: '', | |
| 140 | + ownerId: '', | |
| 141 | + idCard: '', | |
| 142 | + rooms: [], | |
| 143 | + fees: [], | |
| 144 | + communityId: '' | |
| 145 | + } | |
| 146 | + } | |
| 147 | + }, | |
| 148 | + created() { | |
| 149 | + this.handoverInfo.communityId = getCommunityId() | |
| 150 | + }, | |
| 151 | + methods: { | |
| 152 | + selectOwner() { | |
| 153 | + this.$refs.searchOwner.open() | |
| 154 | + }, | |
| 155 | + selectRoom() { | |
| 156 | + this.$refs.roomTree.open() | |
| 157 | + }, | |
| 158 | + createFeeOrder() { | |
| 159 | + this.$refs.selectFeeConfig.open({ | |
| 160 | + call: 'handover' | |
| 161 | + }) | |
| 162 | + }, | |
| 163 | + goBack() { | |
| 164 | + this.$router.go(-1) | |
| 165 | + }, | |
| 166 | + handleChooseOwner(owner) { | |
| 167 | + this.handoverInfo = { ...this.handoverInfo, ...owner } | |
| 168 | + }, | |
| 169 | + handleNotifyFeeConfig(fee) { | |
| 170 | + this.handoverInfo.fees.push(fee) | |
| 171 | + }, | |
| 172 | + openDelRoomModel(room) { | |
| 173 | + this.handoverInfo.rooms = this.handoverInfo.rooms.filter(item => item.roomId !== room.roomId) | |
| 174 | + }, | |
| 175 | + openDelFeeModel(fee) { | |
| 176 | + this.handoverInfo.fees = this.handoverInfo.fees.filter(item => item.configId !== fee.configId) | |
| 177 | + }, | |
| 178 | + async saveHandoverInfo() { | |
| 179 | + try { | |
| 180 | + const res = await saveHandover(this.handoverInfo) | |
| 181 | + if (res.code === 0) { | |
| 182 | + this.$message.success(this.$t('handover.submitSuccess')) | |
| 183 | + this.goBack() | |
| 184 | + } else { | |
| 185 | + this.$message.error(res.msg) | |
| 186 | + } | |
| 187 | + } catch (error) { | |
| 188 | + this.$message.error(this.$t('handover.submitError')) | |
| 189 | + } | |
| 190 | + }, | |
| 191 | + handleChooseRoom(room) { | |
| 192 | + this.listRoom(room.roomId) | |
| 193 | + }, | |
| 194 | + async listRoom(roomId) { | |
| 195 | + try { | |
| 196 | + const params = { | |
| 197 | + page: 1, | |
| 198 | + row: 1, | |
| 199 | + roomId, | |
| 200 | + communityId: this.handoverInfo.communityId | |
| 201 | + } | |
| 202 | + const { data } = await queryRooms(params) | |
| 203 | + const room = data.rooms[0] | |
| 204 | + if (room.state !== '2002') { | |
| 205 | + this.$message.error(this.$t('handover.houseNotUnsold')) | |
| 206 | + return | |
| 207 | + } | |
| 208 | + this.handoverInfo.rooms.push(room) | |
| 209 | + } catch (error) { | |
| 210 | + this.$message.error(this.$t('handover.fetchRoomError')) | |
| 211 | + } | |
| 212 | + } | |
| 213 | + } | |
| 214 | +} | |
| 215 | +</script> | |
| 216 | + | |
| 217 | +<style lang="scss" scoped> | |
| 218 | +.handover-container { | |
| 219 | + padding: 20px; | |
| 220 | + | |
| 221 | + .box-card { | |
| 222 | + margin-bottom: 20px; | |
| 223 | + } | |
| 224 | + | |
| 225 | + .card-header-right { | |
| 226 | + float: right; | |
| 227 | + } | |
| 228 | + | |
| 229 | + .submit-btn { | |
| 230 | + margin-top: 20px; | |
| 231 | + text-align: right; | |
| 232 | + } | |
| 233 | + | |
| 234 | + .el-row { | |
| 235 | + margin-bottom: 20px; | |
| 236 | + | |
| 237 | + &:last-child { | |
| 238 | + margin-bottom: 0; | |
| 239 | + } | |
| 240 | + } | |
| 241 | +} | |
| 242 | +</style> | |
| 0 | 243 | \ No newline at end of file | ... | ... |
src/views/room/ownerExitRoomLang.js
0 → 100644
| 1 | +export const messages = { | |
| 2 | + en: { | |
| 3 | + ownerExitRoom: { | |
| 4 | + ownerInfo: 'Owner Information', | |
| 5 | + name: 'Name', | |
| 6 | + idCard: 'ID Card', | |
| 7 | + phone: 'Phone', | |
| 8 | + ownerRoom: 'Owner Rooms', | |
| 9 | + room: 'Room', | |
| 10 | + builtUpArea: 'Built-up Area', | |
| 11 | + squareMeter: 'Square Meter', | |
| 12 | + feeInfo: 'Fee Information', | |
| 13 | + feeItem: 'Fee Item', | |
| 14 | + arrears: 'Arrears', | |
| 15 | + startTime: 'Start Time', | |
| 16 | + endTime: 'End Time', | |
| 17 | + feeStatus: 'Fee Status', | |
| 18 | + validate: { | |
| 19 | + ownerRequired: 'Owner is required', | |
| 20 | + roomRequired: 'Please select at least one room', | |
| 21 | + unpaidFee: 'There are unpaid fees, please handle them first' | |
| 22 | + } | |
| 23 | + }, | |
| 24 | + searchOwner: { | |
| 25 | + title: 'Select Owner', | |
| 26 | + roomPlaceholder: 'Enter room number (Building-Unit-Room)', | |
| 27 | + namePlaceholder: 'Enter owner name', | |
| 28 | + memberId: 'Owner ID', | |
| 29 | + name: 'Name', | |
| 30 | + personType: 'Person Type', | |
| 31 | + personRole: 'Person Role', | |
| 32 | + idCard: 'ID Card', | |
| 33 | + contact: 'Contact' | |
| 34 | + }, | |
| 35 | + selectFeeConfig: { | |
| 36 | + title: 'Create Fee', | |
| 37 | + feeType: 'Fee Type', | |
| 38 | + feeItem: 'Fee Item', | |
| 39 | + amount: 'Amount', | |
| 40 | + startTime: 'Start Time', | |
| 41 | + endTime: 'End Time', | |
| 42 | + amountPlaceholder: 'Required, please enter amount', | |
| 43 | + startTimePlaceholder: 'Required, please enter start time', | |
| 44 | + endTimePlaceholder: 'Required, please enter end time', | |
| 45 | + validate: { | |
| 46 | + feeTypeRequired: 'Fee type is required', | |
| 47 | + feeItemRequired: 'Fee item is required', | |
| 48 | + startTimeRequired: 'Start time is required', | |
| 49 | + amountRequired: 'Amount is required' | |
| 50 | + } | |
| 51 | + } | |
| 52 | + }, | |
| 53 | + zh: { | |
| 54 | + ownerExitRoom: { | |
| 55 | + ownerInfo: '业主信息', | |
| 56 | + name: '姓名', | |
| 57 | + idCard: '身份证', | |
| 58 | + phone: '手机', | |
| 59 | + ownerRoom: '业主房屋', | |
| 60 | + room: '房屋', | |
| 61 | + builtUpArea: '建筑面积', | |
| 62 | + squareMeter: '平方米', | |
| 63 | + feeInfo: '费用信息', | |
| 64 | + feeItem: '费用项目', | |
| 65 | + arrears: '欠费', | |
| 66 | + startTime: '开始时间', | |
| 67 | + endTime: '结束时间', | |
| 68 | + feeStatus: '费用状态', | |
| 69 | + validate: { | |
| 70 | + ownerRequired: '业主不能为空', | |
| 71 | + roomRequired: '请至少选择一间房屋', | |
| 72 | + unpaidFee: '房屋还存在费用,请先在业务受理处理费用' | |
| 73 | + } | |
| 74 | + }, | |
| 75 | + searchOwner: { | |
| 76 | + title: '选择业主', | |
| 77 | + roomPlaceholder: '输入房屋编号(楼栋-单元-房屋)', | |
| 78 | + namePlaceholder: '输入业主名称', | |
| 79 | + memberId: '业主编号', | |
| 80 | + name: '名称', | |
| 81 | + personType: '人员类型', | |
| 82 | + personRole: '人员角色', | |
| 83 | + idCard: '证件号', | |
| 84 | + contact: '联系方式' | |
| 85 | + }, | |
| 86 | + selectFeeConfig: { | |
| 87 | + title: '创建费用', | |
| 88 | + feeType: '费用类型', | |
| 89 | + feeItem: '收费项目', | |
| 90 | + amount: '收费金额', | |
| 91 | + startTime: '计费起始时间', | |
| 92 | + endTime: '计费结束时间', | |
| 93 | + amountPlaceholder: '必填,请填写收费金额', | |
| 94 | + startTimePlaceholder: '必填,请填写计费起始时间', | |
| 95 | + endTimePlaceholder: '必填,请填写计费结束时间', | |
| 96 | + validate: { | |
| 97 | + feeTypeRequired: '费用类型不能为空', | |
| 98 | + feeItemRequired: '费用项目不能为空', | |
| 99 | + startTimeRequired: '计费起始时间不能为空', | |
| 100 | + amountRequired: '收费金额不能为空' | |
| 101 | + } | |
| 102 | + } | |
| 103 | + } | |
| 104 | +} | |
| 0 | 105 | \ No newline at end of file | ... | ... |
src/views/room/ownerExitRoomList.vue
0 → 100644
| 1 | +<template> | |
| 2 | + <div class="owner-exit-room-container"> | |
| 3 | + <!-- 业主信息 --> | |
| 4 | + <el-card class="box-card"> | |
| 5 | + <div slot="header" class="flex justify-between"> | |
| 6 | + <span>{{ $t('ownerExitRoom.ownerInfo') }}</span> | |
| 7 | + <div class="card-header-actions"> | |
| 8 | + <el-button type="primary" size="small" @click="selectOwner">{{ $t('common.select') }}</el-button> | |
| 9 | + <el-button size="small" @click="goBack">{{ $t('common.back') }}</el-button> | |
| 10 | + </div> | |
| 11 | + </div> | |
| 12 | + <el-row :gutter="20" class="text-left"> | |
| 13 | + <el-col :span="8"> | |
| 14 | + <div class="info-item"> | |
| 15 | + <label>{{ $t('ownerExitRoom.name') }}:</label> | |
| 16 | + <span>{{ ownerExitRoomInfo.name }}</span> | |
| 17 | + </div> | |
| 18 | + </el-col> | |
| 19 | + <el-col :span="8"> | |
| 20 | + <div class="info-item"> | |
| 21 | + <label>{{ $t('ownerExitRoom.idCard') }}:</label> | |
| 22 | + <span>{{ ownerExitRoomInfo.idCard }}</span> | |
| 23 | + </div> | |
| 24 | + </el-col> | |
| 25 | + <el-col :span="8"> | |
| 26 | + <div class="info-item"> | |
| 27 | + <label>{{ $t('ownerExitRoom.phone') }}:</label> | |
| 28 | + <span>{{ ownerExitRoomInfo.link }}</span> | |
| 29 | + </div> | |
| 30 | + </el-col> | |
| 31 | + </el-row> | |
| 32 | + </el-card> | |
| 33 | + | |
| 34 | + <!-- 业主房屋 --> | |
| 35 | + <el-card class="box-card"> | |
| 36 | + <div slot="header" class="clearfix"> | |
| 37 | + <span>{{ $t('ownerExitRoom.ownerRoom') }}</span> | |
| 38 | + </div> | |
| 39 | + <el-table :data="ownerExitRoomInfo.rooms" border style="width: 100%" @selection-change="handleSelectionChange"> | |
| 40 | + <el-table-column type="selection" width="55" align="center"></el-table-column> | |
| 41 | + <el-table-column prop="roomName" :label="$t('ownerExitRoom.room')" align="center"> | |
| 42 | + <template slot-scope="scope"> | |
| 43 | + {{ scope.row.floorNum }}-{{ scope.row.unitNum }}-{{ scope.row.roomNum }} | |
| 44 | + </template> | |
| 45 | + </el-table-column> | |
| 46 | + <el-table-column prop="builtUpArea" :label="$t('ownerExitRoom.builtUpArea')" align="center"> | |
| 47 | + <template slot-scope="scope"> | |
| 48 | + {{ scope.row.builtUpArea }} {{ $t('ownerExitRoom.squareMeter') }} | |
| 49 | + </template> | |
| 50 | + </el-table-column> | |
| 51 | + </el-table> | |
| 52 | + </el-card> | |
| 53 | + | |
| 54 | + <!-- 费用信息 --> | |
| 55 | + <el-card v-if="ownerExitRoomInfo.fees && ownerExitRoomInfo.fees.length > 0" class="box-card"> | |
| 56 | + <div slot="header" class="clearfix"> | |
| 57 | + <span>{{ $t('ownerExitRoom.feeInfo') }}</span> | |
| 58 | + </div> | |
| 59 | + <el-table :data="ownerExitRoomInfo.fees" border style="width: 100%"> | |
| 60 | + <el-table-column prop="feeName" :label="$t('ownerExitRoom.feeItem')" align="center"></el-table-column> | |
| 61 | + <el-table-column prop="payerObjName" :label="$t('ownerExitRoom.room')" align="center"></el-table-column> | |
| 62 | + <el-table-column prop="amountOwed" :label="$t('ownerExitRoom.arrears')" align="center"></el-table-column> | |
| 63 | + <el-table-column prop="endTime" :label="$t('ownerExitRoom.startTime')" align="center"></el-table-column> | |
| 64 | + <el-table-column prop="deadlineTime" :label="$t('ownerExitRoom.endTime')" align="center"> | |
| 65 | + <template slot-scope="scope"> | |
| 66 | + {{ scope.row.deadlineTime || '-' }} | |
| 67 | + </template> | |
| 68 | + </el-table-column> | |
| 69 | + <el-table-column prop="stateName" :label="$t('ownerExitRoom.feeStatus')" align="center"></el-table-column> | |
| 70 | + </el-table> | |
| 71 | + </el-card> | |
| 72 | + | |
| 73 | + <!-- 提交按钮 --> | |
| 74 | + <div class="submit-btn"> | |
| 75 | + <el-button type="primary" @click="saveOwnerExitRoomInfo"> | |
| 76 | + <i class="el-icon-check"></i> {{ $t('common.submit') }} | |
| 77 | + </el-button> | |
| 78 | + </div> | |
| 79 | + | |
| 80 | + <!-- 子组件 --> | |
| 81 | + <search-owner ref="searchOwner" @chooseOwner="handleChooseOwner"></search-owner> | |
| 82 | + <select-fee-config ref="selectFeeConfig"></select-fee-config> | |
| 83 | + </div> | |
| 84 | +</template> | |
| 85 | + | |
| 86 | +<script> | |
| 87 | +import { getCommunityId } from '@/api/community/communityApi' | |
| 88 | +import { ownerExitRoom, queryRoomsByOwner, listFee } from '@/api/room/ownerExitRoomApi' | |
| 89 | +import SearchOwner from '@/components/owner/SearchOwner' | |
| 90 | +import SelectFeeConfig from '@/components/room/selectFeeConfig' | |
| 91 | + | |
| 92 | +export default { | |
| 93 | + name: 'OwnerExitRoomList', | |
| 94 | + components: { | |
| 95 | + SearchOwner, | |
| 96 | + SelectFeeConfig | |
| 97 | + }, | |
| 98 | + data() { | |
| 99 | + return { | |
| 100 | + ownerExitRoomInfo: { | |
| 101 | + name: '', | |
| 102 | + link: '', | |
| 103 | + ownerId: '', | |
| 104 | + idCard: '', | |
| 105 | + rooms: [], | |
| 106 | + selectRooms: [], | |
| 107 | + batchFees: [], | |
| 108 | + fees: [], | |
| 109 | + communityId: '' | |
| 110 | + } | |
| 111 | + } | |
| 112 | + }, | |
| 113 | + created() { | |
| 114 | + this.ownerExitRoomInfo.communityId = getCommunityId() | |
| 115 | + }, | |
| 116 | + methods: { | |
| 117 | + selectOwner() { | |
| 118 | + this.$refs.searchOwner.open() | |
| 119 | + }, | |
| 120 | + goBack() { | |
| 121 | + this.$router.go(-1) | |
| 122 | + }, | |
| 123 | + handleChooseOwner(owner) { | |
| 124 | + this.ownerExitRoomInfo = { | |
| 125 | + ...this.ownerExitRoomInfo, | |
| 126 | + name: owner.name, | |
| 127 | + link: owner.link, | |
| 128 | + ownerId: owner.ownerId, | |
| 129 | + idCard: owner.idCard | |
| 130 | + } | |
| 131 | + this.listRoom() | |
| 132 | + }, | |
| 133 | + handleSelectionChange(val) { | |
| 134 | + this.ownerExitRoomInfo.selectRooms = val.map(item => item.roomId) | |
| 135 | + this.dealFees() | |
| 136 | + }, | |
| 137 | + async saveOwnerExitRoomInfo() { | |
| 138 | + if (!this.ownerExitRoomInfo.ownerId) { | |
| 139 | + this.$message.error(this.$t('ownerExitRoom.validate.ownerRequired')) | |
| 140 | + return | |
| 141 | + } | |
| 142 | + | |
| 143 | + if (!this.ownerExitRoomInfo.selectRooms || this.ownerExitRoomInfo.selectRooms.length < 1) { | |
| 144 | + this.$message.error(this.$t('ownerExitRoom.validate.roomRequired')) | |
| 145 | + return | |
| 146 | + } | |
| 147 | + | |
| 148 | + const hasUnpaidFee = this.ownerExitRoomInfo.fees.some(fee => fee.state === '2008001') | |
| 149 | + if (hasUnpaidFee) { | |
| 150 | + this.$message.error(this.$t('ownerExitRoom.validate.unpaidFee')) | |
| 151 | + return | |
| 152 | + } | |
| 153 | + | |
| 154 | + try { | |
| 155 | + const res = await ownerExitRoom(this.ownerExitRoomInfo) | |
| 156 | + if (res.code === 0) { | |
| 157 | + this.$message.success(this.$t('common.submitSuccess')) | |
| 158 | + this.goBack() | |
| 159 | + } else { | |
| 160 | + this.$message.error(res.msg) | |
| 161 | + } | |
| 162 | + } catch (error) { | |
| 163 | + this.$message.error(this.$t('common.submitFailed')) | |
| 164 | + } | |
| 165 | + }, | |
| 166 | + async listRoom() { | |
| 167 | + try { | |
| 168 | + const params = { | |
| 169 | + ownerId: this.ownerExitRoomInfo.ownerId, | |
| 170 | + communityId: this.ownerExitRoomInfo.communityId, | |
| 171 | + page: 1, | |
| 172 | + row: 100 | |
| 173 | + } | |
| 174 | + const res = await queryRoomsByOwner(params) | |
| 175 | + this.ownerExitRoomInfo.rooms = res.rooms | |
| 176 | + this.ownerExitRoomInfo.selectRooms = res.rooms.map(room => room.roomId) | |
| 177 | + this.loadBatchFees() | |
| 178 | + } catch (error) { | |
| 179 | + console.error('获取房屋列表失败:', error) | |
| 180 | + } | |
| 181 | + }, | |
| 182 | + async loadBatchFees() { | |
| 183 | + try { | |
| 184 | + const params = { | |
| 185 | + communityId: this.ownerExitRoomInfo.communityId, | |
| 186 | + ownerId: this.ownerExitRoomInfo.ownerId, | |
| 187 | + payerObjType: '3333', | |
| 188 | + state: '2008001', | |
| 189 | + page: 1, | |
| 190 | + row: 500 | |
| 191 | + } | |
| 192 | + const res = await listFee(params) | |
| 193 | + this.ownerExitRoomInfo.batchFees = res.fees || [] | |
| 194 | + this.dealFees() | |
| 195 | + } catch (error) { | |
| 196 | + console.error('获取费用列表失败:', error) | |
| 197 | + } | |
| 198 | + }, | |
| 199 | + dealFees() { | |
| 200 | + const selectedRoomIds = this.ownerExitRoomInfo.selectRooms | |
| 201 | + this.ownerExitRoomInfo.fees = this.ownerExitRoomInfo.batchFees.filter(fee => | |
| 202 | + selectedRoomIds.includes(fee.payerObjId) | |
| 203 | + ) | |
| 204 | + } | |
| 205 | + } | |
| 206 | +} | |
| 207 | +</script> | |
| 208 | + | |
| 209 | +<style lang="scss" scoped> | |
| 210 | +.owner-exit-room-container { | |
| 211 | + padding: 20px; | |
| 212 | + | |
| 213 | + .box-card { | |
| 214 | + margin-bottom: 20px; | |
| 215 | + } | |
| 216 | + | |
| 217 | + .clearfix { | |
| 218 | + display: flex; | |
| 219 | + justify-content: space-between; | |
| 220 | + align-items: center; | |
| 221 | + } | |
| 222 | + | |
| 223 | + .info-item { | |
| 224 | + margin-bottom: 10px; | |
| 225 | + | |
| 226 | + label { | |
| 227 | + margin-right: 10px; | |
| 228 | + } | |
| 229 | + } | |
| 230 | + | |
| 231 | + .submit-btn { | |
| 232 | + margin-top: 20px; | |
| 233 | + text-align: right; | |
| 234 | + } | |
| 235 | +} | |
| 236 | +</style> | |
| 0 | 237 | \ No newline at end of file | ... | ... |
src/views/simplify/simplifyAcceptanceList.vue
| ... | ... | @@ -577,10 +577,10 @@ export default { |
| 577 | 577 | this.$refs.roomTree.open() |
| 578 | 578 | }, |
| 579 | 579 | _handover() { |
| 580 | - this.$router.push('/pages/property/handover') | |
| 580 | + this.$router.push('/views/room/handover') | |
| 581 | 581 | }, |
| 582 | 582 | _simplifyOwnerExitRoom() { |
| 583 | - this.$router.push('/pages/property/ownerExitRoom') | |
| 583 | + this.$router.push('/views/room/ownerExitRoom') | |
| 584 | 584 | }, |
| 585 | 585 | _simplifyInputOwner() { |
| 586 | 586 | if (this.simplifyAcceptanceInfo.searchType != "2" && | ... | ... |