index.vue 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. <template>
  2. <div class="main_container">
  3. <!-- 日历——预约总览 -->
  4. <div v-if="defaultTabType == 'appointment'" class="calendar" >
  5. <Calendar v-model:selectedCalendarTime="selectedCalendarTime"
  6. :dateStatus="dateStatus">
  7. </Calendar>
  8. <div class="calendar_desc">
  9. <div class="calendar_desc_title">
  10. <span class="date_desc">{{dayjs(selectedCalendarTime || undefined).month() + 1}}月预约</span>
  11. <span class="total_count">共{{currentMonthAppointment.totalCount}}条</span>
  12. </div>
  13. <div class="calendar_desc_content">
  14. <div class="active">
  15. <span class="num">{{ currentMonthAppointment.waitStart }}</span>
  16. <span>待开始</span>
  17. </div>
  18. <div class="split_line"></div>
  19. <div class="completed">
  20. <span class="num">{{ currentMonthAppointment.end }}</span>
  21. <span>已结束</span>
  22. </div>
  23. <div class="split_line"></div>
  24. <div class="cancelled">
  25. <span class="num">{{ currentMonthAppointment.cancel }}</span>
  26. <span>已取消</span>
  27. </div>
  28. </div>
  29. </div>
  30. </div>
  31. <div class="detail_content">
  32. <div class="page_item appointment_todo" :style="defaultTabType === 'appointment' ? {flex:'1 1'} : {}">
  33. <div class="page_search">
  34. <div class="search_content">
  35. <div class="content_left">
  36. <TabSearch tabType="box"
  37. :tabList="tabSearchList"
  38. :defaultTabKey="defaultTabType"
  39. @tabChange="HandleTypeChange">
  40. </TabSearch>
  41. <!-- 预约登记筛选条件 -->
  42. <FormSearchGroup v-if="defaultTabType === 'appointment'"
  43. :searchList="formSearchList"
  44. @searchChange="HandleSearchChange">
  45. </FormSearchGroup>
  46. </div>
  47. <!-- 待办登记展示信息 -->
  48. <div v-if="defaultTabType === 'todo'" class="content_right" style="flex:1 1">
  49. <!-- 日历导航 头-->
  50. <CalendarDateSelectHeader
  51. v-model:currentYear="currentYear"
  52. v-model:currentMonth="currentMonth"
  53. ></CalendarDateSelectHeader>
  54. </div>
  55. </div>
  56. </div>
  57. <!-- 预约登记 -->
  58. <AppointmentRegister
  59. v-if="defaultTabType === 'appointment'"
  60. :appointmentList="appointmentList"
  61. :followerList="followerList"
  62. :orderStatusList="orderStatusList"
  63. @searchChange="HandleSearchChange">
  64. </AppointmentRegister>
  65. </div>
  66. <!-- 待办登记 -->
  67. <div v-if="defaultTabType === 'todo'" class="page_item" style="padding:10px">
  68. <TodoRegister
  69. v-model:currentYear="currentYear"
  70. v-model:currentMonth="currentMonth"
  71. ></TodoRegister>
  72. </div>
  73. </div>
  74. </div>
  75. </template>
  76. <script setup lang="ts">
  77. import { ref, onMounted, watch } from 'vue';
  78. import dayjs from 'dayjs';
  79. import FormSearchGroup from '@/baseComponents/FormSearchGroup.vue';
  80. import TabSearch from '@/baseComponents/TabSearch.vue';
  81. import {tabSearchList} from './tabSearch'
  82. import {formSearchList} from './formSearchGroup'
  83. import Calendar from '@/baseComponents/Calendar.vue'
  84. import AppointmentRegister from './appointmentRegister/index.vue'
  85. import TodoRegister from './toDoRegister/index.vue'
  86. import CalendarDateSelectHeader from '@/baseComponents/CalendarTodoList/CalendarDateSelectHeader.vue';
  87. import {formatTime} from '@/utils/timeRangeGet'
  88. import schoolIcon from '@/assets/clientManage/school.png'
  89. import { getAppointmentListApi} from '@/api/appointmentAndTodo'
  90. const defaultTabType = ref('appointment')
  91. const HandleTypeChange = (val)=>{
  92. defaultTabType.value = val
  93. }
  94. // 当前选中的日历信息
  95. const selectedCalendarTime =ref(dayjs())
  96. const currentYear = ref(new Date().getFullYear())
  97. const currentMonth = ref(new Date().getMonth() + 1 )
  98. /**
  99. * 处理日期的选择
  100. */
  101. const currentMonthAppointment = ref({
  102. totalCount:0,
  103. waitStart:0,
  104. end:0,
  105. cancel:0,
  106. })
  107. const dateStatus = ref([]) // 当月的日程状态
  108. const appointmentList = ref([])
  109. const followerList = ref([])
  110. const orderStatusList = ref([])
  111. const searchParams = ref({
  112. follower:'all',
  113. appointmentStatus:'all',
  114. queryStr:'',
  115. })
  116. const HandleSearchChange = async (params,key)=>{
  117. searchParams.value = {
  118. ...searchParams.value,
  119. ...params
  120. }
  121. await GetAppointmentList()
  122. }
  123. // 查询预约登记信息
  124. const GetAppointmentList = async ()=>{
  125. let params = {
  126. datetime: formatTime(selectedCalendarTime.value).split(' ')[0],
  127. userId: searchParams.value.follower == 'all' ? '' : searchParams.value.follower,
  128. orderStatus: searchParams.value.appointmentStatus == 'all' ? '' : searchParams.value.appointmentStatus,
  129. queryStr: searchParams.value.queryStr
  130. }
  131. let res = await getAppointmentListApi(params)
  132. if(res?.code == 200){
  133. const {selectData,dataList,dateList,status0Count, status1Count, status2Count, totalCount } = res?.data
  134. currentMonthAppointment.value = {
  135. totalCount:totalCount,
  136. waitStart:status0Count,
  137. end:status1Count,
  138. cancel:status2Count
  139. }
  140. dateStatus.value = dateList.map(item=>{
  141. return {
  142. day:item.day,
  143. hasToDo:item.status === 1 ? true : false
  144. }
  145. })
  146. appointmentList.value = dataList?.map(item=>{
  147. return {
  148. desc:{
  149. id:item.id,
  150. headerTitleList:[item.customerName],
  151. headerTags:[],
  152. taskType:'',
  153. productType:item.productName,
  154. middleDesc:[`跟进人员:${item.claimUserName}`,
  155. `角色:${item.positionName}`,
  156. `联系人:${item.customerPersonName}`,
  157. `地址:${item.address}`,
  158. ],
  159. bottomDesc:`跟进内容:${item.followContent}`,
  160. },
  161. ...item,
  162. navIcon:schoolIcon,
  163. timeDesc:appointmentStatusToName(item.orderStatus),
  164. // id:item.id,
  165. // navTime: item.orderDatetime,
  166. // navTitle:item.customerName,
  167. // cancelReason:item.cancelRemark,
  168. }
  169. })
  170. const {memberData,orderStatusData} = selectData || {}
  171. followerList.value = memberData?.map(item=>{
  172. return {
  173. label:item.username,
  174. value:item.id
  175. }
  176. })
  177. orderStatusList.value = orderStatusData?.map(item=>{
  178. return {
  179. label:item.name,
  180. value:item.status
  181. }
  182. })
  183. }
  184. }
  185. const appointmentStatusToName = (status)=>{
  186. switch(status){
  187. case 0:
  188. return '待开始'
  189. case 1:
  190. return '已结束'
  191. case 2:
  192. return '已取消'
  193. }
  194. }
  195. watch(()=>selectedCalendarTime.value, async(newVal)=>{
  196. await GetAppointmentList()
  197. })
  198. onMounted(async ()=>{
  199. await GetAppointmentList()
  200. })
  201. </script>
  202. <style lang="scss" scoped>
  203. .main_container{
  204. display: flex;
  205. flex-direction: row;
  206. justify-content: flex-start;
  207. gap:20px;
  208. > div{
  209. overflow:auto;
  210. }
  211. .calendar{
  212. padding:16px;
  213. width: 320px;
  214. flex-shrink: 0;
  215. background: #FFFFFF;
  216. border-radius: 10px 10px 10px 10px;
  217. .calendar_desc{
  218. margin-top: 24px;
  219. padding:16px;
  220. background: #F8FAFE;
  221. border-radius: 10px;
  222. border: 1px solid #EBEEF5;
  223. .calendar_desc_title{
  224. display: flex;
  225. justify-content: space-between;
  226. line-height: 22px;
  227. font-size: 16px;
  228. color: #333333;
  229. .date_desc{
  230. font-weight: 600;
  231. }
  232. }
  233. .calendar_desc_content{
  234. display: flex;
  235. gap:28px;
  236. justify-content: space-between;
  237. align-items: center;
  238. margin-top: 18px;
  239. line-height: 20px;
  240. font-size: 14px;
  241. > div{
  242. display: flex;
  243. flex-direction: column;
  244. justify-content: center;
  245. align-items: center;
  246. gap:4px;
  247. .num{
  248. font-weight: 600;
  249. }
  250. }
  251. .split_line{
  252. width: 1px;
  253. height: 32px;
  254. background-color: #EBEEF5;
  255. }
  256. .active{
  257. color:#2E64FA;
  258. }
  259. .completed{
  260. color:#999999;
  261. }
  262. .cancelled{
  263. color:#F56C6C
  264. }
  265. }
  266. }
  267. }
  268. .detail_content{
  269. flex:1 1;
  270. display: flex;
  271. flex-direction: column;
  272. overflow: auto;
  273. gap:10px;
  274. .appointment_todo{
  275. flex-shrink: 0;
  276. overflow: auto;
  277. padding:16px;
  278. display: flex;
  279. flex-direction: column;
  280. gap:16px;
  281. }
  282. }
  283. }
  284. </style>