Commit 84aec3bc3019434c0316ca9ef95727dc1340fb08

Authored by wuxw
1 parent 737b703c

彻底开发完成 房屋管理页面

src/api/owner/deleteOwnerRoomApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 查询业主信息
  5 +export function queryOwners(params) {
  6 + return new Promise((resolve, reject) => {
  7 + // 确保包含社区ID
  8 + if (!params.communityId) {
  9 + params.communityId = getCommunityId()
  10 + }
  11 +
  12 + request({
  13 + url: '/owner.queryOwners',
  14 + method: 'get',
  15 + params
  16 + }).then(response => {
  17 + const res = response.data
  18 + if (res.code === 0) {
  19 + resolve({
  20 + data: res.data,
  21 + total: res.records
  22 + })
  23 + } else {
  24 + reject(new Error(res.msg || '查询业主信息失败'))
  25 + }
  26 + }).catch(error => {
  27 + reject(error)
  28 + })
  29 + })
  30 +}
  31 +
  32 +// 删除业主房屋
  33 +export function deleteOwnerRoom(data) {
  34 + return new Promise((resolve, reject) => {
  35 + // 确保包含社区ID
  36 + if (!data.communityId) {
  37 + data.communityId = getCommunityId()
  38 + }
  39 +
  40 + request({
  41 + url: '/owner.deleteOwnerRoom',
  42 + method: 'post',
  43 + data
  44 + }).then(response => {
  45 + const res = response.data
  46 + if (res.code === 0) {
  47 + resolve(res)
  48 + } else {
  49 + reject(new Error(res.msg || '删除业主房屋失败'))
  50 + }
  51 + }).catch(error => {
  52 + reject(error)
  53 + })
  54 + })
  55 +}
0 56 \ No newline at end of file
... ...
src/api/owner/roomBindOwnerApi.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 + }).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 + if (res.code === 0) {
  29 + resolve(res)
  30 + } else {
  31 + reject(new Error(res.msg || '获取业主列表失败'))
  32 + }
  33 + }).catch(error => {
  34 + reject(error)
  35 + })
  36 + })
  37 +}
  38 +
  39 +// 房屋交房
  40 +export function sellRoom(data) {
  41 + return new Promise((resolve, reject) => {
  42 + request({
  43 + url: '/room.sellRoom',
  44 + method: 'post',
  45 + data
  46 + }).then(response => {
  47 + const res = response.data
  48 + if (res.code === 0) {
  49 + resolve(res)
  50 + } else {
  51 + reject(new Error(res.msg || '房屋交房失败'))
  52 + }
  53 + }).catch(error => {
  54 + reject(error)
  55 + })
  56 + })
  57 +}
0 58 \ No newline at end of file
... ...
src/api/owner/showOwnerRoomApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 查询业主房间信息
  4 +export function queryRoomsByOwner(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/room.queryRoomsByOwner',
  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 exitRoom(data) {
  21 + return new Promise((resolve, reject) => {
  22 + request({
  23 + url: '/room.exitRoom',
  24 + method: 'post',
  25 + data
  26 + }).then(response => {
  27 + const res = response.data
  28 + if (res.code === 0) {
  29 + resolve(res)
  30 + } else {
  31 + reject(new Error(res.msg || '退房操作失败'))
  32 + }
  33 + }).catch(error => {
  34 + reject(error)
  35 + })
  36 + })
  37 +}
0 38 \ No newline at end of file
... ...
src/api/room/importOwnerRoomApi.js
... ... @@ -3,7 +3,7 @@ import request from '@/utils/request'
3 3 export function importOwnerRoom(formData) {
4 4 return new Promise((resolve, reject) => {
5 5 request({
6   - url: '/assetImport/importData',
  6 + url: '/callComponent/upload/assetImport/importData',
7 7 method: 'post',
8 8 data: formData,
9 9 headers: {
... ...
src/components/owner/ownerExitRoom.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('ownerExitRoom.confirmOperation')"
  4 + :visible.sync="visible"
  5 + width="500px"
  6 + center
  7 + @close="close"
  8 + >
  9 + <div class="modal-body">
  10 + <div class="text-center">
  11 + <p>{{ $t('ownerExitRoom.confirmExit') }}</p>
  12 + <p>{{ $t('ownerExitRoom.confirmExitTip') }}</p>
  13 + </div>
  14 + </div>
  15 + <div slot="footer" class="dialog-footer">
  16 + <el-button @click="close">{{ $t('ownerExitRoom.cancel') }}</el-button>
  17 + <el-button type="primary" @click="doOwnerExitRoom">{{ $t('ownerExitRoom.confirmExitBtn') }}</el-button>
  18 + </div>
  19 + </el-dialog>
  20 + </template>
  21 +
  22 + <script>
  23 + import { exitRoom } from '@/api/owner/showOwnerRoomApi'
  24 + import { getCommunityId } from '@/api/community/communityApi'
  25 +
  26 + export default {
  27 + name: 'OwnerExitRoom',
  28 + data() {
  29 + return {
  30 + visible: false,
  31 + roomInfo: {}
  32 + }
  33 + },
  34 + methods: {
  35 + open(roomInfo) {
  36 + this.roomInfo = roomInfo
  37 + this.visible = true
  38 + },
  39 + close() {
  40 + this.visible = false
  41 + this.roomInfo = {}
  42 + },
  43 + async doOwnerExitRoom() {
  44 + try {
  45 + const params = {
  46 + ...this.roomInfo,
  47 + communityId: getCommunityId()
  48 + }
  49 +
  50 + const res = await exitRoom(params)
  51 + if (res.code === 0) {
  52 + this.$emit('exit-success')
  53 + this.close()
  54 + this.$message.success('退房成功')
  55 + } else {
  56 + this.$message.error(res.msg || '退房失败')
  57 + }
  58 + } catch (error) {
  59 + this.$message.error('请求失败')
  60 + }
  61 + }
  62 + }
  63 + }
  64 + </script>
  65 +
  66 + <style scoped>
  67 + .modal-body {
  68 + padding: 20px;
  69 + text-align: center;
  70 + }
  71 + .text-center {
  72 + text-align: center;
  73 + }
  74 + .dialog-footer {
  75 + text-align: center;
  76 + }
  77 + </style>
0 78 \ No newline at end of file
... ...
src/components/owner/showOwnerRoom.vue 0 → 100644
  1 +<template>
  2 + <div class="show-owner-room-container">
  3 + <el-row v-for="(roomInfo, index) in showOwnerRoomInfo.rooms" :key="index" class="room-row">
  4 + <el-col :span="24">
  5 + <el-card class="room-card">
  6 + <div slot="header" class=" flex justify-between">
  7 + <span>{{ $t('showOwnerRoom.info') }}</span>
  8 + <div class="card-tools">
  9 + <el-button v-if="showOwnerRoomInfo.deleteOwnerRoomFlag == false" type="primary" size="small"
  10 + icon="el-icon-plus" @click="showPropertyFee(roomInfo)">
  11 + {{ $t('showOwnerRoom.propertyFee') }}
  12 + </el-button>
  13 + <el-button v-if="showOwnerRoomInfo.deleteOwnerRoomFlag == true" type="danger" size="small"
  14 + icon="el-icon-close" @click="ownerExitRoomModel(roomInfo)">
  15 + {{ $t('showOwnerRoom.exitRoom') }}
  16 + </el-button>
  17 + </div>
  18 + </div>
  19 + <div class="card-content">
  20 + <el-row :gutter="20" class="text-left">
  21 + <el-col v-if="roomInfo.roomType === '2020602'" :span="8">
  22 + <div class="form-item">
  23 + <label>{{ $t('showOwnerRoom.shopNum') }}:</label>
  24 + <span>{{ roomInfo.floorNum }}-{{ roomInfo.roomNum }}</span>
  25 + </div>
  26 + </el-col>
  27 + <el-col v-else :span="8">
  28 + <div class="form-item">
  29 + <label>{{ $t('showOwnerRoom.roomNum') }}:</label>
  30 + <span>{{ roomInfo.floorNum }}-{{ roomInfo.unitNum }}-{{ roomInfo.roomNum }}</span>
  31 + </div>
  32 + </el-col>
  33 +
  34 + <el-col :span="8">
  35 + <div class="form-item">
  36 + <label>{{ $t('showOwnerRoom.floor') }}:</label>
  37 + <span>{{ roomInfo.layer }}{{ $t('showOwnerRoom.layer') }}</span>
  38 + </div>
  39 + </el-col>
  40 +
  41 + <el-col v-if="roomInfo.roomType === '2020602'" :span="8">
  42 + <div class="form-item">
  43 + <label>{{ $t('showOwnerRoom.shopId') }}:</label>
  44 + <span>{{ roomInfo.roomId }}</span>
  45 + </div>
  46 + </el-col>
  47 + <el-col v-else :span="8">
  48 + <div class="form-item">
  49 + <label>{{ $t('showOwnerRoom.roomId') }}:</label>
  50 + <span>{{ roomInfo.roomId }}</span>
  51 + </div>
  52 + </el-col>
  53 + </el-row>
  54 +
  55 + <el-row :gutter="20" class="text-left">
  56 + <el-col :span="8">
  57 + <div class="form-item">
  58 + <label>{{ $t('showOwnerRoom.builtUpArea') }}:</label>
  59 + <span>{{ roomInfo.builtUpArea }}{{ $t('showOwnerRoom.squareMeters') }}</span>
  60 + </div>
  61 + </el-col>
  62 +
  63 + <el-col v-if="roomInfo.roomType === '1010301'" :span="8">
  64 + <div class="form-item">
  65 + <label>{{ $t('showOwnerRoom.apartmentLayout') }}:</label>
  66 + <span>{{ roomInfo.apartment }}</span>
  67 + </div>
  68 + </el-col>
  69 +
  70 + <el-col v-if="roomInfo.roomType === '1010301'" :span="8">
  71 + <div class="form-item">
  72 + <label>{{ $t('showOwnerRoom.roomCount') }}:</label>
  73 + <span>{{ roomInfo.section }}</span>
  74 + </div>
  75 + </el-col>
  76 + </el-row>
  77 +
  78 + <div v-for="(item, attrIndex) in roomInfo.roomAttrDto" :key="attrIndex">
  79 + <el-row v-if="attrIndex % 3 === 0" :gutter="20">
  80 + <el-col :span="8">
  81 + <div class="form-item">
  82 + <label>{{ item.specName }}:</label>
  83 + <span>{{ item.valueName }}</span>
  84 + </div>
  85 + </el-col>
  86 +
  87 + <el-col v-if="attrIndex < roomInfo.roomAttrDto.length - 1" :span="8">
  88 + <div class="form-item">
  89 + <label>{{ roomInfo.roomAttrDto[attrIndex + 1].specName }}:</label>
  90 + <span>{{ roomInfo.roomAttrDto[attrIndex + 1].valueName }}</span>
  91 + </div>
  92 + </el-col>
  93 +
  94 + <el-col v-if="attrIndex < roomInfo.roomAttrDto.length - 2" :span="8">
  95 + <div class="form-item">
  96 + <label>{{ roomInfo.roomAttrDto[attrIndex + 2].specName }}:</label>
  97 + <span>{{ roomInfo.roomAttrDto[attrIndex + 2].valueName }}</span>
  98 + </div>
  99 + </el-col>
  100 + </el-row>
  101 + </div>
  102 + </div>
  103 + </el-card>
  104 + </el-col>
  105 + </el-row>
  106 +
  107 + <owner-exit-room ref="exitRoomDialog" @exit-success="handleExitSuccess" />
  108 + </div>
  109 +</template>
  110 +
  111 +<script>
  112 +import { queryRoomsByOwner } from '@/api/owner/showOwnerRoomApi'
  113 +import OwnerExitRoom from '@/components/owner/ownerExitRoom'
  114 +import { getCommunityId } from '@/api/community/communityApi'
  115 +
  116 +export default {
  117 + name: 'ShowOwnerRoomList',
  118 + components: {
  119 + OwnerExitRoom
  120 + },
  121 + props: {
  122 + deleteOwnerRoomFlag: {
  123 + type: String,
  124 + default: 'false'
  125 + },
  126 + ownerId: {
  127 + type: String,
  128 + required: true
  129 + },
  130 + ownerName: {
  131 + type: String,
  132 + required: true
  133 + }
  134 + },
  135 + data() {
  136 + return {
  137 + showOwnerRoomInfo: {
  138 + ownerId: '',
  139 + ownerName: '',
  140 + rooms: [],
  141 + deleteOwnerRoomFlag: this.deleteOwnerRoomFlag
  142 + }
  143 + }
  144 + },
  145 + watch: {
  146 + ownerId(newVal) {
  147 + if (newVal) {
  148 + this.showOwnerRoomInfo.ownerId = newVal
  149 + this.loadRooms()
  150 + }
  151 + }
  152 + },
  153 + mounted() {
  154 + this.showOwnerRoomInfo.ownerId = this.ownerId
  155 + this.showOwnerRoomInfo.ownerName = this.ownerName
  156 + this.loadRooms()
  157 + },
  158 + methods: {
  159 + async loadRooms() {
  160 + try {
  161 + const params = {
  162 + communityId: getCommunityId(),
  163 + ownerId: this.showOwnerRoomInfo.ownerId
  164 + }
  165 +
  166 + const res = await queryRoomsByOwner(params)
  167 + this.showOwnerRoomInfo.rooms = res.rooms || []
  168 +
  169 + } catch (error) {
  170 + this.$message.error('请求失败')
  171 + }
  172 + },
  173 +
  174 + ownerExitRoomModel(roomInfo) {
  175 + this.$refs.exitRoomDialog.open({
  176 + ownerId: this.showOwnerRoomInfo.ownerId,
  177 + roomId: roomInfo.roomId
  178 + })
  179 + },
  180 +
  181 + showPropertyFee(room) {
  182 + const queryParams = {
  183 + ...room,
  184 + ownerName: this.showOwnerRoomInfo.ownerName
  185 + }
  186 + this.$router.push({
  187 + path: '/property/listRoomFee',
  188 + query: queryParams
  189 + })
  190 + },
  191 +
  192 + handleExitSuccess() {
  193 + this.loadRooms()
  194 + this.$emit('room-exited')
  195 + },
  196 +
  197 + showState(state) {
  198 + const stateMap = {
  199 + '2001': this.$t('showOwnerRoom.sold'),
  200 + '2002': this.$t('showOwnerRoom.unsold'),
  201 + '2003': this.$t('showOwnerRoom.depositPaid'),
  202 + '2004': this.$t('showOwnerRoom.rented'),
  203 + default: this.$t('showOwnerRoom.unknown')
  204 + }
  205 + return stateMap[state] || stateMap.default
  206 + }
  207 + }
  208 +}
  209 +</script>
  210 +
  211 +<style scoped>
  212 +.show-owner-room-container {}
  213 +
  214 +.room-row {
  215 + margin-bottom: 20px;
  216 +}
  217 +
  218 +.room-card {
  219 + margin-bottom: 20px;
  220 +}
  221 +
  222 +.card-tools {
  223 + position: absolute;
  224 + right: 20px;
  225 + top: 15px;
  226 +}
  227 +
  228 +.clearfix:before,
  229 +.clearfix:after {
  230 + display: table;
  231 + content: "";
  232 +}
  233 +
  234 +.clearfix:after {
  235 + clear: both;
  236 +}
  237 +
  238 +.card-content {
  239 + padding: 20px;
  240 +}
  241 +
  242 +.form-item {
  243 + margin-bottom: 15px;
  244 + line-height: 36px;
  245 + color: #606266;
  246 +}
  247 +
  248 +.form-item label {
  249 + font-weight: bold;
  250 + margin-right: 5px;
  251 +}
  252 +
  253 +.form-item span {
  254 + display: inline-block;
  255 +}
  256 +</style>
0 257 \ No newline at end of file
... ...
src/components/owner/viewOwnerInfo.vue 0 → 100644
  1 +<template>
  2 + <el-card class="box-card">
  3 + <div slot="header" class="flex justify-between">
  4 + <span>{{ $t('viewOwnerInfo.title') }}</span>
  5 + <div class="card-header-buttons">
  6 + <el-button v-if="showCallBackButton" type="primary" size="small" @click="handleCallBack">
  7 + <i class="el-icon-close"></i>
  8 + {{ $t('common.back') }}
  9 + </el-button>
  10 + <el-button v-if="viewOwnerFlag !== 'Owner'" type="primary" size="small" @click="openChooseOwner">
  11 + {{ $t('viewOwnerInfo.chooseOwner') }}
  12 + </el-button>
  13 + </div>
  14 + </div>
  15 +
  16 + <div class="content-wrapper">
  17 + <el-row :gutter="20">
  18 + <el-col :span="4">
  19 + <el-image style="width: 120px; height: 140px" :src="ownerPhoto" fit="cover" @error="errorLoadImg"></el-image>
  20 + </el-col>
  21 +
  22 + <el-col :span="20">
  23 + <el-row :gutter="20" class="text-left">
  24 + <el-col :span="8" >
  25 + <div class="info-item">
  26 + <label>{{ $t('viewOwnerInfo.ownerId') }}:</label>
  27 + <span>{{ ownerId }}</span>
  28 + </div>
  29 + </el-col>
  30 + <el-col :span="8">
  31 + <div class="info-item">
  32 + <label>{{ $t('viewOwnerInfo.name') }}:</label>
  33 + <span>{{ name }}</span>
  34 + </div>
  35 + </el-col>
  36 + <el-col :span="8">
  37 + <div class="info-item">
  38 + <label>{{ $t('viewOwnerInfo.sex') }}:</label>
  39 + <span>{{ sex | formatSex }}</span>
  40 + </div>
  41 + </el-col>
  42 + </el-row>
  43 +
  44 + <el-row :gutter="20" class="text-left">
  45 + <el-col :span="8">
  46 + <div class="info-item">
  47 + <label>{{ $t('viewOwnerInfo.age') }}:</label>
  48 + <span>{{ age }}</span>
  49 + </div>
  50 + </el-col>
  51 + <el-col :span="8">
  52 + <div class="info-item">
  53 + <label>{{ $t('viewOwnerInfo.idCard') }}:</label>
  54 + <span>{{ idCard }}</span>
  55 + </div>
  56 + </el-col>
  57 + <el-col :span="8">
  58 + <div class="info-item">
  59 + <label>{{ $t('viewOwnerInfo.link') }}:</label>
  60 + <span>{{ link }}</span>
  61 + </div>
  62 + </el-col>
  63 + </el-row>
  64 +
  65 + <el-row :gutter="20" class="text-left">
  66 + <el-col :span="8">
  67 + <div class="info-item">
  68 + <label>{{ $t('viewOwnerInfo.userName') }}:</label>
  69 + <span>{{ userName }}</span>
  70 + </div>
  71 + </el-col>
  72 + <el-col :span="8">
  73 + <div class="info-item">
  74 + <label>{{ $t('viewOwnerInfo.remark') }}:</label>
  75 + <span>{{ remark }}</span>
  76 + </div>
  77 + </el-col>
  78 + </el-row>
  79 +
  80 + <template v-for="(item, index) in attrs">
  81 + <el-row :gutter="20" :key="index" class="text-left" v-if="index % 3 === 0">
  82 + <el-col :span="8">
  83 + <div class="info-item">
  84 + <label>{{ item.specName }}:</label>
  85 + <span>{{ item.valueName }}</span>
  86 + </div>
  87 + </el-col>
  88 + <el-col :span="8" v-if="index < attrs.length - 1">
  89 + <div class="info-item">
  90 + <label>{{ attrs[index + 1].specName }}:</label>
  91 + <span>{{ attrs[index + 1].valueName }}</span>
  92 + </div>
  93 + </el-col>
  94 + <el-col :span="8" v-if="index < attrs.length - 2">
  95 + <div class="info-item">
  96 + <label>{{ attrs[index + 2].specName }}:</label>
  97 + <span>{{ attrs[index + 2].valueName }}</span>
  98 + </div>
  99 + </el-col>
  100 + </el-row>
  101 + </template>
  102 + </el-col>
  103 + </el-row>
  104 + </div>
  105 +
  106 + <search-owner ref="searchOwner" @chooseOwner="handleChooseOwner" @loadData="handleLoadData" />
  107 + </el-card>
  108 +</template>
  109 +
  110 +<script>
  111 +import { getCommunityId } from '@/api/community/communityApi'
  112 +import { queryOwners } from '@/api/owner/deleteOwnerRoomApi'
  113 +import SearchOwner from './SearchOwner'
  114 +
  115 +export default {
  116 + name: 'ViewOwnerInfo',
  117 + components: {
  118 + SearchOwner
  119 + },
  120 + props: {
  121 + showCallBackButton: {
  122 + type: Boolean,
  123 + default: false
  124 + }
  125 + },
  126 + filters: {
  127 + formatSex(value) {
  128 + return value === '0' ? '男' : value === '1' ? '女' : ''
  129 + }
  130 + },
  131 + data() {
  132 + return {
  133 + viewOwnerFlag: '',
  134 + ownerId: '',
  135 + name: '',
  136 + age: '',
  137 + sex: '',
  138 + userName: '',
  139 + remark: '',
  140 + idCard: '',
  141 + link: '',
  142 + ownerPhoto: '/img/noPhoto.jpg',
  143 + attrs: [],
  144 + communityId: ''
  145 + }
  146 + },
  147 + created() {
  148 + this.communityId = getCommunityId()
  149 + this.loadOwnerInfo()
  150 + },
  151 + methods: {
  152 + async loadOwnerInfo() {
  153 + const ownerId = this.$route.query.ownerId
  154 + if (!ownerId) return
  155 +
  156 + this.viewOwnerFlag = 'Owner'
  157 +
  158 + try {
  159 + const params = {
  160 + ownerId,
  161 + page: 1,
  162 + row: 1,
  163 + communityId: this.communityId,
  164 + ownerTypeCd: '1001'
  165 + }
  166 +
  167 + const res = await queryOwners(params)
  168 + const owner = res.data[0]
  169 + Object.assign(this, {
  170 + ownerId: owner.memberId,
  171 + name: owner.name,
  172 + age: owner.age,
  173 + sex: owner.sex,
  174 + userName: owner.userName,
  175 + remark: owner.remark,
  176 + idCard: owner.idCard,
  177 + link: owner.link,
  178 + attrs: owner.ownerAttrDtos || []
  179 + })
  180 +
  181 + if (owner.url) {
  182 + this.ownerPhoto = owner.url
  183 + }
  184 +
  185 + } catch (error) {
  186 + console.error('Failed to load owner info:', error)
  187 + this.$message.error(this.$t('viewOwnerInfo.loadError'))
  188 + }
  189 + },
  190 +
  191 + handleCallBack() {
  192 + this.$emit('callBackListOwner', this.ownerId)
  193 + },
  194 +
  195 + errorLoadImg() {
  196 + this.ownerPhoto = '/img/noPhoto.jpg'
  197 + },
  198 +
  199 + openChooseOwner() {
  200 + this.$refs.searchOwner.open()
  201 + },
  202 +
  203 + handleChooseOwner(owner) {
  204 + Object.assign(this, {
  205 + ownerId: owner.memberId,
  206 + name: owner.name,
  207 + age: owner.age,
  208 + sex: owner.sex,
  209 + userName: owner.userName,
  210 + remark: owner.remark,
  211 + idCard: owner.idCard,
  212 + link: owner.link,
  213 + ownerPhoto: owner.url || '/img/noPhoto.jpg',
  214 + attrs: owner.ownerAttrDtos || []
  215 + })
  216 + },
  217 +
  218 + handleLoadData({ ownerId }) {
  219 + this.ownerId = ownerId
  220 + this.loadOwnerInfo()
  221 + }
  222 + }
  223 +}
  224 +</script>
  225 +
  226 +<style scoped>
  227 +.box-card {
  228 + margin-bottom: 20px;
  229 +}
  230 +
  231 +.card-header-buttons {
  232 + float: right;
  233 +}
  234 +
  235 +.content-wrapper {
  236 + padding: 20px;
  237 +}
  238 +
  239 +.info-item {
  240 + margin-bottom: 15px;
  241 + line-height: 1.5;
  242 + color: #606266;
  243 +}
  244 +
  245 +.info-item label {
  246 + font-weight: bold;
  247 + margin-right: 5px;
  248 +}
  249 +</style>
0 250 \ No newline at end of file
... ...
src/components/room/importOwnerRoom.vue
... ... @@ -2,7 +2,8 @@
2 2 <el-dialog :title="$t('room.importOwnerRoom.title')" :visible.sync="visible" width="40%" :before-close="handleClose">
3 3 <el-form ref="form" :model="form" label-width="120px" class="text-left">
4 4 <el-form-item :label="$t('room.importOwnerRoom.selectFile')">
5   - <el-upload ref="upload" action="" :auto-upload="false" :on-change="handleFileChange" accept=".xls,.xlsx" class="margin-left">
  5 + <el-upload ref="upload" action="" :auto-upload="false" :on-change="handleFileChange" accept=".xls,.xlsx"
  6 + class="margin-left">
6 7 <el-button size="small" type="primary">{{ $t('room.importOwnerRoom.clickUpload') }}</el-button>
7 8 <div slot="tip" class="el-upload__tip">
8 9 {{ fileName || $t('room.importOwnerRoom.requiredFile') }}
... ... @@ -92,19 +93,14 @@ export default {
92 93  
93 94 const response = await importOwnerRoom(formData)
94 95  
95   - if (response.code === 0) {
96   - this.$message.success(this.$t('room.importOwnerRoom.importSuccess'))
97   - this.handleClose()
98   - this.$router.push({
99   - path: '/property/assetImportLogDetail',
100   - query: {
101   - logId: response.data.logId,
102   - logType: 'importRoomOwner'
103   - }
104   - })
105   - } else {
106   - this.$message.error(response.msg || this.$t('room.importOwnerRoom.importFailed'))
107   - }
  96 + this.handleClose()
  97 + this.$router.push({
  98 + path: '/property/assetImportLogDetail',
  99 + query: {
  100 + logId: response.data.logId,
  101 + logType: 'importRoomOwner'
  102 + }
  103 + })
108 104 } catch (error) {
109 105 this.$message.error(this.$t('room.importOwnerRoom.importError'))
110 106 }
... ...
src/i18n/index.js
... ... @@ -124,7 +124,8 @@ import { messages as feeConfigManageMessages } from &#39;../views/fee/feeConfigManag
124 124 import { messages as payFeeConfigDiscountManageMessages } from '../views/fee/payFeeConfigDiscountManageLang'
125 125 import { messages as roomMessages } from '../views/room/roomLang.js'
126 126 import { messages as addRoomViewMessages } from '../views/room/addRoomViewLang'
127   -
  127 +import { messages as roomBindOwnerMessages } from '../views/owner/roomBindOwnerLang'
  128 +import { messages as deleteOwnerRoomMessages } from '../views/owner/deleteOwnerRoomLang'
128 129  
129 130 Vue.use(VueI18n)
130 131  
... ... @@ -253,6 +254,8 @@ const messages = {
253 254 ...payFeeConfigDiscountManageMessages.en,
254 255 ...roomMessages.en,
255 256 ...addRoomViewMessages.en,
  257 + ...roomBindOwnerMessages.en,
  258 + ...deleteOwnerRoomMessages.en,
256 259 },
257 260 zh: {
258 261 ...loginMessages.zh,
... ... @@ -377,6 +380,8 @@ const messages = {
377 380 ...payFeeConfigDiscountManageMessages.zh,
378 381 ...roomMessages.zh,
379 382 ...addRoomViewMessages.zh,
  383 + ...roomBindOwnerMessages.zh,
  384 + ...deleteOwnerRoomMessages.zh,
380 385 }
381 386 }
382 387  
... ...
src/router/index.js
... ... @@ -602,10 +602,20 @@ const routes = [
602 602 component: () => import('@/views/room/roomList.vue')
603 603 },
604 604 {
605   - path:'/views/room/addRoomView',
606   - name:'/views/room/addRoomView',
  605 + path: '/views/room/addRoomView',
  606 + name: '/views/room/addRoomView',
607 607 component: () => import('@/views/room/addRoomViewList.vue')
  608 + },
  609 + {
  610 + path:'/views/owner/roomBindOwner',
  611 + name:'/views/owner/roomBindOwner',
  612 + component: () => import('@/views/owner/roomBindOwnerList.vue')
608 613 },
  614 + {
  615 + path:'/views/owner/deleteOwnerRoom',
  616 + name:'/views/owner/deleteOwnerRoom',
  617 + component: () => import('@/views/owner/deleteOwnerRoomList.vue')
  618 + },
609 619 // 其他子路由可以在这里添加
610 620 ]
611 621 },
... ...
src/views/owner/deleteOwnerRoomLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + viewOwnerInfo: {
  4 + title: 'Owner Information',
  5 + ownerId: 'Owner ID',
  6 + name: 'Name',
  7 + sex: 'Gender',
  8 + age: 'Age',
  9 + idCard: 'ID Card',
  10 + link: 'Contact',
  11 + userName: 'Created By',
  12 + remark: 'Remark',
  13 + chooseOwner: 'Select Owner',
  14 + loadError: 'Failed to load owner information'
  15 + },
  16 + searchOwner: {
  17 + title: 'Select Owner',
  18 + ownerId: 'Owner ID',
  19 + name: 'Name',
  20 + personType: 'Person Type',
  21 + personRole: 'Person Role',
  22 + idCard: 'ID Card',
  23 + link: 'Contact',
  24 + roomPlaceholder: 'Enter room number (building-unit-room)',
  25 + ownerPlaceholder: 'Enter owner name',
  26 + loadError: 'Failed to load owner list'
  27 + },
  28 + showOwnerRoom: {
  29 + info: 'Room Information',
  30 + propertyFee: 'Property Fee',
  31 + exitRoom: 'I want to exit the room',
  32 + shopNum: 'Shop Number',
  33 + roomNum: 'Room Number',
  34 + floor: 'Floor',
  35 + shopId: 'Shop ID',
  36 + roomId: 'Room ID',
  37 + builtUpArea: 'Built-up Area',
  38 + squareMeters: 'Square Meters',
  39 + apartmentLayout: 'Apartment Layout',
  40 + roomCount: 'Number of Rooms',
  41 + layer: 'layer'
  42 + },
  43 + ownerExitRoom: {
  44 + confirmOperation: 'Please confirm your operation',
  45 + confirmExit: 'Confirm to exit the room?',
  46 + confirmExitTip: 'After exiting, it can be sold again',
  47 + cancel: 'Cancel',
  48 + confirmExitBtn: 'Confirm Exit'
  49 + }
  50 + },
  51 + zh: {
  52 + viewOwnerInfo: {
  53 + title: '业主信息',
  54 + ownerId: '业主ID',
  55 + name: '名称',
  56 + sex: '性别',
  57 + age: '年龄',
  58 + idCard: '身份证',
  59 + link: '联系方式',
  60 + userName: '创建员工',
  61 + remark: '备注',
  62 + chooseOwner: '选择业主',
  63 + loadError: '加载业主信息失败'
  64 + },
  65 + searchOwner: {
  66 + title: '选择业主',
  67 + ownerId: '业主编号',
  68 + name: '名称',
  69 + personType: '人员类型',
  70 + personRole: '人员角色',
  71 + idCard: '证件号',
  72 + link: '联系方式',
  73 + roomPlaceholder: '输入房屋编号(楼栋-单元-房屋)',
  74 + ownerPlaceholder: '输入业主名称',
  75 + loadError: '加载业主列表失败'
  76 + },
  77 + showOwnerRoom: {
  78 + info: '房屋信息',
  79 + propertyFee: '物业费',
  80 + exitRoom: '我要退房',
  81 + shopNum: '商铺编号',
  82 + roomNum: '房屋编号',
  83 + floor: '楼层',
  84 + shopId: '商铺ID',
  85 + roomId: '房屋ID',
  86 + builtUpArea: '建筑面积',
  87 + squareMeters: '平方米',
  88 + apartmentLayout: '户型',
  89 + roomCount: '房间数',
  90 + layer: '层'
  91 + },
  92 + ownerExitRoom: {
  93 + confirmOperation: '请确认您的操作',
  94 + confirmExit: '确认是否退房?',
  95 + confirmExitTip: '退房后可以再次售卖',
  96 + cancel: '点错了',
  97 + confirmExitBtn: '确认退出'
  98 + }
  99 + }
  100 +}
0 101 \ No newline at end of file
... ...
src/views/owner/deleteOwnerRoomList.vue 0 → 100644
  1 +<template>
  2 + <div class="padding">
  3 +
  4 + <!-- 业主信息 -->
  5 + <view-owner-info ref="viewOwnerInfo" :show-call-back-button="true" @notify="handleNotify" @callBackListOwner="goBack"/>
  6 +
  7 +
  8 + <!-- 业主房屋信息 -->
  9 + <show-owner-room :deleteOwnerRoomFlag="deleteOwnerRoomFlag" :ownerId="ownerId" :ownerName="ownerName" />
  10 +
  11 + </div>
  12 +</template>
  13 +
  14 +<script>
  15 +import ViewOwnerInfo from '@/components/owner/viewOwnerInfo'
  16 +import ShowOwnerRoom from '@/components/owner/showOwnerRoom'
  17 +
  18 +export default {
  19 + name: 'DeleteOwnerRoomList',
  20 + components: {
  21 + ViewOwnerInfo,
  22 + ShowOwnerRoom
  23 + },
  24 + data() {
  25 + return {
  26 + ownerId: '',
  27 + ownerName: '',
  28 + deleteOwnerRoomFlag: true
  29 + }
  30 + },
  31 + created() {
  32 + this.ownerId = this.$route.query.ownerId
  33 + },
  34 + methods: {
  35 + handleNotify(ownerInfo) {
  36 + // 处理返回通知
  37 + console.log('Received notify:', ownerInfo)
  38 + // 这里可以添加其他处理逻辑
  39 + },
  40 + goBack() {
  41 + this.$router.go(-1)
  42 + }
  43 + }
  44 +}
  45 +</script>
  46 +
  47 +<style scoped>
  48 +.el-row {
  49 + margin-bottom: 20px;
  50 +}
  51 +</style>
0 52 \ No newline at end of file
... ...
src/views/owner/roomBindOwnerLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + roomBindOwner: {
  4 + title: 'House Handover',
  5 + room: 'Room',
  6 + owner: 'Owner',
  7 + startTime: 'Start Time',
  8 + endTime: 'End Time',
  9 + roomPlaceholder: 'Required, please enter room name',
  10 + ownerPlaceholder: 'Required, please select owner',
  11 + startTimePlaceholder: 'Required, please enter start time',
  12 + endTimePlaceholder: 'Required, please enter end time',
  13 + selectOwner: 'Select Owner',
  14 + roomRequired: 'Room cannot be empty',
  15 + ownerRequired: 'Owner cannot be empty',
  16 + startTimeRequired: 'Start time cannot be empty',
  17 + endTimeRequired: 'End time cannot be empty',
  18 + timeError: 'End time must be greater than start time',
  19 + fetchRoomError: 'Failed to get room information'
  20 + },
  21 + searchOwner: {
  22 + title: 'Select Owner',
  23 + roomPlaceholder: 'Enter room number (building-unit-room)',
  24 + ownerPlaceholder: 'Enter owner name',
  25 + memberId: 'Owner ID',
  26 + name: 'Name',
  27 + personType: 'Person Type',
  28 + personRole: 'Person Role',
  29 + idCard: 'ID Card',
  30 + contact: 'Contact'
  31 + }
  32 + },
  33 + zh: {
  34 + roomBindOwner: {
  35 + title: '房屋交房',
  36 + room: '房屋',
  37 + owner: '业主',
  38 + startTime: '开始时间',
  39 + endTime: '结束时间',
  40 + roomPlaceholder: '必填,请填写房屋名称',
  41 + ownerPlaceholder: '必填,请选择业主',
  42 + startTimePlaceholder: '必填,请填写开始时间',
  43 + endTimePlaceholder: '必填,请填写结束时间',
  44 + selectOwner: '选择业主',
  45 + roomRequired: '房屋不能为空',
  46 + ownerRequired: '业主不能为空',
  47 + startTimeRequired: '开始时间不能为空',
  48 + endTimeRequired: '结束时间不能为空',
  49 + timeError: '结束时间必须大于开始时间',
  50 + fetchRoomError: '获取房屋信息失败'
  51 + },
  52 + searchOwner: {
  53 + title: '选择业主',
  54 + roomPlaceholder: '输入房屋编号(楼栋-单元-房屋)',
  55 + ownerPlaceholder: '输入业主名称',
  56 + memberId: '业主编号',
  57 + name: '名称',
  58 + personType: '人员类型',
  59 + personRole: '人员角色',
  60 + idCard: '证件号',
  61 + contact: '联系方式'
  62 + }
  63 + }
  64 +}
0 65 \ No newline at end of file
... ...
src/views/owner/roomBindOwnerList.vue 0 → 100644
  1 +<template>
  2 + <div class="room-bind-owner-container">
  3 + <el-card class="box-card">
  4 + <div slot="header" class="clearfix">
  5 + <h5>{{ $t('roomBindOwner.title') }}</h5>
  6 + <div class="header-tools">
  7 + <el-button type="primary" size="small" icon="el-icon-close" @click="_goBack">
  8 + {{ $t('common.back') }}
  9 + </el-button>
  10 + </div>
  11 + </div>
  12 +
  13 + <el-row>
  14 + <el-col :span="24">
  15 + <el-form label-width="120px">
  16 + <el-form-item :label="$t('roomBindOwner.room')">
  17 + <el-input v-model.trim="roomBindOwnerInfo.roomName" :placeholder="$t('roomBindOwner.roomPlaceholder')"
  18 + disabled />
  19 + </el-form-item>
  20 +
  21 + <el-form-item :label="$t('roomBindOwner.owner')">
  22 + <el-col :span="18">
  23 + <el-input v-model.trim="roomBindOwnerInfo.ownerName" :placeholder="$t('roomBindOwner.ownerPlaceholder')"
  24 + disabled />
  25 + </el-col>
  26 + <el-col :span="4" :offset="1">
  27 + <el-button type="primary" size="small" icon="el-icon-plus" @click="_openChooseOwner">
  28 + {{ $t('roomBindOwner.selectOwner') }}
  29 + </el-button>
  30 + </el-col>
  31 + </el-form-item>
  32 +
  33 + <el-form-item :label="$t('roomBindOwner.startTime')">
  34 + <el-date-picker v-model="roomBindOwnerInfo.startTime" type="date"
  35 + :placeholder="$t('roomBindOwner.startTimePlaceholder')" value-format="yyyy-MM-dd" class="addStartTime" />
  36 + </el-form-item>
  37 +
  38 + <el-form-item :label="$t('roomBindOwner.endTime')">
  39 + <el-date-picker v-model="roomBindOwnerInfo.endTime" type="date"
  40 + :placeholder="$t('roomBindOwner.endTimePlaceholder')" value-format="yyyy-MM-dd" class="addEndTime" />
  41 + </el-form-item>
  42 + </el-form>
  43 + </el-col>
  44 + </el-row>
  45 + </el-card>
  46 +
  47 + <el-row>
  48 + <el-col :span="24" class="text-right" style="margin-top: 20px;">
  49 + <el-button type="primary" icon="el-icon-check" @click="saveRoomBindOwnerInfo">
  50 + {{ $t('common.submit') }}
  51 + </el-button>
  52 + </el-col>
  53 + </el-row>
  54 +
  55 + <search-owner ref="searchOwnerRef" @chooseOwner="handleChooseOwner" />
  56 + </div>
  57 +</template>
  58 +
  59 +<script>
  60 +import { sellRoom, queryRooms } from '@/api/owner/roomBindOwnerApi'
  61 +import { getCommunityId } from '@/api/community/communityApi'
  62 +import SearchOwner from '@/components/owner/SearchOwner'
  63 +import { getDateYYYYMMDD } from '@/utils/dateUtil'
  64 +
  65 +export default {
  66 + name: 'RoomBindOwnerList',
  67 + components: {
  68 + SearchOwner
  69 + },
  70 + data() {
  71 + return {
  72 + roomBindOwnerInfo: {
  73 + roomId: '',
  74 + roomName: '',
  75 + ownerId: '',
  76 + ownerName: '',
  77 + state: '2001',
  78 + startTime: '',
  79 + endTime: '2099-01-01',
  80 + },
  81 + communityId: ''
  82 + }
  83 + },
  84 + created() {
  85 + this.communityId = getCommunityId()
  86 + this.roomBindOwnerInfo.startTime = getDateYYYYMMDD()
  87 + this.initData()
  88 + },
  89 + methods: {
  90 + initData() {
  91 + const roomId = this.$route.query.roomId
  92 + if (roomId) {
  93 + this.roomBindOwnerInfo.roomId = roomId
  94 + this.listRoom(roomId)
  95 + }
  96 + },
  97 + async listRoom(roomId) {
  98 + try {
  99 + const params = {
  100 + page: 1,
  101 + row: 1,
  102 + roomId: roomId,
  103 + communityId: this.communityId
  104 + }
  105 + const res = await queryRooms(params)
  106 + const room = res.rooms[0]
  107 + this.roomBindOwnerInfo.roomName = `${room.floorNum}-${room.unitNum}-${room.roomNum}`
  108 +
  109 + } catch (error) {
  110 + this.$message.error(this.$t('roomBindOwner.fetchRoomError'))
  111 + }
  112 + },
  113 + handleChooseOwner(owner) {
  114 + this.roomBindOwnerInfo.ownerName = owner.name
  115 + this.roomBindOwnerInfo.ownerId = owner.ownerId
  116 + },
  117 + _openChooseOwner() {
  118 + this.$refs.searchOwnerRef.open()
  119 + },
  120 + _goBack() {
  121 + this.$router.go(-1)
  122 + },
  123 + roomBindOwnerValidate() {
  124 + const rules = {
  125 + ownerId: { required: true, message: this.$t('roomBindOwner.ownerRequired') },
  126 + roomId: { required: true, message: this.$t('roomBindOwner.roomRequired') },
  127 + startTime: { required: true, message: this.$t('roomBindOwner.startTimeRequired') },
  128 + endTime: { required: true, message: this.$t('roomBindOwner.endTimeRequired') }
  129 + }
  130 +
  131 + const errors = []
  132 + Object.keys(rules).forEach(key => {
  133 + if (!this.roomBindOwnerInfo[key]) {
  134 + errors.push(rules[key].message)
  135 + }
  136 + })
  137 +
  138 + if (errors.length > 0) {
  139 + this.$message.error(errors[0])
  140 + return false
  141 + }
  142 +
  143 + const start = new Date(this.roomBindOwnerInfo.startTime)
  144 + const end = new Date(this.roomBindOwnerInfo.endTime)
  145 + if (start >= end) {
  146 + this.$message.error(this.$t('roomBindOwner.timeError'))
  147 + return false
  148 + }
  149 +
  150 + return true
  151 + },
  152 + async saveRoomBindOwnerInfo() {
  153 + if (!this.roomBindOwnerValidate()) return
  154 +
  155 + try {
  156 + const data = {
  157 + ...this.roomBindOwnerInfo,
  158 + communityId: this.communityId
  159 + }
  160 +
  161 + const res = await sellRoom(data)
  162 + if (res.code === 0) {
  163 + this.$message.success(this.$t('common.submitSuccess'))
  164 + this._goBack()
  165 + } else {
  166 + this.$message.error(res.msg || this.$t('common.submitFailed'))
  167 + }
  168 + } catch (error) {
  169 + this.$message.error(this.$t('common.requestError'))
  170 + }
  171 + }
  172 + }
  173 +}
  174 +</script>
  175 +
  176 +<style scoped>
  177 +.room-bind-owner-container {
  178 + padding: 20px;
  179 +}
  180 +
  181 +.header-tools {
  182 + position: absolute;
  183 + top: 20px;
  184 + right: 20px;
  185 +}
  186 +
  187 +.text-right {
  188 + text-align: right;
  189 +}
  190 +
  191 +.addStartTime,
  192 +.addEndTime {
  193 + width: 100%;
  194 +}
  195 +</style>
0 196 \ No newline at end of file
... ...
src/views/room/roomList.vue
... ... @@ -219,9 +219,9 @@
219 219 <div class="hc-td">{{ scope.row.listValues[index] || '' }}</div>
220 220 </template>
221 221 </el-table-column>
222   - <el-table-column :label="$t('roomList.operation')" fixed="right" width="300" align="center"
223   - class-name="text-center hc-table-fix-right-td">
224   - <template slot-scope="scope">
  222 + <el-table-column :label="$t('roomList.operation')" fixed="right" width="180" align="center"
  223 + class-name="text-center">
  224 + <template slot-scope="scope" class="custom-button-group">
225 225 <el-button-group>
226 226 <el-button v-if="hasPrivilege('502020082493857941')" size="mini"
227 227 @click="openEditRoomModel(scope.row)">
... ... @@ -661,11 +661,11 @@ export default {
661 661 },
662 662  
663 663 toRoomBindOwner(room) {
664   - this.$router.push(`/pages/owner/roomBindOwner?roomId=${room.roomId}`)
  664 + this.$router.push(`/views/owner/roomBindOwner?roomId=${room.roomId}`)
665 665 },
666 666  
667 667 toRoomUnBindOwner(room) {
668   - this.$router.push(`/pages/property/deleteOwnerRoom?ownerId=${room.ownerId}`)
  668 + this.$router.push(`/views/owner/deleteOwnerRoom?ownerId=${room.ownerId}`)
669 669 },
670 670  
671 671 showMarkdown() {
... ... @@ -759,4 +759,12 @@ export default {
759 759 .border-radius {
760 760 border-radius: 4px;
761 761 }
  762 +/* 在全局样式文件中 */
  763 +.el-button-group .el-button {
  764 + margin-right: 5px;
  765 + margin-bottom: 5px;
  766 +}
  767 +.el-button-group .el-button:last-child {
  768 + margin-right: 0;
  769 +}
762 770 </style>
763 771 \ No newline at end of file
... ...