Update#178944: 移除 lodash 套件
| | |
| | | import { namespace } from 'nuxt-property-decorator'; |
| | | import { Vue, Component,} from 'vue-property-decorator'; |
| | | |
| | | import * as _ from 'lodash'; |
| | | import { Role } from '~/shared/models/enum/Role'; |
| | | |
| | | const appointmentStore = namespace('appointment.store'); |
| | |
| | | break; |
| | | case 'agentInfo': |
| | | const agentFeatureLabel = this.$route.name.includes('edit') ? '編輯帳號資訊' : '查看帳號資訊'; |
| | | featureLabel = _.isEqual(this.currentRole,Role.ADMIN) |
| | | featureLabel = this.currentRole === Role.ADMIN |
| | | ? agentFeatureLabel |
| | | : '業務員資訊' |
| | | break; |
| | |
| | | import { Vue, Component } from 'vue-property-decorator'; |
| | | import { Action, namespace, State, Watch } from 'nuxt-property-decorator'; |
| | | import { Role } from '~/shared/models/enum/Role'; |
| | | import * as _ from 'lodash'; |
| | | import { NotificationList } from '~/shared/models/reviews.model'; |
| | | import { AppointmentLog } from '~/shared/models/appointment.model'; |
| | | import loginService from '~/shared/services/login.service' |
| | |
| | | |
| | | routerNavigateTo(url: string): void { |
| | | (this.$refs.dropdown as any).hide(); |
| | | _.isEqual(url,'') |
| | | url === '' |
| | | ? this.logout() |
| | | : this.$router.push(_.isEqual(url,'/agentInfo/') ? url+this.consultantId :url); |
| | | : this.$router.push(url === '/agentInfo/' ? url+this.consultantId : url); |
| | | } |
| | | |
| | | pushRouterByLoginRole(): void { |
| | | const link = _.isEqual(this.currentRole, Role.ADMIN) ? '/myAppointmentList/appointmentList' : '/'; |
| | | const link = this.currentRole === Role.ADMIN ? '/myAppointmentList/appointmentList' : '/'; |
| | | this.$router.push(link); |
| | | } |
| | | |
| | | logout(): void { |
| | | loginService.logout().then(() => { |
| | | this.storageClear(); |
| | | _.isEqual(this.$route.name, 'index') ? location.reload() : this.$router.push('/'); |
| | | this.$route.name === 'index' ? location.reload() : this.$router.push('/'); |
| | | }); |
| | | } |
| | | |
| | |
| | | |
| | | <script lang="ts"> |
| | | import { Component , PropSync , Vue} from "vue-property-decorator"; |
| | | import * as _ from 'lodash'; |
| | | |
| | | @Component |
| | | export default class CareerSelect extends Vue { |
| | |
| | | |
| | | patchInitValue(): void{ |
| | | if(this.syncCareerSelect){ |
| | | if(_.includes(['外勤','內勤'],this.syncCareerSelect)){ |
| | | if (['外勤','內勤'].includes(this.syncCareerSelect)) { |
| | | this.career = this.syncCareerSelect; |
| | | }else{ |
| | | this.career = '其他'; |
| | |
| | | patchCareer(): void { |
| | | this.showJobDrawer = false; |
| | | this.syncCareerSelect = this.career === '其他' |
| | | ? _.cloneDeep(this.career_Other) |
| | | : _.cloneDeep(this.career); |
| | | ? JSON.parse(JSON.stringify(this.career_Other)) |
| | | : JSON.parse(JSON.stringify(this.career)); |
| | | } |
| | | |
| | | get isCareerValid(): boolean { |
| | |
| | | |
| | | import { MessageBox } from 'element-ui'; |
| | | import { MessageBoxData } from 'element-ui/types/message-box'; |
| | | import _ from 'lodash'; |
| | | |
| | | import myConsultantService from '~/shared/services/my-consultant.service'; |
| | | |
| | |
| | | } |
| | | |
| | | handleAvatarUploaded(file:any): void { |
| | | const isFollowUploadRule =_.includes(file.raw.type,'image/'); |
| | | const isFollowUploadRule = file.raw.type.includes('image/'); |
| | | isFollowUploadRule ? this.getImgSrc(file) : this.showFileUploadErrorMsg() |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | private splitBase64WithCommon(base64: string): void { |
| | | const splitBase64= _.split(base64, ','); // 為了把 data:image , base64 解析分開; |
| | | const splitBase64 = base64.split(','); // 為了把 data:image , base64 解析分開; |
| | | this.syncPhotoBase64 = splitBase64[1]; |
| | | // NOTE: 因為目前以 agentNO 取得 avatar 會失敗, |
| | | // 故加上此判斷來防範不預期顯示'取消按鈕'的狀況。 [Tomas, 2022/1/3] |
| | |
| | | <script lang="ts"> |
| | | import { Component, Prop, PropSync, Vue } from "nuxt-property-decorator"; |
| | | import { OptionBtnDto } from "~/shared/models/optionBtnDto.model"; |
| | | import * as _ from 'lodash'; |
| | | |
| | | @Component |
| | | export default class SingleSelectBtn extends Vue { |
| | |
| | | ////////////////////////////////////////////////////////////////////// |
| | | patchValue(value: string | number): void { |
| | | // 主要解決按鈕點擊兩次能回到,未點選的狀態 |
| | | this.syncSingleSelected = _.isEqual(this.syncSingleSelected, value) ? "" : value; |
| | | this.syncSingleSelected = this.syncSingleSelected === value ? "" : value; |
| | | } |
| | | } |
| | | </script> |
| | |
| | | |
| | | <script lang="ts"> |
| | | import { Vue, Component } from 'vue-property-decorator'; |
| | | import * as _ from 'lodash'; |
| | | |
| | | @Component |
| | | export default class DefaultLayout extends Vue { |
| | |
| | | // format to {page}-container tag |
| | | private routeFormatContainClass(route: string): string { |
| | | const needContainBgRoutes = ['recommendConsultant', 'questionnaire-agentNo']; |
| | | return _.includes(needContainBgRoutes, route) ? route + '-container' : ''; |
| | | return needContainBgRoutes.includes(route) ? route + '-container' : ''; |
| | | }; |
| | | |
| | | // format to {page}-banner or pam-no-banner tag |
| | | private routeFormatBannerClass(route: string): string { |
| | | const needBannerRoutes = ['recommendConsultant', 'quickFilter', 'myConsultantList-consultantList', 'myConsultantList-contactedList', 'myAppointmentList-appointmentList', 'myAppointmentList-contactedList', 'login', 'notification']; |
| | | return _.includes(needBannerRoutes, route) ? route + '-banner' : 'pam-no-banner'; |
| | | return needBannerRoutes.includes(route) ? route + '-banner' : 'pam-no-banner'; |
| | | }; |
| | | |
| | | private bannerText: FeatureBannerTitle= { |
| | |
| | | </template> |
| | | <script lang="ts"> |
| | | import { Component ,Vue } from "nuxt-property-decorator"; |
| | | import * as _ from 'lodash'; |
| | | @Component |
| | | export default class DefaultLayout extends Vue { |
| | | |
| | |
| | | } |
| | | } |
| | | |
| | | </style> |
| | | </style> |
| | |
| | | import { Vue,Component } from 'vue-property-decorator' |
| | | import { namespace } from 'vuex-class'; |
| | | |
| | | import _ from 'lodash'; |
| | | |
| | | import accountSettingService from '~/shared/services/account-setting.service'; |
| | | import { UserSetting } from '~/shared/models/account.model'; |
| | | |
| | |
| | | |
| | | //////////////////////////////////////////////////////////// |
| | | mounted(){ |
| | | accountSettingService.getUserAccountSetting().then((userInfo: UserSetting)=>{ |
| | | this.defaultUserSetting = _.cloneDeep({ |
| | | name : userInfo.name || '', |
| | | phone: userInfo.phone || '', |
| | | email: userInfo.email || '', |
| | | }); |
| | | this.phoneValue = this.defaultUserSetting.phone!; |
| | | this.userNameValue = this.defaultUserSetting.name!; |
| | | this.emailValue = this.defaultUserSetting.email!; |
| | | }) |
| | | } |
| | | accountSettingService.getUserAccountSetting().then((userInfo: UserSetting)=>{ |
| | | this.defaultUserSetting = { |
| | | name : userInfo.name || '', |
| | | phone: userInfo.phone || '', |
| | | email: userInfo.email || '', |
| | | }; |
| | | this.phoneValue = this.defaultUserSetting.phone!; |
| | | this.userNameValue = this.defaultUserSetting.name!; |
| | | this.emailValue = this.defaultUserSetting.email!; |
| | | }) |
| | | } |
| | | //////////////////////////////////////////////////////////// |
| | | |
| | | editField(fieldName: string): void { |
| | | 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(); |
| | | }); |
| | | } |
| | | 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(); |
| | | }); |
| | | } |
| | | |
| | | updateAccountSetting(): void { |
| | | const editSettingInfo: UserSetting = { |
| | | name: this.userNameValue, |
| | |
| | | } |
| | | |
| | | private resetSettingForm(): void { |
| | | this.userNameDisabled = true; |
| | | this.userPhoneDisabled = true; |
| | | this.userEmailDisabled = true ; |
| | | } |
| | | this.userNameDisabled = true; |
| | | this.userPhoneDisabled = true; |
| | | this.userEmailDisabled = true ; |
| | | } |
| | | |
| | | editOtherContactType(){ |
| | | this.otherContactType = true; |
| | |
| | | <script lang="ts"> |
| | | import { Vue, Component, Watch, namespace } from 'nuxt-property-decorator'; |
| | | |
| | | import * as _ from 'lodash'; |
| | | |
| | | import appointmentService from '~/shared/services/appointment.service'; |
| | | import { Appointment } from '~/shared/models/appointment.model'; |
| | | import { ContactStatus } from '~/shared/models/enum/contact-status'; |
| | |
| | | |
| | | // format to {page}-banner or pam-no-banner tag |
| | | private routeFormatBannerClass(route: string): string { |
| | | const needBannerTags = ['myAppointmentList-appointmentList', 'myAppointmentList-closedList']; |
| | | return _.includes(needBannerTags, route) ? route + '-banner' : 'pam-no-banner'; |
| | | const needBannerTags = ['myAppointmentList-appointmentList', 'myAppointmentList-closedList']; |
| | | return needBannerTags.includes(route) ? route + '-banner' : 'pam-no-banner'; |
| | | }; |
| | | } |
| | | </script> |
| | |
| | | <script lang="ts"> |
| | | import { Vue, Component, State, Action, Watch, namespace } from 'nuxt-property-decorator'; |
| | | import { getRequestsFromStorage, removeRequestQuestionFromStorage, setRequestsToStorage } from '~/shared/storageRequests'; |
| | | import _ from 'lodash'; |
| | | |
| | | import accountSettingService from '~/shared/services/account-setting.service'; |
| | | import appointmentService from '~/shared/services/appointment.service'; |
| | |
| | | ]; |
| | | |
| | | quesAboutList = [ |
| | | { |
| | | title:'健康與保障', |
| | | content:'唯有把身體照顧好,才是保障幸福之本,不做盲目燃燒的蠟燭,只做綻開的陽光,陪孩子多走一哩路,人生的美正要開展。' |
| | | }, |
| | | { |
| | | title:'子女教育', |
| | | content:'孩子,我們是雙方的導師也是學生,面對未來要並肩作戰,學會勇敢無畏、克服挫折、善於理財,這條路上我們一起學。' |
| | | }, |
| | | { |
| | | title:'資產規劃', |
| | | content:'真正的財富來自嚴謹規劃資產傳承,為人生蓋一堵抵禦財務風險的牆,確保資產穩健成長,替全家族的未來做好萬全準備。' |
| | | }, |
| | | { |
| | | title:'樂活退休', |
| | | content:'拼一輩子,退休後的日子要輕鬆快活,就得提早透過保險商品規劃退休財務,替自己創造穩定收入,為精彩的熟年人生揭開序幕。' |
| | | }, |
| | | { |
| | | title:'保單健檢/規劃', |
| | | content:'全面檢視自己的保障結構是否符合現在或未來的風險移轉需求。' |
| | | }, |
| | | { |
| | | title:'分紅保單', |
| | | content:'分紅保單是兼具「分攤風險」與「紅利共享」特色的保單,具有一定穩定度,讓您可以同時享有壽險保障及紅利!' |
| | | } |
| | | { |
| | | title:'健康與保障', |
| | | content:'唯有把身體照顧好,才是保障幸福之本,不做盲目燃燒的蠟燭,只做綻開的陽光,陪孩子多走一哩路,人生的美正要開展。' |
| | | }, |
| | | { |
| | | title:'子女教育', |
| | | content:'孩子,我們是雙方的導師也是學生,面對未來要並肩作戰,學會勇敢無畏、克服挫折、善於理財,這條路上我們一起學。' |
| | | }, |
| | | { |
| | | title:'資產規劃', |
| | | content:'真正的財富來自嚴謹規劃資產傳承,為人生蓋一堵抵禦財務風險的牆,確保資產穩健成長,替全家族的未來做好萬全準備。' |
| | | }, |
| | | { |
| | | title:'樂活退休', |
| | | content:'拼一輩子,退休後的日子要輕鬆快活,就得提早透過保險商品規劃退休財務,替自己創造穩定收入,為精彩的熟年人生揭開序幕。' |
| | | }, |
| | | { |
| | | title:'保單健檢/規劃', |
| | | content:'全面檢視自己的保障結構是否符合現在或未來的風險移轉需求。' |
| | | }, |
| | | { |
| | | title:'分紅保單', |
| | | content:'分紅保單是兼具「分攤風險」與「紅利共享」特色的保單,具有一定穩定度,讓您可以同時享有壽險保障及紅利!' |
| | | } |
| | | ]; |
| | | |
| | | myRequest: AppointmentRequests = { |
| | | name : '', |
| | | phone : '', |
| | | email : '', |
| | | contactType : _.isEqual(this.userInfo?.contactType,ContactType.SMS) ? ContactType.PHONE: ContactType.EMAIL, |
| | | contactType : this.userInfo?.contactType === ContactType.SMS ? ContactType.PHONE: ContactType.EMAIL, |
| | | gender : '', |
| | | age : '', |
| | | job : '', |
| | |
| | | |
| | | //////////////////////////////////////////////////////////////////////////// |
| | | |
| | | |
| | | async sentDemand() { |
| | | if (!this.isEditBtn) { |
| | | if (this.isEditBtn) { |
| | | await this.editAppointmentDemand(); |
| | | } else { |
| | | // 使用 async/await 來等待異步操作的回傳結果 |
| | | const addFavoriteAgentList = [{ agentNo: this.$route.params.agentNo, createdTime: new Date().toISOString() }]; |
| | | const response = await queryConsultantService.addFavoriteConsultant(addFavoriteAgentList); |
| | | |
| | | // 確保異步操作的回傳結果不為 null 或 undefined |
| | | if (!response) { |
| | | throw new Error('queryConsultantService.addFavoriteConsultant returned null-like value.'); |
| | | if (response !== null) { |
| | | await this.sentAppointmentDemand(); |
| | | } else { |
| | | if (typeof this.editAppointmentDemand === 'function') { |
| | | // 確保 this.editAppointmentDemand 是一個函數 |
| | | await this.editAppointmentDemand(); |
| | | } else { |
| | | // 處理 this.editAppointmentDemand 未定義的情況 |
| | | throw new Error('this.editAppointmentDemand is not defined or not a function.'); |
| | | } |
| | | throw new Error('queryConsultantService.addFavoriteConsultant returned null-like value.'); |
| | | } |
| | | } else { |
| | | await this.editAppointmentDemand(); |
| | | } |
| | | |
| | | const editSettingInfo: UserSetting = { |
| | |
| | | this.storageUserInfo(this.userInfo); |
| | | } |
| | | |
| | | |
| | | private editAppointmentDemand() { |
| | | const info = { |
| | | ...this.myRequest, |
| | | requirement: _.map(this.myRequest.requirement,o=>o).toString(), |
| | | requirement: this.myRequest.requirement.map(o => o).toString(), |
| | | hopeContactTime: this.myRequest.phone && this.phoneValid ? this.getHopeContactTime() :'', |
| | | id: this.appointmentId, |
| | | otherRequirement: null |
| | |
| | | private sentAppointmentDemand() { |
| | | const data: AppointmentParams = { |
| | | ...this.myRequest, |
| | | requirement: _.map(this.myRequest.requirement,o=>o).toString(), |
| | | requirement: this.myRequest.requirement.map(o => o).toString(), |
| | | hopeContactTime: this.myRequest.phone && this.phoneValid ? this.getHopeContactTime() :'', |
| | | agentNo: this.$route.params.agentNo |
| | | }; |
| | |
| | | get phoneValid(): boolean { |
| | | const rule = /^09[0-9]{8}$/; |
| | | return this.myRequest.phone |
| | | ? rule.test(this.myRequest.phone) && _.isEqual(this.myRequest.phone.length,10) |
| | | ? rule.test(this.myRequest.phone) && this.myRequest.phone.length === 10 |
| | | : true; |
| | | } |
| | | |
| | |
| | | } |
| | | |
| | | get isDisabledSubmitBtn(): boolean { |
| | | return _.includes(this.myRequest.contactType,ContactType.PHONE) |
| | | ? !this.isHopeContactTimeDone() || !this.emailValid |
| | | : !this.phoneValid; |
| | | return this.myRequest.contactType.includes(ContactType.PHONE) |
| | | ? !this.isHopeContactTimeDone() || !this.emailValid |
| | | : !this.phoneValid; |
| | | } |
| | | |
| | | private isHopeContactTimeDone():boolean{ |
| | |
| | | |
| | | |
| | | </style> |
| | | |
| | |
| | | import { Seniority } from '~/shared/models/enum/seniority'; |
| | | import { Vue, Component, namespace } from 'nuxt-property-decorator'; |
| | | import queryConsultantService from '~/shared/services/query-consultant.service'; |
| | | import _ from 'lodash'; |
| | | |
| | | const localStorage = namespace('localStorage'); |
| | | const seniorityMap={ |
| | |
| | | import { AxiosRequestConfig, AxiosError, AxiosResponse} from 'axios'; |
| | | import axios from 'axios'; |
| | | import _ from 'lodash'; |
| | | import axios, { AxiosError, AxiosRequestConfig, AxiosResponse } from 'axios'; |
| | | |
| | | import messageBoxService from './message-box.service'; |
| | | |
| | |
| | | messageBoxService.showErrorMessage('', error); |
| | | return |
| | | } |
| | | if (!_.includes(notRequireInterceptorErrorUrl, error.config.url)) { |
| | | if (!notRequireInterceptorErrorUrl.includes(error.config.url)) { |
| | | switch (error.response.status) { |
| | | case 401: |
| | | Promise.all([messageBoxService.showErrorMessage('登入逾時'), window.$nuxt.$store.dispatch('localStorage/actionStorageClear')]).then(() => { |
| | | _.isEqual(window.$nuxt.$route.name, 'index') ? location.reload() : window.$nuxt.$router.push('/'); |
| | | if (window.$nuxt.$route.name === 'index') { |
| | | location.reload(); |
| | | } else { |
| | | window.$nuxt.$router.push('/'); |
| | | } |
| | | }); |
| | | break; |
| | | |
| | |
| | | import { http } from "./httpClient"; |
| | | import { AxiosResponse } from 'axios'; |
| | | import _ from "lodash"; |
| | | import CryptoJS from "crypto-js"; |
| | | import forge from "node-forge"; |
| | | import { http } from "./httpClient"; |
| | | // import CryptoJS from "asmcrypto-js"; |
| | | |
| | | import { ConsultantLoginInfo } from "../models/ConsultantLoginInfo"; |
| | |
| | | return http.get('/login/validate/get_img_code',{ responseType : 'arraybuffer' }) |
| | | .then( response => { |
| | | const toBase64 = window.btoa( |
| | | _.reduce( new Uint8Array(response.data),(data,byte) => |
| | | data + String.fromCharCode(byte),'') |
| | | Array.from(new Uint8Array(response.data)).reduce((data, byte) => |
| | | data + String.fromCharCode(byte), '') |
| | | ); |
| | | const imgSrc = `data:image/jpeg;base64,${toBase64}`; |
| | | return imgSrc; |
| | |
| | | import { Module, VuexModule, Mutation, Action } from 'vuex-module-decorators'; |
| | | import _ from 'lodash'; |
| | | import { Action, Module, Mutation, VuexModule } from 'vuex-module-decorators'; |
| | | |
| | | |
| | | export enum LocalStorageItem { |
| | |
| | | //** 初始物件狀態 **// |
| | | private getInitLocalStorageDto(): storageDataDto { |
| | | const initLocalStorageDto = {} as storageDataDto; |
| | | _.forEach( LocalStorageItem , keyName => |
| | | initLocalStorageDto[keyName] = this.processOfStorageGetItem(keyName) |
| | | ) |
| | | Object.values(LocalStorageItem).forEach(keyName => { |
| | | initLocalStorageDto[keyName] = this.processOfStorageGetItem(keyName); |
| | | }); |
| | | return initLocalStorageDto; |
| | | } |
| | | //** 取得 localStorage資料 **/ |
| | |
| | | const storageData = localStorage.getItem(keyName); |
| | | const itemType = initialValueOfStorageItemDto[keyName]; |
| | | const prepareData = storageData |
| | | ? _.isEqual(itemType,String) |
| | | ? typeof itemType === 'string' |
| | | ? storageData |
| | | : JSON.parse(storageData) |
| | | : null; |
| | | return prepareData |
| | | } |
| | | |
| | | ///////////////////////////////////////////////// Mutation |
| | | |
| | | /** 儲存進 localStorageDto **/ |
| | |
| | | |
| | | //** 移除全部物件 **// |
| | | @Mutation clearStoreData(): void { |
| | | _.keys(this.localStorageDto) |
| | | Object.keys(this.localStorageDto) |
| | | .forEach(keyName => { |
| | | localStorage.removeItem(keyName); |
| | | this.localStorageDto[keyName]=null; |
| | |
| | | |
| | | //** 物件儲存 **// |
| | | @Action storeData( data: storageDataDto ): void { |
| | | _.keys(data).forEach(keyName=>{ |
| | | Object.keys(data).forEach(keyName=>{ |
| | | const newObj = { |
| | | keyName:keyName, |
| | | value:data[keyName] |
| | |
| | | //** 將需要 存進 localStorage 格式 **// |
| | | @Action localStorageSet( setItem:SetItemDto ): void { |
| | | const itemType = initialValueOfStorageItemDto[setItem.keyName]; |
| | | const prepareData = _.isEqual(itemType,String) |
| | | const prepareData = typeof itemType === 'string' |
| | | ? setItem.value |
| | | : JSON.stringify(setItem.value); |
| | | localStorage.setItem(setItem.keyName,prepareData); |