保誠-保戶業務員媒合平台
Mila
2022-01-20 1d6d2d14200ed9432347ef8013e3fc117fa2161b
Merge branch 'master' into Phase3
修改13個檔案
新增1個檔案
修改1個檔案名稱
599 ■■■■ 已變更過的檔案
PAMapp/assets/images/logo.png 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/images/taiwan-logo.png 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/scss/utilities/_heading.scss 9 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/scss/vendors/elementUI/_dialog.scss 35 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/scss/vendors/elementUI/_rate.scss 3 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/Consultant/ConsultantCard.vue 57 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/Consultant/ConsultantSwiper.vue 15 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/NavBar.vue 6 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/QuickFilter/QuickFilterSelector.vue 2 ●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/middleware/errorRoute.ts 5 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/middleware/getUrlQuery.ts 12 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/nuxt.config.js 2 ●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/pages/index.vue 182 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/pages/questionnaire/_agentNo.vue 256 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/store/localStorage.ts 15 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/images/logo.png

PAMapp/assets/images/taiwan-logo.png

PAMapp/assets/scss/utilities/_heading.scss
@@ -22,10 +22,6 @@
  font-weight: bold;
}
.lighter {
  font-weight: lighter;
}
.smTxt_bold {
  font-size: 16px;
  font-weight: bold;
@@ -49,6 +45,11 @@
.text--regular {
  font-weight: normal !important;
  font-weight: lighter;
}
.text--lighter {
  font-weight: lighter;
}
.text--center {
PAMapp/assets/scss/vendors/elementUI/_dialog.scss
@@ -35,3 +35,38 @@
    }
  }
}
.pam-dialog-review {
  .review-content {
    display: flex;
    flex-direction: row;
    justify-content: space-evenly;
  }
  .review-text {
    width: 60%;
    line-height: 28px;
    @extend .p;
    @extend .text--lighter;
  }
  .review-score {
    display: flex;
    justify-content: center;
    margin-bottom: 30px;
  }
  .review-btn {
    display: flex;
    justify-content: center;
  }
}
.pam-dialog-reserved {
  .reserved-info {
    font-size: 20px;
    overflow-y:scroll;
    height: 400px;
  }
  .reserved-btn {
    display: flex;
    justify-content: center;
  }
}
PAMapp/assets/scss/vendors/elementUI/_rate.scss
@@ -1,6 +1,5 @@
.pam-quickFilter-rate {
.pam-rate {
  height: auto;
  margin-top: 30px;
  display: flex;
  justify-content: center;
  @extend .fix-chrome-click--issue;
PAMapp/components/Consultant/ConsultantCard.vue
@@ -33,17 +33,17 @@
                    v-if="showRemoveBtn"
                    @click="removeAgent"
                >移除</div>
                <div
                    v-if="notScoreAppointmentYet"
                    class="text--primary text--underline cursor--pointer xsTxt text--bold"
                    @click="reviewsBtn = true">給予滿意度評分</div>
            </el-col>
            <el-col class="flex_column" :xs="9" :sm="6">
                <el-button
                    class="smTxt_bold outline_btn"
                    @click="reserveCommunication"
                    @click="reservedOrShowAppointmentInfo"
                    :class="actionBtnStyle"
                >{{ actionBtnLabel }}</el-button>
                <div
                    v-if="notScoreAppointmentYet"
                    class="text--primary mt-10 text--center text--underline cursor--pointer"
                    @click="reviewsBtn = true">給予滿意度評分</div>
                <div class="updateTime mt-10">
                    {{ agentInfo.updateTime | formatDate }}
                </div>
@@ -53,12 +53,12 @@
        <Ui-Dialog
            :isVisible.sync="isVisibleDialog"
            :width="width"
            class="pam-myDemand-dialog"
            class="pam-myDemand-dialog pam-dialog-reserved"
        >
            <div v-if="appointmentDetail">
                <h5 class="subTitle text--center mb-30">預約成功</h5>
                <p class="smTxt">{{appointmentDetail.appointmentDate | formatDate}}</p>
                <div class="dialogInfo">
                <div class="reserved-info">
                    <p>姓名:{{appointmentDetail.name}}</p>
                    <p>電話:{{appointmentDetail.phone}}</p>
                    <p>Email:{{appointmentDetail.email}}</p>
@@ -80,7 +80,7 @@
                    </div>
                </div>
                <div v-if="notScoreAppointmentYet" class="dialogInfo-btn">
                <div v-if="notScoreAppointmentYet" class="reserved-btn">
                    <el-button type="primary"
                        @click.native="reviewsBtn = true">給予滿意度評分</el-button>
                </div>
@@ -91,14 +91,24 @@
                </div>
            </div>
        </Ui-Dialog>
        <PopUpFrame :isOpen.sync="reviewsBtn">
            <div class="mdTxt">
        <PopUpFrame :isOpen.sync="reviewsBtn" class="reviewDialog-content">
            <div class="mdTxt pam-dialog-review">
                ä¿éšªé¡§å•æ»¿æ„åº¦
                <span class="hint">選取星星</span>
                <div class="dialogInfo-score">
                    <el-rate v-model="inputScore" class="pam-quickFilter-rate"></el-rate>
                <div class="mt-30 review-content">
                    <UiAvatar :size="80" :agentNo="agentInfo.agentNo"></UiAvatar>
                    <div class="review-text">對於顧問
                        <span class="text--primary">{{agentInfo.name}}</span>
                        çš„æ•´é«”服務,您給予幾顆星評價?
                    </div>
                </div>
                <div class="dialogInfo-btn">
                <div class="review-score">
                    <el-rate v-model="inputScore" class="pam-rate mt-30"></el-rate>
                </div>
                <div class="review-btn">
                    <el-button
                        type="primary"
                        :disabled="!inputScore"
@@ -172,7 +182,6 @@
    hideReviews = hideReviews;
    isConfirmPopup = false;
    appointmentDetail: any = {
        age               : '',
        agentNo           : '',
@@ -203,7 +212,7 @@
    }
    get isAppointment(): boolean {
      return !!this.agentInfo['appointmentStatus'];;
      return !!this.agentInfo['appointmentStatus'];
    }
    get latestReservedAppointment(): Appointment {
@@ -290,7 +299,7 @@
    @Action
    storeConsultantList!: () => void;
    reserveCommunication() {
    reservedOrShowAppointmentInfo() {
      const isAppointment = !!this.agentInfo['appointmentStatus'];
      const contactStatus = this.agentInfo.contactStatus;
        if (!isAppointment && (!contactStatus || contactStatus === 'picked')) {
@@ -442,20 +451,4 @@
        flex-direction: column;
        justify-content: space-between;
    }
    .dialogInfo {
        font-size: 20px;
        overflow-y:scroll;
        height: 400px;
    }
    .dialogInfo-btn{
        display: flex;
        justify-content: center;
    }
    .dialogInfo-score{
        display: flex;
        justify-content: center;
        margin-bottom: 50px;
    }
</style>
PAMapp/components/Consultant/ConsultantSwiper.vue
@@ -25,8 +25,12 @@
          </div>
        </swiper-slide>
        <div class="swiper-button-prev" slot="button-prev"></div>
        <div class="swiper-button-next" slot="button-next"></div>
        <div class="swiper-button-prev" slot="button-prev">
          <i class="icon-left"></i>
        </div>
        <div class="swiper-button-next" slot="button-next">
          <i class="icon-right"></i>
        </div>
    </swiper>
</div>
</template>
@@ -93,9 +97,12 @@
    height: 100%;
    &:after {
      display: none;
    }
    .icon-right,.icon-left {
      font-size: 20px;
      font-weight: bold;
      color: #707A81;
      color: $CORAL;
    }
    &.swiper-button-disabled {
PAMapp/components/NavBar.vue
@@ -216,11 +216,11 @@
      height: $DESKTOP_NAV_BAR;
      .pam-header__logo {
        width: 180px;
        height: 100%;
        width: 160px;
        height: 70px;
        margin: 0;
        background-image: url('~/assets/images/logo.png');
        background-size: cover;
        background-size: contain;
        background-repeat: no-repeat;
        background-position: center;
      }
PAMapp/components/QuickFilter/QuickFilterSelector.vue
@@ -71,7 +71,7 @@
        <div v-else>
            <el-rate
            v-if="!hideReviews"
                class="pam-quickFilter-rate"
                class="pam-rate mt-30"
                v-model="pickedItem.avgScore"
            ></el-rate>
        </div>
PAMapp/middleware/errorRoute.ts
File was renamed from PAMapp/middleware/errorRouteMiddleware.ts
@@ -1,6 +1,7 @@
import { Middleware } from '@nuxt/types';
const errorRouteMiddleware: Middleware = (context) => {
const errorRoute: Middleware = (context) => {
  if (!context.route.name) {
    const isAdminLogin = context.store.getters['localStorage/isAdminLogin'];
    if (isAdminLogin) {
@@ -11,4 +12,4 @@
  }
}
export default errorRouteMiddleware
export default errorRoute;
PAMapp/middleware/getUrlQuery.ts
¤ñ¹ï·sÀÉ®×
@@ -0,0 +1,12 @@
import { Middleware } from '@nuxt/types';
const getUrlQuery: Middleware = (context) => {
  const currentRouteName = context.route.name;
  const satisfactionIdFromMsg = context.route.query.appointmentId;
  if (currentRouteName === 'index' && satisfactionIdFromMsg) {
    context.store.commit('localStorage/storageSatisfactionIdFromMsg', satisfactionIdFromMsg);
  }
}
export default getUrlQuery
PAMapp/nuxt.config.js
@@ -70,6 +70,6 @@
  },
  router: {
    base: process.env.ENV === 'uat' ? '/pam/' : '',
    middleware: 'errorRouteMiddleware'
    middleware: ['getUrlQuery', 'errorRoute']
  }
}
PAMapp/pages/index.vue
@@ -39,12 +39,82 @@
        <ConsultantSwiper :agents="recommendList"></ConsultantSwiper>
      </div>
    </div>
    <Ui-Dialog
        :isVisible.sync="isVisibleDialog"
        :width="width"
        class="pam-myDemand-dialog pam-dialog-reserved"
        @closeDialog="clearSatisfactionId"
      >
        <div v-if="appointmentDetail">
            <h5 class="subTitle text--center mb-30">預約成功</h5>
            <p class="smTxt">{{appointmentDetail.appointmentDate | formatDate}}</p>
            <div class="reserved-info">
                <p>姓名:{{appointmentDetail.name}}</p>
                <p>電話:{{appointmentDetail.phone}}</p>
                <p>Email:{{appointmentDetail.email}}</p>
                <p>性別:{{gender}}</p>
                <p>年齡:{{appointmentDetail.age | toAgeLabel }}</p>
                <p>職業:{{appointmentDetail.job}}</p>
                <p>需求:{{appointmentDetail.requirement.split(',').join('、')}}</p>
                <p
                    v-for="(item, index) in hopeContactTime"
                    :key="index"
                >連絡時段{{index + 1 | formatNumber}}:{{ item | formatHopeContactTime }}</p>
                <div v-if="appointmentDetail.satisfactionScore">
                    <div class="mdTxt mt-10 mb-10">滿意度</div>
                    <el-rate
                    :value="appointmentDetail.satisfactionScore"
                    class="pam-myDemand-dialog__rate"
                    disabled>
                    </el-rate>
                </div>
            </div>
            <div v-if="!appointmentDetail.satisfactionScore" class="reserved-btn">
                <el-button type="primary"
                    @click.native="reviewsBtn = true">給予滿意度評分</el-button>
            </div>
        </div>
      </Ui-Dialog>
      <PopUpFrame
        :isOpen.sync="reviewsBtn"
        @closePopUp="clearSatisfactionId"
      >
          <div class="mdTxt pam-dialog-review">
              ä¿éšªé¡§å•æ»¿æ„åº¦
              <span class="hint">選取星星</span>
              <div class="mt-30 review-content" v-if="agentInfo">
                  <UiAvatar :size="80" :agentNo="agentInfo.agentNo"></UiAvatar>
                  <div class="review-text">對於顧問
                      <span class="text--primary">{{agentInfo.name}}</span>
                      çš„æ•´é«”服務,您給予幾顆星評價?
                  </div>
              </div>
              <div class="review-score">
                  <el-rate v-model="inputScore" class="pam-rate mt-30"></el-rate>
              </div>
              <div class="review-btn">
                  <el-button
                      type="primary"
                      :disabled="!inputScore"
                      @click="userReviewsConsultants">送出</el-button>
              </div>
          </div>
      </PopUpFrame>
  </div>
</template>
<script lang="ts">
  import { Vue, Component, State, Action, Watch, namespace } from 'nuxt-property-decorator';
  import { Consultant } from '~/shared/models/consultant.model';
import { UserReviewsConsultantsParams } from '~/shared/models/reviews.model';
  import appointmentService from '~/shared/services/appointment.service';
import reviewsService from '~/shared/services/reviews.service';
  import UtilsService from '~/shared/services/utils.service';
  const localStorage = namespace('localStorage');
@@ -70,7 +140,54 @@
    @localStorage.Mutation
    storageClearRecommendConsultant!: () => void;
    @localStorage.Getter
    currentSatisfactionIdFromMsg!: string;
    @localStorage.Mutation
    storageClearSatisfactionIdFromMsg!: () => void;
    consultantList: Consultant[] = [];
    appointmentDetail: any = {
        age               : '',
        agentNo           : '',
        appointmentDate   : '',
        communicateStatus : '',
        consultantReadTime: null,
        consultantViewTime: null,
        contactTime       : '',
        contactType       : '',
        customerId        : 0,
        email             : '',
        gender            : '',
        hopeContactTime   : "",
        id                : 0,
        job               : "",
        lastModifiedDate  : '',
        name              : '',
        otherRequirement  : null,
        phone             : "",
        requirement       : '',
        satisfactionScore : 0,
    };
    isVisibleDialog = false;
    width = '';
    reviewsBtn = false;
    inputScore = 0;
    agentInfo: Consultant = {
      agentNo            : '',
      name               : '',
      img                : '',
      expertise          : [],
      avgScore           : 0,
      contactStatus      : '',
      createTime         : '',
      updateTime         : '',
      customerViewTime   : '',
      role               : '',
      seniority          : '',
      appointments       : []
    };
    //////////////////////////////////////////////////////////////////////
@@ -84,6 +201,10 @@
      this.storageClearRecommendConsultant();
    }
    destroyed() {
      this.clearSatisfactionId();
    }
    //////////////////////////////////////////////////////////////////////
    @Watch('myConsultantList')
@@ -91,13 +212,71 @@
      this.consultantList = (this.myConsultantList || [])
        .filter(item => item.contactStatus !== 'contacted')
        .map((item) => ({ ...item, formatDate: new Date(item.updateTime || item.createTime)}))
        .sort((preItem, nextItem) => +nextItem.formatDate - +preItem.formatDate)
        .sort((preItem, nextItem) => +nextItem.formatDate - +preItem.formatDate);
      if (this.currentSatisfactionIdFromMsg) {
        this.agentInfo = this.myConsultantList.filter(item => {
          const satisfactionIdIndex = item.appointments?.findIndex(i => i.id === +this.currentSatisfactionIdFromMsg);
          return satisfactionIdIndex !== undefined && satisfactionIdIndex > -1;
        })[0];
        if (this.agentInfo) {
          this.openAppointmentInfo();
        }
      }
    }
    private openAppointmentInfo() {
        appointmentService.getAppointmentDetail(+this.currentSatisfactionIdFromMsg).then(res => {
            this.appointmentDetail = res;
            this.width = UtilsService.isMobileDevice() ? '80%' : '';
            this.isVisibleDialog = true;
            if (!this.appointmentDetail.satisfactionScore) {
              setTimeout(() => {
                this.reviewsBtn = true;
              }, 500)
            }
        });
    }
    //////////////////////////////////////////////////////////////////////
    navigateToRoute(path: string): void {
      this.$router.push(path);
    }
    userReviewsConsultants() {
      const reviewParams: UserReviewsConsultantsParams = {
            appointmentId: this.appointmentDetail.id,
            score: this.inputScore,
        }
        this.appointmentDetail.satisfactionScore = this.inputScore;
        reviewsService.userReviewsConsultants(reviewParams).then((res) => {
            this.reviewsBtn = false;
        });
    }
    clearSatisfactionId() {
        console.log('close');
        this.$router.push({query: {}});
        this.storageClearSatisfactionIdFromMsg();
    }
    ///////////////////////////////////////////////////////////////////////////////
    get gender() {
        if (this.appointmentDetail.gender) {
            return this.appointmentDetail.gender === 'male' ? '男性' : '女性';
        }
        return ''
    }
    get hopeContactTime() {
        const contactList = this.appointmentDetail.hopeContactTime
            .split("'").map((item: any) => item.slice(0, item.length));
        return contactList.filter((item: any) => !!item && item !== ",")
    }
  }
@@ -182,5 +361,4 @@
      max-width: 335px;
    }
  }
</style>
PAMapp/pages/questionnaire/_agentNo.vue
@@ -155,10 +155,17 @@
  const roleStorage = namespace('localStorage');
  @Component
  export default class Questionnaire extends Vue {
    @State('myConsultantList') myConsultantList!: Consultant[];
    @Action storeConsultantList!: () => Promise<number>;
    @roleStorage.Getter isUserLogin!:boolean;
    @roleStorage.State recommendConsultantItem!:string;
    @State('myConsultantList')
    myConsultantList!: Consultant[];
    @Action
    storeConsultantList!: () => Promise<number>;
    @roleStorage.Getter
    isUserLogin!:boolean;
    @roleStorage.State
    recommendConsultantItem!:string;
    genderOptions=[
      {
@@ -279,6 +286,8 @@
    appointmentId = 0;
    appointmentTime = '';
    ////////////////////////////////////////////////////////////////////////////
    beforeRouteEnter(to: any, from: any, next: any) {
      next(vm => {
        const isUserLogin = authService.isUserLogin();
@@ -293,13 +302,10 @@
      })
    }
    async fetch() {
      if (authService.isUserLogin()) {
        await this.storeConsultantList();
      };
    }
    mounted(): void {
      if (authService.isUserLogin()) {
        this.storeConsultantList();
      };
      this.setMyRequest();
    }
@@ -328,6 +334,121 @@
      }
    }
    ////////////////////////////////////////////////////////////////////////////
    @Watch('myConsultantList')
    onMyConsultantListChange() {
      if (authService.isUserLogin() && this.myConsultantList.length > 0) {
          const editAppointment = this.getLatestReserved(this.$route.params.agentNo);
          if (editAppointment && editAppointment.agentNo) {
            this.myRequest = JSON.parse(JSON.stringify(editAppointment));
            if (!this.$route.query || this.$route.query.edit !== 'true') {
              this.isEditPopup = true;
            }
            this.isEditBtn = true;
          }
      }
    }
    private getLatestReserved(agentNo) {
      const agentInfo = this.myConsultantList.filter(item => item.agentNo === agentNo);
      const appointmentInfo = agentInfo.length > 0 && agentInfo[0].appointments
        ? agentInfo[0].appointments!
              .filter((appointment) => appointment.communicateStatus !== 'contacted')
              .map((reversedAppointment) => (
                { ...reversedAppointment,
                  sortDate: new Date(reversedAppointment.appointmentDate)
                }))
              .sort((preAppointment, nextAppointment) => +nextAppointment.sortDate - +preAppointment.sortDate)[0]
        : null;
      return this.getReservedData(appointmentInfo);
    }
    private getReservedData(appointmentInfo) {
      if (appointmentInfo) {
        const hopeContactTime = appointmentInfo!.hopeContactTime.split("'")
              .filter(item => item && item !== ',');
        this.getAppointmentId(appointmentInfo);
        return {
            ...appointmentInfo,
            hopeContactTime: hopeContactTime.map(item => {
                const info = item.split('、');
                return {
                    selectWeekOptions: info[0].split(','),
                    selectTimesOptions: info[1].split(',')
                }
            }),
            requirement: appointmentInfo.requirement.split(',')
          }
      } else {
        return null;
      }
    }
    private getAppointmentId(appointmentInfo) {
      this.appointmentId = appointmentInfo.id;
      this.appointmentTime = appointmentInfo.lastModifiedDate
                  ? appointmentInfo.lastModifiedDate
                  : appointmentInfo.appointmentDate;
    }
    ////////////////////////////////////////////////////////////////////////////
    sentDemand() {
      if (this.isEditBtn) {
        this.editAppointmentDemand();
      } else {
        queryConsultantService.addFavoriteConsultant([this.$route.params.agentNo]).then(res => this.sentAppointmentDemand());
      }
    }
    private editAppointmentDemand() {
      const info = {
          ...this.myRequest,
          requirement: _.map(this.myRequest.requirement,o=>o).toString(),
          hopeContactTime: this.myRequest.phone && this.phoneValid ? this.getHopeContactTime() :'',
          id: this.appointmentId,
          otherRequirement: null
        }
      appointmentService.editAppointment(info).then(res => {
        this.sendReserve = true;
        this.myRequest.hopeContactTime = [];
        setRequestsToStorage(this.myRequest);
      });
    }
    private sentAppointmentDemand() {
        const data: AppointmentParams = {
          ...this.myRequest,
          requirement: _.map(this.myRequest.requirement,o=>o).toString(),
          hopeContactTime: this.myRequest.phone && this.phoneValid ? this.getHopeContactTime() :'',
          agentNo: this.$route.params.agentNo
        };
        queryConsultantService.appointmentDemand(data).then(res => {
            this.sendReserve = true;
            this.myRequest.hopeContactTime = [];
            setRequestsToStorage(this.myRequest);
        });
    }
    private getHopeContactTime() {
        const selectedHopeContactTime = this.myRequest.hopeContactTime.filter((i) => i.selectWeekOptions?.length && i.selectTimesOptions?.length);
        return selectedHopeContactTime.map(i => {
            return `'${i.selectWeekOptions}、${i.selectTimesOptions}'`}
        ).toString();
    }
    closeReservePopUp() {
        this.sendReserve = false;
        this.$router.push('/')
    }
    ////////////////////////////////////////////////////////////////////////////
    get phoneValid(): boolean {
      const rule = /^09[0-9]{8}$/;
      return this.myRequest.phone
@@ -350,121 +471,6 @@
      return this.myRequest.hopeContactTime[0]?.selectWeekOptions.length >0 && this.myRequest.hopeContactTime[0]?.selectTimesOptions.length >0;
    }
    sentDemand() {
      if (this.isEditBtn) {
        this.sentEditAppointmentDemand();
      } else {
        queryConsultantService.addFavoriteConsultant([this.$route.params.agentNo]).then(res => this.sentAppointmentDemand());
      }
    }
    private sentAppointmentDemand() {
        const data: AppointmentParams = {
          ...this.myRequest,
          requirement: _.map(this.myRequest.requirement,o=>o).toString(),
          hopeContactTime: this.myRequest.phone && this.phoneValid ? this.getHopeContactTime() :'',
          agentNo: this.$route.params.agentNo
        };
        queryConsultantService.appointmentDemand(data).then(res => {
            this.sendReserve = true;
            this.myRequest.hopeContactTime = [];
            setRequestsToStorage(this.myRequest);
        });
    }
    private sentEditAppointmentDemand() {
      const info = {
          ...this.myRequest,
          requirement: _.map(this.myRequest.requirement,o=>o).toString(),
          hopeContactTime: this.myRequest.phone && this.phoneValid ? this.getHopeContactTime() :'',
          id: this.appointmentId,
          otherRequirement: null
        }
        appointmentService.editAppointment(info).then(res => {
          this.sendReserve = true;
          this.myRequest.hopeContactTime = [];
          setRequestsToStorage(this.myRequest);
        });
    }
    getHopeContactTime() {
        const selectedHopeContactTime = this.myRequest.hopeContactTime.filter((i) => i.selectWeekOptions?.length && i.selectTimesOptions?.length);
        return selectedHopeContactTime.map(i => {
            return `'${i.selectWeekOptions}、${i.selectTimesOptions}'`}
        ).toString();
    }
    closeReservePopUp() {
        this.sendReserve = false;
        this.$router.push('/')
    }
    private getLatestReserved(agentNo) {
      const agentInfo = this.myConsultantList.filter(item => item.agentNo === agentNo);
      const appointmentInfo = agentInfo.length > 0 && agentInfo[0].appointments
        ? agentInfo[0].appointments!
              .filter((appointment) => appointment.communicateStatus !== 'contacted')
              .map((reversedAppointment) => {
                return {
                  ...reversedAppointment,
                  sortDate: new Date(reversedAppointment.appointmentDate)
                }
              })
              .sort((preAppointment, nextAppointment) => +nextAppointment.sortDate - +preAppointment.sortDate)[0]
        : null;
      return this.getReservedData(appointmentInfo);
    }
    private getReservedData(appointmentInfo) {
      if (appointmentInfo) {
        const hopeContactTime = appointmentInfo!.hopeContactTime.split("'")
              .filter(item => item && item !== ',');
        this.getAppointmentId(appointmentInfo);
        return {
            age: appointmentInfo.age,
            agentNo: appointmentInfo.agentNo,
            contactType: appointmentInfo.contactType,
            email: appointmentInfo.email || '',
            gender: appointmentInfo.gender,
            hopeContactTime: hopeContactTime.map(item => {
                const info = item.split('、');
                return {
                    selectWeekOptions: info[0].split(','),
                    selectTimesOptions: info[1].split(',')
                }
            }),
            job: appointmentInfo.job,
            phone: appointmentInfo.phone || '',
            requirement: appointmentInfo.requirement.split(',')
          }
      } else {
        return null;
      }
    }
    private getAppointmentId(appointmentInfo) {
      this.appointmentId = appointmentInfo.id;
      this.appointmentTime = appointmentInfo.lastModifiedDate
                  ? appointmentInfo.lastModifiedDate
                  : appointmentInfo.appointmentDate;
    }
    @Watch('myConsultantList') onMyConsultantListChange() {
      if (authService.isUserLogin() && this.myConsultantList.length > 0) {
          const editAppointment = this.getLatestReserved(this.$route.params.agentNo);
          if (editAppointment && editAppointment.agentNo) {
            this.myRequest = JSON.parse(JSON.stringify(editAppointment));
            if (!this.$route.query || this.$route.query.edit !== 'true') {
              this.isEditPopup = true;
            }
            this.isEditBtn = true;
            return;
          }
      }
    }
  }
</script>
PAMapp/store/localStorage.ts
@@ -9,6 +9,7 @@
  quickFilterSelectedItem = localStorage.getItem('quickFilter');
  recommendConsultantItem = localStorage.getItem('recommendConsultantItem');
  appointmentIdFromMsg = localStorage.getItem('appointmentIdFromMsg');
  satisfactionIdFromMsg = localStorage.getItem('satisfactionIdFromMsg');
  get idToken(): string|null {
    return this.id_token;
@@ -36,6 +37,10 @@
  get currentAppointmentIdFromMsg(): string|null {
    return this.appointmentIdFromMsg;
  }
  get currentSatisfactionIdFromMsg(): string|null {
    return this.satisfactionIdFromMsg;
  }
  @Mutation storageIdToken(token: string): void {
@@ -68,6 +73,11 @@
    this.appointmentIdFromMsg = localStorage.getItem('appointmentIdFromMsg');
  }
  @Mutation storageSatisfactionIdFromMsg(id: string) {
    localStorage.setItem('satisfactionIdFromMsg', id);
    this.satisfactionIdFromMsg = localStorage.getItem('satisfactionIdFromMsg');
  }
  @Mutation storageClear(): void {
    localStorage.removeItem('myRequests');
    localStorage.removeItem('userInfo');
@@ -97,6 +107,11 @@
    this.appointmentIdFromMsg = localStorage.getItem('appointmentIdFromMsg');
  }
  @Mutation storageClearSatisfactionIdFromMsg() {
    localStorage.removeItem('satisfactionIdFromMsg');
    this.appointmentIdFromMsg = localStorage.getItem('satisfactionIdFromMsg');
  }
  @Action actionStorageClear(): void {
    this.context.commit("storageClear");
  }