Merge branch 'master' of ssh://192.168.0.10:29418/pcalife/PAM
| | |
| | | import { UserSetting } from '../models/account.model'; |
| | | import { Consultant } from '~/assets/ts/models/consultant.model'; |
| | | import { http } from '../services/httpClient'; |
| | | import { FastQueryParams } from '../models/quickFilter.model'; |
| | | |
| | | // 顧客ç»å
¥(TODO: OTPèªèéç¼å æ«æä½¿ç¨) |
| | | export function login(user: any) { |
| | |
| | | |
| | | // å¿«éç¯©é¸ |
| | | export function fastQuery(data: FastQueryParams) { |
| | | return http.post('/consultant/fastQuery', data) |
| | | return http.post<Consultant[]>('/consultant/fastQuery', data).then(res => res.data); |
| | | } |
| | | |
| | | // å´é¸é
å° |
| | |
| | | Authorization: 'Bearer ' + localStorage.getItem('id_token') |
| | | } |
| | | return http.put('/appointment', editAppointmentParams, {headers}); |
| | | } |
| | | |
| | | export interface FastQueryParams { |
| | | gender : string, |
| | | communicationStyles: string[], |
| | | avgScore : number, |
| | | status : string |
| | | } |
| | | |
| | | export interface AppointmentRequests { |
¤ñ¹ï·sÀÉ®× |
| | |
| | | import { QuestionOption } from "../models/quickFilter.model"; |
| | | |
| | | export const questionList: QuestionOption[] = [ |
| | | { |
| | | name: 'gender', |
| | | title: 'é¡§åæ§å¥', |
| | | detail: [ |
| | | { name: 'ç·æ§', value: 'male', className: 'btn_man'}, |
| | | { name: '女æ§', value: 'female', className: 'btn_woman'} |
| | | ], |
| | | type: 'radio' |
| | | }, |
| | | // { TODO:é±è滿æåº¦ |
| | | // 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' |
| | | // } |
| | | ]; |
¤ñ¹ï·sÀÉ®× |
| | |
| | | export interface QuestionOption { |
| | | title: string; |
| | | detail: Detail[]; |
| | | type: string; |
| | | name: string; |
| | | } |
| | | |
| | | interface Detail { |
| | | value: string; |
| | | name?: string; |
| | | className: string; |
| | | } |
| | | |
| | | export interface FastQueryParams { |
| | | gender : string, |
| | | communicationStyles: string[], |
| | | avgScore : number, |
| | | status : string |
| | | } |
| | | |
| | | export interface Selected { |
| | | option: string; |
| | | value: any; |
| | | } |
| | |
| | | :key="index" |
| | | >é£çµ¡ææ®µ{{index + 1 | formatNumber}}ï¼{{ item | formatHopeContactTime }}</p> |
| | | <div v-if="appointmentDetail.satisfactionScore"> |
| | | <div class="mdTxt mt-10 mb-10">滿æåº¦</div> |
| | | <el-rate |
| | | :value="appointmentDetail.satisfactionScore" |
| | | class="pam-myDemand-dialog__rate" |
| | | disabled> |
| | | </el-rate> |
| | | <div class="mdTxt mt-10 mb-10">滿æåº¦</div> |
| | | <el-rate |
| | | :value="appointmentDetail.satisfactionScore" |
| | | class="pam-myDemand-dialog__rate" |
| | | disabled> |
| | | </el-rate> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <div v-if="agentInfo.contactStatus === 'contacted' |
| | | && !appointmentDetail.satisfactionScore" class="dialogInfo-btn"> |
| | |
| | | <PopUpFrame :isOpen.sync="isCancelPopup"> |
| | | <div class="text--center mdTxt">æ¯å¦åæ¶æ¤çé ç´ï¼</div> |
| | | <div class="text--center mt-30"> |
| | | <el-button @click="isCancelPopup = false">åæ¶</el-button> |
| | | <el-button @click="cancel" type="primary">確å®</el-button> |
| | | <el-button @click="isCancelPopup = false">å¦</el-button> |
| | | <el-button @click="cancel" type="primary">æ¯</el-button> |
| | | </div> |
| | | </PopUpFrame> |
| | | |
| | |
| | | endYPosition = 0; |
| | | hideReviews = hideReviews ; |
| | | |
| | | openPopUp(txt: string) { |
| | | this.popUpTxt = txt; |
| | | this.isVisiblePopUp = true; |
| | | } |
| | | |
| | | showAgentDetail(agentNo: string): void { |
| | | this.$router.push(`/agentInfo/${agentNo}`); |
| | | } |
| | | |
| | | moveStart(event: TouchEvent) { |
| | | this.startPosition = event.changedTouches[0].clientX; |
| | | this.startYPosition = event.changedTouches[0].clientY; |
| | |
| | | (this.$refs.carouselRef as ElCarousel).prev(); |
| | | } |
| | | |
| | | openPopUp(txt: string) { |
| | | this.popUpTxt = txt; |
| | | this.isVisiblePopUp = true; |
| | | } |
| | | |
| | | showAgentDetail(agentNo: string): void { |
| | | this.$router.push(`/agentInfo/${agentNo}`); |
| | | } |
| | | } |
| | | </script> |
| | | |
| | |
| | | |
| | | <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 { hideReviews } from '~/assets/ts/const/hide-reviews'; |
| | | import { FastQueryParams, QuestionOption, Selected } from '~/assets/ts/models/quickFilter.model'; |
| | | @Component |
| | | export default class QuickFilterDrawer extends Vue { |
| | | |
| | | |
| | | pickedItem: FastQueryParams = { |
| | | communicationStyles: [], |
| | | status: '', |
| | |
| | | avgScore: 0 |
| | | } |
| | | hideReviews = hideReviews ; |
| | | |
| | | |
| | | @Prop() questionOption!: QuestionOption; |
| | | @Prop() isOpenQuestionPopUp!: boolean; |
| | | @Prop() confirmItem!: Selected[]; |
| | |
| | | value: this.pickedItem[name] |
| | | } |
| | | } |
| | | |
| | | } |
| | | |
| | | export interface Selected { |
| | | option: string; |
| | | value: any; |
| | | } |
| | | </script> |
| | | |
| | |
| | | <template> |
| | | <div> |
| | | <div class="mdTxt pt-10 pb-10">è·æ¥</div> |
| | | <div class="mdTxt pt-10 pb-10">æ¨çè·æ¥</div> |
| | | <div class="ques-career__select" @click="openPopUp"> |
| | | <div class="ques-career__select-input"> |
| | | <span v-if="!syncCareerSelect">è«é¸æ</span> |
| | |
| | | </div> |
| | | <PopUpFrame :isOpen.sync="showJobDrawer"> |
| | | <div class="pam-career"> |
| | | <div class="subTitle">è·æ¥</div> |
| | | <div class="subTitle">æ¨çè·æ¥</div> |
| | | <el-radio-group class="pam-single__select--col" v-model="career" @change="handleChange"> |
| | | <el-radio-button v-for="(career,index) in options" |
| | | :key="index" |
| | |
| | | selectAll:'æ¯å¤©', |
| | | options:[ |
| | | { |
| | | title:'禮æä¸', |
| | | label:'禮æä¸' |
| | | title:'ææä¸', |
| | | label:'ææä¸' |
| | | }, |
| | | { |
| | | title:'禮æäº', |
| | | label:'禮æäº' |
| | | title:'ææäº', |
| | | label:'ææäº' |
| | | }, |
| | | { |
| | | title:'禮æä¸', |
| | | label:'禮æä¸' |
| | | title:'ææä¸', |
| | | label:'ææä¸' |
| | | }, |
| | | { |
| | | title:'禮æå', |
| | | label:'禮æå' |
| | | title:'ææå', |
| | | label:'ææå' |
| | | }, |
| | | { |
| | | title:'禮æäº', |
| | | label:'禮æäº' |
| | | title:'ææäº', |
| | | label:'ææäº' |
| | | }, { |
| | | title:'禮æå
', |
| | | label:'禮æå
' |
| | | title:'ææå
', |
| | | label:'ææå
' |
| | | }, |
| | | { |
| | | title:'ç¦®ææ¥', |
| | | label:'ç¦®ææ¥' |
| | | title:'æææ¥', |
| | | label:'æææ¥' |
| | | }, |
| | | ], |
| | | }; |
| | |
| | | @scroll="detectContractReadStatus"> |
| | | <h3>èéåäººè³æåç¥äºé
</h3> |
| | | <p class="mt-10"> |
| | | éµå®åäººè³æä¿è·æ³è¦å®ï¼å¨æ¨æä¾åäººè³æäºæ¬èåï¼ä¾æ³å |
| | | ç¥ä¸åäºé
ï¼ |
| | | éµå®åäººè³æä¿è·æ³è¦å®ï¼å¨æ¨æä¾åäººè³æäºæ¬èåï¼ä¾æ³åç¥ä¸åäºé
ï¼ |
| | | <p> |
| | | |
| | | <p class="mt-10"> |
| | |
| | | </p> |
| | | |
| | | <p class="mt-10"> |
| | | åãé¤èéä¹ç®çæ¶åå鿥忿´»åå¤ï¼æ¬èå
æ¼ä¸è¯æ°åé åå
§å©ç¨æ¨çåäººè³ |
| | | æã |
| | | åãé¤èéä¹ç®çæ¶åå鿥忿´»åå¤ï¼æ¬èå
æ¼ä¸è¯æ°åé åå
§å©ç¨æ¨çåäººè³æã |
| | | </p> |
| | | |
| | | <p class="mt-10"> |
| | | äºãæ¬èå°æ¼åèéä¹ç¹å®ç®çãæ¬æ¬¡ä»¥å¤ä¹ç¢æ¥ä¹æ¨å»£ã宣å°åè¼å°ã以åå
¶ä»å
¬ |
| | | åæ©éè«æ±è¡æ¿åå©ä¹ç®çç¯åå
§ï¼åçå©ç¨æ¨çåäººè³æã |
| | | äºãæ¬èå°æ¼åèéä¹ç¹å®ç®çãæ¬æ¬¡ä»¥å¤ä¹ç¢æ¥ä¹æ¨å»£ã宣å°åè¼å°ã以åå
¶ä»å
¬åæ©éè«æ±è¡æ¿åå©ä¹ç®çç¯åå
§ï¼åçå©ç¨æ¨çåäººè³æã |
| | | </p> |
| | | |
| | | <p class="mt-10"> |
| | |
| | | phoneNumber = ''; |
| | | otpCode = ''; |
| | | onPhoneVerifyStep: 'APPLY_OTP' | 'INPUT_OTP' | 'SUBMIT_OTP' = 'APPLY_OTP'; |
| | | otpCounterSec = 900; |
| | | otpCounterSec = 300; |
| | | otpResendCounter = 30; |
| | | otpInterval: any; |
| | | phoneOtpInfo!: OtpInfo; |
| | | |
| | | email = ''; |
| | | onEmailVerifyResendStatus: 'APPLY_OTP' | 'CAN_RESEND' = 'APPLY_OTP'; |
| | | emailCounterSec = 900; |
| | | emailCounterSec = 300; |
| | | emailResendCounter = 30; |
| | | emailOtpCode = ''; |
| | | emailResendInterval: any; |
| | |
| | | if (type === 'MOBILE') { |
| | | clearInterval(this.otpInterval); |
| | | this.otpResendCounter = 30; |
| | | this.otpCounterSec = 900; |
| | | this.otpCounterSec = 300; |
| | | } else { |
| | | clearInterval(this.emailResendInterval); |
| | | this.emailResendCounter = 30; |
| | | this.emailCounterSec = 900; |
| | | this.emailCounterSec = 300; |
| | | } |
| | | } |
| | | |
| | |
| | | $ALIGN_PADDING: 60px; |
| | | $TOP_CONTENT_HEIGHT: 186px; |
| | | $BOTTOM_CONTENT_HEIGHT: 131px; |
| | | // text-align:start; |
| | | max-height: calc(100vh - $DEVICE_EXTRA_HEIGHT - $ALIGN_PADDING - $TOP_CONTENT_HEIGHT - $BOTTOM_CONTENT_HEIGHT); |
| | | overflow-y: scroll; |
| | | border-radius: 6px; |
| | |
| | | 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> |
| | | <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> |
| | |
| | | :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" /> |
| | |
| | | |
| | | <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="text--middle sendReserve-txt">åéèæ¨è¯çµ¡ï¼</div> |
| | | <div class="text--center mdTxt"> |
| | | <el-button type="primary" |
| | | @click="closeReservePopUp"> |
| | |
| | | }, |
| | | { |
| | | title:'åç´
ä¿å®', |
| | | content:'åç´
ä¿å® åç´
ä¿å®æ¯å
¼å
·ã忤颍éªãèãç´
å©å
±äº«ãç¹è²çä¿å®ï¼å
·æä¸å®ç©©å®åº¦ï¼è®ä½ å¯ä»¥åæäº«æå£½éªä¿éåç´
å©ï¼' |
| | | content:'åç´
ä¿å®æ¯å
¼å
·ã忤颍éªãèãç´
å©å
±äº«ãç¹è²çä¿å®ï¼å
·æä¸å®ç©©å®åº¦ï¼è®ä½ å¯ä»¥åæäº«æå£½éªä¿éåç´
å©ï¼' |
| | | } |
| | | ]; |
| | | |
| | |
| | | |
| | | <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'; |
| | | import { questionList } from '~/assets/ts/const/quickFilter-questionList'; |
| | | import { FastQueryParams, QuestionOption, Selected } from '~/assets/ts/models/quickFilter.model'; |
| | | |
| | | const localStorage = namespace('localStorage'); |
| | | @Component |
| | |
| | | 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' |
| | | }, |
| | | // { TODO:é±è滿æåº¦ |
| | | // 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' |
| | | // } |
| | | ]; |
| | | questionList = questionList; |
| | | |
| | | //////////////// lifecycle //////////////// |
| | | mounted() { |
| | | if (this.quickFilterSelectedData && this.quickFilterSelectedData.length > 0) { |
| | | this.confirmItem = this.quickFilterSelectedData; |
| | |
| | | } |
| | | } |
| | | |
| | | 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; |
| | |
| | | this.isOpenQuestionPopUp = false; |
| | | } |
| | | |
| | | setConfirmData(event: Selected) { |
| | | isActive(name: string) { |
| | | return name === 'gender' && !!this.gender() |
| | | || name === 'avgScore' && !!this.avgScore() |
| | | || name === 'communicationStyles' && !!this.communicationStyles().length |
| | | } |
| | | |
| | | |
| | | //////////////// private //////////////// |
| | | private gender(): string { |
| | | const filter = this.confirmItem.filter(item => item.option === 'gender').map(i => i.value); |
| | | return filter.length === 0 ? '' : filter[0]; |
| | | } |
| | | |
| | | private avgScore(): number { |
| | | const filter = this.confirmItem.filter(item => item.option === 'avgScore').map(i => i.value); |
| | | return filter.length === 0 ? '' : filter[0]; |
| | | } |
| | | |
| | | private communicationStyles(): string[] { |
| | | return this.confirmItem.filter(item => item.option === 'communicationStyles').map(i => i.value); |
| | | } |
| | | |
| | | private setConfirmData(event: Selected) { |
| | | if (event.option === 'communicationStyles') { |
| | | this.filterCommunicationStyles(event); |
| | | } else { |
| | |
| | | } |
| | | } |
| | | |
| | | filterCommunicationStyles(event: Selected) { |
| | | private filterCommunicationStyles(event: Selected) { |
| | | const confirmValue = this.confirmItem |
| | | .filter(item => item.option === 'communicationStyles') |
| | | .map(i => i.value); |
| | |
| | | } |
| | | } |
| | | |
| | | getRecommendList() { |
| | | private getRecommendList() { |
| | | const data: FastQueryParams = { |
| | | gender: this.gender(), |
| | | communicationStyles: this.communicationStyles(), |
| | |
| | | status: '' |
| | | } |
| | | |
| | | fastQuery(data).then((res) => { |
| | | this.consultantList = res.data; |
| | | fastQuery(data).then((consultantList) => { |
| | | this.consultantList = consultantList; |
| | | 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> |
| | |
| | | .quickBtnBlock { |
| | | display: flex; |
| | | width: 100%; |
| | | height: 132px; |
| | | // height: 132px; |
| | | flex-wrap: wrap; |
| | | justify-content: space-between; |
| | | |
| | |
| | | }, |
| | | { |
| | | title: 'åç´
ä¿å®', |
| | | content: 'åç´
ä¿å® åç´
ä¿å®æ¯å
¼å
·ã忤颍éªãèãç´
å©å
±äº«ãç¹è²çä¿å®ï¼å
·æä¸å®ç©©å®åº¦ï¼è®ä½ å¯ä»¥åæäº«æå£½éªä¿éåç´
å©ï¼' |
| | | content: 'åç´
ä¿å®æ¯å
¼å
·ã忤颍éªãèãç´
å©å
±äº«ãç¹è²çä¿å®ï¼å
·æä¸å®ç©©å®åº¦ï¼è®ä½ å¯ä»¥åæäº«æå£½éªä¿éåç´
å©ï¼' |
| | | } |
| | | ]; |
| | | showDialog = false; |
| | |
| | | import { Selected } from '~/components/QuickFilter/QuickFilterSelector.vue'; |
| | | import { Module, Mutation, VuexModule ,Action } from 'vuex-module-decorators'; |
| | | import { Role } from '~/assets/ts/models/enum/Role'; |
| | | import { Selected } from '~/assets/ts/models/quickFilter.model'; |
| | | @Module |
| | | export default class LocalStorage extends VuexModule { |
| | | id_token = localStorage.getItem('id_token'); |