Commit f52d2b069f8b94095c6e0149be57b5a95a3b5c22

Authored by wuxw
1 parent 71def04c

积分功能开发中

Showing 41 changed files with 3731 additions and 217 deletions
src/api/scm/couponPropertyPoolDetailApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 获取优惠券赠送记录列表
  5 +export function listCouponPropertyPoolDetail(params) {
  6 + return new Promise((resolve, reject) => {
  7 + const communityId = getCommunityId()
  8 + request({
  9 + url: '/couponProperty.listCouponPropertyPoolDetail',
  10 + method: 'get',
  11 + params: {
  12 + ...params,
  13 + communityId
  14 + }
  15 + }).then(response => {
  16 + const res = response.data
  17 + resolve(res)
  18 + }).catch(error => {
  19 + reject(error)
  20 + })
  21 + })
  22 +}
  23 +
  24 +// 退回优惠券
  25 +export function deleteCouponPropertyPoolDetail(data) {
  26 + return new Promise((resolve, reject) => {
  27 + const communityId = getCommunityId()
  28 + request({
  29 + url: '/couponProperty.deleteCouponPropertyPoolDetail',
  30 + method: 'post',
  31 + data: {
  32 + ...data,
  33 + communityId
  34 + }
  35 + }).then(response => {
  36 + const res = response.data
  37 + resolve(res)
  38 + }).catch(error => {
  39 + reject(error)
  40 + })
  41 + })
  42 +}
0 43 \ No newline at end of file
... ...
src/api/scm/couponPropertyUserDetailApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 获取优惠券使用记录列表
  4 +export function listCouponPropertyUserDetail(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/couponProperty.listCouponPropertyUserDetail',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + resolve(res)
  13 + }).catch(error => {
  14 + reject(error)
  15 + })
  16 + })
  17 +}
  18 +
  19 +// 核销优惠券
  20 +export function writeOffCouponPropertyUser(data) {
  21 + return new Promise((resolve, reject) => {
  22 + request({
  23 + url: '/couponProperty.writeOffCouponPropertyUser',
  24 + method: 'post',
  25 + data
  26 + }).then(response => {
  27 + const res = response.data
  28 + resolve(res)
  29 + }).catch(error => {
  30 + reject(error)
  31 + })
  32 + })
  33 +}
0 34 \ No newline at end of file
... ...
src/api/scm/couponPropertyUserManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 获取业主优惠券列表
  4 +export function listCouponPropertyUser(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/couponProperty.listCouponPropertyUser',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + resolve(res)
  13 + }).catch(error => {
  14 + reject(error)
  15 + })
  16 + })
  17 +}
0 18 \ No newline at end of file
... ...
src/api/scm/integralConfigManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 获取积分标准列表
  5 +export function listIntegralConfig(params) {
  6 + return new Promise((resolve, reject) => {
  7 + const communityId = getCommunityId()
  8 + request({
  9 + url: '/integral.listIntegralConfig',
  10 + method: 'get',
  11 + params: {
  12 + ...params,
  13 + communityId
  14 + }
  15 + }).then(response => {
  16 + const res = response.data
  17 + resolve(res)
  18 + }).catch(error => {
  19 + reject(error)
  20 + })
  21 + })
  22 +}
  23 +
  24 +// 添加积分标准
  25 +export function saveIntegralConfig(data) {
  26 + return new Promise((resolve, reject) => {
  27 + const communityId = getCommunityId()
  28 + request({
  29 + url: '/integral.saveIntegralConfig',
  30 + method: 'post',
  31 + data: {
  32 + ...data,
  33 + communityId
  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 updateIntegralConfig(data) {
  46 + return new Promise((resolve, reject) => {
  47 + const communityId = getCommunityId()
  48 + request({
  49 + url: '/integral.updateIntegralConfig',
  50 + method: 'post',
  51 + data: {
  52 + ...data,
  53 + communityId
  54 + }
  55 + }).then(response => {
  56 + const res = response.data
  57 + resolve(res)
  58 + }).catch(error => {
  59 + reject(error)
  60 + })
  61 + })
  62 +}
  63 +
  64 +// 删除积分标准
  65 +export function deleteIntegralConfig(data) {
  66 + return new Promise((resolve, reject) => {
  67 + const communityId = getCommunityId()
  68 + request({
  69 + url: '/integral.deleteIntegralConfig',
  70 + method: 'post',
  71 + data: {
  72 + ...data,
  73 + communityId
  74 + }
  75 + }).then(response => {
  76 + const res = response.data
  77 + resolve(res)
  78 + }).catch(error => {
  79 + reject(error)
  80 + })
  81 + })
  82 +}
0 83 \ No newline at end of file
... ...
src/api/scm/integralGiftDetailManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +/**
  4 + * 查询积分赠送明细列表
  5 + * @param {Object} params 查询参数
  6 + * @returns {Promise}
  7 + */
  8 +export function listIntegralGiftDetail(params) {
  9 + return new Promise((resolve, reject) => {
  10 + request({
  11 + url: '/integral.listIntegralGiftDetail',
  12 + method: 'get',
  13 + params
  14 + }).then(response => {
  15 + const res = response.data
  16 + resolve(res)
  17 + }).catch(error => {
  18 + reject(error)
  19 + })
  20 + })
  21 +}
  22 +
  23 +/**
  24 + * 添加积分赠送明细
  25 + * @param {Object} data 添加数据
  26 + * @returns {Promise}
  27 + */
  28 +export function addIntegralGiftDetail(data) {
  29 + return new Promise((resolve, reject) => {
  30 + request({
  31 + url: '/integral.saveIntegralGiftDetail',
  32 + method: 'post',
  33 + data
  34 + }).then(response => {
  35 + const res = response.data
  36 + resolve(res)
  37 + }).catch(error => {
  38 + reject(error)
  39 + })
  40 + })
  41 +}
  42 +
  43 +/**
  44 + * 删除积分赠送明细
  45 + * @param {String} detailId 明细ID
  46 + * @returns {Promise}
  47 + */
  48 +export function deleteIntegralGiftDetail(detailId) {
  49 + return new Promise((resolve, reject) => {
  50 + request({
  51 + url: '/integral.deleteIntegralGiftDetail',
  52 + method: 'post',
  53 + data: { detailId }
  54 + }).then(response => {
  55 + const res = response.data
  56 + resolve(res)
  57 + }).catch(error => {
  58 + reject(error)
  59 + })
  60 + })
  61 +}
0 62 \ No newline at end of file
... ...
src/api/scm/integralRuleApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +import { getCommunityId } from '@/api/community/communityApi'
  3 +
  4 +// 积分规则相关API
  5 +export function listIntegralRule(params) {
  6 + return new Promise((resolve, reject) => {
  7 + request({
  8 + url: '/integral.listIntegralRule',
  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 +export function saveIntegralRule(data) {
  24 + return new Promise((resolve, reject) => {
  25 + request({
  26 + url: '/integral.saveIntegralRule',
  27 + method: 'post',
  28 + data: {
  29 + ...data,
  30 + communityId: getCommunityId()
  31 + }
  32 + }).then(response => {
  33 + const res = response.data
  34 + resolve(res)
  35 + }).catch(error => {
  36 + reject(error)
  37 + })
  38 + })
  39 +}
  40 +
  41 +export function updateIntegralRule(data) {
  42 + return new Promise((resolve, reject) => {
  43 + request({
  44 + url: '/integral.updateIntegralRule',
  45 + method: 'post',
  46 + data: {
  47 + ...data,
  48 + communityId: getCommunityId()
  49 + }
  50 + }).then(response => {
  51 + const res = response.data
  52 + resolve(res)
  53 + }).catch(error => {
  54 + reject(error)
  55 + })
  56 + })
  57 +}
  58 +
  59 +export function deleteIntegralRule(data) {
  60 + return new Promise((resolve, reject) => {
  61 + request({
  62 + url: '/integral.deleteIntegralRule',
  63 + method: 'post',
  64 + data: {
  65 + ...data,
  66 + communityId: getCommunityId()
  67 + }
  68 + }).then(response => {
  69 + const res = response.data
  70 + resolve(res)
  71 + }).catch(error => {
  72 + reject(error)
  73 + })
  74 + })
  75 +}
  76 +
  77 +// 积分标准配置相关API
  78 +export function listIntegralRuleConfig(params) {
  79 + return new Promise((resolve, reject) => {
  80 + request({
  81 + url: '/integral.listIntegralRuleConfig',
  82 + method: 'get',
  83 + params: {
  84 + ...params,
  85 + communityId: getCommunityId()
  86 + }
  87 + }).then(response => {
  88 + const res = response.data
  89 + resolve(res)
  90 + }).catch(error => {
  91 + reject(error)
  92 + })
  93 + })
  94 +}
  95 +
  96 +export function saveIntegralRuleConfig(data) {
  97 + return new Promise((resolve, reject) => {
  98 + request({
  99 + url: '/integral.saveIntegralRuleConfig',
  100 + method: 'post',
  101 + data: {
  102 + ...data,
  103 + communityId: getCommunityId()
  104 + }
  105 + }).then(response => {
  106 + const res = response.data
  107 + resolve(res)
  108 + }).catch(error => {
  109 + reject(error)
  110 + })
  111 + })
  112 +}
  113 +
  114 +export function deleteIntegralRuleConfig(data) {
  115 + return new Promise((resolve, reject) => {
  116 + request({
  117 + url: '/integral.deleteIntegralRuleConfig',
  118 + method: 'post',
  119 + data: {
  120 + ...data,
  121 + communityId: getCommunityId()
  122 + }
  123 + }).then(response => {
  124 + const res = response.data
  125 + resolve(res)
  126 + }).catch(error => {
  127 + reject(error)
  128 + })
  129 + })
  130 +}
  131 +
  132 +// 积分标准池相关API
  133 +export function listIntegralConfig(params) {
  134 + return new Promise((resolve, reject) => {
  135 + request({
  136 + url: '/integral.listIntegralConfig',
  137 + method: 'get',
  138 + params: {
  139 + ...params,
  140 + communityId: getCommunityId()
  141 + }
  142 + }).then(response => {
  143 + const res = response.data
  144 + resolve(res)
  145 + }).catch(error => {
  146 + reject(error)
  147 + })
  148 + })
  149 +}
  150 +
  151 +// 缴费时间相关API
  152 +export function listIntegralRuleFee(params) {
  153 + return new Promise((resolve, reject) => {
  154 + request({
  155 + url: '/integral.listIntegralRuleFee',
  156 + method: 'get',
  157 + params: {
  158 + ...params,
  159 + communityId: getCommunityId()
  160 + }
  161 + }).then(response => {
  162 + const res = response.data
  163 + resolve(res)
  164 + }).catch(error => {
  165 + reject(error)
  166 + })
  167 + })
  168 +}
  169 +
  170 +export function saveIntegralRuleFee(data) {
  171 + return new Promise((resolve, reject) => {
  172 + request({
  173 + url: '/integral.saveIntegralRuleFee',
  174 + method: 'post',
  175 + data: {
  176 + ...data,
  177 + communityId: getCommunityId()
  178 + }
  179 + }).then(response => {
  180 + const res = response.data
  181 + resolve(res)
  182 + }).catch(error => {
  183 + reject(error)
  184 + })
  185 + })
  186 +}
  187 +
  188 +export function updateIntegralRuleFee(data) {
  189 + return new Promise((resolve, reject) => {
  190 + request({
  191 + url: '/integral.updateIntegralRuleFee',
  192 + method: 'post',
  193 + data: {
  194 + ...data,
  195 + communityId: getCommunityId()
  196 + }
  197 + }).then(response => {
  198 + const res = response.data
  199 + resolve(res)
  200 + }).catch(error => {
  201 + reject(error)
  202 + })
  203 + })
  204 +}
  205 +
  206 +export function deleteIntegralRuleFee(data) {
  207 + return new Promise((resolve, reject) => {
  208 + request({
  209 + url: '/integral.deleteIntegralRuleFee',
  210 + method: 'post',
  211 + data: {
  212 + ...data,
  213 + communityId: getCommunityId()
  214 + }
  215 + }).then(response => {
  216 + const res = response.data
  217 + resolve(res)
  218 + }).catch(error => {
  219 + reject(error)
  220 + })
  221 + })
  222 +}
0 223 \ No newline at end of file
... ...
src/components/scm/AddCouponRuleFee.vue
1 1 <template>
2   - <el-dialog
3   - :title="$t('couponRuleFee.addFee')"
4   - :visible.sync="visible"
5   - width="50%"
6   - @close="handleClose">
7   - <el-form
8   - ref="form"
9   - :model="form"
10   - :rules="rules"
11   - label-width="120px">
12   - <el-form-item
13   - :label="$t('couponRuleFee.fee')"
14   - prop="feeConfigId">
15   - <el-select
16   - v-model="form.feeConfigId"
17   - :placeholder="$t('couponRuleFee.feePlaceholder')"
18   - style="width: 100%">
19   - <el-option
20   - v-for="item in feeOptions"
21   - :key="item.configId"
22   - :label="item.feeName"
23   - :value="item.configId">
  2 + <el-dialog :title="$t('couponRuleFee.addFee')" :visible.sync="visible" width="50%" @close="handleClose">
  3 + <el-form ref="form" :model="form" :rules="rules" label-width="120px">
  4 + <el-form-item :label="$t('couponRuleFee.fee')" prop="feeConfigId">
  5 + <el-select v-model="form.feeConfigId" :placeholder="$t('couponRuleFee.feePlaceholder')" style="width: 100%">
  6 + <el-option v-for="item in feeOptions" :key="item.configId" :label="item.feeName" :value="item.configId">
24 7 </el-option>
25 8 </el-select>
26 9 </el-form-item>
27   -
28   - <el-form-item
29   - :label="$t('couponRuleFee.payStartTime')"
30   - prop="payStartTime">
31   - <el-date-picker
32   - v-model="form.payStartTime"
33   - type="datetime"
34   - :placeholder="$t('couponRuleFee.payStartTimePlaceholder')"
35   - style="width: 100%">
  10 +
  11 + <el-form-item :label="$t('couponRuleFee.payStartTime')" prop="payStartTime">
  12 + <el-date-picker v-model="form.payStartTime" type="datetime" value-format="yyyy-MM-dd"
  13 + :placeholder="$t('couponRuleFee.payStartTimePlaceholder')" style="width: 100%">
36 14 </el-date-picker>
37 15 </el-form-item>
38   -
39   - <el-form-item
40   - :label="$t('couponRuleFee.payEndTime')"
41   - prop="payEndTime">
42   - <el-date-picker
43   - v-model="form.payEndTime"
44   - type="datetime"
45   - :placeholder="$t('couponRuleFee.payEndTimePlaceholder')"
  16 +
  17 + <el-form-item :label="$t('couponRuleFee.payEndTime')" prop="payEndTime">
  18 + <el-date-picker v-model="form.payEndTime" type="datetime" value-format="yyyy-MM-dd" :placeholder="$t('couponRuleFee.payEndTimePlaceholder')"
46 19 style="width: 100%">
47 20 </el-date-picker>
48 21 </el-form-item>
49   -
50   - <el-form-item
51   - :label="$t('couponRuleFee.payMonth')"
52   - prop="payMonth">
53   - <el-input-number
54   - v-model="form.payMonth"
55   - :min="1"
56   - :max="12"
  22 +
  23 + <el-form-item :label="$t('couponRuleFee.payMonth')" prop="payMonth">
  24 + <el-input-number v-model="form.payMonth" :min="1" :max="12"
57 25 :placeholder="$t('couponRuleFee.payMonthPlaceholder')">
58 26 </el-input-number>
59 27 </el-form-item>
60 28 </el-form>
61   -
  29 +
62 30 <span slot="footer" class="dialog-footer">
63 31 <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
64 32 <el-button type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</el-button>
... ... @@ -154,8 +122,9 @@ export default {
154 122 .el-dialog {
155 123 .el-form {
156 124 padding: 0 20px;
157   -
158   - .el-select, .el-date-picker {
  125 +
  126 + .el-select,
  127 + .el-date-picker {
159 128 width: 100%;
160 129 }
161 130 }
... ...
src/components/scm/CouponRuleCpps.vue
1 1 <template>
2 2 <div class="coupon-rule-cpps">
3 3 <el-row class="operation-row">
4   - <el-col :span="24">
5   - <el-button
6   - type="primary"
7   - size="small"
8   - @click="handleQuery"
9   - class="query-btn">
  4 + <el-col :span="24" class="text-right">
  5 + <el-button type="primary" size="small" @click="handleQuery" class="query-btn">
10 6 {{ $t('common.query') }}
11 7 </el-button>
12   - <el-button
13   - type="primary"
14   - size="small"
15   - @click="openAddModal"
16   - class="add-btn">
  8 + <el-button type="primary" size="small" @click="openAddModal" class="add-btn">
17 9 <i class="el-icon-plus"></i>
18 10 {{ $t('common.add') }}
19 11 </el-button>
20 12 </el-col>
21 13 </el-row>
22 14  
23   - <el-table
24   - :data="tableData"
25   - border
26   - style="width: 100%"
27   - v-loading="loading">
28   - <el-table-column
29   - prop="crcId"
30   - :label="$t('couponRuleCpps.id')"
31   - align="center"
32   - width="100">
  15 + <el-table :data="tableData" border style="width: 100%" v-loading="loading">
  16 + <el-table-column prop="crcId" :label="$t('couponRuleCpps.id')" align="center" width="100">
33 17 </el-table-column>
34   - <el-table-column
35   - prop="couponName"
36   - :label="$t('couponRuleCpps.coupon')"
37   - align="center">
  18 + <el-table-column prop="couponName" :label="$t('couponRuleCpps.coupon')" align="center">
38 19 </el-table-column>
39   - <el-table-column
40   - prop="quantity"
41   - :label="$t('couponRuleCpps.quantity')"
42   - align="center">
  20 + <el-table-column prop="quantity" :label="$t('couponRuleCpps.quantity')" align="center">
43 21 </el-table-column>
44   - <el-table-column
45   - prop="giftFrequencyName"
46   - :label="$t('couponRuleCpps.frequency')"
47   - align="center">
  22 + <el-table-column prop="giftFrequencyName" :label="$t('couponRuleCpps.frequency')" align="center">
48 23 </el-table-column>
49   - <el-table-column
50   - :label="$t('common.operation')"
51   - align="center"
52   - width="200">
  24 + <el-table-column :label="$t('common.operation')" align="center" width="200">
53 25 <template slot-scope="scope">
54   - <el-button
55   - size="mini"
56   - @click="openEditModal(scope.row)">
  26 + <el-button size="mini" @click="openEditModal(scope.row)">
57 27 {{ $t('common.edit') }}
58 28 </el-button>
59   - <el-button
60   - size="mini"
61   - type="danger"
62   - @click="openDeleteModal(scope.row)">
  29 + <el-button size="mini" type="danger" @click="openDeleteModal(scope.row)">
63 30 {{ $t('common.delete') }}
64 31 </el-button>
65 32 </template>
66 33 </el-table-column>
67 34 </el-table>
68 35  
69   - <el-pagination
70   - @size-change="handleSizeChange"
71   - @current-change="handleCurrentChange"
72   - :current-page="pagination.current"
73   - :page-sizes="[10, 20, 30, 50]"
74   - :page-size="pagination.size"
75   - layout="total, sizes, prev, pager, next, jumper"
76   - :total="pagination.total">
  36 + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
  37 + :current-page="pagination.current" :page-sizes="[10, 20, 30, 50]" :page-size="pagination.size"
  38 + layout="total, sizes, prev, pager, next, jumper" :total="pagination.total">
77 39 </el-pagination>
78 40  
79   - <add-coupon-rule-cpps
80   - ref="addCouponRuleCpps"
81   - :rule-id="ruleId"
82   - @success="handleSuccess" />
83   - <edit-coupon-rule-cpps
84   - ref="editCouponRuleCpps"
85   - @success="handleSuccess" />
86   - <delete-coupon-rule-cpps
87   - ref="deleteCouponRuleCpps"
88   - @success="handleSuccess" />
  41 + <add-coupon-rule-cpps ref="addCouponRuleCpps" :rule-id="ruleId" @success="handleSuccess" />
  42 + <edit-coupon-rule-cpps ref="editCouponRuleCpps" @success="handleSuccess" />
  43 + <delete-coupon-rule-cpps ref="deleteCouponRuleCpps" @success="handleSuccess" />
89 44 </div>
90 45 </template>
91 46  
... ... @@ -103,14 +58,9 @@ export default {
103 58 EditCouponRuleCpps,
104 59 DeleteCouponRuleCpps
105 60 },
106   - props: {
107   - ruleId: {
108   - type: String,
109   - required: true
110   - }
111   - },
112 61 data() {
113 62 return {
  63 + ruleId:'',
114 64 loading: false,
115 65 tableData: [],
116 66 pagination: {
... ... @@ -120,15 +70,14 @@ export default {
120 70 }
121 71 }
122 72 },
123   - watch: {
124   - ruleId() {
125   - this.getList()
126   - }
127   - },
128 73 methods: {
  74 + open(ruleId){
  75 + this.ruleId = ruleId
  76 + this.getList()
  77 + },
129 78 async getList() {
130 79 if (!this.ruleId) return
131   -
  80 +
132 81 this.loading = true
133 82 try {
134 83 const params = {
... ... @@ -178,12 +127,12 @@ export default {
178 127 .coupon-rule-cpps {
179 128 .operation-row {
180 129 margin-bottom: 20px;
181   -
  130 +
182 131 .query-btn {
183 132 margin-right: 10px;
184 133 }
185 134 }
186   -
  135 +
187 136 .el-pagination {
188 137 margin-top: 20px;
189 138 text-align: right;
... ...
src/components/scm/CouponRuleDiv.vue
1 1 <template>
2   - <el-card class="coupon-rule-div">
3   - <div class="operation-buttons">
4   - <el-button type="primary" size="small" @click="openAddModal">{{ $t('common.add') }}</el-button>
5   - <el-button type="warning" size="small" @click="openEditModal">{{ $t('common.edit') }}</el-button>
6   - <el-button type="danger" size="small" @click="openDeleteModal">{{ $t('common.delete') }}</el-button>
7   - </div>
  2 + <div>
  3 + <el-card class="coupon-rule-div">
  4 + <div class="operation-buttons">
  5 + <el-button type="primary" size="small" @click="openAddModal">{{ $t('common.add') }}</el-button>
  6 + <el-button type="warning" size="small" @click="openEditModal">{{ $t('common.edit') }}</el-button>
  7 + <el-button type="danger" size="small" @click="openDeleteModal">{{ $t('common.delete') }}</el-button>
  8 + </div>
8 9  
9   - <el-divider></el-divider>
  10 + <el-divider></el-divider>
10 11  
11   - <el-tree :data="couponRules" :props="treeProps" node-key="ruleId" highlight-current @node-click="handleNodeClick"
12   - class="coupon-rule-tree">
13   - <span slot-scope="{ node }" class="custom-tree-node">
14   - <span>{{ node.label }}</span>
15   - </span>
16   - </el-tree>
17   - </el-card>
  12 + <el-tree :data="couponRules" :props="treeProps" node-key="ruleId" highlight-current @node-click="handleNodeClick"
  13 + class="coupon-rule-tree">
  14 + <span slot-scope="{ node }" class="custom-tree-node">
  15 + <span>{{ node.label }}</span>
  16 + </span>
  17 + </el-tree>
  18 + </el-card>
  19 + <add-coupon-rule ref="addCouponRule" @success="handleSuccess" />
  20 + <edit-coupon-rule ref="editCouponRule" @success="handleSuccess" />
  21 + <delete-coupon-rule ref="deleteCouponRule" @success="handleSuccess" />
  22 + </div>
18 23 </template>
19 24  
20 25 <script>
21 26 import { listCouponRule } from '@/api/scm/couponRuleApi'
22 27 import { getCommunityId } from '@/api/community/communityApi'
23   -
  28 +import AddCouponRule from '@/components/scm/AddCouponRule'
  29 +import EditCouponRule from '@/components/scm/EditCouponRule'
  30 +import DeleteCouponRule from '@/components/scm/DeleteCouponRule'
24 31 export default {
25 32 name: 'CouponRuleDiv',
26 33 data() {
... ... @@ -33,6 +40,11 @@ export default {
33 40 }
34 41 }
35 42 },
  43 + components: {
  44 + AddCouponRule,
  45 + EditCouponRule,
  46 + DeleteCouponRule
  47 + },
36 48 created() {
37 49 this.communityId = getCommunityId()
38 50 this.getList()
... ... @@ -56,27 +68,30 @@ export default {
56 68 },
57 69 handleNodeClick(data) {
58 70 this.currentRule = data
59   - this.$emit('switch', data)
  71 + this.$emit('switch',this.currentRule);
60 72 },
61 73 openAddModal() {
62   - this.$emit('open-add')
  74 + this.$refs.addCouponRule.open()
63 75 },
64 76 openEditModal() {
65 77 if (!this.currentRule.ruleId) {
66 78 this.$message.warning(this.$t('couponRule.selectRuleFirst'))
67 79 return
68 80 }
69   - this.$emit('open-edit', this.currentRule)
  81 + this.$refs.editCouponRule.open(this.currentRule)
70 82 },
71 83 openDeleteModal() {
72 84 if (!this.currentRule.ruleId) {
73 85 this.$message.warning(this.$t('couponRule.selectRuleFirst'))
74 86 return
75 87 }
76   - this.$emit('open-delete', this.currentRule)
  88 + this.$refs.deleteCouponRule.open(this.currentRule)
77 89 },
78   - refreshList() {
  90 + handleSuccess() {
79 91 this.getList()
  92 + },
  93 + refreshList() {
  94 +
80 95 }
81 96 }
82 97 }
... ...
src/components/scm/CouponRuleFees.vue
1 1 <template>
2 2 <div class="coupon-rule-fees">
3 3 <el-row class="operation-row">
4   - <el-col :span="24">
  4 + <el-col :span="24" class="text-right">
5 5 <el-button type="primary" size="small" @click="handleQuery" class="query-btn">
6 6 {{ $t('common.query') }}
7 7 </el-button>
... ... @@ -26,9 +26,9 @@
26 26 </el-table-column>
27 27 <el-table-column :label="$t('common.operation')" align="center" width="200">
28 28 <template slot-scope="scope">
29   - <el-button size="mini" @click="openEditModal(scope.row)">
  29 + <!-- <el-button size="mini" @click="openEditModal(scope.row)">
30 30 {{ $t('common.edit') }}
31   - </el-button>
  31 + </el-button> -->
32 32 <el-button size="mini" type="danger" @click="openDeleteModal(scope.row)">
33 33 {{ $t('common.delete') }}
34 34 </el-button>
... ... @@ -42,29 +42,29 @@
42 42 </el-pagination>
43 43  
44 44 <add-coupon-rule-fee ref="addCouponRuleFee" :rule-id="ruleId" @success="handleSuccess" />
  45 + <delete-coupon-rule-fee ref="deleteCouponRuleFee" @success="handleSuccess" />
  46 +
45 47 </div>
46 48 </template>
47 49  
48 50 <script>
49 51 import { listCouponRuleFee } from '@/api/scm/couponRuleApi'
50 52 import AddCouponRuleFee from './AddCouponRuleFee'
  53 +import DeleteCouponRuleFee from './DeleteCouponRuleFee'
51 54 import { getCommunityId } from '@/api/community/communityApi'
52 55  
53 56 export default {
54 57 name: 'CouponRuleFees',
55 58 components: {
56   - AddCouponRuleFee
57   - },
58   - props: {
59   - ruleId: {
60   - type: String,
61   - required: true
62   - }
  59 + AddCouponRuleFee,
  60 + DeleteCouponRuleFee
63 61 },
  62 +
64 63 data() {
65 64 return {
66 65 loading: false,
67 66 tableData: [],
  67 + ruleId:'',
68 68 pagination: {
69 69 current: 1,
70 70 size: 10,
... ... @@ -72,12 +72,12 @@ export default {
72 72 }
73 73 }
74 74 },
75   - watch: {
76   - ruleId() {
77   - this.getList()
78   - }
79   - },
80 75 methods: {
  76 +
  77 + open(ruleId){
  78 + this.ruleId = ruleId
  79 + this.getList()
  80 + },
81 81 async getList() {
82 82 if (!this.ruleId) return
83 83  
... ... @@ -116,14 +116,10 @@ export default {
116 116 openEditModal(row) {
117 117 // TODO: Implement edit modal
118 118 this.$refs.editCouponRuleFee.open(row)
119   -
120   - this.$message.warning('Edit feature will be implemented soon')
121 119 },
122 120 openDeleteModal(row) {
123 121 this.$refs.deleteCouponRuleFee.open(row)
124 122  
125   - // TODO: Implement delete modal
126   - this.$message.warning('Delete feature will be implemented soon')
127 123 },
128 124 handleSuccess() {
129 125 this.getList()
... ...
src/components/scm/DeleteCouponRuleFee.vue
1 1 <template>
2   - <el-dialog
3   - :title="$t('couponRuleFee.deleteConfirm')"
4   - :visible.sync="visible"
5   - width="30%"
6   - center
7   - @close="handleClose">
  2 + <el-dialog :title="$t('couponRuleFee.deleteConfirm')" :visible.sync="visible" width="30%" center @close="handleClose">
8 3 <div class="text-center">
9 4 <p>{{ $t('couponRuleFee.deletePrompt') }}</p>
10 5 <p class="delete-item">{{ currentItem.feeConfigName }}</p>
... ... @@ -12,13 +7,10 @@
12 7 {{ currentItem.payStartTime }} ~ {{ currentItem.payEndTime }}
13 8 </p>
14 9 </div>
15   -
  10 +
16 11 <span slot="footer" class="dialog-footer">
17 12 <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
18   - <el-button
19   - type="danger"
20   - @click="handleConfirm"
21   - :loading="loading">
  13 + <el-button type="danger" @click="handleConfirm" :loading="loading">
22 14 {{ $t('common.confirmDelete') }}
23 15 </el-button>
24 16 </span>
... ... @@ -82,13 +74,13 @@ export default {
82 74 <style lang="scss" scoped>
83 75 .text-center {
84 76 text-align: center;
85   -
  77 +
86 78 .delete-item {
87 79 font-weight: bold;
88 80 color: #f56c6c;
89 81 margin: 10px 0;
90 82 }
91   -
  83 +
92 84 .delete-info {
93 85 color: #909399;
94 86 font-size: 12px;
... ...
src/components/scm/addIntegralConfig.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('integralConfigManage.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 + label-position="right"
  14 + >
  15 + <el-form-item
  16 + :label="$t('integralConfigManage.form.configName')"
  17 + prop="configName"
  18 + >
  19 + <el-input
  20 + v-model="formData.configName"
  21 + :placeholder="$t('integralConfigManage.form.configNamePlaceholder')"
  22 + />
  23 + </el-form-item>
  24 +
  25 + <el-form-item
  26 + :label="$t('integralConfigManage.form.computingFormula')"
  27 + prop="computingFormula"
  28 + >
  29 + <el-select
  30 + v-model="formData.computingFormula"
  31 + :placeholder="$t('integralConfigManage.form.computingFormulaPlaceholder')"
  32 + style="width: 100%"
  33 + @change="handleFormulaChange"
  34 + >
  35 + <el-option
  36 + v-for="item in formulaOptions"
  37 + :key="item.value"
  38 + :label="item.label"
  39 + :value="item.value"
  40 + />
  41 + </el-select>
  42 + </el-form-item>
  43 +
  44 + <el-form-item
  45 + v-if="formData.computingFormula === '1001'"
  46 + :label="$t('integralConfigManage.form.amount')"
  47 + prop="squarePrice"
  48 + >
  49 + <el-input
  50 + v-model="formData.squarePrice"
  51 + :placeholder="$t('integralConfigManage.form.amountPlaceholder')"
  52 + />
  53 + </el-form-item>
  54 +
  55 + <el-form-item
  56 + v-else-if="formData.computingFormula === '2002'"
  57 + :label="$t('integralConfigManage.form.month')"
  58 + prop="squarePrice"
  59 + >
  60 + <el-input
  61 + v-model="formData.squarePrice"
  62 + :placeholder="$t('integralConfigManage.form.monthPlaceholder')"
  63 + />
  64 + </el-form-item>
  65 +
  66 + <el-form-item
  67 + :label="$t('integralConfigManage.form.points')"
  68 + prop="additionalAmount"
  69 + >
  70 + <el-input
  71 + v-model="formData.additionalAmount"
  72 + type="number"
  73 + :placeholder="$t('integralConfigManage.form.pointsPlaceholder')"
  74 + />
  75 + </el-form-item>
  76 +
  77 + <el-form-item
  78 + :label="$t('integralConfigManage.form.scale')"
  79 + prop="scale"
  80 + >
  81 + <el-select
  82 + v-model="formData.scale"
  83 + :placeholder="$t('integralConfigManage.form.scalePlaceholder')"
  84 + style="width: 100%"
  85 + >
  86 + <el-option
  87 + v-for="item in scaleOptions"
  88 + :key="item.value"
  89 + :label="item.label"
  90 + :value="item.value"
  91 + />
  92 + </el-select>
  93 + </el-form-item>
  94 + </el-form>
  95 +
  96 + <span slot="footer" class="dialog-footer">
  97 + <el-button @click="visible = false">
  98 + {{ $t('common.cancel') }}
  99 + </el-button>
  100 + <el-button type="primary" @click="handleSubmit">
  101 + {{ $t('common.confirm') }}
  102 + </el-button>
  103 + </span>
  104 + </el-dialog>
  105 +</template>
  106 +
  107 +<script>
  108 +import { saveIntegralConfig } from '@/api/scm/integralConfigManageApi'
  109 +import { getCommunityId } from '@/api/community/communityApi'
  110 +
  111 +export default {
  112 + name: 'AddIntegralConfig',
  113 + data() {
  114 + return {
  115 + visible: false,
  116 + formData: {
  117 + configName: '',
  118 + computingFormula: '',
  119 + squarePrice: '',
  120 + additionalAmount: '',
  121 + scale: '3',
  122 + communityId: ''
  123 + },
  124 + formulaOptions: [
  125 + { value: '1001', label: this.$t('integralConfigManage.formula.fullAmount') },
  126 + { value: '2002', label: this.$t('integralConfigManage.formula.fullMonth') }
  127 + ],
  128 + scaleOptions: [
  129 + { value: '3', label: this.$t('integralConfigManage.scale.roundUp') },
  130 + { value: '4', label: this.$t('integralConfigManage.scale.roundDown') }
  131 + ],
  132 + rules: {
  133 + configName: [
  134 + { required: true, message: this.$t('integralConfigManage.validate.configNameRequired'), trigger: 'blur' },
  135 + { max: 100, message: this.$t('integralConfigManage.validate.configNameMaxLength'), trigger: 'blur' }
  136 + ],
  137 + computingFormula: [
  138 + { required: true, message: this.$t('integralConfigManage.validate.computingFormulaRequired'), trigger: 'change' }
  139 + ],
  140 + squarePrice: [
  141 + { required: true, message: this.$t('integralConfigManage.validate.squarePriceRequired'), trigger: 'blur' },
  142 + { max: 12, message: this.$t('integralConfigManage.validate.squarePriceMaxLength'), trigger: 'blur' }
  143 + ],
  144 + additionalAmount: [
  145 + { required: true, message: this.$t('integralConfigManage.validate.additionalAmountRequired'), trigger: 'blur' },
  146 + { max: 12, message: this.$t('integralConfigManage.validate.additionalAmountMaxLength'), trigger: 'blur' }
  147 + ],
  148 + scale: [
  149 + { required: true, message: this.$t('integralConfigManage.validate.scaleRequired'), trigger: 'change' }
  150 + ]
  151 + }
  152 + }
  153 + },
  154 + methods: {
  155 + open() {
  156 + this.visible = true
  157 + this.formData.communityId = getCommunityId()
  158 + this.$nextTick(() => {
  159 + this.$refs.form && this.$refs.form.resetFields()
  160 + })
  161 + },
  162 + handleClose() {
  163 + this.$refs.form.resetFields()
  164 + },
  165 + handleFormulaChange() {
  166 + this.formData.squarePrice = ''
  167 + },
  168 + handleSubmit() {
  169 + this.$refs.form.validate(async valid => {
  170 + if (valid) {
  171 + try {
  172 + await saveIntegralConfig(this.formData)
  173 + this.$message.success(this.$t('integralConfigManage.message.addSuccess'))
  174 + this.visible = false
  175 + this.$emit('success')
  176 + } catch (error) {
  177 + this.$message.error(error.message || this.$t('integralConfigManage.message.addFailed'))
  178 + }
  179 + }
  180 + })
  181 + }
  182 + }
  183 +}
  184 +</script>
0 185 \ No newline at end of file
... ...
src/components/scm/addIntegralRule.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('integralRule.addTitle')"
  4 + :visible.sync="visible"
  5 + width="50%"
  6 + @close="handleClose"
  7 + >
  8 + <el-form ref="form" :model="form" :rules="rules" label-width="120px">
  9 + <el-form-item :label="$t('integralRule.ruleName')" prop="ruleName">
  10 + <el-input
  11 + v-model="form.ruleName"
  12 + :placeholder="$t('integralRule.ruleNamePlaceholder')"
  13 + ></el-input>
  14 + </el-form-item>
  15 + <el-form-item :label="$t('integralRule.remark')" prop="remark">
  16 + <el-input
  17 + type="textarea"
  18 + :rows="3"
  19 + v-model="form.remark"
  20 + :placeholder="$t('integralRule.remarkPlaceholder')"
  21 + ></el-input>
  22 + </el-form-item>
  23 + </el-form>
  24 + <span slot="footer" class="dialog-footer">
  25 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  26 + <el-button type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</el-button>
  27 + </span>
  28 + </el-dialog>
  29 +</template>
  30 +
  31 +<script>
  32 +import { saveIntegralRule } from '@/api/scm/integralRuleApi'
  33 +import { getCommunityId } from '@/api/community/communityApi'
  34 +
  35 +export default {
  36 + name: 'AddIntegralRule',
  37 + data() {
  38 + return {
  39 + visible: false,
  40 + form: {
  41 + ruleName: '',
  42 + remark: ''
  43 + },
  44 + rules: {
  45 + ruleName: [
  46 + { required: true, message: this.$t('integralRule.ruleNameRequired'), trigger: 'blur' },
  47 + { max: 64, message: this.$t('integralRule.ruleNameMaxLength'), trigger: 'blur' }
  48 + ],
  49 + remark: [
  50 + { required: true, message: this.$t('integralRule.remarkRequired'), trigger: 'blur' },
  51 + { max: 512, message: this.$t('integralRule.remarkMaxLength'), trigger: 'blur' }
  52 + ]
  53 + }
  54 + }
  55 + },
  56 + methods: {
  57 + open() {
  58 + this.visible = true
  59 + this.communityId = getCommunityId()
  60 + },
  61 + handleClose() {
  62 + this.$refs.form.resetFields()
  63 + },
  64 + handleSubmit() {
  65 + this.$refs.form.validate(async valid => {
  66 + if (!valid) return
  67 +
  68 + try {
  69 + const params = {
  70 + ...this.form,
  71 + communityId: this.communityId
  72 + }
  73 + await saveIntegralRule(params)
  74 + this.$message.success(this.$t('common.addSuccess'))
  75 + this.visible = false
  76 + this.$emit('success')
  77 + } catch (error) {
  78 + this.$message.error(error.message || this.$t('common.addFailed'))
  79 + }
  80 + })
  81 + }
  82 + }
  83 +}
  84 +</script>
0 85 \ No newline at end of file
... ...
src/components/scm/addIntegralRuleConfig.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('integralRule.addConfigTitle')"
  4 + :visible.sync="visible"
  5 + width="50%"
  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('integralRule.configName')"
  16 + prop="configId"
  17 + >
  18 + <el-select
  19 + v-model="form.configId"
  20 + :placeholder="$t('integralRule.configPlaceholder')"
  21 + style="width: 100%"
  22 + >
  23 + <el-option
  24 + v-for="item in configOptions"
  25 + :key="item.configId"
  26 + :label="item.configName"
  27 + :value="item.configId"
  28 + />
  29 + </el-select>
  30 + </el-form-item>
  31 + </el-form>
  32 + <span slot="footer" class="dialog-footer">
  33 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  34 + <el-button
  35 + type="primary"
  36 + @click="handleSubmit"
  37 + >{{ $t('common.confirm') }}</el-button>
  38 + </span>
  39 + </el-dialog>
  40 +</template>
  41 +
  42 +<script>
  43 +import { saveIntegralRuleConfig, listIntegralConfig } from '@/api/scm/integralRuleApi'
  44 +import { getCommunityId } from '@/api/community/communityApi'
  45 +
  46 +export default {
  47 + name: 'AddIntegralRuleConfig',
  48 + props: {
  49 + ruleId: {
  50 + type: String,
  51 + required: true
  52 + }
  53 + },
  54 + data() {
  55 + return {
  56 + visible: false,
  57 + form: {
  58 + configId: '',
  59 + ruleId: ''
  60 + },
  61 + rules: {
  62 + configId: [
  63 + { required: true, message: this.$t('integralRule.configRequired'), trigger: 'change' }
  64 + ]
  65 + },
  66 + configOptions: []
  67 + }
  68 + },
  69 + methods: {
  70 + async open() {
  71 + this.visible = true
  72 + this.form.ruleId = this.ruleId
  73 + await this.fetchConfigOptions()
  74 + },
  75 + async fetchConfigOptions() {
  76 + try {
  77 + const { data } = await listIntegralConfig({
  78 + page: 1,
  79 + row: 100,
  80 + communityId: getCommunityId()
  81 + })
  82 + this.configOptions = data
  83 + } catch (error) {
  84 + this.$message.error(this.$t('common.fetchError'))
  85 + }
  86 + },
  87 + handleClose() {
  88 + this.$refs.form.resetFields()
  89 + },
  90 + async handleSubmit() {
  91 + this.$refs.form.validate(async valid => {
  92 + if (!valid) return
  93 +
  94 + try {
  95 + await saveIntegralRuleConfig(this.form)
  96 + this.$message.success(this.$t('common.addSuccess'))
  97 + this.visible = false
  98 + this.$emit('success')
  99 + } catch (error) {
  100 + this.$message.error(error.message || this.$t('common.addFailed'))
  101 + }
  102 + })
  103 + }
  104 + }
  105 +}
  106 +</script>
0 107 \ No newline at end of file
... ...
src/components/scm/addIntegralRuleFee.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('integralRule.addFeeTitle')"
  4 + :visible.sync="visible"
  5 + width="50%"
  6 + @close="handleClose"
  7 + >
  8 + <el-form
  9 + ref="form"
  10 + :model="form"
  11 + :rules="rules"
  12 + label-width="150px"
  13 + >
  14 + <el-form-item
  15 + :label="$t('integralRule.payStartTime')"
  16 + prop="payStartTime"
  17 + >
  18 + <el-date-picker
  19 + v-model="form.payStartTime"
  20 + type="datetime"
  21 + :placeholder="$t('integralRule.payStartTimePlaceholder')"
  22 + style="width: 100%"
  23 + value-format="yyyy-MM-dd HH:mm:ss"
  24 + />
  25 + </el-form-item>
  26 + <el-form-item
  27 + :label="$t('integralRule.payEndTime')"
  28 + prop="payEndTime"
  29 + >
  30 + <el-date-picker
  31 + v-model="form.payEndTime"
  32 + type="datetime"
  33 + :placeholder="$t('integralRule.payEndTimePlaceholder')"
  34 + style="width: 100%"
  35 + value-format="yyyy-MM-dd HH:mm:ss"
  36 + />
  37 + </el-form-item>
  38 + </el-form>
  39 + <span slot="footer" class="dialog-footer">
  40 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  41 + <el-button
  42 + type="primary"
  43 + @click="handleSubmit"
  44 + >{{ $t('common.confirm') }}</el-button>
  45 + </span>
  46 + </el-dialog>
  47 +</template>
  48 +
  49 +<script>
  50 +import { saveIntegralRuleFee } from '@/api/scm/integralRuleApi'
  51 +import { getCommunityId } from '@/api/community/communityApi'
  52 +
  53 +export default {
  54 + name: 'AddIntegralRuleFee',
  55 + data() {
  56 + return {
  57 + visible: false,
  58 + form: {
  59 + ruleId: '',
  60 + payStartTime: '',
  61 + payEndTime: ''
  62 + },
  63 + rules: {
  64 + payStartTime: [
  65 + { required: true, message: this.$t('integralRule.payStartTimeRequired'), trigger: 'change' }
  66 + ],
  67 + payEndTime: [
  68 + { required: true, message: this.$t('integralRule.payEndTimeRequired'), trigger: 'change' },
  69 + {
  70 + validator: (rule, value, callback) => {
  71 + if (!value || !this.form.payStartTime) {
  72 + callback()
  73 + } else if (new Date(value) <= new Date(this.form.payStartTime)) {
  74 + callback(new Error(this.$t('integralRule.payEndTimeAfterStart')))
  75 + } else {
  76 + callback()
  77 + }
  78 + },
  79 + trigger: 'change'
  80 + }
  81 + ]
  82 + }
  83 + }
  84 + },
  85 + methods: {
  86 + open(data) {
  87 + this.form.ruleId = data.ruleId
  88 + this.communityId = getCommunityId()
  89 + this.visible = true
  90 + },
  91 + handleClose() {
  92 + this.$refs.form.resetFields()
  93 + },
  94 + async handleSubmit() {
  95 + this.$refs.form.validate(async valid => {
  96 + if (!valid) return
  97 +
  98 + try {
  99 + const params = {
  100 + ...this.form,
  101 + communityId: this.communityId
  102 + }
  103 + await saveIntegralRuleFee(params)
  104 + this.$message.success(this.$t('common.addSuccess'))
  105 + this.visible = false
  106 + this.$emit('success')
  107 + } catch (error) {
  108 + this.$message.error(error.message || this.$t('common.addFailed'))
  109 + }
  110 + })
  111 + }
  112 + }
  113 +}
  114 +</script>
0 115 \ No newline at end of file
... ...
src/components/scm/deleteCouponPropertyPoolDetail.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('couponPropertyPoolDetail.delete.title')"
  4 + :visible.sync="visible"
  5 + width="30%"
  6 + @close="handleClose"
  7 + >
  8 + <div class="text-center">
  9 + <p>{{ $t('couponPropertyPoolDetail.delete.confirmText') }}</p>
  10 + </div>
  11 + <span slot="footer" class="dialog-footer">
  12 + <el-button @click="handleClose">{{ $t('common.cancel') }}</el-button>
  13 + <el-button type="primary" @click="handleConfirm">{{ $t('common.confirm') }}</el-button>
  14 + </span>
  15 + </el-dialog>
  16 +</template>
  17 +
  18 +<script>
  19 +import { deleteCouponPropertyPoolDetail } from '@/api/scm/couponPropertyPoolDetailApi'
  20 +
  21 +export default {
  22 + name: 'DeleteCouponPropertyPoolDetail',
  23 + data() {
  24 + return {
  25 + visible: false,
  26 + currentRow: null
  27 + }
  28 + },
  29 + methods: {
  30 + open(row) {
  31 + this.currentRow = row
  32 + this.visible = true
  33 + },
  34 + handleClose() {
  35 + this.visible = false
  36 + this.currentRow = null
  37 + },
  38 + async handleConfirm() {
  39 + try {
  40 + await deleteCouponPropertyPoolDetail(this.currentRow)
  41 + this.$message.success(this.$t('couponPropertyPoolDetail.delete.success'))
  42 + this.$emit('success')
  43 + this.handleClose()
  44 + } catch (error) {
  45 + this.$message.error(this.$t('couponPropertyPoolDetail.delete.error'))
  46 + }
  47 + }
  48 + }
  49 +}
  50 +</script>
  51 +
  52 +<style scoped>
  53 +.text-center {
  54 + text-align: center;
  55 +}
  56 +</style>
0 57 \ No newline at end of file
... ...
src/components/scm/deleteIntegralConfig.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('integralConfigManage.delete.title')"
  4 + :visible.sync="visible"
  5 + width="30%"
  6 + @close="handleClose"
  7 + >
  8 + <div class="delete-content">
  9 + <el-alert
  10 + :title="$t('integralConfigManage.delete.confirmMessage')"
  11 + type="warning"
  12 + :closable="false"
  13 + show-icon
  14 + />
  15 + </div>
  16 + <span slot="footer" class="dialog-footer">
  17 + <el-button @click="visible = false">
  18 + {{ $t('common.cancel') }}
  19 + </el-button>
  20 + <el-button type="primary" @click="handleConfirm" :loading="loading">
  21 + {{ $t('common.confirm') }}
  22 + </el-button>
  23 + </span>
  24 + </el-dialog>
  25 +</template>
  26 +
  27 +<script>
  28 +import { deleteIntegralConfig } from '@/api/scm/integralConfigManageApi'
  29 +import { getCommunityId } from '@/api/community/communityApi'
  30 +
  31 +export default {
  32 + name: 'DeleteIntegralConfig',
  33 + data() {
  34 + return {
  35 + visible: false,
  36 + loading: false,
  37 + deleteData: {
  38 + configId: '',
  39 + communityId: ''
  40 + }
  41 + }
  42 + },
  43 + methods: {
  44 + open(data) {
  45 + this.visible = true
  46 + this.deleteData = {
  47 + configId: data.configId,
  48 + communityId: getCommunityId()
  49 + }
  50 + },
  51 + handleClose() {
  52 + this.deleteData = {
  53 + configId: '',
  54 + communityId: ''
  55 + }
  56 + this.loading = false
  57 + },
  58 + async handleConfirm() {
  59 + try {
  60 + this.loading = true
  61 + await deleteIntegralConfig(this.deleteData)
  62 + this.$message.success(this.$t('integralConfigManage.message.deleteSuccess'))
  63 + this.visible = false
  64 + this.$emit('success')
  65 + } catch (error) {
  66 + this.$message.error(error.message || this.$t('integralConfigManage.message.deleteFailed'))
  67 + } finally {
  68 + this.loading = false
  69 + }
  70 + }
  71 + }
  72 +}
  73 +</script>
  74 +
  75 +<style scoped>
  76 +.delete-content {
  77 + margin-bottom: 20px;
  78 +}
  79 +</style>
0 80 \ No newline at end of file
... ...
src/components/scm/deleteIntegralRule.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('common.confirmTitle')"
  4 + :visible.sync="visible"
  5 + width="30%"
  6 + center
  7 + >
  8 + <div class="text-center">
  9 + <p>{{ $t('integralRule.deleteConfirm') }}</p>
  10 + </div>
  11 + <span slot="footer" class="dialog-footer">
  12 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  13 + <el-button type="danger" @click="handleConfirm">{{ $t('common.confirm') }}</el-button>
  14 + </span>
  15 + </el-dialog>
  16 +</template>
  17 +
  18 +<script>
  19 +import { deleteIntegralRule } from '@/api/scm/integralRuleApi'
  20 +import { getCommunityId } from '@/api/community/communityApi'
  21 +
  22 +export default {
  23 + name: 'DeleteIntegralRule',
  24 + data() {
  25 + return {
  26 + visible: false,
  27 + ruleId: '',
  28 + communityId: ''
  29 + }
  30 + },
  31 + methods: {
  32 + open(data) {
  33 + this.ruleId = data.ruleId
  34 + this.communityId = getCommunityId()
  35 + this.visible = true
  36 + },
  37 + async handleConfirm() {
  38 + try {
  39 + await deleteIntegralRule({
  40 + ruleId: this.ruleId,
  41 + communityId: this.communityId
  42 + })
  43 + this.$message.success(this.$t('common.deleteSuccess'))
  44 + this.visible = false
  45 + this.$emit('success')
  46 + } catch (error) {
  47 + this.$message.error(error.message || this.$t('common.deleteFailed'))
  48 + }
  49 + }
  50 + }
  51 +}
  52 +</script>
0 53 \ No newline at end of file
... ...
src/components/scm/deleteIntegralRuleConfig.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('common.confirmTitle')"
  4 + :visible.sync="visible"
  5 + width="30%"
  6 + center
  7 + >
  8 + <div class="text-center">
  9 + <p>{{ $t('integralRule.deleteConfigConfirm') }}</p>
  10 + </div>
  11 + <span slot="footer" class="dialog-footer">
  12 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  13 + <el-button
  14 + type="danger"
  15 + @click="handleConfirm"
  16 + >{{ $t('common.confirm') }}</el-button>
  17 + </span>
  18 + </el-dialog>
  19 +</template>
  20 +
  21 +<script>
  22 +import { deleteIntegralRuleConfig } from '@/api/scm/integralRuleApi'
  23 +
  24 +export default {
  25 + name: 'DeleteIntegralRuleConfig',
  26 + data() {
  27 + return {
  28 + visible: false,
  29 + configId: '',
  30 + ruleId: ''
  31 + }
  32 + },
  33 + methods: {
  34 + open(data) {
  35 + this.configId = data.configId
  36 + this.ruleId = data.ruleId
  37 + this.visible = true
  38 + },
  39 + async handleConfirm() {
  40 + try {
  41 + await deleteIntegralRuleConfig({
  42 + configId: this.configId,
  43 + ruleId: this.ruleId
  44 + })
  45 + this.$message.success(this.$t('common.deleteSuccess'))
  46 + this.visible = false
  47 + this.$emit('success')
  48 + } catch (error) {
  49 + this.$message.error(error.message || this.$t('common.deleteFailed'))
  50 + }
  51 + }
  52 + }
  53 +}
  54 +</script>
0 55 \ No newline at end of file
... ...
src/components/scm/deleteIntegralRuleFee.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('common.confirmTitle')"
  4 + :visible.sync="visible"
  5 + width="30%"
  6 + center
  7 + >
  8 + <div class="text-center">
  9 + <p>{{ $t('integralRule.deleteFeeConfirm') }}</p>
  10 + </div>
  11 + <span slot="footer" class="dialog-footer">
  12 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  13 + <el-button
  14 + type="danger"
  15 + @click="handleConfirm"
  16 + >{{ $t('common.confirm') }}</el-button>
  17 + </span>
  18 + </el-dialog>
  19 +</template>
  20 +
  21 +<script>
  22 +import { deleteIntegralRuleFee } from '@/api/scm/integralRuleApi'
  23 +import { getCommunityId } from '@/api/community/communityApi'
  24 +
  25 +export default {
  26 + name: 'DeleteIntegralRuleFee',
  27 + data() {
  28 + return {
  29 + visible: false,
  30 + irfId: '',
  31 + ruleId: '',
  32 + communityId: ''
  33 + }
  34 + },
  35 + methods: {
  36 + open(data) {
  37 + this.irfId = data.irfId
  38 + this.ruleId = data.ruleId
  39 + this.communityId = getCommunityId()
  40 + this.visible = true
  41 + },
  42 + async handleConfirm() {
  43 + try {
  44 + await deleteIntegralRuleFee({
  45 + irfId: this.irfId,
  46 + ruleId: this.ruleId,
  47 + communityId: this.communityId
  48 + })
  49 + this.$message.success(this.$t('common.deleteSuccess'))
  50 + this.visible = false
  51 + this.$emit('success')
  52 + } catch (error) {
  53 + this.$message.error(error.message || this.$t('common.deleteFailed'))
  54 + }
  55 + }
  56 + }
  57 +}
  58 +</script>
0 59 \ No newline at end of file
... ...
src/components/scm/editIntegralConfig.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('integralConfigManage.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 + label-position="right"
  14 + >
  15 + <el-form-item
  16 + :label="$t('integralConfigManage.form.configName')"
  17 + prop="configName"
  18 + >
  19 + <el-input
  20 + v-model="formData.configName"
  21 + :placeholder="$t('integralConfigManage.form.configNamePlaceholder')"
  22 + />
  23 + </el-form-item>
  24 +
  25 + <el-form-item
  26 + :label="$t('integralConfigManage.form.computingFormula')"
  27 + prop="computingFormula"
  28 + >
  29 + <el-select
  30 + v-model="formData.computingFormula"
  31 + :placeholder="$t('integralConfigManage.form.computingFormulaPlaceholder')"
  32 + style="width: 100%"
  33 + @change="handleFormulaChange"
  34 + >
  35 + <el-option
  36 + v-for="item in formulaOptions"
  37 + :key="item.value"
  38 + :label="item.label"
  39 + :value="item.value"
  40 + />
  41 + </el-select>
  42 + </el-form-item>
  43 +
  44 + <el-form-item
  45 + v-if="formData.computingFormula === '1001'"
  46 + :label="$t('integralConfigManage.form.amount')"
  47 + prop="squarePrice"
  48 + >
  49 + <el-input
  50 + v-model="formData.squarePrice"
  51 + :placeholder="$t('integralConfigManage.form.amountPlaceholder')"
  52 + />
  53 + </el-form-item>
  54 +
  55 + <el-form-item
  56 + v-else-if="formData.computingFormula === '2002'"
  57 + :label="$t('integralConfigManage.form.month')"
  58 + prop="squarePrice"
  59 + >
  60 + <el-input
  61 + v-model="formData.squarePrice"
  62 + :placeholder="$t('integralConfigManage.form.monthPlaceholder')"
  63 + />
  64 + </el-form-item>
  65 +
  66 + <el-form-item
  67 + :label="$t('integralConfigManage.form.points')"
  68 + prop="additionalAmount"
  69 + >
  70 + <el-input
  71 + v-model="formData.additionalAmount"
  72 + type="number"
  73 + :placeholder="$t('integralConfigManage.form.pointsPlaceholder')"
  74 + />
  75 + </el-form-item>
  76 +
  77 + <el-form-item
  78 + :label="$t('integralConfigManage.form.scale')"
  79 + prop="scale"
  80 + >
  81 + <el-select
  82 + v-model="formData.scale"
  83 + :placeholder="$t('integralConfigManage.form.scalePlaceholder')"
  84 + style="width: 100%"
  85 + >
  86 + <el-option
  87 + v-for="item in scaleOptions"
  88 + :key="item.value"
  89 + :label="item.label"
  90 + :value="item.value"
  91 + />
  92 + </el-select>
  93 + </el-form-item>
  94 + </el-form>
  95 +
  96 + <span slot="footer" class="dialog-footer">
  97 + <el-button @click="visible = false">
  98 + {{ $t('common.cancel') }}
  99 + </el-button>
  100 + <el-button type="primary" @click="handleSubmit">
  101 + {{ $t('common.confirm') }}
  102 + </el-button>
  103 + </span>
  104 + </el-dialog>
  105 +</template>
  106 +
  107 +<script>
  108 +import { updateIntegralConfig } from '@/api/scm/integralConfigManageApi'
  109 +import { getCommunityId } from '@/api/community/communityApi'
  110 +
  111 +export default {
  112 + name: 'EditIntegralConfig',
  113 + data() {
  114 + return {
  115 + visible: false,
  116 + formData: {
  117 + configId: '',
  118 + configName: '',
  119 + computingFormula: '',
  120 + squarePrice: '',
  121 + additionalAmount: '',
  122 + scale: '',
  123 + communityId: ''
  124 + },
  125 + formulaOptions: [
  126 + { value: '1001', label: this.$t('integralConfigManage.formula.fullAmount') },
  127 + { value: '2002', label: this.$t('integralConfigManage.formula.fullMonth') }
  128 + ],
  129 + scaleOptions: [
  130 + { value: '3', label: this.$t('integralConfigManage.scale.roundUp') },
  131 + { value: '4', label: this.$t('integralConfigManage.scale.roundDown') }
  132 + ],
  133 + rules: {
  134 + configId: [
  135 + { required: true, message: this.$t('integralConfigManage.validate.configIdRequired'), trigger: 'blur' }
  136 + ],
  137 + configName: [
  138 + { required: true, message: this.$t('integralConfigManage.validate.configNameRequired'), trigger: 'blur' },
  139 + { max: 100, message: this.$t('integralConfigManage.validate.configNameMaxLength'), trigger: 'blur' }
  140 + ],
  141 + computingFormula: [
  142 + { required: true, message: this.$t('integralConfigManage.validate.computingFormulaRequired'), trigger: 'change' }
  143 + ],
  144 + squarePrice: [
  145 + { required: true, message: this.$t('integralConfigManage.validate.squarePriceRequired'), trigger: 'blur' }
  146 + ],
  147 + additionalAmount: [
  148 + { required: true, message: this.$t('integralConfigManage.validate.additionalAmountRequired'), trigger: 'blur' }
  149 + ],
  150 + scale: [
  151 + { required: true, message: this.$t('integralConfigManage.validate.scaleRequired'), trigger: 'change' }
  152 + ]
  153 + }
  154 + }
  155 + },
  156 + methods: {
  157 + open(data) {
  158 + this.visible = true
  159 + this.formData = {
  160 + ...data,
  161 + communityId: getCommunityId()
  162 + }
  163 + },
  164 + handleClose() {
  165 + this.$refs.form.resetFields()
  166 + },
  167 + handleFormulaChange() {
  168 + // 计算公式变化时清空金额/月份
  169 + this.formData.squarePrice = ''
  170 + },
  171 + async handleSubmit() {
  172 + this.$refs.form.validate(async valid => {
  173 + if (valid) {
  174 + try {
  175 + await updateIntegralConfig(this.formData)
  176 + this.$message.success(this.$t('integralConfigManage.message.editSuccess'))
  177 + this.visible = false
  178 + this.$emit('success')
  179 + } catch (error) {
  180 + this.$message.error(error.message || this.$t('integralConfigManage.message.editFailed'))
  181 + }
  182 + }
  183 + })
  184 + }
  185 + }
  186 +}
  187 +</script>
0 188 \ No newline at end of file
... ...
src/components/scm/editIntegralRule.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('integralRule.editTitle')"
  4 + :visible.sync="visible"
  5 + width="50%"
  6 + @close="handleClose"
  7 + >
  8 + <el-form ref="form" :model="form" :rules="rules" label-width="120px">
  9 + <el-form-item :label="$t('integralRule.ruleName')" prop="ruleName">
  10 + <el-input
  11 + v-model="form.ruleName"
  12 + :placeholder="$t('integralRule.ruleNamePlaceholder')"
  13 + ></el-input>
  14 + </el-form-item>
  15 + <el-form-item :label="$t('integralRule.remark')" prop="remark">
  16 + <el-input
  17 + type="textarea"
  18 + :rows="3"
  19 + v-model="form.remark"
  20 + :placeholder="$t('integralRule.remarkPlaceholder')"
  21 + ></el-input>
  22 + </el-form-item>
  23 + </el-form>
  24 + <span slot="footer" class="dialog-footer">
  25 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  26 + <el-button type="primary" @click="handleSubmit">{{ $t('common.confirm') }}</el-button>
  27 + </span>
  28 + </el-dialog>
  29 +</template>
  30 +
  31 +<script>
  32 +import { updateIntegralRule } from '@/api/scm/integralRuleApi'
  33 +import { getCommunityId } from '@/api/community/communityApi'
  34 +
  35 +export default {
  36 + name: 'EditIntegralRule',
  37 + data() {
  38 + return {
  39 + visible: false,
  40 + form: {
  41 + ruleId: '',
  42 + ruleName: '',
  43 + remark: ''
  44 + },
  45 + rules: {
  46 + ruleName: [
  47 + { required: true, message: this.$t('integralRule.ruleNameRequired'), trigger: 'blur' },
  48 + { max: 64, message: this.$t('integralRule.ruleNameMaxLength'), trigger: 'blur' }
  49 + ],
  50 + remark: [
  51 + { required: true, message: this.$t('integralRule.remarkRequired'), trigger: 'blur' },
  52 + { max: 512, message: this.$t('integralRule.remarkMaxLength'), trigger: 'blur' }
  53 + ],
  54 + ruleId: [
  55 + { required: true, message: this.$t('integralRule.ruleIdRequired'), trigger: 'blur' }
  56 + ]
  57 + }
  58 + }
  59 + },
  60 + methods: {
  61 + open(data) {
  62 + this.form = {
  63 + ruleId: data.ruleId,
  64 + ruleName: data.ruleName,
  65 + remark: data.remark
  66 + }
  67 + this.communityId = getCommunityId()
  68 + this.visible = true
  69 + },
  70 + handleClose() {
  71 + this.$refs.form.resetFields()
  72 + },
  73 + handleSubmit() {
  74 + this.$refs.form.validate(async valid => {
  75 + if (!valid) return
  76 +
  77 + try {
  78 + const params = {
  79 + ...this.form,
  80 + communityId: this.communityId
  81 + }
  82 + await updateIntegralRule(params)
  83 + this.$message.success(this.$t('common.editSuccess'))
  84 + this.visible = false
  85 + this.$emit('success')
  86 + } catch (error) {
  87 + this.$message.error(error.message || this.$t('common.editFailed'))
  88 + }
  89 + })
  90 + }
  91 + }
  92 +}
  93 +</script>
0 94 \ No newline at end of file
... ...
src/components/scm/editIntegralRuleFee.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('integralRule.editFeeTitle')"
  4 + :visible.sync="visible"
  5 + width="50%"
  6 + @close="handleClose"
  7 + >
  8 + <el-form
  9 + ref="form"
  10 + :model="form"
  11 + :rules="rules"
  12 + label-width="150px"
  13 + >
  14 + <el-form-item
  15 + :label="$t('integralRule.payStartTime')"
  16 + prop="payStartTime"
  17 + >
  18 + <el-date-picker
  19 + v-model="form.payStartTime"
  20 + type="datetime"
  21 + :placeholder="$t('integralRule.payStartTimePlaceholder')"
  22 + style="width: 100%"
  23 + value-format="yyyy-MM-dd HH:mm:ss"
  24 + />
  25 + </el-form-item>
  26 + <el-form-item
  27 + :label="$t('integralRule.payEndTime')"
  28 + prop="payEndTime"
  29 + >
  30 + <el-date-picker
  31 + v-model="form.payEndTime"
  32 + type="datetime"
  33 + :placeholder="$t('integralRule.payEndTimePlaceholder')"
  34 + style="width: 100%"
  35 + value-format="yyyy-MM-dd HH:mm:ss"
  36 + />
  37 + </el-form-item>
  38 + </el-form>
  39 + <span slot="footer" class="dialog-footer">
  40 + <el-button @click="visible = false">{{ $t('common.cancel') }}</el-button>
  41 + <el-button
  42 + type="primary"
  43 + @click="handleSubmit"
  44 + >{{ $t('common.confirm') }}</el-button>
  45 + </span>
  46 + </el-dialog>
  47 +</template>
  48 +
  49 +<script>
  50 +import { updateIntegralRuleFee } from '@/api/scm/integralRuleApi'
  51 +import { getCommunityId } from '@/api/community/communityApi'
  52 +
  53 +export default {
  54 + name: 'EditIntegralRuleFee',
  55 + data() {
  56 + return {
  57 + visible: false,
  58 + form: {
  59 + irfId: '',
  60 + ruleId: '',
  61 + payStartTime: '',
  62 + payEndTime: ''
  63 + },
  64 + rules: {
  65 + payStartTime: [
  66 + { required: true, message: this.$t('integralRule.payStartTimeRequired'), trigger: 'change' }
  67 + ],
  68 + payEndTime: [
  69 + { required: true, message: this.$t('integralRule.payEndTimeRequired'), trigger: 'change' },
  70 + {
  71 + validator: (rule, value, callback) => {
  72 + if (!value || !this.form.payStartTime) {
  73 + callback()
  74 + } else if (new Date(value) <= new Date(this.form.payStartTime)) {
  75 + callback(new Error(this.$t('integralRule.payEndTimeAfterStart')))
  76 + } else {
  77 + callback()
  78 + }
  79 + },
  80 + trigger: 'change'
  81 + }
  82 + ],
  83 + irfId: [
  84 + { required: true, message: this.$t('integralRule.feeIdRequired'), trigger: 'blur' }
  85 + ]
  86 + }
  87 + }
  88 + },
  89 + methods: {
  90 + open(data) {
  91 + this.form = {
  92 + irfId: data.irfId,
  93 + ruleId: data.ruleId,
  94 + payStartTime: data.payStartTime,
  95 + payEndTime: data.payEndTime
  96 + }
  97 + this.communityId = getCommunityId()
  98 + this.visible = true
  99 + },
  100 + handleClose() {
  101 + this.$refs.form.resetFields()
  102 + },
  103 + async handleSubmit() {
  104 + this.$refs.form.validate(async valid => {
  105 + if (!valid) return
  106 +
  107 + try {
  108 + const params = {
  109 + ...this.form,
  110 + communityId: this.communityId
  111 + }
  112 + await updateIntegralRuleFee(params)
  113 + this.$message.success(this.$t('common.editSuccess'))
  114 + this.visible = false
  115 + this.$emit('success')
  116 + } catch (error) {
  117 + this.$message.error(error.message || this.$t('common.editFailed'))
  118 + }
  119 + })
  120 + }
  121 + }
  122 +}
  123 +</script>
0 124 \ No newline at end of file
... ...
src/components/scm/integralRuleConfig.vue 0 → 100644
  1 +<template>
  2 + <div class="integral-rule-config">
  3 + <el-row class="operation-bar">
  4 + <el-col :span="24" class="text-right">
  5 + <el-button-group>
  6 + <el-button type="primary" size="small" @click="handleQuery">{{ $t('common.query') }}</el-button>
  7 + <el-button type="primary" size="small" @click="openAddModal">{{ $t('common.add') }}</el-button>
  8 + </el-button-group>
  9 + </el-col>
  10 + </el-row>
  11 +
  12 + <el-table :data="tableData" border style="width: 100%" v-loading="loading">
  13 + <el-table-column prop="configId" :label="$t('integralRule.configId')" width="100" align="center" />
  14 + <el-table-column prop="configName" :label="$t('integralRule.configName')" align="center" />
  15 + <el-table-column prop="computingFormulaName" :label="$t('integralRule.computingFormula')" align="center" />
  16 + <el-table-column prop="squarePrice" :label="$t('integralRule.squarePrice')" align="center" />
  17 + <el-table-column prop="additionalAmount" :label="$t('integralRule.additionalAmount')" align="center" />
  18 + <el-table-column prop="scaleName" :label="$t('integralRule.scale')" align="center" />
  19 + <el-table-column :label="$t('common.operation')" width="150" align="center">
  20 + <template slot-scope="scope">
  21 + <el-button size="mini" type="danger" @click="handleDelete(scope.row)">{{ $t('common.delete') }}</el-button>
  22 + </template>
  23 + </el-table-column>
  24 + </el-table>
  25 +
  26 + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
  27 + :current-page="pagination.current" :page-sizes="[10, 20, 30, 50]" :page-size="pagination.size"
  28 + layout="total, sizes, prev, pager, next, jumper" :total="pagination.total" />
  29 +
  30 + <add-integral-rule-config ref="addIntegralRuleConfig" :rule-id="ruleId" @success="handleSuccess" />
  31 + </div>
  32 +</template>
  33 +
  34 +<script>
  35 +import { listIntegralRuleConfig, deleteIntegralRuleConfig } from '@/api/scm/integralRuleApi'
  36 +import AddIntegralRuleConfig from './addIntegralRuleConfig'
  37 +
  38 +export default {
  39 + name: 'IntegralRuleConfig',
  40 + components: {
  41 + AddIntegralRuleConfig
  42 + },
  43 + data() {
  44 + return {
  45 + loading: false,
  46 + ruleId: '',
  47 + tableData: [],
  48 + pagination: {
  49 + current: 1,
  50 + size: 10,
  51 + total: 0
  52 + }
  53 + }
  54 + },
  55 + methods: {
  56 + open(rule) {
  57 + this.ruleId = rule.ruleId
  58 + this.handleQuery()
  59 + },
  60 + async fetchData() {
  61 + try {
  62 + this.loading = true
  63 + const params = {
  64 + page: this.pagination.current,
  65 + row: this.pagination.size,
  66 + ruleId: this.ruleId
  67 + }
  68 + const { data, total } = await listIntegralRuleConfig(params)
  69 + this.tableData = data
  70 + this.pagination.total = total
  71 + } catch (error) {
  72 + this.$message.error(this.$t('common.fetchError'))
  73 + } finally {
  74 + this.loading = false
  75 + }
  76 + },
  77 + handleQuery() {
  78 + this.pagination.current = 1
  79 + this.fetchData()
  80 + },
  81 + openAddModal() {
  82 + this.$refs.addIntegralRuleConfig.open()
  83 + },
  84 + async handleDelete(row) {
  85 + try {
  86 + await this.$confirm(
  87 + this.$t('integralRule.deleteConfigConfirm'),
  88 + this.$t('common.tip'),
  89 + {
  90 + confirmButtonText: this.$t('common.confirm'),
  91 + cancelButtonText: this.$t('common.cancel'),
  92 + type: 'warning'
  93 + }
  94 + )
  95 + await deleteIntegralRuleConfig({
  96 + configId: row.configId,
  97 + ruleId: this.ruleId,
  98 + ircId: row.ircId
  99 + })
  100 + this.$message.success(this.$t('common.deleteSuccess'))
  101 + this.handleQuery()
  102 + } catch (error) {
  103 + if (error !== 'cancel') {
  104 + this.$message.error(error.message || this.$t('common.deleteFailed'))
  105 + }
  106 + }
  107 + },
  108 + handleSizeChange(val) {
  109 + this.pagination.size = val
  110 + this.fetchData()
  111 + },
  112 + handleCurrentChange(val) {
  113 + this.pagination.current = val
  114 + this.fetchData()
  115 + },
  116 + handleSuccess() {
  117 + this.handleQuery()
  118 + }
  119 + }
  120 +}
  121 +</script>
  122 +
  123 +<style scoped>
  124 +.integral-rule-config {
  125 + padding: 20px;
  126 +}
  127 +
  128 +.operation-bar {
  129 + margin-bottom: 20px;
  130 +}
  131 +</style>
0 132 \ No newline at end of file
... ...
src/components/scm/integralRuleDiv.vue 0 → 100644
  1 +<template>
  2 + <div>
  3 +
  4 + <el-card class="box-card">
  5 + <div slot="header" class="flex justify-between">
  6 + <el-button-group>
  7 + <el-button size="small" @click="openAddModal">{{ $t('common.add') }}</el-button>
  8 + <el-button size="small" @click="openEditModal">{{ $t('common.edit') }}</el-button>
  9 + <el-button size="small" @click="openDeleteModal">{{ $t('common.delete') }}</el-button>
  10 + </el-button-group>
  11 + </div>
  12 + <el-tree
  13 + :data="integralRules"
  14 + :props="defaultProps"
  15 + node-key="ruleId"
  16 + highlight-current
  17 + @node-click="handleNodeClick"
  18 + ></el-tree>
  19 + </el-card>
  20 + <add-integral-rule ref="addIntegralRule" @success="handleSuccess" />
  21 + <edit-integral-rule ref="editIntegralRule" @success="handleSuccess" />
  22 + <delete-integral-rule ref="deleteIntegralRule" @success="handleSuccess" />
  23 + </div>
  24 +</template>
  25 +
  26 +<script>
  27 +import { listIntegralRule } from '@/api/scm/integralRuleApi'
  28 +import { getCommunityId } from '@/api/community/communityApi'
  29 +import AddIntegralRule from '@/components/scm/addIntegralRule'
  30 +import EditIntegralRule from '@/components/scm/editIntegralRule'
  31 +import DeleteIntegralRule from '@/components/scm/deleteIntegralRule'
  32 +export default {
  33 + name: 'IntegralRuleDiv',
  34 + data() {
  35 + return {
  36 + integralRules: [],
  37 + curIntegralRule: {},
  38 + defaultProps: {
  39 + children: 'children',
  40 + label: 'ruleName'
  41 + }
  42 + }
  43 + },
  44 + components: {
  45 + AddIntegralRule,
  46 + EditIntegralRule,
  47 + DeleteIntegralRule
  48 + },
  49 + created() {
  50 + this.communityId = getCommunityId()
  51 + this.refreshList()
  52 + },
  53 + methods: {
  54 + async refreshList() {
  55 + try {
  56 + const params = {
  57 + page: 1,
  58 + row: 100,
  59 + communityId: this.communityId
  60 + }
  61 + const { data } = await listIntegralRule(params)
  62 + this.integralRules = data
  63 + if (this.integralRules.length > 0) {
  64 + this.handleNodeClick(this.integralRules[0])
  65 + }
  66 + } catch (error) {
  67 + this.$message.error(this.$t('integralRule.fetchError'))
  68 + }
  69 + },
  70 + handleNodeClick(data) {
  71 + this.curIntegralRule = data
  72 + this.$emit('switch', data)
  73 + },
  74 + openAddModal() {
  75 + this.$refs.addIntegralRule.open()
  76 + },
  77 + openEditModal() {
  78 + if (!this.curIntegralRule.ruleId) {
  79 + this.$message.warning(this.$t('integralRule.selectRule'))
  80 + return
  81 + }
  82 + this.$refs.editIntegralRule.open(this.curIntegralRule)
  83 + },
  84 + openDeleteModal() {
  85 + if (!this.curIntegralRule.ruleId) {
  86 + this.$message.warning(this.$t('integralRule.selectRule'))
  87 + return
  88 + }
  89 + this.$refs.deleteIntegralRule.open(this.curIntegralRule)
  90 + },
  91 + handleSuccess() {
  92 + this.refreshList()
  93 + }
  94 + }
  95 +}
  96 +</script>
  97 +
  98 +<style scoped>
  99 +.box-card {
  100 + height: 100%;
  101 +}
  102 +
  103 +.el-tree {
  104 + margin-top: 10px;
  105 +}
  106 +</style>
0 107 \ No newline at end of file
... ...
src/components/scm/integralRuleFees.vue 0 → 100644
  1 +<template>
  2 + <div class="integral-rule-fees">
  3 + <el-row class="operation-bar">
  4 + <el-col :span="24" class="text-right">
  5 + <el-button-group>
  6 + <el-button type="primary" size="small" @click="handleQuery">{{ $t('common.query') }}</el-button>
  7 + <el-button type="primary" size="small" @click="openAddModal">{{ $t('common.add') }}</el-button>
  8 + </el-button-group>
  9 + </el-col>
  10 + </el-row>
  11 +
  12 + <el-table :data="tableData" border style="width: 100%" v-loading="loading">
  13 + <el-table-column prop="irfId" :label="$t('integralRule.feeId')" width="100" align="center" />
  14 + <el-table-column :label="$t('integralRule.payTimeRange')" align="center">
  15 + <template slot-scope="scope">
  16 + {{ scope.row.payStartTime }} ~ {{ scope.row.payEndTime }}
  17 + </template>
  18 + </el-table-column>
  19 + <el-table-column :label="$t('common.operation')" width="200" align="center">
  20 + <template slot-scope="scope">
  21 + <el-button size="mini" type="primary" @click="handleEdit(scope.row)">{{ $t('common.edit') }}</el-button>
  22 + <el-button size="mini" type="danger" @click="handleDelete(scope.row)">{{ $t('common.delete') }}</el-button>
  23 + </template>
  24 + </el-table-column>
  25 + </el-table>
  26 +
  27 + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
  28 + :current-page="pagination.current" :page-sizes="[10, 20, 30, 50]" :page-size="pagination.size"
  29 + layout="total, sizes, prev, pager, next, jumper" :total="pagination.total" />
  30 +
  31 + <add-integral-rule-fee ref="addIntegralRuleFee" :rule-id="ruleId" @success="handleSuccess" />
  32 + <edit-integral-rule-fee ref="editIntegralRuleFee" @success="handleSuccess" />
  33 + </div>
  34 +</template>
  35 +
  36 +<script>
  37 +import { listIntegralRuleFee, deleteIntegralRuleFee } from '@/api/scm/integralRuleApi'
  38 +import AddIntegralRuleFee from './addIntegralRuleFee'
  39 +import EditIntegralRuleFee from './editIntegralRuleFee'
  40 +
  41 +export default {
  42 + name: 'IntegralRuleFees',
  43 + components: {
  44 + AddIntegralRuleFee,
  45 + EditIntegralRuleFee
  46 + },
  47 + data() {
  48 + return {
  49 + ruleId: '',
  50 + loading: false,
  51 + tableData: [],
  52 + pagination: {
  53 + current: 1,
  54 + size: 10,
  55 + total: 0
  56 + }
  57 + }
  58 + },
  59 + methods: {
  60 + open(rule) {
  61 + this.ruleId = rule.ruleId
  62 + this.handleQuery()
  63 + },
  64 + async fetchData() {
  65 + try {
  66 + this.loading = true
  67 + const params = {
  68 + page: this.pagination.current,
  69 + row: this.pagination.size,
  70 + ruleId: this.ruleId
  71 + }
  72 + const { data, total } = await listIntegralRuleFee(params)
  73 + this.tableData = data
  74 + this.pagination.total = total
  75 + } catch (error) {
  76 + this.$message.error(this.$t('common.fetchError'))
  77 + } finally {
  78 + this.loading = false
  79 + }
  80 + },
  81 + handleQuery() {
  82 + this.pagination.current = 1
  83 + this.fetchData()
  84 + },
  85 + openAddModal() {
  86 + console.log(this.ruleId)
  87 + this.$refs.addIntegralRuleFee.open({
  88 + ruleId: this.ruleId
  89 + })
  90 + },
  91 + handleEdit(row) {
  92 + this.$refs.editIntegralRuleFee.open(row)
  93 + },
  94 + async handleDelete(row) {
  95 + try {
  96 + await this.$confirm(
  97 + this.$t('integralRule.deleteFeeConfirm'),
  98 + this.$t('common.tip'),
  99 + {
  100 + confirmButtonText: this.$t('common.confirm'),
  101 + cancelButtonText: this.$t('common.cancel'),
  102 + type: 'warning'
  103 + }
  104 + )
  105 +
  106 + await deleteIntegralRuleFee({
  107 + irfId: row.irfId,
  108 + ruleId: this.ruleId
  109 + })
  110 + this.$message.success(this.$t('common.deleteSuccess'))
  111 + this.handleQuery()
  112 + } catch (error) {
  113 + if (error !== 'cancel') {
  114 + this.$message.error(error.message || this.$t('common.deleteFailed'))
  115 + }
  116 + }
  117 + },
  118 + handleSizeChange(val) {
  119 + this.pagination.size = val
  120 + this.fetchData()
  121 + },
  122 + handleCurrentChange(val) {
  123 + this.pagination.current = val
  124 + this.fetchData()
  125 + },
  126 + handleSuccess() {
  127 + this.handleQuery()
  128 + }
  129 + }
  130 +}
  131 +</script>
  132 +
  133 +<style scoped>
  134 +.integral-rule-fees {
  135 + padding: 20px;
  136 +}
  137 +
  138 +.operation-bar {
  139 + margin-bottom: 20px;
  140 +}
  141 +</style>
0 142 \ No newline at end of file
... ...
src/i18n/scmI18n.js
1 1 import { messages as couponMarketMessages } from '../views/scm/couponMarketLang'
2 2 import { messages as couponPropertyPoolManageMessages } from '../views/scm/couponPropertyPoolManageLang'
3 3 import { messages as couponRuleMessages } from '../views/scm/couponRuleLang'
  4 +import { messages as couponPropertyPoolDetailMessages } from '../views/scm/couponPropertyPoolDetailLang'
  5 +import { messages as couponPropertyUserManageMessages } from '../views/scm/couponPropertyUserManageLang'
  6 +import { messages as couponPropertyUserDetailMessages } from '../views/scm/couponPropertyUserDetailLang'
  7 +import { messages as integralConfigManageMessages } from '../views/scm/integralConfigManageLang'
  8 +import { messages as integralRuleMessages } from '../views/scm/integralRuleLang'
  9 +import { messages as integralGiftDetailManageMessages } from '../views/scm/integralGiftDetailManageLang'
4 10  
5 11 export const messages = {
6 12 en: {
... ... @@ -8,10 +14,22 @@ export const messages = {
8 14 ...couponMarketMessages.en,
9 15 ...couponPropertyPoolManageMessages.en,
10 16 ...couponRuleMessages.en,
11   - },
  17 + ...couponPropertyPoolDetailMessages.en,
  18 + ...couponPropertyUserManageMessages.en,
  19 + ...couponPropertyUserDetailMessages.en,
  20 + ...integralConfigManageMessages.en,
  21 + ...integralRuleMessages.en,
  22 + ...integralGiftDetailManageMessages.en,
  23 + },
12 24 zh: {
13 25 ...couponMarketMessages.zh,
14 26 ...couponPropertyPoolManageMessages.zh,
15 27 ...couponRuleMessages.zh,
  28 + ...couponPropertyPoolDetailMessages.zh,
  29 + ...couponPropertyUserManageMessages.zh,
  30 + ...couponPropertyUserDetailMessages.zh,
  31 + ...integralConfigManageMessages.zh,
  32 + ...integralRuleMessages.zh,
  33 + ...integralGiftDetailManageMessages.zh,
16 34 }
17 35 }
18 36 \ No newline at end of file
... ...
src/router/scmRouter.js
... ... @@ -10,8 +10,38 @@ export default [
10 10 component: () => import('@/views/scm/couponPropertyPoolManageList.vue')
11 11 },
12 12 {
13   - path:'/pages/scm/couponRule',
14   - name:'/pages/scm/couponRule',
  13 + path: '/pages/scm/couponRule',
  14 + name: '/pages/scm/couponRule',
15 15 component: () => import('@/views/scm/couponRuleList.vue')
16   - },
  16 + },
  17 + {
  18 + path: '/pages/scm/couponPropertyPoolDetail',
  19 + name: '/pages/scm/couponPropertyPoolDetail',
  20 + component: () => import('@/views/scm/couponPropertyPoolDetailList.vue')
  21 + },
  22 + {
  23 + path: '/pages/scm/couponPropertyUserManage',
  24 + name: '/pages/scm/couponPropertyUserManage',
  25 + component: () => import('@/views/scm/couponPropertyUserManageList.vue')
  26 + },
  27 + {
  28 + path: '/pages/scm/couponPropertyUserDetail',
  29 + name: '/pages/scm/couponPropertyUserDetail',
  30 + component: () => import('@/views/scm/couponPropertyUserDetailList.vue')
  31 + },
  32 + {
  33 + path: '/pages/scm/integralConfigManage',
  34 + name: '/pages/scm/integralConfigManage',
  35 + component: () => import('@/views/scm/integralConfigManageList.vue')
  36 + },
  37 + {
  38 + path: '/pages/scm/integralRule',
  39 + name: '/pages/scm/integralRule',
  40 + component: () => import('@/views/scm/integralRuleList.vue')
  41 + },
  42 + {
  43 + path: '/pages/scm/integralGiftDetailManage',
  44 + name: '/pages/scm/integralGiftDetailManage',
  45 + component: () => import('@/views/scm/integralGiftDetailManageList.vue')
  46 + },
17 47 ]
18 48 \ No newline at end of file
... ...
src/views/scm/couponPropertyPoolDetailLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + couponPropertyPoolDetail: {
  4 + search: {
  5 + title: 'Search Conditions',
  6 + cppId: 'Coupon ID',
  7 + couponName: 'Coupon Name',
  8 + fromType: 'Source Type',
  9 + fromTypePlaceholder: 'Please select source type',
  10 + fromType1: 'Purchased from coupon market',
  11 + fromType2: 'Self-made',
  12 + userName: 'User Name',
  13 + tel: 'Phone Number',
  14 + toType: 'Usage Type',
  15 + toTypePlaceholder: 'Please select usage type',
  16 + toType1: 'Shopping',
  17 + toType2: 'Maintenance Coupon',
  18 + toType3: 'Parking Coupon'
  19 + },
  20 + list: {
  21 + title: 'Gift Records'
  22 + },
  23 + table: {
  24 + cppId: 'ID',
  25 + couponName: 'Coupon Name',
  26 + value: 'Face Value',
  27 + sendCount: 'Quantity',
  28 + unit: 'piece',
  29 + userName: 'User Name',
  30 + tel: 'Phone Number',
  31 + createTime: 'Gift Time'
  32 + },
  33 + btn: {
  34 + return: 'Return'
  35 + },
  36 + delete: {
  37 + title: 'Confirm Operation',
  38 + confirmText: 'Are you sure to return this coupon?',
  39 + success: 'Return successfully',
  40 + error: 'Return failed'
  41 + },
  42 + fetchError: 'Failed to fetch data'
  43 + }
  44 + },
  45 + zh: {
  46 + couponPropertyPoolDetail: {
  47 + search: {
  48 + title: '查询条件',
  49 + cppId: '优惠券编号',
  50 + couponName: '优惠券名称',
  51 + fromType: '来源方式',
  52 + fromTypePlaceholder: '请选择来源方式',
  53 + fromType1: '优惠券市场购买',
  54 + fromType2: '自己制作',
  55 + userName: '用户名称',
  56 + tel: '手机号',
  57 + toType: '用途',
  58 + toTypePlaceholder: '请选择用途',
  59 + toType1: '购物',
  60 + toType2: '维修券',
  61 + toType3: '停车券'
  62 + },
  63 + list: {
  64 + title: '赠送记录'
  65 + },
  66 + table: {
  67 + cppId: '编号',
  68 + couponName: '优惠券名称',
  69 + value: '面值',
  70 + sendCount: '数量',
  71 + unit: '张',
  72 + userName: '用户名称',
  73 + tel: '手机号',
  74 + createTime: '赠送时间'
  75 + },
  76 + btn: {
  77 + return: '退回'
  78 + },
  79 + delete: {
  80 + title: '确认操作',
  81 + confirmText: '确定退回优惠券吗?',
  82 + success: '退回成功',
  83 + error: '退回失败'
  84 + },
  85 + fetchError: '获取数据失败'
  86 + }
  87 + }
  88 +}
0 89 \ No newline at end of file
... ...
src/views/scm/couponPropertyPoolDetailList.vue 0 → 100644
  1 +<template>
  2 + <div class="coupon-property-pool-detail-container">
  3 + <!-- 查询条件 -->
  4 + <el-card class="search-wrapper">
  5 + <div slot="header" class="flex justify-between">
  6 + <span>{{ $t('couponPropertyPoolDetail.search.title') }}</span>
  7 + </div>
  8 + <el-row :gutter="20">
  9 + <el-col :span="6">
  10 + <el-input v-model="searchForm.cppId" :placeholder="$t('couponPropertyPoolDetail.search.cppId')" clearable />
  11 + </el-col>
  12 + <el-col :span="6">
  13 + <el-input v-model="searchForm.couponName" :placeholder="$t('couponPropertyPoolDetail.search.couponName')"
  14 + clearable />
  15 + </el-col>
  16 + <el-col :span="6">
  17 + <el-select v-model="searchForm.fromType" :placeholder="$t('couponPropertyPoolDetail.search.fromType')"
  18 + style="width:100%">
  19 + <el-option :label="$t('couponPropertyPoolDetail.search.fromTypePlaceholder')" value="" />
  20 + <el-option :label="$t('couponPropertyPoolDetail.search.fromType1')" value="1001" />
  21 + <el-option :label="$t('couponPropertyPoolDetail.search.fromType2')" value="2002" />
  22 + </el-select>
  23 + </el-col>
  24 + <el-col :span="6">
  25 + <el-button type="primary" @click="handleSearch">
  26 + {{ $t('common.search') }}
  27 + </el-button>
  28 + </el-col>
  29 + </el-row>
  30 + <el-row :gutter="20" style="margin-top:20px">
  31 + <el-col :span="6">
  32 + <el-input v-model="searchForm.userName" :placeholder="$t('couponPropertyPoolDetail.search.userName')"
  33 + clearable />
  34 + </el-col>
  35 + <el-col :span="6">
  36 + <el-input v-model="searchForm.tel" :placeholder="$t('couponPropertyPoolDetail.search.tel')" clearable />
  37 + </el-col>
  38 + <el-col :span="6">
  39 + <el-select v-model="searchForm.toType" :placeholder="$t('couponPropertyPoolDetail.search.toType')"
  40 + style="width:100%">
  41 + <el-option :label="$t('couponPropertyPoolDetail.search.toTypePlaceholder')" value="" />
  42 + <el-option :label="$t('couponPropertyPoolDetail.search.toType1')" value="1011" />
  43 + <el-option :label="$t('couponPropertyPoolDetail.search.toType2')" value="3003" />
  44 + <el-option :label="$t('couponPropertyPoolDetail.search.toType3')" value="4004" />
  45 + </el-select>
  46 + </el-col>
  47 + </el-row>
  48 + </el-card>
  49 +
  50 + <!-- 赠送记录列表 -->
  51 + <el-card class="list-wrapper">
  52 + <div slot="header" class="flex justify-between">
  53 + <span>{{ $t('couponPropertyPoolDetail.list.title') }}</span>
  54 + </div>
  55 + <el-table v-loading="loading" :data="tableData" border style="width: 100%">
  56 + <el-table-column prop="cppId" :label="$t('couponPropertyPoolDetail.table.cppId')" align="center" />
  57 + <el-table-column prop="couponName" :label="$t('couponPropertyPoolDetail.table.couponName')" align="center" />
  58 + <el-table-column prop="value" :label="$t('couponPropertyPoolDetail.table.value')" align="center" />
  59 + <el-table-column prop="sendCount" :label="$t('couponPropertyPoolDetail.table.sendCount')" align="center">
  60 + <template slot-scope="scope">
  61 + {{ scope.row.sendCount }}{{ $t('couponPropertyPoolDetail.table.unit') }}
  62 + </template>
  63 + </el-table-column>
  64 + <el-table-column prop="userName" :label="$t('couponPropertyPoolDetail.table.userName')" align="center" />
  65 + <el-table-column prop="tel" :label="$t('couponPropertyPoolDetail.table.tel')" align="center" />
  66 + <el-table-column prop="createTime" :label="$t('couponPropertyPoolDetail.table.createTime')" align="center" />
  67 + <el-table-column :label="$t('common.operation')" align="center" width="150">
  68 + <template slot-scope="scope">
  69 + <el-button size="mini" type="danger" @click="handleReturn(scope.row)">
  70 + {{ $t('couponPropertyPoolDetail.btn.return') }}
  71 + </el-button>
  72 + </template>
  73 + </el-table-column>
  74 + </el-table>
  75 +
  76 + <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
  77 + :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
  78 + @current-change="handleCurrentChange" />
  79 + </el-card>
  80 +
  81 + <!-- 退回确认对话框 -->
  82 + <delete-coupon-property-pool-detail ref="deleteDialog" @success="handleSuccess" />
  83 + </div>
  84 +</template>
  85 +
  86 +<script>
  87 +import { listCouponPropertyPoolDetail } from '@/api/scm/couponPropertyPoolDetailApi'
  88 +import DeleteCouponPropertyPoolDetail from '@/components/scm/deleteCouponPropertyPoolDetail'
  89 +import { getCommunityId } from '@/api/community/communityApi'
  90 +
  91 +export default {
  92 + name: 'CouponPropertyPoolDetailList',
  93 + components: {
  94 + DeleteCouponPropertyPoolDetail
  95 + },
  96 + data() {
  97 + return {
  98 + loading: false,
  99 + searchForm: {
  100 + cppId: '',
  101 + couponName: '',
  102 + fromType: '',
  103 + toType: '',
  104 + userName: '',
  105 + tel: '',
  106 + communityId: ''
  107 + },
  108 + tableData: [],
  109 + page: {
  110 + current: 1,
  111 + size: 10,
  112 + total: 0
  113 + }
  114 + }
  115 + },
  116 + created() {
  117 + this.searchForm.communityId = getCommunityId()
  118 + this.getList()
  119 + },
  120 + methods: {
  121 + async getList() {
  122 + try {
  123 + this.loading = true
  124 + const params = {
  125 + ...this.searchForm,
  126 + page: this.page.current,
  127 + row: this.page.size
  128 + }
  129 + const { data, total } = await listCouponPropertyPoolDetail(params)
  130 + this.tableData = data
  131 + this.page.total = total
  132 + } catch (error) {
  133 + this.$message.error(this.$t('couponPropertyPoolDetail.fetchError'))
  134 + } finally {
  135 + this.loading = false
  136 + }
  137 + },
  138 + handleSearch() {
  139 + this.page.current = 1
  140 + this.getList()
  141 + },
  142 + handleReturn(row) {
  143 + this.$refs.deleteDialog.open(row)
  144 + },
  145 + handleSuccess() {
  146 + this.getList()
  147 + },
  148 + handleSizeChange(val) {
  149 + this.page.size = val
  150 + this.getList()
  151 + },
  152 + handleCurrentChange(val) {
  153 + this.page.current = val
  154 + this.getList()
  155 + }
  156 + }
  157 +}
  158 +</script>
  159 +
  160 +<style lang="scss" scoped>
  161 +.coupon-property-pool-detail-container {
  162 + padding: 20px;
  163 +
  164 + .search-wrapper {
  165 + margin-bottom: 20px;
  166 + }
  167 +
  168 + .list-wrapper {
  169 + margin-top: 20px;
  170 + }
  171 +
  172 + .el-pagination {
  173 + margin-top: 20px;
  174 + text-align: right;
  175 + }
  176 +}
  177 +</style>
0 178 \ No newline at end of file
... ...
src/views/scm/couponPropertyUserDetailLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + couponPropertyUser: {
  4 + scanPlaceholder: 'Please scan with barcode scanner',
  5 + verify: 'Verify',
  6 + verifyResult: 'Verification Result',
  7 + verifyTime: 'Verification Time',
  8 + couponName: 'Coupon Name',
  9 + faceValue: 'Face Value',
  10 + userName: 'User Name',
  11 + phone: 'Phone',
  12 + purpose: 'Purpose',
  13 + searchCondition: 'Search Conditions',
  14 + couponNamePlaceholder: 'Please enter coupon name',
  15 + userNamePlaceholder: 'Please enter user name',
  16 + phonePlaceholder: 'Please enter phone number',
  17 + usageRecord: 'Coupon Usage Records',
  18 + serialNumber: 'No.',
  19 + usageTime: 'Usage Time',
  20 + scanTip: 'Please scan first',
  21 + verifySuccess: 'Verification successful',
  22 + fetchError: 'Failed to fetch data'
  23 + }
  24 + },
  25 + zh: {
  26 + couponPropertyUser: {
  27 + scanPlaceholder: '请扫码枪扫码核销',
  28 + verify: '核销',
  29 + verifyResult: '核销结果',
  30 + verifyTime: '核销时间',
  31 + couponName: '优惠券名称',
  32 + faceValue: '面值',
  33 + userName: '用户名称',
  34 + phone: '手机号',
  35 + purpose: '用途',
  36 + searchCondition: '查询条件',
  37 + couponNamePlaceholder: '请填写优惠券名称',
  38 + userNamePlaceholder: '请填写用户名称',
  39 + phonePlaceholder: '请填写手机号',
  40 + usageRecord: '优惠券使用记录',
  41 + serialNumber: '编号',
  42 + usageTime: '使用时间',
  43 + scanTip: '请先扫码',
  44 + verifySuccess: '核销成功',
  45 + fetchError: '获取数据失败'
  46 + }
  47 + }
  48 +}
0 49 \ No newline at end of file
... ...
src/views/scm/couponPropertyUserDetailList.vue 0 → 100644
  1 +<template>
  2 + <div class="coupon-property-user-detail-container">
  3 + <el-row :gutter="20">
  4 + <el-col :span="6">
  5 + <el-card class="verification-card">
  6 + <div class="verification-wrapper">
  7 + <el-row :gutter="10">
  8 + <el-col :span="18">
  9 + <el-input v-model="couponId" :placeholder="$t('couponPropertyUser.scanPlaceholder')"
  10 + @keyup.enter.native="handleConfirmCoupon" />
  11 + </el-col>
  12 + <el-col :span="6">
  13 + <el-button type="primary" @click="handleConfirmCoupon">
  14 + {{ $t('couponPropertyUser.verify') }}
  15 + </el-button>
  16 + </el-col>
  17 + </el-row>
  18 +
  19 + <div class="verification-result">
  20 + <div class="result-item">
  21 + <span class="label">{{ $t('couponPropertyUser.verifyResult') }}:</span>
  22 + <span class="value">{{ order.remark }}</span>
  23 + </div>
  24 + <div class="result-item">
  25 + <span class="label">{{ $t('couponPropertyUser.verifyTime') }}:</span>
  26 + <span class="value">{{ order.createTime }}</span>
  27 + </div>
  28 + <div class="result-item">
  29 + <span class="label">{{ $t('couponPropertyUser.couponName') }}:</span>
  30 + <span class="value">{{ order.couponName }}</span>
  31 + </div>
  32 + <div class="result-item">
  33 + <span class="label">{{ $t('couponPropertyUser.faceValue') }}:</span>
  34 + <span class="value">{{ order.value }}</span>
  35 + </div>
  36 + <div class="result-item">
  37 + <span class="label">{{ $t('couponPropertyUser.userName') }}:</span>
  38 + <span class="value">{{ order.userName }}</span>
  39 + </div>
  40 + <div class="result-item">
  41 + <span class="label">{{ $t('couponPropertyUser.phone') }}:</span>
  42 + <span class="value">{{ order.tel }}</span>
  43 + </div>
  44 + <div class="result-item">
  45 + <span class="label">{{ $t('couponPropertyUser.purpose') }}:</span>
  46 + <span class="value">{{ order.toTypeName }}</span>
  47 + </div>
  48 + </div>
  49 + </div>
  50 + </el-card>
  51 + </el-col>
  52 +
  53 + <el-col :span="18">
  54 + <el-card class="search-card">
  55 + <div slot="header" class="flex justify-between">
  56 + <span>{{ $t('couponPropertyUser.searchCondition') }}</span>
  57 + </div>
  58 + <el-row :gutter="20">
  59 + <el-col :span="8">
  60 + <el-input v-model="conditions.couponName" :placeholder="$t('couponPropertyUser.couponNamePlaceholder')" />
  61 + </el-col>
  62 + <el-col :span="8">
  63 + <el-input v-model="conditions.userName" :placeholder="$t('couponPropertyUser.userNamePlaceholder')" />
  64 + </el-col>
  65 + <el-col :span="6">
  66 + <el-input v-model="conditions.tel" :placeholder="$t('couponPropertyUser.phonePlaceholder')" />
  67 + </el-col>
  68 + <el-col :span="2">
  69 + <el-button type="primary" @click="handleQuery">
  70 + <i class="el-icon-search"></i>
  71 + {{ $t('common.search') }}
  72 + </el-button>
  73 + </el-col>
  74 + </el-row>
  75 + </el-card>
  76 +
  77 + <el-card class="table-card">
  78 + <div slot="header" class="flex justify-between">
  79 + <span>{{ $t('couponPropertyUser.usageRecord') }}</span>
  80 + </div>
  81 + <el-table :data="couponPropertyUsers" border style="width: 100%" v-loading="loading">
  82 + <el-table-column prop="uoId" :label="$t('couponPropertyUser.serialNumber')" align="center" />
  83 + <el-table-column prop="couponName" :label="$t('couponPropertyUser.couponName')" align="center" />
  84 + <el-table-column prop="value" :label="$t('couponPropertyUser.faceValue')" align="center" />
  85 + <el-table-column prop="userName" :label="$t('couponPropertyUser.userName')" align="center" />
  86 + <el-table-column prop="tel" :label="$t('couponPropertyUser.phone')" align="center" />
  87 + <el-table-column prop="remark" :label="$t('couponPropertyUser.purpose')" align="center" />
  88 + <el-table-column prop="createTime" :label="$t('couponPropertyUser.usageTime')" align="center" />
  89 + </el-table>
  90 +
  91 + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
  92 + :current-page="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
  93 + layout="total, sizes, prev, pager, next, jumper" :total="page.total" class="pagination" />
  94 + </el-card>
  95 + </el-col>
  96 + </el-row>
  97 + </div>
  98 +</template>
  99 +
  100 +<script>
  101 +import { listCouponPropertyUserDetail, writeOffCouponPropertyUser } from '@/api/scm/couponPropertyUserDetailApi'
  102 +import { getCommunityId } from '@/api/community/communityApi'
  103 +
  104 +export default {
  105 + name: 'CouponPropertyUserDetailList',
  106 + data() {
  107 + return {
  108 + loading: false,
  109 + couponId: '',
  110 + couponPropertyUsers: [],
  111 + order: {
  112 + remark: '',
  113 + userName: '',
  114 + createTime: '',
  115 + tel: '',
  116 + couponName: '',
  117 + value: '',
  118 + toTypeName: ''
  119 + },
  120 + conditions: {
  121 + couponId: '',
  122 + couponName: '',
  123 + validityDay: '',
  124 + userName: '',
  125 + tel: '',
  126 + toType: '',
  127 + state: '',
  128 + communityId: getCommunityId()
  129 + },
  130 + page: {
  131 + current: 1,
  132 + size: 10,
  133 + total: 0
  134 + }
  135 + }
  136 + },
  137 + created() {
  138 + this.getList()
  139 + },
  140 + methods: {
  141 + async getList() {
  142 + try {
  143 + this.loading = true
  144 + const params = {
  145 + page: this.page.current,
  146 + row: this.page.size,
  147 + ...this.conditions
  148 + }
  149 + const { data, total } = await listCouponPropertyUserDetail(params)
  150 + this.couponPropertyUsers = data
  151 + this.page.total = total
  152 + } catch (error) {
  153 + this.$message.error(this.$t('couponPropertyUser.fetchError'))
  154 + } finally {
  155 + this.loading = false
  156 + }
  157 + },
  158 + handleQuery() {
  159 + this.page.current = 1
  160 + this.getList()
  161 + },
  162 + async handleConfirmCoupon() {
  163 + if (!this.couponId) {
  164 + this.$message.warning(this.$t('couponPropertyUser.scanTip'))
  165 + return
  166 + }
  167 +
  168 + try {
  169 + const data = {
  170 + couponQrcode: this.couponId,
  171 + communityId: this.conditions.communityId,
  172 + giftCount: 1
  173 + }
  174 + const res = await writeOffCouponPropertyUser(data)
  175 + if (res.code !== 0) {
  176 + this.$message.error(res.msg)
  177 + return
  178 + }
  179 +
  180 + this.couponId = ''
  181 + this.$message.success(this.$t('couponPropertyUser.verifySuccess'))
  182 + this.getList()
  183 +
  184 + if (res.data && res.data.length > 0) {
  185 + this.order = { ...res.data[0] }
  186 + if (!this.order.remark) {
  187 + this.order.remark = this.$t('couponPropertyUser.verifySuccess')
  188 + }
  189 + }
  190 + } catch (error) {
  191 + this.couponId = ''
  192 + this.$message.error(error.message)
  193 + }
  194 + },
  195 + handleSizeChange(val) {
  196 + this.page.size = val
  197 + this.getList()
  198 + },
  199 + handleCurrentChange(val) {
  200 + this.page.current = val
  201 + this.getList()
  202 + }
  203 + }
  204 +}
  205 +</script>
  206 +
  207 +<style lang="scss" scoped>
  208 +.coupon-property-user-detail-container {
  209 + padding: 20px;
  210 +
  211 + .verification-card {
  212 + height: 100%;
  213 +
  214 + .verification-wrapper {
  215 + padding: 10px;
  216 +
  217 + .verification-result {
  218 + margin-top: 20px;
  219 +
  220 + .result-item {
  221 + display: flex;
  222 + justify-content: space-between;
  223 + margin-bottom: 10px;
  224 + font-size: 14px;
  225 +
  226 + .label {
  227 + color: #606266;
  228 + }
  229 +
  230 + .value {
  231 + color: #303133;
  232 + font-weight: 500;
  233 + }
  234 + }
  235 + }
  236 + }
  237 + }
  238 +
  239 + .search-card {
  240 + margin-bottom: 20px;
  241 + }
  242 +
  243 + .table-card {
  244 + .pagination {
  245 + margin-top: 20px;
  246 + text-align: right;
  247 + }
  248 + }
  249 +
  250 + .el-input {
  251 + width: 100%;
  252 + }
  253 +}
  254 +</style>
0 255 \ No newline at end of file
... ...
src/views/scm/couponPropertyUserManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + couponPropertyUserManage: {
  4 + search: {
  5 + title: 'Search Conditions',
  6 + couponId: 'Coupon ID',
  7 + couponName: 'Coupon Name',
  8 + validityDay: 'Validity Day',
  9 + userName: 'User Name',
  10 + tel: 'Phone Number',
  11 + toType: 'Usage',
  12 + selectToType: 'Select Usage',
  13 + shopping: 'Shopping',
  14 + payment: 'Payment',
  15 + repair: 'Repair Coupon',
  16 + parking: 'Parking Coupon',
  17 + state: 'Status',
  18 + selectState: 'Select Status',
  19 + unused: 'Unused',
  20 + used: 'Used'
  21 + },
  22 + list: {
  23 + title: 'Owner Coupons'
  24 + },
  25 + table: {
  26 + couponId: 'ID',
  27 + couponName: 'Coupon Name',
  28 + value: 'Face Value',
  29 + validityDay: 'Validity',
  30 + userName: 'User Name',
  31 + tel: 'Phone',
  32 + toType: 'Usage',
  33 + quantity: 'Quantity',
  34 + sheet: 'Sheet',
  35 + state: 'Status',
  36 + startTime: 'Effective Time',
  37 + unused: 'Unused',
  38 + used: 'Used'
  39 + },
  40 + fetchError: 'Failed to fetch coupon data'
  41 + }
  42 + },
  43 + zh: {
  44 + couponPropertyUserManage: {
  45 + search: {
  46 + title: '查询条件',
  47 + couponId: '优惠券编号',
  48 + couponName: '优惠券名称',
  49 + validityDay: '有效期',
  50 + userName: '用户名称',
  51 + tel: '手机号',
  52 + toType: '用途',
  53 + selectToType: '选择用途',
  54 + shopping: '购物',
  55 + payment: '缴费',
  56 + repair: '维修劵',
  57 + parking: '停车劵',
  58 + state: '状态',
  59 + selectState: '请选择状态',
  60 + unused: '未使用',
  61 + used: '已使用'
  62 + },
  63 + list: {
  64 + title: '业主优惠券'
  65 + },
  66 + table: {
  67 + couponId: '编号',
  68 + couponName: '优惠券名称',
  69 + value: '面值',
  70 + validityDay: '有效期',
  71 + userName: '用户名称',
  72 + tel: '手机号',
  73 + toType: '用途',
  74 + quantity: '数量',
  75 + sheet: '张',
  76 + state: '状态',
  77 + startTime: '生效时间',
  78 + unused: '未使用',
  79 + used: '已使用'
  80 + },
  81 + fetchError: '获取优惠券数据失败'
  82 + }
  83 + }
  84 +}
0 85 \ No newline at end of file
... ...
src/views/scm/couponPropertyUserManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="coupon-property-user-manage-container">
  3 + <!-- 查询条件 -->
  4 + <el-card class="search-wrapper">
  5 + <div slot="header" class="flex justify-between">
  6 + <span>{{ $t('couponPropertyUserManage.search.title') }}</span>
  7 + </div>
  8 + <el-row :gutter="20">
  9 + <el-col :span="6">
  10 + <el-input v-model="searchForm.couponId" :placeholder="$t('couponPropertyUserManage.search.couponId')"
  11 + clearable />
  12 + </el-col>
  13 + <el-col :span="6">
  14 + <el-input v-model="searchForm.couponName" :placeholder="$t('couponPropertyUserManage.search.couponName')"
  15 + clearable />
  16 + </el-col>
  17 + <el-col :span="6">
  18 + <el-input v-model="searchForm.validityDay" :placeholder="$t('couponPropertyUserManage.search.validityDay')"
  19 + clearable />
  20 + </el-col>
  21 + <el-col :span="6">
  22 + <el-button type="primary" @click="handleSearch">
  23 + {{ $t('common.search') }}
  24 + </el-button>
  25 + </el-col>
  26 + </el-row>
  27 +
  28 + <el-row :gutter="20" style="margin-top: 15px;">
  29 + <el-col :span="6">
  30 + <el-input v-model="searchForm.userName" :placeholder="$t('couponPropertyUserManage.search.userName')"
  31 + clearable />
  32 + </el-col>
  33 + <el-col :span="6">
  34 + <el-input v-model="searchForm.tel" :placeholder="$t('couponPropertyUserManage.search.tel')" clearable />
  35 + </el-col>
  36 + <el-col :span="6">
  37 + <el-select v-model="searchForm.toType" :placeholder="$t('couponPropertyUserManage.search.toType')"
  38 + style="width:100%">
  39 + <el-option :label="$t('couponPropertyUserManage.search.selectToType')" value="" />
  40 + <el-option :label="$t('couponPropertyUserManage.search.shopping')" value="1001" />
  41 + <el-option :label="$t('couponPropertyUserManage.search.payment')" value="2002" />
  42 + <el-option :label="$t('couponPropertyUserManage.search.repair')" value="3003" />
  43 + <el-option :label="$t('couponPropertyUserManage.search.parking')" value="4004" />
  44 + </el-select>
  45 + </el-col>
  46 + </el-row>
  47 +
  48 + <el-row :gutter="20" style="margin-top: 15px;">
  49 + <el-col :span="6">
  50 + <el-select v-model="searchForm.state" :placeholder="$t('couponPropertyUserManage.search.state')"
  51 + style="width:100%">
  52 + <el-option :label="$t('couponPropertyUserManage.search.selectState')" value="" />
  53 + <el-option :label="$t('couponPropertyUserManage.search.unused')" value="1001" />
  54 + <el-option :label="$t('couponPropertyUserManage.search.used')" value="2002" />
  55 + </el-select>
  56 + </el-col>
  57 + </el-row>
  58 + </el-card>
  59 +
  60 + <!-- 列表 -->
  61 + <el-card class="list-wrapper">
  62 + <div slot="header" class="flex justify-between">
  63 + <span>{{ $t('couponPropertyUserManage.list.title') }}</span>
  64 + </div>
  65 +
  66 + <el-table v-loading="loading" :data="tableData" border style="width: 100%">
  67 + <el-table-column prop="couponId" :label="$t('couponPropertyUserManage.table.couponId')" align="center" />
  68 + <el-table-column prop="couponName" :label="$t('couponPropertyUserManage.table.couponName')" align="center" />
  69 + <el-table-column prop="value" :label="$t('couponPropertyUserManage.table.value')" align="center" />
  70 + <el-table-column prop="validityDay" :label="$t('couponPropertyUserManage.table.validityDay')" align="center" />
  71 + <el-table-column prop="userName" :label="$t('couponPropertyUserManage.table.userName')" align="center" />
  72 + <el-table-column prop="tel" :label="$t('couponPropertyUserManage.table.tel')" align="center" />
  73 + <el-table-column prop="toTypeName" :label="$t('couponPropertyUserManage.table.toType')" align="center" />
  74 + <el-table-column prop="stock" :label="$t('couponPropertyUserManage.table.quantity')" align="center">
  75 + <template slot-scope="scope">
  76 + {{ scope.row.stock }}{{ $t('couponPropertyUserManage.table.sheet') }}
  77 + </template>
  78 + </el-table-column>
  79 + <el-table-column prop="state" :label="$t('couponPropertyUserManage.table.state')" align="center">
  80 + <template slot-scope="scope">
  81 + {{ scope.row.state === '1001' ? $t('couponPropertyUserManage.table.unused') :
  82 + $t('couponPropertyUserManage.table.used') }}
  83 + </template>
  84 + </el-table-column>
  85 + <el-table-column prop="startTime" :label="$t('couponPropertyUserManage.table.startTime')" align="center" />
  86 + </el-table>
  87 +
  88 + <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
  89 + :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
  90 + @current-change="handleCurrentChange" />
  91 + </el-card>
  92 + </div>
  93 +</template>
  94 +
  95 +<script>
  96 +import { listCouponPropertyUser } from '@/api/scm/couponPropertyUserManageApi'
  97 +import { getCommunityId } from '@/api/community/communityApi'
  98 +
  99 +export default {
  100 + name: 'CouponPropertyUserManageList',
  101 + data() {
  102 + return {
  103 + loading: false,
  104 + searchForm: {
  105 + couponId: '',
  106 + couponName: '',
  107 + validityDay: '',
  108 + userName: '',
  109 + tel: '',
  110 + toType: '',
  111 + state: '',
  112 + communityId: ''
  113 + },
  114 + tableData: [],
  115 + page: {
  116 + current: 1,
  117 + size: 10,
  118 + total: 0
  119 + }
  120 + }
  121 + },
  122 + created() {
  123 + this.searchForm.communityId = getCommunityId()
  124 + this.getList()
  125 + },
  126 + methods: {
  127 + async getList() {
  128 + try {
  129 + this.loading = true
  130 + const params = {
  131 + page: this.page.current,
  132 + row: this.page.size,
  133 + ...this.searchForm
  134 + }
  135 + const { data, total, records } = await listCouponPropertyUser(params)
  136 + this.tableData = data
  137 + this.page.total = records || total
  138 + } catch (error) {
  139 + this.$message.error(this.$t('couponPropertyUserManage.fetchError'))
  140 + } finally {
  141 + this.loading = false
  142 + }
  143 + },
  144 + handleSearch() {
  145 + this.page.current = 1
  146 + this.getList()
  147 + },
  148 + handleSizeChange(val) {
  149 + this.page.size = val
  150 + this.getList()
  151 + },
  152 + handleCurrentChange(val) {
  153 + this.page.current = val
  154 + this.getList()
  155 + }
  156 + }
  157 +}
  158 +</script>
  159 +
  160 +<style lang="scss" scoped>
  161 +.coupon-property-user-manage-container {
  162 + padding: 20px;
  163 +
  164 + .search-wrapper {
  165 + margin-bottom: 20px;
  166 +
  167 + .el-row {
  168 + margin-bottom: 15px;
  169 + }
  170 + }
  171 +
  172 + .list-wrapper {
  173 + .el-pagination {
  174 + margin-top: 20px;
  175 + text-align: right;
  176 + }
  177 + }
  178 +}
  179 +</style>
0 180 \ No newline at end of file
... ...
src/views/scm/couponRuleList.vue
... ... @@ -6,26 +6,23 @@
6 6 </el-col>
7 7 <el-col :span="20" class="right-panel">
8 8 <el-card class="box-card">
9   - <div slot="header" class="clearfix">
  9 + <div slot="header" class="text-left">
10 10 <h5>{{ currentCouponRule.ruleName }}</h5>
11 11 <div class="role-context">{{ currentCouponRule.remark }}</div>
12 12 </div>
13   - <el-divider></el-divider>
14   - <el-tabs v-model="activeTab" @tab-click="handleTabClick">
  13 + <el-tabs v-model="activeTab" @tab-click="handleTabClick(activeTab)">
15 14 <el-tab-pane :label="$t('couponRule.coupon')" name="couponRuleCpps">
16   - <coupon-rule-cpps v-if="activeTab === 'couponRuleCpps'" :rule-id="currentCouponRule.ruleId" />
  15 + <coupon-rule-cpps ref="couponRuleCpps" v-if="activeTab === 'couponRuleCpps'" />
17 16 </el-tab-pane>
18 17 <el-tab-pane :label="$t('couponRule.fee')" name="couponRuleFee">
19   - <coupon-rule-fees v-if="activeTab === 'couponRuleFee'" :rule-id="currentCouponRule.ruleId" />
  18 + <coupon-rule-fees ref="couponRuleFee" v-if="activeTab === 'couponRuleFee'" />
20 19 </el-tab-pane>
21 20 </el-tabs>
22 21 </el-card>
23 22 </el-col>
24 23 </el-row>
25 24  
26   - <add-coupon-rule ref="addCouponRule" @success="handleSuccess" />
27   - <edit-coupon-rule ref="editCouponRule" @success="handleSuccess" />
28   - <delete-coupon-rule ref="deleteCouponRule" @success="handleSuccess" />
  25 +
29 26 </div>
30 27 </template>
31 28  
... ... @@ -33,9 +30,7 @@
33 30 import CouponRuleDiv from '@/components/scm/CouponRuleDiv'
34 31 import CouponRuleCpps from '@/components/scm/CouponRuleCpps'
35 32 import CouponRuleFees from '@/components/scm/CouponRuleFees'
36   -import AddCouponRule from '@/components/scm/AddCouponRule'
37   -import EditCouponRule from '@/components/scm/EditCouponRule'
38   -import DeleteCouponRule from '@/components/scm/DeleteCouponRule'
  33 +
39 34  
40 35 export default {
41 36 name: 'CouponRuleList',
... ... @@ -43,9 +38,7 @@ export default {
43 38 CouponRuleDiv,
44 39 CouponRuleCpps,
45 40 CouponRuleFees,
46   - AddCouponRule,
47   - EditCouponRule,
48   - DeleteCouponRule
  41 +
49 42 },
50 43 data() {
51 44 return {
... ... @@ -60,30 +53,18 @@ export default {
60 53 methods: {
61 54 handleSwitchCouponRule(rule) {
62 55 this.currentCouponRule = rule
  56 + this.handleTabClick(this.activeTab)
63 57 },
  58 +
64 59 handleTabClick(tab) {
65   - this.activeTab = tab.name
66   - },
67   - handleSuccess() {
68   - this.$refs.couponRuleDiv.refreshList()
  60 + this.activeTab = tab
  61 + let _that = this;
  62 + setTimeout(function(){
  63 + _that.$refs[tab].open(_that.currentCouponRule.ruleId)
  64 + },500)
69 65 },
70   - openAddModal() {
71   - this.$refs.addCouponRule.open()
72   - },
73   - openEditModal() {
74   - if (!this.currentCouponRule.ruleId) {
75   - this.$message.warning(this.$t('couponRule.selectRuleFirst'))
76   - return
77   - }
78   - this.$refs.editCouponRule.open(this.currentCouponRule)
79   - },
80   - openDeleteModal() {
81   - if (!this.currentCouponRule.ruleId) {
82   - this.$message.warning(this.$t('couponRule.selectRuleFirst'))
83   - return
84   - }
85   - this.$refs.deleteCouponRule.open(this.currentCouponRule)
86   - }
  66 +
  67 +
87 68 }
88 69 }
89 70 </script>
... ...
src/views/scm/integralConfigManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + integralConfigManage: {
  4 + search: {
  5 + title: 'Search Conditions',
  6 + configNamePlaceholder: 'Please enter standard name'
  7 + },
  8 + list: {
  9 + title: 'Points Standard'
  10 + },
  11 + table: {
  12 + configName: 'Standard Name',
  13 + computingFormula: 'Calculation Formula',
  14 + squarePrice: 'Amount/Month',
  15 + additionalAmount: 'Points',
  16 + scale: 'Rounding'
  17 + },
  18 + form: {
  19 + configName: 'Standard Name',
  20 + configNamePlaceholder: 'Required, please enter standard name',
  21 + computingFormula: 'Calculation Formula',
  22 + computingFormulaPlaceholder: 'Required, please select calculation formula',
  23 + amount: 'Amount',
  24 + amountPlaceholder: 'Required, please enter amount',
  25 + month: 'Month',
  26 + monthPlaceholder: 'Required, please enter month',
  27 + points: 'Points',
  28 + pointsPlaceholder: 'Required, please enter points',
  29 + scale: 'Rounding',
  30 + scalePlaceholder: 'Required, please select rounding'
  31 + },
  32 + formula: {
  33 + fullAmount: 'Full amount give points',
  34 + fullMonth: 'Full month give points'
  35 + },
  36 + scale: {
  37 + roundUp: 'Round up',
  38 + roundDown: 'Round down'
  39 + },
  40 + validate: {
  41 + configIdRequired: 'Points standard cannot be empty',
  42 + configNameRequired: 'Standard name cannot be empty',
  43 + configNameMaxLength: 'Standard name cannot exceed 100 characters',
  44 + computingFormulaRequired: 'Calculation formula cannot be empty',
  45 + squarePriceRequired: 'Amount/month cannot be empty',
  46 + squarePriceMaxLength: 'Amount/month cannot exceed 12 characters',
  47 + additionalAmountRequired: 'Points cannot be empty',
  48 + additionalAmountMaxLength: 'Points cannot exceed 12 characters',
  49 + scaleRequired: 'Rounding cannot be empty'
  50 + },
  51 + message: {
  52 + addSuccess: 'Add points standard successfully',
  53 + addFailed: 'Add points standard failed',
  54 + editSuccess: 'Edit points standard successfully',
  55 + editFailed: 'Edit points standard failed',
  56 + deleteSuccess: 'Delete points standard successfully',
  57 + deleteFailed: 'Delete points standard failed',
  58 + fetchError: 'Failed to get points standard data'
  59 + },
  60 + add: {
  61 + title: 'Add Points Standard'
  62 + },
  63 + edit: {
  64 + title: 'Edit Points Standard'
  65 + },
  66 + delete: {
  67 + title: 'Delete Points Standard',
  68 + confirmMessage: 'Are you sure to delete this points standard?'
  69 + }
  70 + }
  71 + },
  72 + zh: {
  73 + integralConfigManage: {
  74 + search: {
  75 + title: '查询条件',
  76 + configNamePlaceholder: '请输入标准名称'
  77 + },
  78 + list: {
  79 + title: '积分标准'
  80 + },
  81 + table: {
  82 + configName: '标准名称',
  83 + computingFormula: '计算公式',
  84 + squarePrice: '金额/月',
  85 + additionalAmount: '赠送积分',
  86 + scale: '进位'
  87 + },
  88 + form: {
  89 + configName: '标准名称',
  90 + configNamePlaceholder: '必填,请填写标准名称',
  91 + computingFormula: '计算公式',
  92 + computingFormulaPlaceholder: '必填,请选择计算公式',
  93 + amount: '金额',
  94 + amountPlaceholder: '必填,请填写金额',
  95 + month: '月份',
  96 + monthPlaceholder: '必填,请填写月份',
  97 + points: '积分',
  98 + pointsPlaceholder: '必填,请填写积分',
  99 + scale: '进位',
  100 + scalePlaceholder: '必填,请选择进位'
  101 + },
  102 + formula: {
  103 + fullAmount: '满(金额)送积分',
  104 + fullMonth: '满(月)送积分'
  105 + },
  106 + scale: {
  107 + roundUp: '向上取整',
  108 + roundDown: '向下取整'
  109 + },
  110 + validate: {
  111 + configIdRequired: '积分标准不能为空',
  112 + configNameRequired: '标准名称不能为空',
  113 + configNameMaxLength: '标准名称不能超过100个字符',
  114 + computingFormulaRequired: '计算公式不能为空',
  115 + squarePriceRequired: '金额/月不能为空',
  116 + squarePriceMaxLength: '金额/月不能超过12个字符',
  117 + additionalAmountRequired: '积分不能为空',
  118 + additionalAmountMaxLength: '积分不能超过12个字符',
  119 + scaleRequired: '进位不能为空'
  120 + },
  121 + message: {
  122 + addSuccess: '添加积分标准成功',
  123 + addFailed: '添加积分标准失败',
  124 + editSuccess: '修改积分标准成功',
  125 + editFailed: '修改积分标准失败',
  126 + deleteSuccess: '删除积分标准成功',
  127 + deleteFailed: '删除积分标准失败',
  128 + fetchError: '获取积分标准数据失败'
  129 + },
  130 + add: {
  131 + title: '添加积分标准'
  132 + },
  133 + edit: {
  134 + title: '修改积分标准'
  135 + },
  136 + delete: {
  137 + title: '删除积分标准',
  138 + confirmMessage: '确定删除该积分标准吗?'
  139 + }
  140 + }
  141 + }
  142 +}
0 143 \ No newline at end of file
... ...
src/views/scm/integralConfigManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="integral-config-manage-container">
  3 + <!-- 查询条件 -->
  4 + <el-card class="search-wrapper">
  5 + <div slot="header" class="flex justify-between">
  6 + <span>{{ $t('integralConfigManage.search.title') }}</span>
  7 + </div>
  8 + <el-row :gutter="20">
  9 + <el-col :span="6">
  10 + <el-input v-model="searchForm.configName"
  11 + :placeholder="$t('integralConfigManage.search.configNamePlaceholder')" clearable />
  12 + </el-col>
  13 + <el-col :span="2">
  14 + <el-button type="primary" @click="handleSearch">
  15 + {{ $t('common.search') }}
  16 + </el-button>
  17 + </el-col>
  18 + </el-row>
  19 + </el-card>
  20 +
  21 + <!-- 积分标准列表 -->
  22 + <el-card class="list-wrapper">
  23 + <div slot="header" class="flex justify-between">
  24 + <span>{{ $t('integralConfigManage.list.title') }}</span>
  25 + <el-button type="primary" size="small" style="float: right" @click="handleAdd">
  26 + {{ $t('common.add') }}
  27 + </el-button>
  28 + </div>
  29 +
  30 + <el-table v-loading="loading" :data="tableData" border style="width: 100%">
  31 + <el-table-column prop="configName" :label="$t('integralConfigManage.table.configName')" align="center" />
  32 + <el-table-column prop="computingFormulaName" :label="$t('integralConfigManage.table.computingFormula')"
  33 + align="center" />
  34 + <el-table-column prop="squarePrice" :label="$t('integralConfigManage.table.squarePrice')" align="center" />
  35 + <el-table-column prop="additionalAmount" :label="$t('integralConfigManage.table.additionalAmount')"
  36 + align="center" />
  37 + <el-table-column prop="scaleName" :label="$t('integralConfigManage.table.scale')" align="center" />
  38 + <el-table-column :label="$t('common.operation')" align="center" width="200">
  39 + <template slot-scope="scope">
  40 + <el-button size="mini" type="primary" @click="handleEdit(scope.row)">
  41 + {{ $t('common.edit') }}
  42 + </el-button>
  43 + <el-button size="mini" type="danger" @click="handleDelete(scope.row)">
  44 + {{ $t('common.delete') }}
  45 + </el-button>
  46 + </template>
  47 + </el-table-column>
  48 + </el-table>
  49 +
  50 + <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
  51 + :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
  52 + @current-change="handleCurrentChange" />
  53 + </el-card>
  54 +
  55 + <!-- 添加/编辑/删除组件 -->
  56 + <add-integral-config ref="addDialog" @success="handleSuccess" />
  57 + <edit-integral-config ref="editDialog" @success="handleSuccess" />
  58 + <delete-integral-config ref="deleteDialog" @success="handleSuccess" />
  59 + </div>
  60 +</template>
  61 +
  62 +<script>
  63 +import { listIntegralConfig } from '@/api/scm/integralConfigManageApi'
  64 +import AddIntegralConfig from '@/components/scm/addIntegralConfig'
  65 +import EditIntegralConfig from '@/components/scm/editIntegralConfig'
  66 +import DeleteIntegralConfig from '@/components/scm/deleteIntegralConfig'
  67 +import { getCommunityId } from '@/api/community/communityApi'
  68 +
  69 +export default {
  70 + name: 'IntegralConfigManageList',
  71 + components: {
  72 + AddIntegralConfig,
  73 + EditIntegralConfig,
  74 + DeleteIntegralConfig
  75 + },
  76 + data() {
  77 + return {
  78 + loading: false,
  79 + searchForm: {
  80 + configName: '',
  81 + communityId: ''
  82 + },
  83 + tableData: [],
  84 + page: {
  85 + current: 1,
  86 + size: 10,
  87 + total: 0
  88 + }
  89 + }
  90 + },
  91 + created() {
  92 + this.searchForm.communityId = getCommunityId()
  93 + this.getList()
  94 + },
  95 + methods: {
  96 + async getList() {
  97 + try {
  98 + this.loading = true
  99 + const params = {
  100 + page: this.page.current,
  101 + row: this.page.size,
  102 + ...this.searchForm
  103 + }
  104 + const { data, total } = await listIntegralConfig(params)
  105 + this.tableData = data
  106 + this.page.total = total
  107 + } catch (error) {
  108 + this.$message.error(this.$t('integralConfigManage.fetchError'))
  109 + } finally {
  110 + this.loading = false
  111 + }
  112 + },
  113 + handleSearch() {
  114 + this.page.current = 1
  115 + this.getList()
  116 + },
  117 + handleAdd() {
  118 + this.$refs.addDialog.open()
  119 + },
  120 + handleEdit(row) {
  121 + this.$refs.editDialog.open(row)
  122 + },
  123 + handleDelete(row) {
  124 + this.$refs.deleteDialog.open(row)
  125 + },
  126 + handleSuccess() {
  127 + this.getList()
  128 + },
  129 + handleSizeChange(val) {
  130 + this.page.size = val
  131 + this.getList()
  132 + },
  133 + handleCurrentChange(val) {
  134 + this.page.current = val
  135 + this.getList()
  136 + }
  137 + }
  138 +}
  139 +</script>
  140 +
  141 +<style lang="scss" scoped>
  142 +.integral-config-manage-container {
  143 + padding: 20px;
  144 +
  145 + .search-wrapper {
  146 + margin-bottom: 20px;
  147 + }
  148 +
  149 + .el-pagination {
  150 + margin-top: 20px;
  151 + text-align: right;
  152 + }
  153 +}
  154 +</style>
0 155 \ No newline at end of file
... ...
src/views/scm/integralGiftDetailManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + integralGiftDetailManage: {
  4 + search: {
  5 + title: 'Search Conditions',
  6 + detailId: 'Record ID',
  7 + userNameLike: 'User Name',
  8 + tel: 'Phone Number'
  9 + },
  10 + list: {
  11 + title: 'Gift Records'
  12 + },
  13 + table: {
  14 + detailId: 'Record ID',
  15 + acctName: 'Account Name',
  16 + configName: 'Standard Name',
  17 + ruleName: 'Rule Name',
  18 + quantity: 'Points Quantity',
  19 + userName: 'User Name',
  20 + tel: 'Phone Number',
  21 + createTime: 'Gift Time'
  22 + },
  23 + fetchError: 'Failed to fetch gift records'
  24 + }
  25 + },
  26 + zh: {
  27 + integralGiftDetailManage: {
  28 + search: {
  29 + title: '查询条件',
  30 + detailId: '记录编号',
  31 + userNameLike: '用户名称',
  32 + tel: '手机号'
  33 + },
  34 + list: {
  35 + title: '赠送记录'
  36 + },
  37 + table: {
  38 + detailId: '记录编号',
  39 + acctName: '账户名称',
  40 + configName: '标准名称',
  41 + ruleName: '规则名称',
  42 + quantity: '积分数量',
  43 + userName: '用户名称',
  44 + tel: '手机号',
  45 + createTime: '赠送时间'
  46 + },
  47 + fetchError: '获取赠送记录失败'
  48 + }
  49 + }
  50 +}
0 51 \ No newline at end of file
... ...
src/views/scm/integralGiftDetailManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="integral-gift-detail-container">
  3 + <!-- 查询条件 -->
  4 + <el-card class="search-wrapper">
  5 + <div slot="header" class="text-left">
  6 + <span>{{ $t('integralGiftDetailManage.search.title') }}</span>
  7 + </div>
  8 + <el-row :gutter="20">
  9 + <el-col :span="6">
  10 + <el-input v-model="searchForm.detailId" :placeholder="$t('integralGiftDetailManage.search.detailId')"
  11 + clearable @keyup.enter.native="handleSearch" />
  12 + </el-col>
  13 + <el-col :span="6">
  14 + <el-input v-model="searchForm.userNameLike" :placeholder="$t('integralGiftDetailManage.search.userNameLike')"
  15 + clearable @keyup.enter.native="handleSearch" />
  16 + </el-col>
  17 + <el-col :span="6">
  18 + <el-input v-model="searchForm.tel" :placeholder="$t('integralGiftDetailManage.search.tel')" clearable
  19 + @keyup.enter.native="handleSearch" />
  20 + </el-col>
  21 + <el-col :span="6">
  22 + <el-button type="primary" @click="handleSearch">
  23 + {{ $t('common.search') }}
  24 + </el-button>
  25 + </el-col>
  26 + </el-row>
  27 + </el-card>
  28 +
  29 + <!-- 数据列表 -->
  30 + <el-card class="list-wrapper">
  31 + <div slot="header" class="text-left">
  32 + <span>{{ $t('integralGiftDetailManage.list.title') }}</span>
  33 + </div>
  34 +
  35 + <el-table v-loading="loading" :data="tableData" border style="width: 100%">
  36 + <el-table-column prop="detailId" :label="$t('integralGiftDetailManage.table.detailId')" align="center" />
  37 + <el-table-column prop="acctName" :label="$t('integralGiftDetailManage.table.acctName')" align="center" />
  38 + <el-table-column prop="configName" :label="$t('integralGiftDetailManage.table.configName')" align="center" />
  39 + <el-table-column prop="ruleName" :label="$t('integralGiftDetailManage.table.ruleName')" align="center" />
  40 + <el-table-column prop="quantity" :label="$t('integralGiftDetailManage.table.quantity')" align="center" />
  41 + <el-table-column prop="userName" :label="$t('integralGiftDetailManage.table.userName')" align="center" />
  42 + <el-table-column prop="tel" :label="$t('integralGiftDetailManage.table.tel')" align="center" />
  43 + <el-table-column prop="createTime" :label="$t('integralGiftDetailManage.table.createTime')" align="center" />
  44 + <el-table-column :label="$t('common.operation')" align="center" width="150">
  45 + <template slot-scope="scope">
  46 + <el-button size="mini" type="text" @click="handleDetail(scope.row)">
  47 + {{ $t('common.detail') }}
  48 + </el-button>
  49 + </template>
  50 + </el-table-column>
  51 + </el-table>
  52 +
  53 + <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
  54 + :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
  55 + @current-change="handleCurrentChange" />
  56 + </el-card>
  57 + </div>
  58 +</template>
  59 +
  60 +<script>
  61 +import { listIntegralGiftDetail } from '@/api/scm/integralGiftDetailManageApi'
  62 +import { getCommunityId } from '@/api/community/communityApi'
  63 +
  64 +export default {
  65 + name: 'IntegralGiftDetailManageList',
  66 + data() {
  67 + return {
  68 + loading: false,
  69 + searchForm: {
  70 + detailId: '',
  71 + userNameLike: '',
  72 + tel: '',
  73 + communityId: ''
  74 + },
  75 + tableData: [],
  76 + page: {
  77 + current: 1,
  78 + size: 10,
  79 + total: 0
  80 + }
  81 + }
  82 + },
  83 + created() {
  84 + this.searchForm.communityId = getCommunityId()
  85 + this.getList()
  86 + },
  87 + methods: {
  88 + async getList() {
  89 + try {
  90 + this.loading = true
  91 + const params = {
  92 + page: this.page.current,
  93 + row: this.page.size,
  94 + ...this.searchForm
  95 + }
  96 + const { data, total } = await listIntegralGiftDetail(params)
  97 + this.tableData = data
  98 + this.page.total = total
  99 + } catch (error) {
  100 + this.$message.error(this.$t('integralGiftDetailManage.fetchError'))
  101 + } finally {
  102 + this.loading = false
  103 + }
  104 + },
  105 + handleSearch() {
  106 + this.page.current = 1
  107 + this.getList()
  108 + },
  109 + handleSizeChange(val) {
  110 + this.page.size = val
  111 + this.getList()
  112 + },
  113 + handleCurrentChange(val) {
  114 + this.page.current = val
  115 + this.getList()
  116 + },
  117 + handleDetail(row) {
  118 + // 查看详情逻辑
  119 + console.log(row)
  120 + }
  121 + }
  122 +}
  123 +</script>
  124 +
  125 +<style lang="scss" scoped>
  126 +.integral-gift-detail-container {
  127 + padding: 20px;
  128 +
  129 + .search-wrapper {
  130 + margin-bottom: 20px;
  131 +
  132 + .el-input {
  133 + width: 100%;
  134 + }
  135 + }
  136 +
  137 + .list-wrapper {
  138 + .el-pagination {
  139 + margin-top: 20px;
  140 + text-align: right;
  141 + }
  142 + }
  143 +}
  144 +</style>
0 145 \ No newline at end of file
... ...
src/views/scm/integralRuleLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + integralRule: {
  4 + addTitle: 'Add Integral Rule',
  5 + editTitle: 'Edit Integral Rule',
  6 + deleteTitle: 'Delete Integral Rule',
  7 + deleteConfirm: 'Are you sure to delete this integral rule?',
  8 + ruleName: 'Rule Name',
  9 + ruleNamePlaceholder: 'Please enter rule name',
  10 + ruleNameRequired: 'Rule name is required',
  11 + ruleNameMaxLength: 'Rule name cannot exceed 64 characters',
  12 + remark: 'Remark',
  13 + remarkPlaceholder: 'Please enter remark',
  14 + remarkRequired: 'Remark is required',
  15 + remarkMaxLength: 'Remark cannot exceed 512 characters',
  16 + ruleIdRequired: 'Rule ID is required',
  17 + selectRule: 'Please select a rule first',
  18 +
  19 + // Config related
  20 + addConfigTitle: 'Add Integral Config',
  21 + configId: 'Config ID',
  22 + configName: 'Config Name',
  23 + configPlaceholder: 'Please select config',
  24 + configRequired: 'Config is required',
  25 + deleteConfigConfirm: 'Are you sure to delete this config?',
  26 + computingFormula: 'Computing Formula',
  27 + squarePrice: 'Square Price',
  28 + additionalAmount: 'Additional Amount',
  29 + scale: 'Scale',
  30 +
  31 + // Fee related
  32 + addFeeTitle: 'Add Payment Time',
  33 + editFeeTitle: 'Edit Payment Time',
  34 + feeId: 'Fee ID',
  35 + payTimeRange: 'Payment Time Range',
  36 + payStartTime: 'Start Time',
  37 + payStartTimePlaceholder: 'Select start time',
  38 + payStartTimeRequired: 'Start time is required',
  39 + payEndTime: 'End Time',
  40 + payEndTimePlaceholder: 'Select end time',
  41 + payEndTimeRequired: 'End time is required',
  42 + payEndTimeAfterStart: 'End time must be after start time',
  43 + deleteFeeConfirm: 'Are you sure to delete this payment time?',
  44 + feeIdRequired: 'Fee ID is required',
  45 +
  46 + // Tab names
  47 + integralRuleConfig: 'Integral Standard',
  48 + integralRuleFee: 'Payment Time',
  49 +
  50 + // Messages
  51 + fetchError: 'Failed to fetch data',
  52 + selectRuleFirst: 'Please select a rule first'
  53 + }
  54 + },
  55 + zh: {
  56 + integralRule: {
  57 + addTitle: '添加积分规则',
  58 + editTitle: '编辑积分规则',
  59 + deleteTitle: '删除积分规则',
  60 + deleteConfirm: '确定删除该积分规则吗?',
  61 + ruleName: '规则名称',
  62 + ruleNamePlaceholder: '请输入规则名称',
  63 + ruleNameRequired: '规则名称不能为空',
  64 + ruleNameMaxLength: '规则名称不能超过64个字符',
  65 + remark: '备注',
  66 + remarkPlaceholder: '请输入备注',
  67 + remarkRequired: '备注不能为空',
  68 + remarkMaxLength: '备注不能超过512个字符',
  69 + ruleIdRequired: '规则ID不能为空',
  70 + selectRule: '请先选择规则',
  71 +
  72 + // Config related
  73 + addConfigTitle: '添加积分标准',
  74 + configId: '配置ID',
  75 + configName: '配置名称',
  76 + configPlaceholder: '请选择配置',
  77 + configRequired: '配置不能为空',
  78 + deleteConfigConfirm: '确定删除该配置吗?',
  79 + computingFormula: '计算公式',
  80 + squarePrice: '单价',
  81 + additionalAmount: '固定积分',
  82 + scale: '进位',
  83 +
  84 + // Fee related
  85 + addFeeTitle: '添加缴费时间',
  86 + editFeeTitle: '编辑缴费时间',
  87 + feeId: '费用ID',
  88 + payTimeRange: '缴费时间范围',
  89 + payStartTime: '开始时间',
  90 + payStartTimePlaceholder: '选择开始时间',
  91 + payStartTimeRequired: '开始时间不能为空',
  92 + payEndTime: '结束时间',
  93 + payEndTimePlaceholder: '选择结束时间',
  94 + payEndTimeRequired: '结束时间不能为空',
  95 + payEndTimeAfterStart: '结束时间必须晚于开始时间',
  96 + deleteFeeConfirm: '确定删除该缴费时间吗?',
  97 + feeIdRequired: '费用ID不能为空',
  98 +
  99 + // Tab names
  100 + integralRuleConfig: '积分标准',
  101 + integralRuleFee: '缴费时间',
  102 +
  103 + // Messages
  104 + fetchError: '获取数据失败',
  105 + selectRuleFirst: '请先选择规则'
  106 + }
  107 + }
  108 +}
0 109 \ No newline at end of file
... ...
src/views/scm/integralRuleList.vue 0 → 100644
  1 +<template>
  2 + <div class="integral-rule-container">
  3 + <el-row :gutter="20">
  4 + <el-col :span="4" class="left-panel">
  5 + <integral-rule-div ref="integralRuleDiv" @switch="handleSwitchRule" />
  6 + </el-col>
  7 + <el-col :span="20" class="right-panel">
  8 + <el-card class="box-card">
  9 + <div slot="header" class="text-left">
  10 + <h5>{{ integralRuleInfo.curIntegralRule.ruleName }}</h5>
  11 + <div class="role-context">{{ integralRuleInfo.curIntegralRule.remark }}</div>
  12 + </div>
  13 + <el-tabs v-model="integralRuleInfo.tabName" @tab-click="handleTabClick(integralRuleInfo.tabName)">
  14 + <el-tab-pane label="积分标准" name="integralRuleConfig">
  15 + <integral-rule-config ref="integralRuleConfig" v-if="integralRuleInfo.tabName === 'integralRuleConfig'"
  16 + />
  17 + </el-tab-pane>
  18 + <el-tab-pane label="缴费时间" name="integralRuleFee">
  19 + <integral-rule-fees ref="integralRuleFee" v-if="integralRuleInfo.tabName === 'integralRuleFee'"
  20 + />
  21 + </el-tab-pane>
  22 + </el-tabs>
  23 + </el-card>
  24 + </el-col>
  25 + </el-row>
  26 +
  27 +
  28 + </div>
  29 +</template>
  30 +
  31 +<script>
  32 +import IntegralRuleDiv from '@/components/scm/integralRuleDiv'
  33 +import IntegralRuleConfig from '@/components/scm/integralRuleConfig'
  34 +import IntegralRuleFees from '@/components/scm/integralRuleFees'
  35 +
  36 +
  37 +export default {
  38 + name: 'IntegralRuleList',
  39 + components: {
  40 + IntegralRuleDiv,
  41 + IntegralRuleConfig,
  42 + IntegralRuleFees,
  43 +
  44 + },
  45 + data() {
  46 + return {
  47 + integralRuleInfo: {
  48 + curIntegralRule: {},
  49 + tabName: 'integralRuleConfig'
  50 + }
  51 + }
  52 + },
  53 + methods: {
  54 + handleSwitchRule(rule) {
  55 + this.integralRuleInfo.curIntegralRule = rule
  56 + this.handleTabClick(this.integralRuleInfo.tabName)
  57 + },
  58 + handleTabClick(tab) {
  59 + this.integralRuleInfo.tabName = tab
  60 + setTimeout(() => {
  61 + this.$refs[tab].open(this.integralRuleInfo.curIntegralRule)
  62 + }, 500);
  63 + },
  64 +
  65 +
  66 + }
  67 +}
  68 +</script>
  69 +
  70 +<style lang="scss" scoped>
  71 +.integral-rule-container {
  72 + padding: 20px;
  73 + height: 100%;
  74 +
  75 + .left-panel {
  76 + padding-right: 0;
  77 + }
  78 +
  79 + .right-panel {
  80 + padding-left: 20px;
  81 + }
  82 +
  83 + .box-card {
  84 + height: 100%;
  85 +
  86 + .clearfix {
  87 +
  88 + &:before,
  89 + &:after {
  90 + display: table;
  91 + content: "";
  92 + }
  93 +
  94 + &:after {
  95 + clear: both;
  96 + }
  97 + }
  98 +
  99 + .role-title {
  100 + margin: 0;
  101 + font-size: 16px;
  102 + font-weight: bold;
  103 + }
  104 +
  105 + .role-context {
  106 + margin-top: 10px;
  107 + color: #666;
  108 + }
  109 + }
  110 +}
  111 +</style>
0 112 \ No newline at end of file
... ...