index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  1. <template>
  2. <div class="main_container">
  3. <TopBackNav>
  4. <template #topRight>
  5. <div class="header_content">
  6. <span>{{ customerBaseMsg.name }}</span>
  7. </div>
  8. <div class="desc">
  9. <span>学段:{{ customerBaseMsg.stageName }}</span>
  10. <span>省份:{{ customerBaseMsg.provinceName }}</span>
  11. <span>地区:{{ customerBaseMsg.cityName }}</span>
  12. <span>地址:{{ customerBaseMsg.address }}</span>
  13. <span>进入公海时间:{{ customerBaseMsg.resetDatetime }}</span>
  14. <span>闲置天数:{{ customerBaseMsg.unUsedDayCount }}</span>
  15. </div>
  16. <div class="action">
  17. <el-button class="button_background" @click="ClaimCustomer"><img :src="peopleAuthenticationIcon" alt=""> 认领</el-button>
  18. <el-button class="button_border" @click="OpenConcactPeoplelFormDialog"><img :src="addIcon" alt=""> 新增联系人</el-button>
  19. <el-button class="button_refresh" @click="OpenSchoolFormDialog"><img :src="editIcon" alt="" > 编辑</el-button>
  20. <el-button class="button_refresh" @click="OpenOperationRecordDialog"><img :src="logIcon" alt=""> 操作记录</el-button>
  21. <el-button class="delete_button_border_no_bg" @click="OpenDeleteDialog"><el-icon class="img"><Delete /></el-icon>删除</el-button>
  22. </div>
  23. </template>
  24. </TopBackNav>
  25. <div class="page_item bottom_detail end_item">
  26. <TabSearch :defaultTabKey="defaultShowTab"
  27. tabType="line" :tabList="tabList"
  28. @tabChange="HandleTabChange"/>
  29. <div class="page_solid_line" />
  30. <div class="page_jg_20" style="flex-shrink: 0 !important;"></div>
  31. <!-- 联系人详情 -->
  32. <ContactDetail :reloadFlag="reloadFlag" v-if="defaultShowTab === 'contactDetails'"/>
  33. <CustomerStatusOverview v-if="defaultShowTab === 'messageOverview'"/>
  34. </div>
  35. <!-- 操作记录 弹窗 -->
  36. <PreviewDialog
  37. v-if="operationRecordDialogVisible"
  38. class="operation_dialog"
  39. title="操作记录"
  40. :previewVisible="operationRecordDialogVisible"
  41. :customFooter="true"
  42. @close="CloseOperationRecordDialog">
  43. <SearchBlock :searchList="operationRecordSearchList"></SearchBlock>
  44. <FollowCard :card-list="finalOperationLogRenderData">
  45. <template #operation><i></i></template>
  46. </FollowCard>
  47. <Pagination :currentPage="currentPage" :pageSize="pageSize" :totalNum="totalNum"></Pagination>
  48. <template #close>
  49. <el-button @click="CloseOperationRecordDialog" class="button_background" >关闭</el-button>
  50. </template>
  51. <template #confirm><i></i></template>
  52. </PreviewDialog>
  53. <!-- 编辑学校弹窗 -->
  54. <SchoolFormDialog
  55. v-model:visible="schoolVisible"
  56. :defaultFormData="schoolDefaultFormData"
  57. v-model:submitLoading="schoolSubmitLoading"
  58. @confirm="HandleSchoolDialogConfirm">
  59. </SchoolFormDialog>
  60. <!-- 新增联系人弹窗 -->
  61. <ConcactPeopleFormDialog
  62. v-if="concactPeopleVisible"
  63. v-model:visible="concactPeopleVisible"
  64. v-model:submitLoading="concactPeopleSubmitLoading"
  65. title="新增联系人"
  66. :defaultFormData="concactPeopleDefaultFormData"
  67. @confirm="HandleAddPeoplelConfirm">
  68. </ConcactPeopleFormDialog>
  69. <!-- 删除客户弹窗 -->
  70. <DeleteCustomerDialog
  71. :currentDeleteRow="customerBaseMsg"
  72. v-model:dialogVisible="deleteDialogVisible"
  73. @confirm="HandleDeleteConfirm">
  74. </DeleteCustomerDialog>
  75. </div>
  76. </template>
  77. <script setup lang="ts">
  78. import { ref, computed, onMounted } from 'vue';
  79. import { useRoute, useRouter } from 'vue-router';
  80. import TopBackNav from '@/baseComponents/TopBackNav.vue';
  81. import addIcon from '@/assets/icon/add.svg';
  82. import peopleAuthenticationIcon from '@/assets/icon/people_authentication.png'
  83. import editIcon from '@/assets/icon/edit.svg'
  84. import logIcon from '@/assets/icon/log.png'
  85. import TabSearch from '@/baseComponents/TabSearch.vue';
  86. import {tabList} from './tabSearch'
  87. import ContactDetail from './contactDetail/index.vue'
  88. import CustomerStatusOverview from './customerStatusOverview/index.vue'
  89. import PreviewDialog from '@/baseComponents/PreviewDialog.vue';
  90. import SearchBlock from '@/baseComponents/SearchBlock.vue';
  91. import {operationRecordSearchList} from './searchBlock'
  92. import FollowCard from '@/components/FollowCard.vue';
  93. import Pagination from '@/baseComponents/Pagination.vue';
  94. import SchoolFormDialog from '@/components/SchoolFormDialog/index.vue'
  95. import ConcactPeopleFormDialog from '@/components/ConcactPeopleFormDialog/index.vue'
  96. import { ElMessage } from 'element-plus';
  97. import DeleteCustomerDialog from '../components/DeleteCustomerDialog.vue';
  98. import {
  99. addContactPeopleApi,
  100. claimHighSeasCustomerApi,
  101. updateHighSeasCustomerApi,
  102. getOperationLogApi,
  103. } from '@/api/highSeasCustomer'
  104. interface CustomerBaseMsg {
  105. name:string, //学校名称
  106. stageName:string, //学段
  107. stageId:string,
  108. provinceName:string, //省份
  109. provinceId:string,
  110. cityName:string, // 地区
  111. cityId:string,
  112. address:string, //地址
  113. resetDatetime:string, //进入公海时间
  114. unUsedDayCount:string, //闲置天数
  115. }
  116. const route = useRoute()
  117. const router = useRouter()
  118. const customerBaseMsg = ref<CustomerBaseMsg>({}); //客户基础信息
  119. /**
  120. * 1. 信息展示切换
  121. */
  122. const defaultShowTab = ref('messageOverview')
  123. const HandleTabChange = (val)=>{
  124. defaultShowTab.value = val
  125. }
  126. /** 2. 新增联系人有关数据 及操作 */
  127. const concactPeopleVisible = ref(false)
  128. const concactPeopleDefaultFormData = ref({})
  129. const concactPeopleSubmitLoading = ref(false)
  130. const reloadFlag = ref(0) //重新加载联系人数据标识
  131. const OpenConcactPeoplelFormDialog = ()=>{
  132. concactPeopleVisible.value = true
  133. }
  134. const CloseConcactPeoplelFormDialog = ()=>{
  135. concactPeopleSubmitLoading.value = false
  136. concactPeopleVisible.value = false
  137. concactPeopleDefaultFormData.value = {}
  138. }
  139. const HandleAddPeoplelConfirm = async (params:any)=>{
  140. concactPeopleSubmitLoading.value = true
  141. const {formData,formRef} = params
  142. let transferParams = {
  143. customerId: route.query.id, //
  144. name: formData.name,
  145. positionId: JSON.parse(formData.position || '{}')?.value,
  146. positionName: JSON.parse(formData.position || '{}')?.label,
  147. phoneNo: formData.phoneNo,
  148. officePhoneNo: formData.officePhoneNo,
  149. remark: formData.remark,
  150. }
  151. let res = undefined
  152. try{
  153. res = await addContactPeopleApi(transferParams)
  154. }catch{}
  155. if(res?.code == 200){
  156. ElMessage.success(res?.msg)
  157. CloseConcactPeoplelFormDialog()
  158. reloadFlag.value += 1
  159. }
  160. }
  161. /** 3. 编辑学校 有关数据 及操作 */
  162. const schoolVisible = ref(false)
  163. const schoolSubmitLoading = ref(false)
  164. const schoolDefaultFormData = ref({})
  165. const CloseSchoolFormDialog = ()=>{
  166. schoolVisible.value = false
  167. schoolSubmitLoading.value = false
  168. schoolDefaultFormData.value = {}
  169. }
  170. // 打开弹窗
  171. const OpenSchoolFormDialog = ()=>{
  172. schoolVisible.value = true
  173. schoolDefaultFormData.value = {
  174. ...customerBaseMsg.value,
  175. schoolStage:JSON.stringify({
  176. label:customerBaseMsg.value?.stageName,
  177. value:customerBaseMsg.value?.stageId,
  178. }),
  179. provinceArea:{
  180. province:JSON.stringify({
  181. label:customerBaseMsg.value?.provinceName,
  182. value:customerBaseMsg.value?.provinceId,
  183. }),
  184. district:JSON.stringify({
  185. label:customerBaseMsg.value?.cityName,
  186. value:customerBaseMsg.value?.cityId,
  187. }),
  188. }
  189. }
  190. }
  191. // 编辑确认
  192. const HandleSchoolDialogConfirm = async (params)=>{
  193. schoolSubmitLoading.value = true
  194. const {formData,formRef} = params
  195. let transferParams = {
  196. id: formData.id,
  197. name: formData.name,
  198. stageId: JSON.parse(formData.schoolStage || '{}')?.value,
  199. stageName: JSON.parse(formData.schoolStage || '{}')?.label,
  200. provinceId: JSON.parse(formData.provinceArea.province || '{}')?.value,
  201. provinceName: JSON.parse(formData.provinceArea.province || '{}')?.label,
  202. cityId: JSON.parse(formData.provinceArea.district || '{}')?.value,
  203. cityName: JSON.parse(formData.provinceArea.district || '{}')?.label,
  204. address: formData.address,
  205. }
  206. let res = undefined
  207. try{
  208. res = await updateHighSeasCustomerApi(transferParams)
  209. }catch{}
  210. if(res?.code == 200){
  211. customerBaseMsg.value = {
  212. ...customerBaseMsg.value,
  213. name:formData.name,
  214. stageId: JSON.parse(formData.schoolStage || '{}')?.value,
  215. stageName: JSON.parse(formData.schoolStage || '{}')?.label,
  216. provinceId: JSON.parse(formData.provinceArea.province || '{}')?.value,
  217. provinceName: JSON.parse(formData.provinceArea.province || '{}')?.label,
  218. cityId: JSON.parse(formData.provinceArea.district || '{}')?.value,
  219. cityName: JSON.parse(formData.provinceArea.district || '{}')?.label,
  220. address: formData.address,
  221. }
  222. sessionStorage.setItem('customerMsg',JSON.stringify(customerBaseMsg.value))
  223. CloseSchoolFormDialog()
  224. }else{
  225. schoolSubmitLoading.value = false
  226. }
  227. }
  228. /** 4. 操作记录相关内容及操作 */
  229. const operationRecordDialogVisible = ref(false)
  230. const OpenOperationRecordDialog = async ()=>{
  231. console.log('打开操作记录弹窗')
  232. operationRecordDialogVisible.value = true
  233. await GetOperationList()
  234. }
  235. const CloseOperationRecordDialog=()=>{
  236. operationRecordDialogVisible.value = false
  237. }
  238. /** 操作记录有关数据 */
  239. const operationLogList = ref([
  240. {
  241. id:1,
  242. operationTime: '26-02-19 19:00',
  243. operatorName: '张安顺',
  244. schoolName: '北京师达学校',
  245. operationType: '编辑学校信息',
  246. operationContent: '学校名称【北京109中学】学段【初中】调整为学校名称【北京一零九中学】学段【九年一贯】。'
  247. },
  248. {
  249. id:2,
  250. operationTime: '26-02-19 19:00',
  251. operatorName: '张安顺',
  252. schoolName: '北京师达学校',
  253. operationType: '删除联系人',
  254. operationContent: '删除 姓名【张三】职务【校长】手机电话【17820681226】办公电话【17820681226】备注【文案文案】。'
  255. },
  256. {
  257. id:3,
  258. operationTime: '26-02-19 19:00',
  259. operatorName: '张安顺',
  260. schoolName: '北京师达学校',
  261. operationType: '新增联系人',
  262. operationContent: '新增 姓名【张三】职务【校长】手机电话【17820681226】办公电话【17820681226】备注【文案文案】。'
  263. },
  264. {
  265. id:4,
  266. operationTime: '26-02-19 19:00',
  267. operatorName: '张安顺',
  268. schoolName: '北京师达学校',
  269. operationType: '编辑联系人',
  270. operationContent: '联系人姓名【张三】职务【校长】手机电话【17820681226】备注【文案文案】调整为 联系人姓名【李四】职务【校长】手机电话【17820681226】备注【文案文案】。'
  271. },
  272. {
  273. id:5,
  274. operationTime: '26-02-19 19:00',
  275. operatorName: '张安顺',
  276. schoolName: '北京师达学校',
  277. operationType: '转至公海',
  278. operationContent: '将客户转至公海。'
  279. }
  280. ]);
  281. const finalOperationLogRenderData = computed(()=>{
  282. return operationLogList.value.map(item=>{
  283. return {
  284. headerTitleList:[
  285. item.operationTime,
  286. item.operatorName,
  287. item.schoolName,
  288. item.operationType
  289. ],
  290. headerTags:[],
  291. middleDesc:[],
  292. bottomDesc:`操作内容:${item.operationContent}`
  293. }
  294. })
  295. })
  296. // 分页参数 有关数据 *
  297. const currentPage = ref(1)
  298. const pageSize = ref(20)
  299. const totalNum = ref(0)
  300. const GetOperationList = async ()=>{
  301. let params = {
  302. customerId: route.params.id,
  303. "operUserId": '',
  304. // "groupId": 0,
  305. // "startDate": "",
  306. // "endDate": "",
  307. pageNum: currentPage.value,
  308. pageSize: pageSize.value
  309. }
  310. let res = await getOperationLogApi(params)
  311. if(res?.code == 200){
  312. const {data:operationData, dateData, groupData, memberData} = res?.data
  313. totalNum.value = operationData.total
  314. finalOperationLogRenderData = operationData.records.map(item=>{
  315. return {
  316. headerTitleList:[
  317. item.operDatetime,
  318. item.operName,
  319. item.operationType
  320. ],
  321. headerTags:[],
  322. middleDesc:[],
  323. bottomDesc:`操作内容:${item.operationContent}`
  324. }
  325. })
  326. }
  327. }
  328. /**
  329. * 5. 认领 有关操作
  330. */
  331. const ClaimCustomer = async ()=>{
  332. let res = await claimHighSeasCustomerApi(route.query.id)
  333. if(res?.code == 200){
  334. ElMessage.success(res?.msg)
  335. router.go(-1)
  336. }
  337. }
  338. /**
  339. * 6. 删除弹窗 有关操作
  340. */
  341. const deleteDialogVisible = ref(false)
  342. const OpenDeleteDialog = ()=>{
  343. deleteDialogVisible.value = true
  344. }
  345. // 删除后执行的操作
  346. const HandleDeleteConfirm = ()=>{
  347. router.go(-1)
  348. }
  349. onMounted(async ()=>{
  350. // 获取学校的基础信息
  351. customerBaseMsg.value = JSON.parse(sessionStorage.getItem('customerMsg') || '{}')
  352. })
  353. </script>
  354. <style lang="scss" scoped>
  355. .main_container{
  356. gap:16px;
  357. :deep(.top_right){
  358. flex: 1 1;
  359. .header_content{
  360. display: flex;
  361. align-items: center;
  362. gap:10px;
  363. font-weight: 600;
  364. font-size: 20px;
  365. color: #333333;
  366. line-height: 28px;
  367. }
  368. .desc{
  369. display: flex;
  370. gap:5px 16px;
  371. flex-wrap: wrap;
  372. font-size: 12px;
  373. color: #999999;
  374. margin-top: 8px;
  375. margin-bottom: 16px;
  376. }
  377. .action{
  378. display: flex;
  379. gap:16px;
  380. .el-button{
  381. margin:0;
  382. .img,
  383. img{
  384. font-size: 16px;
  385. width: 16px;
  386. height: 16px;
  387. margin-right: 4px;
  388. }
  389. }
  390. }
  391. }
  392. .bottom_detail{
  393. overflow: auto;
  394. }
  395. }
  396. .operation_dialog{
  397. .follow_card{
  398. margin-top: 16px;
  399. }
  400. }
  401. </style>