保誠-保戶業務員媒合平台
Mila
2021-11-11 a8e5dcd396b2934e0abdd97e2241bd020afe569b
TODO#130018 [加入顧問] API 串接
修改8個檔案
新增2個檔案
257 ■■■■■ 已變更過的檔案
PAMapp/assets/ts/api/consultant.ts 4 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/ts/storageConsultant.ts 10 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/AddAndReservedBtns.vue 61 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/Consultant/ConsultantCard.vue 8 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/Consultant/ConsultantList.vue 12 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/QuickFilter/QuickFilterConsultantList.vue 86 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/components/QuickFilter/QuickFilterSelector.vue 4 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/pages/index.vue 30 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/pages/myConsultantList.vue 8 ●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/pages/quickFilter/index.vue 34 ●●●●● 修補檔 | 檢視 | 原始 | 究查 | 歷程
PAMapp/assets/ts/api/consultant.ts
@@ -56,11 +56,11 @@
// åŠ å…¥é¡§å•
export function addFavoriteConsultant(agentNoList: string[]) {
    return service.post('/consultant/favorite', agentNoList)
    return service.post('/consultant/favorite', {agentNoList})
}
export interface Consultants {
    agentNo: number,
    agentNo: string,
    name: string,
    img: string,
    new: boolean,
PAMapp/assets/ts/storageConsultant.ts
¤ñ¹ï·sÀÉ®×
@@ -0,0 +1,10 @@
import { Consultants } from "./api/consultant";
export function getFavoriteFromStorage(): Consultants[] {
    const consultantList = localStorage.getItem('favoriteConsultant');
    return consultantList ? JSON.parse(consultantList) : [];
}
export function setFavoriteToStorage(consultants: Consultants[]) {
    localStorage.setItem('favoriteConsultant', JSON.stringify(consultants));
}
PAMapp/components/AddAndReservedBtns.vue
¤ñ¹ï·sÀÉ®×
@@ -0,0 +1,61 @@
<template>
    <el-row type="flex" justify="center" :class="cusClass">
        <el-button @click="addConsultant(agentInfo)">
            <span> + é¡§å•æ¸…å–®</span>
        </el-button>
        <el-button
            @click="reserveCommunication"
            type="primary"
        >進行預約</el-button>
    </el-row>
</template>
<script lang="ts">
import { Vue, Component, Prop, Emit } from 'nuxt-property-decorator';
import { addFavoriteConsultant, Consultants } from '~/assets/ts/api/consultant';
import { isLogin } from '~/assets/ts/auth';
import { getFavoriteFromStorage, setFavoriteToStorage } from '~/assets/ts/storageConsultant';
@Component
export default class AddAndReservedBtns extends Vue {
    @Prop() agentInfo!: Consultants;
    @Prop() cusClass!: string;
    isVisiblePopUp = false;
    addConsultant(item: Consultants) {
        console.log('click')
        if (isLogin()) {
            addFavoriteConsultant([item.agentNo]).then(res => this.openPopUp())
        } else {
            this.addConsultantToStorage(item);
        }
    }
    addConsultantToStorage(item: Consultants) {
        let agentList = [item];
        const consultantList = getFavoriteFromStorage();
        if (consultantList) {
            const isRepeat = consultantList.findIndex(i => i.agentNo === item.agentNo) === -1;
            isRepeat
                ? this.storageFavoriteAndPopUp(consultantList.concat(agentList))
                : this.openPopUp('已經加入顧問清單');
        } else {
            this.storageFavoriteAndPopUp(agentList);
        }
    }
    storageFavoriteAndPopUp(item: Consultants[]) {
        setFavoriteToStorage(item);
        this.openPopUp();
    }
    reserveCommunication() {
        isLogin() ? this.$router.push('/questionnaire') : this.$router.push('/login');
    }
    @Emit('openPopUp') openPopUp(popUpTxt: string = '成功加入顧問清單') {
        return popUpTxt
    }
}
</script>
PAMapp/components/Consultant/ConsultantCard.vue
@@ -27,7 +27,8 @@
                        </div>
                        <div
                            class="delete"
                            v-if="agentInfo.contactStatus === 'picked'"
                            v-if="agentInfo.contactStatus !== 'reserved'
                                || agentInfo.contactStatus !== 'contacted'"
                            @click="removeAgent"
                        >移除</div>
                    </el-col>
@@ -92,11 +93,12 @@
        let date = newDate.getDate();
        let hours = newDate.getHours();
        let minutes = newDate.getMinutes();
        return `${year}/${month}/${date} ${hours} : ${minutes}`
        return isLogin() ? `${year}/${month}/${date} ${hours} : ${minutes}` : ''
    }
    reserveCommunication() {
        if (this.agentInfo.contactStatus === 'picked') {
        const contactStatus = this.agentInfo.contactStatus;
        if (contactStatus !== 'reserved' && contactStatus !== 'contacted') {
            isLogin() ? this.$router.push('/questionnaire') : this.$router.push('/login');
        } else {
            this.width = isMobileDevice() ? '80%' : '';
PAMapp/components/Consultant/ConsultantList.vue
@@ -8,17 +8,17 @@
                @removeAgent="removeAgent"
            ></ConsultantCard>
        </template>
        <template v-else-if="!isLogin && agents.length === 0">
            <div class="emptyRowStyle">
                <div class="mdTxt login" @click="$router.push('/login')">登入</div>
                <div class="smTxt txt">查看更多已選顧問</div>
            </div>
        </template>
        <template v-else>
            <div class="emptyRowStyle">
                <div class="smTxt txt">您目前無已選顧問</div>
            </div>
        </template>
        <template v-if="!isLogin && agents.length > 0">
            <div class="emptyRowStyle">
                <div class="mdTxt login" @click="$router.push('/login')">登入</div>
                <div class="smTxt txt">查看更多</div>
            </div>
        </template>
    </div>
</template>
PAMapp/components/QuickFilter/QuickFilterConsultantList.vue
@@ -9,7 +9,7 @@
        ref="carouselRef"
    >
        <el-carousel-item
            v-for="(item, index) in 5"
            v-for="(item, index) in consultantList"
            :key="index"
        >
            <div
@@ -21,79 +21,69 @@
                    :size="200"
                    class="mx-auto cursor--pointer"
                    @click="$router.push('/agentInfo')"
                    src=""
                    :src="item.img"
                />
                <div class="mdTxt mt-30 mb-10 text--center">蔡美莓(伯樂保險經紀人)</div>
                <div class="mdTxt mt-30 mb-30 text--center">{{item.name}}(伯樂保險經紀人)</div>
                <el-row>
                    <el-col :span="12">
                        <div class="smTxt_bold mb-10 text--prudential_grey">服務資歷</div>
                        <div class="mb-10">一年12個月</div>
                        <div class="mb-10">{{item.seniority}}</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>
                            <i class="icon-star pam-icon icon--yellow "></i>
                            {{item.avgScore}}</div>
                    </el-col>
                </el-row>
                <div class="smTxt_bold mb-10 text--prudential_grey">專長領域</div>
                <div class="p bold">#財務規劃</div>
            </div>
            <div class="fixedBtn text--center">
                <el-button @click="addConsultant">
                    <i class="icon-add smTxt"></i>
                    <span>顧問清單</span>
                </el-button>
                <el-button
                    @click="reserveCommunication"
                    type="primary"
                >進行預約</el-button>
                <div class="smTxt_bold mt-10 mb-10 text--prudential_grey">專長領域</div>
                <div>
                    <span
                        v-for="(i, index) in item.expertise"
                        :key="index"
                        class="p bold mr-30 mb-10 inline-block"
                    >#{{i}}</span>
                </div>
                <AddAndReservedBtns
                    :cusClass="'fixedBtn'"
                    :agentInfo="item"
                    @openPopUp="openPopUp"
                ></AddAndReservedBtns>
            </div>
        </el-carousel-item>
    </el-carousel>
    <div class="absolute arrow-left-position" @click="nextCard">
    <div class="absolute arrow-left-position" @click="prevCard">
        <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"
    <PopUpFrame :isOpen.sync="isVisiblePopUp"
    >
        <div class="text--center mdTxt">
            <p class="mb-50">成功加入顧問清單</p>
            <p class="mb-50">{{popUpTxt}}</p>
            <p class="text--primary cursor--pointer"
                @click="isVisibleDrawer = false">我知道了</p>
                @click="isVisiblePopUp = false">我知道了</p>
        </div>
    </Ui-Drawer>
    <Ui-Dialog
        :isVisible.sync="isVisibleDialog"
    >
        <div class="text--center mdTxt">
            <p class="mb-50">成功加入顧問清單</p>
            <p class="text--primary cursor--pointer"
                @click="isVisibleDialog = false">我知道了</p>
        </div>
    </Ui-Dialog>
    </PopUpFrame>
</div>
</template>
<script lang="ts">
import { ElCarousel } from 'element-ui/types/carousel';
import { Vue, Component } from 'vue-property-decorator';
import { isLogin } from '~/assets/ts/auth';
import { isMobileDevice } from '~/assets/ts/device';
import { Vue, Component, Prop } from 'vue-property-decorator';
import { Consultants } from '~/assets/ts/api/consultant';
@Component
export default class QuickFilterConsultantList extends Vue {
    isVisibleDrawer = false;
    isVisibleDialog = false;
    @Prop() consultantList!: Consultants[];
    isVisiblePopUp = false;
    startPosition = 0;
    endPosition = 0;
    popUpTxt = '成功加入顧問清單';
    touchStart(event: TouchEvent) {
        this.startPosition = event.changedTouches[0].clientX;
@@ -103,12 +93,10 @@
        this.endPosition = event.changedTouches[0].clientX;
        if (this.endPosition < this.startPosition) {
            this.nextCard();
            return;
        }
        if (this.endPosition > this.startPosition) {
            this.prevCard();
            return;
        }
    }
@@ -120,14 +108,9 @@
        (this.$refs.carouselRef as ElCarousel).prev();
    }
    addConsultant() {
        isMobileDevice()
            ? this.isVisibleDrawer = true
            : this.isVisibleDialog = true;
    }
    reserveCommunication() {
        isLogin() ? this.$router.push('/questionnaire') : this.$router.push('/login');
    openPopUp(txt: string) {
        this.popUpTxt = txt;
        this.isVisiblePopUp = true;
    }
@@ -152,7 +135,6 @@
        bottom: 30px;
        left: 50%;
        transform: translateX(-50%);
        width: 100%;
    }
    .pam-left-arrow,.pam-right-arrow {
@@ -203,6 +185,10 @@
        position: absolute;
    }
    .inline-block {
        display: inline-block;
    }
    @media (min-width: 768px) {
        .relative {
            overflow: hidden;
PAMapp/components/QuickFilter/QuickFilterSelector.vue
@@ -69,10 +69,6 @@
        avgScore: 0
    }
    mounted() {
        console.log(this.questionOption, 'questionOption')
    }
    @PropSync('drawerVisible') isVisible!: boolean;
    @Prop() selectedItem!: FastQueryParams;
    @Prop() questionOption!: QuestionOption;
PAMapp/pages/index.vue
@@ -22,7 +22,10 @@
                    <span class="mdTxt">我的顧問清單</span>
                    <span class="smTxt_bold amount">共 {{consultantList.length}} ç­†</span>
                </el-col>
                <el-col :span="8" class="mdTxt readMore"
                <el-col
                    :span="8"
                    class="mdTxt readMore"
                    v-if="consultantList.length > 3"
                    @click.native="routerPush('/myConsultantList/consultantList')">查看更多</el-col>
            </el-row>
            <ConsultantList
@@ -40,8 +43,9 @@
<script lang="ts">
import { Vue, Component, State, Action } from 'nuxt-property-decorator';
import { Consultants } from '~/assets/ts/api/consultant';
import { login, recommend, getFavoriteConsultant } from '~/assets/ts/api/consultant';
import { getFavoriteFromStorage, setFavoriteToStorage } from '~/assets/ts/storageConsultant';
import { addFavoriteConsultant, Consultants } from '~/assets/ts/api/consultant';
import { login, getFavoriteConsultant } from '~/assets/ts/api/consultant';
import { isLogin } from '~/assets/ts/auth';
@Component({
@@ -54,26 +58,38 @@
    @Action storeRecommendList!: any;
    mounted() {
        if (!this.recommendList) {
            this.storeRecommendList();
        }
        if (isLogin()) {
            this.addFavoriteFromStorageToApi();
            getFavoriteConsultant().then((response) => this.consultantList = response.data);
        } else {
            this.consultantList = getFavoriteFromStorage();
        }
    }
    addFavoriteFromStorageToApi() {
        const agentNoList = getFavoriteFromStorage().map(i => i.agentNo)
        if (agentNoList.length > 0) {
            addFavoriteConsultant(agentNoList).then(res => res);
            localStorage.removeItem('favoriteConsultant');
        }
    }
    routerPush(path: string) {
        this.$router.push(path);
    }
    removeAgent(agentNo: number) {
    removeAgent(agentNo: string) {
        const findIndex = this.consultantList.findIndex((item, i) => {
            return item.agentNo === agentNo;
        })
        this.consultantList.splice(findIndex, 1)
        this.consultantList.splice(findIndex, 1);
        if (!isLogin()) {
            setFavoriteToStorage(this.consultantList)
        }
    }
    // TODO: åƒ…OTP認證開發前 æš«æ™‚使用
@@ -90,7 +106,7 @@
    // TODO: åƒ…OTP認證開發前 æš«æ™‚使用
    remove() {
        localStorage.clear();
        localStorage.removeItem('id_token');
        this.$router.go(0)
    }
PAMapp/pages/myConsultantList.vue
@@ -29,6 +29,7 @@
import { Context } from '@nuxt/types';
import { Vue, Component, Watch } from 'vue-property-decorator';
import { Route } from 'vue-router/types/router.d'
import { getFavoriteFromStorage, setFavoriteToStorage } from '~/assets/ts/storageConsultant';
import { Consultants, getFavoriteConsultant } from '~/assets/ts/api/consultant';
import { isLogin } from '~/assets/ts/auth';
@@ -51,6 +52,8 @@
        if (isLogin()) {
            await getFavoriteConsultant().then((response) => agents = response.data);
        } else {
            agents = getFavoriteFromStorage();
        }
        contactedList = agents.filter(item => item.contactStatus === 'contacted');
@@ -63,9 +66,12 @@
        }
    }
    removeAgent(agentNo: number) {
    removeAgent(agentNo: string) {
        const fintIndex = this.consultantList.findIndex(item => item.agentNo === agentNo);
        this.consultantList.splice(fintIndex, 1);
        if (!isLogin()) {
            setFavoriteToStorage(this.consultantList);
        }
    }
    @Watch('$route') watchRouter(currentRoute: Route) {
PAMapp/pages/quickFilter/index.vue
@@ -48,7 +48,7 @@
            <img class="img" src="~/assets/images/quickFilter/recommend.svg" alt="">
            <template v-if="consultantList.length > 0">
                <QuickFilterConsultantList></QuickFilterConsultantList>
                <QuickFilterConsultantList :consultantList="consultantList"></QuickFilterConsultantList>
            </template>
            <template v-else>
@@ -58,44 +58,32 @@
            </template>
        </div>
        <Ui-Drawer
            :isVisible.sync="questionDrawer"
            :size="questionOption.name === 'communicationStyles' ? '50%' : '30%'"
            @closeDrawer="closePopUp"
        <PopUpFrame
            :isOpen.sync="questionPopUp"
            :drawerSize="questionOption.name === 'communicationStyles' ? '50%' : '30%'"
            @update:isOpen="closePopUp"
        >
            <QuickFilterSelector
                ref="quickFilterRef"
                :drawerVisible.sync="questionDrawer"
                :drawerVisible.sync="questionPopUp"
                :questionOption="questionOption"
                :selectedItem="selectedItem"
            ></QuickFilterSelector>
        </Ui-Drawer>
        </PopUpFrame>
        <Ui-Dialog :isVisible.sync="questionDialog"
            @closeDialog="closePopUp"
        >
            <QuickFilterSelector
                ref="quickFilterRef"
                :drawerVisible.sync="questionDrawer"
                :questionOption="questionOption"
                :selectedItem="selectedItem"
            ></QuickFilterSelector>
        </Ui-Dialog>
    </div>
</template>
<script lang="ts">
import { Vue, Component } from 'nuxt-property-decorator';
import { FastQueryParams } from '~/assets/ts/api/consultant';
import { isMobileDevice } from '~/assets/ts/device';
import { Consultants, FastQueryParams } from '~/assets/ts/api/consultant';
import QuickFilterDrawer from '~/components/QuickFilter/QuickFilterSelector.vue';
import { fastQuery } from '~/assets/ts/api/consultant';
@Component
export default class QuickFilter extends Vue {
    questionDialog = false;
    consultantList = [];
    questionDrawer = false;
    questionPopUp = false;
    consultantList: Consultants[] = [];
    questionOption = {};
    selectedItem: FastQueryParams = {
        gender: '',
@@ -147,7 +135,7 @@
    openPopUp(question: QuestionOption) {
        this.questionOption = question;
        isMobileDevice() ? this.questionDrawer = true : this.questionDialog = true;
        this.questionPopUp =true;
    }
    removeTag(type: string, index: number = 0) {