测试完成房屋装修模块

This commit is contained in:
wuxw 2025-07-12 13:17:10 +08:00
parent 81ca23ff1b
commit 8fc7c7915a
16 changed files with 1036 additions and 105 deletions

View File

@ -0,0 +1,88 @@
import request from '@/utils/request'
// 查询装修跟踪记录列表
export function queryRoomRenovationRecord(params) {
return new Promise((resolve, reject) => {
request({
url: '/roomRenovation/queryRoomRenovationRecord',
method: 'get',
params
}).then(response => {
const res = response.data
resolve(res)
}).catch(error => {
reject(error)
})
})
}
// 更新装修跟踪记录
export function updateRoomDecorationRecord(data) {
return new Promise((resolve, reject) => {
request({
url: '/roomRenovation/updateRoomDecorationRecord',
method: 'post',
data
}).then(response => {
const res = response.data
resolve(res)
}).catch(error => {
reject(error)
})
})
}
// 删除装修跟踪记录
export function deleteRoomRenovationRecord(data) {
return new Promise((resolve, reject) => {
request({
url: '/roomRenovation/deleteRoomRenovationRecord',
method: 'post',
data
}).then(response => {
const res = response.data
resolve(res)
}).catch(error => {
reject(error)
})
})
}
// 上传图片
export function uploadImage(data) {
return new Promise((resolve, reject) => {
request({
url: '/uploadImage',
method: 'post',
data,
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(response => {
const res = response.data
resolve(res)
}).catch(error => {
reject(error)
})
})
}
// 上传视频
export function uploadVedio(data, config) {
return new Promise((resolve, reject) => {
request({
url: '/uploadVedio',
method: 'post',
data,
headers: {
'Content-Type': 'multipart/form-data'
},
...config
}).then(response => {
const res = response.data
resolve(res)
}).catch(error => {
reject(error)
})
})
}

View File

@ -0,0 +1,38 @@
import request from '@/utils/request'
import { getCommunityId } from '@/api/community/communityApi'
/**
* 查询房屋装修记录详情
* @param {Object} params 查询参数
* @param {string} params.recordId 记录ID
* @param {string} params.roomName 房间名称
* @param {string} params.state 状态
* @param {string} params.roomId 房间ID
* @param {number} params.page 页码
* @param {number} params.row 每页条数
* @returns {Promise} 返回Promise对象
*/
export function queryRoomRenovationRecordDetail(params) {
return new Promise((resolve, reject) => {
// 确保有communityId
const queryParams = {
...params,
communityId: params.communityId || getCommunityId()
}
request({
url: '/roomRenovation/queryRoomRenovationRecordDetail',
method: 'get',
params: queryParams
}).then(response => {
const res = response.data
resolve({
data: res.data,
total: res.total,
records: res.records
})
}).catch(error => {
reject(error)
})
})
}

View File

@ -0,0 +1,63 @@
<template>
<el-dialog
:title="$t('deleteRoomDecorationRecord.title')"
:visible.sync="visible"
width="30%"
@close="handleClose"
>
<div class="confirm-message">
{{ $t('deleteRoomDecorationRecord.confirm') }}
</div>
<div slot="footer" class="dialog-footer">
<el-button @click="visible = false">
{{ $t('deleteRoomDecorationRecord.cancel') }}
</el-button>
<el-button type="primary" @click="confirmDelete">
{{ $t('deleteRoomDecorationRecord.confirmDelete') }}
</el-button>
</div>
</el-dialog>
</template>
<script>
import { deleteRoomRenovationRecord } from '@/api/community/listRoomDecorationRecordApi'
import { getCommunityId } from '@/api/community/communityApi'
export default {
name: 'DeleteRoomDecorationRecord',
data() {
return {
visible: false,
record: {}
}
},
methods: {
open(record) {
this.record = { ...record }
this.visible = true
},
handleClose() {
this.record = {}
},
async confirmDelete() {
try {
this.record.communityId = getCommunityId()
await deleteRoomRenovationRecord(this.record)
this.$message.success(this.$t('deleteRoomDecorationRecord.success'))
this.$emit('success')
this.visible = false
} catch (error) {
this.$message.error(this.$t('deleteRoomDecorationRecord.failed'))
}
}
}
}
</script>
<style lang="scss" scoped>
.confirm-message {
text-align: center;
font-size: 16px;
margin-bottom: 20px;
}
</style>

View File

@ -0,0 +1,149 @@
<template>
<el-dialog :title="$t('roomDecorationRecord.title')" :visible.sync="visible" width="40%" @close="handleClose">
<el-form ref="form" :model="roomDecorationRecordInfo" label-width="120px" class="text-left" label-position="left">
<el-form-item :label="$t('roomDecorationRecord.room')">
<el-input v-model="roomDecorationRecordInfo.roomName" disabled
:placeholder="$t('roomDecorationRecord.roomPlaceholder')" />
</el-form-item>
<el-form-item :label="$t('roomDecorationRecord.status')">
<el-input v-model="roomDecorationRecordInfo.stateName" disabled />
</el-form-item>
<el-form-item :label="$t('roomDecorationRecord.isViolation')" required>
<el-select v-model="roomDecorationRecordInfo.isTrue" style="width: 100%"
:placeholder="$t('roomDecorationRecord.isViolationPlaceholder')">
<el-option value="" disabled :label="$t('roomDecorationRecord.isViolationPlaceholder')" />
<el-option value="true" :label="$t('roomDecorationRecord.yes')" />
<el-option value="false" :label="$t('roomDecorationRecord.no')" />
</el-select>
</el-form-item>
<el-form-item :label="$t('roomDecorationRecord.remark')" required>
<el-input v-model="roomDecorationRecordInfo.remark" type="textarea"
:placeholder="$t('roomDecorationRecord.remarkPlaceholder')" :rows="3" />
</el-form-item>
<el-form-item :label="$t('roomDecorationRecord.uploadImage')">
<upload-image-url ref="uploadImageUrl" :image-count="99" @notifyUploadCoverImage="handleImageChange" />
</el-form-item>
<el-form-item :label="$t('roomDecorationRecord.uploadVideo')">
<upload-vedio ref="uploadVedio" @change="handleVideoChange" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="visible = false">
{{ $t('common.cancel') }}
</el-button>
<el-button type="primary" @click="saveRoomDecorationRecordInfo">
{{ $t('common.save') }}
</el-button>
</div>
</el-dialog>
</template>
<script>
import { updateRoomDecorationRecord } from '@/api/community/listRoomDecorationRecordApi'
import { getCommunityId } from '@/api/community/communityApi'
import UploadImageUrl from '@/components/upload/UploadImageUrl'
import UploadVedio from './UploadVedio'
export default {
name: 'RoomDecorationRecord',
components: {
UploadImageUrl,
UploadVedio
},
props: {
callBackListener: {
type: String,
default: ''
},
callBackFunction: {
type: String,
default: ''
}
},
data() {
return {
visible: false,
roomDecorationRecordInfo: {
rId: '',
roomName: '',
state: '',
stateName: '',
remark: '',
examineRemark: '',
roomId: '',
photos: [],
videoName: '',
url: '',
detailType: '1001',
isTrue: '',
isTrues: []
}
}
},
methods: {
open(params) {
this.clearRoomDecorationRecordInfo()
this.roomDecorationRecordInfo.rId = params[0]
this.roomDecorationRecordInfo.roomId = params[1]
this.roomDecorationRecordInfo.roomName = params[2]
this.roomDecorationRecordInfo.state = params[3]
this.roomDecorationRecordInfo.stateName = params[4]
this.visible = true
},
handleClose() {
this.clearRoomDecorationRecordInfo()
},
handleImageChange(photosUrl) {
this.roomDecorationRecordInfo.photos = photosUrl.map(item => item.fileId)
},
handleVideoChange(videoInfo) {
this.roomDecorationRecordInfo.videoName = videoInfo.realFileName
},
validateForm() {
if (!this.roomDecorationRecordInfo.isTrue) {
this.$message.error(this.$t('roomDecorationRecord.isViolationRequired'))
return false
}
if (!this.roomDecorationRecordInfo.remark) {
this.$message.error(this.$t('roomDecorationRecord.remarkRequired'))
return false
}
return true
},
async saveRoomDecorationRecordInfo() {
if (!this.validateForm()) return
try {
this.roomDecorationRecordInfo.communityId = getCommunityId()
await updateRoomDecorationRecord(this.roomDecorationRecordInfo)
this.$message.success(this.$t('common.saveSuccess'))
this.$emit('success')
this.visible = false
} catch (error) {
this.$message.error(this.$t('common.saveFailed'))
}
},
clearRoomDecorationRecordInfo() {
setTimeout(() => {
this.$refs.uploadImageUrl.clearImages()
this.$refs.uploadVedio.clear()
},100)
this.roomDecorationRecordInfo = {
rId: '',
state: '',
remark: '',
examineRemark: '',
roomId: '',
photos: [],
videoName: '',
detailType: '1001',
isTrue: '',
isTrues: []
}
}
}
}
</script>

View File

@ -1,39 +1,22 @@
<template>
<el-dialog
:title="$t('roomRenovationManage.review')"
:visible.sync="visible"
width="40%"
@close="resetForm"
>
<el-dialog :title="$t('roomRenovationManage.review')" :visible.sync="visible" width="40%" @close="resetForm">
<el-form :model="form" ref="form" label-width="120px">
<el-form-item :label="$t('roomRenovationManage.room')" prop="roomName">
<el-input
v-model.trim="form.roomName"
disabled
/>
<el-input v-model.trim="form.roomName" disabled />
</el-form-item>
<el-form-item :label="$t('roomRenovationManage.status')" prop="state" required>
<el-select v-model="form.state">
<el-option
:label="$t('roomRenovationManage.reviewPass')"
value="3000"
/>
<el-option
:label="$t('roomRenovationManage.reviewReject')"
value="2000"
/>
<el-option :label="$t('roomRenovationManage.reviewPass')" value="3000" />
<el-option :label="$t('roomRenovationManage.reviewReject')" value="2000" />
</el-select>
</el-form-item>
<el-form-item :label="$t('roomRenovationManage.reviewOpinion')" prop="examineRemark" required>
<el-input
v-model.trim="form.examineRemark"
type="textarea"
/>
<el-input v-model.trim="form.examineRemark" type="textarea" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="visible = false">
{{ $t('roomRenovationManage.cancel') }}
@ -73,7 +56,7 @@ export default {
}
this.visible = true
},
resetForm() {
this.form = {
rId: '',
@ -83,7 +66,7 @@ export default {
communityId: ''
}
},
async saveRoomToExamine() {
try {
await updateRoomToExamine(this.form)

View File

@ -0,0 +1,120 @@
<template>
<div class="upload-vedio-container">
<div v-if="progress > 0" class="progress-container">
<el-progress :percentage="progress" :stroke-width="2" />
<div class="file-name">{{ fileName }}</div>
</div>
<el-button type="primary" @click="triggerUpload">
{{ $t('common.upload') }}
</el-button>
<input
ref="fileInput"
type="file"
accept="video/*"
hidden
@change="handleFileChange"
/>
</div>
</template>
<script>
import { uploadVedio } from '@/api/community/listRoomDecorationRecordApi'
import { getCommunityId } from '@/api/community/communityApi'
export default {
name: 'UploadVedio',
props: {
callBackListener: {
type: String,
default: ''
},
callBackFunction: {
type: String,
default: ''
}
},
data() {
return {
vedio: {},
fileName: '',
realFileName: '',
progress: 0
}
},
watch: {
vedio: {
handler(newVal) {
this.$emit('change', newVal)
},
deep: true
}
},
methods: {
triggerUpload() {
this.$refs.fileInput.click()
},
async handleFileChange(event) {
const file = event.target.files[0]
if (!file) return
if (file.size > 500 * 1024 * 1024) {
this.$message.error(this.$t('uploadVedio.sizeLimit'))
return
}
this.fileName = file.name
await this.uploadFile(file)
event.target.value = null
},
async uploadFile(file) {
const formData = new FormData()
formData.append('uploadFile', file)
formData.append('communityId', getCommunityId())
try {
const response = await uploadVedio(formData, {
onUploadProgress: (progressEvent) => {
const percentCompleted = Math.round(
(progressEvent.loaded * 90) / progressEvent.total
)
this.progress = percentCompleted
}
})
this.progress = 100
this.realFileName = response.realFileName
this.vedio = response
this.$message.success(this.$t('uploadVedio.success'))
} catch (error) {
this.$message.error(this.$t('uploadVedio.failed'))
this.progress = 0
}
},
clear() {
this.vedio = {}
this.fileName = ''
this.realFileName = ''
this.progress = 0
},
notifyVedio(fileName) {
this.fileName = fileName
this.realFileName = fileName
this.progress = 100
}
}
}
</script>
<style lang="scss" scoped>
.upload-vedio-container {
.progress-container {
margin-bottom: 15px;
.file-name {
margin-top: 5px;
font-size: 12px;
color: #606266;
}
}
}
</style>

View File

@ -2,30 +2,23 @@
<div class="upload-image-container">
<div v-for="(image, index) in photos" :key="index" class="image-item">
<el-image
:src="image.url || image"
:src="getImageUrl(image)"
fit="cover"
style="width: 100px; height: 100px"
:preview-src-list="[image.url || image]"
>
<div slot="error" class="image-slot">
<i class="el-icon-picture-outline"></i>
</div>
</el-image>
<i
class="el-icon-delete remove-icon"
@click="removeImage(index)"
></i>
:preview-src-list="[getImageUrl(image)]"
/>
<i class="el-icon-delete delete-icon" @click="removeImage(index)" />
</div>
<div
v-if="photos.length < imageCount"
class="upload-button"
@click="triggerUpload"
>
<i class="el-icon-plus"></i>
<i class="el-icon-plus" />
</div>
<input
type="file"
ref="fileInput"
type="file"
accept="image/*"
hidden
@change="handleFileChange"
@ -34,7 +27,8 @@
</template>
<script>
import { uploadImage } from '@/api/community/addCommunityPublicityApi'
import { uploadImage } from '@/api/community/listRoomDecorationRecordApi'
import { getCommunityId } from '@/api/community/communityApi'
export default {
name: 'UploadImageUrl',
@ -45,11 +39,11 @@ export default {
},
callBackListener: {
type: String,
required: true
default: ''
},
callBackFunction: {
type: String,
required: true
default: ''
}
},
data() {
@ -60,64 +54,81 @@ export default {
},
watch: {
photosUrl: {
deep: true,
handler(newVal) {
this.$emit(this.callBackFunction, newVal)
}
this.$emit('change', newVal)
},
deep: true
}
},
methods: {
getImageUrl(image) {
if (image.indexOf('base64,') > -1) return image
if (image.indexOf('http') > -1 || image.indexOf('https') > -1) return image
return `/callComponent/download/getFile/file?fileId=${image}&communityId=${getCommunityId()}`
},
triggerUpload() {
this.$refs.fileInput.click()
},
async handleFileChange(event) {
const files = event.target.files
if (!files || files.length === 0) return
const file = event.target.files[0]
if (!file) return
const file = files[0]
if (file.size > 2 * 1024 * 1024) {
this.$message.error(this.$t('uploadImage.fileSizeError'))
this.$message.error(this.$t('uploadImage.imageSizeLimit'))
return
}
try {
// Preview image
const reader = new FileReader()
reader.onload = (e) => {
this.photos.push(e.target.result)
}
reader.readAsDataURL(file)
// Preview image
const reader = new FileReader()
reader.onload = (e) => {
this.photos.push(e.target.result)
}
reader.readAsDataURL(file)
// Upload image
// Upload image
try {
const formData = new FormData()
formData.append('uploadFile', file)
formData.append('communityId', getCommunityId())
const response = await uploadImage(formData)
this.photosUrl.push(response.data)
this.photosUrl.push(response)
} catch (error) {
this.$message.error(this.$t('uploadImage.uploadError'))
} finally {
event.target.value = ''
this.$message.error(this.$t('uploadImage.uploadFailed'))
}
event.target.value = null
},
removeImage(index) {
this.photos.splice(index, 1)
this.photosUrl.splice(index, 1)
},
clearImages() {
clear() {
this.photos = []
this.photosUrl = []
},
setImages(images) {
this.clearImages()
images.forEach(image => {
if (typeof image === 'string') {
this.photos.push(image)
this.photosUrl.push({ fileId: image, url: image })
} else {
this.photos.push(image.url)
this.photosUrl.push(image)
notifyPhotos(photos) {
this.clear()
photos.forEach(photo => {
if (photo.indexOf('base64,') > -1) {
this.photos.push(photo)
return
}
if (photo.indexOf('http') > -1 || photo.indexOf('https') > -1) {
this.photos.push(photo)
const fileId = this.getFileIdFromUrl(photo)
if (fileId) {
this.photosUrl.push({ fileId, url: photo })
}
return
}
this.photos.push(this.getImageUrl(photo))
this.photosUrl.push({ fileId: photo, url: this.getImageUrl(photo) })
})
},
getFileIdFromUrl(url) {
const match = url.match(/fileId=([^&]+)/)
return match ? match[1] : null
}
}
}
@ -131,23 +142,19 @@ export default {
.image-item {
position: relative;
margin-right: 10px;
margin-bottom: 10px;
width: 100px;
height: 100px;
.remove-icon {
.delete-icon {
position: absolute;
top: -10px;
right: -10px;
color: #f56c6c;
background: #fff;
border-radius: 50%;
cursor: pointer;
font-size: 16px;
z-index: 1;
&:hover {
color: #f78989;
}
background: white;
border-radius: 50%;
padding: 2px;
}
}
@ -155,7 +162,6 @@ export default {
width: 100px;
height: 100px;
border: 1px dashed #dcdfe6;
border-radius: 4px;
display: flex;
align-items: center;
justify-content: center;
@ -168,16 +174,5 @@ export default {
color: #409eff;
}
}
.image-slot {
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
background: #f5f7fa;
color: #909399;
font-size: 30px;
}
}
</style>

View File

@ -107,4 +107,4 @@ export default {
}
}
}
</style>
</style>

View File

@ -11,6 +11,8 @@ import { messages as adminRoomDetailMessages } from '../views/aCommunity/adminRo
import { messages as adminOwnerDetailMessages } from '../views/aCommunity/adminOwnerDetailLang.js'
import { messages as adminCarDetailMessages } from '../views/aCommunity/adminCarDetailLang.js'
import { messages as adminFeeDetailMessages } from '../views/aCommunity/adminFeeDetailLang.js'
import { messages as listRoomDecorationRecordMessages } from '../views/community/listRoomDecorationRecordLang'
import { messages as listRoomRenovationRecordDetailsMessages } from '../views/community/listRoomRenovationRecordDetailsLang'
export const messages = {
en: {
...roomStructureMessages.en,
@ -26,6 +28,8 @@ export const messages = {
...adminOwnerDetailMessages.en,
...adminCarDetailMessages.en,
...adminFeeDetailMessages.en,
...listRoomDecorationRecordMessages.en,
...listRoomRenovationRecordDetailsMessages.en,
},
zh: {
...roomStructureMessages.zh,
@ -41,5 +45,7 @@ export const messages = {
...adminOwnerDetailMessages.zh,
...adminCarDetailMessages.zh,
...adminFeeDetailMessages.zh,
...listRoomDecorationRecordMessages.zh,
...listRoomRenovationRecordDetailsMessages.zh,
}
}

View File

@ -60,8 +60,18 @@ export default [
component: () => import('@/views/aCommunity/adminCarDetailList.vue')
},
{
path:'/pages/fee/adminFeeDetail',
name:'/pages/fee/adminFeeDetail',
path: '/pages/fee/adminFeeDetail',
name: '/pages/fee/adminFeeDetail',
component: () => import('@/views/aCommunity/adminFeeDetailList.vue')
},
},
{
path: '/views/community/listRoomDecorationRecord',
name: '/views/community/listRoomDecorationRecord',
component: () => import('@/views/community/listRoomDecorationRecordList.vue')
},
{
path: '/views/community/listRoomRenovationRecordDetails',
name: '/views/community/listRoomRenovationRecordDetails',
component: () => import('@/views/community/listRoomRenovationRecordDetailsList.vue')
},
]

View File

@ -0,0 +1,108 @@
export const messages = {
en: {
listRoomDecorationRecord: {
title: 'Decoration Tracking Record',
add: 'Add',
back: 'Back',
recordId: 'Record ID',
room: 'Room',
operator: 'Operator',
createTime: 'Create Time',
status: 'Status',
originalImage: 'Original Image',
isViolation: 'Is Violation',
remark: 'Remark',
operation: 'Operation',
viewDetails: 'View Details',
delete: 'Delete',
fetchError: 'Failed to fetch decoration records'
},
roomDecorationRecord: {
title: 'Decoration Tracking',
room: 'Room',
roomPlaceholder: 'Required, please fill in the room',
status: 'Status',
isViolation: 'Is Violation',
isViolationPlaceholder: 'Please select whether it is a violation',
yes: 'Yes',
no: 'No',
remark: 'Remark',
remarkPlaceholder: 'Please fill in the remark',
uploadImage: 'Upload Image',
uploadVideo: 'Upload Video',
isViolationRequired: 'Is violation is required',
remarkRequired: 'Remark is required'
},
uploadImage: {
imageSizeLimit: 'Image size cannot exceed 2MB',
uploadFailed: 'Failed to upload image'
},
uploadVedio: {
upload: 'Upload Video',
sizeLimit: 'Video size cannot exceed 500MB',
success: 'Video uploaded successfully',
failed: 'Failed to upload video'
},
deleteRoomDecorationRecord: {
title: 'Confirm Your Operation',
confirm: 'Are you sure to delete the room decoration record?',
cancel: 'Cancel',
confirmDelete: 'Confirm Delete',
success: 'Deleted successfully',
failed: 'Failed to delete'
}
},
zh: {
listRoomDecorationRecord: {
title: '装修跟踪记录',
add: '添加',
back: '返回',
recordId: '记录ID',
room: '房屋',
operator: '操作人员',
createTime: '创建时间',
status: '状态',
originalImage: '原始图片',
isViolation: '是否违规',
remark: '备注',
operation: '操作',
viewDetails: '查看详情',
delete: '删除',
fetchError: '获取装修记录失败'
},
roomDecorationRecord: {
title: '装修跟踪',
room: '房屋',
roomPlaceholder: '必填,请填写房屋',
status: '状态',
isViolation: '是否违规',
isViolationPlaceholder: '请选择是否违规',
yes: '是',
no: '否',
remark: '备注',
remarkPlaceholder: '请填写备注',
uploadImage: '上传图片',
uploadVideo: '上传视频',
isViolationRequired: '是否违规不能为空',
remarkRequired: '备注不能为空'
},
uploadImage: {
imageSizeLimit: '图片大小不能超过2MB',
uploadFailed: '图片上传失败'
},
uploadVedio: {
upload: '上传视频',
sizeLimit: '视频大小不能超过500MB',
success: '视频上传成功',
failed: '视频上传失败'
},
deleteRoomDecorationRecord: {
title: '请确认您的操作',
confirm: '确定删除房屋装修记录?',
cancel: '点错了',
confirmDelete: '确认删除',
success: '删除成功',
failed: '删除失败'
}
}
}

View File

@ -0,0 +1,180 @@
<template>
<div class="list-room-decoration-record-container">
<el-card class="box-card">
<div slot="header" class="flex justify-between">
<div>
<span>{{ roomDecorationRecordsInfo.conditions.roomName }}</span>
<span>{{ $t('listRoomDecorationRecord.title') }}</span>
</div>
<div >
<el-button type="primary" size="small" @click="_openAddModal(roomDecorationRecordsInfo.roomRenovation)">
<i class="el-icon-plus"></i>
{{ $t('listRoomDecorationRecord.add') }}
</el-button>
<el-button type="primary" size="small" style="margin-left: 10px" @click="_goBack()">
<i class="el-icon-close"></i>
{{ $t('listRoomDecorationRecord.back') }}
</el-button>
</div>
</div>
<el-table :data="roomDecorationRecordsInfo.roomRenovationRecords" border style="width: 100%">
<el-table-column prop="recordId" :label="$t('listRoomDecorationRecord.recordId')" align="center" />
<el-table-column prop="roomName" :label="$t('listRoomDecorationRecord.room')" align="center" />
<el-table-column prop="staffName" :label="$t('listRoomDecorationRecord.operator')" align="center" />
<el-table-column prop="createTime" :label="$t('listRoomDecorationRecord.createTime')" align="center" />
<el-table-column prop="stateName" :label="$t('listRoomDecorationRecord.status')" align="center">
<template slot-scope="scope">
<span v-if="scope.row.state === '1000'">
{{ scope.row.stateName }}({{ $t('listRoomDecorationRecord.originalImage') }})
</span>
<span v-else>{{ scope.row.stateName }}</span>
</template>
</el-table-column>
<el-table-column prop="isTrueName" :label="$t('listRoomDecorationRecord.isViolation')" align="center" />
<el-table-column prop="remark" :label="$t('listRoomDecorationRecord.remark')" align="center" />
<el-table-column :label="$t('listRoomDecorationRecord.operation')" align="center" width="200">
<template slot-scope="scope">
<el-button size="mini" @click="_openRoomRenovationRecordDetailsModel(scope.row)">
{{ $t('listRoomDecorationRecord.viewDetails') }}
</el-button>
<el-button size="mini" type="danger" @click="_openDeleteRoomRenovationRecordModel(scope.row)">
{{ $t('listRoomDecorationRecord.delete') }}
</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
:total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
@current-change="handleCurrentChange" />
</el-card>
<room-decoration-record ref="roomDecorationRecord" @success="handleSuccess" />
<delete-room-decoration-record ref="deleteRoomDecorationRecord" @success="handleSuccess" />
</div>
</template>
<script>
import { queryRoomRenovationRecord } from '@/api/community/listRoomDecorationRecordApi'
import { getCommunityId } from '@/api/community/communityApi'
import RoomDecorationRecord from '@/components/community/RoomDecorationRecord'
import DeleteRoomDecorationRecord from '@/components/community/DeleteRoomDecorationRecord'
export default {
name: 'ListRoomDecorationRecord',
components: {
RoomDecorationRecord,
DeleteRoomDecorationRecord
},
data() {
return {
roomDecorationRecordsInfo: {
roomRenovationRecords: [],
roomRenovation: [],
conditions: {
rId: '',
roomName: '',
roomId: '',
stateName: '',
state: '',
communityId: ''
}
},
page: {
current: 1,
size: 10,
total: 0
}
}
},
created() {
this.communityId = getCommunityId()
this.roomDecorationRecordsInfo.conditions.communityId = this.communityId
this.roomDecorationRecordsInfo.conditions.rId = this.$route.query.rId
this.roomDecorationRecordsInfo.conditions.roomId = this.$route.query.roomId
this.roomDecorationRecordsInfo.conditions.roomName = this.$route.query.roomName
this.roomDecorationRecordsInfo.conditions.state = this.$route.query.state
this.roomDecorationRecordsInfo.conditions.stateName = this.$route.query.stateName
this._listRoomRenovationRecords(this.page.current, this.page.size)
},
methods: {
async _listRoomRenovationRecords(page, size) {
try {
const params = {
page,
row: size,
...this.roomDecorationRecordsInfo.conditions
}
const { data, total } = await queryRoomRenovationRecord(params)
this.roomDecorationRecordsInfo.roomRenovationRecords = data
this.page.total = total
} catch (error) {
this.$message.error(this.$t('listRoomDecorationRecord.fetchError'))
}
},
_openAddModal(roomRenovation) {
roomRenovation.push(this.roomDecorationRecordsInfo.conditions.rId)
roomRenovation.push(this.roomDecorationRecordsInfo.conditions.roomId)
roomRenovation.push(this.roomDecorationRecordsInfo.conditions.roomName)
roomRenovation.push(this.roomDecorationRecordsInfo.conditions.state)
roomRenovation.push(this.roomDecorationRecordsInfo.conditions.stateName)
this.$refs.roomDecorationRecord.open(roomRenovation)
},
_openDeleteRoomRenovationRecordModel(record) {
this.$refs.deleteRoomDecorationRecord.open(record)
},
_openRoomRenovationRecordDetailsModel(record) {
this.$router.push({
path: '/views/community/listRoomRenovationRecordDetails',
query: {
recordId: record.recordId,
roomName: record.roomName,
state: record.state
}
})
},
handleSuccess() {
this._listRoomRenovationRecords(this.page.current, this.page.size)
},
handleSizeChange(val) {
this.page.size = val
this._listRoomRenovationRecords(this.page.current, val)
},
handleCurrentChange(val) {
this.page.current = val
this._listRoomRenovationRecords(val, this.page.size)
},
_goBack() {
this.$router.go(-1)
}
}
}
</script>
<style lang="scss" scoped>
.list-room-decoration-record-container {
padding: 20px;
.box-card {
margin-bottom: 20px;
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
span {
font-size: 16px;
font-weight: bold;
}
}
.el-pagination {
margin-top: 20px;
text-align: right;
}
}
}
</style>

View File

@ -0,0 +1,24 @@
export const messages = {
en: {
listRoomRenovationRecordDetails: {
title: 'Renovation Record',
back: 'Back',
room: 'Room',
media: 'Media',
originalMedia: 'Original Media',
createTime: 'Create Time',
fetchError: 'Failed to fetch renovation record details'
}
},
zh: {
listRoomRenovationRecordDetails: {
title: '装修记录',
back: '返回',
room: '房屋',
media: '图片/视频',
originalMedia: '原始图片/视频',
createTime: '创建时间',
fetchError: '获取装修记录详情失败'
}
}
}

View File

@ -0,0 +1,156 @@
<template>
<div class="list-room-renovation-record-details-container">
<el-row :gutter="20" style="width:100%">
<el-col :span="24" style="width:100%">
<el-card>
<div slot="header" class="flex justify-between">
<div>
<span>{{ roomRenovationRecordDetailsInfo.conditions.roomName }}</span>
<span>{{ $t('listRoomRenovationRecordDetails.title') }}</span>
</div>
<div class="header-tools">
<el-button type="primary" size="small" @click="_goBack" icon="el-icon-close">
{{ $t('listRoomRenovationRecordDetails.back') }}
</el-button>
</div>
</div>
<el-table :data="roomRenovationRecordDetailsInfo.roomRenovationRecordDetails" border style="width: 100%">
<el-table-column prop="roomName" :label="$t('listRoomRenovationRecordDetails.room')" align="center" />
<el-table-column :label="$t('listRoomRenovationRecordDetails.media')" align="center">
<template slot-scope="scope">
<div v-if="scope.row.relTypeCd === '19000'" class="image-container" @click="showImg(scope.row.url)">
<el-image :src="scope.row.url" :preview-src-list="[scope.row.url]" fit="cover"
style="width:50px;height:50px">
<div slot="error" class="image-slot">
<img src="/img/noPhoto.jpg" style="width:50px;height:50px">
</div>
</el-image>
<img src="/img/icon-bigimg.png" class="preview-icon">
</div>
<video v-else-if="scope.row.relTypeCd === '21000'" width="200" height="200" controls autoplay>
<source :src="scope.row.url" type="video/mp4">
</video>
</template>
</el-table-column>
<el-table-column prop="createTime" :label="$t('listRoomRenovationRecordDetails.createTime')"
align="center" />
</el-table>
<el-pagination :current-page.sync="pagination.current" :page-sizes="[10, 20, 30, 50]"
:page-size="pagination.size" :total="pagination.total" layout="total, sizes, prev, pager, next, jumper"
@size-change="handleSizeChange" @current-change="handleCurrentChange" />
</el-card>
</el-col>
</el-row>
<view-image ref="viewImage" />
</div>
</template>
<script>
import { queryRoomRenovationRecordDetail } from '@/api/community/listRoomRenovationRecordDetailsApi'
import ViewImage from '@/components/community/viewImage'
import { getCommunityId } from '@/api/community/communityApi'
export default {
name: 'ListRoomRenovationRecordDetails',
components: {
ViewImage
},
data() {
return {
roomRenovationRecordDetailsInfo: {
roomRenovationRecordDetails: [],
conditions: {
recordId: '',
roomName: '',
state: '',
roomId: '',
communityId: '',
page: 1,
row: 10
}
},
pagination: {
current: 1,
size: 10,
total: 0
},
loading: false
}
},
created() {
this.roomRenovationRecordDetailsInfo.conditions.communityId = getCommunityId()
this.roomRenovationRecordDetailsInfo.conditions.recordId = this.$route.query.recordId
this.roomRenovationRecordDetailsInfo.conditions.roomName = this.$route.query.roomName
this.roomRenovationRecordDetailsInfo.conditions.state = this.$route.query.state
this._listRoomRenovationRecordDetails()
},
methods: {
async _listRoomRenovationRecordDetails() {
try {
this.loading = true
const params = {
...this.roomRenovationRecordDetailsInfo.conditions,
page: this.pagination.current,
row: this.pagination.size
}
const { data, total } = await queryRoomRenovationRecordDetail(params)
this.roomRenovationRecordDetailsInfo.roomRenovationRecordDetails = data
this.pagination.total = total
} catch (error) {
this.$message.error(this.$t('listRoomRenovationRecordDetails.fetchError'))
} finally {
this.loading = false
}
},
handleSizeChange(val) {
this.pagination.size = val
this._listRoomRenovationRecordDetails()
},
handleCurrentChange(val) {
this.pagination.current = val
this._listRoomRenovationRecordDetails()
},
_goBack() {
this.$router.go(-1)
},
showImg(url) {
this.$refs.viewImage.open(url)
}
}
}
</script>
<style lang="scss" scoped>
.list-room-renovation-record-details-container {
padding: 20px;
.clearfix {
display: flex;
align-items: center;
justify-content: space-between;
}
.header-tools {
display: flex;
align-items: center;
}
.image-container {
position: relative;
display: inline-block;
cursor: pointer;
.preview-icon {
position: absolute;
right: 0;
bottom: 0;
width: 20px;
height: 20px;
}
}
}
</style>

View File

@ -58,7 +58,11 @@ export const messages = {
acceptanceOpinion: "Acceptance Opinion",
reviewOpinion: "Review Opinion",
violationPlaceholder: "Please select if violation",
violationDescPlaceholder: "Please enter violation description"
violationDescPlaceholder: "Please enter violation description",
reviewPass: "Review Pass",
reviewReject: "Review Reject",
acceptanceSuccess: "Acceptance Success",
acceptanceFailed: "Acceptance Failure"
}
},
zh: {
@ -120,7 +124,11 @@ export const messages = {
acceptanceOpinion: "验收意见",
reviewOpinion: "审核意见",
violationPlaceholder: "请选择是否违规",
violationDescPlaceholder: "请输入违规说明"
violationDescPlaceholder: "请输入违规说明",
reviewPass: "审核通过",
reviewReject: "审核不通过",
acceptanceSuccess: "验收成功",
acceptanceFailed: "验收失败"
}
}
}

View File

@ -112,10 +112,10 @@
<el-table-column prop="remark" :label="$t('roomRenovationManage.remark')" align="center" />
<el-table-column :label="$t('roomRenovationManage.operation')" align="center" width="150">
<template slot-scope="scope">
<el-button v-if="scope.row.state === '1000'" size="mini" type="text"
<!-- <el-button v-if="scope.row.state === '1000'" size="mini" type="text"
@click="openRoomRenovationFee(scope.row)">
{{ $t('roomRenovationManage.fee') }}
</el-button>
</el-button> -->
<el-button size="mini" v-if="scope.row.state === '1000' && scope.row.isViolation === 'N'" type="text"
@click="openToExamine(scope.row)">
{{ $t('roomRenovationManage.review') }}
@ -326,10 +326,13 @@ export default {
//
openRoomDecorationRecord(row) {
this.$router.push({
path: '/property/room-decoration-record',
path: '/views/community/listRoomDecorationRecord',
query: {
roomId: row.roomId,
rId: row.rId
rId: row.rId,
roomName: row.roomName,
state: row.state,
stateName: row.stateName
}
})
},
@ -337,7 +340,7 @@ export default {
//
openRoomRenovationDetail(row) {
this.$router.push({
path: '/property/room-renovation-detail',
path: '/views/community/listRoomDecorationRecord',
query: {
rId: row.rId,
roomName: row.roomName