Pārlūkot izejas kodu

预约待办 添加日历和预约登记页面

lm 1 mēnesi atpakaļ
vecāks
revīzija
3499973737

BIN
src/assets/clientManage/next_btn.png


BIN
src/assets/clientManage/pre_btn.png


BIN
src/assets/clientManage/school.png


+ 126 - 0
src/baseComponents/Calendar.vue

@@ -0,0 +1,126 @@
+<template>
+    <div>
+        <el-calendar  v-model="selectedCalendarTime"  ref="calendar">
+            <!-- 自定义日历头 -->
+            <template #header="{ date }">
+                    <img :src="preBtnIcon" alt="" @click="selectDate('prev-month')">
+                    <span>{{ date }}</span>
+                    <img :src="nextBtnIcon" alt=""  @click="selectDate('next-month')">
+            </template>
+
+            <!-- 自定义日期单元格 -->
+                <template #date-cell="{ data}">
+                <!--  -->
+                <span class="has_things">
+                    {{ data.day.split('-').pop() }}
+                </span>
+            </template>
+        </el-calendar>
+    </div>
+</template>
+
+<script setup lang="ts">
+import { ref } from 'vue';
+import preBtnIcon from '@/assets/clientManage/pre_btn.png'
+import nextBtnIcon from '@/assets/clientManage/next_btn.png'
+
+
+// 日历信息
+const selectedCalendarTime = defineModel('selectedCalendarTime')
+const calendar = ref()
+const selectDate = (val) => {
+  if (!calendar.value) return
+  calendar.value.selectDate(val)
+}
+
+</script>
+
+
+<style lang="scss" scoped>
+:deep(.el-calendar){
+    .el-calendar__header{
+        padding:0;
+        border: none;
+        align-items: center;
+        font-weight: 600;
+        font-size: 16px;
+        color: #333333;
+        line-height: 20px;
+        img{
+            width: 24px;
+            height: 24px;
+        }
+    }
+
+    .el-calendar__body{
+        padding:24px 0 8px 0;
+        border-bottom: 1px solid #F3F3F3;
+        font-size: 14px;
+        .el-calendar-table{
+            tr td{
+                border:none;
+                &.is-today{
+                    color: #2E64FA;
+                }
+                &.prev .el-calendar-day span.has_things{
+                    &::after{
+                        background-color: #a8abb2;
+                    }
+                }
+                &.is-selected{
+                    background-color: transparent;
+                    .el-calendar-day{
+                        span{
+                            background-color: #2E64FA;
+                            color: #FFFFFF;
+                            &:hover{
+                                background-color: #2E64FA;
+                            }
+
+                            &.has_things::after{
+                                    background-color: #fff;
+                            }
+                        }
+                    }
+                }
+                .el-calendar-day{
+                    display: flex;
+                    justify-content: center;
+                    align-items: center;
+                    height: 48px;
+                    padding:0;
+                    &:hover{
+                        background-color: transparent;
+                    }
+                    span{
+                        display: flex;
+                        justify-content: center;
+                        align-items: center;
+                        line-height: 1;
+                        width: 40px;
+                        height: 40px;
+                        border-radius: 50%;
+
+                        &.has_things{
+                            position: relative;
+                            &::after{
+                                position: absolute;
+                                bottom: 3px;
+                                content: '';
+                                display: block;
+                                width: 4px;
+                                height: 4px;
+                                border-radius: 50%;
+                                background-color: #2E64FA;
+                            }
+                        }
+                        &:hover{
+                            background-color: rgba(46, 100, 250,0.1);
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+</style>

+ 99 - 0
src/baseComponents/TimeNavLine.vue

@@ -0,0 +1,99 @@
+<template>
+    <div class="time_nav_line">
+        <div class="time_point">
+            <span class="time">{{navTime}}</span>
+            <span class="time_desc">{{timeDesc}}</span>
+        </div>
+        <div class="nav_line">
+            <div class="point" v-if="!navIcon"></div>
+            <img class="custom_icon" :src="navIcon" v-else alt="">
+            <div v-if="!isLast" class="line"></div>
+        </div>
+        <div class="nav_content">
+            <slot name="navContent">
+                {{ navContent }}
+            </slot>
+        </div>
+    </div>
+</template>
+
+<script setup lang="ts">
+
+const props = defineProps({
+    navIcon:null,
+    navTime:{
+        type:String,
+        default:'时间点'
+    },
+    timeDesc:{
+        type:String,
+        default:'时间说明'
+    },
+    navContent:{
+        type:String,
+        default:'导航内容'
+    },
+    isLast:{
+        type:Boolean,
+        default:false,
+    }
+})
+
+</script>
+
+
+<style lang="scss" scoped>
+.time_nav_line{
+    display: flex;
+    align-items:flex-start;
+    gap:10px;
+    .time_point{
+        display: flex;
+        flex-direction: column;
+        .time{
+            line-height: 22px;
+            font-weight: 600;
+            font-size: 16px;
+            color: #333333;
+        }
+        .time_desc{
+            line-height: 17px;
+            font-weight: 400;
+            font-size: 12px;
+            color: #2E64FA;
+        }
+
+    }
+    .nav_line{
+        align-self: stretch;
+        display: flex;
+        flex-direction: column;
+        align-items: center;
+        position: relative;
+        .point{
+            width: 5px;
+            height: 5px;
+            background-color: #efefef;
+            border-radius: 50%;
+            flex-grow: 0 !important;
+            flex-shrink: 0 !important;
+        }
+        .custom_icon{
+            width: 20px;
+            height: 20px;
+            border-radius: 50%;
+            background-color: #efefef;
+            flex-grow: 0 !important;
+            flex-shrink: 0 !important;
+        }
+        .line{
+            flex:1 1;
+            border-left:dashed #efefef 2px;
+        }
+    }
+    .nav_content{
+        flex: 1 1;
+        margin-bottom: 30px;
+    }
+}
+</style>

+ 10 - 0
src/views/appointmentAndTodo/formSearchGroup.ts

@@ -0,0 +1,10 @@
+import { ref } from 'vue'
+
+export const formSearchList = ref([
+    {
+        key:'queryStr',
+        type:'input',
+        placeholder:'请输入关键字搜索',
+        defaultValue:'',
+    }
+])

+ 212 - 2
src/views/appointmentAndTodo/index.vue

@@ -1,15 +1,225 @@
 <template>
-    <div>
-        预约待办
+    <div class="main_container">
+        <div class="calendar" >
+            <Calendar v-model:selectedCalendarTime="selectedCalendarTime"></Calendar>
+             <div class="calendar_desc"> 
+                <div class="calendar_desc_title">
+                    <span class="date_desc">7月预约</span>
+                    <span class="total_count">共20条</span>
+                </div>
+                <div class="calendar_desc_content">
+                    <div class="active">
+                        <span class="num">10</span>
+                        <span>待开始</span>
+                    </div>
+                    <div class="split_line"></div>
+                    <div class="completed">
+                        <span class="num">10</span>
+                        <span>已结束</span>
+                    </div>
+                    <div class="split_line"></div>
+                    <div class="cancelled">
+                        <span class="num">10</span>
+                        <span>已取消</span>
+                    </div>
+                </div>
+             </div>
+        </div>
+
+        <div class="page_item appointment_todo">
+            <div class="page_search" style="margin-bottom: 16px">
+                <div class="search_content">
+                    <div class="content_left">
+                        <TabSearch  tabType="box" 
+                            :tabList="tabSearchList" 
+                            :defaultTabKey="defaultTabType"
+                            @tabChange="HandleTypeChange">
+                        </TabSearch>
+                        <FormSearchGroup :searchList="formSearchList" @searchChange=""></FormSearchGroup>
+                    </div>
+                </div>
+            </div>
+            <SearchBlock :searchList="blockSearchList"></SearchBlock>
+            <div class="page_jg_20"></div>
+
+            <TimeNavLine v-for="(item,index) in appointmentList" 
+                :key="item.id" 
+                :navIcon="item.navIcon" 
+                :navTime="item.navTime" 
+                :timeDesc="item.timeDesc"
+                :isLast="index == (appointmentList.length - 1)">
+                <template #navContent>
+                    <FollowCard :cardList="[{...(item.desc)}]">
+                        <template #operation>
+                            <div class="table_row_option">
+                                <span class="button_delete">取消预约</span>
+                                <span class="option_button_editor">查看详情</span>
+                            </div>
+                        </template>
+
+                    </FollowCard>
+                </template>
+            </TimeNavLine>
+        </div>
     </div>
 </template>
 
 
 <script setup lang="ts">
+import { ref } from 'vue';
+import FormSearchGroup from '@/baseComponents/FormSearchGroup.vue';
+import SearchBlock from '@/baseComponents/SearchBlock.vue';
+import TabSearch from '@/baseComponents/TabSearch.vue';
+
+import {tabSearchList} from './tabSearch'
+import {formSearchList} from './formSearchGroup'
+  
+import {blockSearchList} from './searchBlock'
+import TimeNavLine from '@/baseComponents/TimeNavLine.vue';
+import schoolIcon from '@/assets/clientManage/school.png'
+import FollowCard from '@/components/FollowCard.vue';
+
+import Calendar from '@/baseComponents/Calendar.vue'
+
+const defaultTabType = ref('appointment')
+
+
+const appointmentList = ref([
+    {
+        id:1,
+        navTime: '14:00',
+        navIcon:schoolIcon,
+        timeDesc: '待开始',
+        navTitle:'北京市第一中学',
+
+        desc:{
+            id:1,
+            headerTitleList:['北京市区第一中学'],
+            headerTags:[],
+            taskType:'',
+            middleDesc:['跟进人员:张三','角色:校长','联系人:王德态'],
+            bottomDesc:'跟进内容:9:50会议室,所有管理层一起参会,准备PPT9:50会议室,所有管理层一起参会,准备PPT9:50会议室,所有管理层一起参会,准备PPT',
+        }
+        
+    },
+    {
+        id:2,
+        navTime: '14:00',
+        navIcon:schoolIcon,
+        timeDesc: '待开始',
+        navTitle:'北京市第一中学',
+        desc:{
+            id:1,
+            headerTitleList:['北京市区第一中学'],
+            headerTags:[],
+            taskType:'',
+            middleDesc:['跟进人员:张三','角色:校长','联系人:王德态'],
+            bottomDesc:'跟进内容:9:50会议室,所有管理层一起参会,准备PPT9:50会议室,所有管理层一起参会,准备PPT9:50会议室,所有管理层一起参会,准备PPT',
+        }
+    },
+])
+
+const HandleTypeChange = (val)=>{
+    defaultTabType.value = val
+}
+
+// 当前选中的日历信息
+const selectedCalendarTime =ref()
+
 
 </script>
 
 
 <style lang="scss" scoped>
+.main_container{
+    display: flex;
+    flex-direction: row;
+    justify-content: flex-start;
+    gap:20px;
+    > div{
+        overflow:auto;
+    }
+
+    .calendar{
+        padding:16px;
+        width: 320px;
+        flex-shrink: 0;
+        background: #FFFFFF;
+        border-radius: 10px 10px 10px 10px;
+        .calendar_desc{
+            padding:16px;
+            background: #F8FAFE;
+            border-radius: 10px;
+            border: 1px solid #EBEEF5;
+            .calendar_desc_title{
+                display: flex;
+                justify-content: space-between;
+                line-height: 22px;
+                font-size: 16px;
+                color: #333333;
+                .date_desc{
+                    font-weight: 600;
+                }
+            }
+            .calendar_desc_content{
+                display: flex;
+                gap:28px;
+                justify-content: space-between;
+                align-items: center;
+                margin-top: 18px;
+                line-height: 20px;
+                font-size: 14px;
+                > div{
+                    display: flex;
+                    flex-direction: column;
+                    justify-content: center;
+                    align-items: center;
+                    gap:4px;
+                    .num{
+                        font-weight: 600;
+                    }
+                }
+                .split_line{
+                    width: 1px;
+                    height: 32px;
+                    background-color: #EBEEF5;
+                }
+
+                .active{
+                    color:#2E64FA;
+                }
+                .completed{
+                    color:#999999;
+
+                }
+                .cancelled{
+                    color:#F56C6C
+                }
+            }
+        }
+    }
+    
+}
 
+.time_nav_line{
+    :deep(.follow_card){
+        .audit_card{
+            border-color: transparent;
+            .table_row_option{
+                display: none;
+            }
+        }
+    }
+    :hover{
+        :deep(.follow_card){
+            .audit_card{
+                background-color: #F8FAFE;
+                border: 1px solid #EBEEF5;
+                .table_row_option{
+                    display: flex;
+                }
+            }
+        }
+    }
+}
 </style>

+ 31 - 0
src/views/appointmentAndTodo/searchBlock.ts

@@ -0,0 +1,31 @@
+import { ref } from 'vue'
+
+export const blockSearchList = ref([
+  {
+    label: '跟进人员',
+    key: 'follower',
+    type: 'single', 
+    defaultValue: 'all',
+    options: [
+      { label: '全部', value: 'all' },
+      { label: '章泽析', value: 'zhang_zexi' },
+      { label: '朱云', value: 'zhu_yun' },
+      { label: '陈思怡', value: 'chen_siyi' },
+      { label: '陈雅琪', value: 'chen_yaqi' },
+      { label: '付文杰', value: 'fu_wenjie' },
+      { label: '刘懂', value: 'liu_dong' }
+    ]
+  },
+  {
+    label: '预约状态',
+    key: 'appointmentStatus',
+    type: 'single',
+    defaultValue: 'all',
+    options: [
+      { label: '全部', value: 'all' },
+      { label: '待开始', value: 'pending' },
+      { label: '已结束', value: 'finished' },
+      { label: '已取消', value: 'cancelled' }
+    ]
+  }
+]);

+ 12 - 0
src/views/appointmentAndTodo/tabSearch.ts

@@ -0,0 +1,12 @@
+import { ref } from 'vue'
+
+export const tabSearchList = ref([
+    {
+        label:'预约登记',
+        key:'appointment',
+    },
+    {
+        label:'待办登记',
+        key:'todo',
+    },
+])

+ 0 - 15
src/views/highSeasCustomer/highSeasCustomerDetail/searchBlock.ts

@@ -2,21 +2,6 @@ import { ref } from "vue";
 
 
 export const operationRecordSearchList = ref([
-    {
-        label: '时间',
-        key: 'time',
-        type: 'single',
-        options:[
-            { label: '全部', value: 'all' },
-            { label: '今天', value: 'today' },
-            { label: '昨天', value: 'yesterday' },
-            { label: '近3天', value: 'last3Days' },
-            { label: '近1周', value: 'last1Week' },
-            { label: '近1月', value: 'last1Month' },
-            { label: '自定义', value: 'custom' }
-        ],
-        defaultValue: 'all'
-    },
     {
         label: '人员',
         key: 'personnel',