|
13 | 13 | <span class="u-value">{{ subtypes[data.subtype] }}</span> |
14 | 14 | </div> |
15 | 15 | </div> |
16 | | - <el-dropdown |
17 | | - v-if="isTeammate && data.status < 12" |
18 | | - split-button |
19 | | - trigger="click" |
20 | | - type="primary" |
21 | | - @click.stop="onDeal" |
22 | | - > |
23 | | - <i class="el-icon-s-tools u-dropdown-icon"></i> |
24 | | - {{ statusText(data.status) }} |
25 | | - <template #dropdown> |
26 | | - <el-dropdown-menu> |
27 | | - <el-dropdown-item @click="handleEdit"> |
28 | | - <el-button class="u-btn" type="primary" icon="Edit">编辑</el-button> |
29 | | - </el-dropdown-item> |
30 | | - <el-dropdown-item @click="handleTransfer"> |
31 | | - <el-button class="u-btn" type="warning" icon="Right">转交</el-button> |
32 | | - </el-dropdown-item> |
33 | | - <template v-if="data.status === 2"> |
34 | | - <el-dropdown-item @click="handleCoordination"> |
35 | | - <el-button class="u-btn" type="success" icon="Help">协同</el-button> |
| 16 | + <div class="m-actions" v-if="canCancelTicket || canUrgeTicket || (isTeammate && data.status < 12)"> |
| 17 | + <el-button |
| 18 | + v-if="canCancelTicket" |
| 19 | + class="u-action-btn is-cancel" |
| 20 | + type="danger" |
| 21 | + plain |
| 22 | + icon="CircleClose" |
| 23 | + :loading="closeTicketLoading" |
| 24 | + :disabled="closeTicketLoading" |
| 25 | + @click.stop="onCancelTicket" |
| 26 | + > |
| 27 | + 取消工单 |
| 28 | + </el-button> |
| 29 | + <el-button |
| 30 | + v-if="canUrgeTicket" |
| 31 | + class="u-action-btn is-urgent" |
| 32 | + type="warning" |
| 33 | + plain |
| 34 | + icon="Bell" |
| 35 | + :loading="urgeTicketLoading" |
| 36 | + :disabled="urgeTicketLoading" |
| 37 | + @click.stop="onUrgeTicket" |
| 38 | + > |
| 39 | + 催单 |
| 40 | + </el-button> |
| 41 | + <el-dropdown |
| 42 | + v-if="isTeammate && data.status < 12" |
| 43 | + split-button |
| 44 | + trigger="click" |
| 45 | + type="primary" |
| 46 | + @click.stop="onDeal" |
| 47 | + > |
| 48 | + <i class="el-icon-s-tools u-dropdown-icon"></i> |
| 49 | + {{ statusText(data.status) }} |
| 50 | + <template #dropdown> |
| 51 | + <el-dropdown-menu> |
| 52 | + <el-dropdown-item @click="handleEdit"> |
| 53 | + <el-button class="u-btn" type="primary" icon="Edit">编辑</el-button> |
36 | 54 | </el-dropdown-item> |
37 | | - |
38 | | - <el-dropdown-item @click="handleClose"> |
39 | | - <el-button class="u-btn" type="info" icon="CircleClose">关闭 </el-button> |
| 55 | + <el-dropdown-item @click="handleTransfer"> |
| 56 | + <el-button class="u-btn" type="warning" icon="Right">转交</el-button> |
40 | 57 | </el-dropdown-item> |
41 | | - </template> |
42 | | - </el-dropdown-menu> |
43 | | - </template> |
44 | | - </el-dropdown> |
| 58 | + <template v-if="data.status === 2"> |
| 59 | + <el-dropdown-item @click="handleCoordination"> |
| 60 | + <el-button class="u-btn" type="success" icon="Help">协同</el-button> |
| 61 | + </el-dropdown-item> |
| 62 | + |
| 63 | + <el-dropdown-item @click="handleClose"> |
| 64 | + <el-button class="u-btn" type="info" icon="CircleClose">关闭 </el-button> |
| 65 | + </el-dropdown-item> |
| 66 | + </template> |
| 67 | + </el-dropdown-menu> |
| 68 | + </template> |
| 69 | + </el-dropdown> |
| 70 | + </div> |
45 | 71 | </div> |
46 | 72 | <div class="m-block m-user"> |
47 | 73 | <div class="u-subblock"> |
|
292 | 318 |
|
293 | 319 | <script> |
294 | 320 | import DOMPurify from "dompurify"; |
295 | | -import { getFeedback, getFeedbackLog } from "@/service/dashboard/feedback"; |
| 321 | +import { closeMyFeedback, getFeedback, getFeedbackLog, urgeMyFeedback } from "@/service/dashboard/feedback"; |
296 | 322 | import { getTeammates } from "@/service/dashboard/index"; |
297 | 323 | import feedbackData from "@/assets/data/dashboard/feedback.json"; |
298 | 324 | const { types, subtypes, statusMap, statusColors, statusTypes } = feedbackData; |
@@ -348,6 +374,8 @@ export default { |
348 | 374 | opType: "assign", |
349 | 375 | statusVisible: false, |
350 | 376 | isClose: false, |
| 377 | + closeTicketLoading: false, |
| 378 | + urgeTicketLoading: false, |
351 | 379 | }; |
352 | 380 | }, |
353 | 381 | computed: { |
@@ -390,6 +418,27 @@ export default { |
390 | 418 | videoAttachments() { |
391 | 419 | return this.attachments.filter((item) => this.isVideoUrl(item)); |
392 | 420 | }, |
| 421 | + isTicketOwner() { |
| 422 | + const user = User.getInfo(); |
| 423 | + const ownerId = Number(this.data?.user_id || this.data?.user?.id); |
| 424 | + return User.isLogin() && Number(user?.uid) === ownerId; |
| 425 | + }, |
| 426 | + isTicketFinalStatus() { |
| 427 | + return [10, 11, 12].includes(Number(this.data?.status)); |
| 428 | + }, |
| 429 | + hasUrgedTicket() { |
| 430 | + return Boolean(this.data?.is_urgent); |
| 431 | + }, |
| 432 | + canCancelTicket() { |
| 433 | + return this.isTicketOwner && !this.isTicketFinalStatus; |
| 434 | + }, |
| 435 | + canUrgeTicket() { |
| 436 | + return ( |
| 437 | + this.isTicketOwner && |
| 438 | + ![0, 10, 11, 12].includes(Number(this.data?.status)) && |
| 439 | + !this.hasUrgedTicket |
| 440 | + ); |
| 441 | + }, |
393 | 442 | }, |
394 | 443 | watch: { |
395 | 444 | id: { |
@@ -477,6 +526,52 @@ export default { |
477 | 526 | this.isClose = true; |
478 | 527 | this.statusVisible = true; |
479 | 528 | }, |
| 529 | + async onCancelTicket() { |
| 530 | + if (!this.canCancelTicket || this.closeTicketLoading) return; |
| 531 | +
|
| 532 | + try { |
| 533 | + const { value } = await this.$prompt("请输入取消工单的备注", "取消工单", { |
| 534 | + confirmButtonText: "确定", |
| 535 | + cancelButtonText: "取消", |
| 536 | + inputPlaceholder: "请输入备注", |
| 537 | + inputValidator(value) { |
| 538 | + return !!String(value || "").trim() || "请输入备注"; |
| 539 | + }, |
| 540 | + }); |
| 541 | + const remark = String(value || "").trim(); |
| 542 | + this.closeTicketLoading = true; |
| 543 | + await closeMyFeedback(this.id, { remark }); |
| 544 | + this.$message.success("取消成功"); |
| 545 | + this.load(); |
| 546 | + } catch (error) { |
| 547 | + if (error !== "cancel" && error !== "close") { |
| 548 | + this.$message.error(error?.response?.data?.msg || "取消失败"); |
| 549 | + } |
| 550 | + } finally { |
| 551 | + this.closeTicketLoading = false; |
| 552 | + } |
| 553 | + }, |
| 554 | + async onUrgeTicket() { |
| 555 | + if (!this.canUrgeTicket || this.urgeTicketLoading) return; |
| 556 | +
|
| 557 | + try { |
| 558 | + await this.$confirm("每个工单只有一次催单机会,确定要催单吗?", "催单", { |
| 559 | + confirmButtonText: "确定", |
| 560 | + cancelButtonText: "取消", |
| 561 | + type: "warning", |
| 562 | + }); |
| 563 | + this.urgeTicketLoading = true; |
| 564 | + await urgeMyFeedback(this.id); |
| 565 | + this.$message.success("催单成功"); |
| 566 | + this.load(); |
| 567 | + } catch (error) { |
| 568 | + if (error !== "cancel" && error !== "close") { |
| 569 | + this.$message.error(error?.response?.data?.msg || "催单失败"); |
| 570 | + } |
| 571 | + } finally { |
| 572 | + this.urgeTicketLoading = false; |
| 573 | + } |
| 574 | + }, |
480 | 575 | loadLogs() { |
481 | 576 | this.logLoading = true; |
482 | 577 | getFeedbackLog(this.id) |
|
0 commit comments