Commit 43eaaadb2858acee57c08cbc1d1d42574b0a0367
1 parent
7505cb92
开发房屋优惠折扣
Showing
19 changed files
with
2823 additions
and
43 deletions
public/index.html
| @@ -19,8 +19,6 @@ | @@ -19,8 +19,6 @@ | ||
| 19 | <script src="https://map.qq.com/api/gljs?v=1.exp&key="></script> | 19 | <script src="https://map.qq.com/api/gljs?v=1.exp&key="></script> |
| 20 | 20 | ||
| 21 | <!-- Qs 库 - 主 CDN --> | 21 | <!-- Qs 库 - 主 CDN --> |
| 22 | - <script src="https://cdn.bootcdn.net/ajax/libs/qs/6.10.3/qs.min.js" | ||
| 23 | - onerror="handleScriptError('Qs-bootcdn', new Error('bootcdn 加载失败'))"></script> | ||
| 24 | <script src="/js/jessibuca/jessibuca.js"></script> | 22 | <script src="/js/jessibuca/jessibuca.js"></script> |
| 25 | 23 | ||
| 26 | 24 |
src/api/fee/applyRoomDiscountManageApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 3 | + | ||
| 4 | +// 查询优惠申请列表 | ||
| 5 | +export function queryApplyRoomDiscount(params) { | ||
| 6 | + return new Promise((resolve, reject) => { | ||
| 7 | + request({ | ||
| 8 | + url: '/applyRoomDiscount/queryApplyRoomDiscount', | ||
| 9 | + method: 'get', | ||
| 10 | + params: { | ||
| 11 | + ...params, | ||
| 12 | + communityId: getCommunityId() | ||
| 13 | + } | ||
| 14 | + }).then(response => { | ||
| 15 | + const res = response.data | ||
| 16 | + resolve(res) | ||
| 17 | + }).catch(error => { | ||
| 18 | + reject(error) | ||
| 19 | + }) | ||
| 20 | + }) | ||
| 21 | +} | ||
| 22 | + | ||
| 23 | + | ||
| 24 | + | ||
| 25 | +// 查询优惠申请列表 | ||
| 26 | +export function listRoomsWhereFeeSet(params) { | ||
| 27 | + return new Promise((resolve, reject) => { | ||
| 28 | + request({ | ||
| 29 | + url: '/fee.listRoomsWhereFeeSet', | ||
| 30 | + method: 'get', | ||
| 31 | + params: { | ||
| 32 | + ...params, | ||
| 33 | + communityId: getCommunityId() | ||
| 34 | + } | ||
| 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 queryApplyRoomDiscountType(params) { | ||
| 46 | + return new Promise((resolve, reject) => { | ||
| 47 | + request({ | ||
| 48 | + url: '/applyRoomDiscount/queryApplyRoomDiscountType', | ||
| 49 | + method: 'get', | ||
| 50 | + params: { | ||
| 51 | + ...params, | ||
| 52 | + communityId: getCommunityId() | ||
| 53 | + } | ||
| 54 | + }).then(response => { | ||
| 55 | + const res = response.data | ||
| 56 | + resolve(res) | ||
| 57 | + }).catch(error => { | ||
| 58 | + reject(error) | ||
| 59 | + }) | ||
| 60 | + }) | ||
| 61 | +} | ||
| 62 | + | ||
| 63 | +// 查询费用折扣 | ||
| 64 | +export function queryFeeDiscount(params) { | ||
| 65 | + return new Promise((resolve, reject) => { | ||
| 66 | + request({ | ||
| 67 | + url: '/feeDiscount/queryFeeDiscount', | ||
| 68 | + method: 'get', | ||
| 69 | + params: { | ||
| 70 | + ...params, | ||
| 71 | + communityId: getCommunityId() | ||
| 72 | + } | ||
| 73 | + }).then(response => { | ||
| 74 | + const res = response.data | ||
| 75 | + resolve(res) | ||
| 76 | + }).catch(error => { | ||
| 77 | + reject(error) | ||
| 78 | + }) | ||
| 79 | + }) | ||
| 80 | +} | ||
| 81 | + | ||
| 82 | +// 保存优惠申请 | ||
| 83 | +export function saveApplyRoomDiscount(data) { | ||
| 84 | + return new Promise((resolve, reject) => { | ||
| 85 | + request({ | ||
| 86 | + url: '/applyRoomDiscount/saveApplyRoomDiscount', | ||
| 87 | + method: 'post', | ||
| 88 | + data: { | ||
| 89 | + ...data, | ||
| 90 | + communityId: getCommunityId() | ||
| 91 | + } | ||
| 92 | + }).then(response => { | ||
| 93 | + const res = response.data | ||
| 94 | + resolve(res) | ||
| 95 | + }).catch(error => { | ||
| 96 | + reject(error) | ||
| 97 | + }) | ||
| 98 | + }) | ||
| 99 | +} | ||
| 100 | + | ||
| 101 | +// 更新优惠申请 | ||
| 102 | +export function updateApplyRoomDiscount(data) { | ||
| 103 | + return new Promise((resolve, reject) => { | ||
| 104 | + request({ | ||
| 105 | + url: '/applyRoomDiscount/updateApplyRoomDiscount', | ||
| 106 | + method: 'post', | ||
| 107 | + data: { | ||
| 108 | + ...data, | ||
| 109 | + communityId: getCommunityId() | ||
| 110 | + } | ||
| 111 | + }).then(response => { | ||
| 112 | + const res = response.data | ||
| 113 | + resolve(res) | ||
| 114 | + }).catch(error => { | ||
| 115 | + reject(error) | ||
| 116 | + }) | ||
| 117 | + }) | ||
| 118 | +} | ||
| 119 | + | ||
| 120 | +// 更新审核优惠申请 | ||
| 121 | +export function updateReviewApplyRoomDiscount(data) { | ||
| 122 | + return new Promise((resolve, reject) => { | ||
| 123 | + request({ | ||
| 124 | + url: '/applyRoomDiscount/updateReviewApplyRoomDiscount', | ||
| 125 | + method: 'post', | ||
| 126 | + data: { | ||
| 127 | + ...data, | ||
| 128 | + communityId: getCommunityId() | ||
| 129 | + } | ||
| 130 | + }).then(response => { | ||
| 131 | + const res = response.data | ||
| 132 | + resolve(res) | ||
| 133 | + }).catch(error => { | ||
| 134 | + reject(error) | ||
| 135 | + }) | ||
| 136 | + }) | ||
| 137 | +} | ||
| 138 | + | ||
| 139 | +// 删除优惠申请 | ||
| 140 | +export function deleteApplyRoomDiscount(data) { | ||
| 141 | + return new Promise((resolve, reject) => { | ||
| 142 | + request({ | ||
| 143 | + url: '/applyRoomDiscount/deleteApplyRoomDiscount', | ||
| 144 | + method: 'post', | ||
| 145 | + data: { | ||
| 146 | + ...data, | ||
| 147 | + communityId: getCommunityId() | ||
| 148 | + } | ||
| 149 | + }).then(response => { | ||
| 150 | + const res = response.data | ||
| 151 | + resolve(res) | ||
| 152 | + }).catch(error => { | ||
| 153 | + reject(error) | ||
| 154 | + }) | ||
| 155 | + }) | ||
| 156 | +} | ||
| 157 | + | ||
| 158 | +// 处理返还金额计算 | ||
| 159 | +export function dealWithRefundAmount(data) { | ||
| 160 | + return new Promise((resolve, reject) => { | ||
| 161 | + request({ | ||
| 162 | + url: '/applyRoomDiscount/dealWithRefundAmount', | ||
| 163 | + method: 'post', | ||
| 164 | + data: { | ||
| 165 | + ...data, | ||
| 166 | + communityId: getCommunityId() | ||
| 167 | + } | ||
| 168 | + }).then(response => { | ||
| 169 | + const res = response.data | ||
| 170 | + resolve(res) | ||
| 171 | + }).catch(error => { | ||
| 172 | + reject(error) | ||
| 173 | + }) | ||
| 174 | + }) | ||
| 175 | +} | ||
| 0 | \ No newline at end of file | 176 | \ No newline at end of file |
src/api/fee/discountTypeApi.js
0 → 100644
| 1 | +import request from '@/utils/request' | ||
| 2 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 3 | + | ||
| 4 | +/** | ||
| 5 | + * 查询优惠类型列表 | ||
| 6 | + * @param {Object} params 查询参数 | ||
| 7 | + * @returns {Promise} | ||
| 8 | + */ | ||
| 9 | +export function queryApplyRoomDiscountType(params) { | ||
| 10 | + return new Promise((resolve, reject) => { | ||
| 11 | + request({ | ||
| 12 | + url: '/applyRoomDiscount/queryApplyRoomDiscountType', | ||
| 13 | + method: 'get', | ||
| 14 | + params: { | ||
| 15 | + ...params, | ||
| 16 | + communityId: getCommunityId() | ||
| 17 | + } | ||
| 18 | + }).then(response => { | ||
| 19 | + const res = response.data | ||
| 20 | + resolve(res) | ||
| 21 | + }).catch(error => { | ||
| 22 | + reject(error) | ||
| 23 | + }) | ||
| 24 | + }) | ||
| 25 | +} | ||
| 26 | + | ||
| 27 | +/** | ||
| 28 | + * 添加优惠类型 | ||
| 29 | + * @param {Object} data 优惠类型数据 | ||
| 30 | + * @returns {Promise} | ||
| 31 | + */ | ||
| 32 | +export function saveApplyRoomDiscountType(data) { | ||
| 33 | + return new Promise((resolve, reject) => { | ||
| 34 | + request({ | ||
| 35 | + url: '/applyRoomDiscount/saveApplyRoomDiscountType', | ||
| 36 | + method: 'post', | ||
| 37 | + data: { | ||
| 38 | + ...data, | ||
| 39 | + communityId: getCommunityId() | ||
| 40 | + } | ||
| 41 | + }).then(response => { | ||
| 42 | + const res = response.data | ||
| 43 | + resolve(res) | ||
| 44 | + }).catch(error => { | ||
| 45 | + reject(error) | ||
| 46 | + }) | ||
| 47 | + }) | ||
| 48 | +} | ||
| 49 | + | ||
| 50 | +/** | ||
| 51 | + * 更新优惠类型 | ||
| 52 | + * @param {Object} data 优惠类型数据 | ||
| 53 | + * @returns {Promise} | ||
| 54 | + */ | ||
| 55 | +export function updateApplyRoomDiscountType(data) { | ||
| 56 | + return new Promise((resolve, reject) => { | ||
| 57 | + request({ | ||
| 58 | + url: '/applyRoomDiscount/updateApplyRoomDiscountType', | ||
| 59 | + method: 'post', | ||
| 60 | + data: { | ||
| 61 | + ...data, | ||
| 62 | + communityId: getCommunityId() | ||
| 63 | + } | ||
| 64 | + }).then(response => { | ||
| 65 | + const res = response.data | ||
| 66 | + resolve(res) | ||
| 67 | + }).catch(error => { | ||
| 68 | + reject(error) | ||
| 69 | + }) | ||
| 70 | + }) | ||
| 71 | +} | ||
| 72 | + | ||
| 73 | +/** | ||
| 74 | + * 删除优惠类型 | ||
| 75 | + * @param {Object} data 删除参数 | ||
| 76 | + * @returns {Promise} | ||
| 77 | + */ | ||
| 78 | +export function deleteApplyRoomDiscountType(data) { | ||
| 79 | + return new Promise((resolve, reject) => { | ||
| 80 | + request({ | ||
| 81 | + url: '/applyRoomDiscount/deleteApplyRoomDiscountType', | ||
| 82 | + method: 'post', | ||
| 83 | + data: { | ||
| 84 | + ...data, | ||
| 85 | + communityId: getCommunityId() | ||
| 86 | + } | ||
| 87 | + }).then(response => { | ||
| 88 | + const res = response.data | ||
| 89 | + resolve(res) | ||
| 90 | + }).catch(error => { | ||
| 91 | + reject(error) | ||
| 92 | + }) | ||
| 93 | + }) | ||
| 94 | +} | ||
| 0 | \ No newline at end of file | 95 | \ No newline at end of file |
src/components/fee/addApplyRoomDiscount.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog :title="$t('applyRoomDiscount.add.title')" :visible.sync="visible" width="60%" @close="handleClose"> | ||
| 3 | + <el-form ref="form" :model="form" :rules="rules" label-width="120px"> | ||
| 4 | + <el-form-item :label="$t('applyRoomDiscount.add.room')" prop="roomName"> | ||
| 5 | + <el-input v-model.trim="form.roomName" :placeholder="$t('applyRoomDiscount.add.roomPlaceholder')" | ||
| 6 | + @blur="queryRoom" /> | ||
| 7 | + </el-form-item> | ||
| 8 | + | ||
| 9 | + <el-form-item :label="$t('applyRoomDiscount.add.applyType')" prop="applyType"> | ||
| 10 | + <el-select v-model="form.applyType" :placeholder="$t('applyRoomDiscount.add.applyTypePlaceholder')" | ||
| 11 | + style="width:100%"> | ||
| 12 | + <el-option v-for="item in applyTypes" :key="item.applyType" :label="item.typeName" :value="item.applyType" /> | ||
| 13 | + </el-select> | ||
| 14 | + </el-form-item> | ||
| 15 | + | ||
| 16 | + <el-form-item :label="$t('applyRoomDiscount.add.feeItem')" prop="feeId"> | ||
| 17 | + <el-select v-model="form.feeId" :placeholder="$t('applyRoomDiscount.add.feeItemPlaceholder')" | ||
| 18 | + style="width:100%"> | ||
| 19 | + <el-option v-for="item in feeTypeCds" :key="item.feeId" | ||
| 20 | + :label="`${item.feeName}(${item.endTime}至${item.deadlineTime})`" :value="item.feeId" /> | ||
| 21 | + </el-select> | ||
| 22 | + </el-form-item> | ||
| 23 | + | ||
| 24 | + <el-form-item :label="$t('applyRoomDiscount.add.createUser')" prop="createUserName"> | ||
| 25 | + <el-input v-model.trim="form.createUserName" :placeholder="$t('applyRoomDiscount.add.createUserPlaceholder')" | ||
| 26 | + disabled /> | ||
| 27 | + </el-form-item> | ||
| 28 | + | ||
| 29 | + <el-form-item :label="$t('applyRoomDiscount.add.createUserTel')" prop="createUserTel"> | ||
| 30 | + <el-input v-model.trim="form.createUserTel" :placeholder="$t('applyRoomDiscount.add.createUserTelPlaceholder')" | ||
| 31 | + disabled /> | ||
| 32 | + </el-form-item> | ||
| 33 | + | ||
| 34 | + <el-form-item :label="$t('applyRoomDiscount.add.startTime')" prop="startTime"> | ||
| 35 | + <el-date-picker v-model="form.startTime" type="date" | ||
| 36 | + :placeholder="$t('applyRoomDiscount.add.startTimePlaceholder')" value-format="yyyy-MM-dd" style="width:100%" | ||
| 37 | + @change="validateDate" /> | ||
| 38 | + </el-form-item> | ||
| 39 | + | ||
| 40 | + <el-form-item :label="$t('applyRoomDiscount.add.endTime')" prop="endTime"> | ||
| 41 | + <el-date-picker v-model="form.endTime" type="date" :placeholder="$t('applyRoomDiscount.add.endTimePlaceholder')" | ||
| 42 | + value-format="yyyy-MM-dd" style="width:100%" @change="validateDate" /> | ||
| 43 | + </el-form-item> | ||
| 44 | + | ||
| 45 | + <el-form-item :label="$t('applyRoomDiscount.add.createRemark')" prop="createRemark"> | ||
| 46 | + <el-input v-model="form.createRemark" type="textarea" | ||
| 47 | + :placeholder="$t('applyRoomDiscount.add.createRemarkPlaceholder')" :rows="3" /> | ||
| 48 | + </el-form-item> | ||
| 49 | + | ||
| 50 | + <el-form-item :label="$t('applyRoomDiscount.add.images')"> | ||
| 51 | + <upload-image-url ref="uploadImage" :image-count="4" @change="handleImageChange" /> | ||
| 52 | + </el-form-item> | ||
| 53 | + </el-form> | ||
| 54 | + | ||
| 55 | + <div slot="footer" class="dialog-footer"> | ||
| 56 | + <el-button @click="visible = false"> | ||
| 57 | + {{ $t('common.cancel') }} | ||
| 58 | + </el-button> | ||
| 59 | + <el-button type="primary" @click="submitForm"> | ||
| 60 | + {{ $t('common.save') }} | ||
| 61 | + </el-button> | ||
| 62 | + </div> | ||
| 63 | + </el-dialog> | ||
| 64 | +</template> | ||
| 65 | + | ||
| 66 | +<script> | ||
| 67 | +import { queryApplyRoomDiscountType ,listRoomsWhereFeeSet} from '@/api/fee/applyRoomDiscountManageApi' | ||
| 68 | +import UploadImageUrl from '@/components/upload/UploadImageUrl' | ||
| 69 | + | ||
| 70 | +export default { | ||
| 71 | + name: 'AddApplyRoomDiscount', | ||
| 72 | + components: { | ||
| 73 | + UploadImageUrl | ||
| 74 | + }, | ||
| 75 | + data() { | ||
| 76 | + return { | ||
| 77 | + visible: false, | ||
| 78 | + form: { | ||
| 79 | + roomName: '', | ||
| 80 | + roomId: '', | ||
| 81 | + applyType: '', | ||
| 82 | + createUserName: '', | ||
| 83 | + createUserTel: '', | ||
| 84 | + startTime: '', | ||
| 85 | + endTime: '', | ||
| 86 | + createRemark: '', | ||
| 87 | + feeId: '', | ||
| 88 | + photos: [], | ||
| 89 | + communityId: '' | ||
| 90 | + }, | ||
| 91 | + applyTypes: [], | ||
| 92 | + feeTypeCds: [], | ||
| 93 | + rules: { | ||
| 94 | + roomName: [ | ||
| 95 | + { required: true, message: this.$t('applyRoomDiscount.validate.roomRequired'), trigger: 'blur' }, | ||
| 96 | + { max: 64, message: this.$t('applyRoomDiscount.validate.roomFormat'), trigger: 'blur' } | ||
| 97 | + ], | ||
| 98 | + applyType: [ | ||
| 99 | + { required: true, message: this.$t('applyRoomDiscount.validate.applyTypeRequired'), trigger: 'change' } | ||
| 100 | + ], | ||
| 101 | + feeId: [ | ||
| 102 | + { required: true, message: this.$t('applyRoomDiscount.validate.feeIdRequired'), trigger: 'change' } | ||
| 103 | + ], | ||
| 104 | + createUserName: [ | ||
| 105 | + { required: true, message: this.$t('applyRoomDiscount.validate.createUserRequired'), trigger: 'blur' }, | ||
| 106 | + { max: 64, message: this.$t('applyRoomDiscount.validate.createUserFormat'), trigger: 'blur' } | ||
| 107 | + ], | ||
| 108 | + createUserTel: [ | ||
| 109 | + { required: true, message: this.$t('applyRoomDiscount.validate.createUserTelRequired'), trigger: 'blur' }, | ||
| 110 | + { pattern: /^1[3-9]\d{9}$/, message: this.$t('applyRoomDiscount.validate.createUserTelFormat'), trigger: 'blur' } | ||
| 111 | + ], | ||
| 112 | + startTime: [ | ||
| 113 | + { required: true, message: this.$t('applyRoomDiscount.validate.startTimeRequired'), trigger: 'change' } | ||
| 114 | + ], | ||
| 115 | + endTime: [ | ||
| 116 | + { required: true, message: this.$t('applyRoomDiscount.validate.endTimeRequired'), trigger: 'change' } | ||
| 117 | + ], | ||
| 118 | + createRemark: [ | ||
| 119 | + { required: true, message: this.$t('applyRoomDiscount.validate.createRemarkRequired'), trigger: 'blur' }, | ||
| 120 | + { max: 512, message: this.$t('applyRoomDiscount.validate.createRemarkFormat'), trigger: 'blur' } | ||
| 121 | + ] | ||
| 122 | + } | ||
| 123 | + } | ||
| 124 | + }, | ||
| 125 | + methods: { | ||
| 126 | + open() { | ||
| 127 | + this.visible = true | ||
| 128 | + this.getApplyTypes() | ||
| 129 | + }, | ||
| 130 | + handleClose() { | ||
| 131 | + this.$refs.form.resetFields() | ||
| 132 | + this.$refs.uploadImage.clear() | ||
| 133 | + this.form = { | ||
| 134 | + roomName: '', | ||
| 135 | + roomId: '', | ||
| 136 | + applyType: '', | ||
| 137 | + createUserName: '', | ||
| 138 | + createUserTel: '', | ||
| 139 | + startTime: '', | ||
| 140 | + endTime: '', | ||
| 141 | + createRemark: '', | ||
| 142 | + feeId: '', | ||
| 143 | + photos: [], | ||
| 144 | + communityId: '' | ||
| 145 | + } | ||
| 146 | + }, | ||
| 147 | + async getApplyTypes() { | ||
| 148 | + try { | ||
| 149 | + const { data } = await queryApplyRoomDiscountType({ | ||
| 150 | + page: 1, | ||
| 151 | + row: 50, | ||
| 152 | + communityId: this.form.communityId | ||
| 153 | + }) | ||
| 154 | + this.applyTypes = data | ||
| 155 | + } catch (error) { | ||
| 156 | + console.error('获取申请类型失败:', error) | ||
| 157 | + } | ||
| 158 | + }, | ||
| 159 | + async queryRoom() { | ||
| 160 | + if (!this.form.roomName) return | ||
| 161 | + | ||
| 162 | + const parts = this.form.roomName.split('-') | ||
| 163 | + if (parts.length !== 3) { | ||
| 164 | + this.$message.error(this.$t('applyRoomDiscount.validate.roomFormat')) | ||
| 165 | + this.form.roomName = '' | ||
| 166 | + return | ||
| 167 | + } | ||
| 168 | + | ||
| 169 | + try { | ||
| 170 | + const params = { | ||
| 171 | + page: 1, | ||
| 172 | + row: 1, | ||
| 173 | + communityId: this.form.communityId, | ||
| 174 | + flag: 0, | ||
| 175 | + floorNum: parts[0].trim(), | ||
| 176 | + unitNum: parts[1].trim(), | ||
| 177 | + roomNum: parts[2].trim() | ||
| 178 | + } | ||
| 179 | + | ||
| 180 | + const { rooms } = await listRoomsWhereFeeSet(params) | ||
| 181 | + if (rooms.length === 0) { | ||
| 182 | + this.$message.error(this.$t('applyRoomDiscount.validate.roomNotFound')) | ||
| 183 | + this.form.roomName = '' | ||
| 184 | + return | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + const room = rooms[0] | ||
| 188 | + this.form.roomId = room.roomId | ||
| 189 | + this.form.createUserName = room.ownerName | ||
| 190 | + this.form.createUserTel = room.link | ||
| 191 | + this.queryRoomFees() | ||
| 192 | + } catch (error) { | ||
| 193 | + console.error('查询房屋失败:', error) | ||
| 194 | + } | ||
| 195 | + }, | ||
| 196 | + async queryRoomFees() { | ||
| 197 | + try { | ||
| 198 | + const params = { | ||
| 199 | + page: 1, | ||
| 200 | + row: 50, | ||
| 201 | + communityId: this.form.communityId, | ||
| 202 | + payerObjId: this.form.roomId, | ||
| 203 | + state: '2008001' | ||
| 204 | + } | ||
| 205 | + | ||
| 206 | + const { data } = await this.$api.fee.listFee(params) | ||
| 207 | + this.feeTypeCds = data.fees | ||
| 208 | + } catch (error) { | ||
| 209 | + console.error('查询费用项失败:', error) | ||
| 210 | + } | ||
| 211 | + }, | ||
| 212 | + validateDate() { | ||
| 213 | + if (this.form.startTime && this.form.endTime) { | ||
| 214 | + const start = new Date(this.form.startTime) | ||
| 215 | + const end = new Date(this.form.endTime) | ||
| 216 | + if (start >= end) { | ||
| 217 | + this.$message.error(this.$t('applyRoomDiscount.validate.dateInvalid')) | ||
| 218 | + this.form.endTime = '' | ||
| 219 | + } | ||
| 220 | + } | ||
| 221 | + }, | ||
| 222 | + handleImageChange(photos) { | ||
| 223 | + this.form.photos = photos | ||
| 224 | + }, | ||
| 225 | + submitForm() { | ||
| 226 | + this.$refs.form.validate(valid => { | ||
| 227 | + if (valid) { | ||
| 228 | + this.saveApplyRoomDiscount() | ||
| 229 | + } | ||
| 230 | + }) | ||
| 231 | + }, | ||
| 232 | + async saveApplyRoomDiscount() { | ||
| 233 | + try { | ||
| 234 | + this.form.communityId = this.$store.getters.communityId | ||
| 235 | + await this.$api.applyRoomDiscount.saveApplyRoomDiscount(this.form) | ||
| 236 | + this.$message.success(this.$t('applyRoomDiscount.message.saveSuccess')) | ||
| 237 | + this.visible = false | ||
| 238 | + this.$emit('success') | ||
| 239 | + } catch (error) { | ||
| 240 | + this.$message.error(error.message || this.$t('applyRoomDiscount.message.saveFailed')) | ||
| 241 | + } | ||
| 242 | + } | ||
| 243 | + } | ||
| 244 | +} | ||
| 245 | +</script> | ||
| 246 | + | ||
| 247 | +<style lang="scss" scoped> | ||
| 248 | +.el-form-item { | ||
| 249 | + margin-bottom: 22px; | ||
| 250 | +} | ||
| 251 | +</style> | ||
| 0 | \ No newline at end of file | 252 | \ No newline at end of file |
src/components/fee/addApplyRoomDiscountType.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('discountType.add.title')" | ||
| 4 | + :visible.sync="visible" | ||
| 5 | + width="50%" | ||
| 6 | + @close="handleClose" | ||
| 7 | + > | ||
| 8 | + <el-form | ||
| 9 | + ref="form" | ||
| 10 | + :model="formData" | ||
| 11 | + :rules="rules" | ||
| 12 | + label-width="120px" | ||
| 13 | + > | ||
| 14 | + <el-form-item | ||
| 15 | + :label="$t('discountType.form.typeName')" | ||
| 16 | + prop="typeName" | ||
| 17 | + > | ||
| 18 | + <el-input | ||
| 19 | + v-model="formData.typeName" | ||
| 20 | + :placeholder="$t('discountType.form.typeNamePlaceholder')" | ||
| 21 | + /> | ||
| 22 | + </el-form-item> | ||
| 23 | + <el-form-item | ||
| 24 | + :label="$t('discountType.form.typeDesc')" | ||
| 25 | + prop="typeDesc" | ||
| 26 | + > | ||
| 27 | + <el-input | ||
| 28 | + v-model="formData.typeDesc" | ||
| 29 | + type="textarea" | ||
| 30 | + :placeholder="$t('discountType.form.typeDescPlaceholder')" | ||
| 31 | + :rows="3" | ||
| 32 | + /> | ||
| 33 | + </el-form-item> | ||
| 34 | + </el-form> | ||
| 35 | + | ||
| 36 | + <div slot="footer" class="dialog-footer"> | ||
| 37 | + <el-button @click="visible = false"> | ||
| 38 | + {{ $t('common.cancel') }} | ||
| 39 | + </el-button> | ||
| 40 | + <el-button type="primary" @click="handleSubmit"> | ||
| 41 | + {{ $t('common.confirm') }} | ||
| 42 | + </el-button> | ||
| 43 | + </div> | ||
| 44 | + </el-dialog> | ||
| 45 | +</template> | ||
| 46 | + | ||
| 47 | +<script> | ||
| 48 | +import { saveApplyRoomDiscountType } from '@/api/fee/discountTypeApi' | ||
| 49 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 50 | + | ||
| 51 | +export default { | ||
| 52 | + name: 'AddApplyRoomDiscountType', | ||
| 53 | + data() { | ||
| 54 | + return { | ||
| 55 | + visible: false, | ||
| 56 | + formData: { | ||
| 57 | + typeName: '', | ||
| 58 | + typeDesc: '', | ||
| 59 | + communityId: '' | ||
| 60 | + }, | ||
| 61 | + rules: { | ||
| 62 | + typeName: [ | ||
| 63 | + { required: true, message: this.$t('discountType.validate.typeNameRequired'), trigger: 'blur' }, | ||
| 64 | + { max: 64, message: this.$t('discountType.validate.typeNameMaxLength'), trigger: 'blur' } | ||
| 65 | + ], | ||
| 66 | + typeDesc: [ | ||
| 67 | + { max: 512, message: this.$t('discountType.validate.typeDescMaxLength'), trigger: 'blur' } | ||
| 68 | + ] | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | + }, | ||
| 72 | + methods: { | ||
| 73 | + open() { | ||
| 74 | + this.visible = true | ||
| 75 | + this.$nextTick(() => { | ||
| 76 | + this.$refs.form && this.$refs.form.resetFields() | ||
| 77 | + }) | ||
| 78 | + }, | ||
| 79 | + handleClose() { | ||
| 80 | + this.$refs.form.resetFields() | ||
| 81 | + }, | ||
| 82 | + handleSubmit() { | ||
| 83 | + this.$refs.form.validate(async valid => { | ||
| 84 | + if (valid) { | ||
| 85 | + try { | ||
| 86 | + this.formData.communityId = getCommunityId() | ||
| 87 | + await saveApplyRoomDiscountType(this.formData) | ||
| 88 | + this.$message.success(this.$t('discountType.add.success')) | ||
| 89 | + this.visible = false | ||
| 90 | + this.$emit('success') | ||
| 91 | + } catch (error) { | ||
| 92 | + console.error(error) | ||
| 93 | + } | ||
| 94 | + } | ||
| 95 | + }) | ||
| 96 | + } | ||
| 97 | + } | ||
| 98 | +} | ||
| 99 | +</script> | ||
| 0 | \ No newline at end of file | 100 | \ No newline at end of file |
src/components/fee/deleteApplyRoomDiscount.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('applyRoomDiscount.delete.title')" | ||
| 4 | + :visible.sync="visible" | ||
| 5 | + width="500px" | ||
| 6 | + @close="handleClose" | ||
| 7 | + > | ||
| 8 | + <div class="delete-content"> | ||
| 9 | + <p>{{ $t('applyRoomDiscount.delete.confirmText') }}</p> | ||
| 10 | + </div> | ||
| 11 | + | ||
| 12 | + <div slot="footer" class="dialog-footer"> | ||
| 13 | + <el-button @click="visible = false"> | ||
| 14 | + {{ $t('common.cancel') }} | ||
| 15 | + </el-button> | ||
| 16 | + <el-button | ||
| 17 | + type="primary" | ||
| 18 | + @click="confirmDelete" | ||
| 19 | + :loading="loading" | ||
| 20 | + > | ||
| 21 | + {{ $t('common.confirm') }} | ||
| 22 | + </el-button> | ||
| 23 | + </div> | ||
| 24 | + </el-dialog> | ||
| 25 | +</template> | ||
| 26 | + | ||
| 27 | +<script> | ||
| 28 | +import { deleteApplyRoomDiscount } from '@/api/fee/applyRoomDiscountManageApi' | ||
| 29 | + | ||
| 30 | +export default { | ||
| 31 | + name: 'DeleteApplyRoomDiscount', | ||
| 32 | + data() { | ||
| 33 | + return { | ||
| 34 | + visible: false, | ||
| 35 | + loading: false, | ||
| 36 | + form: { | ||
| 37 | + ardId: '', | ||
| 38 | + communityId: '' | ||
| 39 | + } | ||
| 40 | + } | ||
| 41 | + }, | ||
| 42 | + methods: { | ||
| 43 | + open(data) { | ||
| 44 | + this.form = { | ||
| 45 | + ardId: data.ardId, | ||
| 46 | + communityId: this.$store.getters.communityId | ||
| 47 | + } | ||
| 48 | + this.visible = true | ||
| 49 | + }, | ||
| 50 | + handleClose() { | ||
| 51 | + this.form = { | ||
| 52 | + ardId: '', | ||
| 53 | + communityId: '' | ||
| 54 | + } | ||
| 55 | + this.loading = false | ||
| 56 | + }, | ||
| 57 | + async confirmDelete() { | ||
| 58 | + try { | ||
| 59 | + this.loading = true | ||
| 60 | + await deleteApplyRoomDiscount(this.form) | ||
| 61 | + this.$message.success(this.$t('applyRoomDiscount.message.deleteSuccess')) | ||
| 62 | + this.visible = false | ||
| 63 | + this.$emit('success') | ||
| 64 | + } catch (error) { | ||
| 65 | + this.$message.error(error.message || this.$t('applyRoomDiscount.message.deleteFailed')) | ||
| 66 | + } finally { | ||
| 67 | + this.loading = false | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | +} | ||
| 72 | +</script> | ||
| 73 | + | ||
| 74 | +<style lang="scss" scoped> | ||
| 75 | +.delete-content { | ||
| 76 | + text-align: center; | ||
| 77 | + font-size: 16px; | ||
| 78 | + padding: 20px 0; | ||
| 79 | +} | ||
| 80 | + | ||
| 81 | +.dialog-footer { | ||
| 82 | + text-align: right; | ||
| 83 | +} | ||
| 84 | +</style> | ||
| 0 | \ No newline at end of file | 85 | \ No newline at end of file |
src/components/fee/deleteApplyRoomDiscountType.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('discountType.delete.title')" | ||
| 4 | + :visible.sync="visible" | ||
| 5 | + width="30%" | ||
| 6 | + @close="handleClose" | ||
| 7 | + > | ||
| 8 | + <div class="delete-content"> | ||
| 9 | + <p>{{ $t('discountType.delete.confirmText') }}</p> | ||
| 10 | + <p class="delete-item"> | ||
| 11 | + <span class="label">{{ $t('discountType.table.applyType') }}:</span> | ||
| 12 | + <span>{{ formData.applyType }}</span> | ||
| 13 | + </p> | ||
| 14 | + <p class="delete-item"> | ||
| 15 | + <span class="label">{{ $t('discountType.table.typeName') }}:</span> | ||
| 16 | + <span>{{ formData.typeName }}</span> | ||
| 17 | + </p> | ||
| 18 | + </div> | ||
| 19 | + | ||
| 20 | + <div slot="footer" class="dialog-footer"> | ||
| 21 | + <el-button @click="visible = false"> | ||
| 22 | + {{ $t('common.cancel') }} | ||
| 23 | + </el-button> | ||
| 24 | + <el-button type="danger" @click="handleConfirm"> | ||
| 25 | + {{ $t('common.confirm') }} | ||
| 26 | + </el-button> | ||
| 27 | + </div> | ||
| 28 | + </el-dialog> | ||
| 29 | +</template> | ||
| 30 | + | ||
| 31 | +<script> | ||
| 32 | +import { deleteApplyRoomDiscountType } from '@/api/fee/discountTypeApi' | ||
| 33 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 34 | + | ||
| 35 | +export default { | ||
| 36 | + name: 'DeleteApplyRoomDiscountType', | ||
| 37 | + data() { | ||
| 38 | + return { | ||
| 39 | + visible: false, | ||
| 40 | + formData: { | ||
| 41 | + applyType: '', | ||
| 42 | + typeName: '', | ||
| 43 | + communityId: '' | ||
| 44 | + } | ||
| 45 | + } | ||
| 46 | + }, | ||
| 47 | + methods: { | ||
| 48 | + open(row) { | ||
| 49 | + this.visible = true | ||
| 50 | + this.formData = { ...row } | ||
| 51 | + }, | ||
| 52 | + handleClose() { | ||
| 53 | + this.formData = { | ||
| 54 | + applyType: '', | ||
| 55 | + typeName: '', | ||
| 56 | + communityId: '' | ||
| 57 | + } | ||
| 58 | + }, | ||
| 59 | + async handleConfirm() { | ||
| 60 | + try { | ||
| 61 | + this.formData.communityId = getCommunityId() | ||
| 62 | + await deleteApplyRoomDiscountType(this.formData) | ||
| 63 | + this.$message.success(this.$t('discountType.delete.success')) | ||
| 64 | + this.visible = false | ||
| 65 | + this.$emit('success') | ||
| 66 | + } catch (error) { | ||
| 67 | + console.error(error) | ||
| 68 | + } | ||
| 69 | + } | ||
| 70 | + } | ||
| 71 | +} | ||
| 72 | +</script> | ||
| 73 | + | ||
| 74 | +<style scoped> | ||
| 75 | +.delete-content { | ||
| 76 | + padding: 0 20px; | ||
| 77 | +} | ||
| 78 | +.delete-item { | ||
| 79 | + margin: 10px 0; | ||
| 80 | +} | ||
| 81 | +.label { | ||
| 82 | + font-weight: bold; | ||
| 83 | + margin-right: 10px; | ||
| 84 | +} | ||
| 85 | +</style> | ||
| 0 | \ No newline at end of file | 86 | \ No newline at end of file |
src/components/fee/editApplyRoomDiscount.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog :title="$t('applyRoomDiscount.edit.title')" :visible.sync="visible" width="60%" @close="handleClose"> | ||
| 3 | + <el-form ref="form" :model="form" :rules="rules" label-width="120px"> | ||
| 4 | + <el-form-item :label="$t('applyRoomDiscount.edit.startTime')" prop="startTime"> | ||
| 5 | + <el-date-picker v-model="form.startTime" type="datetime" | ||
| 6 | + :placeholder="$t('applyRoomDiscount.edit.startTimePlaceholder')" value-format="yyyy-MM-dd HH:mm:ss" | ||
| 7 | + style="width:100%" @change="validateDate" /> | ||
| 8 | + </el-form-item> | ||
| 9 | + | ||
| 10 | + <el-form-item :label="$t('applyRoomDiscount.edit.endTime')" prop="endTime"> | ||
| 11 | + <el-date-picker v-model="form.endTime" type="datetime" | ||
| 12 | + :placeholder="$t('applyRoomDiscount.edit.endTimePlaceholder')" value-format="yyyy-MM-dd HH:mm:ss" | ||
| 13 | + style="width:100%" @change="validateDate" /> | ||
| 14 | + </el-form-item> | ||
| 15 | + | ||
| 16 | + <el-form-item :label="$t('applyRoomDiscount.edit.state')" prop="state"> | ||
| 17 | + <el-select v-model="form.state" :placeholder="$t('applyRoomDiscount.edit.statePlaceholder')" style="width:100%"> | ||
| 18 | + <el-option :label="$t('applyRoomDiscount.status.checkPass')" value="2" /> | ||
| 19 | + <el-option :label="$t('applyRoomDiscount.status.checkReject')" value="3" /> | ||
| 20 | + </el-select> | ||
| 21 | + </el-form-item> | ||
| 22 | + | ||
| 23 | + <el-form-item :label="$t('applyRoomDiscount.edit.createRemark')"> | ||
| 24 | + <el-input v-model="form.createRemark" type="textarea" :rows="3" disabled /> | ||
| 25 | + </el-form-item> | ||
| 26 | + | ||
| 27 | + <el-form-item :label="$t('applyRoomDiscount.edit.checkRemark')" prop="checkRemark"> | ||
| 28 | + <el-input v-model="form.checkRemark" type="textarea" | ||
| 29 | + :placeholder="$t('applyRoomDiscount.edit.checkRemarkPlaceholder')" :rows="3" /> | ||
| 30 | + </el-form-item> | ||
| 31 | + | ||
| 32 | + <el-form-item :label="$t('applyRoomDiscount.edit.images')"> | ||
| 33 | + <upload-image-url ref="uploadImage" :image-count="4" @change="handleImageChange" /> | ||
| 34 | + </el-form-item> | ||
| 35 | + </el-form> | ||
| 36 | + | ||
| 37 | + <div slot="footer" class="dialog-footer"> | ||
| 38 | + <el-button @click="visible = false"> | ||
| 39 | + {{ $t('common.cancel') }} | ||
| 40 | + </el-button> | ||
| 41 | + <el-button type="primary" @click="submitForm"> | ||
| 42 | + {{ $t('common.save') }} | ||
| 43 | + </el-button> | ||
| 44 | + </div> | ||
| 45 | + </el-dialog> | ||
| 46 | +</template> | ||
| 47 | + | ||
| 48 | +<script> | ||
| 49 | +import { updateApplyRoomDiscount } from '@/api/fee/applyRoomDiscountManageApi' | ||
| 50 | +import UploadImageUrl from '@/components/upload/UploadImageUrl' | ||
| 51 | + | ||
| 52 | +export default { | ||
| 53 | + name: 'EditApplyRoomDiscount', | ||
| 54 | + components: { | ||
| 55 | + UploadImageUrl | ||
| 56 | + }, | ||
| 57 | + data() { | ||
| 58 | + return { | ||
| 59 | + visible: false, | ||
| 60 | + form: { | ||
| 61 | + ardId: '', | ||
| 62 | + startTime: '', | ||
| 63 | + endTime: '', | ||
| 64 | + checkRemark: '', | ||
| 65 | + createRemark: '', | ||
| 66 | + state: '', | ||
| 67 | + photos: [], | ||
| 68 | + urls: [], | ||
| 69 | + communityId: '' | ||
| 70 | + }, | ||
| 71 | + rules: { | ||
| 72 | + startTime: [ | ||
| 73 | + { required: true, message: this.$t('applyRoomDiscount.validate.startTimeRequired'), trigger: 'change' } | ||
| 74 | + ], | ||
| 75 | + endTime: [ | ||
| 76 | + { required: true, message: this.$t('applyRoomDiscount.validate.endTimeRequired'), trigger: 'change' } | ||
| 77 | + ], | ||
| 78 | + state: [ | ||
| 79 | + { required: true, message: this.$t('applyRoomDiscount.validate.stateRequired'), trigger: 'change' } | ||
| 80 | + ], | ||
| 81 | + checkRemark: [ | ||
| 82 | + { required: true, message: this.$t('applyRoomDiscount.validate.checkRemarkRequired'), trigger: 'blur' }, | ||
| 83 | + { max: 512, message: this.$t('applyRoomDiscount.validate.checkRemarkFormat'), trigger: 'blur' } | ||
| 84 | + ] | ||
| 85 | + } | ||
| 86 | + } | ||
| 87 | + }, | ||
| 88 | + methods: { | ||
| 89 | + open(data) { | ||
| 90 | + this.form = { | ||
| 91 | + ...this.form, | ||
| 92 | + ...data, | ||
| 93 | + communityId: this.$store.getters.communityId | ||
| 94 | + } | ||
| 95 | + this.$nextTick(() => { | ||
| 96 | + if (this.$refs.uploadImage) { | ||
| 97 | + this.$refs.uploadImage.setImages(this.form.urls || []) | ||
| 98 | + } | ||
| 99 | + }) | ||
| 100 | + this.visible = true | ||
| 101 | + }, | ||
| 102 | + handleClose() { | ||
| 103 | + this.$refs.form.resetFields() | ||
| 104 | + if (this.$refs.uploadImage) { | ||
| 105 | + this.$refs.uploadImage.clear() | ||
| 106 | + } | ||
| 107 | + this.form = { | ||
| 108 | + ardId: '', | ||
| 109 | + startTime: '', | ||
| 110 | + endTime: '', | ||
| 111 | + checkRemark: '', | ||
| 112 | + createRemark: '', | ||
| 113 | + state: '', | ||
| 114 | + photos: [], | ||
| 115 | + urls: [], | ||
| 116 | + communityId: '' | ||
| 117 | + } | ||
| 118 | + }, | ||
| 119 | + validateDate() { | ||
| 120 | + if (this.form.startTime && this.form.endTime) { | ||
| 121 | + const start = new Date(this.form.startTime) | ||
| 122 | + const end = new Date(this.form.endTime) | ||
| 123 | + if (start >= end) { | ||
| 124 | + this.$message.error(this.$t('applyRoomDiscount.validate.dateInvalid')) | ||
| 125 | + this.form.endTime = '' | ||
| 126 | + } | ||
| 127 | + } | ||
| 128 | + }, | ||
| 129 | + handleImageChange(photos) { | ||
| 130 | + this.form.photos = photos | ||
| 131 | + }, | ||
| 132 | + submitForm() { | ||
| 133 | + this.$refs.form.validate(valid => { | ||
| 134 | + if (valid) { | ||
| 135 | + this.updateApplyRoomDiscount() | ||
| 136 | + } | ||
| 137 | + }) | ||
| 138 | + }, | ||
| 139 | + async updateApplyRoomDiscount() { | ||
| 140 | + try { | ||
| 141 | + await updateApplyRoomDiscount(this.form) | ||
| 142 | + this.$message.success(this.$t('applyRoomDiscount.message.updateSuccess')) | ||
| 143 | + this.visible = false | ||
| 144 | + this.$emit('success') | ||
| 145 | + } catch (error) { | ||
| 146 | + this.$message.error(error.message || this.$t('applyRoomDiscount.message.updateFailed')) | ||
| 147 | + } | ||
| 148 | + } | ||
| 149 | + } | ||
| 150 | +} | ||
| 151 | +</script> | ||
| 152 | + | ||
| 153 | +<style lang="scss" scoped> | ||
| 154 | +.el-form-item { | ||
| 155 | + margin-bottom: 22px; | ||
| 156 | +} | ||
| 157 | +</style> | ||
| 0 | \ No newline at end of file | 158 | \ No newline at end of file |
src/components/fee/editApplyRoomDiscountRecord.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('applyRoomDiscount.editRecord.title')" | ||
| 4 | + :visible.sync="visible" | ||
| 5 | + width="60%" | ||
| 6 | + @close="handleClose" | ||
| 7 | + > | ||
| 8 | + <el-form | ||
| 9 | + ref="form" | ||
| 10 | + :model="form" | ||
| 11 | + :rules="rules" | ||
| 12 | + label-width="120px" | ||
| 13 | + > | ||
| 14 | + <el-form-item | ||
| 15 | + :label="$t('applyRoomDiscount.editRecord.ardId')" | ||
| 16 | + prop="ardId" | ||
| 17 | + > | ||
| 18 | + <el-input | ||
| 19 | + v-model="form.ardId" | ||
| 20 | + disabled | ||
| 21 | + /> | ||
| 22 | + </el-form-item> | ||
| 23 | + | ||
| 24 | + <el-form-item | ||
| 25 | + :label="$t('applyRoomDiscount.editRecord.roomName')" | ||
| 26 | + prop="roomName" | ||
| 27 | + > | ||
| 28 | + <el-input | ||
| 29 | + v-model="form.roomName" | ||
| 30 | + disabled | ||
| 31 | + /> | ||
| 32 | + </el-form-item> | ||
| 33 | + | ||
| 34 | + <el-form-item | ||
| 35 | + :label="$t('applyRoomDiscount.editRecord.applyTypeName')" | ||
| 36 | + prop="applyTypeName" | ||
| 37 | + > | ||
| 38 | + <el-input | ||
| 39 | + v-model="form.applyTypeName" | ||
| 40 | + disabled | ||
| 41 | + /> | ||
| 42 | + </el-form-item> | ||
| 43 | + | ||
| 44 | + <el-form-item | ||
| 45 | + :label="$t('applyRoomDiscount.editRecord.createUserName')" | ||
| 46 | + prop="createUserName" | ||
| 47 | + > | ||
| 48 | + <el-input | ||
| 49 | + v-model="form.createUserName" | ||
| 50 | + disabled | ||
| 51 | + /> | ||
| 52 | + </el-form-item> | ||
| 53 | + | ||
| 54 | + <el-form-item | ||
| 55 | + :label="$t('applyRoomDiscount.editRecord.createUserTel')" | ||
| 56 | + prop="createUserTel" | ||
| 57 | + > | ||
| 58 | + <el-input | ||
| 59 | + v-model="form.createUserTel" | ||
| 60 | + disabled | ||
| 61 | + /> | ||
| 62 | + </el-form-item> | ||
| 63 | + | ||
| 64 | + <el-form-item | ||
| 65 | + :label="$t('applyRoomDiscount.editRecord.startTime')" | ||
| 66 | + prop="startTime" | ||
| 67 | + > | ||
| 68 | + <el-date-picker | ||
| 69 | + v-model="form.startTime" | ||
| 70 | + type="datetime" | ||
| 71 | + :placeholder="$t('applyRoomDiscount.editRecord.startTimePlaceholder')" | ||
| 72 | + value-format="yyyy-MM-dd HH:mm:ss" | ||
| 73 | + style="width:100%" | ||
| 74 | + @change="validateDate" | ||
| 75 | + /> | ||
| 76 | + </el-form-item> | ||
| 77 | + | ||
| 78 | + <el-form-item | ||
| 79 | + :label="$t('applyRoomDiscount.editRecord.endTime')" | ||
| 80 | + prop="endTime" | ||
| 81 | + > | ||
| 82 | + <el-date-picker | ||
| 83 | + v-model="form.endTime" | ||
| 84 | + type="datetime" | ||
| 85 | + :placeholder="$t('applyRoomDiscount.editRecord.endTimePlaceholder')" | ||
| 86 | + value-format="yyyy-MM-dd HH:mm:ss" | ||
| 87 | + style="width:100%" | ||
| 88 | + @change="validateDate" | ||
| 89 | + /> | ||
| 90 | + </el-form-item> | ||
| 91 | + | ||
| 92 | + <el-form-item | ||
| 93 | + :label="$t('applyRoomDiscount.editRecord.stateName')" | ||
| 94 | + prop="stateName" | ||
| 95 | + > | ||
| 96 | + <el-input | ||
| 97 | + v-model="form.stateName" | ||
| 98 | + disabled | ||
| 99 | + /> | ||
| 100 | + </el-form-item> | ||
| 101 | + </el-form> | ||
| 102 | + | ||
| 103 | + <div slot="footer" class="dialog-footer"> | ||
| 104 | + <el-button @click="visible = false"> | ||
| 105 | + {{ $t('common.cancel') }} | ||
| 106 | + </el-button> | ||
| 107 | + <el-button type="primary" @click="submitForm"> | ||
| 108 | + {{ $t('common.save') }} | ||
| 109 | + </el-button> | ||
| 110 | + </div> | ||
| 111 | + </el-dialog> | ||
| 112 | +</template> | ||
| 113 | + | ||
| 114 | +<script> | ||
| 115 | +import { updateApplyRoomDiscount } from '@/api/fee/applyRoomDiscountManageApi' | ||
| 116 | + | ||
| 117 | +export default { | ||
| 118 | + name: 'EditApplyRoomDiscountRecord', | ||
| 119 | + data() { | ||
| 120 | + return { | ||
| 121 | + visible: false, | ||
| 122 | + form: { | ||
| 123 | + ardId: '', | ||
| 124 | + roomName: '', | ||
| 125 | + roomId: '', | ||
| 126 | + discountId: '', | ||
| 127 | + discountName: '', | ||
| 128 | + applyTypeName: '', | ||
| 129 | + createUserName: '', | ||
| 130 | + createUserTel: '', | ||
| 131 | + startTime: '', | ||
| 132 | + endTime: '', | ||
| 133 | + stateName: '', | ||
| 134 | + state: '', | ||
| 135 | + communityId: '' | ||
| 136 | + }, | ||
| 137 | + rules: { | ||
| 138 | + ardId: [ | ||
| 139 | + { required: true, message: this.$t('applyRoomDiscount.validate.ardIdRequired'), trigger: 'blur' } | ||
| 140 | + ], | ||
| 141 | + roomName: [ | ||
| 142 | + { required: true, message: this.$t('applyRoomDiscount.validate.roomRequired'), trigger: 'blur' } | ||
| 143 | + ], | ||
| 144 | + applyTypeName: [ | ||
| 145 | + { required: true, message: this.$t('applyRoomDiscount.validate.applyTypeRequired'), trigger: 'blur' } | ||
| 146 | + ], | ||
| 147 | + createUserName: [ | ||
| 148 | + { required: true, message: this.$t('applyRoomDiscount.validate.createUserRequired'), trigger: 'blur' } | ||
| 149 | + ], | ||
| 150 | + startTime: [ | ||
| 151 | + { required: true, message: this.$t('applyRoomDiscount.validate.startTimeRequired'), trigger: 'change' } | ||
| 152 | + ], | ||
| 153 | + endTime: [ | ||
| 154 | + { required: true, message: this.$t('applyRoomDiscount.validate.endTimeRequired'), trigger: 'change' } | ||
| 155 | + ], | ||
| 156 | + stateName: [ | ||
| 157 | + { required: true, message: this.$t('applyRoomDiscount.validate.stateRequired'), trigger: 'blur' } | ||
| 158 | + ] | ||
| 159 | + } | ||
| 160 | + } | ||
| 161 | + }, | ||
| 162 | + methods: { | ||
| 163 | + open(data) { | ||
| 164 | + this.form = { | ||
| 165 | + ...this.form, | ||
| 166 | + ...data, | ||
| 167 | + communityId: this.$store.getters.communityId | ||
| 168 | + } | ||
| 169 | + this.visible = true | ||
| 170 | + }, | ||
| 171 | + handleClose() { | ||
| 172 | + this.$refs.form.resetFields() | ||
| 173 | + this.form = { | ||
| 174 | + ardId: '', | ||
| 175 | + roomName: '', | ||
| 176 | + roomId: '', | ||
| 177 | + discountId: '', | ||
| 178 | + discountName: '', | ||
| 179 | + applyTypeName: '', | ||
| 180 | + createUserName: '', | ||
| 181 | + createUserTel: '', | ||
| 182 | + startTime: '', | ||
| 183 | + endTime: '', | ||
| 184 | + stateName: '', | ||
| 185 | + state: '', | ||
| 186 | + communityId: '' | ||
| 187 | + } | ||
| 188 | + }, | ||
| 189 | + validateDate() { | ||
| 190 | + if (this.form.startTime && this.form.endTime) { | ||
| 191 | + const start = new Date(this.form.startTime) | ||
| 192 | + const end = new Date(this.form.endTime) | ||
| 193 | + if (start >= end) { | ||
| 194 | + this.$message.error(this.$t('applyRoomDiscount.validate.dateInvalid')) | ||
| 195 | + this.form.endTime = '' | ||
| 196 | + } | ||
| 197 | + } | ||
| 198 | + }, | ||
| 199 | + submitForm() { | ||
| 200 | + this.$refs.form.validate(valid => { | ||
| 201 | + if (valid) { | ||
| 202 | + this.updateApplyRoomDiscount() | ||
| 203 | + } | ||
| 204 | + }) | ||
| 205 | + }, | ||
| 206 | + async updateApplyRoomDiscount() { | ||
| 207 | + try { | ||
| 208 | + await updateApplyRoomDiscount(this.form) | ||
| 209 | + this.$message.success(this.$t('applyRoomDiscount.message.updateSuccess')) | ||
| 210 | + this.visible = false | ||
| 211 | + this.$emit('success') | ||
| 212 | + } catch (error) { | ||
| 213 | + this.$message.error(error.message || this.$t('applyRoomDiscount.message.updateFailed')) | ||
| 214 | + } | ||
| 215 | + } | ||
| 216 | + } | ||
| 217 | +} | ||
| 218 | +</script> | ||
| 219 | + | ||
| 220 | +<style lang="scss" scoped> | ||
| 221 | +.el-form-item { | ||
| 222 | + margin-bottom: 22px; | ||
| 223 | +} | ||
| 224 | +</style> | ||
| 0 | \ No newline at end of file | 225 | \ No newline at end of file |
src/components/fee/editApplyRoomDiscountType.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog | ||
| 3 | + :title="$t('discountType.edit.title')" | ||
| 4 | + :visible.sync="visible" | ||
| 5 | + width="50%" | ||
| 6 | + @close="handleClose" | ||
| 7 | + > | ||
| 8 | + <el-form | ||
| 9 | + ref="form" | ||
| 10 | + :model="formData" | ||
| 11 | + :rules="rules" | ||
| 12 | + label-width="120px" | ||
| 13 | + > | ||
| 14 | + <el-form-item | ||
| 15 | + :label="$t('discountType.form.applyType')" | ||
| 16 | + prop="applyType" | ||
| 17 | + > | ||
| 18 | + <el-input | ||
| 19 | + v-model="formData.applyType" | ||
| 20 | + disabled | ||
| 21 | + /> | ||
| 22 | + </el-form-item> | ||
| 23 | + <el-form-item | ||
| 24 | + :label="$t('discountType.form.typeName')" | ||
| 25 | + prop="typeName" | ||
| 26 | + > | ||
| 27 | + <el-input | ||
| 28 | + v-model="formData.typeName" | ||
| 29 | + :placeholder="$t('discountType.form.typeNamePlaceholder')" | ||
| 30 | + /> | ||
| 31 | + </el-form-item> | ||
| 32 | + <el-form-item | ||
| 33 | + :label="$t('discountType.form.typeDesc')" | ||
| 34 | + prop="typeDesc" | ||
| 35 | + > | ||
| 36 | + <el-input | ||
| 37 | + v-model="formData.typeDesc" | ||
| 38 | + type="textarea" | ||
| 39 | + :placeholder="$t('discountType.form.typeDescPlaceholder')" | ||
| 40 | + :rows="3" | ||
| 41 | + /> | ||
| 42 | + </el-form-item> | ||
| 43 | + </el-form> | ||
| 44 | + | ||
| 45 | + <div slot="footer" class="dialog-footer"> | ||
| 46 | + <el-button @click="visible = false"> | ||
| 47 | + {{ $t('common.cancel') }} | ||
| 48 | + </el-button> | ||
| 49 | + <el-button type="primary" @click="handleSubmit"> | ||
| 50 | + {{ $t('common.confirm') }} | ||
| 51 | + </el-button> | ||
| 52 | + </div> | ||
| 53 | + </el-dialog> | ||
| 54 | +</template> | ||
| 55 | + | ||
| 56 | +<script> | ||
| 57 | +import { updateApplyRoomDiscountType } from '@/api/fee/discountTypeApi' | ||
| 58 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 59 | + | ||
| 60 | +export default { | ||
| 61 | + name: 'EditApplyRoomDiscountType', | ||
| 62 | + data() { | ||
| 63 | + return { | ||
| 64 | + visible: false, | ||
| 65 | + formData: { | ||
| 66 | + applyType: '', | ||
| 67 | + typeName: '', | ||
| 68 | + typeDesc: '', | ||
| 69 | + communityId: '' | ||
| 70 | + }, | ||
| 71 | + rules: { | ||
| 72 | + applyType: [ | ||
| 73 | + { required: true, message: this.$t('discountType.validate.applyTypeRequired'), trigger: 'blur' } | ||
| 74 | + ], | ||
| 75 | + typeName: [ | ||
| 76 | + { required: true, message: this.$t('discountType.validate.typeNameRequired'), trigger: 'blur' }, | ||
| 77 | + { max: 64, message: this.$t('discountType.validate.typeNameMaxLength'), trigger: 'blur' } | ||
| 78 | + ], | ||
| 79 | + typeDesc: [ | ||
| 80 | + { max: 512, message: this.$t('discountType.validate.typeDescMaxLength'), trigger: 'blur' } | ||
| 81 | + ] | ||
| 82 | + } | ||
| 83 | + } | ||
| 84 | + }, | ||
| 85 | + methods: { | ||
| 86 | + open(row) { | ||
| 87 | + this.visible = true | ||
| 88 | + this.$nextTick(() => { | ||
| 89 | + this.formData = { ...row } | ||
| 90 | + }) | ||
| 91 | + }, | ||
| 92 | + handleClose() { | ||
| 93 | + this.$refs.form.resetFields() | ||
| 94 | + }, | ||
| 95 | + handleSubmit() { | ||
| 96 | + this.$refs.form.validate(async valid => { | ||
| 97 | + if (valid) { | ||
| 98 | + try { | ||
| 99 | + this.formData.communityId = getCommunityId() | ||
| 100 | + await updateApplyRoomDiscountType(this.formData) | ||
| 101 | + this.$message.success(this.$t('discountType.edit.success')) | ||
| 102 | + this.visible = false | ||
| 103 | + this.$emit('success') | ||
| 104 | + } catch (error) { | ||
| 105 | + console.error(error) | ||
| 106 | + } | ||
| 107 | + } | ||
| 108 | + }) | ||
| 109 | + } | ||
| 110 | + } | ||
| 111 | +} | ||
| 112 | +</script> | ||
| 0 | \ No newline at end of file | 113 | \ No newline at end of file |
src/components/fee/reviewApplyRoomDiscount.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <el-dialog :title="$t('applyRoomDiscount.review.title')" :visible.sync="visible" width="70%" @close="handleClose"> | ||
| 3 | + <el-form ref="form" :model="form" :rules="rules" label-width="150px"> | ||
| 4 | + <template v-if="form.state !== '5'"> | ||
| 5 | + <el-form-item :label="$t('applyRoomDiscount.review.discountType')" prop="discountType"> | ||
| 6 | + <el-select v-model="form.discountType" :placeholder="$t('applyRoomDiscount.review.discountTypePlaceholder')" | ||
| 7 | + style="width:100%" @change="handleDiscountTypeChange"> | ||
| 8 | + <el-option :label="$t('applyRoomDiscount.discountType.discount')" value="3003" /> | ||
| 9 | + </el-select> | ||
| 10 | + </el-form-item> | ||
| 11 | + | ||
| 12 | + <el-form-item :label="$t('applyRoomDiscount.review.discountName')" prop="discountId"> | ||
| 13 | + <el-select v-model="form.discountId" :placeholder="$t('applyRoomDiscount.review.discountNamePlaceholder')" | ||
| 14 | + style="width:100%"> | ||
| 15 | + <el-option v-for="item in discounts" :key="item.discountId" :label="item.discountName" | ||
| 16 | + :value="item.discountId" /> | ||
| 17 | + </el-select> | ||
| 18 | + </el-form-item> | ||
| 19 | + | ||
| 20 | + <el-form-item :label="$t('applyRoomDiscount.review.returnWay')" prop="returnWay"> | ||
| 21 | + <el-select v-model="form.returnWay" :placeholder="$t('applyRoomDiscount.review.returnWayPlaceholder')" | ||
| 22 | + style="width:100%"> | ||
| 23 | + <el-option :label="$t('applyRoomDiscount.returnWay.discount')" value="1001" /> | ||
| 24 | + <el-option :label="$t('applyRoomDiscount.returnWay.account')" value="1002" /> | ||
| 25 | + </el-select> | ||
| 26 | + </el-form-item> | ||
| 27 | + | ||
| 28 | + <div v-show="form.returnWay === '1002'"> | ||
| 29 | + <el-form-item :label="$t('applyRoomDiscount.review.paymentRecords')"> | ||
| 30 | + <div class="checkbox-group"> | ||
| 31 | + <el-checkbox v-for="item in fees" :key="item.detailId" v-model="form.selectedFees" :label="item.detailId" | ||
| 32 | + @change="handleFeeSelection(item)"> | ||
| 33 | + 【{{ item.feeName }}】<span class="text-danger">{{ item.receivedAmount }}{{ $t('common.yuan') }}</span> - | ||
| 34 | + {{ item.createTime }} | ||
| 35 | + </el-checkbox> | ||
| 36 | + </div> | ||
| 37 | + </el-form-item> | ||
| 38 | + | ||
| 39 | + <el-form-item :label="$t('applyRoomDiscount.review.refundAmount')" prop="refundAmount"> | ||
| 40 | + <el-input v-model="form.refundAmount" | ||
| 41 | + :placeholder="$t('applyRoomDiscount.review.refundAmountPlaceholder')" /> | ||
| 42 | + </el-form-item> | ||
| 43 | + </div> | ||
| 44 | + </template> | ||
| 45 | + | ||
| 46 | + <el-form-item :label="$t('applyRoomDiscount.review.startTime')" prop="startTime"> | ||
| 47 | + <el-date-picker v-model="form.startTime" type="datetime" | ||
| 48 | + :placeholder="$t('applyRoomDiscount.review.startTimePlaceholder')" value-format="yyyy-MM-dd HH:mm:ss" | ||
| 49 | + style="width:100%" /> | ||
| 50 | + </el-form-item> | ||
| 51 | + | ||
| 52 | + <el-form-item :label="$t('applyRoomDiscount.review.endTime')" prop="endTime"> | ||
| 53 | + <el-date-picker v-model="form.endTime" type="datetime" | ||
| 54 | + :placeholder="$t('applyRoomDiscount.review.endTimePlaceholder')" value-format="yyyy-MM-dd HH:mm:ss" | ||
| 55 | + style="width:100%" /> | ||
| 56 | + </el-form-item> | ||
| 57 | + | ||
| 58 | + <el-form-item :label="$t('applyRoomDiscount.review.state')" prop="state"> | ||
| 59 | + <el-select v-model="form.state" :placeholder="$t('applyRoomDiscount.review.statePlaceholder')" | ||
| 60 | + style="width:100%"> | ||
| 61 | + <el-option :label="$t('applyRoomDiscount.status.reviewPass')" value="4" /> | ||
| 62 | + <el-option :label="$t('applyRoomDiscount.status.reviewReject')" value="5" /> | ||
| 63 | + </el-select> | ||
| 64 | + </el-form-item> | ||
| 65 | + | ||
| 66 | + <el-form-item :label="$t('applyRoomDiscount.review.createRemark')"> | ||
| 67 | + <el-input v-model="form.createRemark" type="textarea" :rows="2" disabled /> | ||
| 68 | + </el-form-item> | ||
| 69 | + | ||
| 70 | + <el-form-item :label="$t('applyRoomDiscount.review.checkRemark')"> | ||
| 71 | + <el-input v-model="form.checkRemark" type="textarea" :rows="2" disabled /> | ||
| 72 | + </el-form-item> | ||
| 73 | + | ||
| 74 | + <el-form-item :label="$t('applyRoomDiscount.review.reviewRemark')" prop="reviewRemark"> | ||
| 75 | + <el-input v-model="form.reviewRemark" type="textarea" | ||
| 76 | + :placeholder="$t('applyRoomDiscount.review.reviewRemarkPlaceholder')" :rows="3" /> | ||
| 77 | + </el-form-item> | ||
| 78 | + | ||
| 79 | + <el-form-item :label="$t('applyRoomDiscount.review.images')"> | ||
| 80 | + <div class="image-preview-group"> | ||
| 81 | + <div v-for="(url, index) in form.images" :key="index" class="image-preview-item"> | ||
| 82 | + <img :src="getImageUrl(url)" @click="showImage(url)" /> | ||
| 83 | + </div> | ||
| 84 | + </div> | ||
| 85 | + </el-form-item> | ||
| 86 | + </el-form> | ||
| 87 | + | ||
| 88 | + <div slot="footer" class="dialog-footer"> | ||
| 89 | + <el-button @click="visible = false"> | ||
| 90 | + {{ $t('common.cancel') }} | ||
| 91 | + </el-button> | ||
| 92 | + <el-button type="primary" @click="submitForm"> | ||
| 93 | + {{ $t('common.save') }} | ||
| 94 | + </el-button> | ||
| 95 | + </div> | ||
| 96 | + | ||
| 97 | + <view-image ref="viewImage" /> | ||
| 98 | + </el-dialog> | ||
| 99 | +</template> | ||
| 100 | + | ||
| 101 | +<script> | ||
| 102 | +//import { getDict } from '@/api/community/communityApi' | ||
| 103 | +import { queryFeeDiscount, updateReviewApplyRoomDiscount } from '@/api/fee/applyRoomDiscountManageApi' | ||
| 104 | +import ViewImage from '@/components/system/viewImage' | ||
| 105 | + | ||
| 106 | +export default { | ||
| 107 | + name: 'ReviewApplyRoomDiscount', | ||
| 108 | + components: { | ||
| 109 | + ViewImage | ||
| 110 | + }, | ||
| 111 | + data() { | ||
| 112 | + return { | ||
| 113 | + visible: false, | ||
| 114 | + form: { | ||
| 115 | + ardId: '', | ||
| 116 | + discountId: '', | ||
| 117 | + discountType: '', | ||
| 118 | + startTime: '', | ||
| 119 | + endTime: '', | ||
| 120 | + createRemark: '', | ||
| 121 | + checkRemark: '', | ||
| 122 | + reviewRemark: '', | ||
| 123 | + refundAmount: '', | ||
| 124 | + state: '', | ||
| 125 | + roomId: '', | ||
| 126 | + discounts: [], | ||
| 127 | + fees: [], | ||
| 128 | + selectedFees: [], | ||
| 129 | + images: [], | ||
| 130 | + returnWay: '1001', | ||
| 131 | + feeId: '' | ||
| 132 | + }, | ||
| 133 | + discounts: [], | ||
| 134 | + fees: [], | ||
| 135 | + rules: { | ||
| 136 | + discountId: [ | ||
| 137 | + { required: true, message: this.$t('applyRoomDiscount.validate.discountIdRequired'), trigger: 'change' } | ||
| 138 | + ], | ||
| 139 | + discountType: [ | ||
| 140 | + { required: true, message: this.$t('applyRoomDiscount.validate.discountTypeRequired'), trigger: 'change' } | ||
| 141 | + ], | ||
| 142 | + returnWay: [ | ||
| 143 | + { required: true, message: this.$t('applyRoomDiscount.validate.returnWayRequired'), trigger: 'change' } | ||
| 144 | + ], | ||
| 145 | + refundAmount: [ | ||
| 146 | + { | ||
| 147 | + required: true, | ||
| 148 | + message: this.$t('applyRoomDiscount.validate.refundAmountRequired'), | ||
| 149 | + trigger: 'blur', | ||
| 150 | + validator: (rule, value, callback) => { | ||
| 151 | + if (this.form.returnWay === '1002' && !value) { | ||
| 152 | + callback(new Error(this.$t('applyRoomDiscount.validate.refundAmountRequired'))) | ||
| 153 | + } else { | ||
| 154 | + callback() | ||
| 155 | + } | ||
| 156 | + } | ||
| 157 | + }, | ||
| 158 | + { | ||
| 159 | + pattern: /^\d+(\.\d{1,2})?$/, | ||
| 160 | + message: this.$t('applyRoomDiscount.validate.refundAmountFormat'), | ||
| 161 | + trigger: 'blur' | ||
| 162 | + } | ||
| 163 | + ], | ||
| 164 | + startTime: [ | ||
| 165 | + { required: true, message: this.$t('applyRoomDiscount.validate.startTimeRequired'), trigger: 'change' } | ||
| 166 | + ], | ||
| 167 | + endTime: [ | ||
| 168 | + { required: true, message: this.$t('applyRoomDiscount.validate.endTimeRequired'), trigger: 'change' } | ||
| 169 | + ], | ||
| 170 | + state: [ | ||
| 171 | + { required: true, message: this.$t('applyRoomDiscount.validate.stateRequired'), trigger: 'change' } | ||
| 172 | + ], | ||
| 173 | + reviewRemark: [ | ||
| 174 | + { required: true, message: this.$t('applyRoomDiscount.validate.reviewRemarkRequired'), trigger: 'blur' }, | ||
| 175 | + { max: 512, message: this.$t('applyRoomDiscount.validate.reviewRemarkFormat'), trigger: 'blur' } | ||
| 176 | + ] | ||
| 177 | + } | ||
| 178 | + } | ||
| 179 | + }, | ||
| 180 | + methods: { | ||
| 181 | + open(data) { | ||
| 182 | + this.form = { | ||
| 183 | + ...this.form, | ||
| 184 | + ...data, | ||
| 185 | + communityId: this.$store.getters.communityId, | ||
| 186 | + selectedFees: [], | ||
| 187 | + refundAmount: '' | ||
| 188 | + } | ||
| 189 | + this.visible = true | ||
| 190 | + this.loadDiscounts() | ||
| 191 | + this.loadFees() | ||
| 192 | + }, | ||
| 193 | + handleClose() { | ||
| 194 | + this.$refs.form.resetFields() | ||
| 195 | + this.form = { | ||
| 196 | + ardId: '', | ||
| 197 | + discountId: '', | ||
| 198 | + discountType: '', | ||
| 199 | + startTime: '', | ||
| 200 | + endTime: '', | ||
| 201 | + createRemark: '', | ||
| 202 | + checkRemark: '', | ||
| 203 | + reviewRemark: '', | ||
| 204 | + refundAmount: '', | ||
| 205 | + state: '', | ||
| 206 | + roomId: '', | ||
| 207 | + discounts: [], | ||
| 208 | + fees: [], | ||
| 209 | + selectedFees: [], | ||
| 210 | + images: [], | ||
| 211 | + returnWay: '1001', | ||
| 212 | + feeId: '' | ||
| 213 | + } | ||
| 214 | + }, | ||
| 215 | + async loadDiscounts() { | ||
| 216 | + try { | ||
| 217 | + const { data } = await queryFeeDiscount({ | ||
| 218 | + page: 1, | ||
| 219 | + row: 100, | ||
| 220 | + communityId: this.form.communityId, | ||
| 221 | + discountType: this.form.discountType || '3003' | ||
| 222 | + }) | ||
| 223 | + this.discounts = data | ||
| 224 | + } catch (error) { | ||
| 225 | + console.error('加载折扣信息失败:', error) | ||
| 226 | + } | ||
| 227 | + }, | ||
| 228 | + async loadFees() { | ||
| 229 | + try { | ||
| 230 | + const { data } = await this.$api.fee.queryFeeDetail({ | ||
| 231 | + page: 1, | ||
| 232 | + row: 50, | ||
| 233 | + communityId: this.form.communityId, | ||
| 234 | + feeId: this.form.feeId, | ||
| 235 | + state: '1400' | ||
| 236 | + }) | ||
| 237 | + this.fees = data.feeDetails | ||
| 238 | + } catch (error) { | ||
| 239 | + console.error('加载缴费记录失败:', error) | ||
| 240 | + } | ||
| 241 | + }, | ||
| 242 | + handleDiscountTypeChange() { | ||
| 243 | + this.form.discountId = '' | ||
| 244 | + this.loadDiscounts() | ||
| 245 | + }, | ||
| 246 | + handleFeeSelection(item) { | ||
| 247 | + console.log(item) | ||
| 248 | + this.calculateRefundAmount() | ||
| 249 | + }, | ||
| 250 | + calculateRefundAmount() { | ||
| 251 | + if (this.form.returnWay !== '1002') return | ||
| 252 | + | ||
| 253 | + let total = 0 | ||
| 254 | + this.fees.forEach(item => { | ||
| 255 | + if (this.form.selectedFees.includes(item.detailId)) { | ||
| 256 | + total += parseFloat(item.receivedAmount) || 0 | ||
| 257 | + } | ||
| 258 | + }) | ||
| 259 | + this.form.refundAmount = total.toFixed(2) | ||
| 260 | + }, | ||
| 261 | + getImageUrl(url) { | ||
| 262 | + if (url.startsWith('http') || url.startsWith('https') || url.startsWith('data:')) { | ||
| 263 | + return url | ||
| 264 | + } | ||
| 265 | + return `/callComponent/download/getFile/file?fileId=${url}&communityId=-1&time=${new Date().getTime()}` | ||
| 266 | + }, | ||
| 267 | + showImage(url) { | ||
| 268 | + this.$refs.viewImage.open(this.getImageUrl(url)) | ||
| 269 | + }, | ||
| 270 | + submitForm() { | ||
| 271 | + this.$refs.form.validate(valid => { | ||
| 272 | + if (valid) { | ||
| 273 | + this.updateReview() | ||
| 274 | + } | ||
| 275 | + }) | ||
| 276 | + }, | ||
| 277 | + async updateReview() { | ||
| 278 | + try { | ||
| 279 | + await updateReviewApplyRoomDiscount(this.form) | ||
| 280 | + this.$message.success(this.$t('applyRoomDiscount.message.reviewSuccess')) | ||
| 281 | + this.visible = false | ||
| 282 | + this.$emit('success') | ||
| 283 | + } catch (error) { | ||
| 284 | + this.$message.error(error.message || this.$t('applyRoomDiscount.message.reviewFailed')) | ||
| 285 | + } | ||
| 286 | + } | ||
| 287 | + } | ||
| 288 | +} | ||
| 289 | +</script> | ||
| 290 | + | ||
| 291 | +<style lang="scss" scoped> | ||
| 292 | +.el-form-item { | ||
| 293 | + margin-bottom: 22px; | ||
| 294 | +} | ||
| 295 | + | ||
| 296 | +.checkbox-group { | ||
| 297 | + max-height: 200px; | ||
| 298 | + overflow-y: auto; | ||
| 299 | + border: 1px solid #dcdfe6; | ||
| 300 | + border-radius: 4px; | ||
| 301 | + padding: 10px; | ||
| 302 | + | ||
| 303 | + .el-checkbox { | ||
| 304 | + display: block; | ||
| 305 | + margin: 5px 0; | ||
| 306 | + } | ||
| 307 | +} | ||
| 308 | + | ||
| 309 | +.text-danger { | ||
| 310 | + color: #f56c6c; | ||
| 311 | +} | ||
| 312 | + | ||
| 313 | +.image-preview-group { | ||
| 314 | + display: flex; | ||
| 315 | + flex-wrap: wrap; | ||
| 316 | + gap: 10px; | ||
| 317 | + | ||
| 318 | + .image-preview-item { | ||
| 319 | + width: 60px; | ||
| 320 | + height: 60px; | ||
| 321 | + border: 1px solid #dcdfe6; | ||
| 322 | + border-radius: 4px; | ||
| 323 | + overflow: hidden; | ||
| 324 | + cursor: pointer; | ||
| 325 | + | ||
| 326 | + img { | ||
| 327 | + width: 100%; | ||
| 328 | + height: 100%; | ||
| 329 | + object-fit: cover; | ||
| 330 | + } | ||
| 331 | + } | ||
| 332 | +} | ||
| 333 | +</style> | ||
| 0 | \ No newline at end of file | 334 | \ No newline at end of file |
src/components/fee/uploadImageUrl.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="upload-image-container"> | ||
| 3 | + <div v-for="(image, index) in photos" :key="index" class="image-item"> | ||
| 4 | + <img :src="getImageUrl(image)" @error="handleImageError" /> | ||
| 5 | + <span class="remove-icon" @click="removeImage(index)"> | ||
| 6 | + <i class="el-icon-delete"></i> | ||
| 7 | + </span> | ||
| 8 | + </div> | ||
| 9 | + | ||
| 10 | + <div v-if="photos.length < imageCount" class="upload-btn" @click="triggerUpload"> | ||
| 11 | + <i class="el-icon-plus"></i> | ||
| 12 | + </div> | ||
| 13 | + | ||
| 14 | + <input | ||
| 15 | + ref="fileInput" | ||
| 16 | + type="file" | ||
| 17 | + accept="image/*" | ||
| 18 | + style="display: none" | ||
| 19 | + @change="handleFileChange" | ||
| 20 | + /> | ||
| 21 | + </div> | ||
| 22 | +</template> | ||
| 23 | + | ||
| 24 | +<script> | ||
| 25 | +import { uploadFile } from '@/api/common' | ||
| 26 | + | ||
| 27 | +export default { | ||
| 28 | + name: 'UploadImageUrl', | ||
| 29 | + props: { | ||
| 30 | + imageCount: { | ||
| 31 | + type: Number, | ||
| 32 | + default: 99 | ||
| 33 | + } | ||
| 34 | + }, | ||
| 35 | + data() { | ||
| 36 | + return { | ||
| 37 | + photos: [], // 用于显示的图片数组 | ||
| 38 | + photosUrl: [] // 实际存储的图片信息数组 | ||
| 39 | + } | ||
| 40 | + }, | ||
| 41 | + methods: { | ||
| 42 | + triggerUpload() { | ||
| 43 | + this.$refs.fileInput.click() | ||
| 44 | + }, | ||
| 45 | + async handleFileChange(event) { | ||
| 46 | + const files = event.target.files | ||
| 47 | + if (!files || files.length === 0) return | ||
| 48 | + | ||
| 49 | + const file = files[0] | ||
| 50 | + if (file.size > 2 * 1024 * 1024) { | ||
| 51 | + this.$message.error(this.$t('uploadImage.validate.sizeLimit')) | ||
| 52 | + return | ||
| 53 | + } | ||
| 54 | + | ||
| 55 | + try { | ||
| 56 | + // 显示本地预览 | ||
| 57 | + const reader = new FileReader() | ||
| 58 | + reader.onload = (e) => { | ||
| 59 | + this.photos.push(e.target.result) | ||
| 60 | + } | ||
| 61 | + reader.readAsDataURL(file) | ||
| 62 | + | ||
| 63 | + // 上传到服务器 | ||
| 64 | + const formData = new FormData() | ||
| 65 | + formData.append('uploadFile', file) | ||
| 66 | + formData.append('communityId', this.$store.getters.communityId) | ||
| 67 | + | ||
| 68 | + const { data } = await uploadFile(formData) | ||
| 69 | + this.photosUrl.push(data) | ||
| 70 | + this.$emit('change', this.photosUrl) | ||
| 71 | + } catch (error) { | ||
| 72 | + this.$message.error(this.$t('uploadImage.message.uploadFailed')) | ||
| 73 | + } finally { | ||
| 74 | + event.target.value = null | ||
| 75 | + } | ||
| 76 | + }, | ||
| 77 | + removeImage(index) { | ||
| 78 | + this.photos.splice(index, 1) | ||
| 79 | + this.photosUrl.splice(index, 1) | ||
| 80 | + this.$emit('change', this.photosUrl) | ||
| 81 | + }, | ||
| 82 | + handleImageError(e) { | ||
| 83 | + e.target.src = '/img/noPhoto.jpg' | ||
| 84 | + }, | ||
| 85 | + getImageUrl(image) { | ||
| 86 | + if (typeof image === 'string') { | ||
| 87 | + if (image.startsWith('http') || image.startsWith('https') || image.startsWith('data:')) { | ||
| 88 | + return image | ||
| 89 | + } | ||
| 90 | + return `/callComponent/download/getFile/file?fileId=${image}&communityId=-1&time=${new Date().getTime()}` | ||
| 91 | + } | ||
| 92 | + return image.url || '/img/noPhoto.jpg' | ||
| 93 | + }, | ||
| 94 | + clear() { | ||
| 95 | + this.photos = [] | ||
| 96 | + this.photosUrl = [] | ||
| 97 | + }, | ||
| 98 | + setImages(images) { | ||
| 99 | + this.photos = [] | ||
| 100 | + this.photosUrl = [] | ||
| 101 | + images.forEach(image => { | ||
| 102 | + if (image.startsWith('data:')) { | ||
| 103 | + this.photos.push(image) | ||
| 104 | + return | ||
| 105 | + } | ||
| 106 | + this.photosUrl.push({ fileId: image, url: image }) | ||
| 107 | + this.photos.push(this.getImageUrl(image)) | ||
| 108 | + }) | ||
| 109 | + } | ||
| 110 | + } | ||
| 111 | +} | ||
| 112 | +</script> | ||
| 113 | + | ||
| 114 | +<style lang="scss" scoped> | ||
| 115 | +.upload-image-container { | ||
| 116 | + display: flex; | ||
| 117 | + flex-wrap: wrap; | ||
| 118 | + gap: 10px; | ||
| 119 | + | ||
| 120 | + .image-item { | ||
| 121 | + position: relative; | ||
| 122 | + width: 100px; | ||
| 123 | + height: 100px; | ||
| 124 | + border: 1px dashed #dcdfe6; | ||
| 125 | + border-radius: 4px; | ||
| 126 | + overflow: hidden; | ||
| 127 | + | ||
| 128 | + img { | ||
| 129 | + width: 100%; | ||
| 130 | + height: 100%; | ||
| 131 | + object-fit: cover; | ||
| 132 | + } | ||
| 133 | + | ||
| 134 | + .remove-icon { | ||
| 135 | + position: absolute; | ||
| 136 | + top: 0; | ||
| 137 | + right: 0; | ||
| 138 | + color: #f56c6c; | ||
| 139 | + background: rgba(255, 255, 255, 0.7); | ||
| 140 | + padding: 4px; | ||
| 141 | + cursor: pointer; | ||
| 142 | + font-size: 16px; | ||
| 143 | + | ||
| 144 | + &:hover { | ||
| 145 | + color: #f78989; | ||
| 146 | + } | ||
| 147 | + } | ||
| 148 | + } | ||
| 149 | + | ||
| 150 | + .upload-btn { | ||
| 151 | + width: 100px; | ||
| 152 | + height: 100px; | ||
| 153 | + border: 1px dashed #dcdfe6; | ||
| 154 | + border-radius: 4px; | ||
| 155 | + display: flex; | ||
| 156 | + justify-content: center; | ||
| 157 | + align-items: center; | ||
| 158 | + cursor: pointer; | ||
| 159 | + color: #8c939d; | ||
| 160 | + font-size: 28px; | ||
| 161 | + background-color: #f5f7fa; | ||
| 162 | + | ||
| 163 | + &:hover { | ||
| 164 | + border-color: #409eff; | ||
| 165 | + color: #409eff; | ||
| 166 | + } | ||
| 167 | + } | ||
| 168 | +} | ||
| 169 | +</style> | ||
| 0 | \ No newline at end of file | 170 | \ No newline at end of file |
src/components/fee/viewImage.vue
| 1 | <template> | 1 | <template> |
| 2 | - <div v-show="showImage" class="image-viewer"> | ||
| 3 | - <div class="image-container"> | ||
| 4 | - <img :src="url" :style="imgStyle" @error="handleError"> | ||
| 5 | - <i class="el-icon-close close-icon" @click="close"></i> | 2 | + <div v-show="visible" class="image-viewer-wrapper"> |
| 3 | + <div class="image-viewer-mask" @click="close"></div> | ||
| 4 | + <div class="image-viewer-content"> | ||
| 5 | + <img | ||
| 6 | + :src="imageUrl" | ||
| 7 | + :style="imageStyle" | ||
| 8 | + @error="handleImageError" | ||
| 9 | + /> | ||
| 10 | + <span class="image-viewer-close" @click="close"> | ||
| 11 | + <i class="el-icon-close"></i> | ||
| 12 | + </span> | ||
| 6 | </div> | 13 | </div> |
| 7 | </div> | 14 | </div> |
| 8 | </template> | 15 | </template> |
| @@ -12,72 +19,100 @@ export default { | @@ -12,72 +19,100 @@ export default { | ||
| 12 | name: 'ViewImage', | 19 | name: 'ViewImage', |
| 13 | data() { | 20 | data() { |
| 14 | return { | 21 | return { |
| 15 | - url: '', | ||
| 16 | - showImage: false, | ||
| 17 | - imgWidth: 800, | ||
| 18 | - imgHeight: 800 | 22 | + visible: false, |
| 23 | + imageUrl: '', | ||
| 24 | + imageWidth: 0, | ||
| 25 | + imageHeight: 0 | ||
| 19 | } | 26 | } |
| 20 | }, | 27 | }, |
| 21 | computed: { | 28 | computed: { |
| 22 | - imgStyle() { | 29 | + imageStyle() { |
| 23 | return { | 30 | return { |
| 24 | - width: `${this.imgWidth}px`, | ||
| 25 | - height: `${this.imgHeight}px` | 31 | + width: this.imageWidth ? `${this.imageWidth}px` : 'auto', |
| 32 | + height: this.imageHeight ? `${this.imageHeight}px` : 'auto', | ||
| 33 | + maxWidth: '90vw', | ||
| 34 | + maxHeight: '90vh' | ||
| 26 | } | 35 | } |
| 27 | } | 36 | } |
| 28 | }, | 37 | }, |
| 29 | methods: { | 38 | methods: { |
| 30 | open(url) { | 39 | open(url) { |
| 31 | - this.url = url | ||
| 32 | - this.showImage = true | ||
| 33 | - this.calculateSize(url) | 40 | + this.imageUrl = url |
| 41 | + this.visible = true | ||
| 42 | + this.$nextTick(() => { | ||
| 43 | + this.calculateImageSize(url) | ||
| 44 | + }) | ||
| 34 | }, | 45 | }, |
| 35 | close() { | 46 | close() { |
| 36 | - this.showImage = false | 47 | + this.visible = false |
| 48 | + this.imageUrl = '' | ||
| 49 | + this.imageWidth = 0 | ||
| 50 | + this.imageHeight = 0 | ||
| 37 | }, | 51 | }, |
| 38 | - calculateSize(url) { | 52 | + handleImageError(e) { |
| 53 | + e.target.src = '/img/noPhoto.jpg' | ||
| 54 | + }, | ||
| 55 | + calculateImageSize(url) { | ||
| 39 | const img = new Image() | 56 | const img = new Image() |
| 40 | img.src = url | 57 | img.src = url |
| 41 | img.onload = () => { | 58 | img.onload = () => { |
| 42 | - const ratio = img.width / img.height | ||
| 43 | - this.imgWidth = 800 | ||
| 44 | - this.imgHeight = 800 / ratio | 59 | + const maxWidth = window.innerWidth * 0.8 |
| 60 | + const maxHeight = window.innerHeight * 0.8 | ||
| 61 | + const ratio = Math.min(maxWidth / img.width, maxHeight / img.height, 1) | ||
| 62 | + this.imageWidth = img.width * ratio | ||
| 63 | + this.imageHeight = img.height * ratio | ||
| 45 | } | 64 | } |
| 46 | - }, | ||
| 47 | - handleError() { | ||
| 48 | - this.url = '/img/noPhoto.jpg' | ||
| 49 | } | 65 | } |
| 50 | } | 66 | } |
| 51 | } | 67 | } |
| 52 | </script> | 68 | </script> |
| 53 | 69 | ||
| 54 | -<style scoped> | ||
| 55 | -.image-viewer { | 70 | +<style lang="scss" scoped> |
| 71 | +.image-viewer-wrapper { | ||
| 56 | position: fixed; | 72 | position: fixed; |
| 57 | top: 0; | 73 | top: 0; |
| 58 | left: 0; | 74 | left: 0; |
| 59 | right: 0; | 75 | right: 0; |
| 60 | bottom: 0; | 76 | bottom: 0; |
| 61 | - background-color: rgba(0, 0, 0, 0.5); | ||
| 62 | z-index: 9999; | 77 | z-index: 9999; |
| 63 | display: flex; | 78 | display: flex; |
| 64 | justify-content: center; | 79 | justify-content: center; |
| 65 | align-items: center; | 80 | align-items: center; |
| 66 | -} | ||
| 67 | 81 | ||
| 68 | -.image-container { | ||
| 69 | - position: relative; | ||
| 70 | - background-color: #fff; | ||
| 71 | - padding: 20px; | ||
| 72 | - border-radius: 4px; | ||
| 73 | -} | 82 | + .image-viewer-mask { |
| 83 | + position: absolute; | ||
| 84 | + width: 100%; | ||
| 85 | + height: 100%; | ||
| 86 | + background-color: rgba(0, 0, 0, 0.7); | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | + .image-viewer-content { | ||
| 90 | + position: relative; | ||
| 91 | + z-index: 1; | ||
| 92 | + padding: 20px; | ||
| 93 | + background-color: #fff; | ||
| 94 | + border-radius: 4px; | ||
| 95 | + text-align: center; | ||
| 74 | 96 | ||
| 75 | -.close-icon { | ||
| 76 | - position: absolute; | ||
| 77 | - top: 10px; | ||
| 78 | - right: 10px; | ||
| 79 | - font-size: 24px; | ||
| 80 | - color: #f56c6c; | ||
| 81 | - cursor: pointer; | 97 | + img { |
| 98 | + display: block; | ||
| 99 | + margin: 0 auto; | ||
| 100 | + object-fit: contain; | ||
| 101 | + } | ||
| 102 | + } | ||
| 103 | + | ||
| 104 | + .image-viewer-close { | ||
| 105 | + position: absolute; | ||
| 106 | + top: 10px; | ||
| 107 | + right: 10px; | ||
| 108 | + font-size: 24px; | ||
| 109 | + color: #f56c6c; | ||
| 110 | + cursor: pointer; | ||
| 111 | + z-index: 2; | ||
| 112 | + | ||
| 113 | + &:hover { | ||
| 114 | + color: #f78989; | ||
| 115 | + } | ||
| 116 | + } | ||
| 82 | } | 117 | } |
| 83 | </style> | 118 | </style> |
| 84 | \ No newline at end of file | 119 | \ No newline at end of file |
src/i18n/feeI18n.js
| @@ -3,6 +3,9 @@ import { messages as meterWaterManageMessages } from '../views/fee/meterWaterMan | @@ -3,6 +3,9 @@ import { messages as meterWaterManageMessages } from '../views/fee/meterWaterMan | ||
| 3 | import { messages as meterTypeManageMessages } from '../views/fee/meterTypeManageLang' | 3 | import { messages as meterTypeManageMessages } from '../views/fee/meterTypeManageLang' |
| 4 | import { messages as returnPayFeeManageMessages } from '../views/fee/returnPayFeeManageLang' | 4 | import { messages as returnPayFeeManageMessages } from '../views/fee/returnPayFeeManageLang' |
| 5 | import { messages as feeDiscountManageMessages } from '../views/fee/feeDiscountManageLang' | 5 | import { messages as feeDiscountManageMessages } from '../views/fee/feeDiscountManageLang' |
| 6 | +import { messages as applyRoomDiscountManageMessages } from '../views/fee/applyRoomDiscountManageLang' | ||
| 7 | +import { messages as discountTypeMessages } from '../views/fee/discountTypeLang' | ||
| 8 | + | ||
| 6 | export const messages = { | 9 | export const messages = { |
| 7 | en: { | 10 | en: { |
| 8 | ...contractCreateFeeMessages.en, | 11 | ...contractCreateFeeMessages.en, |
| @@ -10,6 +13,8 @@ export const messages = { | @@ -10,6 +13,8 @@ export const messages = { | ||
| 10 | ...meterTypeManageMessages.en, | 13 | ...meterTypeManageMessages.en, |
| 11 | ...returnPayFeeManageMessages.en, | 14 | ...returnPayFeeManageMessages.en, |
| 12 | ...feeDiscountManageMessages.en, | 15 | ...feeDiscountManageMessages.en, |
| 16 | + ...applyRoomDiscountManageMessages.en, | ||
| 17 | + ...discountTypeMessages.en, | ||
| 13 | }, | 18 | }, |
| 14 | zh: { | 19 | zh: { |
| 15 | ...contractCreateFeeMessages.zh, | 20 | ...contractCreateFeeMessages.zh, |
| @@ -17,5 +22,7 @@ export const messages = { | @@ -17,5 +22,7 @@ export const messages = { | ||
| 17 | ...meterTypeManageMessages.zh, | 22 | ...meterTypeManageMessages.zh, |
| 18 | ...returnPayFeeManageMessages.zh, | 23 | ...returnPayFeeManageMessages.zh, |
| 19 | ...feeDiscountManageMessages.zh, | 24 | ...feeDiscountManageMessages.zh, |
| 25 | + ...applyRoomDiscountManageMessages.zh, | ||
| 26 | + ...discountTypeMessages.zh, | ||
| 20 | } | 27 | } |
| 21 | } | 28 | } |
| 22 | \ No newline at end of file | 29 | \ No newline at end of file |
src/router/feeRouter.js
| @@ -20,8 +20,18 @@ export default [ | @@ -20,8 +20,18 @@ export default [ | ||
| 20 | component: () => import('@/views/fee/returnPayFeeManageList.vue') | 20 | component: () => import('@/views/fee/returnPayFeeManageList.vue') |
| 21 | }, | 21 | }, |
| 22 | { | 22 | { |
| 23 | - path:'/pages/property/feeDiscountManage', | ||
| 24 | - name:'/pages/property/feeDiscountManage', | 23 | + path: '/pages/property/feeDiscountManage', |
| 24 | + name: '/pages/property/feeDiscountManage', | ||
| 25 | component: () => import('@/views/fee/feeDiscountManageList.vue') | 25 | component: () => import('@/views/fee/feeDiscountManageList.vue') |
| 26 | + }, | ||
| 27 | + { | ||
| 28 | + path: '/pages/property/applyRoomDiscountManage', | ||
| 29 | + name: '/pages/property/applyRoomDiscountManage', | ||
| 30 | + component: () => import('@/views/fee/applyRoomDiscountManageList.vue') | ||
| 31 | + }, | ||
| 32 | + { | ||
| 33 | + path:'/views/fee/discountType', | ||
| 34 | + name:'/views/fee/discountType', | ||
| 35 | + component: () => import('@/views/fee/discountTypeList.vue') | ||
| 26 | }, | 36 | }, |
| 27 | ] | 37 | ] |
| 28 | \ No newline at end of file | 38 | \ No newline at end of file |
src/views/fee/applyRoomDiscountManageLang.js
0 → 100644
| 1 | +export const messages = { | ||
| 2 | + en: { | ||
| 3 | + applyRoomDiscount: { | ||
| 4 | + search: { | ||
| 5 | + title: 'Search Conditions', | ||
| 6 | + roomName: 'Please enter room name (Building-Unit-Room)', | ||
| 7 | + applyType: 'Please select application type', | ||
| 8 | + state: 'Please select status' | ||
| 9 | + }, | ||
| 10 | + list: { | ||
| 11 | + title: 'Discount Application' | ||
| 12 | + }, | ||
| 13 | + table: { | ||
| 14 | + roomName: 'Room (Building-Unit-Room)', | ||
| 15 | + discountId: 'Discount ID', | ||
| 16 | + discountName: 'Discount Name', | ||
| 17 | + applyType: 'Application Type', | ||
| 18 | + createUser: 'Applicant', | ||
| 19 | + createUserTel: 'Applicant Phone', | ||
| 20 | + startTime: 'Start Time', | ||
| 21 | + endTime: 'End Time', | ||
| 22 | + state: 'Status', | ||
| 23 | + createTime: 'Create Time', | ||
| 24 | + inUse: 'Usage Status', | ||
| 25 | + returnType: 'Return Type', | ||
| 26 | + returnAmount: 'Return Amount' | ||
| 27 | + }, | ||
| 28 | + button: { | ||
| 29 | + discountType: 'Discount Type', | ||
| 30 | + phoneApply: 'Phone Application', | ||
| 31 | + export: 'Export', | ||
| 32 | + check: 'Check', | ||
| 33 | + record: 'Record', | ||
| 34 | + review: 'Review', | ||
| 35 | + edit: 'Edit', | ||
| 36 | + delete: 'Delete' | ||
| 37 | + }, | ||
| 38 | + status: { | ||
| 39 | + notUsed: 'Not Used', | ||
| 40 | + used: 'Used', | ||
| 41 | + checkPass: 'Check Passed', | ||
| 42 | + checkReject: 'Check Rejected', | ||
| 43 | + reviewPass: 'Review Passed', | ||
| 44 | + reviewReject: 'Review Rejected' | ||
| 45 | + }, | ||
| 46 | + returnType: { | ||
| 47 | + account: 'Account Balance', | ||
| 48 | + discount: 'Discount' | ||
| 49 | + }, | ||
| 50 | + discountType: { | ||
| 51 | + discount: 'Discount (Need Application)' | ||
| 52 | + }, | ||
| 53 | + returnWay: { | ||
| 54 | + discount: 'Enjoy Payment Discount', | ||
| 55 | + account: 'Refund to Balance Account' | ||
| 56 | + }, | ||
| 57 | + add: { | ||
| 58 | + title: 'Phone Application', | ||
| 59 | + room: 'Room', | ||
| 60 | + roomPlaceholder: 'Required, please fill in room (Building-Unit-Room)', | ||
| 61 | + applyType: 'Application Type', | ||
| 62 | + applyTypePlaceholder: 'Required, please select application type', | ||
| 63 | + feeItem: 'Fee Item', | ||
| 64 | + feeItemPlaceholder: 'Please select fee item', | ||
| 65 | + createUser: 'Applicant', | ||
| 66 | + createUserPlaceholder: 'Required, please fill in applicant', | ||
| 67 | + createUserTel: 'Applicant Phone', | ||
| 68 | + createUserTelPlaceholder: 'Required, please fill in applicant phone', | ||
| 69 | + startTime: 'Start Time', | ||
| 70 | + startTimePlaceholder: 'Required, please fill in start time', | ||
| 71 | + endTime: 'End Time', | ||
| 72 | + endTimePlaceholder: 'Required, please fill in end time', | ||
| 73 | + createRemark: 'Application Description', | ||
| 74 | + createRemarkPlaceholder: 'Required, please fill in application description', | ||
| 75 | + images: 'Image Materials' | ||
| 76 | + }, | ||
| 77 | + edit: { | ||
| 78 | + title: 'Check Room', | ||
| 79 | + startTime: 'Start Time', | ||
| 80 | + startTimePlaceholder: 'Required, please fill in start time', | ||
| 81 | + endTime: 'End Time', | ||
| 82 | + endTimePlaceholder: 'Required, please fill in end time', | ||
| 83 | + state: 'Check Status', | ||
| 84 | + statePlaceholder: 'Required, please select status', | ||
| 85 | + createRemark: 'Application Description', | ||
| 86 | + checkRemark: 'Check Description', | ||
| 87 | + checkRemarkPlaceholder: 'Required, please fill in check description', | ||
| 88 | + images: 'Image Materials' | ||
| 89 | + }, | ||
| 90 | + editRecord: { | ||
| 91 | + title: 'Edit Discount Application', | ||
| 92 | + ardId: 'Application ID', | ||
| 93 | + roomName: 'Room (Building-Unit-Room)', | ||
| 94 | + applyTypeName: 'Application Type', | ||
| 95 | + createUserName: 'Applicant', | ||
| 96 | + createUserTel: 'Applicant Phone', | ||
| 97 | + startTime: 'Start Time', | ||
| 98 | + startTimePlaceholder: 'Required, please fill in start time', | ||
| 99 | + endTime: 'End Time', | ||
| 100 | + endTimePlaceholder: 'Required, please fill in end time', | ||
| 101 | + stateName: 'Status' | ||
| 102 | + }, | ||
| 103 | + review: { | ||
| 104 | + title: 'Review', | ||
| 105 | + discountType: 'Discount Type', | ||
| 106 | + discountTypePlaceholder: 'Required, please select discount type', | ||
| 107 | + discountName: 'Discount Name', | ||
| 108 | + discountNamePlaceholder: 'Required, please select discount name', | ||
| 109 | + returnWay: 'Return Way', | ||
| 110 | + returnWayPlaceholder: 'Please select return way', | ||
| 111 | + paymentRecords: 'Payment Records', | ||
| 112 | + refundAmount: 'Return Amount', | ||
| 113 | + refundAmountPlaceholder: 'Required, please fill in return amount', | ||
| 114 | + startTime: 'Start Time', | ||
| 115 | + startTimePlaceholder: 'Required, please fill in start time', | ||
| 116 | + endTime: 'End Time', | ||
| 117 | + endTimePlaceholder: 'Required, please fill in end time', | ||
| 118 | + state: 'Review Status', | ||
| 119 | + statePlaceholder: 'Required, please select status', | ||
| 120 | + createRemark: 'Application Remark', | ||
| 121 | + checkRemark: 'Check Remark', | ||
| 122 | + reviewRemark: 'Review Remark', | ||
| 123 | + reviewRemarkPlaceholder: 'Required, please fill in review description', | ||
| 124 | + images: 'Image Materials' | ||
| 125 | + }, | ||
| 126 | + delete: { | ||
| 127 | + title: 'Please confirm your operation', | ||
| 128 | + confirmText: 'Confirm to delete the room discount application?' | ||
| 129 | + }, | ||
| 130 | + validate: { | ||
| 131 | + roomRequired: 'Room cannot be empty', | ||
| 132 | + roomFormat: 'Room format error', | ||
| 133 | + roomNotFound: 'Room not found', | ||
| 134 | + applyTypeRequired: 'Application type cannot be empty', | ||
| 135 | + feeIdRequired: 'Fee item cannot be empty', | ||
| 136 | + createUserRequired: 'Applicant cannot be empty', | ||
| 137 | + createUserFormat: 'Applicant format error', | ||
| 138 | + createUserTelRequired: 'Applicant phone cannot be empty', | ||
| 139 | + createUserTelFormat: 'Applicant phone format error', | ||
| 140 | + startTimeRequired: 'Start time cannot be empty', | ||
| 141 | + endTimeRequired: 'End time cannot be empty', | ||
| 142 | + dateInvalid: 'End time must be greater than start time', | ||
| 143 | + createRemarkRequired: 'Application description cannot be empty', | ||
| 144 | + createRemarkFormat: 'Application description too long', | ||
| 145 | + checkRemarkRequired: 'Check description cannot be empty', | ||
| 146 | + checkRemarkFormat: 'Check description too long', | ||
| 147 | + reviewRemarkRequired: 'Review description cannot be empty', | ||
| 148 | + reviewRemarkFormat: 'Review description too long', | ||
| 149 | + stateRequired: 'Status cannot be empty', | ||
| 150 | + ardIdRequired: 'Application ID cannot be empty', | ||
| 151 | + discountIdRequired: 'Discount name cannot be empty', | ||
| 152 | + discountTypeRequired: 'Discount type cannot be empty', | ||
| 153 | + returnWayRequired: 'Return way cannot be empty', | ||
| 154 | + refundAmountRequired: 'Return amount cannot be empty', | ||
| 155 | + refundAmountFormat: 'Return amount format error' | ||
| 156 | + }, | ||
| 157 | + message: { | ||
| 158 | + saveSuccess: 'Application successful', | ||
| 159 | + saveFailed: 'Application failed', | ||
| 160 | + updateSuccess: 'Update successful', | ||
| 161 | + updateFailed: 'Update failed', | ||
| 162 | + reviewSuccess: 'Review successful', | ||
| 163 | + reviewFailed: 'Review failed', | ||
| 164 | + deleteSuccess: 'Delete successful', | ||
| 165 | + deleteFailed: 'Delete failed', | ||
| 166 | + fetchError: 'Failed to get data' | ||
| 167 | + } | ||
| 168 | + } | ||
| 169 | + }, | ||
| 170 | + zh: { | ||
| 171 | + applyRoomDiscount: { | ||
| 172 | + search: { | ||
| 173 | + title: '查询条件', | ||
| 174 | + roomName: '请输入房屋名称(楼栋-单元-房屋)', | ||
| 175 | + applyType: '请选择申请类型', | ||
| 176 | + state: '请选择状态' | ||
| 177 | + }, | ||
| 178 | + list: { | ||
| 179 | + title: '优惠申请' | ||
| 180 | + }, | ||
| 181 | + table: { | ||
| 182 | + roomName: '房屋(楼栋-单元-房屋)', | ||
| 183 | + discountId: '折扣ID', | ||
| 184 | + discountName: '折扣名称', | ||
| 185 | + applyType: '申请类型', | ||
| 186 | + createUser: '申请人', | ||
| 187 | + createUserTel: '申请电话', | ||
| 188 | + startTime: '开始时间', | ||
| 189 | + endTime: '结束时间', | ||
| 190 | + state: '状态', | ||
| 191 | + createTime: '创建时间', | ||
| 192 | + inUse: '使用状态', | ||
| 193 | + returnType: '返还类型', | ||
| 194 | + returnAmount: '返还金额' | ||
| 195 | + }, | ||
| 196 | + button: { | ||
| 197 | + discountType: '优惠类型', | ||
| 198 | + phoneApply: '电话申请', | ||
| 199 | + export: '导出', | ||
| 200 | + check: '验房', | ||
| 201 | + record: '跟踪记录', | ||
| 202 | + review: '审核', | ||
| 203 | + edit: '修改', | ||
| 204 | + delete: '删除' | ||
| 205 | + }, | ||
| 206 | + status: { | ||
| 207 | + notUsed: '未使用', | ||
| 208 | + used: '已使用', | ||
| 209 | + checkPass: '验房通过', | ||
| 210 | + checkReject: '验房不通过', | ||
| 211 | + reviewPass: '审批通过', | ||
| 212 | + reviewReject: '审批不通过' | ||
| 213 | + }, | ||
| 214 | + returnType: { | ||
| 215 | + account: '账户余额', | ||
| 216 | + discount: '折扣' | ||
| 217 | + }, | ||
| 218 | + discountType: { | ||
| 219 | + discount: '优惠(需要申请)' | ||
| 220 | + }, | ||
| 221 | + returnWay: { | ||
| 222 | + discount: '享受缴纳折扣', | ||
| 223 | + account: '预缴金额返还至余额账户' | ||
| 224 | + }, | ||
| 225 | + add: { | ||
| 226 | + title: '电话申请', | ||
| 227 | + room: '房屋', | ||
| 228 | + roomPlaceholder: '必填,请填写房屋 楼栋-单元-房屋', | ||
| 229 | + applyType: '申请类型', | ||
| 230 | + applyTypePlaceholder: '必填,请选择申请类型', | ||
| 231 | + feeItem: '费用项目', | ||
| 232 | + feeItemPlaceholder: '请选择费用项目', | ||
| 233 | + createUser: '申请人', | ||
| 234 | + createUserPlaceholder: '必填,请填写申请人', | ||
| 235 | + createUserTel: '申请电话', | ||
| 236 | + createUserTelPlaceholder: '必填,请填写申请电话', | ||
| 237 | + startTime: '开始时间', | ||
| 238 | + startTimePlaceholder: '必填,请填写开始时间', | ||
| 239 | + endTime: '结束时间', | ||
| 240 | + endTimePlaceholder: '必填,请填写结束时间', | ||
| 241 | + createRemark: '申请说明', | ||
| 242 | + createRemarkPlaceholder: '必填,请填写申请说明', | ||
| 243 | + images: '图片材料' | ||
| 244 | + }, | ||
| 245 | + edit: { | ||
| 246 | + title: '验房', | ||
| 247 | + startTime: '开始时间', | ||
| 248 | + startTimePlaceholder: '必填,请填写开始时间', | ||
| 249 | + endTime: '结束时间', | ||
| 250 | + endTimePlaceholder: '必填,请填写结束时间', | ||
| 251 | + state: '验房状态', | ||
| 252 | + statePlaceholder: '必填,请选择状态', | ||
| 253 | + createRemark: '申请说明', | ||
| 254 | + checkRemark: '验房说明', | ||
| 255 | + checkRemarkPlaceholder: '必填,请填写验房说明', | ||
| 256 | + images: '图片资料' | ||
| 257 | + }, | ||
| 258 | + editRecord: { | ||
| 259 | + title: '修改优惠申请', | ||
| 260 | + ardId: '申请ID', | ||
| 261 | + roomName: '房屋(楼栋-单元-房屋)', | ||
| 262 | + applyTypeName: '申请类型', | ||
| 263 | + createUserName: '申请人', | ||
| 264 | + createUserTel: '申请电话', | ||
| 265 | + startTime: '开始时间', | ||
| 266 | + startTimePlaceholder: '必填,请填写开始时间', | ||
| 267 | + endTime: '结束时间', | ||
| 268 | + endTimePlaceholder: '必填,请填写结束时间', | ||
| 269 | + stateName: '状态' | ||
| 270 | + }, | ||
| 271 | + review: { | ||
| 272 | + title: '审批', | ||
| 273 | + discountType: '折扣类型', | ||
| 274 | + discountTypePlaceholder: '必填,请选择折扣类型', | ||
| 275 | + discountName: '折扣名称', | ||
| 276 | + discountNamePlaceholder: '必填,请选择折扣名称', | ||
| 277 | + returnWay: '返还方式', | ||
| 278 | + returnWayPlaceholder: '请选择返还方式', | ||
| 279 | + paymentRecords: '缴费记录', | ||
| 280 | + refundAmount: '返还金额', | ||
| 281 | + refundAmountPlaceholder: '必填,请填写返还金额', | ||
| 282 | + startTime: '开始时间', | ||
| 283 | + startTimePlaceholder: '必填,请填写开始时间', | ||
| 284 | + endTime: '结束时间', | ||
| 285 | + endTimePlaceholder: '必填,请填写结束时间', | ||
| 286 | + state: '审批状态', | ||
| 287 | + statePlaceholder: '必填,请选择状态', | ||
| 288 | + createRemark: '申请备注', | ||
| 289 | + checkRemark: '验房备注', | ||
| 290 | + reviewRemark: '审批备注', | ||
| 291 | + reviewRemarkPlaceholder: '必填,请填写审批说明', | ||
| 292 | + images: '图片资料' | ||
| 293 | + }, | ||
| 294 | + delete: { | ||
| 295 | + title: '请确认您的操作', | ||
| 296 | + confirmText: '确定删除房屋折扣申请?' | ||
| 297 | + }, | ||
| 298 | + validate: { | ||
| 299 | + roomRequired: '房屋不能为空', | ||
| 300 | + roomFormat: '房屋格式错误', | ||
| 301 | + roomNotFound: '未找到房屋', | ||
| 302 | + applyTypeRequired: '申请类型不能为空', | ||
| 303 | + feeIdRequired: '费用项不能为空', | ||
| 304 | + createUserRequired: '申请人不能为空', | ||
| 305 | + createUserFormat: '申请人错误', | ||
| 306 | + createUserTelRequired: '申请电话不能为空', | ||
| 307 | + createUserTelFormat: '申请电话错误', | ||
| 308 | + startTimeRequired: '开始时间不能为空', | ||
| 309 | + endTimeRequired: '结束时间不能为空', | ||
| 310 | + dateInvalid: '结束时间必须大于开始时间', | ||
| 311 | + createRemarkRequired: '申请说明不能为空', | ||
| 312 | + createRemarkFormat: '申请说明过长', | ||
| 313 | + checkRemarkRequired: '验房说明不能为空', | ||
| 314 | + checkRemarkFormat: '验房说明过长', | ||
| 315 | + reviewRemarkRequired: '审批说明不能为空', | ||
| 316 | + reviewRemarkFormat: '审批说明过长', | ||
| 317 | + stateRequired: '状态不能为空', | ||
| 318 | + ardIdRequired: '申请ID不能为空', | ||
| 319 | + discountIdRequired: '折扣名称不能为空', | ||
| 320 | + discountTypeRequired: '折扣类型不能为空', | ||
| 321 | + returnWayRequired: '返还方式不能为空', | ||
| 322 | + refundAmountRequired: '返还金额不能为空', | ||
| 323 | + refundAmountFormat: '返还金额格式错误' | ||
| 324 | + }, | ||
| 325 | + message: { | ||
| 326 | + saveSuccess: '申请成功', | ||
| 327 | + saveFailed: '申请失败', | ||
| 328 | + updateSuccess: '修改成功', | ||
| 329 | + updateFailed: '修改失败', | ||
| 330 | + reviewSuccess: '审批成功', | ||
| 331 | + reviewFailed: '审批失败', | ||
| 332 | + deleteSuccess: '删除成功', | ||
| 333 | + deleteFailed: '删除失败', | ||
| 334 | + fetchError: '获取数据失败' | ||
| 335 | + } | ||
| 336 | + } | ||
| 337 | + } | ||
| 338 | +} | ||
| 0 | \ No newline at end of file | 339 | \ No newline at end of file |
src/views/fee/applyRoomDiscountManageList.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="apply-room-discount-container"> | ||
| 3 | + <!-- 查询条件 --> | ||
| 4 | + <el-card class="search-wrapper"> | ||
| 5 | + <div slot="header" class="flex justify-between"> | ||
| 6 | + <span>{{ $t('applyRoomDiscount.search.title') }}</span> | ||
| 7 | + </div> | ||
| 8 | + <el-row :gutter="20"> | ||
| 9 | + <el-col :span="6"> | ||
| 10 | + <el-input v-model.trim="searchForm.roomName" :placeholder="$t('applyRoomDiscount.search.roomName')" | ||
| 11 | + clearable /> | ||
| 12 | + </el-col> | ||
| 13 | + <el-col :span="6"> | ||
| 14 | + <el-select v-model="searchForm.applyType" :placeholder="$t('applyRoomDiscount.search.applyType')" | ||
| 15 | + style="width:100%"> | ||
| 16 | + <el-option v-for="item in applyTypes" :key="item.applyType" :label="item.typeName" | ||
| 17 | + :value="item.applyType" /> | ||
| 18 | + </el-select> | ||
| 19 | + </el-col> | ||
| 20 | + <el-col :span="6"> | ||
| 21 | + <el-select v-model="searchForm.state" :placeholder="$t('applyRoomDiscount.search.state')" style="width:100%"> | ||
| 22 | + <el-option v-for="item in states" :key="item.statusCd" :label="item.name" :value="item.statusCd" /> | ||
| 23 | + </el-select> | ||
| 24 | + </el-col> | ||
| 25 | + <el-col :span="6"> | ||
| 26 | + <el-button type="primary" @click="handleSearch"> | ||
| 27 | + {{ $t('common.search') }} | ||
| 28 | + </el-button> | ||
| 29 | + <el-button @click="handleReset"> | ||
| 30 | + {{ $t('common.reset') }} | ||
| 31 | + </el-button> | ||
| 32 | + </el-col> | ||
| 33 | + </el-row> | ||
| 34 | + </el-card> | ||
| 35 | + | ||
| 36 | + <!-- 列表 --> | ||
| 37 | + <el-card class="list-wrapper"> | ||
| 38 | + <div slot="header" class="flex justify-between"> | ||
| 39 | + <span>{{ $t('applyRoomDiscount.list.title') }}</span> | ||
| 40 | + <div style="float: right;"> | ||
| 41 | + <el-button type="primary" size="small" @click="handleOpenDiscountType"> | ||
| 42 | + {{ $t('applyRoomDiscount.button.discountType') }} | ||
| 43 | + </el-button> | ||
| 44 | + <el-button type="primary" size="small" @click="handleOpenAddApply"> | ||
| 45 | + <i class="el-icon-plus"></i> | ||
| 46 | + {{ $t('applyRoomDiscount.button.phoneApply') }} | ||
| 47 | + </el-button> | ||
| 48 | + <el-button type="primary" size="small" @click="handleExport"> | ||
| 49 | + <i class="el-icon-download"></i> | ||
| 50 | + {{ $t('applyRoomDiscount.button.export') }} | ||
| 51 | + </el-button> | ||
| 52 | + </div> | ||
| 53 | + </div> | ||
| 54 | + | ||
| 55 | + <el-table v-loading="loading" :data="tableData" border style="width: 100%"> | ||
| 56 | + <el-table-column prop="roomName" :label="$t('applyRoomDiscount.table.roomName')" align="center" /> | ||
| 57 | + <el-table-column prop="discountId" :label="$t('applyRoomDiscount.table.discountId')" align="center" /> | ||
| 58 | + <el-table-column prop="discountName" :label="$t('applyRoomDiscount.table.discountName')" align="center" /> | ||
| 59 | + <el-table-column prop="applyTypeName" :label="$t('applyRoomDiscount.table.applyType')" align="center" /> | ||
| 60 | + <el-table-column prop="createUserName" :label="$t('applyRoomDiscount.table.createUser')" align="center" /> | ||
| 61 | + <el-table-column prop="createUserTel" :label="$t('applyRoomDiscount.table.createUserTel')" align="center" /> | ||
| 62 | + <el-table-column prop="startTime" :label="$t('applyRoomDiscount.table.startTime')" align="center" /> | ||
| 63 | + <el-table-column prop="endTime" :label="$t('applyRoomDiscount.table.endTime')" align="center" /> | ||
| 64 | + <el-table-column prop="stateName" :label="$t('applyRoomDiscount.table.state')" align="center" /> | ||
| 65 | + <el-table-column prop="createTime" :label="$t('applyRoomDiscount.table.createTime')" align="center" /> | ||
| 66 | + <el-table-column :label="$t('applyRoomDiscount.table.inUse')" align="center"> | ||
| 67 | + <template slot-scope="scope"> | ||
| 68 | + {{ scope.row.inUse === '0' ? $t('applyRoomDiscount.status.notUsed') : $t('applyRoomDiscount.status.used') }} | ||
| 69 | + </template> | ||
| 70 | + </el-table-column> | ||
| 71 | + <el-table-column :label="$t('applyRoomDiscount.table.returnType')" align="center"> | ||
| 72 | + <template slot-scope="scope"> | ||
| 73 | + {{ scope.row.discountId ? (scope.row.returnWay === '1002' ? $t('applyRoomDiscount.returnType.account') : | ||
| 74 | + $t('applyRoomDiscount.returnType.discount')) : '-' }} | ||
| 75 | + </template> | ||
| 76 | + </el-table-column> | ||
| 77 | + <el-table-column :label="$t('applyRoomDiscount.table.returnAmount')" align="center"> | ||
| 78 | + <template slot-scope="scope"> | ||
| 79 | + {{ scope.row.returnAmount ? scope.row.returnAmount : '-' }} | ||
| 80 | + </template> | ||
| 81 | + </el-table-column> | ||
| 82 | + <el-table-column :label="$t('common.operation')" align="center" width="300" fixed="right"> | ||
| 83 | + <template slot-scope="scope"> | ||
| 84 | + <el-button v-if="scope.row.state === '1' && hasPrivilege('502021010723590006')" size="mini" | ||
| 85 | + @click="handleOpenCheck(scope.row)"> | ||
| 86 | + {{ $t('applyRoomDiscount.button.check') }} | ||
| 87 | + </el-button> | ||
| 88 | + <el-button size="mini" @click="handleOpenRecord(scope.row)"> | ||
| 89 | + {{ $t('applyRoomDiscount.button.record') }} | ||
| 90 | + </el-button> | ||
| 91 | + <el-button v-if="scope.row.state === '2' && hasPrivilege('502021010761730007')" size="mini" | ||
| 92 | + @click="handleOpenReview(scope.row)"> | ||
| 93 | + {{ $t('applyRoomDiscount.button.review') }} | ||
| 94 | + </el-button> | ||
| 95 | + <el-button size="mini" @click="handleOpenEdit(scope.row)"> | ||
| 96 | + {{ $t('common.edit') }} | ||
| 97 | + </el-button> | ||
| 98 | + <el-button size="mini" type="danger" @click="handleOpenDelete(scope.row)"> | ||
| 99 | + {{ $t('common.delete') }} | ||
| 100 | + </el-button> | ||
| 101 | + </template> | ||
| 102 | + </el-table-column> | ||
| 103 | + </el-table> | ||
| 104 | + | ||
| 105 | + <el-pagination :current-page.sync="pagination.current" :page-sizes="[10, 20, 30, 50]" :page-size="pagination.size" | ||
| 106 | + :total="pagination.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange" | ||
| 107 | + @current-change="handleCurrentChange" /> | ||
| 108 | + </el-card> | ||
| 109 | + | ||
| 110 | + <!-- 子组件 --> | ||
| 111 | + <add-apply-room-discount ref="addApplyRoomDiscount" @success="handleSuccess" /> | ||
| 112 | + <edit-apply-room-discount ref="editApplyRoomDiscount" @success="handleSuccess" /> | ||
| 113 | + <edit-apply-room-discount-record ref="editApplyRoomDiscountRecord" @success="handleSuccess" /> | ||
| 114 | + <review-apply-room-discount ref="reviewApplyRoomDiscount" @success="handleSuccess" /> | ||
| 115 | + <delete-apply-room-discount ref="deleteApplyRoomDiscount" @success="handleSuccess" /> | ||
| 116 | + <view-image ref="viewImage" /> | ||
| 117 | + </div> | ||
| 118 | +</template> | ||
| 119 | + | ||
| 120 | +<script> | ||
| 121 | +import { getDict } from '@/api/community/communityApi' | ||
| 122 | +import { queryApplyRoomDiscount, queryApplyRoomDiscountType } from '@/api/fee/applyRoomDiscountManageApi' | ||
| 123 | +import AddApplyRoomDiscount from '@/components/fee/addApplyRoomDiscount' | ||
| 124 | +import EditApplyRoomDiscount from '@/components/fee/editApplyRoomDiscount' | ||
| 125 | +import EditApplyRoomDiscountRecord from '@/components/fee/editApplyRoomDiscountRecord' | ||
| 126 | +import ReviewApplyRoomDiscount from '@/components/fee/reviewApplyRoomDiscount' | ||
| 127 | +import DeleteApplyRoomDiscount from '@/components/fee/deleteApplyRoomDiscount' | ||
| 128 | +import ViewImage from '@/components/system/viewImage' | ||
| 129 | + | ||
| 130 | +export default { | ||
| 131 | + name: 'ApplyRoomDiscountManageList', | ||
| 132 | + components: { | ||
| 133 | + AddApplyRoomDiscount, | ||
| 134 | + EditApplyRoomDiscount, | ||
| 135 | + EditApplyRoomDiscountRecord, | ||
| 136 | + ReviewApplyRoomDiscount, | ||
| 137 | + DeleteApplyRoomDiscount, | ||
| 138 | + ViewImage | ||
| 139 | + }, | ||
| 140 | + data() { | ||
| 141 | + return { | ||
| 142 | + loading: false, | ||
| 143 | + searchForm: { | ||
| 144 | + roomName: '', | ||
| 145 | + applyType: '', | ||
| 146 | + state: '', | ||
| 147 | + communityId: '' | ||
| 148 | + }, | ||
| 149 | + tableData: [], | ||
| 150 | + applyTypes: [], | ||
| 151 | + states: [], | ||
| 152 | + pagination: { | ||
| 153 | + current: 1, | ||
| 154 | + size: 10, | ||
| 155 | + total: 0 | ||
| 156 | + } | ||
| 157 | + } | ||
| 158 | + }, | ||
| 159 | + created() { | ||
| 160 | + this.getList() | ||
| 161 | + this.getApplyTypes() | ||
| 162 | + this.getDictData() | ||
| 163 | + }, | ||
| 164 | + methods: { | ||
| 165 | + async getList() { | ||
| 166 | + try { | ||
| 167 | + this.loading = true | ||
| 168 | + const params = { | ||
| 169 | + page: this.pagination.current, | ||
| 170 | + row: this.pagination.size, | ||
| 171 | + ...this.searchForm | ||
| 172 | + } | ||
| 173 | + const { data, total } = await queryApplyRoomDiscount(params) | ||
| 174 | + this.tableData = data | ||
| 175 | + this.pagination.total = total | ||
| 176 | + } catch (error) { | ||
| 177 | + this.$message.error(this.$t('applyRoomDiscount.fetchError')) | ||
| 178 | + } finally { | ||
| 179 | + this.loading = false | ||
| 180 | + } | ||
| 181 | + }, | ||
| 182 | + async getApplyTypes() { | ||
| 183 | + try { | ||
| 184 | + const { data } = await queryApplyRoomDiscountType({ | ||
| 185 | + page: 1, | ||
| 186 | + row: 50, | ||
| 187 | + communityId: this.searchForm.communityId | ||
| 188 | + }) | ||
| 189 | + this.applyTypes = data | ||
| 190 | + } catch (error) { | ||
| 191 | + console.error('获取申请类型失败:', error) | ||
| 192 | + } | ||
| 193 | + }, | ||
| 194 | + async getDictData() { | ||
| 195 | + try { | ||
| 196 | + const data = await getDict('apply_room_discount', 'state') | ||
| 197 | + this.states = data | ||
| 198 | + } catch (error) { | ||
| 199 | + console.error('获取字典数据失败:', error) | ||
| 200 | + } | ||
| 201 | + }, | ||
| 202 | + handleSearch() { | ||
| 203 | + this.pagination.current = 1 | ||
| 204 | + this.getList() | ||
| 205 | + }, | ||
| 206 | + handleReset() { | ||
| 207 | + this.searchForm = { | ||
| 208 | + roomName: '', | ||
| 209 | + applyType: '', | ||
| 210 | + state: '', | ||
| 211 | + communityId: '' | ||
| 212 | + } | ||
| 213 | + this.handleSearch() | ||
| 214 | + }, | ||
| 215 | + handleSizeChange(val) { | ||
| 216 | + this.pagination.size = val | ||
| 217 | + this.getList() | ||
| 218 | + }, | ||
| 219 | + handleCurrentChange(val) { | ||
| 220 | + this.pagination.current = val | ||
| 221 | + this.getList() | ||
| 222 | + }, | ||
| 223 | + handleOpenAddApply() { | ||
| 224 | + this.$refs.addApplyRoomDiscount.open() | ||
| 225 | + }, | ||
| 226 | + handleOpenEdit(row) { | ||
| 227 | + this.$refs.editApplyRoomDiscountRecord.open(row) | ||
| 228 | + }, | ||
| 229 | + handleOpenCheck(row) { | ||
| 230 | + this.$refs.editApplyRoomDiscount.open(row) | ||
| 231 | + }, | ||
| 232 | + handleOpenRecord(row) { | ||
| 233 | + this.$router.push({ | ||
| 234 | + path: '/pages/property/listApplyRoomDiscountRecord', | ||
| 235 | + query: { | ||
| 236 | + ardId: row.ardId, | ||
| 237 | + roomId: row.roomId, | ||
| 238 | + roomName: row.roomName, | ||
| 239 | + state: row.state, | ||
| 240 | + stateName: row.stateName | ||
| 241 | + } | ||
| 242 | + }) | ||
| 243 | + }, | ||
| 244 | + handleOpenReview(row) { | ||
| 245 | + this.$refs.reviewApplyRoomDiscount.open(row) | ||
| 246 | + }, | ||
| 247 | + handleOpenDelete(row) { | ||
| 248 | + this.$refs.deleteApplyRoomDiscount.open(row) | ||
| 249 | + }, | ||
| 250 | + handleOpenDiscountType() { | ||
| 251 | + this.$router.push('/views/fee/discountType') | ||
| 252 | + }, | ||
| 253 | + handleExport() { | ||
| 254 | + // 导出逻辑 | ||
| 255 | + }, | ||
| 256 | + handleSuccess() { | ||
| 257 | + this.getList() | ||
| 258 | + }, | ||
| 259 | + } | ||
| 260 | +} | ||
| 261 | +</script> | ||
| 262 | + | ||
| 263 | +<style lang="scss" scoped> | ||
| 264 | +.apply-room-discount-container { | ||
| 265 | + padding: 20px; | ||
| 266 | + | ||
| 267 | + .search-wrapper { | ||
| 268 | + margin-bottom: 20px; | ||
| 269 | + | ||
| 270 | + .el-row { | ||
| 271 | + margin-bottom: -20px; | ||
| 272 | + } | ||
| 273 | + | ||
| 274 | + .el-col { | ||
| 275 | + margin-bottom: 20px; | ||
| 276 | + } | ||
| 277 | + } | ||
| 278 | + | ||
| 279 | + .list-wrapper { | ||
| 280 | + margin-bottom: 20px; | ||
| 281 | + | ||
| 282 | + .el-pagination { | ||
| 283 | + margin-top: 20px; | ||
| 284 | + text-align: right; | ||
| 285 | + } | ||
| 286 | + } | ||
| 287 | +} | ||
| 288 | +</style> | ||
| 0 | \ No newline at end of file | 289 | \ No newline at end of file |
src/views/fee/discountTypeLang.js
0 → 100644
| 1 | +export const messages = { | ||
| 2 | + en: { | ||
| 3 | + discountType: { | ||
| 4 | + search: { | ||
| 5 | + title: 'Search Conditions', | ||
| 6 | + applyType: 'Please enter type code', | ||
| 7 | + typeName: 'Please enter type name' | ||
| 8 | + }, | ||
| 9 | + list: { | ||
| 10 | + title: 'Discount Types' | ||
| 11 | + }, | ||
| 12 | + table: { | ||
| 13 | + applyType: 'Type Code', | ||
| 14 | + typeName: 'Type Name', | ||
| 15 | + typeDesc: 'Type Description', | ||
| 16 | + createTime: 'Create Time' | ||
| 17 | + }, | ||
| 18 | + form: { | ||
| 19 | + applyType: 'Type Code', | ||
| 20 | + typeName: 'Type Name', | ||
| 21 | + typeNamePlaceholder: 'Required, please enter type name', | ||
| 22 | + typeDesc: 'Type Description', | ||
| 23 | + typeDescPlaceholder: 'Optional, please enter type description' | ||
| 24 | + }, | ||
| 25 | + validate: { | ||
| 26 | + applyTypeRequired: 'Type code is required', | ||
| 27 | + typeNameRequired: 'Type name is required', | ||
| 28 | + typeNameMaxLength: 'Type name max length is 64', | ||
| 29 | + typeDescMaxLength: 'Type description max length is 512' | ||
| 30 | + }, | ||
| 31 | + add: { | ||
| 32 | + title: 'Add Discount Type', | ||
| 33 | + success: 'Add success' | ||
| 34 | + }, | ||
| 35 | + edit: { | ||
| 36 | + title: 'Edit Discount Type', | ||
| 37 | + success: 'Edit success' | ||
| 38 | + }, | ||
| 39 | + delete: { | ||
| 40 | + title: 'Delete Confirmation', | ||
| 41 | + confirmText: 'Are you sure to delete this discount type?', | ||
| 42 | + success: 'Delete success' | ||
| 43 | + }, | ||
| 44 | + fetchError: 'Failed to fetch discount types' | ||
| 45 | + }, | ||
| 46 | + common: { | ||
| 47 | + search: 'Search', | ||
| 48 | + add: 'Add', | ||
| 49 | + edit: 'Edit', | ||
| 50 | + delete: 'Delete', | ||
| 51 | + back: 'Back', | ||
| 52 | + cancel: 'Cancel', | ||
| 53 | + confirm: 'Confirm', | ||
| 54 | + operation: 'Operation' | ||
| 55 | + } | ||
| 56 | + }, | ||
| 57 | + zh: { | ||
| 58 | + discountType: { | ||
| 59 | + search: { | ||
| 60 | + title: '查询条件', | ||
| 61 | + applyType: '请输入类型编码', | ||
| 62 | + typeName: '请输入类型名称' | ||
| 63 | + }, | ||
| 64 | + list: { | ||
| 65 | + title: '优惠类型' | ||
| 66 | + }, | ||
| 67 | + table: { | ||
| 68 | + applyType: '类型编码', | ||
| 69 | + typeName: '类型名称', | ||
| 70 | + typeDesc: '类型描述', | ||
| 71 | + createTime: '创建时间' | ||
| 72 | + }, | ||
| 73 | + form: { | ||
| 74 | + applyType: '类型编码', | ||
| 75 | + typeName: '类型名称', | ||
| 76 | + typeNamePlaceholder: '必填,请填写类型名称', | ||
| 77 | + typeDesc: '类型描述', | ||
| 78 | + typeDescPlaceholder: '选填,请填写类型描述' | ||
| 79 | + }, | ||
| 80 | + validate: { | ||
| 81 | + applyTypeRequired: '类型编码不能为空', | ||
| 82 | + typeNameRequired: '类型名称不能为空', | ||
| 83 | + typeNameMaxLength: '类型名称最大长度64', | ||
| 84 | + typeDescMaxLength: '类型描述最大长度512' | ||
| 85 | + }, | ||
| 86 | + add: { | ||
| 87 | + title: '添加优惠类型', | ||
| 88 | + success: '添加成功' | ||
| 89 | + }, | ||
| 90 | + edit: { | ||
| 91 | + title: '修改优惠类型', | ||
| 92 | + success: '修改成功' | ||
| 93 | + }, | ||
| 94 | + delete: { | ||
| 95 | + title: '删除确认', | ||
| 96 | + confirmText: '确定删除该优惠类型吗?', | ||
| 97 | + success: '删除成功' | ||
| 98 | + }, | ||
| 99 | + fetchError: '获取优惠类型失败' | ||
| 100 | + }, | ||
| 101 | + common: { | ||
| 102 | + search: '查询', | ||
| 103 | + add: '添加', | ||
| 104 | + edit: '修改', | ||
| 105 | + delete: '删除', | ||
| 106 | + back: '返回', | ||
| 107 | + cancel: '取消', | ||
| 108 | + confirm: '确认', | ||
| 109 | + operation: '操作' | ||
| 110 | + } | ||
| 111 | + } | ||
| 112 | +} | ||
| 0 | \ No newline at end of file | 113 | \ No newline at end of file |
src/views/fee/discountTypeList.vue
0 → 100644
| 1 | +<template> | ||
| 2 | + <div class="discount-type-container"> | ||
| 3 | + <!-- 查询条件 --> | ||
| 4 | + <el-card class="search-card"> | ||
| 5 | + <div slot="header" class="clearfix"> | ||
| 6 | + <span>{{ $t('discountType.search.title') }}</span> | ||
| 7 | + </div> | ||
| 8 | + <el-row :gutter="20"> | ||
| 9 | + <el-col :span="6"> | ||
| 10 | + <el-input | ||
| 11 | + v-model.trim="searchForm.applyType" | ||
| 12 | + :placeholder="$t('discountType.search.applyType')" | ||
| 13 | + clearable | ||
| 14 | + /> | ||
| 15 | + </el-col> | ||
| 16 | + <el-col :span="6"> | ||
| 17 | + <el-input | ||
| 18 | + v-model.trim="searchForm.typeName" | ||
| 19 | + :placeholder="$t('discountType.search.typeName')" | ||
| 20 | + clearable | ||
| 21 | + /> | ||
| 22 | + </el-col> | ||
| 23 | + <el-col :span="4"> | ||
| 24 | + <el-button type="primary" @click="handleSearch"> | ||
| 25 | + {{ $t('common.search') }} | ||
| 26 | + </el-button> | ||
| 27 | + </el-col> | ||
| 28 | + </el-row> | ||
| 29 | + </el-card> | ||
| 30 | + | ||
| 31 | + <!-- 列表 --> | ||
| 32 | + <el-card class="list-card"> | ||
| 33 | + <div slot="header" class="clearfix"> | ||
| 34 | + <span>{{ $t('discountType.list.title') }}</span> | ||
| 35 | + <div style="float: right;"> | ||
| 36 | + <el-button type="primary" size="small" @click="handleAdd"> | ||
| 37 | + {{ $t('common.add') }} | ||
| 38 | + </el-button> | ||
| 39 | + <el-button size="small" @click="goBack"> | ||
| 40 | + {{ $t('common.back') }} | ||
| 41 | + </el-button> | ||
| 42 | + </div> | ||
| 43 | + </div> | ||
| 44 | + | ||
| 45 | + <el-table | ||
| 46 | + v-loading="loading" | ||
| 47 | + :data="tableData" | ||
| 48 | + border | ||
| 49 | + style="width: 100%" | ||
| 50 | + > | ||
| 51 | + <el-table-column | ||
| 52 | + prop="applyType" | ||
| 53 | + :label="$t('discountType.table.applyType')" | ||
| 54 | + align="center" | ||
| 55 | + /> | ||
| 56 | + <el-table-column | ||
| 57 | + prop="typeName" | ||
| 58 | + :label="$t('discountType.table.typeName')" | ||
| 59 | + align="center" | ||
| 60 | + /> | ||
| 61 | + <el-table-column | ||
| 62 | + prop="typeDesc" | ||
| 63 | + :label="$t('discountType.table.typeDesc')" | ||
| 64 | + align="center" | ||
| 65 | + /> | ||
| 66 | + <el-table-column | ||
| 67 | + prop="createTime" | ||
| 68 | + :label="$t('discountType.table.createTime')" | ||
| 69 | + align="center" | ||
| 70 | + /> | ||
| 71 | + <el-table-column | ||
| 72 | + :label="$t('common.operation')" | ||
| 73 | + align="center" | ||
| 74 | + width="200" | ||
| 75 | + > | ||
| 76 | + <template slot-scope="scope"> | ||
| 77 | + <el-button | ||
| 78 | + size="mini" | ||
| 79 | + type="primary" | ||
| 80 | + @click="handleEdit(scope.row)" | ||
| 81 | + > | ||
| 82 | + {{ $t('common.edit') }} | ||
| 83 | + </el-button> | ||
| 84 | + <el-button | ||
| 85 | + size="mini" | ||
| 86 | + type="danger" | ||
| 87 | + @click="handleDelete(scope.row)" | ||
| 88 | + > | ||
| 89 | + {{ $t('common.delete') }} | ||
| 90 | + </el-button> | ||
| 91 | + </template> | ||
| 92 | + </el-table-column> | ||
| 93 | + </el-table> | ||
| 94 | + | ||
| 95 | + <el-pagination | ||
| 96 | + :current-page.sync="page.current" | ||
| 97 | + :page-sizes="[10, 20, 30, 50]" | ||
| 98 | + :page-size="page.size" | ||
| 99 | + :total="page.total" | ||
| 100 | + layout="total, sizes, prev, pager, next, jumper" | ||
| 101 | + @size-change="handleSizeChange" | ||
| 102 | + @current-change="handleCurrentChange" | ||
| 103 | + /> | ||
| 104 | + </el-card> | ||
| 105 | + | ||
| 106 | + <!-- 组件 --> | ||
| 107 | + <add-apply-room-discount-type ref="addDialog" @success="handleSuccess" /> | ||
| 108 | + <edit-apply-room-discount-type ref="editDialog" @success="handleSuccess" /> | ||
| 109 | + <delete-apply-room-discount-type ref="deleteDialog" @success="handleSuccess" /> | ||
| 110 | + </div> | ||
| 111 | +</template> | ||
| 112 | + | ||
| 113 | +<script> | ||
| 114 | +import { queryApplyRoomDiscountType } from '@/api/fee/discountTypeApi' | ||
| 115 | +import { getCommunityId } from '@/api/community/communityApi' | ||
| 116 | +import AddApplyRoomDiscountType from '@/components/fee/addApplyRoomDiscountType' | ||
| 117 | +import EditApplyRoomDiscountType from '@/components/fee/editApplyRoomDiscountType' | ||
| 118 | +import DeleteApplyRoomDiscountType from '@/components/fee/deleteApplyRoomDiscountType' | ||
| 119 | + | ||
| 120 | +export default { | ||
| 121 | + name: 'DiscountTypeList', | ||
| 122 | + components: { | ||
| 123 | + AddApplyRoomDiscountType, | ||
| 124 | + EditApplyRoomDiscountType, | ||
| 125 | + DeleteApplyRoomDiscountType | ||
| 126 | + }, | ||
| 127 | + data() { | ||
| 128 | + return { | ||
| 129 | + loading: false, | ||
| 130 | + searchForm: { | ||
| 131 | + applyType: '', | ||
| 132 | + typeName: '', | ||
| 133 | + communityId: '' | ||
| 134 | + }, | ||
| 135 | + tableData: [], | ||
| 136 | + page: { | ||
| 137 | + current: 1, | ||
| 138 | + size: 10, | ||
| 139 | + total: 0 | ||
| 140 | + } | ||
| 141 | + } | ||
| 142 | + }, | ||
| 143 | + created() { | ||
| 144 | + this.getList() | ||
| 145 | + }, | ||
| 146 | + methods: { | ||
| 147 | + async getList() { | ||
| 148 | + try { | ||
| 149 | + this.loading = true | ||
| 150 | + this.searchForm.communityId = getCommunityId() | ||
| 151 | + const params = { | ||
| 152 | + page: this.page.current, | ||
| 153 | + row: this.page.size, | ||
| 154 | + ...this.searchForm | ||
| 155 | + } | ||
| 156 | + const { data, total } = await queryApplyRoomDiscountType(params) | ||
| 157 | + this.tableData = data | ||
| 158 | + this.page.total = total | ||
| 159 | + } catch (error) { | ||
| 160 | + this.$message.error(this.$t('discountType.fetchError')) | ||
| 161 | + } finally { | ||
| 162 | + this.loading = false | ||
| 163 | + } | ||
| 164 | + }, | ||
| 165 | + handleSearch() { | ||
| 166 | + this.page.current = 1 | ||
| 167 | + this.getList() | ||
| 168 | + }, | ||
| 169 | + handleAdd() { | ||
| 170 | + this.$refs.addDialog.open() | ||
| 171 | + }, | ||
| 172 | + handleEdit(row) { | ||
| 173 | + this.$refs.editDialog.open(row) | ||
| 174 | + }, | ||
| 175 | + handleDelete(row) { | ||
| 176 | + this.$refs.deleteDialog.open(row) | ||
| 177 | + }, | ||
| 178 | + handleSuccess() { | ||
| 179 | + this.getList() | ||
| 180 | + }, | ||
| 181 | + handleSizeChange(val) { | ||
| 182 | + this.page.size = val | ||
| 183 | + this.getList() | ||
| 184 | + }, | ||
| 185 | + handleCurrentChange(val) { | ||
| 186 | + this.page.current = val | ||
| 187 | + this.getList() | ||
| 188 | + }, | ||
| 189 | + goBack() { | ||
| 190 | + this.$router.go(-1) | ||
| 191 | + } | ||
| 192 | + } | ||
| 193 | +} | ||
| 194 | +</script> | ||
| 195 | + | ||
| 196 | +<style lang="scss" scoped> | ||
| 197 | +.discount-type-container { | ||
| 198 | + padding: 20px; | ||
| 199 | + | ||
| 200 | + .search-card { | ||
| 201 | + margin-bottom: 20px; | ||
| 202 | + } | ||
| 203 | + | ||
| 204 | + .el-pagination { | ||
| 205 | + margin-top: 20px; | ||
| 206 | + text-align: right; | ||
| 207 | + } | ||
| 208 | +} | ||
| 209 | +</style> | ||
| 0 | \ No newline at end of file | 210 | \ No newline at end of file |