| | |
| | | <template> |
| | | <div class="ques-page--reset"> |
| | | <div class="ques-page--reset" v-if="isUserLogin"> |
| | | <div class="ques-header"> |
| | | <div class="ques-header__mob-banner"></div> |
| | | <div class="ques-header__info" v-if="myRequest.contactType==='phone'"> |
| | | <div |
| | | class="ques-header__info" |
| | | v-if="myRequest.contactType==='phone'"> |
| | | <div class="text--middle"> |
| | | <div class="mdTxt">你指定的聯繫方式</div> |
| | | <div class="mdTxt">您指定的聯繫方式</div> |
| | | <div class="mt-10"> |
| | | <span>手機:</span> |
| | | <span>{{myRequest.phone}}</span> |
| | |
| | | <div class="datepicker required"> |
| | | <span class="mdTxt">手機連絡的方便時間</span> |
| | | <PhoneContactTimePicker |
| | | :scheduleList.sync="myRequest.hopeContactTime"/> |
| | | :scheduleList="myRequest.hopeContactTime"/> |
| | | </div> |
| | | </div> |
| | | <div class="mt-30"> |
| | | <div class="mdTxt">其他備用聯繫方式</div> |
| | | <div class="ques-header__input-block"> |
| | | <span>Email:</span> |
| | | <input class="ques-header__input" |
| | | <input class="ques-header__input break" |
| | | :class="{ 'is-invalid': !emailValid}" |
| | | placeholder="請輸入" |
| | | v-model="myRequest.email"> |
| | | </div> |
| | | <div class="error mt-5 mb-5" style="margin-left:65px"> |
| | | <span v-show="!emailValid">Email格式有誤</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | <div class="ques-header__info" v-else> |
| | | <div class="text--middle"> |
| | | <div class="mdTxt">你指定的聯繫方式</div> |
| | | <div class="mdTxt">您指定的聯繫方式</div> |
| | | <div class="mt-10 ques-header__input-block"> |
| | | <span>Email:</span> |
| | | <span>{{myRequest.email}}</span> |
| | | <span class=" break">{{myRequest.email}}</span> |
| | | </div> |
| | | </div> |
| | | <div class="mt-30"> |
| | | <div class="mdTxt">其他備用聯繫方式</div> |
| | | <div class="ques-header__input-block"> |
| | | <span>手機:</span> |
| | | <input class="ques-header__input" |
| | | <span>手機 : </span> |
| | | <input class="ques-header__input ml-4" |
| | | :class="{'is-invalid': !phoneValid}" |
| | | placeholder="請輸入" |
| | | maxlength="10" |
| | |
| | | <span v-show="!phoneValid">手機號碼格式有誤</span> |
| | | </div> |
| | | </div> |
| | | <div class="mt-30" v-if="checkPhoneLength&&phoneValid"> |
| | | <div class="mt-30" v-if="myRequest.phone && phoneValid"> |
| | | <div class="datepicker"> |
| | | <span class="mdTxt">手機連絡的方便時間</span> |
| | | <PhoneContactTimePicker |
| | | :scheduleList.sync="myRequest.hopeContactTime"/> |
| | | :scheduleList="myRequest.hopeContactTime"/> |
| | | </div> |
| | | </div> |
| | | </div> |
| | |
| | | <div class="ques-container"> |
| | | <div class="pam-paragraph"> |
| | | <div class="mdTxt"> |
| | | 想要詢問的問題 |
| | | 想了解的領域 |
| | | <span class="hint text--bold"> |
| | | (可複選) |
| | | </span> |
| | |
| | | :options="requirementOptions" /> |
| | | </div> |
| | | <div class="pam-paragraph"> |
| | | <div class="mdTxt">諮詢方式</div> |
| | | <SingleSelectBtn class="mt-10" |
| | | :singleSelected.sync="myRequest.consultationMethod" |
| | | :options="consultationMethodOptions" /> |
| | | </div> |
| | | <div class="pam-paragraph"> |
| | | <div class="mdTxt">您的性別</div> |
| | | <SingleSelectBtn class="mt-10" |
| | | :singleSelected.sync="myRequest.gender" |
| | | :options="genderOptions" /> |
| | | </div> |
| | | <div class="pam-paragraph"> |
| | | <div class="mdTxt">年齡</div> |
| | | <div class="mdTxt">您的年齡</div> |
| | | <SingleSelectBtn class="mt-10" |
| | | :singleSelected.sync="myRequest.age" |
| | | :options="ageRangeOptions" /> |
| | |
| | | </div> |
| | | <div class="pam-paragraph ques-footer"> |
| | | <el-button type="primary" |
| | | :disabled="isRequiredByInit || !phoneValid" |
| | | :disabled="isDisabledSubmitBtn" |
| | | @click.native="sentDemand"> |
| | | 送出 |
| | | {{isEditBtn ? '更新' : '送出'}} |
| | | </el-button> |
| | | </div> |
| | | </div> |
| | | |
| | | <PopUpFrame :isOpen.sync="showDrawer" :drawerSize=" '95%' "> |
| | | <PopUpFrame :isOpen.sync="showDrawer"> |
| | | <div class="qaTextTitle mdTxt"> |
| | | <strong>想要詢問的問題</strong> |
| | | <strong>想了解的領域</strong> |
| | | </div> |
| | | <div class="qa-dialog"> |
| | | <div v-for="(qaText,index) in quesAboutList" :key="index" > |
| | |
| | | </PopUpFrame> |
| | | |
| | | <PopUpFrame :isOpen.sync="sendReserve" @update:isOpen="closeReservePopUp"> |
| | | <div class="text--middle mt-30 sendReserve-txt">預約成功!您預約的保險顧問會</div> |
| | | <div class="text--middle sendReserve-txt">儘速與您聯絡!</div> |
| | | <div class="mdTxt mt-30 sendReserve-txt">預約成功!</div> |
| | | <div class="mdTxt sendReserve-txt mb-30">您預約的顧問會儘速與您聯絡!</div> |
| | | <div class="pam-app-review mb-10"> |
| | | <div class="mdTxt mb-10">對於 |
| | | <span class="mdTxt text--primary text--bold ">服務媒合</span> |
| | | 平台的整體服務, |
| | | </div> |
| | | <div class="mdTxt">您給予幾顆星評價?</div> |
| | | </div> |
| | | <el-rate v-model="score" class="pam-satisfaction-rate fix-chrome-click--issue"></el-rate> |
| | | <div class="text--center mdTxt"> |
| | | <el-button @click="closeReservePopUp">略過</el-button> |
| | | <el-button type="primary" |
| | | @click="closeReservePopUp"> |
| | | 我知道了 |
| | | @click="reviewPlatform"> |
| | | 送出 |
| | | </el-button> |
| | | </div> |
| | | </PopUpFrame> |
| | | |
| | | <PopUpFrame :isOpen.sync="isEditPopup"> |
| | | <div class="text--middle text--center mb-10">已於 |
| | | <span class="bold">{{appointmentTime | formatDate}}</span> |
| | | 進行預約,</div> |
| | | <div class="text--middle text--center mb-30">是否繼續編輯?</div> |
| | | <div class="text--center mdTxt"> |
| | | <el-button @click="$router.go(-1)">返回</el-button> |
| | | <el-button @click="isEditPopup = false" type="primary">編輯</el-button> |
| | | </div> |
| | | </PopUpFrame> |
| | | </div> |
| | | </template> |
| | | |
| | | <script lang="ts"> |
| | | import { Vue, Component } from 'vue-property-decorator'; |
| | | import { addFavoriteConsultant, appointmentDemand, AppointmentParams, AppointmentRequests ,RegisterInfo } from '~/assets/ts/api/consultant'; |
| | | import { getRequestsFromStorage, setRequestsToStorage } from '~/assets/ts/storageRequests'; |
| | | import { Gender } from '~/assets/ts/models/enum/Gender'; |
| | | import { ContactType } from '~/assets/ts/models/enum/ContactType'; |
| | | import _ from 'lodash'; |
| | | import { Vue, Component, State, Action, Watch, namespace } from 'nuxt-property-decorator'; |
| | | import { getRequestsFromStorage, removeRequestQuestionFromStorage, setRequestsToStorage } from '~/shared/storageRequests'; |
| | | import _ from 'lodash'; |
| | | |
| | | import accountSettingService from '~/shared/services/account-setting.service'; |
| | | import appointmentService from '~/shared/services/appointment.service'; |
| | | import authService from '~/shared/services/auth.service'; |
| | | import queryConsultantService from '~/shared/services/query-consultant.service'; |
| | | import reviewsService from '~/shared/services/reviews.service'; |
| | | import { Consultant } from '~/shared/models/consultant.model'; |
| | | import { ContactType } from '~/shared/models/enum/ContactType'; |
| | | import { Gender } from '~/shared/models/enum/Gender'; |
| | | import { RegisterInfo } from '~/shared/models/registerInfo'; |
| | | import { AppointmentParams, AppointmentRequests } from '~/shared/models/appointment.model'; |
| | | import { UserSetting } from '~/shared/models/account.model'; |
| | | import { SatisfactionType } from '~/shared/models/enum/satisfaction-type'; |
| | | import { UserReviewParams } from '~/shared/models/reviews.model'; |
| | | |
| | | const roleStorage = namespace('localStorage'); |
| | | @Component |
| | | export default class Questionnaire extends Vue { |
| | | @State('myConsultantList') |
| | | myConsultantList!: Consultant[]; |
| | | |
| | | @Action |
| | | storeConsultantList!: () => Promise<number>; |
| | | |
| | | @roleStorage.Getter |
| | | isUserLogin!:boolean; |
| | | |
| | | @roleStorage.State |
| | | recommendConsultantItem!:string; |
| | | |
| | | @roleStorage.Mutation |
| | | storageUserInfo!: (params: RegisterInfo) => void; |
| | | |
| | | score = 0; |
| | | |
| | | genderOptions=[ |
| | | { |
| | | title:'男性', |
| | |
| | | label:Gender.FEMALE, |
| | | } |
| | | ]; |
| | | |
| | | consultationMethodOptions = [ |
| | | { |
| | | title: '線上', |
| | | label: 'online' |
| | | }, |
| | | { |
| | | title: '線下', |
| | | label: 'offline' |
| | | } |
| | | ]; |
| | | |
| | | requirementOptions=[ |
| | | { |
| | | title:'健康與保障', |
| | |
| | | label:'保單健檢/規劃', |
| | | }, |
| | | { |
| | | title:'分紅保單相關', |
| | | label:'分紅保單相關', |
| | | title:'分紅保單', |
| | | label:'分紅保單', |
| | | }, |
| | | ]; |
| | | |
| | | ageRangeOptions=[ |
| | | { |
| | | title:'20歲以下', |
| | |
| | | label:'41-50' |
| | | }, |
| | | { |
| | | title:'46-55 歲', |
| | | label:'46-55', |
| | | }, |
| | | { |
| | | title:'51-60 歲', |
| | | label:'51-60', |
| | | }, |
| | |
| | | label:'over_71', |
| | | } |
| | | ]; |
| | | |
| | | quesAboutList = [ |
| | | { |
| | | title:'健康與保障', |
| | | content:'突發的意外或疾病,往往造成個人或家庭沉重的經濟負擔,周全的保險才能擁有一個無憂的未來。' |
| | | }, |
| | | { |
| | | title:'子女教育', |
| | | content:'利用分紅保單,規劃教育基金 提早為子女作準備,讓生活更有保障!' |
| | | }, |
| | | { |
| | | title:'資產規劃', |
| | | content:'當財務責任加重時,規劃充足的保障、提供經濟上的庇護,是人生最堅強的後盾。' |
| | | }, |
| | | { |
| | | title:'樂活退休', |
| | | content:'兼具保險與投資雙重功能,可靈活搭配各種附約,順應人生不同階段的靈活需要。' |
| | | }, |
| | | { |
| | | title:'保單健檢/規劃', |
| | | content:'全面檢視自己的保障結構是否符合現在或未來的風險移轉需求,透過「斷、捨、離」把錢花在刀口上。' |
| | | }, |
| | | { |
| | | title:'防疫保單', |
| | | content:'匹配度是透過嚴選配對或快速篩選後,將每一位保險顧問資料進行比對後排序推薦給您的媒合數值,您可以作為選擇適合顧問的參考值。' |
| | | } |
| | | { |
| | | title:'健康與保障', |
| | | content:'唯有把身體照顧好,才是保障幸福之本,不做盲目燃燒的蠟燭,只做綻開的陽光,陪孩子多走一哩路,人生的美正要開展。' |
| | | }, |
| | | { |
| | | title:'子女教育', |
| | | content:'孩子,我們是雙方的導師也是學生,面對未來要並肩作戰,學會勇敢無畏、克服挫折、善於理財,這條路上我們一起學。' |
| | | }, |
| | | { |
| | | title:'資產規劃', |
| | | content:'真正的財富來自嚴謹規劃資產傳承,為人生蓋一堵抵禦財務風險的牆,確保資產穩健成長,替全家族的未來做好萬全準備。' |
| | | }, |
| | | { |
| | | title:'樂活退休', |
| | | content:'拼一輩子,退休後的日子要輕鬆快活,就得提早透過保險商品規劃退休財務,替自己創造穩定收入,為精彩的熟年人生揭開序幕。' |
| | | }, |
| | | { |
| | | title:'保單健檢/規劃', |
| | | content:'全面檢視自己的保障結構是否符合現在或未來的風險移轉需求。' |
| | | }, |
| | | { |
| | | title:'分紅保單', |
| | | content:'分紅保單是兼具「分攤風險」與「紅利共享」特色的保單,具有一定穩定度,讓您可以同時享有壽險保障及紅利!' |
| | | } |
| | | ]; |
| | | myRequest= { |
| | | phone:this.userInfo?.phone ? this.userInfo.phone :'', |
| | | email:this.userInfo?.email ? this.userInfo.email :'', |
| | | contactType:_.includes(this.userInfo.contactType,ContactType.SMS) ? ContactType.PHONE : ContactType.EMAIL , |
| | | gender: '', |
| | | age: '', |
| | | job: '', |
| | | requirement: [], |
| | | |
| | | myRequest: AppointmentRequests = { |
| | | name : '', |
| | | phone : '', |
| | | email : '', |
| | | contactType : _.isEqual(this.userInfo?.contactType,ContactType.SMS) ? ContactType.PHONE: ContactType.EMAIL, |
| | | gender : '', |
| | | age : '', |
| | | job : '', |
| | | requirement : [], |
| | | hopeContactTime: [{ |
| | | selectWeekOptions:[], |
| | | selectTimesOptions:[], |
| | | selectWeekOptions : [], |
| | | selectTimesOptions: [], |
| | | }], |
| | | agentNo:this.$route.params.agentNo, |
| | | agentNo: '', |
| | | consultationMethod: '', |
| | | }; |
| | | |
| | | showDrawer= false; |
| | | sendReserve = false; |
| | | isEditPopup = false; |
| | | isEditBtn = false; |
| | | |
| | | mounted() { |
| | | appointmentId = 0; |
| | | appointmentTime = ''; |
| | | |
| | | //////////////////////////////////////////////////////////////////////////// |
| | | |
| | | beforeRouteEnter(to: any, from: any, next: any) { |
| | | next(vm => { |
| | | const isUserLogin = authService.isUserLogin(); |
| | | if (from.name === 'login' && !isUserLogin) { |
| | | vm.$router.go(-1); |
| | | return; |
| | | } |
| | | |
| | | if (!isUserLogin) { |
| | | vm.$router.push('/login'); |
| | | } |
| | | }) |
| | | } |
| | | |
| | | mounted(): void { |
| | | if (authService.isUserLogin()) { |
| | | this.storeConsultantList(); |
| | | }; |
| | | this.setMyRequest(); |
| | | } |
| | | |
| | | private setMyRequest(): void { |
| | | const storageMyRequest = getRequestsFromStorage(); |
| | | const storageMyRequirement = this.recommendConsultantItem ? JSON.parse(this.recommendConsultantItem).requirements:[]; |
| | | |
| | | if (storageMyRequest) { |
| | | this.myRequest = storageMyRequest; |
| | | this.myRequest = { |
| | | ...storageMyRequest, |
| | | hopeContactTime: storageMyRequest.hopeContactTime?.length |
| | | ? storageMyRequest.hopeContactTime |
| | | : [{ |
| | | selectWeekOptions: [], |
| | | selectTimesOptions: [], |
| | | }], |
| | | }; |
| | | } |
| | | |
| | | if (storageMyRequirement) { |
| | | this.myRequest = { |
| | | ...this.myRequest, |
| | | requirement: storageMyRequirement |
| | | } |
| | | removeRequestQuestionFromStorage(); |
| | | } |
| | | |
| | | if (authService.isUserLogin()) { |
| | | accountSettingService.getUserAccountSetting().then((contactTypeDetail) => { |
| | | this.myRequest = { |
| | | ...this.myRequest, |
| | | ...contactTypeDetail |
| | | } |
| | | }) |
| | | } |
| | | |
| | | |
| | | } |
| | | |
| | | //////////////////////////////////////////////////////////////////////////// |
| | | |
| | | @Watch('myConsultantList') |
| | | onMyConsultantListChange() { |
| | | if (authService.isUserLogin() && this.myConsultantList.length > 0) { |
| | | const editAppointment = this.getLatestReserved(this.$route.params.agentNo); |
| | | |
| | | if (editAppointment && editAppointment.agentNo) { |
| | | this.myRequest = JSON.parse(JSON.stringify(editAppointment)); |
| | | if (!this.$route.query || this.$route.query.edit !== 'true') { |
| | | this.isEditPopup = true; |
| | | } |
| | | this.isEditBtn = true; |
| | | } |
| | | } |
| | | } |
| | | get phoneValid():boolean{ |
| | | const rule = /^09[0-9]{8}$/; |
| | | return this.myRequest.phone ? rule.test(this.myRequest.phone) : true; |
| | | } |
| | | get userInfo():RegisterInfo{ |
| | | const initUserInfo = JSON.parse(localStorage.getItem('userInfo')); |
| | | return initUserInfo; |
| | | |
| | | private getLatestReserved(agentNo) { |
| | | const agentInfo = this.myConsultantList.filter(item => item.agentNo === agentNo); |
| | | const appointmentInfo = agentInfo.length > 0 && agentInfo[0].appointments |
| | | ? agentInfo[0].appointments! |
| | | .filter((appointment) => appointment.communicateStatus === 'reserved') |
| | | .map((reversedAppointment) => ( |
| | | { ...reversedAppointment, |
| | | sortDate: new Date(reversedAppointment.appointmentDate) |
| | | })) |
| | | .sort((preAppointment, nextAppointment) => +nextAppointment.sortDate - +preAppointment.sortDate)[0] |
| | | : null; |
| | | return this.getReservedData(appointmentInfo); |
| | | } |
| | | |
| | | get isMainContractPhoneByLocalStorage():boolean{ |
| | | return true; |
| | | private getReservedData(appointmentInfo) { |
| | | if (appointmentInfo) { |
| | | const hopeContactTime = appointmentInfo!.hopeContactTime |
| | | ? appointmentInfo!.hopeContactTime.split("'").filter(item => item && item !== ',').map(item => { |
| | | const info = item.split('、'); |
| | | return { |
| | | selectWeekOptions: info[0].split(','), |
| | | selectTimesOptions: info[1].split(',') |
| | | } |
| | | }) |
| | | :[{selectWeekOptions : [],selectTimesOptions: []}]; |
| | | this.getAppointmentId(appointmentInfo); |
| | | |
| | | return { |
| | | ...appointmentInfo, |
| | | hopeContactTime: hopeContactTime, |
| | | requirement: appointmentInfo.requirement |
| | | ? appointmentInfo.requirement.split(',') |
| | | : [] |
| | | } |
| | | } else { |
| | | return null; |
| | | } |
| | | } |
| | | |
| | | get isRequiredByInit():boolean{ |
| | | return _.includes(this.myRequest.contactType,ContactType.PHONE) |
| | | ? !this.isHopeContactTimeDone() |
| | | :false; |
| | | private getAppointmentId(appointmentInfo) { |
| | | this.appointmentId = appointmentInfo.id; |
| | | this.appointmentTime = appointmentInfo.lastModifiedDate |
| | | ? appointmentInfo.lastModifiedDate |
| | | : appointmentInfo.appointmentDate; |
| | | } |
| | | get checkPhoneLength():boolean{ |
| | | return _.isEqual(this.myRequest.phone.length,10); |
| | | } |
| | | private isHopeContactTimeDone():boolean{ |
| | | return this.myRequest.hopeContactTime[0].selectWeekOptions.length >0 && this.myRequest.hopeContactTime[0].selectTimesOptions.length >0; |
| | | } |
| | | |
| | | |
| | | sentDemand() { |
| | | addFavoriteConsultant([this.myRequest.agentNo]).then(res => this.sentAppointmentDemand()); |
| | | //////////////////////////////////////////////////////////////////////////// |
| | | |
| | | async sentDemand() { |
| | | if (!this.isEditBtn) { |
| | | // 使用 async/await 來等待異步操作的回傳結果 |
| | | const addFavoriteAgentList = [{ agentNo: this.$route.params.agentNo, createdTime: new Date().toISOString() }]; |
| | | const response = await queryConsultantService.addFavoriteConsultant(addFavoriteAgentList); |
| | | |
| | | // 確保異步操作的回傳結果不為 null 或 undefined |
| | | if (!response) { |
| | | throw new Error('queryConsultantService.addFavoriteConsultant returned null-like value.'); |
| | | } else { |
| | | if (typeof this.editAppointmentDemand === 'function') { |
| | | // 確保 this.editAppointmentDemand 是一個函數 |
| | | await this.editAppointmentDemand(); |
| | | } else { |
| | | // 處理 this.editAppointmentDemand 未定義的情況 |
| | | throw new Error('this.editAppointmentDemand is not defined or not a function.'); |
| | | } |
| | | } |
| | | } else { |
| | | await this.editAppointmentDemand(); |
| | | } |
| | | |
| | | const editSettingInfo: UserSetting = { |
| | | name: this.myRequest.name, |
| | | phone: this.myRequest.phone, |
| | | email: this.myRequest.email, |
| | | }; |
| | | |
| | | await accountSettingService.updateAccountSetting(editSettingInfo); |
| | | this.storageUserInfo(this.userInfo); |
| | | } |
| | | |
| | | private editAppointmentDemand() { |
| | | const info = { |
| | | ...this.myRequest, |
| | | requirement: _.map(this.myRequest.requirement,o=>o).toString(), |
| | | hopeContactTime: this.myRequest.phone && this.phoneValid ? this.getHopeContactTime() :'', |
| | | id: this.appointmentId, |
| | | otherRequirement: null |
| | | } |
| | | appointmentService.editAppointment(info).then(res => { |
| | | this.sendReserve = true; |
| | | this.myRequest.hopeContactTime = []; |
| | | setRequestsToStorage(this.myRequest); |
| | | }); |
| | | } |
| | | |
| | | private sentAppointmentDemand() { |
| | | |
| | | const data: AppointmentParams = { |
| | | ...this.myRequest, |
| | | requirement: _.map(this.myRequest.requirement,o=>o).toString(), |
| | | hopeContactTime:this.phoneValid&&this.checkPhoneLength ? this.getHopeContactTime() :'', |
| | | hopeContactTime: this.myRequest.phone && this.phoneValid ? this.getHopeContactTime() :'', |
| | | agentNo: this.$route.params.agentNo |
| | | }; |
| | | |
| | | appointmentDemand(data).then(res => { |
| | | queryConsultantService.appointmentDemand(data).then(res => { |
| | | this.sendReserve = true; |
| | | this.myRequest.hopeContactTime = []; |
| | | this.appointmentId = res['id']; |
| | | setRequestsToStorage(this.myRequest); |
| | | }); |
| | | } |
| | | |
| | | getHopeContactTime() { |
| | | return this.myRequest.hopeContactTime.map(i => { |
| | | private getHopeContactTime() { |
| | | const selectedHopeContactTime = this.myRequest.hopeContactTime.filter((i) => i.selectWeekOptions?.length && i.selectTimesOptions?.length); |
| | | return selectedHopeContactTime.map(i => { |
| | | return `'${i.selectWeekOptions}、${i.selectTimesOptions}'`} |
| | | ).toString(); |
| | | } |
| | | |
| | | reviewPlatform(): void { |
| | | const reviewPlatformParams: UserReviewParams = { |
| | | appointmentId: this.appointmentId, |
| | | score: this.score, |
| | | type: SatisfactionType.SYSTEM |
| | | }; |
| | | reviewsService.reviewPlatform(reviewPlatformParams).then((_) => { |
| | | this.closeReservePopUp(); |
| | | }); |
| | | } |
| | | |
| | | closeReservePopUp() { |
| | |
| | | this.$router.push('/') |
| | | } |
| | | |
| | | } |
| | | //////////////////////////////////////////////////////////////////////////// |
| | | |
| | | export interface SelectedQuestion { |
| | | name: string; |
| | | selected: boolean; |
| | | 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 emailValid() { |
| | | const rule = /^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$/; |
| | | return this.myRequest.email ? rule.test(this.myRequest.email) : 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.emailValid |
| | | : !this.phoneValid; |
| | | } |
| | | |
| | | private isHopeContactTimeDone():boolean{ |
| | | return this.myRequest.hopeContactTime[0]?.selectWeekOptions.length >0 && this.myRequest.hopeContactTime[0]?.selectTimesOptions.length >0; |
| | | } |
| | | |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | | .sendReserve-txt{ |
| | | display: flex; |
| | | justify-content: center; |
| | | margin-top: 10px; |
| | | margin-bottom: 26px; |
| | | display: flex; |
| | | justify-content: center; |
| | | margin-top: 10px; |
| | | } |
| | | |
| | | //drawer最底下文字樣式 |
| | | .qa-dialog-footer{ |
| | | display: flex; |
| | | justify-content: center; |
| | | margin-bottom: 81px; |
| | | color: #ED1B2E; |
| | | cursor: pointer; |
| | | }//drawer最底下文字樣式 |
| | | |
| | | display: flex; |
| | | justify-content: center; |
| | | margin-bottom: 81px; |
| | | color: #ED1B2E; |
| | | cursor: pointer; |
| | | } |
| | | .error { |
| | | color:$PRIMARY_RED |
| | | } |
| | | //送出按鈕樣式與排版 |
| | | .ques-footer{ |
| | | justify-content: center; |
| | | margin: 30px 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | .el-button { |
| | | justify-content: center; |
| | | margin: 30px 0; |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | .el-button { |
| | | width: 120px; |
| | | height:50px; |
| | | background-color: #ED1B2E; |
| | |
| | | border-style: solid; |
| | | pointer-events: none; |
| | | } |
| | | } |
| | | }//送出按鈕樣式與排版 |
| | | } |
| | | } |
| | | |
| | | //詳細問題drawer中間內容空間大小設置 |
| | | .qa-dialog{ |
| | | overflow-y:auto; |
| | | height: 500px; |
| | | margin-top: 20px; |
| | | }//詳細問題drawer中間內容空間大小設置 |
| | | overflow-y:auto; |
| | | height: 60vh; |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | //詳細問題drawer主要標題 |
| | | .qaTextTitle{ |
| | | margin-top:30px; |
| | | display: flex; |
| | | justify-content: center; |
| | | }//詳細問題drawer主要標題 |
| | | |
| | | .el-button+.el-button{ |
| | | margin-left: 0; |
| | | margin-top:30px; |
| | | display: flex; |
| | | justify-content: center; |
| | | } |
| | | |
| | | .datepicker{ |
| | | display: flex; |
| | | flex-direction: column; |
| | | display: flex; |
| | | flex-direction: column; |
| | | } |
| | | |
| | | .required { |
| | | position: relative; |
| | | &::before { |
| | | content: '*'; |
| | | position: absolute; |
| | | color: #FF0000; |
| | | transform: translate(-12px, 0); |
| | | } |
| | | position: relative; |
| | | &::before { |
| | | content: '*'; |
| | | position: absolute; |
| | | color: #FF0000; |
| | | transform: translate(-12px, 0); |
| | | } |
| | | } |
| | | .break{ |
| | | word-break: break-all; |
| | | line-height: 1.2; |
| | | } |
| | | .ques-page--reset.pam-page-container { |
| | | margin: 0px auto; |
| | | } |
| | | |
| | | .ques-page--reset.pam-page-container{ |
| | | margin: 0px auto; |
| | | .ques-header { |
| | | position: relative; |
| | | } |
| | | .ques-header{ |
| | | position: relative; |
| | | } |
| | | .ques-header__mob-banner{ |
| | | |
| | | .ques-header__mob-banner { |
| | | width: 100%; |
| | | min-height: 80px; |
| | | background-color: #F8F9FA; |
| | |
| | | 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; |
| | | |
| | | .ques-header__info { |
| | | position: relative; |
| | | padding:30px 20px; |
| | | margin: 0px 20px; |
| | | background-color: #B3E7E3; |
| | | 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-header__input-block { |
| | | display: flex; |
| | | align-items: center; |
| | | @extend .text--middle,.mt-10 ; |
| | | .ques-header__input{ |
| | | &.is-invalid{ |
| | | border: 1px 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; |
| | | } |
| | | } |
| | | .ml-4{ |
| | | margin-left: 4px; |
| | | } |
| | | .ques-container { |
| | | position: relative; |
| | | margin: 0px 20px; |
| | | } |
| | | |
| | | .pam-app-review{ |
| | | display: flex; |
| | | flex-direction: column; |
| | | justify-content: center; |
| | | align-items: center; |
| | | } |
| | | |
| | | .ques-container{ |
| | | position: relative; |
| | | margin: 0px 20px; |
| | | .pam-satisfaction-rate{ |
| | | margin-bottom: 45px; |
| | | } |
| | | |
| | | |
| | | @include desktop{ |
| | | @include desktop{ |
| | | .ques-header{ |
| | | display: flex; |
| | | justify-content: flex-end; |
| | |
| | | } |
| | | } |
| | | |
| | | |
| | | </style> |
| | | |