PAMapp/assets/scss/_common.scss
@@ -4,6 +4,7 @@ margin: 0; color: $PRIMARY_BLACK; font-family: Segoe UI; overflow-x: hidden; } h5 { @@ -39,31 +40,4 @@ &:disabled { background-color: $LIGHT_GREY; } } // el-carousel .el-carousel__indicators--outside { .el-carousel__indicator--horizontal { .el-carousel__button { width: 9px; height: 9px; border-radius: 50px; border: solid 1px $LIGHT_GREY; background-color: $PRIMARY_WHITE; } &.is-active { .el-carousel__button { background-color: $PRIMARY_RED; } } } .el-carousel__indicator--horizontal:nth-child(2) { .el-carousel__button { margin: 0 20px; } } } } PAMapp/assets/scss/utilities/_heading.scss
@@ -39,6 +39,10 @@ font-weight: bold; } .text--center { text-align: center; } .text--primary { color: $PRIMARY_RED; } @@ -50,3 +54,11 @@ .text--dark-blue { color: $DARK_BLUE; } .text--prudential_grey { color: $PRUDENTIAL_GREY; } .text--mid_grey { color: $MID_GREY; } PAMapp/assets/scss/utilities/_utilities.scss
@@ -1,6 +1,10 @@ @import '_heading'; @import '_icon'; .mb-50 { margin-bottom: 50px; } .mt-30 { margin-top: 30px; } PAMapp/assets/scss/vendors/_elementUI.scss
@@ -2,3 +2,9 @@ @import './elementUI/button'; @import './elementUI/progress'; @import './elementUI/dropdown'; @import './elementUI/_checkbox'; @import './elementUI/_radio'; @import './elementUI/_drawer'; @import './elementUI/_carousel'; @import './elementUI/_rate'; @import './elementUI/_tag'; PAMapp/assets/scss/vendors/elementUI/_carousel.scss
¤ñ¹ï·sÀÉ®× @@ -0,0 +1,44 @@ .el-carousel__indicators--outside { .el-carousel__indicator--horizontal { .el-carousel__button { width: 9px; height: 9px; border-radius: 50px; border: solid 1px $LIGHT_GREY; background-color: $PRIMARY_WHITE; } &.is-active { .el-carousel__button { background-color: $PRIMARY_RED; } } } .el-carousel__indicator--horizontal:nth-child(2) { .el-carousel__button { margin: 0 20px; } } } .pam-consultant-carousel { padding: 0 10px; margin: 0 -10px; .el-carousel__container { .el-carousel__item { max-width: 336px; width: 100%; box-shadow: 0 0 6px #00000029; border-radius: 10px; background-color: $PRIMARY_WHITE; } } @include desktop { .el-carousel__container { transform: translateX(25%); } } } PAMapp/assets/scss/vendors/elementUI/_checkbox.scss
¤ñ¹ï·sÀÉ®× @@ -0,0 +1,33 @@ .pam-quickFilter-checkbox.el-checkbox-group { display: flex; justify-content: space-between; width: 100%; flex-wrap: wrap; height: 240px; .el-checkbox { display: block; width: 48%; height: 110px; margin-right: 0px; box-shadow: 0 0 6px #22222229; border-radius: 10px; .el-checkbox__input { display: none; } .el-checkbox__label { color: $PRIMARY_BLACK; display: block; padding-left: 0; text-align: center; line-height: 110px; } &.is-checked { background-color: #22222229; } } } PAMapp/assets/scss/vendors/elementUI/_drawer.scss
¤ñ¹ï·sÀÉ®× @@ -0,0 +1,11 @@ .el-drawer { border-radius: 10px 10px 0 0; .el-drawer__header { display: none; } .el-drawer__body { padding: 0 40px; } } PAMapp/assets/scss/vendors/elementUI/_radio.scss
¤ñ¹ï·sÀÉ®× @@ -0,0 +1,31 @@ .pam-quickFilter-radio.el-radio-group { display: flex; justify-content: space-between; width: 100%; .el-radio { display: block; width: 48%; height: 110px; margin-right: 0px; box-shadow: 0 0 6px #22222229; border-radius: 10px; .el-radio__input { display: none; } .el-radio__label { text-align: center; color: $PRIMARY_BLACK; display: block; line-height: 110px; padding-left: 0; } &.is-checked { background-color: #22222229; } } } PAMapp/assets/scss/vendors/elementUI/_rate.scss
¤ñ¹ï·sÀÉ®× @@ -0,0 +1,15 @@ .pam-quickFilter-rate { height: auto; margin-top: 30px; display: flex; justify-content: center; .el-rate__item { .el-rate__icon { font-size: 35px; } .el-icon-star-off { color: $PRIMARY_BLACK !important; } } } PAMapp/assets/scss/vendors/elementUI/_tag.scss
¤ñ¹ï·sÀÉ®× @@ -0,0 +1,18 @@ .pam-tag.el-tag--light { padding: 10px 20px; background-color: $CORAL; border: solid 1px $LIGHT_GREY; height: auto; color: $PRIMARY_WHITE; border-radius: 30px; margin-right: 10px; margin-top: 10px; .el-icon-close { color: $PRIMARY_WHITE; &:hover { background-color: $CORAL; } } } PAMapp/components/QuickFilter/QuickFilterConsultantCarousel.vue
¤ñ¹ï·sÀÉ®× @@ -0,0 +1,187 @@ <template> <div class="relative"> <el-carousel height="600px" :autoplay="false" indicator-position="none" arrow="never" class="pam-consultant-carousel" ref="carouselRef" > <el-carousel-item v-for="(item, index) in 5" :key="index" > <div class="fill" @touchstart="touchStart" @touchend="moveCard" > <img class="avator cursor--pointer" @click="$router.push('/agentInfo')" src="" /> <div class="mdTxt mt-30 mb-10">è¡ç¾è(伯æ¨ä¿éªç¶ç´äºº)</div> <el-row> <el-col :span="12"> <div class="smTxt_bold mb-10 text--prudential_grey">æåè³æ·</div> <div class="mb-10">ä¸å¹´12åæ</div> </el-col> <el-col :span="12"> <div class="smTxt_bold mb-10 text--prudential_grey">å®¢æ¶æ»¿æåº¦</div> <div> <i class="icon-star pam-icon"></i> 4.8</div> </el-col> </el-row> <div class="smTxt_bold mb-10 text--prudential_grey">å°é·é å</div> <div class="p bold">#財åè¦å</div> </div> <div class="parallelBtns"> <el-button @click="isVisibleDrawer = true"> <i class="icon-add smTxt"></i> <span>顧忏 å®</span> </el-button> <el-button @click="$router.push('/communication/myDemand')" type="primary" >é²è¡é ç´</el-button> </div> </el-carousel-item> </el-carousel> <div class="absolute arrow-left-position" @click="nextCard"> <i class="icon-left pam-left-arrow"></i> </div> <div class="absolute arrow-right-position" @click="nextCard"> <i class="icon-right pam-right-arrow"></i> </div> <Ui-Drawer :isVisible.sync="isVisibleDrawer" > <div class="text--center mdTxt"> <p class="mb-50">æåå å ¥é¡§åæ¸ å®</p> <p class="text--primary" @click="isVisibleDrawer = false">æç¥éäº</p> </div> </Ui-Drawer> </div> </template> <script lang="ts"> import { ElCarousel } from 'element-ui/types/carousel'; import { Vue, Component, Prop } from 'vue-property-decorator'; @Component export default class UiCardCarousel extends Vue { isVisibleDrawer = false; startPosition = 0; endPosition = 0; touchStart(event: TouchEvent) { this.startPosition = event.changedTouches[0].clientX; } moveCard(event: any) { this.endPosition = event.changedTouches[0].clientX; if (this.endPosition < this.startPosition) { this.nextCard(); return; } if (this.endPosition > this.startPosition) { this.prevCard(); return; } } nextCard() { (this.$refs.carouselRef as ElCarousel).next(); } prevCard() { (this.$refs.carouselRef as ElCarousel).prev(); } } </script> <style lang="scss" scoped> .fill { display: flex; flex-direction: column; justify-content: center; align-content: center; padding: 20px 30px 30px 30px; } .avator { width: 200px; height: 200px; border-radius: 50%; background-color: $MID_GREY; margin: 0 auto; } .parallelBtns { display: flex; justify-content: center; position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%); width: 100%; .el-button { padding: 10px 0; width: 45%; } } .pam-left-arrow,.pam-right-arrow { display: inline-block; width: 50px; height: 50px; border-radius: 50px; background-color: $LIGHT_GREY; color: $CORAL; z-index: 2; cursor: pointer; &:before { display: block; line-height: 50px; } } .pam-right-arrow { &:before { margin-left: 15px; } } .pam-left-arrow { &:before { margin-left: 25px; } } .arrow-right-position { top: 50%; right: -60px; transform: translateY(-50%); } .arrow-left-position { top: 50%; left: -60px; transform: translateY(-50%); } .relative { position: relative; } .absolute { position: absolute; } </style> PAMapp/components/QuickFilter/QuickFilterDrawer.vue
¤ñ¹ï·sÀÉ®× @@ -0,0 +1,122 @@ <template> <Ui-Drawer :isVisible.sync="isVisible" :size="questionOption.name === 'style' ? '50%' : '30%'" @close="closeDrawer" > <div class="mb-10" v-if="questionOption.title !== 'é¡§åæ§å¥'"> <span class="mdTxt">{{questionOption.title === 'é¡§åæ»¿æåº¦' ? 'ä¿éªé¡§å滿æåº¦' : questionOption.title}}</span> <span class="smTxt_bold text--primary" v-if="questionOption.name === 'style'" >å¯è¤é¸</span> <span class="smTxt_bold text--primary" v-if="questionOption.name === 'satisfaction'" >é¸åææ</span> </div> <div class="quickBtnBlock" v-if="questionOption.name === 'style'"> <el-checkbox-group class="pam-quickFilter-checkbox" v-model="style"> <el-checkbox v-for="(i, index) in questionOption.detail" :key="index" :label="i" :name="i" ></el-checkbox> </el-checkbox-group> </div> <div class="quickBtnBlock" v-else-if="questionOption.name === 'gender'"> <el-radio-group class="pam-quickFilter-radio" v-model="gender"> <el-radio v-for="(i, index) in questionOption.detail" :key="index" :label="i"></el-radio> </el-radio-group> </div> <div class="quickBtnBlock" v-else-if="questionOption.name === 'loginState'"> <el-radio-group class="pam-quickFilter-radio" v-model="loginState"> <el-radio v-for="(i, index) in QuestionOption.detail" :key="index" :label="i"></el-radio> </el-radio-group> </div> <div v-else> <el-rate class="pam-quickFilter-rate" v-model="satisfaction"></el-rate> </div> </Ui-Drawer> </template> <script lang="ts"> import { Vue, Component, PropSync, Prop, Watch, Emit } from 'nuxt-property-decorator'; import { QuestionOption, selectedItem } from '~/pages/quickFilter/index.vue'; @Component export default class QuickFilterDrawer extends Vue { style: string[] = []; loginState: string = ''; gender: string = ''; satisfaction: number = 0; @PropSync('drawerVisible') isVisible!: boolean; @Prop() selectedItem!: selectedItem; @Prop() questionOption!: QuestionOption; @Emit('selected') emitSelected() { return ({ name: this.questionOption.name, gender: this.gender, style: this.style, satisfaction: this.satisfaction, loginState: this.loginState }); } closeDrawer() { this.emitSelected() } @Watch('selectedItem', {deep: true, immediate: true}) watchSelected(newValue: selectedItem) { if (newValue) { this.gender = newValue.gender; this.style = newValue.style; this.satisfaction = newValue.satisfaction; } } } </script> <style lang="scss" scoped> .quickBtnBlock { display: flex; justify-content: space-between; align-content: space-between; flex-wrap: wrap; .quickBtn { width: 48%; height: 110px; text-align: center; box-shadow: 0 0 6px #22222229; padding: auto 0 auto 0; border-radius: 10px; color: $PRIMARY_BLACK; &:hover,&:focus { color: $PRIMARY_BLACK; border-color: $PRIMARY_WHITE; background-color: $PRIMARY_WHITE; } } .quickBtn+.quickBtn { margin-left: 0; } } </style> PAMapp/components/Ui/UiCardCarousel.vue
Àɮפw§R°£ PAMapp/components/Ui/UiDrawer.vue
¤ñ¹ï·sÀÉ®× @@ -0,0 +1,42 @@ <template> <div> <el-drawer :size="size" :visible.sync="drawerVisible" :direction="'btt'" @close="close" class="cus_drawer" > <div class="close" @click="drawerVisible = false"></div> <slot></slot> </el-drawer> </div> </template> <script lang="ts"> import { Vue, Component, PropSync, Prop, Emit } from 'vue-property-decorator'; @Component export default class UiDialog extends Vue { @PropSync('isVisible') drawerVisible!: boolean; @Prop() size!: number; @Emit('close') closeDrawer() { return; } close() { this.closeDrawer(); } } </script> <style lang="scss" scoped> .close { width: 60px; height: 5px; background-color: #CCCCCC; border-radius: 10px; margin: 10px auto 13px auto; } </style> PAMapp/layouts/default.vue
@@ -18,6 +18,7 @@ .page-container{ width: 700px; margin: 0 auto; overflow-x: hidden; } } PAMapp/pages/quickFilter/index.vue
@@ -1,7 +1,240 @@ <template> <div>å¿«éç¯©é¸ <h5>ç¯©é¸æ¢ä»¶</h5> <h5>å¿«éç¯©é¸æ¨è¦</h5> <Ui-CardCarousel></Ui-CardCarousel> <div> <div class="quickBtnBlock"> <el-button v-for="(question, index) in questionList" :key="index" class="subTitle quickBtn" :disabled="question.name === 'onlineState'" @click="openDrawer(question)" >{{question.title}}</el-button> </div> <h5 class="mdTxt mb-10 mt-30">ç¯©é¸æ¢ä»¶</h5> <div> <el-tag v-if="selectedItem.gender" class="pam-tag p" closable type="''" @close="removeTag('gender')" >{{selectedItem.gender}}</el-tag> <el-tag v-if="selectedItem.satisfaction" class="pam-tag p" closable type="''" @close="removeTag('satisfaction')" >{{selectedItem.satisfaction + 'æä»¥ä¸æ»¿æåº¦'}}</el-tag> <template v-if="selectedItem.style.length > 0" > <el-tag v-for="(item, index) in selectedItem.style" :key="index" class="pam-tag p" closable type="''" @close="removeTag('style', index)" >{{item}}</el-tag> </template> <div class="mb-10" v-if="selectedItem.onlineState"></div> <div class="emptyBox text--mid_grey" v-if="!selectedItem.gender && !selectedItem.satisfaction && selectedItem.style.length === 0 && !selectedItem.onlineState"> <p class="smTxt">å°ç¡ç¯©é¸</p> </div> </div> <h5 class="mdTxt mb-10 mt-30">å¿«éç¯©é¸æ¨è¦</h5> <template v-if="consultantList.length > 0"> <QuickFilterConsultantCarousel></QuickFilterConsultantCarousel> </template> <template v-else> <div class="emptyBox bg-white"></div> </template> <QuickFilterDrawer :drawerVisible.sync="questionDrawer" :questionOption="questionOption" :selectedItem="selectedItem" @selected="selected" ></QuickFilterDrawer> </div> </template> </template> <script lang="ts"> import { Context } from '@nuxt/types'; import { Vue, Component } from 'nuxt-property-decorator'; import { Agents } from '~/plugins/api/home'; @Component export default class QuickFilter extends Vue { consultantList = []; questionDrawer = false; questionOption = {}; selectedItem: selectedItem = { gender: '', satisfaction: 0, style: [], onlineState: '' }; questionList: QuestionOption[] = [ { name: 'gender', title: 'é¡§åæ§å¥', detail: ['ç·æ§', '女æ§'], type: 'radio' }, { name: 'satisfaction', title: 'é¡§åæ»¿æåº¦', detail: [], type: '' }, { name: 'style', title: 'æºéé¢¨æ ¼', detail: ['謹æ å實', 'æå¿«ä¸»å', 'èå¿å¾è½', 'å¥è«é¢¨è¶£'], type: 'checkbox' }, { name: 'onlineState', title: 'ä¸ç·çæ ', detail: [], type: 'radio' } ]; async asyncData(context: Context) { let consultantList: Agents[] = []; await context.$service.home.recommendConsultantList().then((result: Agents[]) => { consultantList = result; }) return { consultantList, } } openDrawer(question: QuestionOption) { this.questionDrawer = true; this.questionOption = question; } selected(event: selectedItem) { const name = event.name; if (name === 'gender') { this.selectedItem.gender = event.gender; } if (name === 'satisfaction') { this.selectedItem.satisfaction = event.satisfaction; } if (name === 'style'){ this.selectedItem.style = event.style; } } removeTag(type: string, index: number = 0) { if (type === 'gender') { this.selectedItem.gender = '' } if (type === 'satisfaction') { this.selectedItem.satisfaction = 0 } if (type === 'style') { this.selectedItem.style.splice(index, 1) } } } export interface QuestionOption { title: string; detail: string[]; type: string; name: string; } export interface selectedItem { name?: string; gender: string; satisfaction: number; style: string[]; onlineState: string; } </script> <style lang="scss" scoped> .emptyBox { width: 100%; height: 100px; border: solid 1px $LIGHT_GREY; text-align: center; .smTxt { line-height: 100px; } } .bg-white { 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-color: $PRIMARY_WHITE; border-radius: 10px; color: $PRIMARY_BLACK; &:hover,&:focus { color: $PRIMARY_BLACK; border-color: $PRIMARY_WHITE; background-color: $PRIMARY_WHITE; } &:disabled { color: $PRIMARY_WHITE; border-color: $LIGHT_GREY; background-color: $LIGHT_GREY; } } .quickBtn+.quickBtn { margin-left: 0; } .is-disabled { background-color: $LIGHT_GREY; color: $PRIMARY_WHITE; &:hover,&:focus { color: $PRIMARY_WHITE; border-color: $LIGHT_GREY; background-color: $LIGHT_GREY; } } } </style>