PAMapp/assets/scss/utilities/_utilities.scss | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
PAMapp/assets/scss/vendors/elementUI/_rate.scss | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
PAMapp/components/BackActionBar.vue | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
PAMapp/layouts/default.vue | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
PAMapp/pages/notification/index.vue | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
PAMapp/pages/record/reviews.vue | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 | |
PAMapp/pages/userReviews/index.vue | ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程 |
PAMapp/assets/scss/utilities/_utilities.scss
@@ -24,6 +24,10 @@ margin-bottom: 10px; } .mb-20{ margin-bottom: 20px; } .ml-10{ margin-left: 10px; } PAMapp/assets/scss/vendors/elementUI/_rate.scss
@@ -26,4 +26,9 @@ color: $PRIMARY_BLACK !important; } } } } .user-reviews-rate{ .el-rate__icon { font-size: 30px; } } PAMapp/components/BackActionBar.vue
@@ -37,6 +37,12 @@ break; case 'questionnaire': featureLabel = 'é²è¡é ç´'; break; case 'notification': featureLabel = 'éç¥'; break; case 'notificationDetail': featureLabel='éç¥ç´°ç¯'; } return featureLabel; } else { PAMapp/layouts/default.vue
@@ -31,6 +31,7 @@ [RouterPage.QUICK_FILTER]: ['é»é¸ä¸æ¹é¸é ', 'å°æ¾ä½ çBEST Match'], [RouterPage.MY_CONSULTANT_LIST]:[], [RouterPage.QUESTIONNAIRE]:[], [RouterPage.NOTIFICATION]:[] } get getBannerTextList(): string[] { return this.bannerTextDto[this.route] ? this.bannerTextDto[this.route] : []; @@ -47,7 +48,7 @@ // format to {page}-banner or pam-no-banner tag private routeFormatBannerClass(route: string): string { const needBannerTags = ['recommendConsultant', 'quickFilter', 'myConsultantList-consultantList', 'myConsultantList-contactedList', 'myAppointmentList-appointmentList', 'myAppointmentList-contactedList']; const needBannerTags = ['recommendConsultant', 'quickFilter', 'myConsultantList-consultantList', 'myConsultantList-contactedList', 'myAppointmentList-appointmentList', 'myAppointmentList-contactedList','notification']; return _.includes(needBannerTags, route) ? route + '-banner' : 'pam-no-banner'; }; @@ -66,6 +67,7 @@ QUICK_FILTER = "quickFilter", MY_CONSULTANT_LIST = "myConsultantList", QUESTIONNAIRE = 'questionnaire', NOTIFICATION = 'notification' } type BannerDto={ [x:string]:string[]; @@ -186,5 +188,19 @@ } } } // .notification{ // &-banner{ // background-image: url('~/assets/images/satisfaction/notification_mob.svg'); // background-size: cover; // } // @media (min-width: 768px) { // &-banner { // background-image: url('~/assets/images/satisfaction/notification_web.svg'); // } // } // } </style> PAMapp/pages/notification/index.vue
@@ -1,5 +1,264 @@ <template> <div>éç¥åè½ <el-button @click="$router.push('/notification/detail')">éç¥ç´°ç¯</el-button> </div> </template> <div class="notification-page"> <section class="notification-header"> <div> <i class="icon-edit icon" style="color:#1B365D" @click="showNotification = true" ></i> </div> </section> <section class="notification-reviews" @click="$router.push('/userReviews')"> <div class="reviews-txt"> è«å¡«å¯«æ»¿æåº¦èª¿æ¥ </div> </section> <section class="notification-content"> <div class="notification-container"> <div v-for="(item,index) in notificationList" :key="index" class="notification-card" @click="readNotification(index)" > <div class="notification-card__aside"> <span v-if="!item.hasRead" class="notification-card__aside-unread-indicator"></span> </div> <div class="notification-card__content">{{ item.content }}</div> <div class="notification-card__time-stamp">{{ item.time }}</div> </div> </div> </section> <PopUpFrame :isOpen.sync="showNotification" > <div class="popup-txt"> <div>éç¥</div> <el-radio-group class="pam-radio-group--col" > <el-radio-button class="mt-30" label="å ¨é¨å·²è®" @click.native="readNotification"></el-radio-button> <el-radio-button class="mt-30" label="å ¨é¨åªé¤" @click.native="deleteNotification"></el-radio-button> </el-radio-group> </div> </PopUpFrame> </div> </template> <script lang="ts"> import { Vue, Component } from 'vue-property-decorator' @Component export default class Notification extends Vue{ notificationList: NotificationIF[] = [ { content:'å°æ¼10/30 02:00-14:00é²è¡æ´æ°ï¼è«çææ¨ç帳...', time:'ä»å¤© 10:00', hasRead: false, }, { content:'å°æ¼10/11 02:00-14:00é²è¡æ´æ°ï¼è«çææ¨ç帳...', time:'ä»å¤© 10:00', hasRead: false, }, { content:'å°æ¼9/28 02:00-14:00é²è¡æ´æ°ï¼è«çææ¨ç帳...', time:'ä»å¤© 10:00', hasRead: false, }, { content:'å°æ¼9/28 02:00-14:00é²è¡æ´æ°ï¼è«çææ¨ç帳...', time:'ä»å¤© 10:00', hasRead: false, } ]; showNotification = false; readNotification(index?: number): void { const targetNotification = this.notificationList[index]; const readNotifaction = (notification: NotificationIF) => notification.hasRead = true; // å®ç¾© è®æ¸ = ( 忏 : åå¥ ) if (targetNotification) { readNotifaction(targetNotification); this.$router.push('/notification/detail'); } else { this.notificationList.forEach((notification) => readNotifaction(notification)); } } deleteNotification(): void { this.notificationList = []; } } export interface NotificationIF { content: string; time: string; hasRead: boolean; } </script> <style lang="scss" scoped> .notification-page{ .notification-header{ display: flex; justify-content: flex-end; font-size:20px; margin-bottom:20px; .icon{ cursor: pointer; display: flex; } } .notification-reviews{ background-image: url('~/assets/images/satisfaction/notification_mob.svg'); height: 60px; border-radius: 10px; display: flex; justify-content: center; margin-bottom: 20px; cursor: pointer; .reviews-txt{ font-size: 20px; align-items: center; font-weight: bold; display: flex; color: black; -webkit-text-stroke: .3px #FFFF; } } .notification-content{ .notification-container{ .notification-card { height: 62px; padding-bottom: 11px; display: flex; border-bottom: 1px solid #CCCCCC; padding-top: 10px; .notification-card__aside { width: 30px; display: flex; align-items: center; justify-content: center; .notification-card__aside-unread-indicator { width: 10px; height: 10px; background-color: $YELLOW; border-radius: 50%; } } .notification-card__content { font-size: 20px; line-height: 1.5; } .notification-card__time-stamp { display: flex; width: 52px; align-self: center; font-size: 10px; color: #707070; } } } } } .popup-txt{ font-size: 20px; display: flex; justify-content: center; flex-direction: column; align-items: center; } @include desktop{ .notification-page{ .notification-header{ display: flex; justify-content: flex-end; font-size:24px; margin-bottom:20px; .icon{ cursor: pointer; } } .notification-reviews{ background-image: url('~/assets/images/satisfaction/notification_web.svg'); height: 110px; border-radius: 10px; display: flex; justify-content: center; margin-bottom: 40px; cursor: pointer; .reviews-txt{ font-size: 20px; align-items: center; font-weight: bold; display: flex; color: black; -webkit-text-stroke: .3px #FFFF; } } .notification-content{ .notification-container{ .notification-card { height: 60px; padding-bottom: 10px; display: flex; border-bottom: 1px solid #CCCCCC; padding-top: 10px; .notification-card__aside { width: 30px; display: flex; align-items: center; justify-content: center; .notification-card__aside-unread-indicator { width: 10px; height: 10px; background-color: $YELLOW; border-radius: 50%; } } .notification-card__content { font-size: 20px; line-height: 1.5; padding-top: 10px; } .notification-card__time-stamp { display: flex; width: 52px; align-self: center; font-size: 10px; color: #707070; justify-content: flex-end; flex: 1; } } } } } } </style> PAMapp/pages/record/reviews.vue
@@ -1,3 +1,3 @@ <template> <div>æ¥çç´é(滿æåº¦ç´é)</div> <div>æ¥çç´é(滿æåº¦ç´é)é¡§å</div> </template> PAMapp/pages/userReviews/index.vue
¤ñ¹ï·sÀÉ®× @@ -0,0 +1,217 @@ <template> <div class="reviews-page"> <div class="reviews-banner"></div> <section class="reviews-container"> <section class="reviews-header"> <div class="reviews-header-container"> <div class="reviews-header-title">滿æåº¦èª¿æ¥</div> <div class="reviews-header-subTitle">å ±{{ reviewsList.length }}ç</div> </div> </section> <section class="reviews-content"> <div class="reviews-content-card" v-for="(item,index) in reviewsList" :key="(index)"> <div class="card-body"> <div class="card-avatar"> <img :src="item.avatar" class="img"> </div> <div class="card-txt"> å°æ¼é¡§å <span class="p">{{item.name}}</span>çæ´é«æå,æ¨çµ¦äºå¹¾é¡æçè©å¹? <div class="card-score" v-if="!isMobileDevice"> <el-rate class="user-reviews-rate" v-model="item.avgScore"></el-rate> </div> </div> </div> <div class="card-score" v-if="isMobileDevice"> <el-rate class="user-reviews-rate" v-model="item.avgScore"></el-rate> </div> </div> </section> </section> <section class="reviews-footer"> <el-button type="primary" class="reviews-footer-btn" @click.native="sendReviews">éåº</el-button> </section> <PopUpFrame :isOpen.sync="showReviews"> <div class="reviews-dialog"> <span class="reviews-dialog-title">è©å¹å®æ!</span> </div> <div class="reviews-btn-block"> <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'; @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; .reviews-dialog-btn{ } } } @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-header{ } .reviews-content{ display: flex; flex-direction: column; align-items: flex-start; } } .reviews-footer{ background-color:#F8F9FA; } } } </style>