From 5730601f103ea285d129bf3d89acd649e86c114a Mon Sep 17 00:00:00 2001
From: Tomas <tomasysh@gmail.com>
Date: 星期三, 08 十二月 2021 10:17:44 +0800
Subject: [PATCH] separate vue files

---
 PAMapp/components/QuickFilter/QuickFilterSelector.vue                              |   11 
 PAMapp/pages/consultantLogin/index.vue                                             |  202 --
 PAMapp/pages/myAppointmentList/my-appointment.component.ts                         |   63 
 PAMapp/pages/quickFilter/quick-filter.component.ts                                 |  144 +
 PAMapp/pages/myConsultantList/my-consultant-list.component.ts                      |   28 
 PAMapp/pages/accountSetting/index.vue                                              |  255 --
 PAMapp/assets/ts/models/fast-query-params.model.ts                                 |    6 
 PAMapp/pages/myAppointmentList/appointmentList/appointment-list.component.ts       |   26 
 PAMapp/pages/myAppointmentList/my-appointment.component.scss                       |   26 
 PAMapp/pages/record/record.component.scss                                          |   44 
 PAMapp/pages/recommendConsultant/result/index.vue                                  |   88 
 PAMapp/pages/accountSetting/account-setting.component.scss                         |  118 +
 PAMapp/pages/myAppointmentList/appointmentList/index.vue                           |   29 
 PAMapp/pages/myConsultantList/my-consultant-list.component.scss                    |    0 
 PAMapp/pages/myConsultantList/consultantList/consultant-list.component.ts          |   16 
 PAMapp/assets/ts/models/agentInfo.model.ts                                         |   19 
 PAMapp/pages/questionnaire/_agentNo.vue                                            |  395 ----
 PAMapp/pages/login/login.component.ts                                              |  373 ++++
 PAMapp/assets/ts/models/enum/role.enum.ts                                          |    0 
 PAMapp/components/NavBar.vue                                                       |    9 
 PAMapp/pages/agentInfo/_agentNo.vue                                                |  124 -
 PAMapp/pages/quickFilter/quick-filter.component.scss                               |   52 
 PAMapp/pages/record/record.component.ts                                            |   23 
 PAMapp/assets/ts/models/selected.model.ts                                          |    4 
 PAMapp/pages/accountSetting/account-setting.component.ts                           |   98 +
 PAMapp/pages/myConsultantList/contactedList/contacted-list.component.ts            |   13 
 PAMapp/pages/recommendConsultant/recommend-consultant.component.ts                 |  183 +
 PAMapp/store/localStorage.ts                                                       |    2 
 PAMapp/pages/consultantLogin/consultant-login.component.scss                       |   77 
 PAMapp/pages/recommendConsultant/recommend-consultant.component.scss               |  291 +++
 PAMapp/pages/login/login.component.scss                                            |   97 +
 PAMapp/pages/login/index.vue                                                       |  474 -----
 PAMapp/pages/myAppointmentList/index.vue                                           |   45 
 PAMapp/pages/recommendConsultant/result/recommend-consultant-result.component.ts   |   32 
 PAMapp/pages/userReviews/user-reviews.component.scss                               |  103 +
 PAMapp/pages/myAppointmentList/contactedList/index.vue                             |   33 
 PAMapp/pages/myConsultantList/contactedList/contacted-list.component.scss          |    0 
 PAMapp/pages/myAppointmentList/contactedList/contacted-list.component.scss         |    0 
 PAMapp/pages/record/index.vue                                                      |   83 
 PAMapp/assets/ts/models/strict-query-dto.model.ts                                  |   11 
 PAMapp/pages/myAppointmentList/appointmentList/appointment-list.component.scss     |    0 
 PAMapp/assets/scss/utilities/_utilities.scss                                       |   12 
 PAMapp/assets/ts/models/enum/gender.enum.ts                                        |    2 
 PAMapp/pages/agentInfo/agent-info.component.ts                                     |   54 
 PAMapp/pages/userReviews/user-reviews.component.ts                                 |   43 
 PAMapp/pages/userReviews/index.vue                                                 |  171 -
 PAMapp/pages/recommendConsultant/result/recommend-consultant-result.component.scss |  114 +
 PAMapp/assets/ts/api/consultant.ts                                                 |    8 
 PAMapp/assets/ts/models/question-option.model.ts                                   |   12 
 PAMapp/pages/questionnaire/questionnaire.component.scss                            |  159 +
 PAMapp/pages/quickFilter/index.vue                                                 |  213 --
 PAMapp/pages/consultantLogin/consultant-login.component.ts                         |  103 +
 PAMapp/pages/myConsultantList/consultantList/index.vue                             |   18 
 PAMapp/pages/questionnaire/questionnaire.component.ts                              |  228 ++
 PAMapp/pages/myAppointmentList/contactedList/contacted-list.component.ts           |   34 
 PAMapp/pages/myConsultantList/consultantList/consultant-list.component.scss        |    0 
 PAMapp/components/BackActionBar.vue                                                |    2 
 /dev/null                                                                          |  113 -
 PAMapp/pages/agentInfo/agent-info.component.scss                                   |   48 
 PAMapp/pages/recommendConsultant/index.vue                                         |  493 -----
 PAMapp/assets/ts/models/reviews-item.model.ts                                      |    5 
 PAMapp/pages/myConsultantList/contactedList/contactedList.vue                      |   18 
 PAMapp/pages/myConsultantList/index.vue                                            |   41 
 63 files changed, 2,942 insertions(+), 2,546 deletions(-)

diff --git a/PAMapp/assets/scss/utilities/_utilities.scss b/PAMapp/assets/scss/utilities/_utilities.scss
index 877b5dc..aaa7494 100644
--- a/PAMapp/assets/scss/utilities/_utilities.scss
+++ b/PAMapp/assets/scss/utilities/_utilities.scss
@@ -13,6 +13,10 @@
   margin-top: 20px;
 }
 
+.mt-25 {
+  margin-top: 25px;
+}
+
 .mb-30 {
   margin-bottom: 30px;
 }
@@ -89,8 +93,16 @@
   padding: 20px 30px 40px 30px;
 }
 
+.w-55 {
+  width: 55% !important;
+}
+
 @for $fontSize from 12 through 45 {
   .fs-#{$fontSize} {
     font-size: #{$fontSize} + 'px';
   }
 }
+
+.position-r {
+  position: relative;
+}
diff --git a/PAMapp/assets/ts/api/consultant.ts b/PAMapp/assets/ts/api/consultant.ts
index a797075..768e0b7 100644
--- a/PAMapp/assets/ts/api/consultant.ts
+++ b/PAMapp/assets/ts/api/consultant.ts
@@ -5,6 +5,7 @@
 import _ from 'lodash';
 import { UserSetting } from '../models/account.model';
 import { Consultant } from '~/assets/ts/models/consultant.model';
+import { FastQueryParams } from '../models/fast-query-params.model';
 
 // 憿批恥��(TODO: OTP隤����� ���蝙�)
 export function login(user: any) {
@@ -131,13 +132,6 @@
         Authorization: 'Bearer ' + localStorage.getItem('id_token')
     }
     return service.post('/satisfaction/create', data ,{headers});
-}
-
-export interface FastQueryParams {
-    gender             : string,
-    communicationStyles: string[],
-    avgScore           : number,
-    status             : string
 }
 
 export interface AppointmentRequests {
diff --git a/PAMapp/assets/ts/models/agentInfo.model.ts b/PAMapp/assets/ts/models/agentInfo.model.ts
new file mode 100644
index 0000000..1db440e
--- /dev/null
+++ b/PAMapp/assets/ts/models/agentInfo.model.ts
@@ -0,0 +1,19 @@
+export interface AgentInfo {
+  name           : string;
+  agentNo        : string;
+  role           : string;
+  image          : string;
+  avgScore       : number;
+  title          : string;
+  phoneNumber    : string;
+  serveArea      : string;
+  companyAddress : string;
+  latestLoginTime: Date | null;
+  seniority      : string;
+  suitability    : number;
+  evaluation     : number;
+  expertiseList  : string[];
+  concept        : string;
+  experiences    : string[];
+  awards         : string;
+}
diff --git a/PAMapp/assets/ts/models/enum/Gender.ts b/PAMapp/assets/ts/models/enum/gender.enum.ts
similarity index 97%
rename from PAMapp/assets/ts/models/enum/Gender.ts
rename to PAMapp/assets/ts/models/enum/gender.enum.ts
index b9f84ed..126da1e 100644
--- a/PAMapp/assets/ts/models/enum/Gender.ts
+++ b/PAMapp/assets/ts/models/enum/gender.enum.ts
@@ -1,4 +1,4 @@
 export enum Gender{
   MALE="male",
   FEMALE="female",
-}
\ No newline at end of file
+}
diff --git a/PAMapp/assets/ts/models/enum/Role.ts b/PAMapp/assets/ts/models/enum/role.enum.ts
similarity index 100%
rename from PAMapp/assets/ts/models/enum/Role.ts
rename to PAMapp/assets/ts/models/enum/role.enum.ts
diff --git a/PAMapp/assets/ts/models/fast-query-params.model.ts b/PAMapp/assets/ts/models/fast-query-params.model.ts
new file mode 100644
index 0000000..01f8030
--- /dev/null
+++ b/PAMapp/assets/ts/models/fast-query-params.model.ts
@@ -0,0 +1,6 @@
+export interface FastQueryParams {
+  gender             : string,
+  communicationStyles: string[],
+  avgScore           : number,
+  status             : string
+}
diff --git a/PAMapp/assets/ts/models/question-option.model.ts b/PAMapp/assets/ts/models/question-option.model.ts
new file mode 100644
index 0000000..356674d
--- /dev/null
+++ b/PAMapp/assets/ts/models/question-option.model.ts
@@ -0,0 +1,12 @@
+export interface QuestionOption {
+    title: string;
+    detail: Detail[];
+    type: string;
+    name: string;
+}
+
+interface Detail {
+    value: string;
+    name?: string;
+    className: string;
+}
diff --git a/PAMapp/assets/ts/models/reviews-item.model.ts b/PAMapp/assets/ts/models/reviews-item.model.ts
new file mode 100644
index 0000000..db0bafe
--- /dev/null
+++ b/PAMapp/assets/ts/models/reviews-item.model.ts
@@ -0,0 +1,5 @@
+export interface ReviewsItem {
+  avatar  : any;
+  name    : string;
+  avgScore: number;
+}
diff --git a/PAMapp/assets/ts/models/selected.model.ts b/PAMapp/assets/ts/models/selected.model.ts
new file mode 100644
index 0000000..ee3bf1a
--- /dev/null
+++ b/PAMapp/assets/ts/models/selected.model.ts
@@ -0,0 +1,4 @@
+export interface Selected {
+  option: string;
+  value: any;
+}
diff --git a/PAMapp/assets/ts/models/strict-query-dto.model.ts b/PAMapp/assets/ts/models/strict-query-dto.model.ts
new file mode 100644
index 0000000..102e2af
--- /dev/null
+++ b/PAMapp/assets/ts/models/strict-query-dto.model.ts
@@ -0,0 +1,11 @@
+export interface StrictQueryDto {
+  gender          : string,
+  area            : string,
+  status          : string,
+  requirements    : string[],
+  otherRequirement: string,
+  seniority       : string,
+  avgScore        : number,
+  popularTags     : string[],
+  otherPopularTags: string
+}
diff --git a/PAMapp/components/BackActionBar.vue b/PAMapp/components/BackActionBar.vue
index ea00720..a26b20f 100644
--- a/PAMapp/components/BackActionBar.vue
+++ b/PAMapp/components/BackActionBar.vue
@@ -9,7 +9,7 @@
 <script lang="ts">
 import { namespace, Watch } from 'nuxt-property-decorator';
 import { Vue, Component,} from 'vue-property-decorator';
-import { Role } from '~/assets/ts/models/enum/Role';
+import { Role } from '~/assets/ts/models/enum/role.enum';
 import * as _ from 'lodash';
 import { isLogin } from '~/assets/ts/auth';
 
diff --git a/PAMapp/components/NavBar.vue b/PAMapp/components/NavBar.vue
index c3fc5b3..111e909 100644
--- a/PAMapp/components/NavBar.vue
+++ b/PAMapp/components/NavBar.vue
@@ -34,7 +34,7 @@
 <script lang="ts">
   import { Vue, Component } from 'vue-property-decorator';
   import { namespace } from 'nuxt-property-decorator';
-  import { Role } from '~/assets/ts/models/enum/Role';
+  import { Role } from '~/assets/ts/models/enum/role.enum';
   import * as _ from 'lodash';
 
   const roleStorage = namespace('localStorage');
@@ -63,13 +63,8 @@
         title: '���董�����',
       },
       {
-        authorityOfRoleList:[Role.ADMIN],
+        authorityOfRoleList:[Role.ADMIN, Role.USER],
         routeUrl: '/record',
-        title: '�������',
-      },
-      {
-        authorityOfRoleList: [Role.USER],
-        routeUrl: '/userReviewsRecord',
         title: '�������',
       },
       {
diff --git a/PAMapp/components/QuickFilter/QuickFilterSelector.vue b/PAMapp/components/QuickFilter/QuickFilterSelector.vue
index 915eca1..977d802 100644
--- a/PAMapp/components/QuickFilter/QuickFilterSelector.vue
+++ b/PAMapp/components/QuickFilter/QuickFilterSelector.vue
@@ -65,8 +65,9 @@
 
 <script lang="ts">
 import { Vue, Component, Prop, Watch, Emit } from 'nuxt-property-decorator';
-import { FastQueryParams } from '~/assets/ts/api/consultant';
-import { QuestionOption } from '~/pages/quickFilter/index.vue';
+import { FastQueryParams } from '~/assets/ts/models/fast-query-params.model';
+import { Selected } from '~/assets/ts/models/selected.model';
+import { QuestionOption } from '~/assets/ts/models/question-option.model';
 
 @Component
 export default class QuickFilterDrawer extends Vue {
@@ -131,10 +132,6 @@
 
 }
 
-export interface Selected {
-    option: string;
-    value: any;
-}
 </script>
 
 <style lang="scss" scoped>
@@ -146,4 +143,4 @@
         flex-wrap: wrap;
     }
 
-</style>
\ No newline at end of file
+</style>
diff --git a/PAMapp/pages/accountSetting/account-setting.component.scss b/PAMapp/pages/accountSetting/account-setting.component.scss
new file mode 100644
index 0000000..e32f0e0
--- /dev/null
+++ b/PAMapp/pages/accountSetting/account-setting.component.scss
@@ -0,0 +1,118 @@
+.account-page{
+  .block{
+      display: flex;
+  }
+  .account-page-title{
+      font-size: 20px;
+      margin-bottom: 34px;
+  }
+  .account-card{
+      display: flex;
+      flex-direction: column;
+      border-bottom: 1px solid gray;
+      margin-bottom: 33px;
+      .contact-type{
+          width: 184px;
+          margin-right: 16px;
+          font-size: 20px;
+          display: flex;
+          flex-direction: column;
+          align-items: flex-start;
+      }
+      &.edit {
+          input {
+              border: 1px solid lightgray;
+              background-color: #fff;
+          }
+      }
+  }
+  .account-setting-btn{
+      display: flex;
+      justify-content: center;
+  }
+}
+.error-txt{
+  padding-bottom: 10px;
+  .error {
+      @extend .smTxt_bold;
+      @extend .text--primary;
+      height: 16px;
+      }
+}
+.name-input{
+          width: 184px;
+          height:27px;
+          margin-bottom: 20px;
+          font-size: 20px;
+          margin-top: -3px;
+      }
+.setting-title{
+          margin-left: 28px;
+          margin-bottom:10px;
+          width: 58px;
+          font-size: 20px;
+      }
+.header{
+  display: flex;
+  align-items: baseline;
+}
+.contact-input{
+  font-size: 20px;
+  margin-bottom: 10px;
+  text-overflow: ellipsis;
+  margin-top: 10px;
+  width: 184px;
+}
+.input{
+  border: 0;
+  background-color: rgba(0,0,0,0) ;
+  outline-color: gainsboro;
+}
+.input:focus{
+  background-color: #fff;
+}
+.icon-color-change{
+  color:$PRIMARY_RED;
+  font-size: 20px;
+}
+.icon{
+  font-size:20px;
+  // color:#1B365D;
+}
+@include desktop{
+
+  .header{
+  display: flex;
+  align-items: baseline;
+  justify-content: space-between;
+  }
+  .setting-title{
+          margin-bottom:10px;
+          width: 58px;
+          font-size: 18px;
+          font-weight: bold;
+      }
+  .account-page{
+  .account-page-title{
+      font-size: 20px;
+      margin-bottom: 34px;
+      font-weight: bold;
+  }
+  }
+  .account-card{
+      display: flex;
+      flex-direction: column;
+      border-bottom: 1px solid gray;
+      margin-bottom: 33px;
+      .contact-type{
+          margin-left: 10px;
+          font-size: 20px;
+      }
+  }
+  .name-input{
+      width: 550px;
+  }
+  .contact-input{
+      width:550px
+  }
+  }
diff --git a/PAMapp/pages/accountSetting/account-setting.component.ts b/PAMapp/pages/accountSetting/account-setting.component.ts
new file mode 100644
index 0000000..79dad96
--- /dev/null
+++ b/PAMapp/pages/accountSetting/account-setting.component.ts
@@ -0,0 +1,98 @@
+
+import { Vue,Component } from 'vue-property-decorator'
+import { getUserAccountSetting, updateAccountSetting } from '~/assets/ts/api/consultant';
+import { UserSetting } from '~/assets/ts/models/account.model';
+
+@Component
+export default class AccountSetting extends Vue {
+        _userSetting!: UserSetting;
+        userNameDisabled = true;
+        userPhoneDisabled = true;
+        userEmailDisabled = true ;
+        userNameValue = '';
+        phoneValue = '' ;
+        emailValue = '' ;
+
+        onEditMode = false;
+        formValidStatus = {
+            name: true,
+            phone: true,
+            email: true,
+        };
+
+        get nameValid(): boolean {
+            this.formValidStatus.name = this.userNameValue ? true : false;
+            return this.formValidStatus.name;
+        }
+
+        get phoneValid(): boolean {
+            const rule = /^09[0-9]{8}$/;
+            this.formValidStatus.phone = this.phoneValue ? rule.test(this.phoneValue) : true;
+            return this.formValidStatus.phone;
+        }
+
+        get emailValid(): boolean {
+            const rule = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
+            this.formValidStatus.email = this.emailValue ? rule.test(this.emailValue) : true;;
+            return this.formValidStatus.email;
+        }
+
+        editField(fieldName: string): void {
+            this.onEditMode = true;
+            const enablePromise = new Promise((resolve, reject) => { // 甇斤promise隤��
+                resolve((this as any)[`${fieldName}Disabled`] = false);
+            });
+            const targetInput = this.$refs[fieldName] as any;
+            enablePromise.then((_) => {
+                targetInput.focus();
+            });
+        }
+
+        get isSubmitBtnDisabled(): boolean {
+            const isFormValid = this.formValidStatus.name && this.formValidStatus.phone && this.formValidStatus.email;
+            return !isFormValid || !this.onEditMode
+                || (!this.phoneValue && !this.emailValue);
+        }
+
+        updateAccountSetting(): void {
+            // const dataChanged = (): boolean => {
+            //     return this._userSetting.name !== this.userNameValue
+            //         || this._userSetting.phone !== this.phoneValue
+            //         || this._userSetting.email !== this.emailValue;
+            // };
+            // if (dataChanged) {
+
+            // }
+            if (!this.onEditMode) return;
+            const editSettingInfo: UserSetting = {
+                name: this.userNameValue,
+                phone: this.phoneValue,
+                email: this.emailValue
+            }
+            updateAccountSetting(editSettingInfo).then((res: any) => {
+                this.resetSettingForm();
+            });
+        }
+
+        private resetSettingForm(): void {
+            this.onEditMode = false;
+            this.userNameDisabled = true;
+            this.userPhoneDisabled = true;
+            this.userEmailDisabled = true ;
+        }
+
+        mounted(){
+            getUserAccountSetting().then((userInfo: UserSetting)=>{
+                this._userSetting = {
+                    name: userInfo.name || '',
+                    phone: userInfo.phone || '',
+                    email: userInfo.email || '',
+                };
+
+                this.phoneValue = this._userSetting.phone!;
+                this.userNameValue = this._userSetting.name!;
+                this.emailValue = this._userSetting.email!;
+            })
+        }
+
+}
diff --git a/PAMapp/pages/accountSetting/index.vue b/PAMapp/pages/accountSetting/index.vue
index fb21f19..8c4a31e 100644
--- a/PAMapp/pages/accountSetting/index.vue
+++ b/PAMapp/pages/accountSetting/index.vue
@@ -1,14 +1,14 @@
 <template>
 <div class="account-page">
     <div class="account-page-title">�犖撣唾�身摰�</div>
-    <section class="account-card" :class="{'edit': !userNameDisabled }"> 
+    <section class="account-card" :class="{'edit': !userNameDisabled }">
         <div class="header">
             <div class="block">
                 <div class="setting-title">憪��</div>
                 <div class="contact-type">
                     <input
                         :disabled="userNameDisabled"
-                        v-model="userNameValue" 
+                        v-model="userNameValue"
                         ref="userName"
                         class="input name-input"
                         >
@@ -16,22 +16,22 @@
                         <span v-show="!nameValid" class="error">甇斗���‵</span>
                     </div>
                 </div>
-                
+
             </div>
             <i class="icon-edit icon" @click="editField('userName')" :class="{'icon-color-change': !userNameDisabled}"></i>
         </div>
-        
+
     </section>
 
-    <section class="account-card" :class="{'edit': !userPhoneDisabled }" v-if="phoneValue"> 
+    <section class="account-card" :class="{'edit': !userPhoneDisabled }" v-if="phoneValue">
         <div class="header">
-            <div class="block">   
+            <div class="block">
             <div class="setting-title">蝬��</div>
             <div class="contact-type">
                 ����Ⅳ
                 <input
                     :disabled="userPhoneDisabled"
-                    v-model="phoneValue" 
+                    v-model="phoneValue"
                     :class="{
                     'is-invalid': !phoneValid
                     }"
@@ -44,19 +44,19 @@
                 </div>
             </div>
             </div>
-            <!-- <i class="icon-edit icon" 
+            <!-- <i class="icon-edit icon"
                 @click="editField('userPhone')"
                 :class="{'icon-color-change': !userPhoneDisabled}"></i> -->
         </div>
-        
+
     </section>
 
-    <section class="account-card" :class="{'edit': !userEmailDisabled }" v-if="emailValue"> 
+    <section class="account-card" :class="{'edit': !userEmailDisabled }" v-if="emailValue">
         <div class="header">
             <div class="block">
             <div class="setting-title">蝬��</div>
                 <div class="contact-type">Email
-                    <input 
+                    <input
                         :disabled="userEmailDisabled"
                         v-model="emailValue"
                         :class="{
@@ -71,15 +71,15 @@
                     </div>
                 </div>
                 </div>
-                
-                <!-- <i class="icon-edit icon" @click="editField('userEmail')" 
+
+                <!-- <i class="icon-edit icon" @click="editField('userEmail')"
                         :class="{'icon-color-change': !userEmailDisabled}"></i> -->
         </div>
-        
+
     </section>
 
     <div class="account-setting-btn mb-30">
-        <el-button 
+        <el-button
             :disabled="isSubmitBtnDisabled"
             @click.native="updateAccountSetting">�</el-button>
     </div>
@@ -87,227 +87,8 @@
 </div>
 </template>
 
-<script lang="ts">
-import { Vue,Component } from 'vue-property-decorator'
-import { getUserAccountSetting, updateAccountSetting } from '~/assets/ts/api/consultant';
-import { UserSetting } from '~/assets/ts/models/account.model';
-
-@Component
-export default class AccountSetting extends Vue {
-        _userSetting!: UserSetting;
-        userNameDisabled = true;
-        userPhoneDisabled = true;
-        userEmailDisabled = true ;
-        userNameValue = '';
-        phoneValue = '' ;
-        emailValue = '' ;
-
-        onEditMode = false;
-        formValidStatus = {
-            name: true,
-            phone: true,
-            email: true,
-        };
-
-        get nameValid(): boolean {
-            this.formValidStatus.name = this.userNameValue ? true : false;
-            return this.formValidStatus.name;
-        }
-
-        get phoneValid(): boolean {
-            const rule = /^09[0-9]{8}$/;
-            this.formValidStatus.phone = this.phoneValue ? rule.test(this.phoneValue) : true;
-            return this.formValidStatus.phone;
-        }
-
-        get emailValid(): boolean {
-            const rule = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
-            this.formValidStatus.email = this.emailValue ? rule.test(this.emailValue) : true;;
-            return this.formValidStatus.email;
-        }
-
-        editField(fieldName: string): void {
-            this.onEditMode = true;
-            const enablePromise = new Promise((resolve, reject) => { // 甇斤promise隤��
-                resolve((this as any)[`${fieldName}Disabled`] = false);
-            });
-            const targetInput = this.$refs[fieldName] as any;
-            enablePromise.then((_) => {
-                targetInput.focus();
-            });
-        }
-
-        get isSubmitBtnDisabled(): boolean {
-            const isFormValid = this.formValidStatus.name && this.formValidStatus.phone && this.formValidStatus.email;
-            return !isFormValid || !this.onEditMode
-                || (!this.phoneValue && !this.emailValue);
-        }
-
-        updateAccountSetting(): void {
-            // const dataChanged = (): boolean => {
-            //     return this._userSetting.name !== this.userNameValue
-            //         || this._userSetting.phone !== this.phoneValue
-            //         || this._userSetting.email !== this.emailValue;
-            // };
-            // if (dataChanged) {
-
-            // }
-            if (!this.onEditMode) return;
-            const editSettingInfo: UserSetting = {
-                name: this.userNameValue,
-                phone: this.phoneValue,
-                email: this.emailValue
-            }
-            updateAccountSetting(editSettingInfo).then((res: any) => {
-                console.log('updateRes:', res);
-                this.resetSettingForm();
-            });
-        }
-
-        private resetSettingForm(): void {
-            this.onEditMode = false;
-            this.userNameDisabled = true;
-            this.userPhoneDisabled = true;
-            this.userEmailDisabled = true ;
-        }
-
-        mounted(){
-            getUserAccountSetting().then((userInfo: UserSetting)=>{
-                this._userSetting = {
-                    name: userInfo.name || '',
-                    phone: userInfo.phone || '',
-                    email: userInfo.email || '',
-                };
-
-                this.phoneValue = this._userSetting.phone!;
-                this.userNameValue = this._userSetting.name!;
-                this.emailValue = this._userSetting.email!;
-            })
-        }
-
-}
-
-
-</script>
+<script src="./account-setting.component.ts"></script>
 
 <style lang="scss" scoped>
-.account-page{
-    .block{
-        display: flex;
-    }
-    .account-page-title{
-        font-size: 20px;
-        margin-bottom: 34px;
-    }
-    .account-card{
-        display: flex;
-        flex-direction: column;
-        border-bottom: 1px solid gray;
-        margin-bottom: 33px;
-        .contact-type{
-            width: 184px;
-            margin-right: 16px;
-            font-size: 20px;
-            display: flex;
-            flex-direction: column;
-            align-items: flex-start;
-        }
-        &.edit {
-            input {
-                border: 1px solid lightgray;
-                background-color: #fff;
-            }
-        }
-    }
-    .account-setting-btn{
-        display: flex;
-        justify-content: center;
-    }
-}
-.error-txt{
-    padding-bottom: 10px;
-    .error {
-        @extend .smTxt_bold;
-        @extend .text--primary;
-        height: 16px;
-        }
-}
-.name-input{
-            width: 184px;
-            height:27px;
-            margin-bottom: 20px;
-            font-size: 20px;
-            margin-top: -3px;
-        }
-.setting-title{
-            margin-left: 28px;
-            margin-bottom:10px;
-            width: 58px;
-            font-size: 20px;
-        }
-.header{
-    display: flex;
-    align-items: baseline;
-}
-.contact-input{
-    font-size: 20px;
-    margin-bottom: 10px;
-    text-overflow: ellipsis;
-    margin-top: 10px;
-    width: 184px;
-}
-.input{
-    border: 0;
-    background-color: rgba(0,0,0,0) ;
-    outline-color: gainsboro;
-}
-.input:focus{
-    background-color: #fff;
-}
-.icon-color-change{
-    color:$PRIMARY_RED;
-    font-size: 20px;
-}
-.icon{
-    font-size:20px;
-    // color:#1B365D;
-}
-@include desktop{
-    
-    .header{
-    display: flex;
-    align-items: baseline;
-    justify-content: space-between;
-    }
-    .setting-title{
-            margin-bottom:10px;
-            width: 58px;
-            font-size: 18px;
-            font-weight: bold;
-        }
-    .account-page{
-    .account-page-title{
-        font-size: 20px;
-        margin-bottom: 34px;
-        font-weight: bold;
-    }
-    }
-    .account-card{
-        display: flex;
-        flex-direction: column;
-        border-bottom: 1px solid gray;
-        margin-bottom: 33px;
-        .contact-type{
-            margin-left: 10px;
-            font-size: 20px;
-        }
-    }
-    .name-input{
-        width: 550px;
-    }
-    .contact-input{
-        width:550px
-    }
-    }
-
-</style>
\ No newline at end of file
+  @import "./account-setting.component.scss";
+</style>
diff --git a/PAMapp/pages/agentInfo/_agentNo.vue b/PAMapp/pages/agentInfo/_agentNo.vue
index 03478ed..a3b562f 100644
--- a/PAMapp/pages/agentInfo/_agentNo.vue
+++ b/PAMapp/pages/agentInfo/_agentNo.vue
@@ -130,8 +130,8 @@
         type="flex"
         class="pam-paragraph">
         <UiField icon="school" label="�犖��">
-          <span v-for="(experience, index) in agentInfo.experiences" :key="index">
-            {{ experience }}<span v-if="index !== agentInfo.experiences.length - 1">, </span>
+          <span v-for="(experience, index) in agentInfo.expertiseList" :key="index">
+            {{ experience }}<span v-if="index !== agentInfo.expertiseList.length - 1">, </span>
           </span>
         </UiField>
       </el-row>
@@ -182,124 +182,8 @@
     </div>
 </template>
 
-<script lang="ts">
-import { Context } from '@nuxt/types';
-import { namespace } from 'nuxt-property-decorator';
-import { Vue, Component } from 'vue-property-decorator';
-import { getConsultantDetail } from '~/assets/ts/api/consultant';
-import { Role } from '~/assets/ts//models/enum/Role';
-const roleStorage = namespace('localStorage');
-@Component
-export default class AgentInfoComponent extends Vue {
-  @roleStorage.Getter currentRole!:string|null;
-  role = Role;
-  agentInfo!: AgentInfo;
-  isAlertAddSuccess = false;
-  isAlertFieldInfo = false;
-  fieldInfoTitle = '';
-  fieldInfoDesc = '';
-
-  async asyncData(context: Context) {
-    const agentNo = context.route.params.agentNo;
-    let agentInfo = {};
-    await getConsultantDetail(agentNo).then((res) => agentInfo = res.data )
-    return {
-      agentInfo
-    }
-  }
-
-  get agentName(): string {
-    return `${this.agentInfo.name}(${this.agentInfo.role})`;
-  }
-
-  alertAddSuccess() {
-      this.isAlertAddSuccess = true;
-  }
-
-  alertFieldInfo(field: string): void {
-    this.isAlertFieldInfo = true;
-    switch(field) {
-      case 'suitability':
-        this.fieldInfoTitle = '���漲';
-        this.fieldInfoDesc = '���漲��������翰�祟�敺����雿�憿批����脰�������蝯行�����潘��隞乩������“������潦��';
-        break;
-      case 'evaluation':
-        this.fieldInfoTitle = '隢株岷摨西”�';
-        this.fieldInfoDesc = '隢株岷摨西”��撠��雿�憿批�������垣閰X���脰�������蝯行�����潦��';
-        break;
-    }
-  }
-}
-
-interface AgentInfo {
-  name            : string;
-  agentNo         : string;
-  role            : string;
-  image           : string;
-  avgScore        : number;
-  title           : string;
-  phoneNumber     : string;
-  serveArea       : string;
-  companyAddress  : string;
-  lastestLoginTime: Date | null;
-  seniority       : string;
-  suitability     : number;
-  evaluation      : number;
-  expertises      : string[];
-  concept         : string;
-  experiences     : string[];
-  awards          : string;
-}
-</script>
+<script src="./agent-info.component.ts"></script>
 
 <style lang="scss">
-.pam-icon {
-  font-size: 15px;
-  padding-right: 8px;
-  color: $PRUDENTIAL_GREY;
-  &.icon--primary {
-    color: $PRIMARY_RED;
-  }
-}
-.pam-field {
-  display: flex;
-  flex-direction: column;
-  .pam-field__label {
-    display: flex;
-    align-items: center;
-    .pam-icon {
-      font-size: 12px;
-    }
-    .pam-field__title {
-      font-size: 16px;
-      font-weight: bold;
-      display: flex;
-      align-items: center;
-    }
-  }
-}
-
-.pam-field-suitability {
-  .el-progress-bar__inner {
-    background-color: $LIGHT_BLUE !important;
-  }
-}
-
-.pam-field-evaluation {
-  .el-progress-bar__inner {
-    background-color: $TEAL_GREEN!important;
-  }
-}
-
-.pam-field-experts {
-  display: flex;
-  flex-wrap: wrap;
-}
-
-.pam-progress__label {
-  justify-content: space-between;
-  flex-wrap: wrap;
-  line-height: 24px;
-}
-
+  @import "./agent-info.component.scss";
 </style>
diff --git a/PAMapp/pages/agentInfo/agent-info.component.scss b/PAMapp/pages/agentInfo/agent-info.component.scss
new file mode 100644
index 0000000..37f0e48
--- /dev/null
+++ b/PAMapp/pages/agentInfo/agent-info.component.scss
@@ -0,0 +1,48 @@
+.pam-icon {
+  font-size: 15px;
+  padding-right: 8px;
+  color: $PRUDENTIAL_GREY;
+  &.icon--primary {
+    color: $PRIMARY_RED;
+  }
+}
+.pam-field {
+  display: flex;
+  flex-direction: column;
+  .pam-field__label {
+    display: flex;
+    align-items: center;
+    .pam-icon {
+      font-size: 12px;
+    }
+    .pam-field__title {
+      font-size: 16px;
+      font-weight: bold;
+      display: flex;
+      align-items: center;
+    }
+  }
+}
+
+.pam-field-suitability {
+  .el-progress-bar__inner {
+    background-color: $LIGHT_BLUE !important;
+  }
+}
+
+.pam-field-evaluation {
+  .el-progress-bar__inner {
+    background-color: $TEAL_GREEN!important;
+  }
+}
+
+.pam-field-experts {
+  display: flex;
+  flex-wrap: wrap;
+}
+
+.pam-progress__label {
+  justify-content: space-between;
+  flex-wrap: wrap;
+  line-height: 24px;
+}
diff --git a/PAMapp/pages/agentInfo/agent-info.component.ts b/PAMapp/pages/agentInfo/agent-info.component.ts
new file mode 100644
index 0000000..8a80074
--- /dev/null
+++ b/PAMapp/pages/agentInfo/agent-info.component.ts
@@ -0,0 +1,54 @@
+import { Context } from '@nuxt/types';
+import { namespace } from 'nuxt-property-decorator';
+import { Vue, Component } from 'vue-property-decorator';
+
+import { getConsultantDetail } from '~/assets/ts/api/consultant';
+
+import { Role } from '~/assets/ts/models/enum/role.enum';
+import { AgentInfo } from '~/assets/ts/models/agentInfo.model';
+
+const roleStorage = namespace('localStorage');
+
+@Component
+export default class AgentInfoComponent extends Vue {
+
+  @roleStorage.Getter currentRole!:string|null;
+
+  role = Role;
+  agentInfo!: AgentInfo;
+  isAlertAddSuccess = false;
+  isAlertFieldInfo = false;
+  fieldInfoTitle = '';
+  fieldInfoDesc = '';
+
+  async asyncData(context: Context) {
+    const agentNo = context.route.params.agentNo;
+    let agentInfo = {};
+    await getConsultantDetail(agentNo).then((res) => agentInfo = res.data )
+    return {
+      agentInfo
+    }
+  }
+
+  get agentName(): string {
+    return `${this.agentInfo.name}(${this.agentInfo.role})`;
+  }
+
+  alertAddSuccess() {
+      this.isAlertAddSuccess = true;
+  }
+
+  alertFieldInfo(field: string): void {
+    this.isAlertFieldInfo = true;
+    switch(field) {
+      case 'suitability':
+        this.fieldInfoTitle = '���漲';
+        this.fieldInfoDesc = '���漲��������翰�祟�敺����雿�憿批����脰�������蝯行�����潘��隞乩������“������潦��';
+        break;
+      case 'evaluation':
+        this.fieldInfoTitle = '隢株岷摨西”�';
+        this.fieldInfoDesc = '隢株岷摨西”��撠��雿�憿批�������垣閰X���脰�������蝯行�����潦��';
+        break;
+    }
+  }
+}
diff --git a/PAMapp/pages/consultantLogin/consultant-login.component.scss b/PAMapp/pages/consultantLogin/consultant-login.component.scss
new file mode 100644
index 0000000..756aacc
--- /dev/null
+++ b/PAMapp/pages/consultantLogin/consultant-login.component.scss
@@ -0,0 +1,77 @@
+.pam-consultant-login {
+  margin: auto;
+  width: 336px;
+  font-size: 20px;
+  color: $PRIMARY_BLACK;
+
+  &__header {
+    text-align: center;
+    font-size: 24px;
+    font-weight: bold;
+    letter-spacing: 1.2;
+    color: $PRIMARY_BLACK;
+  }
+
+  &__title {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+  }
+
+  &__input {
+    width: 100%;
+    outline: 0;
+    border: 1px solid #CCCCCC;
+    border-radius: 10px;
+    font-size: 20px;
+    height: 50px;
+    padding: 10px 90px 10px 15px;
+    overflow: auto;
+    box-sizing: border-box;
+    -webkit-box-sizing: border-box;
+    -moz-box-sizing: border-box;
+
+    &Icon {
+      position: absolute;
+      display: flex;
+      align-items: center;
+      top: 15px;
+      right: 15px;
+    }
+  }
+
+  &__forgot-password {
+    color: $PRIMARY_RED;
+    text-decoration: none;
+    font-size: 16px;
+  }
+
+  &__verifyBlock {
+    display: flex;
+    justify-content: space-between;
+  }
+
+  &__verifyImg {
+    width: 126px;
+    height: 50px;
+    border:1px #cccccc solid;
+    img {
+      width: 100%;
+      height: 100%;
+    }
+  }
+
+  &__confirmBlock {
+    display: flex;
+    justify-content: center;
+  }
+
+  &__confirm {
+    color: $PRIMARY_WHITE;
+    width: 80px;
+    height: 50px;
+    border-radius: 30px;
+    border: 1px solid $LIGHT_GREY;
+    background-color: $PRIMARY_RED;
+  }
+}
diff --git a/PAMapp/pages/consultantLogin/consultant-login.component.ts b/PAMapp/pages/consultantLogin/consultant-login.component.ts
new file mode 100644
index 0000000..cbd2696
--- /dev/null
+++ b/PAMapp/pages/consultantLogin/consultant-login.component.ts
@@ -0,0 +1,103 @@
+import { Vue, Component , namespace } from 'nuxt-property-decorator';
+import { AxiosError } from 'axios';
+import { getImgOfVerification, logInToConsultant, getVerificationStatus } from '~/assets/ts/api/consultant';
+import { Role } from '~/assets/ts/models/enum/role.enum';
+import ErrorMessageBox from '~/assets/ts/errorService';
+
+const roleStorage = namespace('localStorage');
+@Component({
+  layout: 'home'
+})
+export default class ConsultantLogin extends Vue {
+  @roleStorage.Mutation storageIdToken!: (token: string) => void;
+  @roleStorage.Mutation storageRole!: (role: string) => void;
+  @roleStorage.Mutation storageConsultantId!:(id:string) => void;
+  isRememberUserName = false;
+  isShowPassword = false;
+  imgSrc = '';
+  verificationCode='';
+  consultantDto = {
+    username: '',
+    password: '',
+  }
+
+  get isAlreadyDone():boolean{
+    return !!(this.verificationCode && this.consultantDto.username && this.consultantDto.password);
+  }
+
+  mounted() {
+    this.getInitUserName();
+    this.regenerateImgOfVerification();
+  };
+
+  private getInitUserName(): void {
+    const username = localStorage.getItem('consultantUserName')
+    if (username) {
+      this.consultantDto.username = username;
+      this.isRememberUserName = true;
+    }
+  }
+
+  public regenerateImgOfVerification(): void {
+    getImgOfVerification().then( imgOfBase64 =>
+      this.imgSrc = imgOfBase64
+    );
+  };
+
+  public isRememberChange():void{
+    this.isRememberUserName = !this.isRememberUserName;
+    this.storeUserName();
+  }
+
+  public sendInfo():void{
+    this.isAlreadyDone ? this.verify() : ErrorMessageBox('隢Ⅱ隤董����Ⅳ隞亙���Ⅳ��憛怠神摰');
+  }
+
+  private verify():void{
+    getVerificationStatus(this.verificationCode).then( verifySuccess => {
+      if(verifySuccess.data){
+        this.loginWithConsultant()
+      }else{
+        this.clearValue();
+        this.regenerateImgOfVerification();
+        ErrorMessageBox('撽�Ⅳ頛詨�隤�');
+      }
+    });
+  }
+
+  private loginWithConsultant(): void {
+    logInToConsultant(this.consultantDto).then(res => {
+      this.storageIdToken(res.data.id_token);
+      this.storageRole(Role.ADMIN);
+      this.storageConsultantId(this.consultantDto.username)
+      this.storeUserName();
+      this.$router.push('/myAppointmentList/appointmentList');
+    }).catch((error:AxiosError)=>{
+      this.checkHttpErrorStatus(error);
+    });
+  }
+  private checkHttpErrorStatus(error:any):void{
+    this.clearValue();
+    this.regenerateImgOfVerification();
+    switch (error.response.status) {
+      case 401:
+        const errorMsg = error.response.data.detail;
+        ErrorMessageBox(errorMsg);
+        break;
+
+      default:
+        ErrorMessageBox('',error);
+        break;
+    }
+  }
+
+  private storeUserName(): void {
+    localStorage.setItem('consultantUserName', this.isRememberUserName ? this.consultantDto.username : '');
+  };
+
+  private clearValue():void{
+    if (!this.isRememberUserName) this.consultantDto.username='';
+    this.consultantDto.password = '';
+    this.verificationCode = '';
+  }
+};
diff --git a/PAMapp/pages/consultantLogin/index.vue b/PAMapp/pages/consultantLogin/index.vue
index 283f867..e59a9ca 100644
--- a/PAMapp/pages/consultantLogin/index.vue
+++ b/PAMapp/pages/consultantLogin/index.vue
@@ -55,206 +55,8 @@
   </div>
 </template>
 
-<script lang="ts">
-  import { Vue, Component , namespace } from 'nuxt-property-decorator';
-  import { AxiosError } from 'axios';
-  import { getImgOfVerification, logInToConsultant, getVerificationStatus } from '~/assets/ts/api/consultant';
-  import { Role } from '~/assets/ts/models/enum/Role';
-  import ErrorMessageBox from '~/assets/ts/errorService';
-
-  const roleStorage = namespace('localStorage');
-  @Component({
-    layout: 'home'
-  })
-  export default class ConsultantLogin extends Vue {
-    @roleStorage.Mutation storageIdToken!: (token: string) => void;
-    @roleStorage.Mutation storageRole!: (role: string) => void;
-    @roleStorage.Mutation storageConsultantId!:(id:string) => void;
-    isRememberUserName = false;
-    isShowPassword = false;
-    imgSrc = '';
-    verificationCode='';
-    consultantDto = {
-      username: '',
-      password: '',
-    }
-
-    get isAlreadyDone():boolean{
-      return !!(this.verificationCode && this.consultantDto.username && this.consultantDto.password);
-    }
-
-    mounted() {
-      this.getInitUserName();
-      this.regenerateImgOfVerification();
-    };
-
-    private getInitUserName(): void {
-      const username = localStorage.getItem('consultantUserName')
-      if (username) {
-        this.consultantDto.username = username;
-        this.isRememberUserName = true;
-      }
-    }
-
-    public regenerateImgOfVerification(): void {
-      getImgOfVerification().then( imgOfBase64 =>
-        this.imgSrc = imgOfBase64
-      );
-    };
-
-    public isRememberChange():void{
-      this.isRememberUserName = !this.isRememberUserName;
-      this.storeUserName();
-    }
-
-    public sendInfo():void{
-      this.isAlreadyDone ? this.verify() : ErrorMessageBox('隢Ⅱ隤董����Ⅳ隞亙���Ⅳ��憛怠神摰');
-    }
-
-    private verify():void{
-      getVerificationStatus(this.verificationCode).then( verifySuccess => {
-        if(verifySuccess.data){
-          this.loginWithConsultant()
-        }else{
-          this.clearValue();
-          this.regenerateImgOfVerification();
-          ErrorMessageBox('撽�Ⅳ頛詨�隤�');
-        }
-      });
-    }
-
-    private loginWithConsultant(): void {
-      logInToConsultant(this.consultantDto).then(res => {
-        this.storageIdToken(res.data.id_token);
-        this.storageRole(Role.ADMIN);
-        this.storageConsultantId(this.consultantDto.username)
-        this.storeUserName();
-        this.$router.push('/myAppointmentList/appointmentList');
-      }).catch((error:AxiosError)=>{
-        this.checkHttpErrorStatus(error);
-      });
-    }
-    private checkHttpErrorStatus(error:any):void{
-      this.clearValue();
-      this.regenerateImgOfVerification();
-      switch (error.response.status) {
-        case 401:
-          const errorMsg = error.response.data.detail;
-          ErrorMessageBox(errorMsg);
-          break;
-
-        default:
-          ErrorMessageBox('',error);
-          break;
-      }
-    }
-
-    private storeUserName(): void {
-      localStorage.setItem('consultantUserName', this.isRememberUserName ? this.consultantDto.username : '');
-    };
-
-    private clearValue():void{
-      if (!this.isRememberUserName) this.consultantDto.username='';
-      this.consultantDto.password = '';
-      this.verificationCode = '';
-    }
-  };
-
-</script>
+<script src="./consultant-login.component.ts"></script>
 
 <style lang="scss" scoped>
-  .mt-20 {
-    margin-top: 20px;
-  }
-
-  .mt-25 {
-    margin-top: 25px;
-  }
-
-  .w-55 {
-    width: 55% !important;
-  }
-
-  .position-r {
-    position: relative;
-  }
-
-  .pam-consultant-login {
-    margin: auto;
-    width: 336px;
-    font-size: 20px;
-    color: $PRIMARY_BLACK;
-
-    &__header {
-      text-align: center;
-      font-size: 24px;
-      font-weight: bold;
-      letter-spacing: 1.2;
-      color: $PRIMARY_BLACK;
-    }
-
-    &__title {
-      display: flex;
-      justify-content: space-between;
-      align-items: center;
-    }
-
-    &__input {
-      width: 100%;
-      outline: 0;
-      border: 1px solid #CCCCCC;
-      border-radius: 10px;
-      font-size: 20px;
-      height: 50px;
-      padding: 10px 90px 10px 15px;
-      overflow: auto;
-      box-sizing: border-box;
-      -webkit-box-sizing: border-box;
-      -moz-box-sizing: border-box;
-
-      &Icon {
-        position: absolute;
-        display: flex;
-        align-items: center;
-        top: 15px;
-        right: 15px;
-      }
-    }
-
-    &__forgot-password {
-      color: $PRIMARY_RED;
-      text-decoration: none;
-      font-size: 16px;
-    }
-
-    &__verifyBlock {
-      display: flex;
-      justify-content: space-between;
-    }
-
-    &__verifyImg {
-      width: 126px;
-      height: 50px;
-      border:1px #cccccc solid;
-      img {
-        width: 100%;
-        height: 100%;
-      }
-    }
-
-    &__confirmBlock {
-      display: flex;
-      justify-content: center;
-    }
-
-    &__confirm {
-      color: $PRIMARY_WHITE;
-      width: 80px;
-      height: 50px;
-      border-radius: 30px;
-      border: 1px solid $LIGHT_GREY;
-      background-color: $PRIMARY_RED;
-    }
-  }
-
+  @import "./consultant-login.component.scss";
 </style>
diff --git a/PAMapp/pages/login/index.vue b/PAMapp/pages/login/index.vue
index 6f02559..cc5c228 100644
--- a/PAMapp/pages/login/index.vue
+++ b/PAMapp/pages/login/index.vue
@@ -339,476 +339,8 @@
     </div>
 </template>
 
-<script lang="ts">
-import { namespace } from 'nuxt-property-decorator';
-import { Vue, Component, Ref } from 'vue-property-decorator';
-import { LoginRequest, LoginVerify, loginVerify, OtpInfo, register, RegisterInfo, sendOtp } from '~/assets/ts/api/consultant';
-import ErrorMessageBox from '~/assets/ts/errorService';
-import { OtpErrorCode } from '~/assets/ts/models/enum/otpErrorCode';
-import { Role } from '~/assets/ts/models/enum/Role';
+<script src="./login.component.ts"></script>
 
-const roleStorage = namespace('localStorage');
-
-@Component
-export default class Login extends Vue {
-  @roleStorage.Mutation storageIdToken!: (token:string) => void;
-  @roleStorage.Mutation storageRole!: (role:string) => void;
-  @Ref('contract') readonly contract!: any;
-
-  connectDevice: 'MOBILE' | 'EMAIL' = 'MOBILE';
-
-  phoneNumber = '';
-  otpCode = '';
-  onPhoneVerifyStep: 'APPLY_OTP' | 'INPUT_OTP' | 'SUBMIT_OTP' = 'APPLY_OTP';
-  otpCounterSec = 900;
-  otpResendCounter = 30;
-  otpInterval: any;
-  phoneOtpInfo!: OtpInfo;
-
-  email = '';
-  onEmailVerifyResendStatus: 'APPLY_OTP' | 'CAN_RESEND' = 'APPLY_OTP';
-  emailCounterSec = 900;
-  emailResendCounter = 30;
-  emailOtpCode = '';
-  emailResendInterval: any;
-  emailOtpInfo!: OtpInfo;
-
-  autoRedirectCounter = 3;
-  autoRedirectInterval: any;
-
-  name = '';
-  agreeContract = false;
-  isReadContract = false;
-
-  phoneSuccessConfirmVisable = false;
-  emailOtpConfirmVisable = false;
-
-  registerDialogVisible = false;
-  registerSuccessConfirmVisable = false;
-
-  applyAccount_onAction = false;
-
-  previousPath = '';
-  mounted() {
-    const phoneOtpTime = localStorage.getItem('phoneOtpTime');
-    const emailOtpTime = localStorage.getItem('emailOtpTime');
-    const parsePhoneOtpTime = phoneOtpTime ? JSON.parse(phoneOtpTime) : '';
-    const parseEmailOtpTime = emailOtpTime ? JSON.parse(emailOtpTime) : '';
-    if (parsePhoneOtpTime && parsePhoneOtpTime.contactType === 'SMS') {
-      this.phoneDiffTime(parsePhoneOtpTime);
-    }
-    if (parseEmailOtpTime && parseEmailOtpTime.contactType === 'EMAIL') {
-      this.emailDiffTime(parseEmailOtpTime);
-    }
-  }
-
-  detectContractReadStatus(event: any): void {
-    const scrollTop = Math.round(event.target.scrollTop);
-    const height = event.target.scrollHeight - event.target.clientHeight;
-    if (Math.floor(scrollTop/10) === (Math.floor(height/10))) {
-      this.isReadContract = true;
-    }
-  };
-
-  get isSubmitBtnDisabled(): boolean {
-    return this.connectDevice === 'MOBILE'
-      ? (!this.otpCode || !this.phoneNumber || !this.phoneValid || !this.otpCounterSec)
-      : (!this.emailOtpCode || !this.email || !this.emailValid || !this.emailCounterSec)
-  }
-
-  get phoneCounter() {
-    let min = Math.floor(this.otpCounterSec / 60);
-    let sec = Math.floor(this.otpCounterSec % 60);
-    return `${min < 10 ? '0' + min : min}:${sec < 10 ? '0' + sec : sec}`;
-  }
-
-  get emailOtpCounter() {
-    let min = Math.floor(this.emailCounterSec / 60);
-    let sec = Math.floor(this.emailCounterSec % 60);
-    return `${min < 10 ? '0' + min : min}:${sec < 10 ? '0' + sec : sec}`;
-  }
-
-  get showPhoneOtpCodeField(): boolean {
-    return this.connectDevice === 'MOBILE' && this.onPhoneVerifyStep === 'INPUT_OTP';
-  };
-
-  get showEmailVerifyField(): boolean {
-    return this.connectDevice === 'EMAIL' && this.onEmailVerifyResendStatus === 'CAN_RESEND';
-  };
-
-  get phoneValid() {
-    const rule = /^09[0-9]{8}$/;
-    return this.phoneNumber ? rule.test(this.phoneNumber) : true;
-  }
-
-  get emailValid() {
-    const rule = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
-    return this.email ? rule.test(this.email) : true;
-  }
-
-  applyOtpVerification(type: string): void {
-    const isMobile = this.connectDevice === 'MOBILE';
-    const loginInfo: LoginRequest = {
-      loginType: isMobile ? 'SMS' : 'EMAIL',
-      account: isMobile ? this.phoneNumber : this.email,
-    }
-    sendOtp(loginInfo).then(otpInfo => {
-      if (otpInfo.success) {
-        this.storageOtpTime(type, otpInfo);
-        this.startOtpSetting(type);
-        this.startOtpCount(type);
-      } else {
-        const errorMsg = OtpErrorCode[otpInfo.failCode] ? OtpErrorCode[otpInfo.failCode]:'OTP蝟餌絞�隤�';
-        ErrorMessageBox(errorMsg);
-      }
-    });
-  };
-
-  resentOtp(type: string) {
-    this.resetOtpSetting(type);
-    this.applyOtpVerification(type);
-  }
-
-  deleteOtpInfo(type: string) {
-    this.resetOtpSetting(type);
-    if (type === 'MOBILE') {
-      this.onPhoneVerifyStep = 'APPLY_OTP';
-      this.phoneNumber = '';
-      this.otpCode = '';
-    } else {
-      this.onEmailVerifyResendStatus = 'APPLY_OTP';
-      this.email = '';
-      this.emailOtpCode = '';
-    }
-    this.removeOtpTime();
-  }
-
-  applyAccount(): void {
-    if (this.applyAccount_onAction) {
-      return ;
-    }
-
-    this.applyAccount_onAction = true;
-    const registerInfo = this.setRegisterInfo();
-
-    register(registerInfo).then(res => {
-      this.storageIdToken(res.data.id_token);
-      this.storageRole(Role.USER);
-      this.storagePhoneOrEmail(registerInfo);
-      this.autoRedirect();
-      this.registerSuccessConfirmVisable = true;
-    }).catch(() => {
-      this.applyAccount_onAction = false;
-    });
-  };
-
-  confirmApplySuccess(): void {
-    this.phoneSuccessConfirmVisable = false;
-    this.registerSuccessConfirmVisable = false;
-    this.redirect();
-  }
-
-  private autoRedirect() {
-    this.autoRedirectInterval = setInterval(() => {
-      this.autoRedirectCounter -= 1;
-
-      if (this.autoRedirectCounter === 0) {
-        clearInterval(this.autoRedirectInterval);
-        this.redirect();
-      }
-    }, 1000)
-  }
-
-  private redirect() {
-    const backToPrevious = ['questionnaire', 'myConsultantList'];
-    const find = backToPrevious.findIndex(item => this.previousPath.includes(item));
-    console.log(this.previousPath, find, 'redirect');
-    find > -1 ? this.$router.go(-1) : this.$router.push('/');
-  }
-
-  beforeRouteEnter (to, from, next) {
-      next(vm => {
-        console.log(from.path, 'beforeRouteEnter');
-        vm.previousPath = from.path;
-      })
-    }
-
-  login() {
-    const login: LoginVerify = this.setLoginInfo();
-    this.removeOtpTime();
-    loginVerify(login).then(res => {
-      this.storageIdToken(res.data.id_token);
-      this.storageRole(Role.USER);
-      this.phoneSuccessConfirmVisable = true;
-      this.autoRedirect();
-      this.storagePhoneOrEmail(this.setRegisterInfo());
-    }).catch(error => {
-      this.checkHttpErrorStatus(error);
-    });
-  }
-  private checkHttpErrorStatus(error:any):void{
-    switch (error.response.status) {
-        case 401:
-          const errorMsg = OtpErrorCode[error.response?.data?.detail] ? OtpErrorCode[error.response?.data?.detail]:'OTP蝟餌絞�隤�';
-          ErrorMessageBox(errorMsg);
-          break;
-        case 403:
-          this.registerDialogVisible = true;
-          setTimeout(() => {
-            const isScrollBarNeedless = this.contract.scrollHeight <= this.contract.clientHeight;
-            if (isScrollBarNeedless) {
-              this.isReadContract = true;
-            }
-          }, 1000);
-          break;
-        default:
-          ErrorMessageBox('',error);
-          break;
-      }
-  }
-
-  destroyed() {
-    this.removeOtpTime();
-    clearInterval(this.otpInterval);
-    clearInterval(this.emailResendInterval);
-    clearInterval(this.autoRedirectInterval);
-  }
-
-  private phoneDiffTime(parseOtpTime: any) {
-    const diffSecs = this.calcDiffSecs(parseOtpTime.time);
-
-    if (diffSecs < this.otpCounterSec) {
-      this.otpResendCounter = diffSecs < 30 ? 30 - diffSecs : 0;
-        this.otpCounterSec -= diffSecs;
-        this.phoneNumber = parseOtpTime.phone;
-        this.onPhoneVerifyStep = 'INPUT_OTP';
-        this.phoneOtpInfo = this.setOtpInfo(parseOtpTime);
-        this.startOtpCount('MOBILE');
-    } else {
-      localStorage.removeItem('phoneOtpTime');
-    }
-  }
-
-  private emailDiffTime(parseOtpTime: any) {
-    const diffSecs = this.calcDiffSecs(parseOtpTime.time);
-
-    if (diffSecs < this.emailCounterSec) {
-      this.emailResendCounter =  diffSecs < 30 ? 30 - diffSecs : 0;
-      this.emailCounterSec -= diffSecs;
-      this.email = parseOtpTime.email;
-      this.onEmailVerifyResendStatus = 'CAN_RESEND';
-      this.emailOtpInfo = this.setOtpInfo(parseOtpTime);
-      this.startOtpCount('EMAIL');
-    } else {
-      localStorage.removeItem('emailOtpTime');
-    }
-  }
-
-  private calcDiffSecs(parseOtpTime) {
-    const currentTime = new Date().getTime();
-    const storageTime = new Date(parseOtpTime).getTime();
-    return Math.floor((currentTime - storageTime) / 1000);
-  }
-
-  private resetOtpSetting(type: string) {
-    if (type === 'MOBILE') {
-      clearInterval(this.otpInterval);
-      this.otpResendCounter = 30;
-      this.otpCounterSec = 900;
-    } else {
-      clearInterval(this.emailResendInterval);
-      this.emailResendCounter = 30;
-      this.emailCounterSec = 900;
-    }
-  }
-
-  private setOtpInfo(parseOtpTime) {
-    return {
-      indexKey: parseOtpTime.indexKey,
-      success: true,
-      failCode: '',
-      failReason: '',
-    }
-  }
-
-  private storageOtpTime(type: string, otpInfo: OtpInfo) {
-    type === 'MOBILE' ? this.phoneOtpInfo = otpInfo : this.emailOtpInfo = otpInfo;
-    const info = {...this.setRegisterInfo(), time: new Date()}
-    type === 'MOBILE' ? localStorage.setItem('phoneOtpTime',JSON.stringify(info))
-                      : localStorage.setItem('emailOtpTime',JSON.stringify(info));
-  }
-
-  private startOtpSetting(type: string) {
-    if (type === 'MOBILE') {
-      this.onPhoneVerifyStep = 'INPUT_OTP';
-    } else {
-      this.onEmailVerifyResendStatus = 'CAN_RESEND';
-      this.emailOtpConfirmVisable = true;
-    }
-  }
-
-  private startOtpCount(type: string) {
-    type === 'MOBILE' ? this.startPhoneCounter() : this.startEmailCounter();;
-  }
-
-  private startEmailCounter() {
-    this.emailResendInterval = setInterval(() => {
-      this.emailCounterSec -= 1;
-      if (this.emailResendCounter !== 0) {
-        this.emailResendCounter -= 1;
-      }
-      if (this.emailCounterSec === 0) {
-        clearInterval(this.emailResendInterval);
-      }
-    }, 1000)
-  }
-
-  private startPhoneCounter() {
-    this.otpInterval = setInterval(() => {
-      this.otpCounterSec -= 1;
-      if (this.otpResendCounter !== 0) {
-        this.otpResendCounter -= 1;
-      }
-      if (this.otpCounterSec === 0) {
-        clearInterval(this.otpInterval)
-      }
-    }, 1000)
-  }
-
-  private setRegisterInfo(): RegisterInfo {
-    return this.connectDevice === 'MOBILE'
-      ? {
-          phone: this.phoneNumber,
-          indexKey: this.phoneOtpInfo.indexKey,
-          otpCode: this.otpCode,
-          name: this.name,
-          contactType: 'SMS'
-        }
-      : {
-          email: this.email,
-          indexKey: this.emailOtpInfo.indexKey,
-          otpCode: this.otpCode,
-          name: this.name,
-          contactType: 'EMAIL'
-        }
-  }
-
-  private storagePhoneOrEmail(registerInfo:RegisterInfo):void{
-    const info = {...registerInfo, time: new Date()}
-    localStorage.setItem('userInfo',JSON.stringify(info));
-  }
-
-  private removeOtpTime() {
-    localStorage.removeItem('emailOtpTime');
-    localStorage.removeItem('phoneOtpTime');
-  }
-
-  private setLoginInfo() {
-    const isMobile = this.connectDevice === 'MOBILE'
-    return {
-      account: isMobile ? this.phoneNumber : this.email,
-      indexKey: isMobile ? this.phoneOtpInfo.indexKey : this.emailOtpInfo.indexKey,
-      otpCode: isMobile ? this.otpCode : this.emailOtpCode
-    }
-  }
-}
-</script>
-
-<style lang="scss">
-.pam-login-page {
-    font-size: 20px !important;
-    display: flex;
-    flex-direction: column;
-    .pam-login-page__action-bar {
-      display: flex;
-      flex: 1;
-      align-items: flex-end;
-      @include desktop {
-        margin-bottom: 30px;
-      }
-    }
-  }
-
-  .pam-input {
-    height: 26px;
-    width: calc(100% - 36px);
-    border-radius: 10px !important;
-    padding: 12px 18px !important;
-    border:1px solid #CCCCCC;
-    outline: 0;
-    @extend .text--middle;
-    &::placeholder {
-      color: $PRUDENTIAL_GREY;
-    }
-    &.is-invalid {
-      border: 1px solid $PRIMARY_RED !important;
-      border-radius: 20px;
-    }
-  }
-
-.pam-register-dialog__contract {
-  $DEVICE_EXTRA_HEIGHT: 42px;
-  $ALIGN_PADDING: 60px;
-  $TOP_CONTENT_HEIGHT: 186px;
-  $BOTTOM_CONTENT_HEIGHT: 131px;
-  max-height: calc(100vh - $DEVICE_EXTRA_HEIGHT - $ALIGN_PADDING - $TOP_CONTENT_HEIGHT - $BOTTOM_CONTENT_HEIGHT);
-  overflow-y: scroll;
-  border-radius: 6px;
-  border: 1px solid #707070;
-  padding: 20px;
-  @include desktop {
-    height: 335px;
-  }
-}
-
-  .pam-radio {
-    color: $PRIMARY_RED;
-    align-items: center;
-    display: flex;
-    font-size: 20px;
-    font-weight: bold;
-    input {
-      display: none;
-    }
-    i {
-      font-size: 27px;
-      padding-right: 5px;
-    }
-  }
-
-  .pam-field-title__hint {
-    @extend .smTxt_bold;
-    color: #68737A;
-  }
-
-  .error {
-    @extend .smTxt_bold;
-    @extend .text--primary;
-    height: 16px;
-  }
-
-  .pam-popUp-title {
-      font-size: 20px;
-      line-height: 27px;
-  }
-
-  .pam-popUp-txt {
-    font-size: 18px;
-    color: $MID_GREY;
-  }
-
-  .disabled {
-    color: #A7A8AA;
-  }
-
-  .pam-input-position {
-    position: relative;
-    .icon-close {
-      cursor: pointer;
-      position: absolute;
-      right: 15px;
-      top: 28px;
-      font-size: 16px;
-    }
-  }
+<style lang="scss" scoped>
+  @import "./login.component.scss";
 </style>
diff --git a/PAMapp/pages/login/login.component.scss b/PAMapp/pages/login/login.component.scss
new file mode 100644
index 0000000..ff9f53f
--- /dev/null
+++ b/PAMapp/pages/login/login.component.scss
@@ -0,0 +1,97 @@
+
+.pam-login-page {
+    font-size: 20px !important;
+    display: flex;
+    flex-direction: column;
+    .pam-login-page__action-bar {
+      display: flex;
+      flex: 1;
+      align-items: flex-end;
+      @include desktop {
+        margin-bottom: 30px;
+      }
+    }
+  }
+
+  .pam-input {
+    height: 26px;
+    width: calc(100% - 36px);
+    border-radius: 10px !important;
+    padding: 12px 18px !important;
+    border:1px solid #CCCCCC;
+    outline: 0;
+    @extend .text--middle;
+    &::placeholder {
+      color: $PRUDENTIAL_GREY;
+    }
+    &.is-invalid {
+      border: 1px solid $PRIMARY_RED !important;
+      border-radius: 20px;
+    }
+  }
+
+.pam-register-dialog__contract {
+  $DEVICE_EXTRA_HEIGHT: 42px;
+  $ALIGN_PADDING: 60px;
+  $TOP_CONTENT_HEIGHT: 186px;
+  $BOTTOM_CONTENT_HEIGHT: 131px;
+  max-height: calc(100vh - $DEVICE_EXTRA_HEIGHT - $ALIGN_PADDING - $TOP_CONTENT_HEIGHT - $BOTTOM_CONTENT_HEIGHT);
+  overflow-y: scroll;
+  border-radius: 6px;
+  border: 1px solid #707070;
+  padding: 20px;
+  @include desktop {
+    height: 335px;
+  }
+}
+
+  .pam-radio {
+    color: $PRIMARY_RED;
+    align-items: center;
+    display: flex;
+    font-size: 20px;
+    font-weight: bold;
+    input {
+      display: none;
+    }
+    i {
+      font-size: 27px;
+      padding-right: 5px;
+    }
+  }
+
+  .pam-field-title__hint {
+    @extend .smTxt_bold;
+    color: #68737A;
+  }
+
+  .error {
+    @extend .smTxt_bold;
+    @extend .text--primary;
+    height: 16px;
+  }
+
+  .pam-popUp-title {
+      font-size: 20px;
+      line-height: 27px;
+  }
+
+  .pam-popUp-txt {
+    font-size: 18px;
+    color: $MID_GREY;
+  }
+
+  .disabled {
+    color: #A7A8AA;
+  }
+
+  .pam-input-position {
+    position: relative;
+    .icon-close {
+      cursor: pointer;
+      position: absolute;
+      right: 15px;
+      top: 28px;
+      font-size: 16px;
+    }
+  }
diff --git a/PAMapp/pages/login/login.component.ts b/PAMapp/pages/login/login.component.ts
new file mode 100644
index 0000000..3bde506
--- /dev/null
+++ b/PAMapp/pages/login/login.component.ts
@@ -0,0 +1,373 @@
+
+import { namespace } from 'nuxt-property-decorator';
+import { Vue, Component, Ref } from 'vue-property-decorator';
+import { LoginRequest, LoginVerify, loginVerify, OtpInfo, register, RegisterInfo, sendOtp } from '~/assets/ts/api/consultant';
+import ErrorMessageBox from '~/assets/ts/errorService';
+import { OtpErrorCode } from '~/assets/ts/models/enum/otpErrorCode';
+import { Role } from '~/assets/ts/models/enum/role.enum';
+
+const roleStorage = namespace('localStorage');
+
+@Component
+export default class Login extends Vue {
+  @roleStorage.Mutation storageIdToken!: (token:string) => void;
+  @roleStorage.Mutation storageRole!: (role:string) => void;
+  @Ref('contract') readonly contract!: any;
+
+  connectDevice: 'MOBILE' | 'EMAIL' = 'MOBILE';
+
+  phoneNumber = '';
+  otpCode = '';
+  onPhoneVerifyStep: 'APPLY_OTP' | 'INPUT_OTP' | 'SUBMIT_OTP' = 'APPLY_OTP';
+  otpCounterSec = 900;
+  otpResendCounter = 30;
+  otpInterval: any;
+  phoneOtpInfo!: OtpInfo;
+
+  email = '';
+  onEmailVerifyResendStatus: 'APPLY_OTP' | 'CAN_RESEND' = 'APPLY_OTP';
+  emailCounterSec = 900;
+  emailResendCounter = 30;
+  emailOtpCode = '';
+  emailResendInterval: any;
+  emailOtpInfo!: OtpInfo;
+
+  autoRedirectCounter = 3;
+  autoRedirectInterval: any;
+
+  name = '';
+  agreeContract = false;
+  isReadContract = false;
+
+  phoneSuccessConfirmVisable = false;
+  emailOtpConfirmVisable = false;
+
+  registerDialogVisible = false;
+  registerSuccessConfirmVisable = false;
+
+  applyAccount_onAction = false;
+
+  previousPath = '';
+  mounted() {
+    const phoneOtpTime = localStorage.getItem('phoneOtpTime');
+    const emailOtpTime = localStorage.getItem('emailOtpTime');
+    const parsePhoneOtpTime = phoneOtpTime ? JSON.parse(phoneOtpTime) : '';
+    const parseEmailOtpTime = emailOtpTime ? JSON.parse(emailOtpTime) : '';
+    if (parsePhoneOtpTime && parsePhoneOtpTime.contactType === 'SMS') {
+      this.phoneDiffTime(parsePhoneOtpTime);
+    }
+    if (parseEmailOtpTime && parseEmailOtpTime.contactType === 'EMAIL') {
+      this.emailDiffTime(parseEmailOtpTime);
+    }
+  }
+
+  detectContractReadStatus(event: any): void {
+    const scrollTop = Math.round(event.target.scrollTop);
+    const height = event.target.scrollHeight - event.target.clientHeight;
+    if (Math.floor(scrollTop/10) === (Math.floor(height/10))) {
+      this.isReadContract = true;
+    }
+  };
+
+  get isSubmitBtnDisabled(): boolean {
+    return this.connectDevice === 'MOBILE'
+      ? (!this.otpCode || !this.phoneNumber || !this.phoneValid || !this.otpCounterSec)
+      : (!this.emailOtpCode || !this.email || !this.emailValid || !this.emailCounterSec)
+  }
+
+  get phoneCounter() {
+    let min = Math.floor(this.otpCounterSec / 60);
+    let sec = Math.floor(this.otpCounterSec % 60);
+    return `${min < 10 ? '0' + min : min}:${sec < 10 ? '0' + sec : sec}`;
+  }
+
+  get emailOtpCounter() {
+    let min = Math.floor(this.emailCounterSec / 60);
+    let sec = Math.floor(this.emailCounterSec % 60);
+    return `${min < 10 ? '0' + min : min}:${sec < 10 ? '0' + sec : sec}`;
+  }
+
+  get showPhoneOtpCodeField(): boolean {
+    return this.connectDevice === 'MOBILE' && this.onPhoneVerifyStep === 'INPUT_OTP';
+  };
+
+  get showEmailVerifyField(): boolean {
+    return this.connectDevice === 'EMAIL' && this.onEmailVerifyResendStatus === 'CAN_RESEND';
+  };
+
+  get phoneValid() {
+    const rule = /^09[0-9]{8}$/;
+    return this.phoneNumber ? rule.test(this.phoneNumber) : true;
+  }
+
+  get emailValid() {
+    const rule = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/;
+    return this.email ? rule.test(this.email) : true;
+  }
+
+  applyOtpVerification(type: string): void {
+    const isMobile = this.connectDevice === 'MOBILE';
+    const loginInfo: LoginRequest = {
+      loginType: isMobile ? 'SMS' : 'EMAIL',
+      account: isMobile ? this.phoneNumber : this.email,
+    }
+    sendOtp(loginInfo).then(otpInfo => {
+      if (otpInfo.success) {
+        this.storageOtpTime(type, otpInfo);
+        this.startOtpSetting(type);
+        this.startOtpCount(type);
+      } else {
+        const errorMsg = OtpErrorCode[otpInfo.failCode] ? OtpErrorCode[otpInfo.failCode]:'OTP蝟餌絞�隤�';
+        ErrorMessageBox(errorMsg);
+      }
+    });
+  };
+
+  resentOtp(type: string) {
+    this.resetOtpSetting(type);
+    this.applyOtpVerification(type);
+  }
+
+  deleteOtpInfo(type: string) {
+    this.resetOtpSetting(type);
+    if (type === 'MOBILE') {
+      this.onPhoneVerifyStep = 'APPLY_OTP';
+      this.phoneNumber = '';
+      this.otpCode = '';
+    } else {
+      this.onEmailVerifyResendStatus = 'APPLY_OTP';
+      this.email = '';
+      this.emailOtpCode = '';
+    }
+    this.removeOtpTime();
+  }
+
+  applyAccount(): void {
+    if (this.applyAccount_onAction) {
+      return ;
+    }
+
+    this.applyAccount_onAction = true;
+    const registerInfo = this.setRegisterInfo();
+
+    register(registerInfo).then(res => {
+      this.storageIdToken(res.data.id_token);
+      this.storageRole(Role.USER);
+      this.storagePhoneOrEmail(registerInfo);
+      this.autoRedirect();
+      this.registerSuccessConfirmVisable = true;
+    }).catch(() => {
+      this.applyAccount_onAction = false;
+    });
+  };
+
+  confirmApplySuccess(): void {
+    this.phoneSuccessConfirmVisable = false;
+    this.registerSuccessConfirmVisable = false;
+    this.redirect();
+  }
+
+  private autoRedirect() {
+    this.autoRedirectInterval = setInterval(() => {
+      this.autoRedirectCounter -= 1;
+
+      if (this.autoRedirectCounter === 0) {
+        clearInterval(this.autoRedirectInterval);
+        this.redirect();
+      }
+    }, 1000)
+  }
+
+  private redirect() {
+    const backToPrevious = ['questionnaire', 'myConsultantList'];
+    const find = backToPrevious.findIndex(item => this.previousPath.includes(item));
+    console.log(this.previousPath, find, 'redirect');
+    find > -1 ? this.$router.go(-1) : this.$router.push('/');
+  }
+
+  beforeRouteEnter (to, from, next) {
+      next(vm => {
+        console.log(from.path, 'beforeRouteEnter');
+        vm.previousPath = from.path;
+      })
+    }
+
+  login() {
+    const login: LoginVerify = this.setLoginInfo();
+    this.removeOtpTime();
+    loginVerify(login).then(res => {
+      this.storageIdToken(res.data.id_token);
+      this.storageRole(Role.USER);
+      this.phoneSuccessConfirmVisable = true;
+      this.autoRedirect();
+      this.storagePhoneOrEmail(this.setRegisterInfo());
+    }).catch(error => {
+      this.checkHttpErrorStatus(error);
+    });
+  }
+  private checkHttpErrorStatus(error:any):void{
+    switch (error.response.status) {
+        case 401:
+          const errorMsg = OtpErrorCode[error.response?.data?.detail] ? OtpErrorCode[error.response?.data?.detail]:'OTP蝟餌絞�隤�';
+          ErrorMessageBox(errorMsg);
+          break;
+        case 403:
+          this.registerDialogVisible = true;
+          setTimeout(() => {
+            const isScrollBarNeedless = this.contract.scrollHeight <= this.contract.clientHeight;
+            if (isScrollBarNeedless) {
+              this.isReadContract = true;
+            }
+          }, 1000);
+          break;
+        default:
+          ErrorMessageBox('',error);
+          break;
+      }
+  }
+
+  destroyed() {
+    this.removeOtpTime();
+    clearInterval(this.otpInterval);
+    clearInterval(this.emailResendInterval);
+    clearInterval(this.autoRedirectInterval);
+  }
+
+  private phoneDiffTime(parseOtpTime: any) {
+    const diffSecs = this.calcDiffSecs(parseOtpTime.time);
+
+    if (diffSecs < this.otpCounterSec) {
+      this.otpResendCounter = diffSecs < 30 ? 30 - diffSecs : 0;
+        this.otpCounterSec -= diffSecs;
+        this.phoneNumber = parseOtpTime.phone;
+        this.onPhoneVerifyStep = 'INPUT_OTP';
+        this.phoneOtpInfo = this.setOtpInfo(parseOtpTime);
+        this.startOtpCount('MOBILE');
+    } else {
+      localStorage.removeItem('phoneOtpTime');
+    }
+  }
+
+  private emailDiffTime(parseOtpTime: any) {
+    const diffSecs = this.calcDiffSecs(parseOtpTime.time);
+
+    if (diffSecs < this.emailCounterSec) {
+      this.emailResendCounter =  diffSecs < 30 ? 30 - diffSecs : 0;
+      this.emailCounterSec -= diffSecs;
+      this.email = parseOtpTime.email;
+      this.onEmailVerifyResendStatus = 'CAN_RESEND';
+      this.emailOtpInfo = this.setOtpInfo(parseOtpTime);
+      this.startOtpCount('EMAIL');
+    } else {
+      localStorage.removeItem('emailOtpTime');
+    }
+  }
+
+  private calcDiffSecs(parseOtpTime) {
+    const currentTime = new Date().getTime();
+    const storageTime = new Date(parseOtpTime).getTime();
+    return Math.floor((currentTime - storageTime) / 1000);
+  }
+
+  private resetOtpSetting(type: string) {
+    if (type === 'MOBILE') {
+      clearInterval(this.otpInterval);
+      this.otpResendCounter = 30;
+      this.otpCounterSec = 900;
+    } else {
+      clearInterval(this.emailResendInterval);
+      this.emailResendCounter = 30;
+      this.emailCounterSec = 900;
+    }
+  }
+
+  private setOtpInfo(parseOtpTime) {
+    return {
+      indexKey: parseOtpTime.indexKey,
+      success: true,
+      failCode: '',
+      failReason: '',
+    }
+  }
+
+  private storageOtpTime(type: string, otpInfo: OtpInfo) {
+    type === 'MOBILE' ? this.phoneOtpInfo = otpInfo : this.emailOtpInfo = otpInfo;
+    const info = {...this.setRegisterInfo(), time: new Date()}
+    type === 'MOBILE' ? localStorage.setItem('phoneOtpTime',JSON.stringify(info))
+                      : localStorage.setItem('emailOtpTime',JSON.stringify(info));
+  }
+
+  private startOtpSetting(type: string) {
+    if (type === 'MOBILE') {
+      this.onPhoneVerifyStep = 'INPUT_OTP';
+    } else {
+      this.onEmailVerifyResendStatus = 'CAN_RESEND';
+      this.emailOtpConfirmVisable = true;
+    }
+  }
+
+  private startOtpCount(type: string) {
+    type === 'MOBILE' ? this.startPhoneCounter() : this.startEmailCounter();;
+  }
+
+  private startEmailCounter() {
+    this.emailResendInterval = setInterval(() => {
+      this.emailCounterSec -= 1;
+      if (this.emailResendCounter !== 0) {
+        this.emailResendCounter -= 1;
+      }
+      if (this.emailCounterSec === 0) {
+        clearInterval(this.emailResendInterval);
+      }
+    }, 1000)
+  }
+
+  private startPhoneCounter() {
+    this.otpInterval = setInterval(() => {
+      this.otpCounterSec -= 1;
+      if (this.otpResendCounter !== 0) {
+        this.otpResendCounter -= 1;
+      }
+      if (this.otpCounterSec === 0) {
+        clearInterval(this.otpInterval)
+      }
+    }, 1000)
+  }
+
+  private setRegisterInfo(): RegisterInfo {
+    return this.connectDevice === 'MOBILE'
+      ? {
+          phone: this.phoneNumber,
+          indexKey: this.phoneOtpInfo.indexKey,
+          otpCode: this.otpCode,
+          name: this.name,
+          contactType: 'SMS'
+        }
+      : {
+          email: this.email,
+          indexKey: this.emailOtpInfo.indexKey,
+          otpCode: this.otpCode,
+          name: this.name,
+          contactType: 'EMAIL'
+        }
+  }
+
+  private storagePhoneOrEmail(registerInfo:RegisterInfo):void{
+    const info = {...registerInfo, time: new Date()}
+    localStorage.setItem('userInfo',JSON.stringify(info));
+  }
+
+  private removeOtpTime() {
+    localStorage.removeItem('emailOtpTime');
+    localStorage.removeItem('phoneOtpTime');
+  }
+
+  private setLoginInfo() {
+    const isMobile = this.connectDevice === 'MOBILE'
+    return {
+      account: isMobile ? this.phoneNumber : this.email,
+      indexKey: isMobile ? this.phoneOtpInfo.indexKey : this.emailOtpInfo.indexKey,
+      otpCode: isMobile ? this.otpCode : this.emailOtpCode
+    }
+  }
+}
diff --git a/PAMapp/pages/myAppointmentList.vue b/PAMapp/pages/myAppointmentList.vue
deleted file mode 100644
index 85a57da..0000000
--- a/PAMapp/pages/myAppointmentList.vue
+++ /dev/null
@@ -1,133 +0,0 @@
-<template>
-    <div>
-        <div class="pam-myAppointment-banner"></div>
-        <div class="pam-container">
-            <div class="pam-cus-tabs mb-30">
-                <div
-                    class="cus-tab-item"
-                    :class="{'is-active': activeTabName === 'appointmentList'}"
-                    @click="tabClick('appointmentList')"
-                >摰X����
-                    <span class="p">({{appointmentList.length}})</span>
-                </div>
-                <div
-                    class="cus-tab-item"
-                    :class="{'is-active': activeTabName === 'contactedList'}"
-                    @click="tabClick('contactedList')"
-                >撌脰蝯�
-                    <span class="p">({{contactedList.length}})</span>
-                </div>
-            </div>
-
-            <NuxtChild></NuxtChild>
-        </div>
-
-        <PopUpFrame
-             :isOpen.sync="showNewAppointmentNumber"
-        >
-            <div class="text--center mdTxt">
-                <p class="mb-50">雿�� <span class="text--primary">{{newAppointmentNumber}}</span> �������</p>
-                <div class="text--center">
-                    <el-button
-                        type="primary"
-                        @click="showNewAppointmentNumber = false"
-                    >������</el-button>
-                </div>
-            </div>
-        </PopUpFrame>
-    </div>
-</template>
-
-<script lang="ts">
-import { Vue, Component, State, Action, Watch } from 'nuxt-property-decorator';
-import { allAppointmentsView, ClientInfo } from '~/assets/ts/api/appointment';
-import * as _ from 'lodash';
-
-@Component({
-    layout: 'home'
-})
-export default class ClientReservedList extends Vue {
-    activeTabName = 'appointmentList';
-    appointmentList: ClientInfo[] = [];
-    contactedList: ClientInfo[] = [];
-    clients: ClientInfo[] = [];
-    newAppointmentNumber: number = 0;
-    showNewAppointmentNumber = false;
-
-    @State('myAppointmentList') myAppointmentList!: ClientInfo[];
-    @Action storeMyAppointmentList!: () => Promise<number>;
-
-    mounted() {
-     this.storeMyAppointmentList().then(newDataLength => {
-         this.newAppointmentNumber = newDataLength;
-         if (this.newAppointmentNumber > 0) {
-             this.showNewAppointmentNumber = true;
-             allAppointmentsView().then(res => res);
-         }
-    });
-
-     if (this.$route.name) {
-         this.activeTabName = this.$route.name.split('-')[1]
-     }
-    }
-
-    @Watch('myAppointmentList')
-    onMyAppointmentListChange() {
-        this.contactedList = this.myAppointmentList
-            .filter(item => item.communicateStatus === 'contacted');
-
-        this.appointmentList = this.myAppointmentList
-            .filter(item => item.communicateStatus !== 'contacted');
-    }
-
-    tabClick(path: string) {
-        this.activeTabName = path;
-        this.$router.push('/myAppointmentList/' + this.activeTabName)
-    }
-
-    get route(): string{
-        const routeName = this.$route.name;
-        return routeName ? routeName:'';
-    };
-
-    get bannerClassName() {
-        return this.routeFormatBannerClass(this.route);
-    };
-
-    // format to {page}-banner or pam-no-banner tag
-    private routeFormatBannerClass(route: string): string {
-        const needBannerTags = ['myAppointmentList-appointmentList', 'myAppointmentList-contactedList'];
-        return _.includes(needBannerTags, route) ? route + '-banner' : 'pam-no-banner';
-    };
-
-}
-</script>
-
-<style lang="scss" scoped>
-    .pam-myAppointment-banner {
-        width: 100%;
-        height: 120px;
-        background-size: cover;
-        background-repeat: no-repeat;
-        background-position: center;
-        position: relative;
-        background-image: url('~/assets/images/myAppointmentList/agent_banner_mob.svg');
-    }
-
-    @media (min-width: 768px) {
-        .pam-myAppointment-banner {
-            background-image: url('~/assets/images/myAppointmentList/agent_banner_web.svg');
-        }
-    }
-
-    .pam-container {
-        margin: 30px 20px;
-    }
-
-    @include desktop {
-        .pam-container {
-            width: 700px;
-            margin: 30px auto;
-        }
-    }
-</style>
\ No newline at end of file
diff --git a/PAMapp/pages/myAppointmentList/appointmentList/appointment-list.component.scss b/PAMapp/pages/myAppointmentList/appointmentList/appointment-list.component.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/PAMapp/pages/myAppointmentList/appointmentList/appointment-list.component.scss
diff --git a/PAMapp/pages/myAppointmentList/appointmentList.vue b/PAMapp/pages/myAppointmentList/appointmentList/appointment-list.component.ts
similarity index 67%
rename from PAMapp/pages/myAppointmentList/appointmentList.vue
rename to PAMapp/pages/myAppointmentList/appointmentList/appointment-list.component.ts
index 8cee481..03e33bc 100644
--- a/PAMapp/pages/myAppointmentList/appointmentList.vue
+++ b/PAMapp/pages/myAppointmentList/appointmentList/appointment-list.component.ts
@@ -1,28 +1,3 @@
-<template>
-    <div>
-        <el-input
-            type="text"
-            placeholder="隢撓���摮�"
-            class="mb-30 pam-clientReserved-input"
-            v-model="keyWord"
-            @keyup.enter.native="search"
-        >
-            <i slot="suffix" class="icon-search search cursor--pointer" @click="search"></i>
-        </el-input>
-
-        <ClientList
-            :clients="pageList"
-            :title="'reservedList'"
-        ></ClientList>
-
-        <UiPagination
-            :totalList="filterList"
-            @changePage="changePage"
-        ></UiPagination>
-    </div>
-</template>
-
-<script lang="ts">
 import { Vue, Component, State, Watch } from 'nuxt-property-decorator';
 import { ClientInfo } from '~/assets/ts/api/appointment';
 
@@ -64,4 +39,3 @@
     }
 
 }
-</script>
\ No newline at end of file
diff --git a/PAMapp/pages/myAppointmentList/appointmentList/index.vue b/PAMapp/pages/myAppointmentList/appointmentList/index.vue
new file mode 100644
index 0000000..e9212ad
--- /dev/null
+++ b/PAMapp/pages/myAppointmentList/appointmentList/index.vue
@@ -0,0 +1,29 @@
+<template>
+    <div>
+        <el-input
+            type="text"
+            placeholder="隢撓���摮�"
+            class="mb-30 pam-clientReserved-input"
+            v-model="keyWord"
+            @keyup.enter.native="search"
+        >
+            <i slot="suffix" class="icon-search search cursor--pointer" @click="search"></i>
+        </el-input>
+
+        <ClientList
+            :clients="pageList"
+            :title="'reservedList'"
+        ></ClientList>
+
+        <UiPagination
+            :totalList="filterList"
+            @changePage="changePage"
+        ></UiPagination>
+    </div>
+</template>
+
+<script src="./appointment-list.component.ts"></script>
+
+<style lang="scss" scoped>
+  @import "./appointment-list.component.scss";
+</style>
diff --git a/PAMapp/pages/myAppointmentList/contactedList.vue b/PAMapp/pages/myAppointmentList/contactedList.vue
deleted file mode 100644
index 15954b7..0000000
--- a/PAMapp/pages/myAppointmentList/contactedList.vue
+++ /dev/null
@@ -1,64 +0,0 @@
-<template>
-    <div>
-        <el-input
-            type="text"
-            placeholder="隢撓���摮�"
-            class="mb-30 pam-clientReserved-input"
-            v-model="keyWord"
-            @keyup.enter.native="search"
-        >
-            <i
-                slot="suffix"
-                class="icon-search search cursor--pointer"
-                @click="search"
-            ></i>
-        </el-input>
-
-        <ClientList
-            :clients="pageList"
-            :title="'contactedList'"
-        ></ClientList>
-
-        <UiPagination
-            :totalList="filterList"
-            @changePage="changePage"
-        ></UiPagination>
-    </div>
-</template>
-
-<script lang="ts">
-import { Vue, Component, Watch, State } from 'nuxt-property-decorator';
-import { ClientInfo } from '~/assets/ts/api/appointment';
-
-@Component
-export default class ClientContactedList extends Vue {
-    @State('myAppointmentList') myAppointmentList!: ClientInfo[];
-
-    contactedList: ClientInfo[] = [];
-    pageList: ClientInfo[] = [];
-    keyWord: string = '';
-    filterList: ClientInfo[] = [];
-
-    @Watch('myAppointmentList')
-    onMyAppointmentListChange() {
-        this.contactedList = (this.myAppointmentList || [])
-            .filter(item => item.communicateStatus === 'contacted')
-            .sort((a, b) => a.contactTime > b.contactTime ? -1 : 1);
-        this.filterList = this.contactedList;
-    }
-
-    mounted() {
-        this.onMyAppointmentListChange();
-    }
-
-    changePage(pageList: ClientInfo[]) {
-        this.pageList = pageList;
-    }
-
-    search() {
-        this.filterList = this.contactedList.filter(item => {
-            return item.name.match(this.keyWord) || item.requirement.match(this.keyWord)
-        })
-    }
-}
-</script>
\ No newline at end of file
diff --git a/PAMapp/pages/myAppointmentList/contactedList/contacted-list.component.scss b/PAMapp/pages/myAppointmentList/contactedList/contacted-list.component.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/PAMapp/pages/myAppointmentList/contactedList/contacted-list.component.scss
diff --git a/PAMapp/pages/myAppointmentList/contactedList/contacted-list.component.ts b/PAMapp/pages/myAppointmentList/contactedList/contacted-list.component.ts
new file mode 100644
index 0000000..7c2aeb2
--- /dev/null
+++ b/PAMapp/pages/myAppointmentList/contactedList/contacted-list.component.ts
@@ -0,0 +1,34 @@
+import { Vue, Component, Watch, State } from 'nuxt-property-decorator';
+import { ClientInfo } from '~/assets/ts/api/appointment';
+
+@Component
+export default class ClientContactedList extends Vue {
+    @State('myAppointmentList') myAppointmentList!: ClientInfo[];
+
+    contactedList: ClientInfo[] = [];
+    pageList: ClientInfo[] = [];
+    keyWord: string = '';
+    filterList: ClientInfo[] = [];
+
+    @Watch('myAppointmentList')
+    onMyAppointmentListChange() {
+        this.contactedList = (this.myAppointmentList || [])
+            .filter(item => item.communicateStatus === 'contacted')
+            .sort((a, b) => a.contactTime > b.contactTime ? -1 : 1);
+        this.filterList = this.contactedList;
+    }
+
+    mounted() {
+        this.onMyAppointmentListChange();
+    }
+
+    changePage(pageList: ClientInfo[]) {
+        this.pageList = pageList;
+    }
+
+    search() {
+        this.filterList = this.contactedList.filter(item => {
+            return item.name.match(this.keyWord) || item.requirement.match(this.keyWord)
+        })
+    }
+}
diff --git a/PAMapp/pages/myAppointmentList/contactedList/index.vue b/PAMapp/pages/myAppointmentList/contactedList/index.vue
new file mode 100644
index 0000000..6c3d427
--- /dev/null
+++ b/PAMapp/pages/myAppointmentList/contactedList/index.vue
@@ -0,0 +1,33 @@
+<template>
+    <div>
+        <el-input
+            type="text"
+            placeholder="隢撓���摮�"
+            class="mb-30 pam-clientReserved-input"
+            v-model="keyWord"
+            @keyup.enter.native="search"
+        >
+            <i
+                slot="suffix"
+                class="icon-search search cursor--pointer"
+                @click="search"
+            ></i>
+        </el-input>
+
+        <ClientList
+            :clients="pageList"
+            :title="'contactedList'"
+        ></ClientList>
+
+        <UiPagination
+            :totalList="filterList"
+            @changePage="changePage"
+        ></UiPagination>
+    </div>
+</template>
+
+<script src="./contacted-list.component.ts"></script>
+
+<style lang="scss" scoped>
+  @import "./contacted-list.component.scss";
+</style>
diff --git a/PAMapp/pages/myAppointmentList/index.vue b/PAMapp/pages/myAppointmentList/index.vue
new file mode 100644
index 0000000..de9a850
--- /dev/null
+++ b/PAMapp/pages/myAppointmentList/index.vue
@@ -0,0 +1,45 @@
+<template>
+    <div>
+        <div class="pam-myAppointment-banner"></div>
+        <div class="pam-container">
+            <div class="pam-cus-tabs mb-30">
+                <div
+                    class="cus-tab-item"
+                    :class="{'is-active': activeTabName === 'appointmentList'}"
+                    @click="tabClick('appointmentList')"
+                >摰X����
+                    <span class="p">({{appointmentList.length}})</span>
+                </div>
+                <div
+                    class="cus-tab-item"
+                    :class="{'is-active': activeTabName === 'contactedList'}"
+                    @click="tabClick('contactedList')"
+                >撌脰蝯�
+                    <span class="p">({{contactedList.length}})</span>
+                </div>
+            </div>
+
+            <NuxtChild></NuxtChild>
+        </div>
+
+        <PopUpFrame
+             :isOpen.sync="showNewAppointmentNumber"
+        >
+            <div class="text--center mdTxt">
+                <p class="mb-50">雿�� <span class="text--primary">{{newAppointmentNumber}}</span> �������</p>
+                <div class="text--center">
+                    <el-button
+                        type="primary"
+                        @click="showNewAppointmentNumber = false"
+                    >������</el-button>
+                </div>
+            </div>
+        </PopUpFrame>
+    </div>
+</template>
+
+<script src="./my-appointment.component.ts"></script>
+
+<style lang="scss" scoped>
+  @import "./my-appointment.component.scss";
+</style>
diff --git a/PAMapp/pages/myAppointmentList/my-appointment.component.scss b/PAMapp/pages/myAppointmentList/my-appointment.component.scss
new file mode 100644
index 0000000..46456ad
--- /dev/null
+++ b/PAMapp/pages/myAppointmentList/my-appointment.component.scss
@@ -0,0 +1,26 @@
+.pam-myAppointment-banner {
+    width: 100%;
+    height: 120px;
+    background-size: cover;
+    background-repeat: no-repeat;
+    background-position: center;
+    position: relative;
+    background-image: url('~/assets/images/myAppointmentList/agent_banner_mob.svg');
+}
+
+@media (min-width: 768px) {
+    .pam-myAppointment-banner {
+        background-image: url('~/assets/images/myAppointmentList/agent_banner_web.svg');
+    }
+}
+
+.pam-container {
+    margin: 30px 20px;
+}
+
+@include desktop {
+    .pam-container {
+        width: 700px;
+        margin: 30px auto;
+    }
+}
diff --git a/PAMapp/pages/myAppointmentList/my-appointment.component.ts b/PAMapp/pages/myAppointmentList/my-appointment.component.ts
new file mode 100644
index 0000000..032d362
--- /dev/null
+++ b/PAMapp/pages/myAppointmentList/my-appointment.component.ts
@@ -0,0 +1,63 @@
+
+import { Vue, Component, State, Action, Watch } from 'nuxt-property-decorator';
+import { allAppointmentsView, ClientInfo } from '~/assets/ts/api/appointment';
+import * as _ from 'lodash';
+
+@Component({
+    layout: 'home'
+})
+export default class ClientReservedList extends Vue {
+    activeTabName = 'appointmentList';
+    appointmentList: ClientInfo[] = [];
+    contactedList: ClientInfo[] = [];
+    clients: ClientInfo[] = [];
+    newAppointmentNumber: number = 0;
+    showNewAppointmentNumber = false;
+
+    @State('myAppointmentList') myAppointmentList!: ClientInfo[];
+    @Action storeMyAppointmentList!: () => Promise<number>;
+
+    mounted() {
+     this.storeMyAppointmentList().then(newDataLength => {
+         this.newAppointmentNumber = newDataLength;
+         if (this.newAppointmentNumber > 0) {
+             this.showNewAppointmentNumber = true;
+             allAppointmentsView().then(res => res);
+         }
+    });
+
+     if (this.$route.name) {
+         this.activeTabName = this.$route.name.split('-')[1]
+     }
+    }
+
+    @Watch('myAppointmentList')
+    onMyAppointmentListChange() {
+        this.contactedList = this.myAppointmentList
+            .filter(item => item.communicateStatus === 'contacted');
+
+        this.appointmentList = this.myAppointmentList
+            .filter(item => item.communicateStatus !== 'contacted');
+    }
+
+    tabClick(path: string) {
+        this.activeTabName = path;
+        this.$router.push('/myAppointmentList/' + this.activeTabName)
+    }
+
+    get route(): string{
+        const routeName = this.$route.name;
+        return routeName ? routeName:'';
+    };
+
+    get bannerClassName() {
+        return this.routeFormatBannerClass(this.route);
+    };
+
+    // format to {page}-banner or pam-no-banner tag
+    private routeFormatBannerClass(route: string): string {
+        const needBannerTags = ['myAppointmentList-appointmentList', 'myAppointmentList-contactedList'];
+        return _.includes(needBannerTags, route) ? route + '-banner' : 'pam-no-banner';
+    };
+
+}
diff --git a/PAMapp/pages/myConsultantList/consultantList.vue b/PAMapp/pages/myConsultantList/consultantList.vue
deleted file mode 100644
index b1b0a5c..0000000
--- a/PAMapp/pages/myConsultantList/consultantList.vue
+++ /dev/null
@@ -1,30 +0,0 @@
-<template>
-    <div>
-        <ConsultantList
-            :agents="pageList"
-        ></ConsultantList>
-
-        <UiPagination
-            :totalList="consultantList"
-            @changePage="changePage"
-        ></UiPagination>
-    </div>
-</template>
-
-<script lang="ts">
-import { Vue, Component, Prop, Getter } from 'nuxt-property-decorator';
-import { Consultant } from '~/assets/ts/models/consultant.model';
-
-
-@Component
-export default class ConsultantPage extends Vue {
-    @Prop() consultantList!: Consultant[];
-    @Getter isLogin!: boolean;
-    pageList: Consultant[] = [];
-
-    changePage(pageList: Consultant[]) {
-        this.pageList = pageList;
-    }
-
-}
-</script>
\ No newline at end of file
diff --git a/PAMapp/pages/myConsultantList/consultantList/consultant-list.component.scss b/PAMapp/pages/myConsultantList/consultantList/consultant-list.component.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/PAMapp/pages/myConsultantList/consultantList/consultant-list.component.scss
diff --git a/PAMapp/pages/myConsultantList/consultantList/consultant-list.component.ts b/PAMapp/pages/myConsultantList/consultantList/consultant-list.component.ts
new file mode 100644
index 0000000..21a9b04
--- /dev/null
+++ b/PAMapp/pages/myConsultantList/consultantList/consultant-list.component.ts
@@ -0,0 +1,16 @@
+
+import { Vue, Component, Prop, Getter } from 'nuxt-property-decorator';
+import { Consultant } from '~/assets/ts/models/consultant.model';
+
+
+@Component
+export default class ConsultantPage extends Vue {
+    @Prop() consultantList!: Consultant[];
+    @Getter isLogin!: boolean;
+    pageList: Consultant[] = [];
+
+    changePage(pageList: Consultant[]) {
+        this.pageList = pageList;
+    }
+
+}
diff --git a/PAMapp/pages/myConsultantList/consultantList/index.vue b/PAMapp/pages/myConsultantList/consultantList/index.vue
new file mode 100644
index 0000000..881a7f1
--- /dev/null
+++ b/PAMapp/pages/myConsultantList/consultantList/index.vue
@@ -0,0 +1,18 @@
+<template>
+    <div>
+        <ConsultantList
+            :agents="pageList"
+        ></ConsultantList>
+
+        <UiPagination
+            :totalList="consultantList"
+            @changePage="changePage"
+        ></UiPagination>
+    </div>
+</template>
+
+<script src="./consultant-list.component.ts"></script>
+
+<style lang="scss" scoped>
+  @import "./consultant-list.component.scss";
+</style>
diff --git a/PAMapp/pages/myConsultantList/contactedList.vue b/PAMapp/pages/myConsultantList/contactedList.vue
deleted file mode 100644
index a9d3d72..0000000
--- a/PAMapp/pages/myConsultantList/contactedList.vue
+++ /dev/null
@@ -1,28 +0,0 @@
-<template>
-    <div>
-        <ConsultantList
-            :agents="pageList"
-        ></ConsultantList>
-
-        <UiPagination
-            :totalList="contactedList"
-            @changePage="changePage"
-        ></UiPagination>
-    </div>
-</template>
-
-<script lang="ts">
-import { Vue, Component, Prop } from 'nuxt-property-decorator' ;
-import { Consultant } from '~/assets/ts/models/consultant.model';
-
-
-@Component
-export default class ContactedList extends Vue {
-    @Prop() contactedList!: Consultant[];
-    pageList: Consultant[] = [];
-
-    changePage(pageList: Consultant[]) {
-        this.pageList = pageList;
-    }
-}
-</script>
\ No newline at end of file
diff --git a/PAMapp/pages/myConsultantList/contactedList/contacted-list.component.scss b/PAMapp/pages/myConsultantList/contactedList/contacted-list.component.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/PAMapp/pages/myConsultantList/contactedList/contacted-list.component.scss
diff --git a/PAMapp/pages/myConsultantList/contactedList/contacted-list.component.ts b/PAMapp/pages/myConsultantList/contactedList/contacted-list.component.ts
new file mode 100644
index 0000000..53a6a6a
--- /dev/null
+++ b/PAMapp/pages/myConsultantList/contactedList/contacted-list.component.ts
@@ -0,0 +1,13 @@
+import { Vue, Component, Prop } from 'nuxt-property-decorator' ;
+import { Consultant } from '~/assets/ts/models/consultant.model';
+
+
+@Component
+export default class ContactedList extends Vue {
+    @Prop() contactedList!: Consultant[];
+    pageList: Consultant[] = [];
+
+    changePage(pageList: Consultant[]) {
+        this.pageList = pageList;
+    }
+}
diff --git a/PAMapp/pages/myConsultantList/contactedList/contactedList.vue b/PAMapp/pages/myConsultantList/contactedList/contactedList.vue
new file mode 100644
index 0000000..42663cf
--- /dev/null
+++ b/PAMapp/pages/myConsultantList/contactedList/contactedList.vue
@@ -0,0 +1,18 @@
+<template>
+    <div>
+        <ConsultantList
+            :agents="pageList"
+        ></ConsultantList>
+
+        <UiPagination
+            :totalList="contactedList"
+            @changePage="changePage"
+        ></UiPagination>
+    </div>
+</template>
+
+<script src="./contacted-list.component.ts"></script>
+
+<style lang="scss" scoped>
+  @import "./contacted-list.component.scss";
+</style>
diff --git a/PAMapp/pages/myConsultantList/index.vue b/PAMapp/pages/myConsultantList/index.vue
new file mode 100644
index 0000000..bb67df2
--- /dev/null
+++ b/PAMapp/pages/myConsultantList/index.vue
@@ -0,0 +1,41 @@
+<template>
+    <div>
+        <div class="pam-cus-tabs mb-30">
+            <div
+                class="cus-tab-item"
+                :class="{'is-active': activeTabName === 'consultantList'}"
+                @click="tabClick('consultantList')"
+            >憿批��
+                <span class="p">({{consultantList.length}})</span>
+            </div>
+            <div
+                class="cus-tab-item"
+                :class="{'is-active': activeTabName === 'contactedList'}"
+                @click="tabClick('contactedList')"
+            >撌脰蝯�
+                <span class="p">({{contactedList.length}})</span>
+            </div>
+        </div>
+
+        <NuxtChild
+            :contactedList="contactedList"
+            :consultantList="consultantList"
+        ></NuxtChild>
+
+        <!-- <ConsultantList
+            :agents="pageList"
+        ></ConsultantList>
+
+        <UiPagination
+            :totalList="consultantList"
+            @changePage="changePage"
+        ></UiPagination> -->
+
+    </div>
+</template>
+
+<script src="./my-consultant-list.component.ts"></script>
+
+<style lang="scss" scoped>
+  @import "./my-consultant-list.component.scss";
+</style>
diff --git a/PAMapp/pages/myConsultantList/my-consultant-list.component.scss b/PAMapp/pages/myConsultantList/my-consultant-list.component.scss
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/PAMapp/pages/myConsultantList/my-consultant-list.component.scss
diff --git a/PAMapp/pages/myConsultantList.vue b/PAMapp/pages/myConsultantList/my-consultant-list.component.ts
similarity index 60%
rename from PAMapp/pages/myConsultantList.vue
rename to PAMapp/pages/myConsultantList/my-consultant-list.component.ts
index 490d23c..2a4c907 100644
--- a/PAMapp/pages/myConsultantList.vue
+++ b/PAMapp/pages/myConsultantList/my-consultant-list.component.ts
@@ -1,30 +1,3 @@
-<template>
-    <div>
-        <div class="pam-cus-tabs mb-30">
-            <div
-                class="cus-tab-item"
-                :class="{'is-active': activeTabName === 'consultantList'}"
-                @click="tabClick('consultantList')"
-            >憿批��
-                <span class="p">({{consultantList.length}})</span>
-            </div>
-            <div
-                class="cus-tab-item"
-                :class="{'is-active': activeTabName === 'contactedList'}"
-                @click="tabClick('contactedList')"
-            >撌脰蝯�
-                <span class="p">({{contactedList.length}})</span>
-            </div>
-        </div>
-
-        <NuxtChild
-            :contactedList="contactedList"
-            :consultantList="consultantList"
-        ></NuxtChild>
-    </div>
-</template>
-
-<script lang='ts'>
 import { Vue, Component, Watch, State, Action } from 'nuxt-property-decorator';
 import { Consultant } from '~/assets/ts/models/consultant.model';
 
@@ -66,4 +39,3 @@
     }
 
 }
-</script>
\ No newline at end of file
diff --git a/PAMapp/pages/questionnaire/_agentNo.vue b/PAMapp/pages/questionnaire/_agentNo.vue
index 547af0a..9e60e96 100644
--- a/PAMapp/pages/questionnaire/_agentNo.vue
+++ b/PAMapp/pages/questionnaire/_agentNo.vue
@@ -127,397 +127,8 @@
   </div>
 </template>
 
-<script lang="ts">
-  import { Vue, Component } from 'nuxt-property-decorator';
-  import { addFavoriteConsultant, appointmentDemand, AppointmentParams, AppointmentRequests ,RegisterInfo } from '~/assets/ts/api/consultant';
-  import { getRequestsFromStorage, setRequestsToStorage, getRequestQuestionFromStorage, removeRequestQuestionFromStorage  } from '~/assets/ts/storageRequests';
-  import { Gender } from '~/assets/ts/models/enum/Gender';
-  import { ContactType } from '~/assets/ts/models/enum/ContactType';
-  import _ from 'lodash';
-  import { isLogin } from '~/assets/ts/auth';
+<script src="./questionnaire.component.ts"></script>
 
-  @Component
-  export default class Questionnaire extends Vue {
-    genderOptions=[
-      {
-        title:'���',
-        label:Gender.MALE,
-      },
-      {
-        title:'憟單��',
-        label:Gender.FEMALE,
-      }
-    ];
-
-    requirementOptions=[
-      {
-        title:'�摨瑁����',
-        label:'�摨瑁����',
-      },
-      {
-        title:'摮戊��',
-        label:'摮戊��',
-      },
-      {
-        title:'鞈閬��',
-        label:'鞈閬��',
-      },
-      {
-        title:'璅暑��隡�',
-        label:'璅暑��隡�',
-      },
-      {
-        title:'靽�瑼�/閬��',
-        label:'靽�瑼�/閬��',
-      },
-      {
-        title:'����',
-        label:'����',
-      },
-    ];
-
-    ageRangeOptions=[
-      {
-        title:'20甇脖誑銝�',
-        label:'under_20',
-      },
-      {
-        title:'21-30 甇�',
-        label:'21-30'
-      },
-      {
-        title:'31-40 甇�',
-        label:'31-40'
-      },
-      {
-        title:'41-50 甇�',
-        label:'41-50'
-      },
-      {
-        title:'46-55 甇�',
-        label:'46-55',
-      },
-      {
-        title:'51-60 甇�',
-        label:'51-60',
-      },
-      {
-        title:'61-70 甇�',
-        label:'61-70',
-      },
-      {
-        title:'71 甇脖誑銝�',
-        label:'over_71',
-      }
-    ];
-
-    quesAboutList = [
-                  {
-                      title:'�摨瑁����',
-                      content:'����澈擃憿批末嚗�靽�兢蝳�嚗��������嚗��飩������摮拙��粥銝��頝荔�犖����迤閬����'
-                  },
-                  {
-                      title:'摮戊��',
-                      content:'摮拙���������葦銋摮貊��撠靘�蒂�雿嚗飛���������������瓷嚗��楝銝���韏瑕飛��'
-                  },
-                  {
-                      title:'鞈閬��',
-                      content:'��迤��瓷撖��雓寡�����嚗鈭箇�����蝳西瓷��◢�����Ⅱ靽�蝛拙��嚗�摰嗆��靘�末��皞���'
-                  },
-                  {
-                      title:'璅暑��隡�',
-                      content:'�銝�頛拙����隡��摮���翰瘣鳴�停敺�����������隡瓷����撌勗�帘摰�嚗蝎曉蔗���僑鈭箇�������'
-                  },
-                  {
-                      title:'靽�瑼�/閬��',
-                      content:'��瑼Z�撌梁������蝚血����靘�◢�蝘餉��瘙��'
-                  },
-                  {
-                      title:'����',
-                      content:'���� ���������憸券�����鈭怒�����嚗���摰帘摰漲嚗��隞亙��澈��ˊ�靽���嚗�'
-                  }
-    ];
-
-    myRequest: AppointmentRequests = {
-      phone          : this.userInfo?.phone ? this.userInfo.phone                               : '',
-      email          : this.userInfo?.email ? this.userInfo.email                               : '',
-      contactType    : _.isEqual(this.userInfo?.contactType,ContactType.SMS) ? ContactType.PHONE: ContactType.EMAIL,
-      gender         : '',
-      age            : '',
-      job            : '',
-      requirement    : [],
-      hopeContactTime: [{
-        selectWeekOptions : [],
-        selectTimesOptions: [],
-      }],
-      agentNo: '',
-    };
-
-    showDrawer= false;
-    sendReserve = false;
-
-    beforeRouteEnter(to: any, from: any, next: any) {
-      next(vm => {
-        if (from.name === 'login' && !isLogin()) {
-          vm.$router.go(-1);
-          return;
-        }
-
-        if (!isLogin()) {
-          vm.$router.push('/login');
-        }
-      })
-    }
-
-    mounted(): void {
-      this.setMyRequest();
-    }
-
-    private setMyRequest(): void {
-      const storageMyRequest = getRequestsFromStorage();
-      const storageMyQuestion = getRequestQuestionFromStorage();
-
-      if (storageMyRequest) {
-        this.myRequest = {
-          ...storageMyRequest,
-          hopeContactTime: storageMyRequest.hopeContactTime?.length
-                            ? storageMyRequest.hopeContactTime
-                            : [{
-                                selectWeekOptions: [],
-                                selectTimesOptions: [],
-                              }],
-        };
-      }
-
-      if (storageMyQuestion) {
-        this.myRequest = {
-          ...this.myRequest,
-          requirement: storageMyQuestion
-        }
-        removeRequestQuestionFromStorage();
-      }
-    }
-
-    get phoneValid(): boolean {
-      const rule = /^09[0-9]{8}$/;
-      return this.myRequest.phone
-            ? rule.test(this.myRequest.phone) && _.isEqual(this.myRequest.phone.length,10)
-            : true;
-    }
-
-    get userInfo(): RegisterInfo {
-      const initUserInfo = JSON.parse(localStorage.getItem('userInfo')!);
-      return initUserInfo;
-    }
-
-    get isDisabledSubmitBtn(): boolean {
-           return _.includes(this.myRequest.contactType,ContactType.PHONE)
-      ? !this.isHopeContactTimeDone()
-      : !this.phoneValid;
-    }
-
-    get isLogin() {
-      return isLogin();
-    }
-
-    private isHopeContactTimeDone():boolean{
-      return this.myRequest.hopeContactTime[0]?.selectWeekOptions.length >0 && this.myRequest.hopeContactTime[0]?.selectTimesOptions.length >0;
-    }
-
-    sentDemand() {
-      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
-        };
-
-        appointmentDemand(data).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('/')
-    }
-
-  }
-</script>
-
-<style lang="scss" scoped>
-.sendReserve-txt{
-    display: flex;
-    justify-content: center;
-    margin-top: 10px;
-    margin-bottom: 26px;
-}
-
-//drawer��摨���見撘�
-.qa-dialog-footer{
-    display: flex;
-    justify-content: center;
-    margin-bottom: 81px;
-    color: #ED1B2E;
-    cursor: pointer;
-}
-
-//����見撘����
-.ques-footer{
-    justify-content: center;
-    margin: 30px 0;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    .el-button {
-    width: 120px;
-    height:50px;
-    background-color: #ED1B2E;
-    color:#FFFFFF;
-    font-weight: normal;
-    @extend .text--middle ;
-    &.el-button--default {
-        color: $PRIMARY_RED;
-        background-color: #FFFFFF;
-        border-color: $PRIMARY_RED;
-    }
-    &.el-button--primary {
-        background-color: $PRIMARY_RED;
-        border-color: $PRIMARY_RED;
-    }
-    &.is-disabled {
-    color: $PRIMARY_WHITE;
-    background-color: $MID_GREY;
-    border-color: $MID_GREY;
-    border-style: solid;
-    pointer-events: none;
-    }
-  }
-}
-
-//閰喟敦���rawer銝剝�摰寧征��之撠身蝵�
-.qa-dialog{
-    overflow-y:auto;
-    height: 500px;
-    margin-top: 20px;
-}
-
-//閰喟敦���rawer銝餉����
-.qaTextTitle{
-    margin-top:30px;
-    display: flex;
-    justify-content: center;
-}
-
-.el-button+.el-button{
-    margin-left: 0;
-}
-
-.datepicker{
-    display: flex;
-    flex-direction: column;
-}
-
-.required {
-    position: relative;
-    &::before {
-        content: '*';
-        position: absolute;
-        color: #FF0000;
-        transform: translate(-12px, 0);
-    }
-}
-
-.ques-page--reset.pam-page-container {
-    margin: 0px auto;
-}
-
-.ques-header {
-    position: relative;
-}
-
-.ques-header__mob-banner {
-  width: 100%;
-  min-height: 80px;
-  background-color: #F8F9FA;
-  background-image: url('~/assets/images/questionnaire/reserve_bg_mob.svg');
-  background-repeat: no-repeat;
-  background-size: cover;
-  background-position: center;
-}
-
-.ques-header__info {
-  position: relative;
-  padding:30px 20px;
-  margin: 0px 20px;
-  background-color: #B3E7E3;
-  border-radius: 10px;
-}
-
-.ques-header__input-block {
-  display: flex;
-  align-items: center;
-  @extend .text--middle,.mt-10 ;
-  .ques-header__input{
-    &.is-invalid{
-      border: 2px solid $PRIMARY_RED !important;
-    }
-    flex: 1;
-    height: 50px;
-    border-radius: 10px;
-    border: 1px #CCCCCC solid;
-    background-color: $PRIMARY_WHITE;
-    padding: 15px 10px;
-    box-sizing: border-box;
-    -webkit-box-sizing: border-box;
-    -moz-box-sizing: border-box;
-  }
-}
-
-.ques-container {
-  position: relative;
-  margin: 0px 20px;
-}
-
-
-@include desktop{
-  .ques-header{
-    display: flex;
-    justify-content: flex-end;
-    min-height: 460px;
-    background-image: url('~/assets/images/questionnaire/reserve_bg_web.svg');
-    background-repeat: no-repeat;
-    background-size: contain;
-    background-position: bottom;
-  }
-  .ques-header__mob-banner{
-    display: none;
-  }
-  .ques-header__info{
-    margin: 30px 20px;
-    width:500px;
-    min-height: 400px;
-    -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
-    -moz-box-sizing: border-box;    /* Firefox, other Gecko */
-    box-sizing: border-box;
-  }
-  .ques-container{
-    margin: 0px;
-  }
-}
-
+<style lang="scss">
+  @import "./questionnaire.component.scss";
 </style>
-
diff --git a/PAMapp/pages/questionnaire/questionnaire.component.scss b/PAMapp/pages/questionnaire/questionnaire.component.scss
new file mode 100644
index 0000000..ee03a39
--- /dev/null
+++ b/PAMapp/pages/questionnaire/questionnaire.component.scss
@@ -0,0 +1,159 @@
+.sendReserve-txt{
+    display: flex;
+    justify-content: center;
+    margin-top: 10px;
+    margin-bottom: 26px;
+}
+
+//drawer��摨���見撘�
+.qa-dialog-footer{
+    display: flex;
+    justify-content: center;
+    margin-bottom: 81px;
+    color: #ED1B2E;
+    cursor: pointer;
+}
+
+//����見撘����
+.ques-footer{
+    justify-content: center;
+    margin: 30px 0;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    .el-button {
+    width: 120px;
+    height:50px;
+    background-color: #ED1B2E;
+    color:#FFFFFF;
+    font-weight: normal;
+    @extend .text--middle ;
+    &.el-button--default {
+        color: $PRIMARY_RED;
+        background-color: #FFFFFF;
+        border-color: $PRIMARY_RED;
+    }
+    &.el-button--primary {
+        background-color: $PRIMARY_RED;
+        border-color: $PRIMARY_RED;
+    }
+    &.is-disabled {
+    color: $PRIMARY_WHITE;
+    background-color: $MID_GREY;
+    border-color: $MID_GREY;
+    border-style: solid;
+    pointer-events: none;
+    }
+  }
+}
+
+//閰喟敦���rawer銝剝�摰寧征��之撠身蝵�
+.qa-dialog{
+    overflow-y:auto;
+    height: 500px;
+    margin-top: 20px;
+}
+
+//閰喟敦���rawer銝餉����
+.qaTextTitle{
+    margin-top:30px;
+    display: flex;
+    justify-content: center;
+}
+
+.el-button+.el-button{
+    margin-left: 0;
+}
+
+.datepicker{
+    display: flex;
+    flex-direction: column;
+}
+
+.required {
+    position: relative;
+    &::before {
+        content: '*';
+        position: absolute;
+        color: #FF0000;
+        transform: translate(-12px, 0);
+    }
+}
+
+.ques-page--reset.pam-page-container {
+    margin: 0px auto;
+}
+
+.ques-header {
+    position: relative;
+}
+
+.ques-header__mob-banner {
+  width: 100%;
+  min-height: 80px;
+  background-color: #F8F9FA;
+  background-image: url('~/assets/images/questionnaire/reserve_bg_mob.svg');
+  background-repeat: no-repeat;
+  background-size: cover;
+  background-position: center;
+}
+
+.ques-header__info {
+  position: relative;
+  padding:30px 20px;
+  margin: 0px 20px;
+  background-color: #B3E7E3;
+  border-radius: 10px;
+}
+
+.ques-header__input-block {
+  display: flex;
+  align-items: center;
+  @extend .text--middle,.mt-10 ;
+  .ques-header__input{
+    &.is-invalid{
+      border: 2px solid $PRIMARY_RED !important;
+    }
+    flex: 1;
+    height: 50px;
+    border-radius: 10px;
+    border: 1px #CCCCCC solid;
+    background-color: $PRIMARY_WHITE;
+    padding: 15px 10px;
+    box-sizing: border-box;
+    -webkit-box-sizing: border-box;
+    -moz-box-sizing: border-box;
+  }
+}
+
+.ques-container {
+  position: relative;
+  margin: 0px 20px;
+}
+
+
+@include desktop{
+  .ques-header{
+    display: flex;
+    justify-content: flex-end;
+    min-height: 460px;
+    background-image: url('~/assets/images/questionnaire/reserve_bg_web.svg');
+    background-repeat: no-repeat;
+    background-size: contain;
+    background-position: bottom;
+  }
+  .ques-header__mob-banner{
+    display: none;
+  }
+  .ques-header__info{
+    margin: 30px 20px;
+    width:500px;
+    min-height: 400px;
+    -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */
+    -moz-box-sizing: border-box;    /* Firefox, other Gecko */
+    box-sizing: border-box;
+  }
+  .ques-container{
+    margin: 0px;
+  }
+}
diff --git a/PAMapp/pages/questionnaire/questionnaire.component.ts b/PAMapp/pages/questionnaire/questionnaire.component.ts
new file mode 100644
index 0000000..a5dddc4
--- /dev/null
+++ b/PAMapp/pages/questionnaire/questionnaire.component.ts
@@ -0,0 +1,228 @@
+import { Vue, Component } from 'nuxt-property-decorator';
+import { addFavoriteConsultant, appointmentDemand, AppointmentParams, AppointmentRequests ,RegisterInfo } from '~/assets/ts/api/consultant';
+import { getRequestsFromStorage, setRequestsToStorage, getRequestQuestionFromStorage, removeRequestQuestionFromStorage  } from '~/assets/ts/storageRequests';
+import { Gender } from '~/assets/ts/models/enum/gender.enum';
+import { ContactType } from '~/assets/ts/models/enum/ContactType';
+import _ from 'lodash';
+import { isLogin } from '~/assets/ts/auth';
+
+@Component
+export default class Questionnaire extends Vue {
+  genderOptions=[
+    {
+      title:'���',
+      label:Gender.MALE,
+    },
+    {
+      title:'憟單��',
+      label:Gender.FEMALE,
+    }
+  ];
+
+  requirementOptions=[
+    {
+      title:'�摨瑁����',
+      label:'�摨瑁����',
+    },
+    {
+      title:'摮戊��',
+      label:'摮戊��',
+    },
+    {
+      title:'鞈閬��',
+      label:'鞈閬��',
+    },
+    {
+      title:'璅暑��隡�',
+      label:'璅暑��隡�',
+    },
+    {
+      title:'靽�瑼�/閬��',
+      label:'靽�瑼�/閬��',
+    },
+    {
+      title:'����',
+      label:'����',
+    },
+  ];
+
+  ageRangeOptions=[
+    {
+      title:'20甇脖誑銝�',
+      label:'under_20',
+    },
+    {
+      title:'21-30 甇�',
+      label:'21-30'
+    },
+    {
+      title:'31-40 甇�',
+      label:'31-40'
+    },
+    {
+      title:'41-50 甇�',
+      label:'41-50'
+    },
+    {
+      title:'46-55 甇�',
+      label:'46-55',
+    },
+    {
+      title:'51-60 甇�',
+      label:'51-60',
+    },
+    {
+      title:'61-70 甇�',
+      label:'61-70',
+    },
+    {
+      title:'71 甇脖誑銝�',
+      label:'over_71',
+    }
+  ];
+
+  quesAboutList = [
+                {
+                    title:'�摨瑁����',
+                    content:'����澈擃憿批末嚗�靽�兢蝳�嚗��������嚗��飩������摮拙��粥銝��頝荔�犖����迤閬����'
+                },
+                {
+                    title:'摮戊��',
+                    content:'摮拙���������葦銋摮貊��撠靘�蒂�雿嚗飛���������������瓷嚗��楝銝���韏瑕飛��'
+                },
+                {
+                    title:'鞈閬��',
+                    content:'��迤��瓷撖��雓寡�����嚗鈭箇�����蝳西瓷��◢�����Ⅱ靽�蝛拙��嚗�摰嗆��靘�末��皞���'
+                },
+                {
+                    title:'璅暑��隡�',
+                    content:'�銝�頛拙����隡��摮���翰瘣鳴�停敺�����������隡瓷����撌勗�帘摰�嚗蝎曉蔗���僑鈭箇�������'
+                },
+                {
+                    title:'靽�瑼�/閬��',
+                    content:'��瑼Z�撌梁������蝚血����靘�◢�蝘餉��瘙��'
+                },
+                {
+                    title:'����',
+                    content:'���� ���������憸券�����鈭怒�����嚗���摰帘摰漲嚗��隞亙��澈��ˊ�靽���嚗�'
+                }
+  ];
+
+  myRequest: AppointmentRequests = {
+    phone          : this.userInfo?.phone ? this.userInfo.phone                               : '',
+    email          : this.userInfo?.email ? this.userInfo.email                               : '',
+    contactType    : _.isEqual(this.userInfo?.contactType,ContactType.SMS) ? ContactType.PHONE: ContactType.EMAIL,
+    gender         : '',
+    age            : '',
+    job            : '',
+    requirement    : [],
+    hopeContactTime: [{
+      selectWeekOptions : [],
+      selectTimesOptions: [],
+    }],
+    agentNo: '',
+  };
+
+  showDrawer= false;
+  sendReserve = false;
+
+  beforeRouteEnter(to: any, from: any, next: any) {
+    next(vm => {
+      if (from.name === 'login' && !isLogin()) {
+        vm.$router.go(-1);
+        return;
+      }
+
+      if (!isLogin()) {
+        vm.$router.push('/login');
+      }
+    })
+  }
+
+  mounted(): void {
+    this.setMyRequest();
+  }
+
+  private setMyRequest(): void {
+    const storageMyRequest = getRequestsFromStorage();
+    const storageMyQuestion = getRequestQuestionFromStorage();
+
+    if (storageMyRequest) {
+      this.myRequest = {
+        ...storageMyRequest,
+        hopeContactTime: storageMyRequest.hopeContactTime?.length
+                          ? storageMyRequest.hopeContactTime
+                          : [{
+                              selectWeekOptions: [],
+                              selectTimesOptions: [],
+                            }],
+      };
+    }
+
+    if (storageMyQuestion) {
+      this.myRequest = {
+        ...this.myRequest,
+        requirement: storageMyQuestion
+      }
+      removeRequestQuestionFromStorage();
+    }
+  }
+
+  get phoneValid(): boolean {
+    const rule = /^09[0-9]{8}$/;
+    return this.myRequest.phone
+          ? rule.test(this.myRequest.phone) && _.isEqual(this.myRequest.phone.length,10)
+          : true;
+  }
+
+  get userInfo(): RegisterInfo {
+    const initUserInfo = JSON.parse(localStorage.getItem('userInfo')!);
+    return initUserInfo;
+  }
+
+  get isDisabledSubmitBtn(): boolean {
+         return _.includes(this.myRequest.contactType,ContactType.PHONE)
+    ? !this.isHopeContactTimeDone()
+    : !this.phoneValid;
+  }
+
+  get isLogin() {
+    return isLogin();
+  }
+
+  private isHopeContactTimeDone():boolean{
+    return this.myRequest.hopeContactTime[0]?.selectWeekOptions.length >0 && this.myRequest.hopeContactTime[0]?.selectTimesOptions.length >0;
+  }
+
+  sentDemand() {
+    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
+      };
+
+      appointmentDemand(data).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('/')
+  }
+
+}
diff --git a/PAMapp/pages/quickFilter/index.vue b/PAMapp/pages/quickFilter/index.vue
index c6ef025..cb9f95a 100644
--- a/PAMapp/pages/quickFilter/index.vue
+++ b/PAMapp/pages/quickFilter/index.vue
@@ -64,213 +64,8 @@
     </div>
 </template>
 
-<script lang="ts">
-import { Vue, Component, namespace } from 'nuxt-property-decorator';
-import { FastQueryParams } from '~/assets/ts/api/consultant';
-import { Consultant } from '~/assets/ts/models/consultant.model';
-import { Selected } from '~/components/QuickFilter/QuickFilterSelector.vue';
-import { fastQuery } from '~/assets/ts/api/consultant';
+<script src="./quick-filter.component.ts"></script>
 
-const localStorage = namespace('localStorage');
-@Component
-export default class QuickFilter extends Vue {
-    @localStorage.Mutation storageQuickFilter!: (token: string) => void;
-    @localStorage.Getter quickFilterSelectedData!: Selected[];
-
-    isOpenQuestionPopUp = false;
-    consultantList: Consultant[] = [];
-    questionOption = {};
-    confirmItem: Selected[] = [];
-    questionList: QuestionOption[] = [
-        {
-            name: 'gender',
-            title: '憿批��批',
-            detail: [
-                { name: '���', value: 'male', className: 'btn_man'},
-                { name: '憟單��', value: 'female', className: 'btn_woman'}
-            ],
-            type: 'radio'
-        },
-        {
-            name: 'avgScore',
-            title: '憿批�遛��漲',
-            detail: [],
-            type: ''
-        },
-        {
-            name: 'communicationStyles',
-            title: '皞�◢�',
-            detail: [
-                { value: '雓寞��祕', className: 'btn_owl'},
-                { value: '��翰銝餃��', className: 'btn_tiger'},
-                { value: '���', className: 'btn_koala'},
-                { value: '�隢◢頞�', className: 'btn_peacock'}
-            ],
-            type: 'checkbox'
-        },
-        // {
-        //     name: 'status',
-        //     title: '銝�����',
-        //     detail: [],
-        //     type: 'radio'
-        // }
-    ];
-
-    mounted() {
-        if (this.quickFilterSelectedData && this.quickFilterSelectedData.length > 0) {
-            this.confirmItem = this.quickFilterSelectedData;
-            this.getRecommendList();
-        }
-    }
-
-    gender(): string {
-        const filter = this.confirmItem.filter(item => item.option === 'gender').map(i => i.value);
-        return filter.length === 0 ? '' : filter[0];
-    }
-
-    avgScore(): number {
-        const filter = this.confirmItem.filter(item => item.option === 'avgScore').map(i => i.value);
-        return filter.length === 0 ? '' : filter[0];
-    }
-
-    communicationStyles(): string[] {
-        return this.confirmItem.filter(item => item.option === 'communicationStyles').map(i => i.value);
-    }
-
-    isActive(name: string) {
-        return name === 'gender' && !!this.gender()
-            || name === 'avgScore' && !!this.avgScore()
-            || name === 'communicationStyles' && !!this.communicationStyles().length
-    }
-
-    openPopUp(question: QuestionOption) {
-        this.questionOption = question;
-        this.isOpenQuestionPopUp =true;
-    }
-
-    removeTag(value: string) {
-        this.confirmItem = this.confirmItem.filter(item => item.value !== value);
-        this.confirmItem.length > 0 ? this.getRecommendList() : this.consultantList = [];
-    }
-
-    confirm(event: Selected) {
-        this.setConfirmData(event);
-        this.confirmItem.length > 0 ? this.getRecommendList() : this.consultantList = [];
-        this.isOpenQuestionPopUp = false;
-    }
-
-    setConfirmData(event: Selected) {
-        if (event.option === 'communicationStyles') {
-            this.filterCommunicationStyles(event);
-        } else {
-            const findIndex = this.confirmItem.findIndex(item => item.option === event.option);
-            findIndex === -1 ? this.confirmItem.push(event) : this.confirmItem[findIndex] = event;
-        }
-    }
-
-    filterCommunicationStyles(event: Selected) {
-        const confirmValue = this.confirmItem
-            .filter(item => item.option === 'communicationStyles')
-            .map(i => i.value);
-        const pickerValue = event.value;
-
-        this.confirmItem = this.confirmItem
-            .filter(item => pickerValue.includes(item.value) || item.option !== 'communicationStyles');
-
-        const addValue = pickerValue.filter(item => !confirmValue.includes(item)).map(i => {
-            return {
-                option: 'communicationStyles',
-                value: i
-            }
-        })
-        if (addValue.length > 0) {
-            this.confirmItem.push(...addValue);
-        }
-    }
-
-    getRecommendList() {
-        const data: FastQueryParams = {
-            gender: this.gender(),
-            communicationStyles: this.communicationStyles(),
-            avgScore: this.avgScore(),
-            status: ''
-        }
-
-        fastQuery(data).then((res) => {
-            this.consultantList = res.data;
-            this.storageQuickFilter(JSON.stringify(this.confirmItem))
-        })
-    }
-
-}
-
-export interface QuestionOption {
-    title: string;
-    detail: Detail[];
-    type: string;
-    name: string;
-}
-
-interface Detail {
-    value: string;
-    name?: string;
-    className: string;
-}
-
-</script>
-
-<style lang="scss" scoped>
-    .emptyBox {
-        width: 100%;
-        height: 100px;
-        border: solid 1px $LIGHT_GREY;
-        text-align: center;
-        border-radius: 10px;
-
-        .smTxt {
-            line-height: 100px;
-        }
-    }
-
-    .recommendStyle {
-        box-shadow: 0 0 6px #00000029;
-        background-color: $PRIMARY_WHITE;
-    }
-
-    .quickBtnBlock {
-        display: flex;
-        width: 100%;
-        height: 132px;
-        flex-wrap: wrap;
-        justify-content: space-between;
-
-        .quickBtn {
-            width: 48%;
-            height: 56px;
-            text-align: center;
-            box-shadow: 0 0 6px #22222229;
-            border-radius: 10px;
-            border-color: $CORAL;
-
-            &.isActive {
-                background-color: $CORAL;
-                color: $PRIMARY_WHITE;
-            }
-        }
-        .quickBtn+.quickBtn {
-            margin-left: 0;
-        }
-
-    }
-
-    .recommend {
-        position: relative;
-
-        .img {
-            position: absolute;
-            top: -50px;
-            right: 10px;
-        }
-    }
-
-</style>
\ No newline at end of file
+<style lang="scss">
+  @import "./quick-filter.component.scss";
+</style>
diff --git a/PAMapp/pages/quickFilter/quick-filter.component.scss b/PAMapp/pages/quickFilter/quick-filter.component.scss
new file mode 100644
index 0000000..d03cdfa
--- /dev/null
+++ b/PAMapp/pages/quickFilter/quick-filter.component.scss
@@ -0,0 +1,52 @@
+.emptyBox {
+    width: 100%;
+    height: 100px;
+    border: solid 1px $LIGHT_GREY;
+    text-align: center;
+    border-radius: 10px;
+
+    .smTxt {
+        line-height: 100px;
+    }
+}
+
+.recommendStyle {
+    box-shadow: 0 0 6px #00000029;
+    background-color: $PRIMARY_WHITE;
+}
+
+.quickBtnBlock {
+    display: flex;
+    width: 100%;
+    height: 132px;
+    flex-wrap: wrap;
+    justify-content: space-between;
+
+    .quickBtn {
+        width: 48%;
+        height: 56px;
+        text-align: center;
+        box-shadow: 0 0 6px #22222229;
+        border-radius: 10px;
+        border-color: $CORAL;
+
+        &.isActive {
+            background-color: $CORAL;
+            color: $PRIMARY_WHITE;
+        }
+    }
+    .quickBtn+.quickBtn {
+        margin-left: 0;
+    }
+
+}
+
+.recommend {
+    position: relative;
+
+    .img {
+        position: absolute;
+        top: -50px;
+        right: 10px;
+    }
+}
diff --git a/PAMapp/pages/quickFilter/quick-filter.component.ts b/PAMapp/pages/quickFilter/quick-filter.component.ts
new file mode 100644
index 0000000..4cfdd1c
--- /dev/null
+++ b/PAMapp/pages/quickFilter/quick-filter.component.ts
@@ -0,0 +1,144 @@
+
+import { Vue, Component, namespace } from 'nuxt-property-decorator';
+
+
+import { fastQuery } from '~/assets/ts/api/consultant';
+import { QuestionOption } from '~/assets/ts/models/question-option.model';
+import { Consultant } from '~/assets/ts/models/consultant.model';
+import { Selected } from '~/assets/ts/models/selected.model';
+import { FastQueryParams } from '~/assets/ts/models/fast-query-params.model';
+
+const localStorage = namespace('localStorage');
+@Component
+export default class QuickFilter extends Vue {
+    @localStorage.Mutation storageQuickFilter!: (token: string) => void;
+    @localStorage.Getter quickFilterSelectedData!: Selected[];
+
+    isOpenQuestionPopUp = false;
+    consultantList: Consultant[] = [];
+    questionOption = {};
+    confirmItem: Selected[] = [];
+    questionList: QuestionOption[] = [
+        {
+            name: 'gender',
+            title: '憿批��批',
+            detail: [
+                { name: '���', value: 'male', className: 'btn_man'},
+                { name: '憟單��', value: 'female', className: 'btn_woman'}
+            ],
+            type: 'radio'
+        },
+        {
+            name: 'avgScore',
+            title: '憿批�遛��漲',
+            detail: [],
+            type: ''
+        },
+        {
+            name: 'communicationStyles',
+            title: '皞�◢�',
+            detail: [
+                { value: '雓寞��祕', className: 'btn_owl'},
+                { value: '��翰銝餃��', className: 'btn_tiger'},
+                { value: '���', className: 'btn_koala'},
+                { value: '�隢◢頞�', className: 'btn_peacock'}
+            ],
+            type: 'checkbox'
+        },
+        // {
+        //     name: 'status',
+        //     title: '銝�����',
+        //     detail: [],
+        //     type: 'radio'
+        // }
+    ];
+
+    mounted() {
+        if (this.quickFilterSelectedData && this.quickFilterSelectedData.length > 0) {
+            this.confirmItem = this.quickFilterSelectedData;
+            this.getRecommendList();
+        }
+    }
+
+    gender(): string {
+        const filter = this.confirmItem.filter(item => item.option === 'gender').map(i => i.value);
+        return filter.length === 0 ? '' : filter[0];
+    }
+
+    avgScore(): number {
+        const filter = this.confirmItem.filter(item => item.option === 'avgScore').map(i => i.value);
+        return filter.length === 0 ? '' : filter[0];
+    }
+
+    communicationStyles(): string[] {
+        return this.confirmItem.filter(item => item.option === 'communicationStyles').map(i => i.value);
+    }
+
+    isActive(name: string) {
+        return name === 'gender' && !!this.gender()
+            || name === 'avgScore' && !!this.avgScore()
+            || name === 'communicationStyles' && !!this.communicationStyles().length
+    }
+
+    openPopUp(question: QuestionOption) {
+        this.questionOption = question;
+        this.isOpenQuestionPopUp =true;
+    }
+
+    removeTag(value: string) {
+        this.confirmItem = this.confirmItem.filter(item => item.value !== value);
+        this.confirmItem.length > 0 ? this.getRecommendList() : this.consultantList = [];
+    }
+
+    confirm(event: Selected) {
+        this.setConfirmData(event);
+        this.confirmItem.length > 0 ? this.getRecommendList() : this.consultantList = [];
+        this.isOpenQuestionPopUp = false;
+    }
+
+    setConfirmData(event: Selected) {
+        if (event.option === 'communicationStyles') {
+            this.filterCommunicationStyles(event);
+        } else {
+            const findIndex = this.confirmItem.findIndex(item => item.option === event.option);
+            findIndex === -1 ? this.confirmItem.push(event) : this.confirmItem[findIndex] = event;
+        }
+    }
+
+    filterCommunicationStyles(event: Selected) {
+        const confirmValue = this.confirmItem
+            .filter(item => item.option === 'communicationStyles')
+            .map(i => i.value);
+        const pickerValue = event.value;
+
+        this.confirmItem = this.confirmItem
+            .filter(item => pickerValue.includes(item.value) || item.option !== 'communicationStyles');
+
+        const addValue = pickerValue.filter(item => !confirmValue.includes(item)).map(i => {
+            return {
+                option: 'communicationStyles',
+                value: i
+            }
+        })
+        if (addValue.length > 0) {
+            this.confirmItem.push(...addValue);
+        }
+    }
+
+    getRecommendList() {
+        const data: FastQueryParams = {
+            gender: this.gender(),
+            communicationStyles: this.communicationStyles(),
+            avgScore: this.avgScore(),
+            status: ''
+        }
+
+        fastQuery(data).then((res) => {
+            this.consultantList = res.data;
+            this.storageQuickFilter(JSON.stringify(this.confirmItem))
+        })
+    }
+
+}
+
+
diff --git a/PAMapp/pages/recommendConsultant/criteria.vue b/PAMapp/pages/recommendConsultant/criteria.vue
deleted file mode 100644
index 039388e..0000000
--- a/PAMapp/pages/recommendConsultant/criteria.vue
+++ /dev/null
@@ -1,3 +0,0 @@
-<template>
-    <div>������(����)</div>
-</template>
\ No newline at end of file
diff --git a/PAMapp/pages/recommendConsultant/index.vue b/PAMapp/pages/recommendConsultant/index.vue
index 37598dc..305c56d 100644
--- a/PAMapp/pages/recommendConsultant/index.vue
+++ b/PAMapp/pages/recommendConsultant/index.vue
@@ -1,5 +1,5 @@
 <template>
-  <div class="pam-rec-cosultant-page">
+  <div class="pam-rec-consultant-page">
     <div class="pb-10 mdTxt">憿批��批</div>
     <SingleSelectBtn :singleSelected.sync="strictQueryDto.gender" :options="genderOptions"/>
     <div class="pam-paragraph">
@@ -83,495 +83,8 @@
   </div>
 </template>
 
-<script lang="ts">
-  import {
-    Vue,
-    Component,
-    Mutation,
-    namespace,
-    Action,
-    State
-  } from 'nuxt-property-decorator';
-  import * as _ from 'lodash';
-  import { Seniority } from '~/assets/ts/models/enum/seniority';
-  import { setRequestQuestionToStorage } from '~/assets/ts/storageRequests';
-
-  const localStorage = namespace('localStorage');
-
-  @Component
-  export default class RecommendConsultant extends Vue {
-    isVisiblePopUp = false;
-    strictQueryDto: StrictQueryDto ={
-      gender:'',
-      area:'',
-      status:'',
-      requirements: [],
-      otherRequirement:'',
-      seniority:'',
-      avgScore:0,
-      popularTags: [],
-      otherPopularTags:'',
-    };
-    genderOptions=[
-      {
-        title:'���',
-        label:Gender.MALE,
-      },
-      {
-        title:'憟單��',
-        label:Gender.FEMALE,
-      }
-    ];
-    requirementOptions=[
-      {
-        title:'�摨瑁����',
-        label:'�摨瑁����',
-      },
-      {
-        title:'摮戊��',
-        label:'摮戊��',
-      },
-      {
-        title:'鞈閬��',
-        label:'鞈閬��',
-      },
-      {
-        title:'璅暑��隡�',
-        label:'璅暑��隡�',
-      },
-      {
-        title:'靽�瑼�/閬��',
-        label:'靽�瑼�/閬��',
-      },
-      {
-        title:'����',
-        label:'����',
-      },
-    ];
-    seniorityOptions=[
-      {
-        title:'銝��',
-        subTitle:'撟湧翩銝����',
-        label:Seniority.UNLIMITED,
-      },
-      {
-        title:'撟渲��',
-        subTitle:'蝯血僑頛犖銝�����',
-        label:Seniority.YOUNG,
-      },
-      {
-        title:'鞈楛',
-        subTitle:'����麾',
-        label:Seniority.SENIOR,
-      }
-    ];
-    popularOptions=[
-      {
-        title: '#��',
-        label:'��'
-      },
-      {
-        title: '#憭梯',
-        label:'憭梯'
-      },
-      {
-        title: '#����',
-        label:'����'
-      },
-      {
-        title: '#����',
-        label:'����'
-      },
-      {
-        title: '#憯賡',
-        label: '憯賡'
-      },
-      {
-        title: '#����',
-        label:'����'
-      },
-      {
-        title: '#����',
-        label:'����'
-      },
-      {
-        title: '#����',
-        label:'����'
-      }
-    ];
-    queaAboutList = [
-      {
-        title: '�摨瑁����',
-        content: '����澈擃憿批末嚗�靽�兢蝳�嚗��������嚗��飩������摮拙��粥銝��頝荔�犖����迤閬����'
-      },
-      {
-        title: '摮戊��',
-        content: '摮拙���������葦銋摮貊��撠靘�蒂�雿嚗飛���������������瓷嚗��楝銝���韏瑕飛��'
-      },
-      {
-        title: '鞈閬��',
-        content: '��迤��瓷撖��雓寡�����嚗鈭箇�����蝳西瓷��◢�����Ⅱ靽�蝛拙��嚗�摰嗆��靘�末��皞���'
-      },
-      {
-        title: '璅暑��隡�',
-        content: '�銝�頛拙����隡��摮���翰瘣鳴�停敺�����������隡瓷����撌勗�帘摰�嚗蝎曉蔗���僑鈭箇�������'
-      },
-      {
-        title: '靽�瑼�/閬��',
-        content: '��瑼Z�撌梁������蝚血����靘�◢�蝘餉��瘙��'
-      },
-      {
-        title: '����',
-        content: '���� ���������憸券�����鈭怒�����嚗���摰帘摰漲嚗��隞亙��澈��ˊ�靽���嚗�'
-      }
-    ];
-    showDialog = false;
-    showAddress = false;
-
-    @Mutation updateStrictQueryList!: (data: any) => void;
-    @Action storeStrictQueryList!: (data: any) => Promise<number>;
-    @State strictQueryList!: any;
-    @localStorage.State recommendConsultantItem!: string;
-
-    mounted() {
-      if (!!this.recommendConsultantItem) {
-        this.strictQueryDto = JSON.parse(this.recommendConsultantItem);
-      }
-    }
-    async makePair() {
-      await this.storeStrictQueryList(this.strictQueryDto).then(dataLength => {
-        const questions = this.strictQueryDto.requirements.length ? this.strictQueryDto.requirements : [];
-        setRequestQuestionToStorage(questions);
-        if (dataLength === 0) {
-          this.isVisiblePopUp = true;
-          return;
-        }
-        this.$router.push('/recommendConsultant/result');
-      });
-    }
-    get notFinishByRequireRules():boolean{
-      const area = this.strictQueryDto.area;
-      const requirementLength = this.strictQueryDto.requirements
-        ? this.strictQueryDto.requirements.length
-        : 0;
-      return !(area && requirementLength >0)
-    }
-
-    confirmAddress(area: string) {
-      this.strictQueryDto.area = area;
-      this.showAddress = false;
-    }
-
-  }
-  enum Gender{
-    MALE="male",
-    FEMALE="female",
-  }
-
-  export interface StrictQueryDto {
-    gender: string,
-    area: string,
-    status: string,
-    requirements: string[],
-    otherRequirement: string,
-    seniority: string,
-    avgScore: number,
-    popularTags: string[],
-    otherPopularTags: string
-  }
-</script>
+<script src="./recommend-consultant.component.ts"></script>
 
 <style lang="scss">
-
-.pam-rec-cosultant-page {
-  .rec-pop-container{
-    width:310px;
-    .rec-pop-options{
-      .el-checkbox-group{
-        display: flex;
-        flex-wrap: wrap;
-        flex-direction: row;
-        .el-checkbox{
-          width:90px;
-          height: 50px;
-          padding:0;
-          .el-checkbox__label{
-            justify-content: center;
-            align-items: center;
-            display: flex;
-            padding:15px 20px;
-            text-align: center;
-          }
-        }
-        .pam-selectAll-btn{
-          margin-top: 60px;
-          margin-left:-203px;
-          height: 50px;
-          width: 90px;
-          padding: 10px;
-        }
-
-      }
-    }
-
-  }
-  .rec-multi-select{
-    .el-checkbox-group {
-      display: flex;
-      flex-direction: column;
-      align-items: flex-start;
-    }
-  }
-
-  input:focus,
-  textarea:focus {
-    outline: none;
-  }
-
-  .input {
-    border: none;
-    width: 90%;
-    border-radius: 10px;
-  }
-
-  .job-pick {
-    height: 50px;
-    border-radius: 10px;
-    border: 1px solid #D0D0CE;
-    display: flex;
-    justify-content: space-between;
-    background-color: #FFFFFF;
-  }
-
-  .down-icon {
-    color: #ED1B2E;
-    font-size: 25px;
-    align-self: center;
-    margin-right: 15px;
-  }
-
-  .popOtherBtn {
-    margin-left: -190px;
-    margin-top: 45px;
-  }
-
-  .genderBtn {
-    width: 80px;
-    height: 47px;
-    display: contents;
-  }
-
-  .qa-dialog {
-    overflow-y: auto;
-    height: 500px;
-    margin-top: 20px;
-    text-align: justify;
-  }
-
-  .qaTextTitle {
-    margin-top: 30px
-  }
-
-  .qa-dialog-footer {
-    display: flex;
-    justify-content: center;
-    margin-bottom: 81px;
-    color: #ED1B2E;
-    cursor: pointer;
-  }
-
-  .el-drawer__container ::-webkit-scrollbar {
-    display: none;
-  }
-  .el-button+.el-button {
-    margin-left: 0;
-  }
-
-  .seniority-choice {
-    display: flex;
-    flex-wrap: wrap;
-  }
-
-  .area-choice {
-    height: 50px;
-    border-radius: 10px;
-    border: 1px solid #D0D0CE;
-    display: flex;
-    justify-content: space-between;
-    background-color: #FFFFFF;
-  }
-
-  .area-icon {
-    color: #ED1B2E;
-    font-size: 25px;
-    display: flex;
-    justify-content: flex-end;
-    padding-right: 16px;
-    padding-top: 11px;
-  }
-
-  input::-webkit-input-placeholder {
-    font-size: 20px;
-    padding-left: 10px;
-  }
-
-  .el-button.is-disabled {
-    font-size: 20px;
-    border-radius: 20px;
-    color: #FFFFFF;
-    background-color: #A7A8AA;
-    border: 1px solid #A7A8AA;
-  }
-
-  .rec-footer {
-    height: 70px;
-    display: flex;
-    justify-content: center;
-    align-items: center;
-  }
-
-  .other-PopBtn {
-    width: 90px;
-    height: 47px;
-    margin-top: 10px;
-  }
-
-
-
-  .rec-ques-location {
-    display: flex;
-    align-items: center;
-  }
-
-  .pop-tag {
-    display: flex;
-    flex-wrap: wrap;
-    margin: -10px;
-
-  }
-
-  .rec-popular {
-    display: flex;
-    align-items: baseline;
-    padding-top: 10px;
-    margin-bottom: 10px;
-  }
-
-  .rec-btn-type {
-    padding-bottom: 10px;
-  }
-
-  .rec-question {
-    display: flex;
-    flex-direction: column;
-
-  }
-
-  .rec-banner {
-    height: 120px;
-    background-color: #D0D0CE;
-
-  }
-
-  .rec-btn {
-    font-size: 20px;
-    border-radius: 20px;
-    color: black;
-    border: 1px solid #D0D0CE;
-  }
-
-  .rec-pop-btn {
-    font-size: 20px;
-    border-radius: 20px;
-    color: black;
-    margin: 0px 0px 10px 10px;
-    border: 1px solid #D0D0CE;
-    width: 90px;
-    height: 47px;
-  }
-
-  .el-progress__text {
-    display: none;
-  }
-
-  .el-progress-bar {
-    padding-right: 0;
-  }
-
-  .el-progress-bar__inner {
-    background-color: #ED1B2E;
-  }
-
-  .required {
-    position: relative;
-
-    &::before {
-      content: '*';
-      position: absolute;
-      color: #FF0000;
-      transform: translate(-12px, 0);
-      z-index: 5;
-    }
-  }
-
-  .area-txt {
-    display: flex;
-    align-items: center;
-    margin-left: 18px;
-  }
-
-  @include desktop {
-
-    .desktopBtn {
-      margin-right: 10px;
-      height: 47px
-    }
-
-    .popOtherBtn {
-      margin-left: 10px;
-      margin-top: -10px;
-    }
-
-    .rec-pop-container{
-      width:auto;
-    .rec-pop-options{
-      .el-checkbox-group{
-        display: flex;
-        flex-wrap:wrap;
-        flex-direction: none;
-        .el-checkbox{
-          width:90px;
-          height: 50px;
-          padding:0;
-          .el-checkbox__label{
-            justify-content: center;
-            align-items: center;
-            display: flex;
-            padding:15px 20px;
-            text-align: center;
-          }
-        }
-        .pam-selectAll-btn{
-          margin-top:0px;
-          margin-left:0px;
-          height: 50px;
-          width: 90px;
-          padding: 10px;
-        }
-      }
-    }
-
-  }
-
-    .rec-multi-select{
-    .el-checkbox-group {
-      display: flex;
-      flex-direction: row;
-      align-items: flex-start;
-      flex-wrap: wrap;
-    }
-  }
-  }
-}
-
+  @import "./recommend-consultant.component.scss";
 </style>
diff --git a/PAMapp/pages/recommendConsultant/recommend-consultant.component.scss b/PAMapp/pages/recommendConsultant/recommend-consultant.component.scss
new file mode 100644
index 0000000..3278a8f
--- /dev/null
+++ b/PAMapp/pages/recommendConsultant/recommend-consultant.component.scss
@@ -0,0 +1,291 @@
+
+.pam-rec-consultant-page {
+  .rec-pop-container{
+    width:310px;
+    .rec-pop-options{
+      .el-checkbox-group{
+        display: flex;
+        flex-wrap: wrap;
+        flex-direction: row;
+        .el-checkbox{
+          width:90px;
+          height: 50px;
+          padding:0;
+          .el-checkbox__label{
+            justify-content: center;
+            align-items: center;
+            display: flex;
+            padding:15px 20px;
+            text-align: center;
+          }
+        }
+        .pam-selectAll-btn{
+          margin-top: 60px;
+          margin-left:-203px;
+          height: 50px;
+          width: 90px;
+          padding: 10px;
+        }
+
+      }
+    }
+
+  }
+  .rec-multi-select{
+    .el-checkbox-group {
+      display: flex;
+      flex-direction: column;
+      align-items: flex-start;
+    }
+  }
+
+  input:focus,
+  textarea:focus {
+    outline: none;
+  }
+
+  .input {
+    border: none;
+    width: 90%;
+    border-radius: 10px;
+  }
+
+  .job-pick {
+    height: 50px;
+    border-radius: 10px;
+    border: 1px solid #D0D0CE;
+    display: flex;
+    justify-content: space-between;
+    background-color: #FFFFFF;
+  }
+
+  .down-icon {
+    color: #ED1B2E;
+    font-size: 25px;
+    align-self: center;
+    margin-right: 15px;
+  }
+
+  .popOtherBtn {
+    margin-left: -190px;
+    margin-top: 45px;
+  }
+
+  .genderBtn {
+    width: 80px;
+    height: 47px;
+    display: contents;
+  }
+
+  .qa-dialog {
+    overflow-y: auto;
+    height: 500px;
+    margin-top: 20px;
+    text-align: justify;
+  }
+
+  .qaTextTitle {
+    margin-top: 30px
+  }
+
+  .qa-dialog-footer {
+    display: flex;
+    justify-content: center;
+    margin-bottom: 81px;
+    color: #ED1B2E;
+    cursor: pointer;
+  }
+
+  .el-drawer__container ::-webkit-scrollbar {
+    display: none;
+  }
+  .el-button+.el-button {
+    margin-left: 0;
+  }
+
+  .seniority-choice {
+    display: flex;
+    flex-wrap: wrap;
+  }
+
+  .area-choice {
+    height: 50px;
+    border-radius: 10px;
+    border: 1px solid #D0D0CE;
+    display: flex;
+    justify-content: space-between;
+    background-color: #FFFFFF;
+  }
+
+  .area-icon {
+    color: #ED1B2E;
+    font-size: 25px;
+    display: flex;
+    justify-content: flex-end;
+    padding-right: 16px;
+    padding-top: 11px;
+  }
+
+  input::-webkit-input-placeholder {
+    font-size: 20px;
+    padding-left: 10px;
+  }
+
+  .el-button.is-disabled {
+    font-size: 20px;
+    border-radius: 20px;
+    color: #FFFFFF;
+    background-color: #A7A8AA;
+    border: 1px solid #A7A8AA;
+  }
+
+  .rec-footer {
+    height: 70px;
+    display: flex;
+    justify-content: center;
+    align-items: center;
+  }
+
+  .other-PopBtn {
+    width: 90px;
+    height: 47px;
+    margin-top: 10px;
+  }
+
+
+
+  .rec-ques-location {
+    display: flex;
+    align-items: center;
+  }
+
+  .pop-tag {
+    display: flex;
+    flex-wrap: wrap;
+    margin: -10px;
+
+  }
+
+  .rec-popular {
+    display: flex;
+    align-items: baseline;
+    padding-top: 10px;
+    margin-bottom: 10px;
+  }
+
+  .rec-btn-type {
+    padding-bottom: 10px;
+  }
+
+  .rec-question {
+    display: flex;
+    flex-direction: column;
+
+  }
+
+  .rec-banner {
+    height: 120px;
+    background-color: #D0D0CE;
+
+  }
+
+  .rec-btn {
+    font-size: 20px;
+    border-radius: 20px;
+    color: black;
+    border: 1px solid #D0D0CE;
+  }
+
+  .rec-pop-btn {
+    font-size: 20px;
+    border-radius: 20px;
+    color: black;
+    margin: 0px 0px 10px 10px;
+    border: 1px solid #D0D0CE;
+    width: 90px;
+    height: 47px;
+  }
+
+  .el-progress__text {
+    display: none;
+  }
+
+  .el-progress-bar {
+    padding-right: 0;
+  }
+
+  .el-progress-bar__inner {
+    background-color: #ED1B2E;
+  }
+
+  .required {
+    position: relative;
+
+    &::before {
+      content: '*';
+      position: absolute;
+      color: #FF0000;
+      transform: translate(-12px, 0);
+      z-index: 5;
+    }
+  }
+
+  .area-txt {
+    display: flex;
+    align-items: center;
+    margin-left: 18px;
+  }
+
+  @include desktop {
+
+    .desktopBtn {
+      margin-right: 10px;
+      height: 47px
+    }
+
+    .popOtherBtn {
+      margin-left: 10px;
+      margin-top: -10px;
+    }
+
+    .rec-pop-container{
+      width:auto;
+    .rec-pop-options{
+      .el-checkbox-group{
+        display: flex;
+        flex-wrap:wrap;
+        flex-direction: none;
+        .el-checkbox{
+          width:90px;
+          height: 50px;
+          padding:0;
+          .el-checkbox__label{
+            justify-content: center;
+            align-items: center;
+            display: flex;
+            padding:15px 20px;
+            text-align: center;
+          }
+        }
+        .pam-selectAll-btn{
+          margin-top:0px;
+          margin-left:0px;
+          height: 50px;
+          width: 90px;
+          padding: 10px;
+        }
+      }
+    }
+
+  }
+
+    .rec-multi-select{
+    .el-checkbox-group {
+      display: flex;
+      flex-direction: row;
+      align-items: flex-start;
+      flex-wrap: wrap;
+    }
+  }
+  }
+}
diff --git a/PAMapp/pages/recommendConsultant/recommend-consultant.component.ts b/PAMapp/pages/recommendConsultant/recommend-consultant.component.ts
new file mode 100644
index 0000000..7b12d6e
--- /dev/null
+++ b/PAMapp/pages/recommendConsultant/recommend-consultant.component.ts
@@ -0,0 +1,183 @@
+import {
+  Vue,
+  Component,
+  Mutation,
+  namespace,
+  Action,
+  State
+} from 'nuxt-property-decorator';
+import * as _ from 'lodash';
+
+import { Seniority } from '~/assets/ts/models/enum/seniority';
+import { setRequestQuestionToStorage } from '~/assets/ts/storageRequests';
+import { Gender } from '~/assets/ts/models/enum/gender.enum';
+import { StrictQueryDto } from '~/assets/ts/models/strict-query-dto.model';
+
+const localStorage = namespace('localStorage');
+
+@Component
+export default class RecommendConsultant extends Vue {
+  isVisiblePopUp = false;
+  strictQueryDto: StrictQueryDto ={
+    gender:'',
+    area:'',
+    status:'',
+    requirements: [],
+    otherRequirement:'',
+    seniority:'',
+    avgScore:0,
+    popularTags: [],
+    otherPopularTags:'',
+  };
+  genderOptions=[
+    {
+      title:'���',
+      label:Gender.MALE,
+    },
+    {
+      title:'憟單��',
+      label:Gender.FEMALE,
+    }
+  ];
+  requirementOptions=[
+    {
+      title:'�摨瑁����',
+      label:'�摨瑁����',
+    },
+    {
+      title:'摮戊��',
+      label:'摮戊��',
+    },
+    {
+      title:'鞈閬��',
+      label:'鞈閬��',
+    },
+    {
+      title:'璅暑��隡�',
+      label:'璅暑��隡�',
+    },
+    {
+      title:'靽�瑼�/閬��',
+      label:'靽�瑼�/閬��',
+    },
+    {
+      title:'����',
+      label:'����',
+    },
+  ];
+  seniorityOptions=[
+    {
+      title:'銝��',
+      subTitle:'撟湧翩銝����',
+      label:Seniority.UNLIMITED,
+    },
+    {
+      title:'撟渲��',
+      subTitle:'蝯血僑頛犖銝�����',
+      label:Seniority.YOUNG,
+    },
+    {
+      title:'鞈楛',
+      subTitle:'����麾',
+      label:Seniority.SENIOR,
+    }
+  ];
+  popularOptions=[
+    {
+      title: '#��',
+      label:'��'
+    },
+    {
+      title: '#憭梯',
+      label:'憭梯'
+    },
+    {
+      title: '#����',
+      label:'����'
+    },
+    {
+      title: '#����',
+      label:'����'
+    },
+    {
+      title: '#憯賡',
+      label: '憯賡'
+    },
+    {
+      title: '#����',
+      label:'����'
+    },
+    {
+      title: '#����',
+      label:'����'
+    },
+    {
+      title: '#����',
+      label:'����'
+    }
+  ];
+  queaAboutList = [
+    {
+      title: '�摨瑁����',
+      content: '����澈擃憿批末嚗�靽�兢蝳�嚗��������嚗��飩������摮拙��粥銝��頝荔�犖����迤閬����'
+    },
+    {
+      title: '摮戊��',
+      content: '摮拙���������葦銋摮貊��撠靘�蒂�雿嚗飛���������������瓷嚗��楝銝���韏瑕飛��'
+    },
+    {
+      title: '鞈閬��',
+      content: '��迤��瓷撖��雓寡�����嚗鈭箇�����蝳西瓷��◢�����Ⅱ靽�蝛拙��嚗�摰嗆��靘�末��皞���'
+    },
+    {
+      title: '璅暑��隡�',
+      content: '�銝�頛拙����隡��摮���翰瘣鳴�停敺�����������隡瓷����撌勗�帘摰�嚗蝎曉蔗���僑鈭箇�������'
+    },
+    {
+      title: '靽�瑼�/閬��',
+      content: '��瑼Z�撌梁������蝚血����靘�◢�蝘餉��瘙��'
+    },
+    {
+      title: '����',
+      content: '���� ���������憸券�����鈭怒�����嚗���摰帘摰漲嚗��隞亙��澈��ˊ�靽���嚗�'
+    }
+  ];
+  showDialog = false;
+  showAddress = false;
+
+  @Mutation updateStrictQueryList!: (data: any) => void;
+  @Action storeStrictQueryList!: (data: any) => Promise<number>;
+  @State strictQueryList!: any;
+  @localStorage.State recommendConsultantItem!: string;
+
+  mounted() {
+    if (!!this.recommendConsultantItem) {
+      this.strictQueryDto = JSON.parse(this.recommendConsultantItem);
+    }
+  }
+  async makePair() {
+    await this.storeStrictQueryList(this.strictQueryDto).then(dataLength => {
+      const questions = this.strictQueryDto.requirements.length ? this.strictQueryDto.requirements : [];
+      setRequestQuestionToStorage(questions);
+      if (dataLength === 0) {
+        this.isVisiblePopUp = true;
+        return;
+      }
+      this.$router.push('/recommendConsultant/result');
+    });
+  }
+  get notFinishByRequireRules():boolean{
+    const area = this.strictQueryDto.area;
+    const requirementLength = this.strictQueryDto.requirements
+      ? this.strictQueryDto.requirements.length
+      : 0;
+    return !(area && requirementLength >0)
+  }
+
+  confirmAddress(area: string) {
+    this.strictQueryDto.area = area;
+    this.showAddress = false;
+  }
+
+}
+
diff --git a/PAMapp/pages/recommendConsultant/result.vue b/PAMapp/pages/recommendConsultant/result.vue
deleted file mode 100644
index 0c06be1..0000000
--- a/PAMapp/pages/recommendConsultant/result.vue
+++ /dev/null
@@ -1,233 +0,0 @@
-<template>
-<div>
-    <div class="mdTxt pb-10">��憿批��</div>
-    <ul class="pam-rec-agent__list">
-        <li class="pam-rec-agent-card" v-for="(info,index) in pageList" :key="index">
-            <div class="pam-rec-agent-card__content">
-                <div class="pam-rec-agent-card__content-header">
-                    <div class="pam-rec-agent-card__avatar">
-                        <UiAvatar :fileName="info.img" ></UiAvatar>
-                    </div>
-                    <div class="pam-rec-agent-card__main-info">
-                        <div class="text--middle  pt-10 rec-desktop-name">{{ info.name }}</div>
-                        <div class="rec-role">{{ info.role }}</div>
-                        <span class="rec-detail fix-chrome-click--issue"  @click="showAgentDetail(info.agentNo)">閰喟敦鞈��</span>
-                    </div>
-                </div>
-                <div class="pam-rec-agent-card__content-body">
-                    <el-row type="flex" class="pam-paragraph">
-                        <div class="field">
-                            <div class="field__label">撠����</div>
-                            <div class="field__content expertieses-container">
-                                <div class="pr-10 pb-10" v-for="(expert, index) in info.expertise" :key="index">
-                                    #{{ expert }}
-                                </div>
-                            </div>
-                        </div>
-                    </el-row>
-
-                    <el-row type="flex" class="pam-paragraph">
-                        <el-col :span="12">
-                            <div class="field__label">
-                            ����風
-                            </div>
-                            <div class="field__content">
-                            {{ info.seniority }}
-                            </div>
-                        </el-col>
-                        <el-col :span="12">
-                            <div class="field__label">
-                            摰X皛踵�漲
-                            </div>
-                            <div class="field__content">
-                                <i class="icon-star" style="color:#F2C75C"></i>
-                            {{ info.avgScore }}
-                            </div>
-                        </el-col>
-                    </el-row>
-
-                </div>
-                <div class="pam-rec-agent-card__content-footer">
-                    <AddAndReservedBtns
-                        :cusClass="'pam-rec-btns'"
-                        :agentInfo="info"
-                        @openPopUp="openPopUp"
-                    ></AddAndReservedBtns>
-                </div>
-            </div>
-        </li>
-    </ul>
-
-    <UiPagination
-        class="mb-30"
-        :totalList="strictQueryList"
-        @changePage="changePage"
-        :pageSize = 6
-    ></UiPagination>
-
-    <PopUpFrame :isOpen.sync="isVisiblePopUp"
-      >
-        <div class="text--center mdTxt">
-            <p class="mb-50">{{popUpTxt}}</p>
-            <div class="text--center">
-                <el-button
-                    type="primary"
-                    @click="isVisiblePopUp = false"
-                >������</el-button>
-            </div>
-        </div>
-    </PopUpFrame>
-
-</div>
-</template>
-<script lang="ts">
-import {Vue,Component, State, namespace, Action} from 'nuxt-property-decorator';
-import { AgentOfStrictQuery } from '~/assets/ts/api/consultant';
-
-const localStorage = namespace('localStorage');
-
-@Component
-export default class Reslut extends Vue{
-    @State('strictQueryList') strictQueryList!: AgentOfStrictQuery[];
-    @Action storeStrictQueryList!: (data: any) => Promise<number>;
-    @localStorage.State recommendConsultantItem!: string;
-
-    pageList: any[] = [];
-    isVisiblePopUp = false;
-    popUpTxt = '';
-    mounted() {
-        if (this.recommendConsultantItem && this.strictQueryList.length === 0) {
-            const strictQueryDto = JSON.parse(this.recommendConsultantItem);
-            this.storeStrictQueryList(strictQueryDto);
-        }
-    }
-
-    changePage(pageList: any[]) {
-        this.pageList = pageList;
-    }
-    showAgentDetail(agentNo: string): void {
-        this.$router.push(`/agentInfo/${agentNo}`);
-    }
-    openPopUp(txt: string) {
-        this.popUpTxt = txt;
-        this.isVisiblePopUp = true;
-    }
-}
-</script>
-
-<style lang="scss" scoped>
-.pam-rec-agent-card {
-    margin-bottom: 10px;
-    border-radius: 10px;
-    border: 1px solid $LIGHT_GREY;
-    padding: 20px 33px;
-
-    .pam-rec-agent-card__content {
-        .pam-rec-agent-card__content-header {
-            display: flex;
-            .pam-rec-agent-card__avatar {
-                display: flex;
-                flex-direction: row;
-                margin-right: 20px;
-            }
-            .pam-rec-agent-card__main-info {
-                display: flex;
-                flex-direction: column;
-                justify-content: flex-end;
-                .rec-role {
-                    font-size: 16px;
-                    color: $PRUDENTIAL_GREY;
-                    font-weight: bold;
-                    margin-top: 4px;
-                }
-                .rec-detail{
-                    font-size: 20px;
-                    color:$PRIMARY_RED;
-                    font-weight: bold;
-                    padding-top: 30px;
-                    cursor: pointer;
-                }
-            }
-        }
-        .pam-rec-agent-card__content-body {
-            height: 200px;
-        }
-    }
-}
-
-.field__label {
-    font-size: 16px;
-    color: $PRUDENTIAL_GREY;
-    font-weight:bold;
-    margin-bottom: 7px;
-}
-.field__content{
-    font-size: 18px;
-}
-.expertieses-container {
-    display: flex;
-    flex-wrap: wrap;
-}
-
-@include desktop{
-    .pam-rec-agent__list{
-        display: flex;
-        flex-wrap: wrap;
-        flex-direction:row;
-        width: 100%;
-    }
-    .pam-paragraph{
-        margin-top: 10px;
-    }
-    .pam-rec-agent-card {
-        border-radius: 10px;
-        border: 1px solid $LIGHT_GREY;
-        padding: 15px 20px 15px 20px;
-        width: 170px;
-        margin: 0 10px 10px 10px;
-
-        .pam-rec-agent-card__content {
-            .pam-rec-agent-card__content-header {
-                display: flex;
-                .pam-rec-agent-card__avatar {
-                    display: flex;
-                    flex-direction: row;
-                    margin-right: 20px;
-                }
-                .pam-rec-agent-card__main-info {
-                    display: flex;
-                    flex-direction: column;
-                    justify-content: center;
-                    .rec-desktop-name{
-                        font-size: 12px;
-                        font-weight: bold;
-                    }
-                    .rec-role {
-                        font-size: 12px;
-                        color:$PRUDENTIAL_GREY;
-                    }
-                    .rec-detail{
-                        font-size: 12px;
-                        color:$PRIMARY_RED;
-                        font-weight: bold;
-                        padding-top: 10px;
-                    }
-                }
-            }
-        }
-    }
-    .field__label {
-        font-size: 12px;
-        color: $PRUDENTIAL_GREY;
-        font-weight:bold;
-        margin-bottom: 7px;
-    }
-    .field__content{
-        font-size: 12px;
-    }
-    .expertieses-container {
-        display: flex;
-        flex-wrap: wrap;
-    }
-}
-</style>
diff --git a/PAMapp/pages/recommendConsultant/result/index.vue b/PAMapp/pages/recommendConsultant/result/index.vue
new file mode 100644
index 0000000..00ce1b1
--- /dev/null
+++ b/PAMapp/pages/recommendConsultant/result/index.vue
@@ -0,0 +1,88 @@
+<template>
+<div>
+    <div class="mdTxt pb-10">��憿批��</div>
+    <ul class="pam-rec-agent__list">
+        <li class="pam-rec-agent-card" v-for="(info,index) in pageList" :key="index">
+            <div class="pam-rec-agent-card__content">
+                <div class="pam-rec-agent-card__content-header">
+                    <div class="pam-rec-agent-card__avatar">
+                        <UiAvatar :fileName="info.img" ></UiAvatar>
+                    </div>
+                    <div class="pam-rec-agent-card__main-info">
+                        <div class="text--middle  pt-10 rec-desktop-name">{{ info.name }}</div>
+                        <div class="rec-role">{{ info.role }}</div>
+                        <span class="rec-detail fix-chrome-click--issue"  @click="showAgentDetail(info.agentNo)">閰喟敦鞈��</span>
+                    </div>
+                </div>
+                <div class="pam-rec-agent-card__content-body">
+                    <el-row type="flex" class="pam-paragraph">
+                        <div class="field">
+                            <div class="field__label">撠����</div>
+                            <div class="field__content expertieses-container">
+                                <div class="pr-10 pb-10" v-for="(expert, index) in info.expertise" :key="index">
+                                    #{{ expert }}
+                                </div>
+                            </div>
+                        </div>
+                    </el-row>
+
+                    <el-row type="flex" class="pam-paragraph">
+                        <el-col :span="12">
+                            <div class="field__label">
+                            ����風
+                            </div>
+                            <div class="field__content">
+                            {{ info.seniority }}
+                            </div>
+                        </el-col>
+                        <el-col :span="12">
+                            <div class="field__label">
+                            摰X皛踵�漲
+                            </div>
+                            <div class="field__content">
+                                <i class="icon-star" style="color:#F2C75C"></i>
+                            {{ info.avgScore }}
+                            </div>
+                        </el-col>
+                    </el-row>
+
+                </div>
+                <div class="pam-rec-agent-card__content-footer">
+                    <AddAndReservedBtns
+                        :cusClass="'pam-rec-btns'"
+                        :agentInfo="info"
+                        @openPopUp="openPopUp"
+                    ></AddAndReservedBtns>
+                </div>
+            </div>
+        </li>
+    </ul>
+
+    <UiPagination
+        class="mb-30"
+        :totalList="strictQueryList"
+        @changePage="changePage"
+        :pageSize = 6
+    ></UiPagination>
+
+    <PopUpFrame :isOpen.sync="isVisiblePopUp"
+      >
+        <div class="text--center mdTxt">
+            <p class="mb-50">{{popUpTxt}}</p>
+            <div class="text--center">
+                <el-button
+                    type="primary"
+                    @click="isVisiblePopUp = false"
+                >������</el-button>
+            </div>
+        </div>
+    </PopUpFrame>
+
+</div>
+</template>
+
+<script src="./recommend-consultant-result.component.ts"></script>
+
+<style lang="scss" scoped>
+  @import "./recommend-consultant-result.component.scss";
+</style>
diff --git a/PAMapp/pages/recommendConsultant/result/recommend-consultant-result.component.scss b/PAMapp/pages/recommendConsultant/result/recommend-consultant-result.component.scss
new file mode 100644
index 0000000..fc88fdd
--- /dev/null
+++ b/PAMapp/pages/recommendConsultant/result/recommend-consultant-result.component.scss
@@ -0,0 +1,114 @@
+.pam-rec-agent-card {
+  margin-bottom: 10px;
+  border-radius: 10px;
+  border: 1px solid $LIGHT_GREY;
+  padding: 20px 33px;
+
+  .pam-rec-agent-card__content {
+      .pam-rec-agent-card__content-header {
+          display: flex;
+          .pam-rec-agent-card__avatar {
+              display: flex;
+              flex-direction: row;
+              margin-right: 20px;
+          }
+          .pam-rec-agent-card__main-info {
+              display: flex;
+              flex-direction: column;
+              justify-content: flex-end;
+              .rec-role {
+                  font-size: 16px;
+                  color: $PRUDENTIAL_GREY;
+                  font-weight: bold;
+                  margin-top: 4px;
+              }
+              .rec-detail{
+                  font-size: 20px;
+                  color:$PRIMARY_RED;
+                  font-weight: bold;
+                  padding-top: 30px;
+                  cursor: pointer;
+              }
+          }
+      }
+      .pam-rec-agent-card__content-body {
+          height: 200px;
+      }
+  }
+}
+
+.field__label {
+  font-size: 16px;
+  color: $PRUDENTIAL_GREY;
+  font-weight:bold;
+  margin-bottom: 7px;
+}
+.field__content{
+  font-size: 18px;
+}
+.expertieses-container {
+  display: flex;
+  flex-wrap: wrap;
+}
+
+@include desktop{
+  .pam-rec-agent__list{
+      display: flex;
+      flex-wrap: wrap;
+      flex-direction:row;
+      width: 100%;
+  }
+  .pam-paragraph{
+      margin-top: 10px;
+  }
+  .pam-rec-agent-card {
+      border-radius: 10px;
+      border: 1px solid $LIGHT_GREY;
+      padding: 15px 20px 15px 20px;
+      width: 170px;
+      margin: 0 10px 10px 10px;
+
+      .pam-rec-agent-card__content {
+          .pam-rec-agent-card__content-header {
+              display: flex;
+              .pam-rec-agent-card__avatar {
+                  display: flex;
+                  flex-direction: row;
+                  margin-right: 20px;
+              }
+              .pam-rec-agent-card__main-info {
+                  display: flex;
+                  flex-direction: column;
+                  justify-content: center;
+                  .rec-desktop-name{
+                      font-size: 12px;
+                      font-weight: bold;
+                  }
+                  .rec-role {
+                      font-size: 12px;
+                      color:$PRUDENTIAL_GREY;
+                  }
+                  .rec-detail{
+                      font-size: 12px;
+                      color:$PRIMARY_RED;
+                      font-weight: bold;
+                      padding-top: 10px;
+                  }
+              }
+          }
+      }
+  }
+  .field__label {
+      font-size: 12px;
+      color: $PRUDENTIAL_GREY;
+      font-weight:bold;
+      margin-bottom: 7px;
+  }
+  .field__content{
+      font-size: 12px;
+  }
+  .expertieses-container {
+      display: flex;
+      flex-wrap: wrap;
+  }
+}
diff --git a/PAMapp/pages/recommendConsultant/result/recommend-consultant-result.component.ts b/PAMapp/pages/recommendConsultant/result/recommend-consultant-result.component.ts
new file mode 100644
index 0000000..fa7b3d5
--- /dev/null
+++ b/PAMapp/pages/recommendConsultant/result/recommend-consultant-result.component.ts
@@ -0,0 +1,32 @@
+import {Vue,Component, State, namespace, Action} from 'nuxt-property-decorator';
+import { AgentOfStrictQuery } from '~/assets/ts/api/consultant';
+
+const localStorage = namespace('localStorage');
+
+@Component
+export default class RecommendConsultantResult extends Vue{
+    @State('strictQueryList') strictQueryList!: AgentOfStrictQuery[];
+    @Action storeStrictQueryList!: (data: any) => Promise<number>;
+    @localStorage.State recommendConsultantItem!: string;
+
+    pageList: any[] = [];
+    isVisiblePopUp = false;
+    popUpTxt = '';
+    mounted() {
+        if (this.recommendConsultantItem && this.strictQueryList.length === 0) {
+            const strictQueryDto = JSON.parse(this.recommendConsultantItem);
+            this.storeStrictQueryList(strictQueryDto);
+        }
+    }
+
+    changePage(pageList: any[]) {
+        this.pageList = pageList;
+    }
+    showAgentDetail(agentNo: string): void {
+        this.$router.push(`/agentInfo/${agentNo}`);
+    }
+    openPopUp(txt: string) {
+        this.popUpTxt = txt;
+        this.isVisiblePopUp = true;
+    }
+}
diff --git a/PAMapp/pages/record.vue b/PAMapp/pages/record.vue
deleted file mode 100644
index bf002b7..0000000
--- a/PAMapp/pages/record.vue
+++ /dev/null
@@ -1,45 +0,0 @@
-<template>
-    <!-- <div>record-�������
-        <el-tabs
-            v-model="activeTabName"
-            @tab-click="tabClick"
-        >
-            <el-tab-pane
-                label="�������"
-                name="contactRecord"
-            >
-            </el-tab-pane>
-            <el-tab-pane
-                label="皛踵�漲蝝����"
-                name="reviews"
-            ></el-tab-pane>
-        </el-tabs> -->
-
-        <NuxtChild></NuxtChild>
-    <!-- </div> -->
-</template>
-
-<script lang="ts">
-import { Vue, Component, Watch } from 'vue-property-decorator';
-import { Route } from 'vue-router/types/router.d';
-
-@Component
-export default class Record extends Vue {
-    activeTabName = 'contactRecord';
-
-    tabClick() {
-        this.$router.push('/record/' + this.activeTabName);
-    }
-
-    @Watch('$route') watchRouter(currentRoute: Route) {
-        const pathArray = currentRoute.fullPath.split('/');
-        this.activeTabName = pathArray[pathArray.length - 1];
-    }
-}
-</script>
-
-<style lang="scss" scoped>
-    .el-tabs__item:hover {
-        color: #303133;
-    }
-</style>
\ No newline at end of file
diff --git a/PAMapp/pages/record/contactRecord.vue b/PAMapp/pages/record/contactRecord.vue
deleted file mode 100644
index eebe275..0000000
--- a/PAMapp/pages/record/contactRecord.vue
+++ /dev/null
@@ -1,3 +0,0 @@
-<template>
-    <div>�������(�������)</div>
-</template>
\ No newline at end of file
diff --git a/PAMapp/pages/record/index.vue b/PAMapp/pages/record/index.vue
index 692841f..0dfac99 100644
--- a/PAMapp/pages/record/index.vue
+++ b/PAMapp/pages/record/index.vue
@@ -12,7 +12,7 @@
     </section>
 
     <section class="user-reviews-content">
-        <div 
+        <div
             class="user-reviews-card"
             v-for="(appointmentLog, index) in myAppointmentReviewLogList"
             :key="index">
@@ -24,92 +24,25 @@
             </div>
             <div class="user-reviews-card-date">
                 <div class="date">
-                    <UiDateFormat 
+                    <UiDateFormat
                         :date="appointmentLog.lastModifiedDate"
                         onlyShowSection="DAY" />
                 </div>
                 <div class="time">
-                    <UiDateFormat 
+                    <UiDateFormat
                         :date="appointmentLog.lastModifiedDate"
                         onlyShowSection="TIME" />
                 </div>
             </div>
         </div>
     </section>
-  
+
 </div>
 
 </template>
-<script lang="ts">
-import { Vue, Component, Action, State, namespace } from 'nuxt-property-decorator';
-import { AppointmentLog } from '~/assets/ts/models/appointment.model';
 
-const roleStorage = namespace('localStorage');
+<script src="./record.component.ts"></script>
 
-@Component
-export default  class Reviews extends Vue{
-
-    today = new Date();
-
-    @roleStorage.Getter currentRole!:string;
-
-    @State('myAppointmentReviewLogList') myAppointmentReviewLogList!: AppointmentLog[];
-
-    @Action storeMyAppointmentReviewLog!: any;
-
-    appointmentLogList: AppointmentLog[] = [];
-
-    mounted() {
-        this.storeMyAppointmentReviewLog();
-    }
-
-    
-    
-}
-</script>
-<style lang="scss" scoped>
-.user-reviews-page{
-    margin-bottom:155px;
-    .user-reviews-header{
-        height: 43px;
-        margin-top: 28px;
-        display: flex;
-        justify-content: center;
-        border-bottom: 2px solid black;
-    }
-    .user-reviews-content{
-        .user-reviews-card{
-            display: flex;
-            justify-content: space-between;
-            margin-top: 26px;
-            border-bottom: 1px solid #707070;
-            height: 54px;
-            padding-bottom: 15px;
-            .user-reviews-card-content{
-                width: 242px;
-                padding-right:50px;
-                line-height: 1.2;
-                font-size: 20px;
-                margin-left: 15px;
-            }
-            .user-reviews-card-date{
-                font-size: 12px;
-                display: flex;
-                flex-direction: column;
-                align-items: flex-end;
-                margin-right: 15px;
-                width:52px;
-                .date{
-                    margin-bottom: 2px;
-                    
-                }
-            }
-        }
-    }
-}
-@include desktop{
-    .user-reviews-card-content{
-        flex: 1;
-    }
-}
-</style>
\ No newline at end of file
+<style lang="scss">
+  @import "./record.component.scss";
+</style>
diff --git a/PAMapp/pages/record/record.component.scss b/PAMapp/pages/record/record.component.scss
new file mode 100644
index 0000000..be1a4c6
--- /dev/null
+++ b/PAMapp/pages/record/record.component.scss
@@ -0,0 +1,44 @@
+.user-reviews-page{
+  margin-bottom:155px;
+  .user-reviews-header{
+      height: 43px;
+      margin-top: 28px;
+      display: flex;
+      justify-content: center;
+      border-bottom: 2px solid black;
+  }
+  .user-reviews-content{
+      .user-reviews-card{
+          display: flex;
+          justify-content: space-between;
+          margin-top: 26px;
+          border-bottom: 1px solid #707070;
+          height: 54px;
+          padding-bottom: 15px;
+          .user-reviews-card-content{
+              width: 242px;
+              padding-right:50px;
+              line-height: 1.2;
+              font-size: 20px;
+              margin-left: 15px;
+          }
+          .user-reviews-card-date{
+              font-size: 12px;
+              display: flex;
+              flex-direction: column;
+              align-items: flex-end;
+              margin-right: 15px;
+              width:52px;
+              .date{
+                  margin-bottom: 2px;
+
+              }
+          }
+      }
+  }
+}
+@include desktop{
+  .user-reviews-card-content{
+      flex: 1;
+  }
+}
diff --git a/PAMapp/pages/record/record.component.ts b/PAMapp/pages/record/record.component.ts
new file mode 100644
index 0000000..4e66245
--- /dev/null
+++ b/PAMapp/pages/record/record.component.ts
@@ -0,0 +1,23 @@
+import { Vue, Component, Action, State, namespace } from 'nuxt-property-decorator';
+import { AppointmentLog } from '~/assets/ts/models/appointment.model';
+
+const roleStorage = namespace('localStorage');
+
+@Component
+export default  class Reviews extends Vue{
+
+    today = new Date();
+
+    @roleStorage.Getter currentRole!:string;
+
+    @State('myAppointmentReviewLogList') myAppointmentReviewLogList!: AppointmentLog[];
+
+    @Action storeMyAppointmentReviewLog!: any;
+
+    appointmentLogList: AppointmentLog[] = [];
+
+    mounted() {
+        this.storeMyAppointmentReviewLog();
+    }
+
+}
diff --git a/PAMapp/pages/record/reviews.vue b/PAMapp/pages/record/reviews.vue
deleted file mode 100644
index 792609c..0000000
--- a/PAMapp/pages/record/reviews.vue
+++ /dev/null
@@ -1,3 +0,0 @@
-<template>
-    <div>�������(皛踵�漲蝝����)</div>
-</template>
\ No newline at end of file
diff --git a/PAMapp/pages/userReviews/index.vue b/PAMapp/pages/userReviews/index.vue
index 96b0cd9..92b8406 100644
--- a/PAMapp/pages/userReviews/index.vue
+++ b/PAMapp/pages/userReviews/index.vue
@@ -1,9 +1,9 @@
-<template> 
+<template>
 <div class="reviews-page">
     <!-- 憿批恥��遛��漲蝯阡“��� -->
     <div class="reviews-banner"></div>
 
-    <section class="reviews-container"> 
+    <section class="reviews-container">
         <section class="reviews-header">
             <div class="reviews-header-container">
                 <div class="reviews-header-title">皛踵�漲隤踵</div>
@@ -20,17 +20,17 @@
                     <div class="card-txt">
                         撠憿批��
                         <span class="p">{{item.name}}</span>��擃���,�蝯虫�嗾憿���?
-                        <div 
+                        <div
                             class="card-score"
                             v-if="!isMobileDevice">
                             <el-rate class="user-reviews-rate" v-model="item.avgScore"></el-rate>
                         </div>
                     </div>
                 </div>
-                <div 
+                <div
                     class="card-score"
                     v-if="isMobileDevice">
-                    <el-rate 
+                    <el-rate
                         class="user-reviews-rate"
                         v-model="item.avgScore"></el-rate>
                 </div>
@@ -49,164 +49,13 @@
             <el-button type="primary" class="reviews-dialog-btn" @click.native="reviewsDialogCheck">������</el-button>
         </div>
     </PopUpFrame>
-    
+
 
 </div>
 </template>
-<script lang="ts">
-import { Vue,Component } from 'vue-property-decorator'
-import { isMobileDevice } from '~/assets/ts/device';
 
+<script src="./user-reviews.component.ts"></script>
 
-@Component({
-    layout: 'home'
-})
-export default class UserReviews extends Vue{
-
-    isMobileDevice = true;
-
-    showReviews = false;
-
-    reviewsList:ReviewsList[] = [
-        {
-            avatar:'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
-            name:'�蝢��',
-            avgScore: 0
-        },
-        {
-            avatar:'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
-            name:'鞈�',
-            avgScore: 0
-        },
-        {
-            avatar:'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
-            name:'������',
-            avgScore: 0
-        }
-    ];
-
-    reviewsDialogCheck(): void {
-        this.reviewsList = this.reviewsList.filter((reviewItem) => !reviewItem.avgScore);
-        this.showReviews = false;
-    };
-
-    mounted() {
-        this.isMobileDevice = isMobileDevice();
-    };
-
-    sendReviews() {
-        this.showReviews = true;
-    };
-}
-export interface ReviewsList{
-    avatar:any;
-    name:string;
-    avgScore:number;
-}
-</script>
-<style lang="scss" scoped>
-.reviews-page{
-    background-color: #F8F9FA;
-    .reviews-banner{
-        background-image: url('~/assets/images/satisfaction/banner_mob.svg');
-        height: 120px;
-        margin-bottom: 10px;
-    }
-    .reviews-container{
-        padding-right: 10px;
-        padding-left: 10px;
-        padding-bottom: 10px;
-        .reviews-header{
-            margin-top: 10px;
-            .reviews-header-container{
-                display: flex;
-                margin-bottom:38px;
-                align-items: baseline;
-                .reviews-header-title{
-                    margin-right: 17.5px;
-                    font-size: 20px;
-                }
-                .reviews-header-subTitle{
-                    font-size: 16px;
-                    color: #68737A;
-                }
-            }
-        }
-        .reviews-content{
-            .reviews-content-card{
-                .card-body{
-                    display: flex;
-                    .card-avatar{
-                        .img{
-                            height: 80px;
-                            width: 80px;
-                        }
-                    }
-                    .card-txt{
-                        font-size: 20px;
-                        padding-top: 20px;
-                        .p{
-                            font-size: 23px;
-                            color:#ED1B2E;
-                            font-weight: bold;
-                        }
-                    }
-                }
-                .card-score{
-                    margin-top: 10px;
-                    margin-bottom: 30px;
-                    display: flex;
-                    justify-content: center;
-                }
-            }
-        }
-    }
-    .reviews-footer{
-        height: 70px;
-        display: flex;
-        justify-content: center;
-        margin-top: 45px;
-        background-color: #fff;
-        .reviews-footer-btn{
-            width: 120px;
-            height: 50px;
-            margin-top: 10px;
-        }
-    }
-    .reviews-dialog{
-        display: flex;
-        justify-content: center;
-        margin-bottom: 56px;
-        .reviews-dialog-title{
-            font-size: 18px;
-        }
-    }
-    .reviews-btn-block{
-        display: flex;
-        justify-content: center;
-    }
-}
-
-@include desktop{
-    .reviews-page{
-        .reviews-banner{
-            height: 147px;
-            background-image: url('~/assets/images/satisfaction/banner_web.svg');
-        }
-        .reviews-container{
-            width: 700px;
-            margin: 30px auto 0px auto;
-            .reviews-content{
-                display: flex;
-                flex-direction: column;
-                align-items: flex-start;
-            }
-        }
-        .reviews-footer{
-            background-color:#F8F9FA;
-        }
-    }
-
-}
-
-</style>
\ No newline at end of file
+<style lang="scss">
+  @import "./user-reviews.component.scss";
+</style>
diff --git a/PAMapp/pages/userReviews/user-reviews.component.scss b/PAMapp/pages/userReviews/user-reviews.component.scss
new file mode 100644
index 0000000..969cf5c
--- /dev/null
+++ b/PAMapp/pages/userReviews/user-reviews.component.scss
@@ -0,0 +1,103 @@
+.reviews-page{
+    background-color: #F8F9FA;
+    .reviews-banner{
+        background-image: url('~/assets/images/satisfaction/banner_mob.svg');
+        height: 120px;
+        margin-bottom: 10px;
+    }
+    .reviews-container{
+        padding-right: 10px;
+        padding-left: 10px;
+        padding-bottom: 10px;
+        .reviews-header{
+            margin-top: 10px;
+            .reviews-header-container{
+                display: flex;
+                margin-bottom:38px;
+                align-items: baseline;
+                .reviews-header-title{
+                    margin-right: 17.5px;
+                    font-size: 20px;
+                }
+                .reviews-header-subTitle{
+                    font-size: 16px;
+                    color: #68737A;
+                }
+            }
+        }
+        .reviews-content{
+            .reviews-content-card{
+                .card-body{
+                    display: flex;
+                    .card-avatar{
+                        .img{
+                            height: 80px;
+                            width: 80px;
+                        }
+                    }
+                    .card-txt{
+                        font-size: 20px;
+                        padding-top: 20px;
+                        .p{
+                            font-size: 23px;
+                            color:#ED1B2E;
+                            font-weight: bold;
+                        }
+                    }
+                }
+                .card-score{
+                    margin-top: 10px;
+                    margin-bottom: 30px;
+                    display: flex;
+                    justify-content: center;
+                }
+            }
+        }
+    }
+    .reviews-footer{
+        height: 70px;
+        display: flex;
+        justify-content: center;
+        margin-top: 45px;
+        background-color: #fff;
+        .reviews-footer-btn{
+            width: 120px;
+            height: 50px;
+            margin-top: 10px;
+        }
+    }
+    .reviews-dialog{
+        display: flex;
+        justify-content: center;
+        margin-bottom: 56px;
+        .reviews-dialog-title{
+            font-size: 18px;
+        }
+    }
+    .reviews-btn-block{
+        display: flex;
+        justify-content: center;
+    }
+}
+
+@include desktop{
+    .reviews-page{
+        .reviews-banner{
+            height: 147px;
+            background-image: url('~/assets/images/satisfaction/banner_web.svg');
+        }
+        .reviews-container{
+            width: 700px;
+            margin: 30px auto 0px auto;
+            .reviews-content{
+                display: flex;
+                flex-direction: column;
+                align-items: flex-start;
+            }
+        }
+        .reviews-footer{
+            background-color:#F8F9FA;
+        }
+    }
+
+}
diff --git a/PAMapp/pages/userReviews/user-reviews.component.ts b/PAMapp/pages/userReviews/user-reviews.component.ts
new file mode 100644
index 0000000..061f640
--- /dev/null
+++ b/PAMapp/pages/userReviews/user-reviews.component.ts
@@ -0,0 +1,43 @@
+import { Vue,Component } from 'vue-property-decorator'
+import { isMobileDevice } from '~/assets/ts/device';
+import { ReviewsItem } from '~/assets/ts/models/reviews-item.model';
+
+@Component({
+    layout: 'home'
+})
+export default class UserReviews extends Vue {
+
+    isMobileDevice = true;
+    showReviews = false;
+
+    reviewsList: ReviewsItem[] = [
+        {
+            avatar:'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
+            name:'�蝢��',
+            avgScore: 0
+        },
+        {
+            avatar:'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
+            name:'鞈�',
+            avgScore: 0
+        },
+        {
+            avatar:'https://cube.elemecdn.com/0/88/03b0d39583f48206768a7534e55bcpng.png',
+            name:'������',
+            avgScore: 0
+        }
+    ];
+
+    reviewsDialogCheck(): void {
+        this.reviewsList = this.reviewsList.filter((reviewItem) => !reviewItem.avgScore);
+        this.showReviews = false;
+    };
+
+    mounted() {
+        this.isMobileDevice = isMobileDevice();
+    };
+
+    sendReviews() {
+        this.showReviews = true;
+    };
+}
diff --git a/PAMapp/pages/userReviewsRecord/index.vue b/PAMapp/pages/userReviewsRecord/index.vue
deleted file mode 100644
index a0665d9..0000000
--- a/PAMapp/pages/userReviewsRecord/index.vue
+++ /dev/null
@@ -1,113 +0,0 @@
-<template>
-
-<div class="user-reviews-page">
-    <section class="mdTxt">
-        �������
-    </section>
-
-    <section class="user-reviews-header">
-        <div class="header-title mdTxt">
-            皛踵�漲蝝����
-        </div>
-    </section>
-
-    <section class="user-reviews-content">
-        <div 
-            class="user-reviews-card"
-            v-for="(appointmentLog, index) in myAppointmentReviewLogList"
-            :key="index">
-            <div class="user-reviews-card-content" v-if="currentRole === 'user'">
-                �撠�<span class="mdTxt">{{ ` ${appointmentLog.agentName} ` }}</span>���� <UiReviewScore :score="appointmentLog.score" /> 閰嚗�
-            </div>
-            <div class="user-reviews-card-content" v-else>
-                {{ `${appointmentLog.clientName} `}} 撠���� <UiReviewScore :score="appointmentLog.score" /> 閰嚗�
-            </div>
-            <div class="user-reviews-card-date">
-                <div class="date">
-                    <UiDateFormat 
-                        :date="appointmentLog.lastModifiedDate"
-                        onlyShowSection="DAY" />
-                </div>
-                <div class="time">
-                    <UiDateFormat 
-                        :date="appointmentLog.lastModifiedDate"
-                        onlyShowSection="TIME" />
-                </div>
-            </div>
-        </div>
-    </section>
-  
-</div>
-
-</template>
-<script lang="ts">
-import { Vue, Component, Action, State, namespace } from 'nuxt-property-decorator';
-import { AppointmentLog } from '~/assets/ts/models/appointment.model';
-
-const roleStorage = namespace('localStorage');
-
-@Component
-export default  class UserReviewsRecord extends Vue{
-
-    today = new Date();
-
-    @roleStorage.Getter currentRole!:string;
-
-    @State('myAppointmentReviewLogList') myAppointmentReviewLogList!: AppointmentLog[];
-
-    @Action storeMyAppointmentReviewLog!: any;
-
-    appointmentLogList: AppointmentLog[] = [];
-
-    mounted() {
-        this.storeMyAppointmentReviewLog();
-    }
-    
-}
-</script>
-<style lang="scss" scoped>
-.user-reviews-page{
-    margin-bottom:155px;
-    .user-reviews-header{
-        height: 43px;
-        margin-top: 28px;
-        display: flex;
-        justify-content: center;
-        border-bottom: 2px solid black;
-    }
-    .user-reviews-content{
-        .user-reviews-card{
-            display: flex;
-            justify-content: space-between;
-            margin-top: 26px;
-            border-bottom: 1px solid #707070;
-            height: 54px;
-            padding-bottom: 15px;
-            .user-reviews-card-content{
-                width: 242px;
-                padding-right:50px;
-                line-height: 1.2;
-                font-size: 20px;
-                margin-left: 15px;
-            }
-            .user-reviews-card-date{
-                font-size: 12px;
-                display: flex;
-                flex-direction: column;
-                align-items: flex-end;
-                margin-right: 15px;
-                width:52px;
-                .date{
-                    margin-bottom: 2px;
-                    
-                }
-            }
-        }
-    }
-}
-@include desktop{
-    .user-reviews-card-content{
-        flex: 1;
-    }
-}
-</style>
\ No newline at end of file
diff --git a/PAMapp/store/localStorage.ts b/PAMapp/store/localStorage.ts
index d93aa2c..96bc774 100644
--- a/PAMapp/store/localStorage.ts
+++ b/PAMapp/store/localStorage.ts
@@ -1,5 +1,5 @@
-import { Selected } from '~/components/QuickFilter/QuickFilterSelector.vue';
 import { Module, Mutation, VuexModule ,Action } from 'vuex-module-decorators';
+import { Selected } from '~/assets/ts/models/selected.model';
 @Module
 export default class LocalStorage extends VuexModule {
   id_token = localStorage.getItem('id_token');

--
Gitblit v1.8.0