Commit 7505cb92edbfec5d09a29cab1f8daa264fe4ac45

Authored by wuxw
1 parent 9d8dc2e6

开发完成折扣设置

src/api/fee/feeDiscountManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 查询折扣列表
  5 +export function queryFeeDiscount(params) {
  6 + return new Promise((resolve, reject) => {
  7 + request({
  8 + url: '/feeDiscount/queryFeeDiscount',
  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 +export function queryFeeDiscountRule(params) {
  25 + return new Promise((resolve, reject) => {
  26 + request({
  27 + url: '/feeDiscount/queryFeeDiscountRule',
  28 + method: 'get',
  29 + params: {
  30 + ...params,
  31 + communityId: getCommunityId()
  32 + }
  33 + }).then(response => {
  34 + const res = response.data
  35 + resolve(res)
  36 + }).catch(error => {
  37 + reject(error)
  38 + })
  39 + })
  40 +}
  41 +
  42 +// 添加折扣
  43 +export function saveFeeDiscount(data) {
  44 + return new Promise((resolve, reject) => {
  45 + request({
  46 + url: '/feeDiscount/saveFeeDiscount',
  47 + method: 'post',
  48 + data: {
  49 + ...data,
  50 + communityId: getCommunityId()
  51 + }
  52 + }).then(response => {
  53 + const res = response.data
  54 + resolve(res)
  55 + }).catch(error => {
  56 + reject(error)
  57 + })
  58 + })
  59 +}
  60 +
  61 +// 更新折扣
  62 +export function updateFeeDiscount(data) {
  63 + return new Promise((resolve, reject) => {
  64 + request({
  65 + url: '/feeDiscount/updateFeeDiscount',
  66 + method: 'post',
  67 + data: {
  68 + ...data,
  69 + communityId: getCommunityId()
  70 + }
  71 + }).then(response => {
  72 + const res = response.data
  73 + resolve(res)
  74 + }).catch(error => {
  75 + reject(error)
  76 + })
  77 + })
  78 +}
  79 +
  80 +// 删除折扣
  81 +export function deleteFeeDiscount(data) {
  82 + return new Promise((resolve, reject) => {
  83 + request({
  84 + url: '/feeDiscount/deleteFeeDiscount',
  85 + method: 'post',
  86 + data: {
  87 + ...data,
  88 + communityId: getCommunityId()
  89 + }
  90 + }).then(response => {
  91 + const res = response.data
  92 + resolve(res)
  93 + }).catch(error => {
  94 + reject(error)
  95 + })
  96 + })
  97 +}
0 98 \ No newline at end of file
... ...
src/api/fee/returnPayFeeManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 获取退费申请单列表
  5 +export function listReturnPayFees(params) {
  6 + return new Promise((resolve, reject) => {
  7 + // 确保社区ID存在
  8 + if (!params.communityId) {
  9 + params.communityId = getCommunityId()
  10 + }
  11 +
  12 + request({
  13 + url: '/returnPayFee.listReturnPayFees',
  14 + method: 'get',
  15 + params
  16 + }).then(response => {
  17 + const res = response.data
  18 + resolve(res)
  19 + }).catch(error => {
  20 + reject(error)
  21 + })
  22 + })
  23 +}
  24 +
  25 +// 更新退费申请单状态
  26 +export function updateReturnPayFee(data) {
  27 + return new Promise((resolve, reject) => {
  28 + // 确保社区ID存在
  29 + if (!data.communityId) {
  30 + data.communityId = getCommunityId()
  31 + }
  32 +
  33 + request({
  34 + url: '/returnPayFee.updateReturnPayFee',
  35 + method: 'post',
  36 + data,
  37 + headers: {
  38 + 'Content-Type': 'application/json'
  39 + }
  40 + }).then(response => {
  41 + const res = response.data
  42 + resolve(res)
  43 + }).catch(error => {
  44 + reject(error)
  45 + })
  46 + })
  47 +}
  48 +
  49 +// 尝试退款
  50 +export function tryRefundMoney(data) {
  51 + return new Promise((resolve, reject) => {
  52 + // 确保社区ID存在
  53 + if (!data.communityId) {
  54 + data.communityId = getCommunityId()
  55 + }
  56 +
  57 + request({
  58 + url: '/returnPayFee.tryRefundMoney',
  59 + method: 'post',
  60 + data,
  61 + headers: {
  62 + 'Content-Type': 'application/json'
  63 + }
  64 + }).then(response => {
  65 + const res = response.data
  66 + resolve(res)
  67 + }).catch(error => {
  68 + reject(error)
  69 + })
  70 + })
  71 +}
  72 +
  73 +// 获取字典数据
  74 +export function getDict(dictType, state) {
  75 + return new Promise((resolve, reject) => {
  76 + request({
  77 + url: '/dict.getDict',
  78 + method: 'get',
  79 + params: {
  80 + dictType,
  81 + state,
  82 + communityId: getCommunityId()
  83 + }
  84 + }).then(response => {
  85 + const res = response.data
  86 + resolve(res)
  87 + }).catch(error => {
  88 + reject(error)
  89 + })
  90 + })
  91 +}
0 92 \ No newline at end of file
... ...
src/components/fee/addFeeDiscount.vue 0 → 100644
  1 +<template>
  2 + <el-dialog :title="$t('feeDiscountManage.add.title')" :visible.sync="visible" width="60%" @close="handleClose">
  3 + <el-form ref="form" :model="addFeeDiscountInfo" label-width="120px" :rules="rules">
  4 + <el-form-item :label="$t('feeDiscountManage.add.discountName')" prop="discountName">
  5 + <el-input v-model.trim="addFeeDiscountInfo.discountName"
  6 + :placeholder="$t('feeDiscountManage.add.discountNamePlaceholder')" />
  7 + </el-form-item>
  8 + <el-form-item :label="$t('feeDiscountManage.add.discountType')" prop="discountType">
  9 + <el-select v-model="addFeeDiscountInfo.discountType"
  10 + :placeholder="$t('feeDiscountManage.add.discountTypePlaceholder')" style="width:100%"
  11 + @change="_changeAddFeeDiscountType">
  12 + <el-option v-for="item in addFeeDiscountInfo.discountTypes" :key="item.statusCd" :label="item.name"
  13 + :value="item.statusCd" />
  14 + </el-select>
  15 + </el-form-item>
  16 + <el-form-item :label="$t('feeDiscountManage.add.rule')" prop="ruleId">
  17 + <el-select v-model="addFeeDiscountInfo.ruleId" :placeholder="$t('feeDiscountManage.add.rulePlaceholder')"
  18 + style="width:100%" @change="_changeAddFeeDiscountRule">
  19 + <el-option v-for="item in addFeeDiscountInfo.rules" :key="item.ruleId" :label="item.ruleName"
  20 + :value="item.ruleId" />
  21 + </el-select>
  22 + </el-form-item>
  23 + <el-form-item v-for="(item, index) in addFeeDiscountInfo.feeDiscountRuleSpecs" :key="index" :label="item.specName"
  24 + :prop="'feeDiscountRuleSpecs.' + index + '.specValue'" :rules="{
  25 + required: true,
  26 + message: $t('feeDiscountManage.add.specValueRequired', { specName: item.specName }),
  27 + trigger: 'blur'
  28 + }">
  29 + <el-input v-model.trim="item.specValue" type="number" :placeholder="item.remark" />
  30 + </el-form-item>
  31 + <el-form-item :label="$t('feeDiscountManage.add.discountDesc')">
  32 + <el-input v-model.trim="addFeeDiscountInfo.discountDesc" type="textarea"
  33 + :placeholder="$t('feeDiscountManage.add.discountDescPlaceholder')" :rows="3" />
  34 + </el-form-item>
  35 + </el-form>
  36 + <span slot="footer" class="dialog-footer">
  37 + <el-button @click="visible = false">
  38 + {{ $t('common.cancel') }}
  39 + </el-button>
  40 + <el-button type="primary" @click="saveFeeDiscountInfo">
  41 + {{ $t('common.save') }}
  42 + </el-button>
  43 + </span>
  44 + </el-dialog>
  45 +</template>
  46 +
  47 +<script>
  48 +import { getDict } from '@/api/community/communityApi'
  49 +import { saveFeeDiscount, queryFeeDiscountRule } from '@/api/fee/feeDiscountManageApi'
  50 +import { getCommunityId } from '@/api/community/communityApi'
  51 +
  52 +export default {
  53 + name: 'AddFeeDiscount',
  54 + data() {
  55 + return {
  56 + visible: false,
  57 + addFeeDiscountInfo: {
  58 + discountName: '',
  59 + discountType: '',
  60 + discountTypes: [],
  61 + ruleId: '',
  62 + discountDesc: '',
  63 + rules: [],
  64 + feeDiscountRuleSpecs: [],
  65 + communityId: ''
  66 + },
  67 + rules: {
  68 + discountName: [
  69 + { required: true, message: this.$t('feeDiscountManage.add.discountNameRequired'), trigger: 'blur' },
  70 + { max: 256, message: this.$t('feeDiscountManage.add.discountNameMaxLength'), trigger: 'blur' }
  71 + ],
  72 + discountType: [
  73 + { required: true, message: this.$t('feeDiscountManage.add.discountTypeRequired'), trigger: 'change' }
  74 + ],
  75 + ruleId: [
  76 + { required: true, message: this.$t('feeDiscountManage.add.ruleRequired'), trigger: 'change' }
  77 + ]
  78 + }
  79 + }
  80 + },
  81 + methods: {
  82 + open() {
  83 + this.visible = true
  84 + this.getCommunityId()
  85 + this.getDictData()
  86 + },
  87 + async getCommunityId() {
  88 + try {
  89 + const communityId = await getCommunityId()
  90 + this.addFeeDiscountInfo.communityId = communityId
  91 + } catch (error) {
  92 + console.error('获取communityId失败:', error)
  93 + }
  94 + },
  95 + async getDictData() {
  96 + try {
  97 + const data = await getDict('fee_discount', 'discount_type')
  98 + this.addFeeDiscountInfo.discountTypes = data
  99 + } catch (error) {
  100 + console.error('获取字典数据失败:', error)
  101 + }
  102 + },
  103 + async _loadAddFeeDiscountRules() {
  104 + if (!this.addFeeDiscountInfo.discountType) return
  105 +
  106 + try {
  107 + const params = {
  108 + page: 1,
  109 + row: 100,
  110 + discountType: this.addFeeDiscountInfo.discountType
  111 + }
  112 + const { data } = await queryFeeDiscountRule(params)
  113 + this.addFeeDiscountInfo.rules = data
  114 + } catch (error) {
  115 + console.error('获取规则列表失败:', error)
  116 + }
  117 + },
  118 + _changeAddFeeDiscountRule() {
  119 + const selectedRule = this.addFeeDiscountInfo.rules.find(
  120 + item => item.ruleId === this.addFeeDiscountInfo.ruleId
  121 + )
  122 + if (selectedRule) {
  123 + this.addFeeDiscountInfo.feeDiscountRuleSpecs = selectedRule.feeDiscountRuleSpecs.map(item => ({
  124 + ...item,
  125 + specValue: ''
  126 + }))
  127 + }
  128 + },
  129 + _changeAddFeeDiscountType() {
  130 + this.addFeeDiscountInfo.ruleId = ''
  131 + this.addFeeDiscountInfo.feeDiscountRuleSpecs = []
  132 + this._loadAddFeeDiscountRules()
  133 + },
  134 + async saveFeeDiscountInfo() {
  135 + this.$refs.form.validate(async valid => {
  136 + if (!valid) return
  137 +
  138 + try {
  139 + await saveFeeDiscount(this.addFeeDiscountInfo)
  140 + this.$message.success(this.$t('common.saveSuccess'))
  141 + this.$emit('success')
  142 + this.visible = false
  143 + this.resetForm()
  144 + } catch (error) {
  145 + console.error('保存折扣信息失败:', error)
  146 + }
  147 + })
  148 + },
  149 + resetForm() {
  150 + this.$refs.form.resetFields()
  151 + this.addFeeDiscountInfo = {
  152 + discountName: '',
  153 + discountType: '',
  154 + discountTypes: this.addFeeDiscountInfo.discountTypes,
  155 + ruleId: '',
  156 + discountDesc: '',
  157 + rules: [],
  158 + feeDiscountRuleSpecs: [],
  159 + communityId: this.addFeeDiscountInfo.communityId
  160 + }
  161 + },
  162 + handleClose() {
  163 + this.resetForm()
  164 + }
  165 + }
  166 +}
  167 +</script>
0 168 \ No newline at end of file
... ...
src/components/fee/audit.vue
... ... @@ -3,14 +3,14 @@
3 3 :title="$t('audit.title')"
4 4 :visible.sync="visible"
5 5 width="50%"
6   - @close="closeDialog"
  6 + @close="handleClose"
7 7 >
8   - <el-form label-width="120px">
9   - <el-form-item :label="$t('audit.status')">
  8 + <el-form ref="form" :model="auditInfo" label-width="120px">
  9 + <el-form-item :label="$t('audit.state')" prop="state" required>
10 10 <el-select
11   - v-model="form.state"
12   - :placeholder="$t('audit.statusRequired')"
13   - style="width: 100%"
  11 + v-model="auditInfo.state"
  12 + :placeholder="$t('audit.selectState')"
  13 + style="width:100%"
14 14 >
15 15 <el-option
16 16 :label="$t('audit.approve')"
... ... @@ -22,68 +22,63 @@
22 22 />
23 23 </el-select>
24 24 </el-form-item>
25   - <el-form-item :label="$t('audit.reason')">
  25 + <el-form-item :label="$t('audit.remark')" prop="remark" required>
26 26 <el-input
27   - v-model="form.remark"
  27 + v-model="auditInfo.remark"
28 28 type="textarea"
29   - :rows="3"
30   - :placeholder="$t('audit.reasonRequired')"
  29 + :rows="4"
  30 + :placeholder="$t('audit.remarkPlaceholder')"
31 31 />
32 32 </el-form-item>
33 33 </el-form>
34   - <div slot="footer">
35   - <el-button @click="closeDialog">{{ $t('common.cancel') }}</el-button>
36   - <el-button
37   - type="primary"
38   - @click="submitAudit"
39   - >{{ $t('common.submit') }}</el-button>
40   - </div>
  34 + <span slot="footer" class="dialog-footer">
  35 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  36 + <el-button type="primary" @click="handleSubmit">{{ $t('common.submit') }}</el-button>
  37 + </span>
41 38 </el-dialog>
42 39 </template>
43 40  
44 41 <script>
45 42 export default {
46   - name: 'AuditDialog',
  43 + name: 'AuditComponent',
47 44 data() {
48 45 return {
49 46 visible: false,
50   - form: {
  47 + auditInfo: {
51 48 state: '',
52 49 remark: ''
53 50 }
54 51 }
55 52 },
56 53 watch: {
57   - 'form.state'(val) {
  54 + 'auditInfo.state'(val) {
58 55 if (val === '1100') {
59   - this.form.remark = this.$t('audit.approve')
60   - } else if (val === '1200') {
61   - this.form.remark = this.$t('audit.reject') + ': '
  56 + this.auditInfo.remark = this.$t('audit.approve')
  57 + } else {
  58 + this.auditInfo.remark = ''
62 59 }
63 60 }
64 61 },
65 62 methods: {
66 63 open() {
67   - this.form = {
68   - state: '',
69   - remark: ''
70   - }
71 64 this.visible = true
72 65 },
73   - closeDialog() {
74   - this.visible = false
  66 + handleClose() {
  67 + this.$refs.form.resetFields()
75 68 },
76   - submitAudit() {
77   - if (!this.form.state) {
78   - this.$message.warning(this.$t('audit.statusRequired'))
79   - return
80   - }
81   - if (!this.form.remark) {
82   - this.$message.warning(this.$t('audit.reasonRequired'))
83   - return
84   - }
85   - this.$emit('success', this.form)
86   - this.closeDialog()
  69 + handleSubmit() {
  70 + this.$refs.form.validate(valid => {
  71 + if (valid) {
  72 + const auditInfo = {
  73 + state: this.auditInfo.state,
  74 + remark: this.auditInfo.state === '1200'
  75 + ? `${this.$t('audit.reject')}: ${this.auditInfo.remark}`
  76 + : this.auditInfo.remark
  77 + }
  78 + this.$emit('notifyAuditInfo', auditInfo)
  79 + this.visible = false
  80 + }
  81 + })
87 82 }
88 83 }
89 84 }
... ...
src/components/fee/deleteFeeDiscount.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('feeDiscountManage.delete.title')"
  4 + :visible.sync="visible"
  5 + width="30%"
  6 + @close="handleClose"
  7 + >
  8 + <div class="text-center">
  9 + <p>{{ $t('feeDiscountManage.delete.confirmText') }}</p>
  10 + </div>
  11 + <span slot="footer" class="dialog-footer">
  12 + <el-button @click="visible = false">
  13 + {{ $t('common.cancel') }}
  14 + </el-button>
  15 + <el-button type="primary" @click="deleteFeeDiscount">
  16 + {{ $t('common.confirm') }}
  17 + </el-button>
  18 + </span>
  19 + </el-dialog>
  20 +</template>
  21 +
  22 +<script>
  23 +import { deleteFeeDiscount } from '@/api/fee/feeDiscountManageApi'
  24 +import { getCommunityId } from '@/api/community/communityApi'
  25 +
  26 +export default {
  27 + name: 'DeleteFeeDiscount',
  28 + data() {
  29 + return {
  30 + visible: false,
  31 + deleteFeeDiscountInfo: {
  32 + discountId: '',
  33 + communityId: ''
  34 + }
  35 + }
  36 + },
  37 + methods: {
  38 + open(row) {
  39 + this.visible = true
  40 + this.getCommunityId()
  41 + this.deleteFeeDiscountInfo.discountId = row.discountId
  42 + },
  43 + async getCommunityId() {
  44 + try {
  45 + const communityId = await getCommunityId()
  46 + this.deleteFeeDiscountInfo.communityId = communityId
  47 + } catch (error) {
  48 + console.error('获取communityId失败:', error)
  49 + }
  50 + },
  51 + async deleteFeeDiscount() {
  52 + try {
  53 + await deleteFeeDiscount(this.deleteFeeDiscountInfo)
  54 + this.$message.success(this.$t('common.deleteSuccess'))
  55 + this.$emit('success')
  56 + this.visible = false
  57 + this.resetForm()
  58 + } catch (error) {
  59 + console.error('删除折扣信息失败:', error)
  60 + }
  61 + },
  62 + resetForm() {
  63 + this.deleteFeeDiscountInfo = {
  64 + discountId: '',
  65 + communityId: this.deleteFeeDiscountInfo.communityId
  66 + }
  67 + },
  68 + handleClose() {
  69 + this.resetForm()
  70 + }
  71 + }
  72 +}
  73 +</script>
0 74 \ No newline at end of file
... ...
src/components/fee/editFeeDiscount.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('feeDiscountManage.edit.title')"
  4 + :visible.sync="visible"
  5 + width="60%"
  6 + @close="handleClose"
  7 + >
  8 + <el-form
  9 + ref="form"
  10 + :model="editFeeDiscountInfo"
  11 + label-width="120px"
  12 + :rules="rules"
  13 + >
  14 + <el-form-item
  15 + :label="$t('feeDiscountManage.edit.discountName')"
  16 + prop="discountName"
  17 + >
  18 + <el-input
  19 + v-model.trim="editFeeDiscountInfo.discountName"
  20 + :placeholder="$t('feeDiscountManage.edit.discountNamePlaceholder')"
  21 + />
  22 + </el-form-item>
  23 + <el-form-item
  24 + :label="$t('feeDiscountManage.edit.discountType')"
  25 + prop="discountType"
  26 + >
  27 + <el-select
  28 + v-model="editFeeDiscountInfo.discountType"
  29 + :placeholder="$t('feeDiscountManage.edit.discountTypePlaceholder')"
  30 + style="width:100%"
  31 + @change="_changeEditFeeDiscountType"
  32 + >
  33 + <el-option
  34 + v-for="item in editFeeDiscountInfo.discountTypes"
  35 + :key="item.statusCd"
  36 + :label="item.name"
  37 + :value="item.statusCd"
  38 + />
  39 + </el-select>
  40 + </el-form-item>
  41 + <el-form-item
  42 + :label="$t('feeDiscountManage.edit.rule')"
  43 + prop="ruleId"
  44 + >
  45 + <el-select
  46 + v-model="editFeeDiscountInfo.ruleId"
  47 + :placeholder="$t('feeDiscountManage.edit.rulePlaceholder')"
  48 + style="width:100%"
  49 + @change="_changeEditFeeDiscountRule"
  50 + >
  51 + <el-option
  52 + v-for="item in editFeeDiscountInfo.rules"
  53 + :key="item.ruleId"
  54 + :label="item.ruleName"
  55 + :value="item.ruleId"
  56 + />
  57 + </el-select>
  58 + </el-form-item>
  59 + <el-form-item
  60 + v-for="(item,index) in editFeeDiscountInfo.feeDiscountRuleSpecs"
  61 + :key="index"
  62 + :label="item.specName"
  63 + :prop="'feeDiscountRuleSpecs.' + index + '.specValue'"
  64 + :rules="{
  65 + required: true,
  66 + message: $t('feeDiscountManage.edit.specValueRequired', {specName: item.specName}),
  67 + trigger: 'blur'
  68 + }"
  69 + >
  70 + <el-input
  71 + v-model.trim="item.specValue"
  72 + type="number"
  73 + :placeholder="item.remark"
  74 + />
  75 + </el-form-item>
  76 + <el-form-item :label="$t('feeDiscountManage.edit.discountDesc')">
  77 + <el-input
  78 + v-model.trim="editFeeDiscountInfo.discountDesc"
  79 + type="textarea"
  80 + :placeholder="$t('feeDiscountManage.edit.discountDescPlaceholder')"
  81 + :rows="3"
  82 + />
  83 + </el-form-item>
  84 + </el-form>
  85 + <span slot="footer" class="dialog-footer">
  86 + <el-button @click="visible = false">
  87 + {{ $t('common.cancel') }}
  88 + </el-button>
  89 + <el-button type="primary" @click="editFeeDiscount">
  90 + {{ $t('common.save') }}
  91 + </el-button>
  92 + </span>
  93 + </el-dialog>
  94 +</template>
  95 +
  96 +<script>
  97 +import { getDict } from '@/api/community/communityApi'
  98 +import { updateFeeDiscount, queryFeeDiscountRule } from '@/api/fee/feeDiscountManageApi'
  99 +import { getCommunityId } from '@/api/community/communityApi'
  100 +
  101 +export default {
  102 + name: 'EditFeeDiscount',
  103 + data() {
  104 + return {
  105 + visible: false,
  106 + editFeeDiscountInfo: {
  107 + discountId: '',
  108 + discountName: '',
  109 + discountType: '',
  110 + discountTypes: [],
  111 + ruleId: '',
  112 + discountDesc: '',
  113 + rules: [],
  114 + feeDiscountRuleSpecs: [],
  115 + communityId: ''
  116 + },
  117 + rules: {
  118 + discountName: [
  119 + { required: true, message: this.$t('feeDiscountManage.edit.discountNameRequired'), trigger: 'blur' },
  120 + { max: 256, message: this.$t('feeDiscountManage.edit.discountNameMaxLength'), trigger: 'blur' }
  121 + ],
  122 + discountType: [
  123 + { required: true, message: this.$t('feeDiscountManage.edit.discountTypeRequired'), trigger: 'change' }
  124 + ],
  125 + ruleId: [
  126 + { required: true, message: this.$t('feeDiscountManage.edit.ruleRequired'), trigger: 'change' }
  127 + ],
  128 + discountId: [
  129 + { required: true, message: this.$t('feeDiscountManage.edit.discountIdRequired'), trigger: 'blur' }
  130 + ]
  131 + }
  132 + }
  133 + },
  134 + methods: {
  135 + open(row) {
  136 + this.visible = true
  137 + this.getCommunityId()
  138 + this.getDictData()
  139 + this.$nextTick(() => {
  140 + this.editFeeDiscountInfo = {
  141 + ...row,
  142 + discountTypes: this.editFeeDiscountInfo.discountTypes,
  143 + rules: this.editFeeDiscountInfo.rules,
  144 + feeDiscountRuleSpecs: row.feeDiscountSpecs || [],
  145 + communityId: this.editFeeDiscountInfo.communityId
  146 + }
  147 + })
  148 + },
  149 + async getCommunityId() {
  150 + try {
  151 + const communityId = await getCommunityId()
  152 + this.editFeeDiscountInfo.communityId = communityId
  153 + } catch (error) {
  154 + console.error('获取communityId失败:', error)
  155 + }
  156 + },
  157 + async getDictData() {
  158 + try {
  159 + const data = await getDict('fee_discount', 'discount_type')
  160 + this.editFeeDiscountInfo.discountTypes = data
  161 + } catch (error) {
  162 + console.error('获取字典数据失败:', error)
  163 + }
  164 + },
  165 + async _loadEditFeeDiscountRules() {
  166 + if (!this.editFeeDiscountInfo.discountType) return
  167 +
  168 + try {
  169 + const params = {
  170 + page: 1,
  171 + row: 100,
  172 + discountType: this.editFeeDiscountInfo.discountType
  173 + }
  174 + const { data } = await queryFeeDiscountRule(params)
  175 + this.editFeeDiscountInfo.rules = data
  176 + } catch (error) {
  177 + console.error('获取规则列表失败:', error)
  178 + }
  179 + },
  180 + _changeEditFeeDiscountRule() {
  181 + const selectedRule = this.editFeeDiscountInfo.rules.find(
  182 + item => item.ruleId === this.editFeeDiscountInfo.ruleId
  183 + )
  184 + if (selectedRule) {
  185 + this.editFeeDiscountInfo.feeDiscountRuleSpecs = selectedRule.feeDiscountRuleSpecs.map(item => ({
  186 + ...item,
  187 + specValue: ''
  188 + }))
  189 + }
  190 + },
  191 + _changeEditFeeDiscountType() {
  192 + this.editFeeDiscountInfo.ruleId = ''
  193 + this.editFeeDiscountInfo.feeDiscountRuleSpecs = []
  194 + this._loadEditFeeDiscountRules()
  195 + },
  196 + async editFeeDiscount() {
  197 + this.$refs.form.validate(async valid => {
  198 + if (!valid) return
  199 +
  200 + try {
  201 + await updateFeeDiscount(this.editFeeDiscountInfo)
  202 + this.$message.success(this.$t('common.saveSuccess'))
  203 + this.$emit('success')
  204 + this.visible = false
  205 + this.resetForm()
  206 + } catch (error) {
  207 + console.error('更新折扣信息失败:', error)
  208 + }
  209 + })
  210 + },
  211 + resetForm() {
  212 + this.$refs.form.resetFields()
  213 + this.editFeeDiscountInfo = {
  214 + discountId: '',
  215 + discountName: '',
  216 + discountType: '',
  217 + discountTypes: this.editFeeDiscountInfo.discountTypes,
  218 + ruleId: '',
  219 + discountDesc: '',
  220 + rules: [],
  221 + feeDiscountRuleSpecs: [],
  222 + communityId: this.editFeeDiscountInfo.communityId
  223 + }
  224 + },
  225 + handleClose() {
  226 + this.resetForm()
  227 + }
  228 + }
  229 +}
  230 +</script>
0 231 \ No newline at end of file
... ...
src/i18n/feeI18n.js
1 1 import { messages as contractCreateFeeMessages } from '../views/fee/contractCreateFeeLang'
2 2 import { messages as meterWaterManageMessages } from '../views/fee/meterWaterManageLang'
3 3 import { messages as meterTypeManageMessages } from '../views/fee/meterTypeManageLang'
  4 +import { messages as returnPayFeeManageMessages } from '../views/fee/returnPayFeeManageLang'
  5 +import { messages as feeDiscountManageMessages } from '../views/fee/feeDiscountManageLang'
4 6 export const messages = {
5 7 en: {
6 8 ...contractCreateFeeMessages.en,
7 9 ...meterWaterManageMessages.en,
8 10 ...meterTypeManageMessages.en,
  11 + ...returnPayFeeManageMessages.en,
  12 + ...feeDiscountManageMessages.en,
9 13 },
10 14 zh: {
11 15 ...contractCreateFeeMessages.zh,
12 16 ...meterWaterManageMessages.zh,
13 17 ...meterTypeManageMessages.zh,
  18 + ...returnPayFeeManageMessages.zh,
  19 + ...feeDiscountManageMessages.zh,
14 20 }
15 21 }
16 22 \ No newline at end of file
... ...
src/router/feeRouter.js
... ... @@ -14,4 +14,14 @@ export default [
14 14 name: '/views/fee/meterTypeManage',
15 15 component: () => import('@/views/fee/meterTypeManageList.vue')
16 16 },
  17 + {
  18 + path: '/pages/property/returnPayFeeManage',
  19 + name: '/pages/property/returnPayFeeManage',
  20 + component: () => import('@/views/fee/returnPayFeeManageList.vue')
  21 + },
  22 + {
  23 + path:'/pages/property/feeDiscountManage',
  24 + name:'/pages/property/feeDiscountManage',
  25 + component: () => import('@/views/fee/feeDiscountManageList.vue')
  26 + },
17 27 ]
18 28 \ No newline at end of file
... ...
src/views/fee/feeDiscountManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + feeDiscountManage: {
  4 + search: {
  5 + title: 'Search Conditions',
  6 + discountId: 'Please enter discount ID',
  7 + discountName: 'Please enter discount name',
  8 + discountType: 'Please select discount type',
  9 + ruleName: 'Please enter rule name'
  10 + },
  11 + list: {
  12 + title: 'Discount Information'
  13 + },
  14 + table: {
  15 + discountId: 'Discount ID',
  16 + discountName: 'Discount Name',
  17 + discountType: 'Discount Type',
  18 + ruleName: 'Rule Name',
  19 + rule: 'Rule',
  20 + createTime: 'Create Time',
  21 + operation: 'Operation'
  22 + },
  23 + add: {
  24 + title: 'Add Discount',
  25 + discountName: 'Discount Name',
  26 + discountNamePlaceholder: 'Required, please enter discount name',
  27 + discountNameRequired: 'Discount name cannot be empty',
  28 + discountNameMaxLength: 'Discount name cannot exceed 256 characters',
  29 + discountType: 'Discount Type',
  30 + discountTypePlaceholder: 'Required, please select discount type',
  31 + discountTypeRequired: 'Discount type cannot be empty',
  32 + rule: 'Rule',
  33 + rulePlaceholder: 'Required, please select rule',
  34 + ruleRequired: 'Rule cannot be empty',
  35 + discountDesc: 'Description',
  36 + discountDescPlaceholder: 'Optional, please enter description',
  37 + specValueRequired: '{specName} cannot be empty'
  38 + },
  39 + edit: {
  40 + title: 'Edit Discount',
  41 + discountName: 'Discount Name',
  42 + discountNamePlaceholder: 'Required, please enter discount name',
  43 + discountNameRequired: 'Discount name cannot be empty',
  44 + discountNameMaxLength: 'Discount name cannot exceed 256 characters',
  45 + discountType: 'Discount Type',
  46 + discountTypePlaceholder: 'Required, please select discount type',
  47 + discountTypeRequired: 'Discount type cannot be empty',
  48 + rule: 'Rule',
  49 + rulePlaceholder: 'Required, please select rule',
  50 + ruleRequired: 'Rule cannot be empty',
  51 + discountDesc: 'Description',
  52 + discountDescPlaceholder: 'Optional, please enter description',
  53 + discountIdRequired: 'Discount ID cannot be empty',
  54 + specValueRequired: '{specName} cannot be empty'
  55 + },
  56 + delete: {
  57 + title: 'Confirm Operation',
  58 + confirmText: 'Are you sure to delete this fee discount?'
  59 + }
  60 + }
  61 + },
  62 + zh: {
  63 + feeDiscountManage: {
  64 + search: {
  65 + title: '查询条件',
  66 + discountId: '请输入折扣ID',
  67 + discountName: '请输入折扣名称',
  68 + discountType: '请选择折扣类型',
  69 + ruleName: '请输入规则名称'
  70 + },
  71 + list: {
  72 + title: '折扣信息'
  73 + },
  74 + table: {
  75 + discountId: '折扣ID',
  76 + discountName: '折扣名称',
  77 + discountType: '折扣类型',
  78 + ruleName: '规则名称',
  79 + rule: '规则',
  80 + createTime: '创建时间',
  81 + operation: '操作'
  82 + },
  83 + add: {
  84 + title: '添加折扣',
  85 + discountName: '折扣名称',
  86 + discountNamePlaceholder: '必填,请填写折扣名称',
  87 + discountNameRequired: '折扣名称不能为空',
  88 + discountNameMaxLength: '折扣名称不能超过256位',
  89 + discountType: '折扣类型',
  90 + discountTypePlaceholder: '必填,请选择折扣类型',
  91 + discountTypeRequired: '折扣类型不能为空',
  92 + rule: '规则',
  93 + rulePlaceholder: '必填,请选择规则',
  94 + ruleRequired: '规则不能为空',
  95 + discountDesc: '描述',
  96 + discountDescPlaceholder: '可选,请填写描述',
  97 + specValueRequired: '{specName}不能为空'
  98 + },
  99 + edit: {
  100 + title: '修改折扣',
  101 + discountName: '折扣名称',
  102 + discountNamePlaceholder: '必填,请填写折扣名称',
  103 + discountNameRequired: '折扣名称不能为空',
  104 + discountNameMaxLength: '折扣名称不能超过256位',
  105 + discountType: '折扣类型',
  106 + discountTypePlaceholder: '必填,请选择折扣类型',
  107 + discountTypeRequired: '折扣类型不能为空',
  108 + rule: '规则',
  109 + rulePlaceholder: '必填,请选择规则',
  110 + ruleRequired: '规则不能为空',
  111 + discountDesc: '描述',
  112 + discountDescPlaceholder: '可选,请填写描述',
  113 + discountIdRequired: '折扣ID不能为空',
  114 + specValueRequired: '{specName}不能为空'
  115 + },
  116 + delete: {
  117 + title: '请确认您的操作',
  118 + confirmText: '确定删除费用折扣'
  119 + }
  120 + }
  121 + }
  122 +}
0 123 \ No newline at end of file
... ...
src/views/fee/feeDiscountManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="fee-discount-manage-container">
  3 + <!-- 查询条件 -->
  4 + <el-card class="search-wrapper">
  5 + <div slot="header" class="flex justify-between">
  6 + <span>{{ $t('feeDiscountManage.search.title') }}</span>
  7 + <el-button type="text" style="float: right; padding: 3px 0" @click="_moreCondition()">
  8 + {{ feeDiscountManageInfo.moreCondition ? $t('common.hide') : $t('common.more') }}
  9 + </el-button>
  10 + </div>
  11 + <el-row :gutter="20">
  12 + <el-col :span="6">
  13 + <el-input v-model="feeDiscountManageInfo.conditions.discountId"
  14 + :placeholder="$t('feeDiscountManage.search.discountId')" clearable />
  15 + </el-col>
  16 + <el-col :span="8">
  17 + <el-input v-model="feeDiscountManageInfo.conditions.discountName"
  18 + :placeholder="$t('feeDiscountManage.search.discountName')" clearable />
  19 + </el-col>
  20 + <el-col :span="6">
  21 + <el-select v-model="feeDiscountManageInfo.conditions.discountType"
  22 + :placeholder="$t('feeDiscountManage.search.discountType')" style="width:100%">
  23 + <el-option v-for="item in feeDiscountManageInfo.discountTypes" :key="item.statusCd" :label="item.name"
  24 + :value="item.statusCd" />
  25 + </el-select>
  26 + </el-col>
  27 + <el-col :span="4">
  28 + <el-button type="primary" @click="_queryFeeDiscountMethod()">
  29 + <i class="el-icon-search"></i>
  30 + {{ $t('common.search') }}
  31 + </el-button>
  32 + <el-button @click="_resetFeeDiscountMethod()">
  33 + <i class="el-icon-refresh"></i>
  34 + {{ $t('common.reset') }}
  35 + </el-button>
  36 + </el-col>
  37 + </el-row>
  38 + <el-row v-show="feeDiscountManageInfo.moreCondition" :gutter="20">
  39 + <el-col :span="6">
  40 + <el-input v-model="feeDiscountManageInfo.conditions.ruleName"
  41 + :placeholder="$t('feeDiscountManage.search.ruleName')" clearable />
  42 + </el-col>
  43 + </el-row>
  44 + </el-card>
  45 +
  46 + <!-- 折扣信息 -->
  47 + <el-card class="list-wrapper">
  48 + <div slot="header" class="flex justify-between">
  49 + <span>{{ $t('feeDiscountManage.list.title') }}</span>
  50 + <el-button type="primary" size="small" style="float: right;" @click="_openAddFeeDiscountModal()">
  51 + <i class="el-icon-plus"></i>
  52 + {{ $t('common.add') }}
  53 + </el-button>
  54 + </div>
  55 + <el-table :data="feeDiscountManageInfo.feeDiscounts" border style="width: 100%" v-loading="loading">
  56 + <el-table-column prop="discountId" :label="$t('feeDiscountManage.table.discountId')" align="center" />
  57 + <el-table-column prop="discountName" :label="$t('feeDiscountManage.table.discountName')" align="center" />
  58 + <el-table-column prop="discountTypeName" :label="$t('feeDiscountManage.table.discountType')" align="center" />
  59 + <el-table-column prop="ruleName" :label="$t('feeDiscountManage.table.ruleName')" align="center" />
  60 + <el-table-column :label="$t('feeDiscountManage.table.rule')" align="center">
  61 + <template slot-scope="scope">
  62 + <div v-for="(item, index) in scope.row.feeDiscountSpecs" :key="index">
  63 + {{ item.specName }}:{{ item.specValue }}
  64 + </div>
  65 + </template>
  66 + </el-table-column>
  67 + <el-table-column prop="createTime" :label="$t('feeDiscountManage.table.createTime')" align="center" />
  68 + <el-table-column :label="$t('common.operation')" align="center" width="200">
  69 + <template slot-scope="scope">
  70 + <el-button size="mini" type="primary" @click="_openEditFeeDiscountModel(scope.row)">
  71 + {{ $t('common.edit') }}
  72 + </el-button>
  73 + <el-button size="mini" type="danger" @click="_openDeleteFeeDiscountModel(scope.row)">
  74 + {{ $t('common.delete') }}
  75 + </el-button>
  76 + </template>
  77 + </el-table-column>
  78 + </el-table>
  79 + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="page.current"
  80 + :page-sizes="[10, 20, 30, 50]" :page-size="page.size" layout="total, sizes, prev, pager, next, jumper"
  81 + :total="page.total" style="margin-top: 20px;" />
  82 + </el-card>
  83 +
  84 + <!-- 组件 -->
  85 + <add-fee-discount ref="addFeeDiscount" @success="handleSuccess" />
  86 + <edit-fee-discount ref="editFeeDiscount" @success="handleSuccess" />
  87 + <delete-fee-discount ref="deleteFeeDiscount" @success="handleSuccess" />
  88 + </div>
  89 +</template>
  90 +
  91 +<script>
  92 +import { getDict,getCommunityId } from '@/api/community/communityApi'
  93 +import { queryFeeDiscount } from '@/api/fee/feeDiscountManageApi'
  94 +import AddFeeDiscount from '@/components/fee/addFeeDiscount'
  95 +import EditFeeDiscount from '@/components/fee/editFeeDiscount'
  96 +import DeleteFeeDiscount from '@/components/fee/deleteFeeDiscount'
  97 +
  98 +export default {
  99 + name: 'FeeDiscountManageList',
  100 + components: {
  101 + AddFeeDiscount,
  102 + EditFeeDiscount,
  103 + DeleteFeeDiscount
  104 + },
  105 + data() {
  106 + return {
  107 + loading: false,
  108 + feeDiscountManageInfo: {
  109 + feeDiscounts: [],
  110 + moreCondition: false,
  111 + discountTypes: [],
  112 + conditions: {
  113 + discountId: '',
  114 + discountName: '',
  115 + discountType: '',
  116 + ruleName: '',
  117 + communityId: ''
  118 + }
  119 + },
  120 + page: {
  121 + current: 1,
  122 + size: 10,
  123 + total: 0
  124 + }
  125 + }
  126 + },
  127 + created() {
  128 + this.getCommunityId()
  129 + this.getDictData()
  130 + this._listFeeDiscounts(this.page.current, this.page.size)
  131 + },
  132 + methods: {
  133 + async getCommunityId() {
  134 + try {
  135 + const communityId = await getCommunityId()
  136 + this.feeDiscountManageInfo.conditions.communityId = communityId
  137 + } catch (error) {
  138 + console.error('获取communityId失败:', error)
  139 + }
  140 + },
  141 + async getDictData() {
  142 + try {
  143 + const data = await getDict('fee_discount', 'discount_type')
  144 + this.feeDiscountManageInfo.discountTypes = data
  145 + } catch (error) {
  146 + console.error('获取字典数据失败:', error)
  147 + }
  148 + },
  149 + async _listFeeDiscounts(page, size) {
  150 + this.loading = true
  151 + try {
  152 + const params = {
  153 + page,
  154 + row: size,
  155 + ...this.feeDiscountManageInfo.conditions
  156 + }
  157 + const { data, total } = await queryFeeDiscount(params)
  158 + this.feeDiscountManageInfo.feeDiscounts = data
  159 + this.page.total = total
  160 + } catch (error) {
  161 + console.error('获取折扣列表失败:', error)
  162 + } finally {
  163 + this.loading = false
  164 + }
  165 + },
  166 + _openAddFeeDiscountModal() {
  167 + this.$refs.addFeeDiscount.open()
  168 + },
  169 + _openEditFeeDiscountModel(row) {
  170 + this.$refs.editFeeDiscount.open(row)
  171 + },
  172 + _openDeleteFeeDiscountModel(row) {
  173 + this.$refs.deleteFeeDiscount.open(row)
  174 + },
  175 + _queryFeeDiscountMethod() {
  176 + this.page.current = 1
  177 + this._listFeeDiscounts(this.page.current, this.page.size)
  178 + },
  179 + _resetFeeDiscountMethod() {
  180 + this.feeDiscountManageInfo.conditions = {
  181 + ...this.feeDiscountManageInfo.conditions,
  182 + discountName: '',
  183 + discountType: '',
  184 + ruleName: '',
  185 + discountId: ''
  186 + }
  187 + this._listFeeDiscounts(this.page.current, this.page.size)
  188 + },
  189 + _moreCondition() {
  190 + this.feeDiscountManageInfo.moreCondition = !this.feeDiscountManageInfo.moreCondition
  191 + },
  192 + handleSuccess() {
  193 + this._listFeeDiscounts(this.page.current, this.page.size)
  194 + },
  195 + handleSizeChange(val) {
  196 + this.page.size = val
  197 + this._listFeeDiscounts(this.page.current, this.page.size)
  198 + },
  199 + handleCurrentChange(val) {
  200 + this.page.current = val
  201 + this._listFeeDiscounts(this.page.current, this.page.size)
  202 + }
  203 + }
  204 +}
  205 +</script>
  206 +
  207 +<style lang="scss" scoped>
  208 +.fee-discount-manage-container {
  209 + padding: 20px;
  210 +
  211 + .search-wrapper {
  212 + margin-bottom: 20px;
  213 +
  214 + .el-row {
  215 + margin-bottom: 10px;
  216 + }
  217 + }
  218 +
  219 + .list-wrapper {
  220 + margin-bottom: 20px;
  221 + }
  222 +}
  223 +</style>
0 224 \ No newline at end of file
... ...
src/views/fee/returnPayFeeManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + returnPayFeeManage: {
  4 + search: {
  5 + title: 'Search Conditions',
  6 + detailId: 'Payment Order Number',
  7 + feeType: 'Select Fee Type',
  8 + state: 'Select Audit Status',
  9 + applyPersonName: 'Applicant Name',
  10 + auditPersonName: 'Auditor Name',
  11 + payerObjName: 'House Number/Car Number etc.',
  12 + startTime: 'Start Time',
  13 + endTime: 'End Time'
  14 + },
  15 + list: {
  16 + title: 'Refund Application List'
  17 + },
  18 + table: {
  19 + returnFeeId: 'Refund Order Number',
  20 + detailId: 'Payment Order Number',
  21 + feeType: 'Fee Type',
  22 + payerObjName: 'Payment Object',
  23 + cycles: 'Payment Cycle (Month)',
  24 + amount: 'Payable Amount/Paid Amount',
  25 + createTime: 'Application Time',
  26 + reason: 'Refund Reason',
  27 + applyPersonName: 'Applicant',
  28 + state: 'Audit Status',
  29 + auditPersonName: 'Auditor',
  30 + retundRemark: 'Refund Status'
  31 + },
  32 + button: {
  33 + retryRefund: 'Retry Refund'
  34 + },
  35 + message: {
  36 + refundSubmitSuccess: 'Refund submitted successfully',
  37 + refundSubmitFailed: 'Refund submission failed'
  38 + }
  39 + },
  40 + audit: {
  41 + title: 'Audit Information',
  42 + state: 'Audit Status',
  43 + selectState: 'Please Audit',
  44 + approve: 'Approve',
  45 + reject: 'Reject',
  46 + remark: 'Reason',
  47 + remarkPlaceholder: 'Required, please fill in the reason'
  48 + }
  49 + },
  50 + zh: {
  51 + returnPayFeeManage: {
  52 + search: {
  53 + title: '查询条件',
  54 + detailId: '缴费单号',
  55 + feeType: '选择费用类型',
  56 + state: '选择审核状态',
  57 + applyPersonName: '申请人姓名',
  58 + auditPersonName: '审核人姓名',
  59 + payerObjName: '房屋编号/车辆编号等',
  60 + startTime: '开始时间',
  61 + endTime: '结束时间'
  62 + },
  63 + list: {
  64 + title: '退费申请单'
  65 + },
  66 + table: {
  67 + returnFeeId: '退款单号',
  68 + detailId: '缴费单号',
  69 + feeType: '费用类型',
  70 + payerObjName: '付费对象',
  71 + cycles: '付费周期(月)',
  72 + amount: '应付金额/实付金额',
  73 + createTime: '申请时间',
  74 + reason: '退费原因',
  75 + applyPersonName: '申请人',
  76 + state: '审核状态',
  77 + auditPersonName: '审核人',
  78 + retundRemark: '退款情况'
  79 + },
  80 + button: {
  81 + retryRefund: '重试退款'
  82 + },
  83 + message: {
  84 + refundSubmitSuccess: '提交退款成功',
  85 + refundSubmitFailed: '提交退款失败'
  86 + }
  87 + },
  88 + audit: {
  89 + title: '审核信息',
  90 + state: '审核状态',
  91 + selectState: '请审核',
  92 + approve: '同意',
  93 + reject: '拒绝',
  94 + remark: '原因',
  95 + remarkPlaceholder: '必填,请填写原因'
  96 + }
  97 + }
  98 +}
0 99 \ No newline at end of file
... ...
src/views/fee/returnPayFeeManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="return-pay-fee-manage-container animated fadeInRight">
  3 + <!-- 查询条件 -->
  4 + <el-card class="box-card">
  5 + <div slot="header" class="flex justify-between">
  6 + <span>{{ $t('returnPayFeeManage.search.title') }}</span>
  7 + <el-button type="text" style="float: right; padding: 3px 0" @click="_moreCondition()">
  8 + {{ returnPayFeeManageInfo.moreCondition ? $t('common.hide') : $t('common.more') }}
  9 + </el-button>
  10 + </div>
  11 + <el-row :gutter="20">
  12 + <el-col :span="6">
  13 + <el-input v-model="returnPayFeeManageInfo.conditions.detailId"
  14 + :placeholder="$t('returnPayFeeManage.search.detailId')" clearable />
  15 + </el-col>
  16 + <el-col :span="6">
  17 + <el-select v-model="returnPayFeeManageInfo.conditions.feeTypeCd"
  18 + :placeholder="$t('returnPayFeeManage.search.feeType')" style="width:100%" clearable>
  19 + <el-option v-for="(item, index) in returnPayFeeManageInfo.feeTypes" :key="index" :label="item.name"
  20 + :value="item.statusCd" />
  21 + </el-select>
  22 + </el-col>
  23 + <el-col :span="6">
  24 + <el-select v-model="returnPayFeeManageInfo.conditions.state"
  25 + :placeholder="$t('returnPayFeeManage.search.state')" style="width:100%" clearable>
  26 + <el-option v-for="(item, index) in returnPayFeeManageInfo.returnPayFeeStates" :key="index" :label="item.name"
  27 + :value="item.statusCd" />
  28 + </el-select>
  29 + </el-col>
  30 + <el-col :span="6">
  31 + <el-button type="primary" @click="_queryReturnPayFeeMethod()">
  32 + <i class="el-icon-search"></i>
  33 + {{ $t('common.search') }}
  34 + </el-button>
  35 + <el-button @click="_resetReturnPayFeeMethod()">
  36 + <i class="el-icon-refresh"></i>
  37 + {{ $t('common.reset') }}
  38 + </el-button>
  39 + </el-col>
  40 + </el-row>
  41 +
  42 + <!-- 更多查询条件 -->
  43 + <el-row v-show="returnPayFeeManageInfo.moreCondition" :gutter="20" style="margin-top:15px">
  44 + <el-col :span="6">
  45 + <el-input v-model="returnPayFeeManageInfo.conditions.applyPersonName"
  46 + :placeholder="$t('returnPayFeeManage.search.applyPersonName')" clearable />
  47 + </el-col>
  48 + <el-col :span="6">
  49 + <el-input v-model="returnPayFeeManageInfo.conditions.auditPersonName"
  50 + :placeholder="$t('returnPayFeeManage.search.auditPersonName')" clearable />
  51 + </el-col>
  52 + <el-col :span="6">
  53 + <el-input v-model="returnPayFeeManageInfo.conditions.payerObjName"
  54 + :placeholder="$t('returnPayFeeManage.search.payerObjName')" clearable />
  55 + </el-col>
  56 + </el-row>
  57 +
  58 + <el-row v-show="returnPayFeeManageInfo.moreCondition" :gutter="20" style="margin-top:15px">
  59 + <el-col :span="6">
  60 + <el-date-picker v-model="returnPayFeeManageInfo.conditions.startTime" type="datetime"
  61 + :placeholder="$t('returnPayFeeManage.search.startTime')" style="width:100%" />
  62 + </el-col>
  63 + <el-col :span="6">
  64 + <el-date-picker v-model="returnPayFeeManageInfo.conditions.endTime" type="datetime"
  65 + :placeholder="$t('returnPayFeeManage.search.endTime')" style="width:100%" />
  66 + </el-col>
  67 + </el-row>
  68 + </el-card>
  69 +
  70 + <!-- 退费申请单列表 -->
  71 + <el-card class="box-card" style="margin-top:20px">
  72 + <div slot="header" class="flex justify-between">
  73 + <span>{{ $t('returnPayFeeManage.list.title') }}</span>
  74 + <el-button type="primary" size="small" @click="_exportFee()">
  75 + {{ $t('common.export') }}
  76 + </el-button>
  77 + </div>
  78 +
  79 + <el-table :data="returnPayFeeManageInfo.returnPayFees" border style="width: 100%">
  80 + <el-table-column prop="returnFeeId" :label="$t('returnPayFeeManage.table.returnFeeId')" align="center" />
  81 + <el-table-column prop="detailId" :label="$t('returnPayFeeManage.table.detailId')" align="center" />
  82 + <el-table-column prop="feeTypeCdName" :label="$t('returnPayFeeManage.table.feeType')" align="center" />
  83 + <el-table-column prop="payerObjName" :label="$t('returnPayFeeManage.table.payerObjName')" align="center" />
  84 + <el-table-column prop="cycles" :label="$t('returnPayFeeManage.table.cycles')" align="center" />
  85 + <el-table-column :label="$t('returnPayFeeManage.table.amount')" align="center">
  86 + <template slot-scope="scope">
  87 + {{ scope.row.receivableAmount }}/{{ scope.row.receivedAmount }}<br>
  88 + <template v-for="(item, index) in scope.row.feeAccountDetailDtoList" >
  89 + <div v-if="item.state != '1001'" :key="index">
  90 + {{ item.stateName }}: {{ item.amount }}<br>
  91 + </div>
  92 + </template>
  93 + <div v-for="(item, index) in scope.row.payFeeDetailDiscountDtoList" :key="index">
  94 + {{ item.discountName }}: {{ Math.abs(item.discountPrice) }}<br>
  95 + </div>
  96 + </template>
  97 + </el-table-column>
  98 + <el-table-column prop="createTime" :label="$t('returnPayFeeManage.table.createTime')" align="center" />
  99 + <el-table-column prop="reason" :label="$t('returnPayFeeManage.table.reason')" align="center" />
  100 + <el-table-column prop="applyPersonName" :label="$t('returnPayFeeManage.table.applyPersonName')" align="center">
  101 + <template slot-scope="scope">
  102 + {{ scope.row.applyPersonName || '-' }}
  103 + </template>
  104 + </el-table-column>
  105 + <el-table-column :label="$t('returnPayFeeManage.table.state')" align="center">
  106 + <template slot-scope="scope">
  107 + <el-tag :type="scope.row.state === '1100' ? 'success' : scope.row.state === '1200' ? 'danger' : 'info'">
  108 + {{ scope.row.stateName }}
  109 + </el-tag>
  110 + </template>
  111 + </el-table-column>
  112 + <el-table-column prop="auditPersonName" :label="$t('returnPayFeeManage.table.auditPersonName')" align="center">
  113 + <template slot-scope="scope">
  114 + {{ scope.row.auditPersonName || '-' }}
  115 + </template>
  116 + </el-table-column>
  117 + <el-table-column prop="retundRemark" :label="$t('returnPayFeeManage.table.retundRemark')" align="center">
  118 + <template slot-scope="scope">
  119 + {{ scope.row.retundRemark || '-' }}
  120 + </template>
  121 + </el-table-column>
  122 + <el-table-column :label="$t('common.operation')" align="center" width="200">
  123 + <template slot-scope="scope">
  124 + <el-button v-if="scope.row.state == '1000'" size="mini" @click="_openReturnPayFeeAuditModel(scope.row)">
  125 + {{ $t('common.audit') }}
  126 + </el-button>
  127 + <el-button v-if="scope.row.refundState == 'FT'" size="mini" @click="_tryRefundMoney(scope.row)">
  128 + {{ $t('returnPayFeeManage.button.retryRefund') }}
  129 + </el-button>
  130 + <el-button size="mini" @click="_toReturnFeeDetail(scope.row)">
  131 + {{ $t('common.detail') }}
  132 + </el-button>
  133 + </template>
  134 + </el-table-column>
  135 + </el-table>
  136 +
  137 + <!-- 分页 -->
  138 + <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
  139 + :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
  140 + @current-change="handleCurrentChange" />
  141 + </el-card>
  142 +
  143 + <!-- 审核组件 -->
  144 + <audit-component ref="auditComponent" @notifyAuditInfo="notifyAuditInfo" />
  145 + </div>
  146 +</template>
  147 +
  148 +<script>
  149 +import { getDict, getCommunityId } from '@/api/community/communityApi'
  150 +import { listReturnPayFees, updateReturnPayFee, tryRefundMoney } from '@/api/fee/returnPayFeeManageApi'
  151 +import AuditComponent from '@/components/fee/audit'
  152 +
  153 +export default {
  154 + name: 'ReturnPayFeeManageList',
  155 + components: {
  156 + AuditComponent
  157 + },
  158 + data() {
  159 + return {
  160 + returnPayFeeManageInfo: {
  161 + returnPayFees: [],
  162 + total: 0,
  163 + records: 1,
  164 + moreCondition: false,
  165 + returnPayFeeStates: [],
  166 + feeTypes: [],
  167 + conditions: {
  168 + communityId: '',
  169 + feeId: '',
  170 + detailId: '',
  171 + userCode: '',
  172 + state: '1000',
  173 + feeTypeCd: '',
  174 + payerObjName: '',
  175 + startTime: '',
  176 + endTime: '',
  177 + auditPersonName: '',
  178 + applyPersonName: ''
  179 + }
  180 + },
  181 + page: {
  182 + current: 1,
  183 + size: 10,
  184 + total: 0
  185 + }
  186 + }
  187 + },
  188 + created() {
  189 + this.returnPayFeeManageInfo.conditions.communityId = getCommunityId()
  190 + this._initReturnPayFeeManage()
  191 + },
  192 + methods: {
  193 + async _initReturnPayFeeManage() {
  194 + try {
  195 + const [feeTypes, returnPayFeeStates] = await Promise.all([
  196 + getDict('pay_fee_config', 'fee_type_cd'),
  197 + getDict('return_pay_fee', 'state')
  198 + ])
  199 + this.returnPayFeeManageInfo.feeTypes = feeTypes
  200 + this.returnPayFeeManageInfo.returnPayFeeStates = returnPayFeeStates
  201 + this._listReturnPayFees(this.page.current, this.page.size)
  202 + } catch (error) {
  203 + console.error('初始化数据失败:', error)
  204 + }
  205 + },
  206 + async _listReturnPayFees(page, size) {
  207 + try {
  208 + this.returnPayFeeManageInfo.conditions.page = page
  209 + this.returnPayFeeManageInfo.conditions.row = size
  210 + const { data, total } = await listReturnPayFees(this.returnPayFeeManageInfo.conditions)
  211 +
  212 + if (data && data.length > 0) {
  213 + data.forEach(item => {
  214 + if (item.feeAccountDetailDtoList && item.feeAccountDetailDtoList.length > 0) {
  215 + item.feeAccountDetailDtoList.forEach(item2 => {
  216 + if (item2.state !== '1001' && item2.state !== '1003') {
  217 + item.receivedAmount = (parseFloat(item.receivedAmount) - parseFloat(item2.amount)).toFixed(2)
  218 + }
  219 + })
  220 + }
  221 + })
  222 + }
  223 +
  224 + this.returnPayFeeManageInfo.returnPayFees = data
  225 + this.page.total = total
  226 + } catch (error) {
  227 + console.error('获取退费申请单列表失败:', error)
  228 + }
  229 + },
  230 + _queryReturnPayFeeMethod() {
  231 + this.page.current = 1
  232 + this._listReturnPayFees(this.page.current, this.page.size)
  233 + },
  234 + _resetReturnPayFeeMethod() {
  235 + this.returnPayFeeManageInfo.conditions = {
  236 + ...this.returnPayFeeManageInfo.conditions,
  237 + detailId: '',
  238 + feeTypeCd: '',
  239 + state: '',
  240 + payerObjName: '',
  241 + startTime: '',
  242 + endTime: '',
  243 + applyPersonName: '',
  244 + auditPersonName: ''
  245 + }
  246 + this._listReturnPayFees(this.page.current, this.page.size)
  247 + },
  248 + _moreCondition() {
  249 + this.returnPayFeeManageInfo.moreCondition = !this.returnPayFeeManageInfo.moreCondition
  250 + },
  251 + _exportFee() {
  252 + // 导出逻辑
  253 + console.log('导出功能')
  254 + },
  255 + _openReturnPayFeeAuditModel(payFee) {
  256 + this.returnPayFeeManageInfo.returnPayFee = payFee
  257 + this.$refs.auditComponent.open()
  258 + },
  259 + async _auditReturnPayFeeState(auditInfo) {
  260 + try {
  261 + const returnPayFee = {
  262 + ...this.returnPayFeeManageInfo.returnPayFee,
  263 + state: auditInfo.state,
  264 + payableAmount: 0.0,
  265 + remark: auditInfo.state === '1200' ? `拒绝:${auditInfo.remark}` : auditInfo.remark
  266 + }
  267 +
  268 + await updateReturnPayFee(returnPayFee)
  269 + this.$message.success(this.$t('common.auditSuccess'))
  270 + this._listReturnPayFees(this.page.current, this.page.size)
  271 + } catch (error) {
  272 + console.error('审核失败:', error)
  273 + this.$message.error(error.message || this.$t('common.auditFailed'))
  274 + }
  275 + },
  276 + async _tryRefundMoney(rPayFee) {
  277 + try {
  278 + const returnPayFee = {
  279 + detailId: rPayFee.detailId,
  280 + communityId: getCommunityId()
  281 + }
  282 +
  283 + await tryRefundMoney(returnPayFee)
  284 + this.$message.success(this.$t('returnPayFeeManage.message.refundSubmitSuccess'))
  285 + this._listReturnPayFees(this.page.current, this.page.size)
  286 + } catch (error) {
  287 + console.error('提交退款失败:', error)
  288 + this.$message.error(error.message || this.$t('returnPayFeeManage.message.refundSubmitFailed'))
  289 + }
  290 + },
  291 + _toReturnFeeDetail(payFee) {
  292 + this.$router.push(`/pages/property/propertyFee?feeId=${payFee.feeId}`)
  293 + },
  294 + notifyAuditInfo(auditInfo) {
  295 + this._auditReturnPayFeeState(auditInfo)
  296 + },
  297 + handleSizeChange(val) {
  298 + this.page.size = val
  299 + this._listReturnPayFees(this.page.current, this.page.size)
  300 + },
  301 + handleCurrentChange(val) {
  302 + this.page.current = val
  303 + this._listReturnPayFees(this.page.current, this.page.size)
  304 + }
  305 + }
  306 +}
  307 +</script>
  308 +
  309 +<style lang="scss" scoped>
  310 +.return-pay-fee-manage-container {
  311 + padding: 20px;
  312 +
  313 + .box-card {
  314 + margin-bottom: 20px;
  315 +
  316 + .clearfix {
  317 +
  318 + &:before,
  319 + &:after {
  320 + display: table;
  321 + content: "";
  322 + }
  323 +
  324 + &:after {
  325 + clear: both;
  326 + }
  327 + }
  328 + }
  329 +
  330 + .el-table {
  331 + margin-top: 15px;
  332 + }
  333 +
  334 + .el-pagination {
  335 + margin-top: 15px;
  336 + text-align: right;
  337 + }
  338 +}
  339 +</style>
0 340 \ No newline at end of file
... ...