Showing
6 changed files
with
378 additions
and
61 deletions
| ... | @@ -14,7 +14,6 @@ import java.time.LocalDate; | ... | @@ -14,7 +14,6 @@ import java.time.LocalDate; |
| 14 | public class DealerAddReq { | 14 | public class DealerAddReq { |
| 15 | 15 | ||
| 16 | @NotBlank(message = "经销商编码不能为空") | 16 | @NotBlank(message = "经销商编码不能为空") |
| 17 | - @Pattern(regexp = "^[A-Z0-9]{6,20}$", message = "经销商编码格式不正确,应为6-20位大写字母和数字") | ||
| 18 | @Schema(description = "经销商编码", required = true) | 17 | @Schema(description = "经销商编码", required = true) |
| 19 | private String dealerCode; | 18 | private String dealerCode; |
| 20 | 19 | ... | ... |
| ... | @@ -18,7 +18,6 @@ public class DealerUpdateReq { | ... | @@ -18,7 +18,6 @@ public class DealerUpdateReq { |
| 18 | private Long dealerId; | 18 | private Long dealerId; |
| 19 | 19 | ||
| 20 | @NotBlank(message = "经销商编码不能为空") | 20 | @NotBlank(message = "经销商编码不能为空") |
| 21 | - @Pattern(regexp = "^[A-Z0-9]{6,20}$", message = "经销商编码格式不正确,应为6-20位大写字母和数字") | ||
| 22 | @Schema(description = "经销商编码", required = true) | 21 | @Schema(description = "经销商编码", required = true) |
| 23 | private String dealerCode; | 22 | private String dealerCode; |
| 24 | 23 | ... | ... |
| ... | @@ -42,7 +42,7 @@ | ... | @@ -42,7 +42,7 @@ |
| 42 | <if test="params.rebateEndDate != null and params.rebateEndDate != ''"> | 42 | <if test="params.rebateEndDate != null and params.rebateEndDate != ''"> |
| 43 | AND rebate_date <= #{params.rebateEndDate} | 43 | AND rebate_date <= #{params.rebateEndDate} |
| 44 | </if> | 44 | </if> |
| 45 | - ORDER BY create_time DESC | 45 | + ORDER BY rebate_date DESC |
| 46 | </select> | 46 | </select> |
| 47 | 47 | ||
| 48 | <!-- 根据经销商编码统计返利总金额 --> | 48 | <!-- 根据经销商编码统计返利总金额 --> | ... | ... |
| ... | @@ -127,49 +127,49 @@ export interface ApiResponse<T = any> { | ... | @@ -127,49 +127,49 @@ export interface ApiResponse<T = any> { |
| 127 | // 经销商管理API | 127 | // 经销商管理API |
| 128 | export const dealerApi = { | 128 | export const dealerApi = { |
| 129 | // 分页查询经销商列表 | 129 | // 分页查询经销商列表 |
| 130 | - getDealerList: (params: DealerQueryReq) => { | 130 | + getDealerList: (params: DealerQueryReq): Promise<ApiResponse<PageData<DealerInfo>>> => { |
| 131 | return api.get<ApiResponse<PageData<DealerInfo>>>('/dealer/list', { params }) | 131 | return api.get<ApiResponse<PageData<DealerInfo>>>('/dealer/list', { params }) |
| 132 | }, | 132 | }, |
| 133 | 133 | ||
| 134 | // 获取经销商详情 | 134 | // 获取经销商详情 |
| 135 | - getDealerDetail: (dealerId: number) => { | 135 | + getDealerDetail: (dealerId: number): Promise<ApiResponse<DealerInfo>> => { |
| 136 | return api.get<ApiResponse<DealerInfo>>(`/dealer/${dealerId}`) | 136 | return api.get<ApiResponse<DealerInfo>>(`/dealer/${dealerId}`) |
| 137 | }, | 137 | }, |
| 138 | 138 | ||
| 139 | // 新增经销商 | 139 | // 新增经销商 |
| 140 | - addDealer: (data: DealerAddReq) => { | 140 | + addDealer: (data: DealerAddReq): Promise<ApiResponse> => { |
| 141 | return api.post<ApiResponse>('/dealer', data) | 141 | return api.post<ApiResponse>('/dealer', data) |
| 142 | }, | 142 | }, |
| 143 | 143 | ||
| 144 | // 修改经销商 | 144 | // 修改经销商 |
| 145 | - updateDealer: (data: DealerUpdateReq) => { | 145 | + updateDealer: (data: DealerUpdateReq): Promise<ApiResponse> => { |
| 146 | return api.post<ApiResponse>('/dealer/update', data) | 146 | return api.post<ApiResponse>('/dealer/update', data) |
| 147 | }, | 147 | }, |
| 148 | 148 | ||
| 149 | // 删除经销商 | 149 | // 删除经销商 |
| 150 | - deleteDealer: (dealerId: number) => { | 150 | + deleteDealer: (dealerId: number): Promise<ApiResponse> => { |
| 151 | return api.delete<ApiResponse>(`/dealer/${dealerId}`) | 151 | return api.delete<ApiResponse>(`/dealer/${dealerId}`) |
| 152 | }, | 152 | }, |
| 153 | 153 | ||
| 154 | // 批量删除经销商 | 154 | // 批量删除经销商 |
| 155 | - batchDeleteDealer: (dealerIds: number[]) => { | 155 | + batchDeleteDealer: (dealerIds: number[]): Promise<ApiResponse> => { |
| 156 | return api.delete<ApiResponse>('/dealer/batch', { data: dealerIds }) | 156 | return api.delete<ApiResponse>('/dealer/batch', { data: dealerIds }) |
| 157 | }, | 157 | }, |
| 158 | 158 | ||
| 159 | // 修改经销商合作状态 | 159 | // 修改经销商合作状态 |
| 160 | - updateCooperateStatus: (dealerId: number, cooperateStatus: number) => { | 160 | + updateCooperateStatus: (dealerId: number, cooperateStatus: number): Promise<ApiResponse> => { |
| 161 | return api.post<ApiResponse>(`/dealer/${dealerId}/cooperateStatus/${cooperateStatus}`) | 161 | return api.post<ApiResponse>(`/dealer/${dealerId}/cooperateStatus/${cooperateStatus}`) |
| 162 | }, | 162 | }, |
| 163 | 163 | ||
| 164 | // 修改经销商资质审核状态 | 164 | // 修改经销商资质审核状态 |
| 165 | - updateAuditStatus: (dealerId: number, qualificationAuditStatus: number, auditOpinion?: string) => { | 165 | + updateAuditStatus: (dealerId: number, qualificationAuditStatus: number, auditOpinion?: string): Promise<ApiResponse> => { |
| 166 | return api.post<ApiResponse>(`/dealer/${dealerId}/auditStatus`, null, { | 166 | return api.post<ApiResponse>(`/dealer/${dealerId}/auditStatus`, null, { |
| 167 | params: { qualificationAuditStatus, auditOpinion } | 167 | params: { qualificationAuditStatus, auditOpinion } |
| 168 | }) | 168 | }) |
| 169 | }, | 169 | }, |
| 170 | 170 | ||
| 171 | // 获取所有经销商(用于下拉选择) | 171 | // 获取所有经销商(用于下拉选择) |
| 172 | - getAllDealers: () => { | 172 | + getAllDealers: (): Promise<ApiResponse<DealerInfo[]>> => { |
| 173 | return api.get<ApiResponse<DealerInfo[]>>('/dealer/all') | 173 | return api.get<ApiResponse<DealerInfo[]>>('/dealer/all') |
| 174 | } | 174 | } |
| 175 | } | 175 | } | ... | ... |
| 1 | import request from '@/utils/request' | 1 | import request from '@/utils/request' |
| 2 | 2 | ||
| 3 | +// API响应接口 | ||
| 4 | +export interface ApiResponse<T = any> { | ||
| 5 | + code: number | ||
| 6 | + message: string | ||
| 7 | + data: T | ||
| 8 | +} | ||
| 9 | + | ||
| 10 | +// 分页数据接口 | ||
| 11 | +export interface PageData<T> { | ||
| 12 | + records: T[] | ||
| 13 | + total: number | ||
| 14 | + pageNum: number | ||
| 15 | + pageSize: number | ||
| 16 | +} | ||
| 17 | + | ||
| 3 | // 返利台账明细类型定义 | 18 | // 返利台账明细类型定义 |
| 4 | export interface Rebate { | 19 | export interface Rebate { |
| 5 | rebateId?: number | 20 | rebateId?: number |
| ... | @@ -57,7 +72,7 @@ export interface RebateUpdateParams extends RebateAddParams { | ... | @@ -57,7 +72,7 @@ export interface RebateUpdateParams extends RebateAddParams { |
| 57 | } | 72 | } |
| 58 | 73 | ||
| 59 | // 分页查询返利列表 | 74 | // 分页查询返利列表 |
| 60 | -export const getRebatePage = (params: RebateSearchParams) => { | 75 | +export const getRebatePage = (params: RebateSearchParams): Promise<ApiResponse<PageData<Rebate>>> => { |
| 61 | return request({ | 76 | return request({ |
| 62 | url: '/api/rebate/page', | 77 | url: '/api/rebate/page', |
| 63 | method: 'post', | 78 | method: 'post', | ... | ... |
| ... | @@ -84,7 +84,6 @@ | ... | @@ -84,7 +84,6 @@ |
| 84 | <th>统一社会信用代码</th> | 84 | <th>统一社会信用代码</th> |
| 85 | <th>经销商等级</th> | 85 | <th>经销商等级</th> |
| 86 | <th>所在区域</th> | 86 | <th>所在区域</th> |
| 87 | - <th>合作起始日期</th> | ||
| 88 | <th>合作状态</th> | 87 | <th>合作状态</th> |
| 89 | <th>累计应返金额</th> | 88 | <th>累计应返金额</th> |
| 90 | <th>累计已返金额</th> | 89 | <th>累计已返金额</th> |
| ... | @@ -106,7 +105,6 @@ | ... | @@ -106,7 +105,6 @@ |
| 106 | <td>{{ dealer.creditCode }}</td> | 105 | <td>{{ dealer.creditCode }}</td> |
| 107 | <td>{{ getDealerLevelText(dealer.dealerLevel) }}</td> | 106 | <td>{{ getDealerLevelText(dealer.dealerLevel) }}</td> |
| 108 | <td>{{ dealer.region }}</td> | 107 | <td>{{ dealer.region }}</td> |
| 109 | - <td>{{ dealer.cooperateStartDate }}</td> | ||
| 110 | <td> | 108 | <td> |
| 111 | <span :class="getCooperateStatusClass(dealer.cooperateStatus)"> | 109 | <span :class="getCooperateStatusClass(dealer.cooperateStatus)"> |
| 112 | {{ getCooperateStatusText(dealer.cooperateStatus) }} | 110 | {{ getCooperateStatusText(dealer.cooperateStatus) }} |
| ... | @@ -119,6 +117,7 @@ | ... | @@ -119,6 +117,7 @@ |
| 119 | <button @click="handleEdit(dealer)" class="table-btn edit">✏️ 编辑</button> | 117 | <button @click="handleEdit(dealer)" class="table-btn edit">✏️ 编辑</button> |
| 120 | <button @click="handleDelete(dealer)" class="table-btn delete">🗑️ 删除</button> | 118 | <button @click="handleDelete(dealer)" class="table-btn delete">🗑️ 删除</button> |
| 121 | <button @click="handleStatusChange(dealer)" class="table-btn status">🔄 状态</button> | 119 | <button @click="handleStatusChange(dealer)" class="table-btn status">🔄 状态</button> |
| 120 | + <button @click="handleRebateDetail(dealer)" class="table-btn rebate">💰 返利明细</button> | ||
| 122 | </td> | 121 | </td> |
| 123 | </tr> | 122 | </tr> |
| 124 | </tbody> | 123 | </tbody> |
| ... | @@ -185,9 +184,7 @@ | ... | @@ -185,9 +184,7 @@ |
| 185 | <input | 184 | <input |
| 186 | v-model="formData.dealerCode" | 185 | v-model="formData.dealerCode" |
| 187 | class="form-input" | 186 | class="form-input" |
| 188 | - placeholder="请输入经销商编码(6-20位大写字母和数字)" | 187 | + placeholder="请输入经销商编码" |
| 189 | - pattern="^[A-Z0-9]{6,20}$" | ||
| 190 | - title="经销商编码应为6-20位大写字母和数字" | ||
| 191 | required | 188 | required |
| 192 | /> | 189 | /> |
| 193 | </div> | 190 | </div> |
| ... | @@ -277,7 +274,7 @@ | ... | @@ -277,7 +274,7 @@ |
| 277 | </div> | 274 | </div> |
| 278 | </div> | 275 | </div> |
| 279 | <div class="form-row"> | 276 | <div class="form-row"> |
| 280 | - <div class="form-item"> | 277 | + <div class="form-item full-width"> |
| 281 | <label>合作协议URL:</label> | 278 | <label>合作协议URL:</label> |
| 282 | <input | 279 | <input |
| 283 | v-model="formData.cooperationAgreementUrl" | 280 | v-model="formData.cooperationAgreementUrl" |
| ... | @@ -285,22 +282,14 @@ | ... | @@ -285,22 +282,14 @@ |
| 285 | placeholder="请输入合作协议URL" | 282 | placeholder="请输入合作协议URL" |
| 286 | /> | 283 | /> |
| 287 | </div> | 284 | </div> |
| 288 | - <div class="form-item"> | ||
| 289 | - <label>审核意见:</label> | ||
| 290 | - <input | ||
| 291 | - v-model="formData.auditOpinion" | ||
| 292 | - class="form-input" | ||
| 293 | - placeholder="请输入审核意见" | ||
| 294 | - /> | ||
| 295 | - </div> | ||
| 296 | </div> | 285 | </div> |
| 297 | <div class="form-row"> | 286 | <div class="form-row"> |
| 298 | <div class="form-item full-width"> | 287 | <div class="form-item full-width"> |
| 299 | - <label>备注:</label> | 288 | + <label>审核意见:</label> |
| 300 | <textarea | 289 | <textarea |
| 301 | - v-model="formData.remark" | 290 | + v-model="formData.auditOpinion" |
| 302 | class="form-textarea" | 291 | class="form-textarea" |
| 303 | - placeholder="请输入备注" | 292 | + placeholder="请输入审核意见" |
| 304 | rows="3" | 293 | rows="3" |
| 305 | ></textarea> | 294 | ></textarea> |
| 306 | </div> | 295 | </div> |
| ... | @@ -346,12 +335,103 @@ | ... | @@ -346,12 +335,103 @@ |
| 346 | </div> | 335 | </div> |
| 347 | </div> | 336 | </div> |
| 348 | 337 | ||
| 338 | + <!-- 返利明细对话框 --> | ||
| 339 | + <div v-if="showRebateDialog" class="dialog-overlay" @click="handleRebateDialogClose"> | ||
| 340 | + <div class="dialog-content rebate-dialog" @click.stop> | ||
| 341 | + <div class="dialog-header"> | ||
| 342 | + <h3>返利明细 - {{ currentDealer.dealerName }} ({{ currentDealer.dealerCode }})</h3> | ||
| 343 | + <button @click="handleRebateDialogClose" class="dialog-close">×</button> | ||
| 344 | + </div> | ||
| 345 | + <div class="dialog-body"> | ||
| 346 | + <div v-if="rebateLoading" class="loading-overlay"> | ||
| 347 | + <div class="loading-spinner">加载中...</div> | ||
| 348 | + </div> | ||
| 349 | + <div v-else> | ||
| 350 | + <table class="rebate-table"> | ||
| 351 | + <thead> | ||
| 352 | + <tr> | ||
| 353 | + <th>返利编号</th> | ||
| 354 | + <th>订单编号</th> | ||
| 355 | + <th>经销商代码</th> | ||
| 356 | + <th>产品编码</th> | ||
| 357 | + <th>返利金额</th> | ||
| 358 | + <th>返利日期</th> | ||
| 359 | + <th>操作类型</th> | ||
| 360 | + <th>计算状态</th> | ||
| 361 | + </tr> | ||
| 362 | + </thead> | ||
| 363 | + <tbody> | ||
| 364 | + <tr v-for="rebate in rebateList" :key="rebate.rebateId"> | ||
| 365 | + <td>{{ rebate.rebateNo }}</td> | ||
| 366 | + <td>{{ rebate.orderNo }}</td> | ||
| 367 | + <td>{{ rebate.dealerCode }}</td> | ||
| 368 | + <td>{{ rebate.productCode }}</td> | ||
| 369 | + <td class="amount-cell">{{ formatAmount(rebate.rebateAmount) }}</td> | ||
| 370 | + <td>{{ rebate.rebateDate }}</td> | ||
| 371 | + <td> | ||
| 372 | + <span :class="getOperateTypeClass(rebate.operateType || 0)"> | ||
| 373 | + {{ getOperateTypeText(rebate.operateType || 0) }} | ||
| 374 | + </span> | ||
| 375 | + </td> | ||
| 376 | + <td> | ||
| 377 | + <span :class="getCalcFlagClass(rebate.calcFlag || 0)"> | ||
| 378 | + {{ getCalcFlagText(rebate.calcFlag || 0) }} | ||
| 379 | + </span> | ||
| 380 | + </td> | ||
| 381 | + </tr> | ||
| 382 | + <tr v-if="rebateList.length === 0"> | ||
| 383 | + <td colspan="8" class="no-data">暂无返利明细数据</td> | ||
| 384 | + </tr> | ||
| 385 | + </tbody> | ||
| 386 | + </table> | ||
| 387 | + | ||
| 388 | + <!-- 返利明细分页 --> | ||
| 389 | + <div class="rebate-pagination"> | ||
| 390 | + <div class="pagination-info"> | ||
| 391 | + 共 {{ rebatePagination.total || 0 }} 条记录,第 {{ rebatePagination.pageNum || 1 }} / {{ rebateTotalPages || 1 }} 页 | ||
| 392 | + </div> | ||
| 393 | + <div class="pagination-container"> | ||
| 394 | + <button | ||
| 395 | + @click="handleRebatePageChange(rebatePagination.pageNum - 1)" | ||
| 396 | + :disabled="rebatePagination.pageNum <= 1" | ||
| 397 | + class="pagination-btn prev-btn" | ||
| 398 | + > | ||
| 399 | + 上一页 | ||
| 400 | + </button> | ||
| 401 | + <div class="pagination-pages"> | ||
| 402 | + <button | ||
| 403 | + v-for="page in getRebatePageNumbers()" | ||
| 404 | + :key="page" | ||
| 405 | + @click="handleRebatePageChange(page)" | ||
| 406 | + :class="['page-number', { active: page === rebatePagination.pageNum }]" | ||
| 407 | + > | ||
| 408 | + {{ page }} | ||
| 409 | + </button> | ||
| 410 | + </div> | ||
| 411 | + <button | ||
| 412 | + @click="handleRebatePageChange(rebatePagination.pageNum + 1)" | ||
| 413 | + :disabled="rebatePagination.pageNum >= rebateTotalPages" | ||
| 414 | + class="pagination-btn next-btn" | ||
| 415 | + > | ||
| 416 | + 下一页 | ||
| 417 | + </button> | ||
| 418 | + </div> | ||
| 419 | + </div> | ||
| 420 | + </div> | ||
| 421 | + </div> | ||
| 422 | + <div class="dialog-footer"> | ||
| 423 | + <button @click="handleRebateDialogClose" class="dialog-btn confirm">关闭</button> | ||
| 424 | + </div> | ||
| 425 | + </div> | ||
| 426 | + </div> | ||
| 427 | + | ||
| 349 | </div> | 428 | </div> |
| 350 | </template> | 429 | </template> |
| 351 | 430 | ||
| 352 | <script setup lang="ts"> | 431 | <script setup lang="ts"> |
| 353 | import { ref, reactive, computed, onMounted } from 'vue' | 432 | import { ref, reactive, computed, onMounted } from 'vue' |
| 354 | import { dealerApi, type DealerInfo, type DealerQueryReq, type DealerAddReq, type DealerUpdateReq } from '../../api/dealer' | 433 | import { dealerApi, type DealerInfo, type DealerQueryReq, type DealerAddReq, type DealerUpdateReq } from '../../api/dealer' |
| 434 | +import { getRebatePage, type Rebate, type RebateSearchParams } from '../../api/rebate' | ||
| 355 | 435 | ||
| 356 | // 响应式数据 | 436 | // 响应式数据 |
| 357 | const loading = ref(false) | 437 | const loading = ref(false) |
| ... | @@ -363,6 +443,16 @@ const showStatusDialog = ref(false) | ... | @@ -363,6 +443,16 @@ const showStatusDialog = ref(false) |
| 363 | const currentDealer = ref<DealerInfo>({} as DealerInfo) | 443 | const currentDealer = ref<DealerInfo>({} as DealerInfo) |
| 364 | const newCooperateStatus = ref<number>(1) | 444 | const newCooperateStatus = ref<number>(1) |
| 365 | 445 | ||
| 446 | +// 返利明细相关数据 | ||
| 447 | +const showRebateDialog = ref(false) | ||
| 448 | +const rebateLoading = ref(false) | ||
| 449 | +const rebateList = ref<Rebate[]>([]) | ||
| 450 | +const rebatePagination = reactive({ | ||
| 451 | + total: 0, | ||
| 452 | + pageNum: 1, | ||
| 453 | + pageSize: 10 | ||
| 454 | +}) | ||
| 455 | + | ||
| 366 | // 搜索参数 | 456 | // 搜索参数 |
| 367 | const searchParams = reactive<DealerQueryReq>({ | 457 | const searchParams = reactive<DealerQueryReq>({ |
| 368 | dealerCode: '', | 458 | dealerCode: '', |
| ... | @@ -393,6 +483,12 @@ const totalPages = computed(() => { | ... | @@ -393,6 +483,12 @@ const totalPages = computed(() => { |
| 393 | return Math.ceil(pagination.total / pagination.pageSize) || 1 | 483 | return Math.ceil(pagination.total / pagination.pageSize) || 1 |
| 394 | }) | 484 | }) |
| 395 | 485 | ||
| 486 | +// 返利明细分页计算属性 | ||
| 487 | +const rebateTotalPages = computed(() => { | ||
| 488 | + if (rebatePagination.pageSize <= 0) return 1 | ||
| 489 | + return Math.ceil(rebatePagination.total / rebatePagination.pageSize) || 1 | ||
| 490 | +}) | ||
| 491 | + | ||
| 396 | // 表单数据 | 492 | // 表单数据 |
| 397 | const formData = reactive<DealerAddReq & { dealerId?: number }>({ | 493 | const formData = reactive<DealerAddReq & { dealerId?: number }>({ |
| 398 | dealerCode: '', | 494 | dealerCode: '', |
| ... | @@ -455,6 +551,42 @@ const formatAmount = (amount: number | undefined) => { | ... | @@ -455,6 +551,42 @@ const formatAmount = (amount: number | undefined) => { |
| 455 | return `¥${amount.toFixed(2)}` | 551 | return `¥${amount.toFixed(2)}` |
| 456 | } | 552 | } |
| 457 | 553 | ||
| 554 | +// 获取操作类型文本 | ||
| 555 | +const getOperateTypeText = (type: number) => { | ||
| 556 | + const typeMap: { [key: number]: string } = { | ||
| 557 | + 1: '新增', | ||
| 558 | + 2: '扣减' | ||
| 559 | + } | ||
| 560 | + return typeMap[type] || '未知' | ||
| 561 | +} | ||
| 562 | + | ||
| 563 | +// 获取操作类型样式 | ||
| 564 | +const getOperateTypeClass = (type: number) => { | ||
| 565 | + const classMap: { [key: number]: string } = { | ||
| 566 | + 1: 'operate-add', | ||
| 567 | + 2: 'operate-subtract' | ||
| 568 | + } | ||
| 569 | + return classMap[type] || '' | ||
| 570 | +} | ||
| 571 | + | ||
| 572 | +// 获取计算状态文本 | ||
| 573 | +const getCalcFlagText = (flag: number) => { | ||
| 574 | + const flagMap: { [key: number]: string } = { | ||
| 575 | + 0: '未计算', | ||
| 576 | + 1: '已计算' | ||
| 577 | + } | ||
| 578 | + return flagMap[flag] || '未知' | ||
| 579 | +} | ||
| 580 | + | ||
| 581 | +// 获取计算状态样式 | ||
| 582 | +const getCalcFlagClass = (flag: number) => { | ||
| 583 | + const classMap: { [key: number]: string } = { | ||
| 584 | + 0: 'calc-pending', | ||
| 585 | + 1: 'calc-completed' | ||
| 586 | + } | ||
| 587 | + return classMap[flag] || '' | ||
| 588 | +} | ||
| 589 | + | ||
| 458 | 590 | ||
| 459 | // 获取分页页码数组 | 591 | // 获取分页页码数组 |
| 460 | const getPageNumbers = () => { | 592 | const getPageNumbers = () => { |
| ... | @@ -471,11 +603,26 @@ const getPageNumbers = () => { | ... | @@ -471,11 +603,26 @@ const getPageNumbers = () => { |
| 471 | return pages | 603 | return pages |
| 472 | } | 604 | } |
| 473 | 605 | ||
| 606 | +// 获取返利明细分页页码数组 | ||
| 607 | +const getRebatePageNumbers = () => { | ||
| 608 | + const pages = [] | ||
| 609 | + const totalPagesValue = rebateTotalPages.value | ||
| 610 | + if (totalPagesValue <= 0) return [] | ||
| 611 | + | ||
| 612 | + const start = Math.max(1, rebatePagination.pageNum - 2) | ||
| 613 | + const end = Math.min(totalPagesValue, start + 4) | ||
| 614 | + | ||
| 615 | + for (let i = start; i <= end; i++) { | ||
| 616 | + pages.push(i) | ||
| 617 | + } | ||
| 618 | + return pages | ||
| 619 | +} | ||
| 620 | + | ||
| 474 | // 获取经销商列表 | 621 | // 获取经销商列表 |
| 475 | const fetchDealers = async () => { | 622 | const fetchDealers = async () => { |
| 476 | try { | 623 | try { |
| 477 | loading.value = true | 624 | loading.value = true |
| 478 | - const response = await dealerApi.getDealerList(searchParams) | 625 | + const response = await dealerApi.getDealerList(searchParams) as any |
| 479 | if (response.code === 200) { | 626 | if (response.code === 200) { |
| 480 | dealerList.value = response.data.records | 627 | dealerList.value = response.data.records |
| 481 | pagination.total = response.data.total | 628 | pagination.total = response.data.total |
| ... | @@ -531,30 +678,47 @@ const handleAdd = () => { | ... | @@ -531,30 +678,47 @@ const handleAdd = () => { |
| 531 | } | 678 | } |
| 532 | 679 | ||
| 533 | // 编辑 | 680 | // 编辑 |
| 534 | -const handleEdit = (dealer: DealerInfo) => { | 681 | +const handleEdit = async (dealer: DealerInfo) => { |
| 535 | - isEdit.value = true | 682 | + try { |
| 536 | - Object.assign(formData, { | 683 | + isEdit.value = true |
| 537 | - dealerId: dealer.dealerId, | 684 | + showDialog.value = true |
| 538 | - dealerCode: dealer.dealerCode, | 685 | + |
| 539 | - dealerName: dealer.dealerName, | 686 | + // 获取最新的经销商详情 |
| 540 | - creditCode: dealer.creditCode, | 687 | + const response = await dealerApi.getDealerDetail(dealer.dealerId) as any |
| 541 | - dealerLevel: dealer.dealerLevel, | 688 | + if (response.code === 200) { |
| 542 | - region: dealer.region, | 689 | + const dealerDetail = response.data |
| 543 | - contactPerson: dealer.contactPerson, | 690 | + Object.assign(formData, { |
| 544 | - contactPhone: dealer.contactPhone, | 691 | + dealerId: dealerDetail.dealerId, |
| 545 | - cooperateStartDate: dealer.cooperateStartDate, | 692 | + dealerCode: dealerDetail.dealerCode, |
| 546 | - cooperateStatus: dealer.cooperateStatus, | 693 | + dealerName: dealerDetail.dealerName, |
| 547 | - businessLicenseUrl: dealer.businessLicenseUrl, | 694 | + creditCode: dealerDetail.creditCode, |
| 548 | - cooperationAgreementUrl: dealer.cooperationAgreementUrl | 695 | + dealerLevel: dealerDetail.dealerLevel, |
| 549 | - }) | 696 | + region: dealerDetail.region, |
| 550 | - showDialog.value = true | 697 | + contactPerson: dealerDetail.contactPerson, |
| 698 | + contactPhone: dealerDetail.contactPhone, | ||
| 699 | + cooperateStartDate: dealerDetail.cooperateStartDate, | ||
| 700 | + cooperateStatus: dealerDetail.cooperateStatus, | ||
| 701 | + businessLicenseUrl: dealerDetail.businessLicenseUrl, | ||
| 702 | + cooperationAgreementUrl: dealerDetail.cooperationAgreementUrl, | ||
| 703 | + qualificationAuditStatus: dealerDetail.qualificationAuditStatus, | ||
| 704 | + auditOpinion: dealerDetail.auditOpinion | ||
| 705 | + }) | ||
| 706 | + } else { | ||
| 707 | + alert('获取经销商详情失败') | ||
| 708 | + showDialog.value = false | ||
| 709 | + } | ||
| 710 | + } catch (error: any) { | ||
| 711 | + console.error('获取经销商详情失败:', error) | ||
| 712 | + alert('获取经销商详情失败') | ||
| 713 | + showDialog.value = false | ||
| 714 | + } | ||
| 551 | } | 715 | } |
| 552 | 716 | ||
| 553 | // 删除 | 717 | // 删除 |
| 554 | const handleDelete = async (dealer: DealerInfo) => { | 718 | const handleDelete = async (dealer: DealerInfo) => { |
| 555 | if (confirm(`确定要删除经销商"${dealer.dealerName}"吗?`)) { | 719 | if (confirm(`确定要删除经销商"${dealer.dealerName}"吗?`)) { |
| 556 | try { | 720 | try { |
| 557 | - const response = await dealerApi.deleteDealer(dealer.dealerId) | 721 | + const response = await dealerApi.deleteDealer(dealer.dealerId) as any |
| 558 | if (response.code === 200) { | 722 | if (response.code === 200) { |
| 559 | alert('删除成功') | 723 | alert('删除成功') |
| 560 | fetchDealers() | 724 | fetchDealers() |
| ... | @@ -594,7 +758,7 @@ const handleBatchDelete = async () => { | ... | @@ -594,7 +758,7 @@ const handleBatchDelete = async () => { |
| 594 | 758 | ||
| 595 | if (confirm(`确定要删除选中的 ${selectedDealers.value.length} 个经销商吗?`)) { | 759 | if (confirm(`确定要删除选中的 ${selectedDealers.value.length} 个经销商吗?`)) { |
| 596 | try { | 760 | try { |
| 597 | - const response = await dealerApi.batchDeleteDealer(selectedDealers.value) | 761 | + const response = await dealerApi.batchDeleteDealer(selectedDealers.value) as any |
| 598 | if (response.code === 200) { | 762 | if (response.code === 200) { |
| 599 | alert('批量删除成功') | 763 | alert('批量删除成功') |
| 600 | selectedDealers.value = [] | 764 | selectedDealers.value = [] |
| ... | @@ -637,14 +801,7 @@ const handleStatusChange = (dealer: DealerInfo) => { | ... | @@ -637,14 +801,7 @@ const handleStatusChange = (dealer: DealerInfo) => { |
| 637 | // 提交表单 | 801 | // 提交表单 |
| 638 | const handleSubmit = async () => { | 802 | const handleSubmit = async () => { |
| 639 | try { | 803 | try { |
| 640 | - // 前端验证经销商编码格式 | 804 | + let response: any |
| 641 | - const dealerCodePattern = /^[A-Z0-9]{6,20}$/ | ||
| 642 | - if (!dealerCodePattern.test(formData.dealerCode)) { | ||
| 643 | - alert('经销商编码格式不正确,应为6-20位大写字母和数字') | ||
| 644 | - return | ||
| 645 | - } | ||
| 646 | - | ||
| 647 | - let response | ||
| 648 | if (isEdit.value) { | 805 | if (isEdit.value) { |
| 649 | response = await dealerApi.updateDealer(formData as DealerUpdateReq) | 806 | response = await dealerApi.updateDealer(formData as DealerUpdateReq) |
| 650 | } else { | 807 | } else { |
| ... | @@ -695,7 +852,7 @@ const handleSubmit = async () => { | ... | @@ -695,7 +852,7 @@ const handleSubmit = async () => { |
| 695 | // 状态提交 | 852 | // 状态提交 |
| 696 | const handleStatusSubmit = async () => { | 853 | const handleStatusSubmit = async () => { |
| 697 | try { | 854 | try { |
| 698 | - const response = await dealerApi.updateCooperateStatus(currentDealer.value.dealerId, newCooperateStatus.value) | 855 | + const response = await dealerApi.updateCooperateStatus(currentDealer.value.dealerId, newCooperateStatus.value) as any |
| 699 | if (response.code === 200) { | 856 | if (response.code === 200) { |
| 700 | alert('状态修改成功') | 857 | alert('状态修改成功') |
| 701 | showStatusDialog.value = false | 858 | showStatusDialog.value = false |
| ... | @@ -726,6 +883,52 @@ const handleStatusSubmit = async () => { | ... | @@ -726,6 +883,52 @@ const handleStatusSubmit = async () => { |
| 726 | } | 883 | } |
| 727 | } | 884 | } |
| 728 | 885 | ||
| 886 | +// 返利明细相关方法 | ||
| 887 | +const handleRebateDetail = (dealer: DealerInfo) => { | ||
| 888 | + currentDealer.value = dealer | ||
| 889 | + rebatePagination.pageNum = 1 | ||
| 890 | + showRebateDialog.value = true | ||
| 891 | + fetchRebateList() | ||
| 892 | +} | ||
| 893 | + | ||
| 894 | +const fetchRebateList = async () => { | ||
| 895 | + try { | ||
| 896 | + rebateLoading.value = true | ||
| 897 | + const params: RebateSearchParams = { | ||
| 898 | + dealerCode: currentDealer.value.dealerCode, | ||
| 899 | + pageNum: rebatePagination.pageNum, | ||
| 900 | + pageSize: rebatePagination.pageSize | ||
| 901 | + } | ||
| 902 | + | ||
| 903 | + const response = await getRebatePage(params) as any | ||
| 904 | + // @/utils/request 的响应拦截器已经返回了 data 部分 | ||
| 905 | + rebateList.value = response.records | ||
| 906 | + rebatePagination.total = response.total | ||
| 907 | + rebatePagination.pageNum = response.current | ||
| 908 | + rebatePagination.pageSize = response.size | ||
| 909 | + } catch (error: any) { | ||
| 910 | + console.error('获取返利明细失败:', error) | ||
| 911 | + alert('获取返利明细失败') | ||
| 912 | + } finally { | ||
| 913 | + rebateLoading.value = false | ||
| 914 | + } | ||
| 915 | +} | ||
| 916 | + | ||
| 917 | +const handleRebatePageChange = (page: number) => { | ||
| 918 | + const totalPagesValue = rebateTotalPages.value | ||
| 919 | + if (page >= 1 && page <= totalPagesValue && totalPagesValue > 0) { | ||
| 920 | + rebatePagination.pageNum = page | ||
| 921 | + fetchRebateList() | ||
| 922 | + } | ||
| 923 | +} | ||
| 924 | + | ||
| 925 | +const handleRebateDialogClose = () => { | ||
| 926 | + showRebateDialog.value = false | ||
| 927 | + rebateList.value = [] | ||
| 928 | + rebatePagination.total = 0 | ||
| 929 | + rebatePagination.pageNum = 1 | ||
| 930 | +} | ||
| 931 | + | ||
| 729 | 932 | ||
| 730 | // 全选 | 933 | // 全选 |
| 731 | const handleSelectAll = () => { | 934 | const handleSelectAll = () => { |
| ... | @@ -743,8 +946,7 @@ const handlePageChange = (page: number) => { | ... | @@ -743,8 +946,7 @@ const handlePageChange = (page: number) => { |
| 743 | } | 946 | } |
| 744 | 947 | ||
| 745 | const handlePageSizeChange = () => { | 948 | const handlePageSizeChange = () => { |
| 746 | - pagination.pageSize = pageSize.value | 949 | + searchParams.pageSize = pagination.pageSize |
| 747 | - searchParams.pageSize = pageSize.value | ||
| 748 | pagination.pageNum = 1 | 950 | pagination.pageNum = 1 |
| 749 | searchParams.pageNum = 1 | 951 | searchParams.pageNum = 1 |
| 750 | fetchDealers() | 952 | fetchDealers() |
| ... | @@ -1301,4 +1503,106 @@ onMounted(() => { | ... | @@ -1301,4 +1503,106 @@ onMounted(() => { |
| 1301 | color: #1890ff; | 1503 | color: #1890ff; |
| 1302 | font-family: 'Courier New', monospace; | 1504 | font-family: 'Courier New', monospace; |
| 1303 | } | 1505 | } |
| 1506 | + | ||
| 1507 | +/* 返利明细相关样式 */ | ||
| 1508 | +.table-btn.rebate { | ||
| 1509 | + background: linear-gradient(135deg, #ffd700, #ffed4e); | ||
| 1510 | + color: #333; | ||
| 1511 | + border: 1px solid #ffd700; | ||
| 1512 | +} | ||
| 1513 | + | ||
| 1514 | +.table-btn.rebate:hover { | ||
| 1515 | + background: linear-gradient(135deg, #ffed4e, #ffd700); | ||
| 1516 | + transform: translateY(-1px); | ||
| 1517 | + box-shadow: 0 4px 8px rgba(255, 215, 0, 0.3); | ||
| 1518 | +} | ||
| 1519 | + | ||
| 1520 | +/* 返利明细对话框样式 */ | ||
| 1521 | +.rebate-dialog { | ||
| 1522 | + max-width: 1200px; | ||
| 1523 | + width: 90%; | ||
| 1524 | + max-height: 80vh; | ||
| 1525 | +} | ||
| 1526 | + | ||
| 1527 | +.rebate-table { | ||
| 1528 | + width: 100%; | ||
| 1529 | + border-collapse: collapse; | ||
| 1530 | + margin-bottom: 20px; | ||
| 1531 | + font-size: 14px; | ||
| 1532 | +} | ||
| 1533 | + | ||
| 1534 | +.rebate-table th, | ||
| 1535 | +.rebate-table td { | ||
| 1536 | + padding: 12px 8px; | ||
| 1537 | + text-align: left; | ||
| 1538 | + border-bottom: 1px solid #eee; | ||
| 1539 | +} | ||
| 1540 | + | ||
| 1541 | +.rebate-table th { | ||
| 1542 | + background: #f8f9fa; | ||
| 1543 | + font-weight: 600; | ||
| 1544 | + color: #333; | ||
| 1545 | + position: sticky; | ||
| 1546 | + top: 0; | ||
| 1547 | + z-index: 10; | ||
| 1548 | +} | ||
| 1549 | + | ||
| 1550 | +.rebate-table tbody tr:hover { | ||
| 1551 | + background: #f5f7fa; | ||
| 1552 | +} | ||
| 1553 | + | ||
| 1554 | +.rebate-table .no-data { | ||
| 1555 | + text-align: center; | ||
| 1556 | + color: #999; | ||
| 1557 | + font-style: italic; | ||
| 1558 | + padding: 40px; | ||
| 1559 | +} | ||
| 1560 | + | ||
| 1561 | +/* 返利明细分页样式 */ | ||
| 1562 | +.rebate-pagination { | ||
| 1563 | + display: flex; | ||
| 1564 | + justify-content: space-between; | ||
| 1565 | + align-items: center; | ||
| 1566 | + margin-top: 20px; | ||
| 1567 | + padding: 15px 0; | ||
| 1568 | + border-top: 1px solid #eee; | ||
| 1569 | +} | ||
| 1570 | + | ||
| 1571 | +/* 操作类型样式 */ | ||
| 1572 | +.operate-add { | ||
| 1573 | + color: #67c23a; | ||
| 1574 | + font-weight: 500; | ||
| 1575 | + background: #f0f9ff; | ||
| 1576 | + padding: 2px 8px; | ||
| 1577 | + border-radius: 4px; | ||
| 1578 | + font-size: 12px; | ||
| 1579 | +} | ||
| 1580 | + | ||
| 1581 | +.operate-subtract { | ||
| 1582 | + color: #f56c6c; | ||
| 1583 | + font-weight: 500; | ||
| 1584 | + background: #fef0f0; | ||
| 1585 | + padding: 2px 8px; | ||
| 1586 | + border-radius: 4px; | ||
| 1587 | + font-size: 12px; | ||
| 1588 | +} | ||
| 1589 | + | ||
| 1590 | +/* 计算状态样式 */ | ||
| 1591 | +.calc-pending { | ||
| 1592 | + color: #e6a23c; | ||
| 1593 | + font-weight: 500; | ||
| 1594 | + background: #fdf6ec; | ||
| 1595 | + padding: 2px 8px; | ||
| 1596 | + border-radius: 4px; | ||
| 1597 | + font-size: 12px; | ||
| 1598 | +} | ||
| 1599 | + | ||
| 1600 | +.calc-completed { | ||
| 1601 | + color: #67c23a; | ||
| 1602 | + font-weight: 500; | ||
| 1603 | + background: #f0f9ff; | ||
| 1604 | + padding: 2px 8px; | ||
| 1605 | + border-radius: 4px; | ||
| 1606 | + font-size: 12px; | ||
| 1607 | +} | ||
| 1304 | </style> | 1608 | </style> |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
-
Please register or login to post a comment