From a7b45caf5b3784f65ba82793d87f5ffb202fca1e Mon Sep 17 00:00:00 2001 From: Tomas <tomasysh@gmail.com> Date: 星期五, 21 一月 2022 11:42:07 +0800 Subject: [PATCH] update#134555: [顧問] 預約單結案/編輯結案功能串接 --- PAMapp/shared/const/appointment-fail-reason-list.ts | 26 +++ PAMapp/shared/services/appointment.service.ts | 2 PAMapp/pages/myAppointmentList/closedList.vue | 16 +- PAMapp/components/Client/ClientCard.vue | 11 + PAMapp/components/Appointment/AppointmentClosedInfo.vue | 59 ++++++++ PAMapp/shared/models/appointment.model.ts | 56 ++++--- PAMapp/plugins/filters/appointment-fail-reason.filter.ts | 16 ++ PAMapp/pages/appointment/_appointmentId/index.vue | 77 +++++++--- PAMapp/pages/appointment/_appointmentId/close/index.vue | 108 +++++++------- 9 files changed, 257 insertions(+), 114 deletions(-) diff --git a/PAMapp/components/Appointment/AppointmentClosedInfo.vue b/PAMapp/components/Appointment/AppointmentClosedInfo.vue new file mode 100644 index 0000000..8b08adb --- /dev/null +++ b/PAMapp/components/Appointment/AppointmentClosedInfo.vue @@ -0,0 +1,59 @@ +<template> + <section class="close-appointment-detail"> + + <div class="close-appointment-detail-nav"> + <div class="mdTxt">蝯�撘�</div> + <div class="mdTxt text--primary text--underline cursor--pointer" @click="editAppointmentHasClosed">蝺刻摩</div> + </div> + <span class="mt-10 mb-30">{{ displayClosedType }}</span> + + <template v-if="appointmentDetail.appointmentClosedInfo.policyholderIdentityId"> + <div class="mdTxt mb-10">靽頨思遢霅���</div> + <div class="mb-30">{{ appointmentDetail.appointmentClosedInfo.policyholderIdentityId }}</div> + </template> + + <template v-if="appointmentDetail.appointmentClosedInfo.planCode"> + <div class="mdTxt mb-10">���誨蝣噗lan Code</div> + <div class="mb-30">{{ appointmentDetail.appointmentClosedInfo.planCode }}</div> + </template> + + <template v-if="appointmentDetail.appointmentClosedInfo.closedReason"> + <div class="mdTxt mb-10">���漱����</div> + <div >{{ appointmentDetail.appointmentClosedInfo.closedReason | toFailReasonLabel }}</div> + <div v-if="appointmentDetail.appointmentClosedInfo.closedOtherReason" class="mt-10">{{ appointmentDetail.appointmentClosedInfo.closedOtherReason }}</div> + <div class="mb-30"></div> + </template> + + <template v-if="appointmentDetail.appointmentClosedInfo.policyEntryDate"> + <div class="mdTxt mb-10">�脖辣����</div> + <div class="mb-30">{{ appointmentDetail.appointmentClosedInfo.policyEntryDate | formatDate }}</div> + </template> + + <div class="mdTxt mb-10">��酉</div> + <div>{{ appointmentDetail.appointmentClosedInfo.remark || '�' }}</div> + + </section> +</template> + +<script lang="ts"> +import { Vue, Component, Prop } from 'nuxt-property-decorator'; + +import { Appointment } from '~/shared/models/appointment.model'; + +@Component +export default class AppointmentRecordList extends Vue { + + @Prop() + appointmentDetail!: Appointment; + + ////////////////////////////////////////////////////////////////////// + + editAppointmentHasClosed(): void{ + this.$router.push(`/appointment/${this.appointmentDetail.id}/close`); + } + +} +</script> + +<style lang="scss" scoped> +</style> diff --git a/PAMapp/components/Client/ClientCard.vue b/PAMapp/components/Client/ClientCard.vue index f203dd0..cfe5154 100644 --- a/PAMapp/components/Client/ClientCard.vue +++ b/PAMapp/components/Client/ClientCard.vue @@ -257,6 +257,7 @@ viewAppointmentDetail(): void { this.getAppointmentDetail(this.client.id).then((_) => { + this.readAppointment(); this.$router.push(`/appointment/${this.client.id}`); }); } @@ -289,7 +290,13 @@ } closeInformDialog(): void { - const unread = !this.client.consultantReadTime; + this.readAppointment(); + this.isEdit = false; + this.clearAppointmentIdFromMsg(); + } + + private readAppointment(): void { + const unread = !this.client.consultantReadTime; if (unread) { appointmentService.recordRead(this.client.id).then((_) => { const updatedClient = {...this.client}; @@ -297,8 +304,6 @@ this.updateMyAppointmentList(updatedClient); }); }; - this.isEdit = false; - this.clearAppointmentIdFromMsg(); } private clearAppointmentIdFromMsg() { diff --git a/PAMapp/pages/appointment/_appointmentId/close/index.vue b/PAMapp/pages/appointment/_appointmentId/close/index.vue index 973e48a..956280e 100644 --- a/PAMapp/pages/appointment/_appointmentId/close/index.vue +++ b/PAMapp/pages/appointment/_appointmentId/close/index.vue @@ -11,7 +11,7 @@ </UiField> </el-row> - <template v-if="appointmentCloseInfo.selectCloseOption === 'done'"> + <template v-if="appointmentCloseInfo.selectCloseOption === contactStatus.DONE"> <el-row type="flex" class="pam-paragraph" style="flex-direction: column"> @@ -43,18 +43,20 @@ <el-row type="flex" class="pam-paragraph"> - <UiField label="�脖辣����" :labelSize="20" class="required"> - <DateTimePicker @changeDateTime="appointmentCloseDate = $event"></DateTimePicker> + <UiField label="�脖辣����" :labelSize="20"> + <DateTimePicker + :defaultValue="appointmentCloseInfo.policyEntryDate" + @changeDateTime="appointmentCloseInfo.policyEntryDate = $event"></DateTimePicker> </UiField> </el-row> </template> - <template v-if="appointmentCloseInfo.selectCloseOption === 'close'"> + <template v-if="appointmentCloseInfo.selectCloseOption === contactStatus.CLOSE"> <el-row class="pam-paragraph"> <UiField label="���漱����" :labelSize="20" class="required"> </UiField> - <div class="appointment-client-detail-close__selectbox"> + <div class="appointment-client-detail-close__select-box"> <select class="appointment-client-detail-close__select" name="closedReason" id="closedReason" v-model="appointmentCloseInfo.closedReason"> @@ -64,8 +66,7 @@ </select> <i class="icon-down down-icon"></i> </div> - <div style="display: flex" class="mt-10"> - + <div class="mt-10"> <input v-if="appointmentCloseInfo.closedReason === 'other' || appointmentCloseInfo.closedReason === 'no_suitable_commodity'" @@ -88,16 +89,6 @@ v-model="appointmentCloseInfo.remark" resize="none"> </el-input> - - <!-- <textarea - v-model="appointmentCloseInfo.archivedDate" - class="appointment-close__remark" - placeholder="隢撓�" - name="remark" - id="remark" - wrap="off" - rows="3"> - </textarea> --> </UiField> </el-row> @@ -123,9 +114,10 @@ import { namespace } from 'nuxt-property-decorator'; import { Vue, Component } from 'vue-property-decorator'; import { Appointment, ToCloseAppointment, ToDoneAppointment } from '~/shared/models/appointment.model'; -import { ContactStatus } from '~/shared/models/enum/contact-status'; import appointmentService from '~/shared/services/appointment.service'; +import { appointmentFailReasonList } from '~/shared/const/appointment-fail-reason-list'; +import { ContactStatus } from '~/shared/models/enum/contact-status'; const appointmentStore = namespace('appointment.store'); @@ -133,7 +125,10 @@ export default class AppointmentDetailCloseComponent extends Vue { @appointmentStore.Action - updateAppointmentDetail!: () => Appointment; + updateAppointmentDetail!: (appointmentId: number) => Appointment; + + @appointmentStore.State('appointmentDetail') + appointmentDetail!: Appointment; contactStatus = ContactStatus; @@ -147,58 +142,60 @@ policyEntryDate : this.appointmentCloseDate, policyholderIdentityId: '', remark : '', - selectCloseOption : 'done', + selectCloseOption : this.contactStatus.DONE, }; closeOptions = [ { title:'��漱', - label: 'done', + label: this.contactStatus.DONE, }, { title:'���漱', - label: 'close', + label: this.contactStatus.CLOSE, } ]; - appointmentFailReason = [ - { - key: '�瘜蝜怠恥�', - value: 'cannot_to_contact_customer' - }, - { - key: '�蝝垣閰�', - value: 'only_consultation' - }, - { - key: '�������', - value: 'no_suitable_commodity' - }, - { - key: '�靽���- 擃��瓷���璆�', - value: 'prohibited_factors' - }, - { - key: '蝬����', - value: 'economy' - }, - { - key: '�隞�', - value: 'other' - }, - ]; + appointmentFailReason = appointmentFailReasonList; + + ////////////////////////////////////////////////////////////////////// + + mounted() { + const appointmentId = +this.$route.params.appointmentId; + const closedInfo = this.appointmentDetail.appointmentClosedInfo; + if (this.appointmentDetail.id === appointmentId + && (this.appointmentDetail.communicateStatus === this.contactStatus.DONE + || this.appointmentDetail.communicateStatus === this.contactStatus.CLOSE + || this.appointmentDetail.communicateStatus === this.contactStatus.CANCEL) + ) { + this.appointmentCloseInfo = { + closedOtherReason : closedInfo?.closedOtherReason, + closedReason : closedInfo?.closedReason, + planCode : closedInfo?.planCode, + policyEntryDate : closedInfo?.policyEntryDate, + policyholderIdentityId: closedInfo?.policyholderIdentityId, + remark : closedInfo?.remark, + selectCloseOption : this.appointmentDetail.communicateStatus === this.contactStatus.DONE + ? this.contactStatus.DONE + : this.contactStatus.CLOSE + }; + } + } + + ////////////////////////////////////////////////////////////////////// closeAppointment(): void { const appointmentId = +this.$route.params.appointmentId; - if (this.appointmentCloseInfo.selectCloseOption === 'done') { + if (this.appointmentCloseInfo.selectCloseOption === this.contactStatus.DONE) { const toDoneAppointment: ToDoneAppointment = { appointmentId : appointmentId, contactStatus : this.contactStatus.DONE, planCode : this.appointmentCloseInfo.planCode, policyEntryDate : this.appointmentCloseInfo.policyEntryDate, policyholderIdentityId: this.appointmentCloseInfo.policyholderIdentityId, + remark : this.appointmentCloseInfo.remark, } - appointmentService.closeAppointment(toDoneAppointment).then((res) => res); + appointmentService.closeAppointment(toDoneAppointment).then((_) => this.updateAppointmentDetail(appointmentId)); this.isShowSuccessAlert = true; } else { const toCloseAppointment: ToCloseAppointment = { @@ -208,7 +205,7 @@ contactStatus : this.contactStatus.CLOSE, remark : this.appointmentCloseInfo.remark, } - appointmentService.closeAppointment(toCloseAppointment).then((res) => res); + appointmentService.closeAppointment(toCloseAppointment).then((_) => this.updateAppointmentDetail(appointmentId)); this.isShowSuccessAlert = true; } } @@ -224,11 +221,12 @@ policyholderIdentityId, planCode, closedReason, - closedOtherReason + closedOtherReason, + remark } = this.appointmentCloseInfo; // this.appointmentCloseInfo.policyEntryDate 銝行��齒瘜��澆 this.appointmentCloseDate - if (selectCloseOption === 'done') { - return !policyholderIdentityId || !this.identityIdValid || !planCode || !this.appointmentCloseDate + if (selectCloseOption === this.contactStatus.DONE) { + return !policyholderIdentityId || !this.identityIdValid || !planCode || !this.appointmentCloseInfo.policyEntryDate || !remark } else if (closedReason === 'other' || closedReason === 'no_suitable_commodity') { return !closedOtherReason } @@ -261,7 +259,7 @@ border-color: $PRIMARY_RED !important; } } -.appointment-client-detail-close__selectbox { +.appointment-client-detail-close__select-box { position: relative; & .appointment-client-detail-close__select{ diff --git a/PAMapp/pages/appointment/_appointmentId/index.vue b/PAMapp/pages/appointment/_appointmentId/index.vue index b4a7da0..54ad105 100644 --- a/PAMapp/pages/appointment/_appointmentId/index.vue +++ b/PAMapp/pages/appointment/_appointmentId/index.vue @@ -31,15 +31,22 @@ </div> <div class="client-detail-demand mt-10"> - <div class="client-detail-demand__demand-list"> + + <div class="client-detail-demand__demand-list mb-10"> <div class="client-detail-demand__demand-list-label">��瘙�</div> - <div>{{ appointmentDetail.requirement }}</div> + <div class="client-detail-demand__demand-list-content">{{ appointmentDetail.requirement }}</div> </div> - <div class="client-detail-demand__hope-contact-time"> + + <div class="client-detail-demand__demand-list"> <div class="client-detail-demand__demand-list-label">�蝯�<br />��挾</div> - <div>���� 17:00 ~ 19:00</div> - <!-- TODO: 憭�蝯⊥�挾憒�� && 頝���� [Tomas. 2021/1/12] --> - <!-- <div>{{ appointmentDetail.hopeContactTime }}</div> --> + <div class="client-detail-demand__demand-list-content"> + <div v-for="(hopeContactTime, index) in hopeContactTimeList" :key="index" + :class="{'mt-10': index > 0, 'pb-10': true, 'hope-contact-time__line': index + 1 < hopeContactTimeList.length }"> + <div v-for="(item, index) in getHopeContactTimeContent(hopeContactTime)" :key="index" :class="{'mt-10': index < 0 }"> + {{ item }} + </div> + </div> + </div> </div> </div> @@ -54,24 +61,9 @@ </section> - <section class="close-appointment-detail" v-if="showWhenAppointmentHasClosed"> - - <div class="close-appointment-detail-nav"> - <div class="mdTxt">蝯�撘�</div> - <div class="mdTxt text--primary text--underline cursor--pointer" @click="editAppointmentHasClosed">蝺刻摩</div> - </div> - <span class="mt-10 mb-30">��漱</span> - - <div class="mdTxt mb-10">靽頨思遢霅���</div> - <div class="mb-30">A123456789</div> - <div class="mdTxt mb-10">���誨蝣噗lan Code</div> - <div class="mb-30">8888888</div> - <div class="mdTxt mb-10">�脖辣����</div> - <div class="mb-30">2021/12/2</div> - <div class="mdTxt mb-10">��酉</div> - <div class="">蝝赤4甈∴�恥�敺�迭��窄�憭U��</div> - - </section> + <template v-if="showWhenAppointmentHasClosed"> + <AppointmentClosedInfo :appointmentDetail="appointmentDetail" /> + </template> <InterviewMsg :isVisible.sync="isVisibleDialog" @@ -131,6 +123,28 @@ return this.appointmentDetail.communicateStatus === this.contactStatus.DONE || this.appointmentDetail.communicateStatus === this.contactStatus.CLOSE || this.appointmentDetail.communicateStatus === this.contactStatus.CANCEL; + } + + get displayClosedType(): string { + let closedType = '��漱'; + switch (this.appointmentDetail.communicateStatus) { + case this.contactStatus.CLOSE: + closedType = '���漱'; + break; + case this.contactStatus.CANCEL: + closedType = '����'; + break; + } + return closedType; + } + + get hopeContactTimeList(): any[] { + return this.appointmentDetail.hopeContactTime.split("','") + } + + getHopeContactTimeContent(hopeContactTimeString: string): string[] { + const result = hopeContactTimeString.replace("'", '').split('��'); + return result; } } </script> @@ -195,9 +209,17 @@ display: flex; } .client-detail-demand__demand-list-label { - @extend .mr-10; - @extend .mdTxt; @extend .mb-10; + @extend .mdTxt; + @extend .mr-10; + color : $DARK_BLUE; + flex-basis: auto; + min-width : 40px; + } + .client-detail-demand__demand-list-content { + text-align: justify; + text-justify: auto; + word-break: break-all; } } .client-detail-action { @@ -219,5 +241,8 @@ justify-content: space-between; flex: 1; } +.hope-contact-time__line { + border-bottom: 1px solid #CCCCCC; +} </style> diff --git a/PAMapp/pages/myAppointmentList/closedList.vue b/PAMapp/pages/myAppointmentList/closedList.vue index 9d7957f..b050cab 100644 --- a/PAMapp/pages/myAppointmentList/closedList.vue +++ b/PAMapp/pages/myAppointmentList/closedList.vue @@ -34,7 +34,7 @@ </template> <script lang="ts"> -import { Vue, Component, Watch, State, namespace } from 'nuxt-property-decorator'; +import { Vue, Component, Watch, namespace } from 'nuxt-property-decorator'; import { Appointment } from '~/shared/models/appointment.model'; import { ContactStatus } from '~/shared/models/enum/contact-status'; @@ -52,14 +52,16 @@ @localStorage.Getter currentAppointmentIdFromMsg!: string; - closedItemSum = 0; - closedList: Appointment[] = []; contactStatus= ContactStatus; - currentPage : number = 1; - doneItemSum = 0; + + closedItemSum = 0; + currentPage = 1; + doneItemSum = 0; + itemSum = 0; + keyWord = ''; + + closedList: Appointment[] = []; filterList : Appointment[] = []; - itemSum = 0; - keyWord : string = ''; pageList : Appointment[] = []; selectedClosedCategory: 'all' | 'done' | 'closed' = 'all'; diff --git a/PAMapp/plugins/filters/appointment-fail-reason.filter.ts b/PAMapp/plugins/filters/appointment-fail-reason.filter.ts new file mode 100644 index 0000000..7df365f --- /dev/null +++ b/PAMapp/plugins/filters/appointment-fail-reason.filter.ts @@ -0,0 +1,16 @@ +import Vue from 'vue' +import { appointmentFailReasonList } from '~/shared/const/appointment-fail-reason-list'; + +Vue.filter('toFailReasonLabel', (value: string): string => { + + if (!value || typeof value !== 'string') { + return '--'; + }; + + let failReasonLabel = {}; + appointmentFailReasonList.forEach((failReason) => { + failReasonLabel[failReason.value] = failReason.key; + }); + + return failReasonLabel[value]; +}) diff --git a/PAMapp/shared/const/appointment-fail-reason-list.ts b/PAMapp/shared/const/appointment-fail-reason-list.ts new file mode 100644 index 0000000..3e8f309 --- /dev/null +++ b/PAMapp/shared/const/appointment-fail-reason-list.ts @@ -0,0 +1,26 @@ +export const appointmentFailReasonList = [ + { + key: '�瘜蝜怠恥�', + value: 'cannot_to_contact_customer' + }, + { + key: '�蝝垣閰�', + value: 'only_consultation' + }, + { + key: '�������', + value: 'no_suitable_commodity' + }, + { + key: '�靽���- 擃��瓷���璆�', + value: 'prohibited_factors' + }, + { + key: '蝬����', + value: 'economy' + }, + { + key: '�隞�', + value: 'other' + }, +]; diff --git a/PAMapp/shared/models/appointment.model.ts b/PAMapp/shared/models/appointment.model.ts index 3488334..9a66ebe 100644 --- a/PAMapp/shared/models/appointment.model.ts +++ b/PAMapp/shared/models/appointment.model.ts @@ -14,31 +14,43 @@ } export interface Appointment { - age : string; - agentNo : string; - appointmentDate : string; - appointmentMemoList: AppointmentMemoInfo[] - communicateStatus : ContactStatus; - consultantReadTime : string; - consultantViewTime : string; - contactTime : string; - contactType : string; - customerId : number; - email : string; - gender : string; - hopeContactTime : string; - id : number; - interviewRecordDTOs: InterviewRecord[]; - job : string; - lastModifiedDate : string; - name : string; - otherRequirement : string; - phone : string; - requirement : string; - satisfactionScore : number; + age : string; + agentNo : string; + appointmentClosedInfo: AppointmentClosedInfo; + appointmentDate : string; + appointmentMemoList : AppointmentMemoInfo[] appointmentNoticeLogs: NoticeLogs[]; + communicateStatus : ContactStatus; + consultantReadTime : string; + consultantViewTime : string; + contactTime : string; + contactType : string; + customerId : number; + email : string; + gender : string; + hopeContactTime : string; + id : number; + interviewRecordDTOs : InterviewRecord[]; + job : string; + lastModifiedDate : string; + name : string; + otherRequirement : string; + phone : string; + requirement : string; + satisfactionScore : number; }; +export interface AppointmentClosedInfo { + appointmentId : number; + closedOtherReason : string; + closedReason : string; + id : number; + planCode : string; + policyEntryDate : string; + policyholderIdentityId: string; + remark : string; +} + export interface AppointmentMemoInfo { appointmentId: number; content : string; diff --git a/PAMapp/shared/services/appointment.service.ts b/PAMapp/shared/services/appointment.service.ts index dcba492..9f07fe9 100644 --- a/PAMapp/shared/services/appointment.service.ts +++ b/PAMapp/shared/services/appointment.service.ts @@ -55,7 +55,7 @@ return http.delete(`/appointment/memo/${appointmentMemoId}`) } - // ���蝯�� + // ���蝯��, ��蝯��敦 async closeAppointment(appointmentInfo: ToDoneAppointment | ToCloseAppointment) { return http.post(`/appointment/close`, appointmentInfo).then((res) => res.data); } -- Gitblit v1.8.0