保誠-保戶業務員媒合平台
Mila
2022-01-22 c047a3336ff1efc7d21edee6f0c8811264eebae7
update: TODO#134222/134105 通知小鈴鐺/取得待評分的滿意度清單, 串接api
修改9個檔案
235 ■■■■ 已變更過的檔案
PAMapp/components/NavBar.vue 48 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/ReviewRecords/ReviewRecords.vue 10 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/pages/notification/index.vue 43 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/pages/record/index.vue 15 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/pages/satisfactionList.vue 51 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/pages/userReviewsRecord/index.vue 13 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/shared/models/reviews.model.ts 17 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/shared/services/reviews.service.ts 7 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/store/index.ts 31 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/NavBar.vue
@@ -8,7 +8,7 @@
    </div>
    <div class="pam-header__action-bar">
      <i
        v-if="currentRole"
        v-if="isShowNotification"
        class="icon-bell text--dark-blue cursor--pointer fix-chrome-click--issue"
        @click="$router.push('/notification')"
      ></i>
@@ -49,9 +49,11 @@
<script lang="ts">
  import { Vue, Component } from 'vue-property-decorator';
  import { namespace } from 'nuxt-property-decorator';
  import { Action, namespace, State, Watch } from 'nuxt-property-decorator';
  import { Role } from '~/shared/models/enum/Role';
  import * as _ from 'lodash';
  import { NotificationList } from '~/shared/models/reviews.model';
  import { AppointmentLog } from '~/shared/models/appointment.model';
  const roleStorage = namespace('localStorage');
  @Component
@@ -71,6 +73,21 @@
    @roleStorage.Getter
    isAdminLogin!: boolean;
    @roleStorage.Getter
    isUserLogin!: boolean;
    @Action
    storeMyPersonalNotification!: () => void;
    @State
    notificationList!: NotificationList[];
    @Action
    storeMyAppointmentReviewLog!: () => void;
    @State
    unReviewLogList!: AppointmentLog[];
    isOpenDropdown = false;
@@ -123,6 +140,24 @@
    //////////////////////////////////////////////////////////////////////
    @Watch('$route', {immediate: true})
    onRouterChange() {
        this.getNotificationAndReviewLog();
    }
    private getNotificationAndReviewLog() {
      if (this.isUserLogin) {
        this.storeMyPersonalNotification();
        this.storeMyAppointmentReviewLog();
      }
      if (this.isAdminLogin) {
        this.storeMyPersonalNotification();
      }
    }
    //////////////////////////////////////////////////////////////////////
    routerNavigateTo(url: string): void {
      (this.$refs.dropdown as any).hide();
      _.isEqual(url,'')
@@ -144,6 +179,15 @@
      return this.idToken && this.currentRole ? (this.currentRole as Role): Role.NOT_LOGIN;
    }
    get isShowNotification() {
      if (this.isUserLogin) {
        return this.notificationList.length || this.unReviewLogList.length;
      }
      if (this.isAdminLogin) {
        return this.notificationList.length
      }
    }
  }
</script>
PAMapp/components/ReviewRecords/ReviewRecords.vue
@@ -11,11 +11,11 @@
    </section>
    <div class="user-reviews-page">
      <template v-if="myAppointmentReviewLogList.length">
      <template v-if="reviewLogList.length">
        <section class="user-reviews-content">
            <div
                class="user-reviews-card"
                v-for="(appointmentLog, index) in myAppointmentReviewLogList"
                v-for="(appointmentLog, index) in reviewLogList"
                :key="index">
                <div class="user-reviews-card-content" v-if="isUserLogin">
                    您對<span class="mdTxt">{{ ` ${appointmentLog.agentName} ` }}</span>做了 <UiReviewScore :score="appointmentLog.score" /> 評價!
@@ -55,17 +55,19 @@
</template>
<script lang="ts">
import { AppointmentLog } from '~/shared/models/appointment.model';
import { Vue, Component, Prop } from 'nuxt-property-decorator';
import { Vue, Component, Prop, Watch } from 'nuxt-property-decorator';
import authService from '~/shared/services/auth.service';
@Component
export default  class ReviewRecords extends Vue{
    @Prop()
    myAppointmentReviewLogList!: AppointmentLog[];
    reviewLogList!: AppointmentLog[];
    isUserLogin = false;
    //////////////////////////////////////////////////////////////////////
    mounted() {
      this.isUserLogin = authService.isUserLogin();
    }
PAMapp/pages/notification/index.vue
@@ -3,7 +3,11 @@
        <div class="text--right mb-10" @click="showNotificationHint = true">
            <i class="satisfaction-icon icon-edit"></i>
        </div>
        <div class="satisfaction-banner my-10 cursor--pointer" @click="$router.push('/satisfactionList')">
        <div
            v-if="isUserLogin && unReviewLogList.length"
            class="satisfaction-banner my-10 cursor--pointer"
            @click="$router.push('/satisfactionList')"
        >
            <p class="satisfaction-text text--center">請填寫滿意度調查</p>
        </div>
        <el-row
@@ -14,7 +18,7 @@
            align="middle"
            class="notification-card"
        >
            <el-col class="unRead" :span="3"></el-col>
            <el-col class="unRead" :span="3" v-if="!item.readDate"></el-col>
            <el-col :span="18">
                <p class="text">{{item.content}}</p>
            </el-col>
@@ -22,13 +26,13 @@
                <div>
                    <UiDateFormat
                        class="date"
                        :date="item.date"
                        :date="item.createdDate"
                        onlyShowSection="DAY" />
                </div>
                <div>
                    <UiDateFormat
                        class="time"
                        :date="item.date"
                        :date="item.createdDate"
                        onlyShowSection="TIME" />
                </div>
@@ -54,22 +58,29 @@
</template>
<script lang="ts">
import { Component, Vue } from "nuxt-property-decorator";
import { Component, State, Vue } from "nuxt-property-decorator";
import { AppointmentLog } from "~/shared/models/appointment.model";
import { NotificationList } from "~/shared/models/reviews.model";
import authService from "~/shared/services/auth.service";
@Component
export default class Notification extends Vue {
    showNotificationHint = false;
    notificationList = [
        {
            content: '系統停機公告:10/19(五)22:30至10/21(日)20:00進行系統更新',
            date: '2022-01-05T04:18:05.249Z'
        },
        {
            content: '系統停機公告:10/19(五)22:30至10/21(日)20:00進行系統更新',
            date: '2022-01-05T04:18:05.249Z'
        }
    ]
    @State
    unReviewLogList!: AppointmentLog[];
    @State
    notificationList!: NotificationList[];
    showNotificationHint = false;
    isUserLogin = false;
    ////////////////////////////////////////////////////////////
    mounted() {
        this.isUserLogin = authService.isUserLogin();
    }
}
</script>
PAMapp/pages/record/index.vue
@@ -1,7 +1,7 @@
<template>
<div>
    <ReviewRecords
      :myAppointmentReviewLogList="myAppointmentReviewLogList"
      :reviewLogList="reviewLogList"
    ></ReviewRecords>
</div>
</template>
@@ -13,17 +13,8 @@
@Component
export default  class Reviews extends Vue{
    @State('myAppointmentReviewLogList')
    myAppointmentReviewLogList!: AppointmentLog[];
    @Action
    storeMyAppointmentReviewLog!: any;
    //////////////////////////////////////////////////////////////////////
    mounted() {
        this.storeMyAppointmentReviewLog();
    }
    @State('reviewLogList')
    reviewLogList!: AppointmentLog[];
}
</script>
PAMapp/pages/satisfactionList.vue
@@ -4,17 +4,17 @@
    <div class="pam-container">
      <div class="satisfaction-title">
        <span class="mdTxt">滿意度調查</span>
        <span class="ml-10 text--prudential_grey smTxt_bold">共 {{satisfactionList.length}} 筆</span>
        <span class="ml-10 text--prudential_grey smTxt_bold">共 {{mapUnReviewLogList.length}} 筆</span>
      </div>
      <div class="satisfaction-card" v-for="(item, index) in satisfactionList" :key="index">
      <div class="satisfaction-card" v-for="(item, index) in mapUnReviewLogList" :key="index">
        <div class="satisfaction-card-content">
          <UiAvatar :size="80" :agentNo="''"></UiAvatar>
          <UiAvatar :size="80" :agentNo="item.agentNo"></UiAvatar>
          <div class="satisfaction-card-text">對於顧問
              <span class="text--primary text--bold">{{item.agentName}}</span>
              的整體服務,您給予幾顆星評價?
          </div>
        </div>
        <el-rate v-model="item.score" class="pam-satisfaction-rate mt-10"></el-rate>
        <el-rate v-model="item.satisfaction" class="pam-satisfaction-rate mt-10"></el-rate>
      </div>
      <div class="text--center mt-30">
        <el-button type="primary" :disabled="isBtnDisabled">送出</el-button>
@@ -23,28 +23,47 @@
  </div>
</template>
<script>
import { Vue, Component } from 'nuxt-property-decorator';
<script lang="ts">
import { Vue, Component, Action, State, Watch } from 'nuxt-property-decorator';
import { AppointmentLog } from '~/shared/models/appointment.model';
@Component({
  layout: 'home'
})
export default class MySatisfactionList extends Vue {
  satisfactionList = [
    {
      agentName: '蔡美眉',
      score: 0
    },
    {
      agentName: '蔡美眉',
      score: 0
  @State
  unReviewLogList!: AppointmentLog[];
  mapUnReviewLogList: AppointmentReviewLog[] = [];
  ///////////////////////////////////////////////////////
  @Watch('unReviewLogList')
  onUnReviewLogListChange() {
    if (this.unReviewLogList.length) {
      this.mapUnReviewLogList = this.unReviewLogList.map(item => {
        return {
          ...item,
          satisfaction: 0
        }
      })
    }
  ]
  }
  ///////////////////////////////////////////////////////
  get isBtnDisabled() {
    return this.satisfactionList.findIndex(item => item.score > 0) === -1;
    if (this.mapUnReviewLogList.length) {
      return this.mapUnReviewLogList.findIndex(item => item.satisfaction > 0) === -1;
    }
    return false;
  }
}
interface AppointmentReviewLog extends AppointmentLog {
  satisfaction: number;
}
</script>
<style lang="scss" scoped>
PAMapp/pages/userReviewsRecord/index.vue
@@ -1,7 +1,7 @@
<template>
  <div>
    <ReviewRecords
      :myAppointmentReviewLogList="myAppointmentReviewLogList"
      :reviewLogList="reviewLogList"
    ></ReviewRecords>
  </div>
</template>
@@ -11,16 +11,9 @@
@Component
export default  class UserReviewsRecord extends Vue{
    @State('myAppointmentReviewLogList')
    myAppointmentReviewLogList!: AppointmentLog[];
    @Action
    storeMyAppointmentReviewLog!: any;
    //////////////////////////////////////////////////////////////////////
    mounted() {
      this.storeMyAppointmentReviewLog();
    }
    @State('reviewLogList')
    reviewLogList!: AppointmentLog[];
}
</script>
PAMapp/shared/models/reviews.model.ts
@@ -2,3 +2,20 @@
  appointmentId: number,
  score        : number,
}
export interface NotificationList {
  id: number;
  /** 標題 */
  title: string;
  /** 通知內容 */
  content: string;
  /** ACTIVITY(個人活動通知)、SYSTEM(系統通知) */
  notificationType: string;
  /** CUSTOMER(客戶)、CONSULTANT(顧問) */
  ownerRole: string;
  /** 登入者id */
  ownerId: number
  createdDate: string;
  /** 已讀時間 */
  readDate: string;
}
PAMapp/shared/services/reviews.service.ts
@@ -1,6 +1,6 @@
import { http } from "./httpClient";
import { UserReviewsConsultantsParams } from "../models/reviews.model";
import { NotificationList, UserReviewsConsultantsParams } from "../models/reviews.model";
import { AppointmentLog } from "../models/appointment.model";
class ReviewsService {
@@ -19,6 +19,11 @@
  sendSatisfactionToClient(appointmentId: number) {
    return http.post(`/consultant/sendSatisfactionToClient/${appointmentId}`).then((res) => res);
  }
  // 通知小鈴鐺
  getMyPersonalNotification(): Promise<NotificationList[]> {
    return http.get('/personal_notification/getMyPersonalNotification').then(res => res.data);
  }
}
export default new ReviewsService();
PAMapp/store/index.ts
@@ -7,6 +7,7 @@
import { getFavoriteFromStorage, setFavoriteToStorage } from '~/shared/storageConsultant';
import { AppointmentLog } from '~/shared/models/appointment.model';
import { AgentOfStrictQuery, StrictQueryParams } from '~/shared/models/strict-query.model';
import { NotificationList } from '~/shared/models/reviews.model';
@Module
export default class Store extends VuexModule {
@@ -14,7 +15,9 @@
    strictQueryList: AgentOfStrictQuery[] = [];
    myConsultantList: Consultant[] = [];
    myAppointmentReviewLogList: AppointmentLog[] = [];
    reviewLogList: AppointmentLog[] = [];
    unReviewLogList: AppointmentLog[] = [];
    notificationList: NotificationList[] = [];
    get isUserLogin() {
        return this.context.getters['localStorage/isUserLogin'];
@@ -36,8 +39,18 @@
    }
    @Mutation
    updateMyAppointmentReviewLog(data: AppointmentLog[]) {
        this.myAppointmentReviewLogList = data;
    updateReviewLog(data: AppointmentLog[]) {
        this.reviewLogList = data;
    }
    @Mutation
    updateUnReviewLog(data: AppointmentLog[]) {
        this.unReviewLogList = data;
    }
    @Mutation
    updateNotification(data: NotificationList[]) {
        this.notificationList = data;
    }
    @Action
@@ -118,7 +131,10 @@
                }
            });
            const sortedData = dataWithLatestDate.sort((a, b) => +b.compareDate - +a.compareDate);
            this.context.commit('updateMyAppointmentReviewLog', sortedData);
            const reviewLog = sortedData.filter(item => item.score);
            const unReviewLog = sortedData.filter(item => !item.score);
            this.context.commit('updateReviewLog', reviewLog);
            this.context.commit('updateUnReviewLog', unReviewLog);
        });
    }
@@ -131,4 +147,11 @@
        });
    }
    @Action
    storeMyPersonalNotification() {
        reviewsService.getMyPersonalNotification().then(data => {
            this.context.commit('updateNotification', data);
        })
    }
}