保誠-保戶業務員媒合平台
Mila
2021-11-01 d4a535ae7dd07f70cf2f59fbc8256a3fa1df8c93
TODO#129053 快速篩選 畫面刻版
刪除1個檔案
修改6個檔案
新增9個檔案
876 ■■■■ 已變更過的檔案
PAMapp/assets/scss/_common.scss 30 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/scss/utilities/_heading.scss 12 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/scss/utilities/_utilities.scss 4 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/scss/vendors/_elementUI.scss 6 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/scss/vendors/elementUI/_carousel.scss 44 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/scss/vendors/elementUI/_checkbox.scss 33 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/scss/vendors/elementUI/_drawer.scss 11 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/scss/vendors/elementUI/_radio.scss 31 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/scss/vendors/elementUI/_rate.scss 15 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/scss/vendors/elementUI/_tag.scss 18 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/QuickFilter/QuickFilterConsultantCarousel.vue 187 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/QuickFilter/QuickFilterDrawer.vue 122 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/Ui/UiCardCarousel.vue 77 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/Ui/UiDrawer.vue 42 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/layouts/default.vue 1 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/pages/quickFilter/index.vue 243 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
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>