PAMapp/components/Client/ClientCard.vue | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
PAMapp/components/Interview/InterviewMsg.vue | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
PAMapp/pages/agentInfo/_agentNo.vue | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
PAMapp/pages/agentInfo/edit/_agentNo.vue | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
PAMapp/pages/appointment/_appointmentId/close/index.vue | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
PAMapp/pages/appointment/_appointmentId/index.vue | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
PAMapp/store/localStorage.ts | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
pamapi/src/main/java/com/pollex/pam/security/provider/CustomAuthenticationProvider.java | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
pamapi/src/main/java/com/pollex/pam/security/provider/EServiceAuthenticationProvider.java | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
pamapi/src/main/java/com/pollex/pam/web/rest/EServiceResource.java | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
pamapi/src/main/resources/config/application-uat.yml | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 |
PAMapp/components/Client/ClientCard.vue
@@ -77,12 +77,12 @@ v-else-if="client.communicateStatus === contactStatus.CONTACTED"> çµæ¡ </div> <div <!-- <div class="invite-msg smTxt_bold" @click.stop="inviteReview" v-else-if="!client.satisfactionScore"> ç¼é滿æåº¦ </div> </div> --> <div class="date xsTxt text--black" PAMapp/components/Interview/InterviewMsg.vue
@@ -102,11 +102,12 @@ } addInterview() { const message = this.getMessage(); const appointmentInformation: ToInformAppointment = { appointmentId: this.client.id, email : this.client?.email, interviewDate: this.interviewTime, message : this.interviewTxt, message, phone : this.client?.phone, }; appointmentService.informAppointment(appointmentInformation).then((_) => { @@ -121,6 +122,20 @@ this.getMyAppointmentList(); } private getMessage(): string { const targetDate = new Date(this.interviewTime); const interviewTime = `${targetDate.getFullYear()}å¹´${targetDate.getMonth() + 1}æ${targetDate.getDate()}æ¥ ${targetDate.getHours()}æ${targetDate.getMinutes()}å`; let result = ''; if(this.loginConsultant.phoneNumber && this.loginConsultant.email) { result = "æ¨å¥½ï¼ææ¯ä¿èª åªåå¹³å°çä¿éªé¡§å" + this.loginConsultant.name + "ï¼æè¬æ¨çé ç´ï¼æé è¨æå¨ä¸è¿°çæéèæ¨è¯ç¹«"+"\n" + interviewTime + "\n" +"以䏿¯æçé»è©±è碼/Emailï¼"+"\n" + this.loginConsultant.phoneNumber + "\n" + this.loginConsultant.email + "\n"+"è¥æ¤æé䏿¹ä¾¿ï¼è«èæè¯ç¹«ï¼è¬è¬ï¼"} else if (!this.loginConsultant.phoneNumber && this.loginConsultant.email) { result = "æ¨å¥½ï¼ææ¯ä¿èª åªåå¹³å°çä¿éªé¡§å" + this.loginConsultant.name + "ï¼æè¬æ¨çé ç´ï¼æé è¨æå¨ä¸è¿°çæéèæ¨è¯ç¹«"+"\n" + interviewTime + "\n" +"以䏿¯æçEmailï¼"+"\n" + this.loginConsultant.email + "\n"+"è¥æ¤æé䏿¹ä¾¿ï¼è«èæè¯ç¹«ï¼è¬è¬ï¼" } else { result = "æ¨å¥½ï¼ææ¯ä¿èª åªåå¹³å°çä¿éªé¡§å" + this.loginConsultant.name + "ï¼æè¬æ¨çé ç´ï¼æé è¨æå¨ä¸è¿°çæéèæ¨è¯ç¹«"+"\n" + interviewTime + "\n" +"以䏿¯æçé»è©±è碼ï¼"+"\n" + this.loginConsultant.phoneNumber + "\n"+"è¥æ¤æé䏿¹ä¾¿ï¼è«èæè¯ç¹«ï¼è¬è¬ï¼" } return result; } get isBtnDisabled() :Boolean { const isFormValid = this.client.phone ? this.interviewTxt && this.interviewTime :this.interviewTxt return !isFormValid PAMapp/pages/agentInfo/_agentNo.vue
@@ -1,5 +1,5 @@ <template> <div> <div v-if="!!agentInfo"> <el-row type="flex" justify="center"> @@ -110,26 +110,13 @@ </el-col> </el-row> --> <!-- <el-row <el-row type="flex" class="pam-paragraph"> <el-col :span="24" class="pam-field"> <div class="pam-field__label pam-progress__label"> <div> <div class="pam-field__title"> <i class="pam-icon icon-thumbs-up" ></i>è«®è©¢åº¦è¡¨ç¾ <i class="pl-5 text--primary icon-information" @click="alertFieldInfo('evaluation')"></i> </div> </div> <div class="xsTxt"> {{ agentInfo.evaluation }}/50 (è¿ä¸åæ/ç´¯è¨) </div> </div> <div class="pam-field__content pam-field-evaluation pt-10"> <el-progress :show-text="false" :stroke-width="15" :percentage="agentInfo.evaluation * 2"></el-progress> </div> </el-col> </el-row> --> <UiField icon="thumbs-up" label="諮詢度表ç¾"> {{ agentInfo.nearlyMonthAppointmentCount || 0 }} / {{ agentInfo.allAppointmentCount || 0 }} (è¿ä¸åæ/ç´¯è¨) </UiField> </el-row> <div class="consultant-edit-btn"> <UiField icon="flag" label="æºéé¢¨æ ¼"> @@ -273,11 +260,13 @@ } get agentName(): string { return `${this.agentInfo.name}(${this.agentInfo.role})`; if (!this.agentInfo) return ''; return `${this.agentInfo?.name}(${this.agentInfo?.role})`; } get displayCommunicationStyleList(): string[] { return this.agentInfo.communicationStyle.split('ã').filter((item) => item); if (!this.agentInfo) return []; return this.agentInfo?.communicationStyle.split('ã').filter((item) => item); } } PAMapp/pages/agentInfo/edit/_agentNo.vue
@@ -1,5 +1,5 @@ <template> <div class="edit-agent-info-page"> <div class="edit-agent-info-page" v-if="!!agentInfo"> <el-row type="flex" PAMapp/pages/appointment/_appointmentId/close/index.vue
@@ -17,7 +17,7 @@ class="pam-paragraph" style="flex-direction: column"> <UiField label="身åèåè/å± çèåè" :labelSize="20" class="required"> <input class="appointment-client-detail-close__input" class="appointment-client-detail-close__input mt-10" :class="{'is-invalid':!identityIdValid}" v-model="appointmentCloseInfo.policyholderIdentityId" placeholder="è«è¼¸å ¥" @@ -33,7 +33,7 @@ class="pam-paragraph"> <UiField label="åå代碼Plan Code" :labelSize="20" class="required"> <input class="appointment-client-detail-close__input" class="appointment-client-detail-close__input mt-10" v-model="appointmentCloseInfo.planCode" placeholder="è«è¼¸å ¥" type="text"> @@ -46,6 +46,7 @@ <UiField label="é²ä»¶æé" :labelSize="20" class="required"> <DateTimePicker :defaultValue="appointmentCloseInfo.policyEntryDate" class="mt-10" @changeDateTime="appointmentCloseDate = $event"></DateTimePicker> </UiField> </el-row> @@ -56,7 +57,7 @@ class="pam-paragraph"> <UiField label="æªæäº¤åå " :labelSize="20" class="required"> <UiSelect :closeReason.sync="appointmentCloseInfo.closedReason" :options="appointmentFailReason"/> :options="appointmentFailReason" class="mt-10"/> </UiField> <input v-if="appointmentCloseInfo.closedReason === 'other' @@ -73,6 +74,7 @@ class="pam-paragraph"> <UiField label="å註" :labelSize="20"> <el-input class="mt-10" type="textarea" :rows="3" placeholder="è«è¼¸å ¥" PAMapp/pages/appointment/_appointmentId/index.vue
@@ -1,5 +1,5 @@ <template> <div class="appointment-client-detail-page"> <div class="appointment-client-detail-page" v-if="!!appointmentDetail"> <div class="date-detail"> <div>{{ appointmentDetail.appointmentDate | formatDate }}é ç´</div> <div>{{ appointmentDetail.consultantReadTime | formatDate }} @@ -55,9 +55,9 @@ </div> </div> <div class=" btn-center" v-if="showWhenAppointmentHasClosed"> <!-- <div class=" btn-center" v-if="showWhenAppointmentHasClosed"> <el-button @click="inviteReview">ç¼é滿æåº¦</el-button> </div> </div> --> <div class="client-detail-action" v-if="showWhenAppointmentHasContacted"> <el-button @click="closeAppointment" class="desktop-client-detail-action-btn" >çµæ¡</el-button> PAMapp/store/localStorage.ts
@@ -110,6 +110,9 @@ localStorage.removeItem('consultant_id'); localStorage.removeItem('appointment'); localStorage.removeItem('login_consultant'); localStorage.removeItem('notContactAppointmentIdFromMsg'); localStorage.removeItem('satisfactionIdFromMsg'); localStorage.removeItem('appointmentIdFromMsg'); this.id_token = localStorage.getItem('id_token'); this.current_role = localStorage.getItem('current_role'); this.consultant_id = localStorage.getItem('consultant_id'); pamapi/src/main/java/com/pollex/pam/security/provider/CustomAuthenticationProvider.java
@@ -1,6 +1,5 @@ package com.pollex.pam.security.provider; import com.pollex.pam.business.security.provider.EServiceAuthenticationProvider; import com.pollex.pam.config.ApplicationProperties; import com.pollex.pam.business.security.token.EServiceAuthenticationToken; import com.pollex.pam.security.token.OtpAuthenticationToken; pamapi/src/main/java/com/pollex/pam/security/provider/EServiceAuthenticationProvider.java
¤ñ¹ï·sÀÉ®× @@ -0,0 +1,85 @@ package com.pollex.pam.security.provider; import com.pollex.pam.business.domain.Consultant; import com.pollex.pam.business.enums.ConsultantDetailEnum; import com.pollex.pam.business.repository.ConsultantRepository; import com.pollex.pam.business.service.EServiceConnectService; import com.pollex.pam.business.service.dto.EServiceResponse; import com.pollex.pam.business.web.errors.ConsultantDisableException; import com.pollex.pam.business.config.AppProperties; import com.pollex.pam.business.security.token.EServiceAuthenticationToken; import com.pollex.pam.business.web.errors.EServiceErrorException; import com.pollex.pam.config.ApplicationProperties; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.*; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.stereotype.Component; import java.security.GeneralSecurityException; import java.util.*; @Component public class EServiceAuthenticationProvider { private static final String E_SERVICE_LOGIN_SUCCESS_CODE = "true"; private static final Logger log = LoggerFactory.getLogger(EServiceAuthenticationProvider.class); @Autowired ApplicationProperties applicationProperties; @Autowired ConsultantRepository consultantRepository; @Autowired EServiceConnectService eServiceConnectService; public Authentication authenticate(EServiceAuthenticationToken authenticationToken) throws AuthenticationException { String account = authenticationToken.getPrincipal(); String credentials = authenticationToken.getCredentials(); if(applicationProperties.isMockLogin()){ return getConsultantTokenAndRecordLoginTime(account, credentials); } try { ResponseEntity<EServiceResponse> responseEntity = eServiceConnectService.loginByEService(account, credentials); if(HttpStatus.OK.equals(responseEntity.getStatusCode())) { EServiceResponse eServiceResponse = responseEntity.getBody(); log.debug("eService response = {}", eServiceResponse); if(E_SERVICE_LOGIN_SUCCESS_CODE.equals(eServiceResponse.getIssuccess())){ return getConsultantTokenAndRecordLoginTime(account, credentials); } else { throw new EServiceErrorException(eServiceResponse.getMsg()); } } throw new RuntimeException("eService http error!, response http status code = " + responseEntity.getStatusCode()); } catch (GeneralSecurityException e) { throw new RuntimeException("General Security SSL error!"); } } private UsernamePasswordAuthenticationToken getConsultantTokenAndRecordLoginTime(String account, String credential) throws ConsultantDisableException { Consultant consultant = consultantRepository.findOneByAgentNo(account).orElseThrow(() -> new UsernameNotFoundException("該顧åè³æä¸¦ä¸å卿¼åªåå¹³å°ç³»çµ±ä¸")); List<GrantedAuthority> grantedAuths = Arrays.asList(new SimpleGrantedAuthority("ROLE_USER")); UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(account, credential, grantedAuths); Map<String, String> details = new HashMap<>(); details.put(ConsultantDetailEnum.ID.getValue(), consultant.getId().toString()); details.put(ConsultantDetailEnum.NAME.getValue(), consultant.getName()); details.put(ConsultantDetailEnum.AGENT_NO.getValue(), account); authenticationToken.setDetails(details); return authenticationToken; } } pamapi/src/main/java/com/pollex/pam/web/rest/EServiceResource.java
@@ -1,6 +1,7 @@ package com.pollex.pam.web.rest; import com.pollex.pam.business.aop.logging.audit.AuditLoggingInject; import com.pollex.pam.business.service.ConsultantService; import com.pollex.pam.security.jwt.JWTFilter; import com.pollex.pam.security.jwt.TokenProvider; import com.pollex.pam.business.security.token.EServiceAuthenticationToken; @@ -29,6 +30,9 @@ @Autowired TokenProvider tokenProvider; @Autowired ConsultantService consultantService; @AuditLoggingInject(type = CONSULTANT_LOGIN) @PostMapping("/authenticate") public ResponseEntity<UserJWTController.JWTToken> authorize(@RequestBody EServiceLoginVM eServiceLoginVM) { @@ -38,7 +42,9 @@ ); Authentication authentication = authenticationManagerBuilder.getObject().authenticate(authenticationToken); consultantService.updateLoginTime(eServiceLoginVM.getUsername()); SecurityContextHolder.getContext().setAuthentication(authenticationToken); String jwt = tokenProvider.createToken(authentication, false); HttpHeaders httpHeaders = new HttpHeaders(); httpHeaders.add(JWTFilter.AUTHORIZATION_HEADER, "Bearer" + jwt); pamapi/src/main/resources/config/application-uat.yml
@@ -117,7 +117,7 @@ e-service-login-url: https://eserviceuat.pcalife.com.tw/sso/chatbotValidate e-service-login-func: ValidateUsrLogin e-service-login-sys: epos front-end-domain: https://vtwlifeopensysuat.pru.intranet.asia/pam front-end-domain: https://onlineuat.pcalife.com.tw/pam sms: send-notify-msg: true url: https://vtwlifeopensysuat.pru.intranet.asia/MesgQueueMgmnt/rest/smsSendMsgResource