index.vue 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. <!-- 我的客户 和 公海客户、 客户跟进 的客户操作记录 -->
  2. <template>
  3. <!-- 操作记录 弹窗 -->
  4. <PreviewDialog
  5. class="operation_dialog"
  6. title="操作记录"
  7. :previewVisible="operationRecordDialogVisible"
  8. :customFooter="true"
  9. @close="CloseOperationRecordDialog">
  10. <SearchBlock :searchList="operationRecordSearchList"
  11. @searchChange="HandleOperationLogSearchChange">
  12. <template #rowItem-time>
  13. <el-date-picker
  14. v-if="searchParams.time=='custom'"
  15. style="flex-grow: 0;height: 28px;width: 220px;"
  16. v-model="searchParams.startAndEndTime"
  17. @change="(val)=>HandleOperationLogSearchChange({startAndEndTime:val},'startAndEndTime')"
  18. start-placeholder="开始时间"
  19. end-placeholder="结束时间"
  20. type="datetimerange"
  21. range-separator="至"
  22. size="default"
  23. />
  24. </template>
  25. </SearchBlock>
  26. <FormSearchGroup style="margin:16px 0" v-if="props.interfaceSource == 'customerFollow'"
  27. :searchList="operationRecordBlurSearch" @searchChange="HandleOperationLogSearchChange"/>
  28. <FollowCard :cardList="finalOperationLogRenderData">
  29. <template #operation><i></i></template>
  30. </FollowCard>
  31. <Pagination :currentPage="currentPage"
  32. :pageSize="pageSize" :totalNum="totalNum"
  33. :showPageSize="true"
  34. @paginationChange="HandleLogPaginationChange">
  35. <template #paginationDesc>
  36. <span>共 {{totalNum}} 条数据</span>
  37. </template>
  38. </Pagination>
  39. <template #close>
  40. <el-button @click="CloseOperationRecordDialog" class="button_background" >关闭</el-button>
  41. </template>
  42. <template #confirm><i></i></template>
  43. </PreviewDialog>
  44. </template>
  45. <script setup lang="ts">
  46. import { ref, onMounted } from 'vue';
  47. import { useRoute } from 'vue-router';
  48. import PreviewDialog from '@/baseComponents/PreviewDialog.vue';
  49. import SearchBlock from '@/baseComponents/SearchBlock.vue';
  50. import FollowCard from '@/components/FollowCard.vue';
  51. import Pagination from '@/baseComponents/Pagination.vue';
  52. import {operationRecordSearchList} from './searchBlock'
  53. import FormSearchGroup from '@/baseComponents/FormSearchGroup.vue';
  54. import {operationRecordBlurSearch} from './formSearchGroup'
  55. import {
  56. getOperationLogApi,
  57. } from '@/api/highSeasCustomer'
  58. import {getPrivateOperationLogApi} from '@/api/myCustomer'
  59. import { getCustomerOperationLogApi} from '@/api/customerFollowUp';
  60. import {
  61. getTodayRange,
  62. getYesterdayRange,
  63. getRecentDaysRange,
  64. getRecentWeeksRange,
  65. getRecentMonthsRange,
  66. formatTime
  67. } from '@/utils/timeRangeGet'
  68. const props = defineProps({
  69. interfaceSource:{
  70. type:String as ()=>'highSeasCustomer'|'myCustomer'|'customerFollow',
  71. requreid:true,
  72. }, //查询操作日志 接口来源
  73. })
  74. const operationRecordDialogVisible = defineModel('dialogVisible')
  75. const route = useRoute()
  76. // /** 操作记录列表有关数据 */
  77. const finalOperationLogRenderData = ref([])
  78. // 分页参数 有关数据 *
  79. const currentPage = ref(1)
  80. const pageSize = ref(20)
  81. const totalNum = ref(0)
  82. const searchParams = ref({
  83. personnel:'all',
  84. time:'all',
  85. group:'all',
  86. startAndEndTime:[],
  87. })
  88. // 关闭
  89. const CloseOperationRecordDialog=()=>{
  90. operationRecordDialogVisible.value = false
  91. searchParams.value = {
  92. personnel:'all',
  93. time:'all',
  94. group:'all',
  95. startAndEndTime:[],
  96. }
  97. }
  98. // 搜索条件变化
  99. const HandleOperationLogSearchChange = async (params,key)=>{
  100. searchParams.value = {
  101. ...searchParams.value,
  102. ...params,
  103. }
  104. await GetOperationList()
  105. }
  106. // 分页变化
  107. const HandleLogPaginationChange = async (params)=>{
  108. const {type,val} = params
  109. if(type == 'currentPage'){
  110. currentPage.value = val
  111. }else if(type == 'pageSize'){
  112. pageSize.value = val
  113. }
  114. await GetOperationList()
  115. }
  116. //获取日志列表
  117. const GetOperationList = async ()=>{
  118. let rangeTime = {
  119. startTime:'',
  120. endTime:'',
  121. }
  122. if(['myCustomer','customerFollow'].includes(props.interfaceSource)){
  123. switch(searchParams.value.time){
  124. case 'today':
  125. rangeTime = getTodayRange()
  126. break
  127. case 'yesterday':
  128. rangeTime = getYesterdayRange()
  129. break
  130. case 'last3Days':
  131. rangeTime = getRecentDaysRange(3)
  132. break
  133. case 'last1Week':
  134. rangeTime = getRecentWeeksRange(1)
  135. break
  136. case 'last1Month':
  137. rangeTime = getRecentMonthsRange(1)
  138. break
  139. case 'custom':
  140. rangeTime = {
  141. startTime:formatTime(searchParams.value.startAndEndTime?.[0]) ,
  142. endTime: formatTime(searchParams.value.startAndEndTime?.[1]),
  143. }
  144. break
  145. }
  146. }
  147. let res = undefined
  148. if(props.interfaceSource == 'highSeasCustomer'){
  149. let params = {
  150. customerId: route.query.id,
  151. operUserId: searchParams.value.personnel == 'all' ? '' : searchParams.value.personnel,
  152. pageNum: currentPage.value,
  153. pageSize: pageSize.value
  154. }
  155. res = await getOperationLogApi(params)
  156. }else if(props.interfaceSource == 'myCustomer'){
  157. let params = {
  158. customerId: route.query.id,
  159. operUserId: searchParams.value.personnel == 'all' ? '' : searchParams.value.personnel,
  160. startDate: rangeTime.startTime,
  161. endDate: rangeTime.endTime,
  162. pageNum: currentPage.value,
  163. pageSize: pageSize.value
  164. }
  165. res = await getPrivateOperationLogApi(params)
  166. }else if(props.interfaceSource == 'customerFollow'){
  167. let params = {
  168. operUserId: searchParams.value.personnel == 'all' ? '' : searchParams.value.personnel,
  169. groupId: searchParams.value.group == 'all' ? '' : searchParams.value.group,
  170. startDate: rangeTime.startTime,
  171. endDate: rangeTime.endTime,
  172. pageNum: currentPage.value,
  173. pageSize: pageSize.value,
  174. queryStr:searchParams.value.queryStr
  175. }
  176. res = await getCustomerOperationLogApi(params)
  177. }
  178. if(res?.code == 200){
  179. const {data:operationData, groupData, memberData} = res?.data
  180. totalNum.value = operationData.total
  181. let memberOption = memberData?.map(item=>{
  182. return {
  183. label:item.username,
  184. value:item.id
  185. }
  186. }) || []
  187. let groupOption = groupData?.map(item=>{
  188. return {
  189. label:item.name,
  190. value:item.id
  191. }
  192. }) || []
  193. operationRecordSearchList.value = operationRecordSearchList.value.map(item=>{
  194. switch(item.key){
  195. case 'personnel':
  196. item.options = [
  197. { label: '全部', value: 'all' },
  198. ...memberOption
  199. ]
  200. break
  201. case 'group':
  202. item.options = [
  203. { label: '全部', value: 'all' },
  204. ...groupOption
  205. ]
  206. item.hidden = props.interfaceSource == 'customerFollow' ? false : true
  207. break
  208. case 'time':
  209. item.hidden = ['customerFollow','myCustomer']?.includes(props.interfaceSource) ? false : true
  210. break
  211. }
  212. item.defaultValue = searchParams.value[item.key]
  213. return item
  214. })
  215. finalOperationLogRenderData.value = operationData.records.map(item=>{
  216. let operationName = OperationNumToName(item.operAction)
  217. //操作概览
  218. let operationAim = ''
  219. if(item.operDataType === 1){ //联系人
  220. // 增 改 删
  221. if([11,12,13].includes(item.operAction)){
  222. operationAim = '联系人'
  223. }else{
  224. operationAim = ''
  225. }
  226. }else if(item.operDataType === 0){ //客户
  227. if([12].includes(item.operAction)){
  228. operationAim = '学校信息'
  229. }else if([2].includes(item.operAction)){ //转让
  230. operationAim = '归属人'
  231. }else{
  232. operationAim = ''
  233. }
  234. }
  235. // 具体操作信息
  236. // 增 改 删
  237. let operationDetail = ''
  238. let content = item.content.split(',')
  239. if([11,12,13].includes(item.operAction)){
  240. if([12,2].includes(item.operAction)){
  241. operationDetail = content[0] + ` <span style="color:#2E64FA">调整为</span> ` + content[1]
  242. }else if(item.operAction === 11){
  243. operationDetail = `<span style="color:#2E64FA">新增</span> ` + content[0]
  244. }else if(item.operAction === 13){
  245. operationDetail = `<span style="color:#F56C6C">删除</span> ` + content[0]
  246. }
  247. }else{
  248. operationDetail = content[0]
  249. }
  250. return {
  251. headerTitleList:props.interfaceSource == 'customerFollow' ? [
  252. item.operDatetime,
  253. item.operName,
  254. item.customerName, // 学校信息 只在 客户跟进显示
  255. operationName+operationAim,
  256. ] : [
  257. item.operDatetime,
  258. item.operName,
  259. operationName+operationAim,
  260. ],
  261. headerTags:[],
  262. middleDesc:[],
  263. bottomDesc:`操作内容:${operationDetail}`
  264. }
  265. })
  266. }
  267. }
  268. // 0-认领,1-跟进,2-转让,3-转到公海,11-新增,12-修改,13-删除
  269. const OperationNumToName = (num)=>{
  270. switch(num){
  271. case 0:
  272. return '认领'
  273. case 1:
  274. return '跟进'
  275. case 2:
  276. return '转让'
  277. case 3:
  278. return '转至公海'
  279. case 11:
  280. return '新增'
  281. case 12:
  282. return '编辑'
  283. case 13:
  284. return '删除'
  285. }
  286. }
  287. onMounted(async ()=>{
  288. await GetOperationList()
  289. })
  290. </script>
  291. <style lang="scss" scoped>
  292. </style>