refactor: pages component - separate vue files
刪除10個檔案
修改14個檔案
新增43個檔案
修改4個檔案名稱
| | |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | .mt-25 { |
| | | margin-top: 25px; |
| | | } |
| | | |
| | | .mb-30 { |
| | | margin-bottom: 30px; |
| | | } |
| | |
| | | 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; |
| | | } |
| | |
| | | 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) { |
| | |
| | | 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 { |
¤ñ¹ï·sÀÉ®× |
| | |
| | | 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; |
| | | } |
File was renamed from PAMapp/assets/ts/models/enum/Gender.ts |
| | |
| | | export enum Gender{ |
| | | MALE="male", |
| | | FEMALE="female", |
| | | } |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | export interface FastQueryParams { |
| | | gender : string, |
| | | communicationStyles: string[], |
| | | avgScore : number, |
| | | status : string |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | export interface QuestionOption { |
| | | title: string; |
| | | detail: Detail[]; |
| | | type: string; |
| | | name: string; |
| | | } |
| | | |
| | | interface Detail { |
| | | value: string; |
| | | name?: string; |
| | | className: string; |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | export interface ReviewsItem { |
| | | avatar : any; |
| | | name : string; |
| | | avgScore: number; |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | export interface Selected { |
| | | option: string; |
| | | value: any; |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | export interface StrictQueryDto { |
| | | gender : string, |
| | | area : string, |
| | | status : string, |
| | | requirements : string[], |
| | | otherRequirement: string, |
| | | seniority : string, |
| | | avgScore : number, |
| | | popularTags : string[], |
| | | otherPopularTags: string |
| | | } |
| | |
| | | <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'; |
| | | |
| | |
| | | <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'); |
| | |
| | | title: 'æ¥ç帳èè³è¨', |
| | | }, |
| | | { |
| | | authorityOfRoleList:[Role.ADMIN], |
| | | authorityOfRoleList:[Role.ADMIN, Role.USER], |
| | | routeUrl: '/record', |
| | | title: 'æ¥çç´é', |
| | | }, |
| | | { |
| | | authorityOfRoleList: [Role.USER], |
| | | routeUrl: '/userReviewsRecord', |
| | | title: 'æ¥çç´é', |
| | | }, |
| | | { |
| | |
| | | |
| | | <script lang="ts"> |
| | | import { Vue, Component, Prop, Watch, Emit } from 'nuxt-property-decorator'; |
| | | import { FastQueryParams } from '~/assets/ts/api/consultant'; |
| | | import { FastQueryParams } from '~/assets/ts/models/fast-query-params.model'; |
| | | import { Selected } from '~/assets/ts/models/selected.model'; |
| | | import { QuestionOption } from '~/pages/quickFilter/index.vue'; |
| | | |
| | | @Component |
| | |
| | | |
| | | } |
| | | |
| | | export interface Selected { |
| | | option: string; |
| | | value: any; |
| | | } |
| | | </script> |
| | | |
| | | <style lang="scss" scoped> |
| | |
| | | flex-wrap: wrap; |
| | | } |
| | | |
| | | </style> |
| | | </style> |
¤ñ¹ï·sÀÉ®× |
| | |
| | | .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 |
| | | } |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | |
| | | 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!; |
| | | }) |
| | | } |
| | | |
| | | } |
| | |
| | | <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" |
| | | > |
| | |
| | | <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 |
| | | }" |
| | |
| | | </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="{ |
| | |
| | | </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> |
| | |
| | | </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> |
| | | @import "./account-setting.component.scss"; |
| | | </style> |
| | |
| | | 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> |
| | |
| | | </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 = 'è«®è©¢åº¦è¡¨ç¾æ¯å°æ¯ä¸ä½ä¿éªé¡§åè¿ä¸åæåè¦è«®è©¢æ¸éé²è¡æ¯å°å¾æåºæ¨è¦çµ¦æ¨çåªåæ¸å¼ã'; |
| | | 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> |
¤ñ¹ï·sÀÉ®× |
| | |
| | | .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; |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | 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 = 'è«®è©¢åº¦è¡¨ç¾æ¯å°æ¯ä¸ä½ä¿éªé¡§åè¿ä¸åæåè¦è«®è©¢æ¸éé²è¡æ¯å°å¾æåºæ¨è¦çµ¦æ¨çåªåæ¸å¼ã'; |
| | | break; |
| | | } |
| | | } |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | .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; |
| | | } |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | 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 = ''; |
| | | } |
| | | }; |
| | |
| | | </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> |
| | |
| | | </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> |
¤ñ¹ï·sÀÉ®× |
| | |
| | | |
| | | .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; |
| | | } |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | |
| | | 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 |
| | | } |
| | | } |
| | | } |
File was renamed from PAMapp/pages/myAppointmentList/appointmentList.vue |
| | |
| | | <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'; |
| | | |
| | |
| | | } |
| | | |
| | | } |
| | | </script> |
¤ñ¹ï·sÀÉ®× |
| | |
| | | <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> |
¤ñ¹ï·sÀÉ®× |
| | |
| | | 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) |
| | | }) |
| | | } |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | <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> |
¤ñ¹ï·sÀÉ®× |
| | |
| | | <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')" |
| | | >客æ¶é ç´ |
| | | <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> |
¤ñ¹ï·sÀÉ®× |
| | |
| | | .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; |
| | | } |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | |
| | | 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'; |
| | | }; |
| | | |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | |
| | | 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; |
| | | } |
| | | |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | <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> |
¤ñ¹ï·sÀÉ®× |
| | |
| | | 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; |
| | | } |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | <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> |
¤ñ¹ï·sÀÉ®× |
| | |
| | | <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 src="./my-consultant-list.component.ts"></script> |
| | | |
| | | <style lang="scss" scoped> |
| | | @import "./my-consultant-list.component.scss"; |
| | | </style> |
File was renamed from PAMapp/pages/myConsultantList.vue |
| | |
| | | <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'; |
| | | |
| | |
| | | } |
| | | |
| | | } |
| | | </script> |
| | |
| | | </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:'å
¨é¢æª¢è¦èªå·±çä¿éçµæ§æ¯å¦ç¬¦åç¾å¨ææªä¾ç風éªç§»è½éæ±ã' |
| | | }, |
| | | { |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | | |
| | | //詳細åé¡drawerä¸éå
§å®¹ç©ºé大å°è¨ç½® |
| | | .qa-dialog{ |
| | | overflow-y:auto; |
| | | height: 500px; |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | //詳細åé¡drawerä¸»è¦æ¨é¡ |
| | | .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> |
| | | |
¤ñ¹ï·sÀÉ®× |
| | |
| | | .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; |
| | | } |
| | | } |
| | | } |
| | | |
| | | //詳細åé¡drawerä¸éå
§å®¹ç©ºé大å°è¨ç½® |
| | | .qa-dialog{ |
| | | overflow-y:auto; |
| | | height: 500px; |
| | | margin-top: 20px; |
| | | } |
| | | |
| | | //詳細åé¡drawerä¸»è¦æ¨é¡ |
| | | .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; |
| | | } |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | 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:'å
¨é¢æª¢è¦èªå·±çä¿éçµæ§æ¯å¦ç¬¦åç¾å¨ææªä¾ç風éªç§»è½éæ±ã' |
| | | }, |
| | | { |
| | | 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('/') |
| | | } |
| | | |
| | | } |
| | |
| | | </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> |
| | | <style lang="scss"> |
| | | @import "./quick-filter.component.scss"; |
| | | </style> |
¤ñ¹ï·sÀÉ®× |
| | |
| | | .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; |
| | | } |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | |
| | | 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)) |
| | | }) |
| | | } |
| | | |
| | | } |
| | | |
| | | |
| | |
| | | <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"> |
| | |
| | | </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: 'å
¨é¢æª¢è¦èªå·±çä¿éçµæ§æ¯å¦ç¬¦åç¾å¨ææªä¾ç風éªç§»è½éæ±ã' |
| | | }, |
| | | { |
| | | 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> |
¤ñ¹ï·sÀÉ®× |
| | |
| | | |
| | | .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; |
| | | } |
| | | } |
| | | } |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | 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: 'å
¨é¢æª¢è¦èªå·±çä¿éçµæ§æ¯å¦ç¬¦åç¾å¨ææªä¾ç風éªç§»è½éæ±ã' |
| | | }, |
| | | { |
| | | 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; |
| | | } |
| | | |
| | | } |
| | | |
¤ñ¹ï·sÀÉ®× |
| | |
| | | <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"> |
| | | å®¢æ¶æ»¿æåº¦ |
| | | </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> |
¤ñ¹ï·sÀÉ®× |
| | |
| | | .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; |
| | | } |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | 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; |
| | | } |
| | | } |
| | |
| | | </section> |
| | | |
| | | <section class="user-reviews-content"> |
| | | <div |
| | | <div |
| | | class="user-reviews-card" |
| | | v-for="(appointmentLog, index) in myAppointmentReviewLogList" |
| | | :key="index"> |
| | |
| | | </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> |
| | | <style lang="scss"> |
| | | @import "./record.component.scss"; |
| | | </style> |
¤ñ¹ï·sÀÉ®× |
| | |
| | | .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; |
| | | } |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | 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(); |
| | | } |
| | | |
| | | } |
| | |
| | | <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> |
| | |
| | | <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> |
| | |
| | | <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> |
| | | <style lang="scss"> |
| | | @import "./user-reviews.component.scss"; |
| | | </style> |
¤ñ¹ï·sÀÉ®× |
| | |
| | | .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; |
| | | } |
| | | } |
| | | |
| | | } |
¤ñ¹ï·sÀÉ®× |
| | |
| | | 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; |
| | | }; |
| | | } |