index.vue 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. <template>
  2. <div class="main_container">
  3. <TopBackNav>
  4. <template #topRight>
  5. <div class="header_content">
  6. <span>{{ customerBaseMsg.name }}</span>
  7. <el-tag type="success" effect="light" size="small" :disable-transitions="true" class="status_tag">
  8. {{ customerBaseMsg.typeName }}
  9. </el-tag>
  10. </div>
  11. <div class="desc">
  12. <span>学段:{{ customerBaseMsg.stageName }}</span>
  13. <span>省份:{{ customerBaseMsg.provinceName }}</span>
  14. <span>地区:{{ customerBaseMsg.cityName }}</span>
  15. <span>地址:{{ customerBaseMsg.address }}</span>
  16. <span>归属人:{{ customerBaseMsg.claimUserName }}</span>
  17. <span>认领时间:{{ customerBaseMsg.claimDatetime }}</span>
  18. <span>上次跟进时间:{{ customerBaseMsg.lastFollowDatetime }}</span>
  19. </div>
  20. <div class="action">
  21. <el-button class="button_background" @click="OpenFollowlFormDialog"><img :src="peopleEditIcon" alt=""> 写跟进</el-button>
  22. <el-button class="button_border" @click="OpenConcactPeoplelFormDialog"><img :src="addIcon" alt=""> 新增联系人</el-button>
  23. <el-button class="button_refresh" @click="OpenSchoolFormDialog"><img :src="editIcon" alt="" > 编辑</el-button>
  24. <el-button class="button_refresh" @click="OpenTransferPublicDialog"><img :src="poepleMoveIcon" alt=""> 转至公海</el-button>
  25. <el-button class="button_refresh" @click="OpenTransferFormDialog"><img :src="exchangeIcon" alt="" > 转让</el-button>
  26. <el-button class="button_refresh" @click="OpenOperationRecordDialog"><img :src="logIcon" alt=""> 操作记录</el-button>
  27. </div>
  28. </template>
  29. </TopBackNav>
  30. <div class="page_item bottom_detail end_item">
  31. <TabSearch :defaultTabKey="defaultShowTab"
  32. tabType="line" :tabList="tabList"
  33. @tabChange="HandleTabChange"
  34. />
  35. <div class="page_solid_line" />
  36. <div class="page_jg_20" style="flex-shrink: 0 !important;"></div>
  37. <!-- 联系人详情 -->
  38. <ContactDetail :contactReloadFlag="contactReloadFlag" v-if="defaultShowTab === 'contactDetails'"/>
  39. <CustomerStatusOverview :followReloadFlag="followReloadFlag" v-if="defaultShowTab === 'messageOverview'"/>
  40. </div>
  41. <!-- 转让 弹窗 -->
  42. <FormDialog
  43. v-if="transferFormDialogVisible"
  44. title="转让" :visible="transferFormDialogVisible"
  45. :submitLoading="transferFormDialogSubmitLoading"
  46. :defaultFormData="transferDefaultFormData"
  47. :formItemList="formItemList"
  48. @close="CloseTransferFormDialog"
  49. @confirm="HandleTransferFormDialogConfirm">
  50. </FormDialog>
  51. <!-- 操作记录 弹窗 -->
  52. <CustomerOperationDialog
  53. v-if="operationRecordDialogVisible"
  54. v-model:dialogVisible="operationRecordDialogVisible">
  55. </CustomerOperationDialog>
  56. <!-- 编辑学校弹窗 -->
  57. <SchoolFormDialog
  58. v-model:visible="schoolVisible"
  59. v-model:submitLoading="schoolSubmitLoading"
  60. :defaultFormData="schoolDefaultFormData"
  61. @confirm="HandleSchoolFormDialogConfirm">
  62. </SchoolFormDialog>
  63. <!-- 新增联系人弹窗 -->
  64. <ConcactPeopleFormDialog
  65. v-if="concactPeopleVisible"
  66. v-model:visible="concactPeopleVisible"
  67. title="新增联系人"
  68. :defaultFormData="concactPeopleDefaultFormData"
  69. v-model:submitLoading="concactPeopleSubmitLoading"
  70. @confirm="HandleConcactPeopleDialogConfirm">
  71. </ConcactPeopleFormDialog>
  72. <!-- 写跟进弹窗 -->
  73. <FollowFormDialog
  74. v-if="followVisible"
  75. v-model:visible="followVisible"
  76. :defaultFormData="followDefaultFormData"
  77. @confirm="HandleFollowDialogConfirm">
  78. </FollowFormDialog>
  79. <!-- 转至公海 提示弹窗 -->
  80. <Dialog :visible="transferPublicVisible"
  81. :submitLoading="transferPublicSubmitLoading"
  82. @close="CloseTransferPublicDialog"
  83. @confirm="HandleTransferPublicConfirm">
  84. 请确认是否将【{{customerBaseMsg.name}}】转至公海
  85. </Dialog>
  86. </div>
  87. </template>
  88. <script setup lang="ts">
  89. import { ref, computed, onMounted, onUnmounted } from 'vue';
  90. import { useRoute, useRouter } from 'vue-router';
  91. import TopBackNav from '@/baseComponents/TopBackNav.vue';
  92. import addIcon from '@/assets/icon/add.svg';
  93. import peopleEditIcon from '@/assets/icon/people_edit.png'
  94. import poepleMoveIcon from '@/assets/icon/people_move.png'
  95. import editIcon from '@/assets/icon/edit.svg'
  96. import exchangeIcon from '@/assets/icon/exchange.png'
  97. import logIcon from '@/assets/icon/log.png'
  98. import TabSearch from '@/baseComponents/TabSearch.vue';
  99. import {tabList} from './tabSearch'
  100. import FormDialog from '@/baseComponents/FormDialog.vue';
  101. import {formItemList} from './formDialog'
  102. import ContactDetail from './contactDetail/index.vue'
  103. import CustomerStatusOverview from './customerStatusOverview/index.vue'
  104. import SchoolFormDialog from '@/components/SchoolFormDialog/index.vue'
  105. import ConcactPeopleFormDialog from '@/components/ConcactPeopleFormDialog/index.vue'
  106. import FollowFormDialog from './components/FollowFormDialog/index.vue'
  107. import Dialog from '@/baseComponents/Dialog.vue';
  108. import CustomerOperationDialog from '@/components/CustomerOperationDialog/index.vue'
  109. import {
  110. updatePrivateCustomerApi,
  111. sendBackHighSeasCustomerApi,
  112. transferCustomerApi,
  113. getTransferPeopleListApi,
  114. addPrivateContactApi,
  115. } from '@/api/myCustomer'
  116. interface CustomerBaseMsg {
  117. name:string, //学校名称
  118. typeName:string,
  119. stageName:string, //学段
  120. stageId:string,
  121. provinceName:string, //省份
  122. provinceId:string,
  123. cityName:string, // 地区
  124. cityId:string,
  125. address:string, //地址
  126. claimUserName:string, //归属人
  127. claimDatetime:string, //认领时间
  128. lastFollowDatetime:string, //上次跟进时间
  129. }
  130. const route = useRoute()
  131. const router = useRouter()
  132. const customerBaseMsg = ref<CustomerBaseMsg>({});
  133. // 默认列表的tab切换
  134. const defaultShowTab = ref('messageOverview')
  135. const HandleTabChange = (val)=>{
  136. defaultShowTab.value = val
  137. }
  138. /** 1. 转至公海 弹窗有关数据 及操作 */
  139. const transferPublicVisible = ref(false)
  140. const transferPublicSubmitLoading = ref(false)
  141. const CloseTransferPublicDialog = ()=>{
  142. transferPublicSubmitLoading.value = false
  143. transferPublicVisible.value = false
  144. }
  145. const OpenTransferPublicDialog = ()=>{
  146. transferPublicVisible.value = true
  147. }
  148. const HandleTransferPublicConfirm = async ()=>{
  149. transferPublicSubmitLoading.value = true
  150. let res = undefined
  151. try{
  152. res = await sendBackHighSeasCustomerApi(route.query.id)
  153. }catch{}
  154. if(res?.code == 200){
  155. CloseTransferPublicDialog()
  156. router.go(-1)
  157. }else{
  158. transferPublicSubmitLoading.value = false
  159. }
  160. }
  161. /**2. 转让弹窗相关内容及操作 */
  162. const transferFormDialogVisible = ref(false)
  163. const transferFormDialogSubmitLoading = ref(false)
  164. const transferDefaultFormData = ref({})
  165. const OpenTransferFormDialog = async()=>{
  166. console.log('打开转让弹窗')
  167. transferFormDialogVisible.value = true
  168. transferDefaultFormData.value = {
  169. schoolName: customerBaseMsg.value.name,
  170. currentOwner: customerBaseMsg.value.claimUserName,
  171. newOwner:'',
  172. }
  173. await GetOwnerList()
  174. }
  175. const CloseTransferFormDialog=()=>{
  176. transferFormDialogSubmitLoading.value = false
  177. transferFormDialogVisible.value = false
  178. }
  179. // 转让确认
  180. const HandleTransferFormDialogConfirm = async (params)=>{
  181. transferFormDialogSubmitLoading.value = true
  182. const {formData,formRef} = params
  183. let finalParams = {
  184. customerId: route.query.id,
  185. userId: JSON.parse(formData.newOwner || '{}')?.userId,
  186. userName: JSON.parse(formData.newOwner || '{}')?.userName,
  187. groupId: JSON.parse(formData.newOwner || '{}')?.groupId,
  188. }
  189. let res = await transferCustomerApi(finalParams)
  190. if(res?.code == 200){
  191. CloseTransferFormDialog()
  192. router.go(-1)
  193. }else{
  194. transferFormDialogSubmitLoading.value = false
  195. }
  196. }
  197. // 获取归属人列表
  198. const GetOwnerList = async ()=>{
  199. let res = await getTransferPeopleListApi(route.query.id)
  200. if(res?.code == 200){
  201. let userList = res?.data?.map(item=>{
  202. return {
  203. label:item.userName,
  204. value:JSON.stringify({
  205. userId:item.userId,
  206. userName:item.userName,
  207. groupId:item.groupId
  208. })
  209. }
  210. }) || []
  211. formItemList.value = formItemList.value.map(item=>{
  212. if(item.key == 'newOwner'){
  213. item.selectList = userList
  214. }
  215. return item
  216. })
  217. }
  218. }
  219. /** 3. 新增联系人有关数据 及操作 */
  220. const concactPeopleVisible = ref(false)
  221. const concactPeopleSubmitLoading = ref(false)
  222. const concactPeopleDefaultFormData = ref({})
  223. const contactReloadFlag = ref(0) //重新加载联系人数据标识
  224. const OpenConcactPeoplelFormDialog = ()=>{
  225. concactPeopleVisible.value = true
  226. }
  227. const CloseConcactPeoplelFormDialog = ()=>{
  228. concactPeopleVisible.value = false
  229. concactPeopleSubmitLoading.value = false
  230. concactPeopleDefaultFormData.value = {}
  231. }
  232. // 新增确认
  233. const HandleConcactPeopleDialogConfirm = async (params)=>{
  234. concactPeopleSubmitLoading.value = true
  235. const {formData,formRef} = params
  236. let finalParams = {
  237. customerId: route.query.id,
  238. name: formData.name,
  239. positionId:JSON.parse(formData.position || '{}')?.value,
  240. positionName: JSON.parse(formData.position || '{}')?.label,
  241. phoneNo: formData.phoneNo,
  242. officePhoneNo: formData.officePhoneNo,
  243. remark: formData.remark,
  244. }
  245. let res = await addPrivateContactApi(finalParams)
  246. if(res?.code == 200){
  247. CloseConcactPeoplelFormDialog()
  248. // 重新查询联系人信息
  249. contactReloadFlag.value += 1
  250. }else{
  251. concactPeopleSubmitLoading.value = false
  252. }
  253. }
  254. /** 4. 写跟进 弹窗有关数据 及操作*/
  255. const followVisible = ref(false)
  256. const followDefaultFormData = ref({})
  257. const followReloadFlag = ref(0) //重新加载跟进信息标识
  258. const OpenFollowlFormDialog = ()=>{
  259. followVisible.value = true
  260. followDefaultFormData.value = {
  261. school:customerBaseMsg.value.name,
  262. }
  263. }
  264. // 跟进弹窗关闭后的后续操作
  265. const HandleFollowDialogConfirm = ()=>{
  266. followDefaultFormData.value = {}
  267. followReloadFlag.value += 1
  268. }
  269. /** 5. 操作记录相关内容及操作*/
  270. const operationRecordDialogVisible = ref(false)
  271. // 打开操作记录弹窗
  272. const OpenOperationRecordDialog=()=>{
  273. operationRecordDialogVisible.value = true
  274. }
  275. /** 6.编辑学校 有关数据 及操作 */
  276. const schoolVisible = ref(false)
  277. const schoolSubmitLoading = ref(false)
  278. const schoolDefaultFormData = ref({})
  279. const OpenSchoolFormDialog = ()=>{
  280. schoolVisible.value = true
  281. schoolDefaultFormData.value = {
  282. ...customerBaseMsg.value,
  283. schoolStage:JSON.stringify({
  284. label:customerBaseMsg.value?.stageName,
  285. value:customerBaseMsg.value?.stageId,
  286. }),
  287. provinceArea:{
  288. province:JSON.stringify({
  289. label:customerBaseMsg.value?.provinceName,
  290. value:customerBaseMsg.value?.provinceId,
  291. }),
  292. district:JSON.stringify({
  293. label:customerBaseMsg.value?.cityName,
  294. value:customerBaseMsg.value?.cityId,
  295. }),
  296. }
  297. }
  298. }
  299. const CloseSchoolFormDialog = ()=>{
  300. schoolVisible.value = false
  301. schoolSubmitLoading.value = false
  302. schoolDefaultFormData.value = {}
  303. }
  304. // 修改确认
  305. const HandleSchoolFormDialogConfirm = async (params)=>{
  306. schoolSubmitLoading.value = true
  307. const {formData,formRef} = params
  308. let finalParams = {
  309. id: formData.id,
  310. name: formData.name,
  311. stageId: JSON.parse(formData.schoolStage || '{}')?.value,
  312. stageName: JSON.parse(formData.schoolStage || '{}')?.label,
  313. provinceId: JSON.parse(formData.provinceArea.province || '{}')?.value,
  314. provinceName: JSON.parse(formData.provinceArea.province || '{}')?.label,
  315. cityId: JSON.parse(formData.provinceArea.district || '{}')?.value,
  316. cityName: JSON.parse(formData.provinceArea.district || '{}')?.label,
  317. address: formData.address,
  318. }
  319. let res = undefined
  320. try{
  321. res = await updatePrivateCustomerApi(finalParams)
  322. }catch{}
  323. if(res?.code == 200){
  324. customerBaseMsg.value = {
  325. ...customerBaseMsg.value,
  326. name:formData.name,
  327. stageId: JSON.parse(formData.schoolStage || '{}')?.value,
  328. stageName: JSON.parse(formData.schoolStage || '{}')?.label,
  329. provinceId: JSON.parse(formData.provinceArea.province || '{}')?.value,
  330. provinceName: JSON.parse(formData.provinceArea.province || '{}')?.label,
  331. cityId: JSON.parse(formData.provinceArea.district || '{}')?.value,
  332. cityName: JSON.parse(formData.provinceArea.district || '{}')?.label,
  333. address: formData.address,
  334. }
  335. sessionStorage.setItem('customerMsg',JSON.stringify(customerBaseMsg.value))
  336. CloseSchoolFormDialog()
  337. }else{
  338. schoolSubmitLoading.value = false
  339. }
  340. }
  341. onMounted(async ()=>{
  342. // 获取学校的基础信息
  343. customerBaseMsg.value = JSON.parse(sessionStorage.getItem('customerMsg') || '{}')
  344. })
  345. onUnmounted(()=>{
  346. sessionStorage.removeItem('customerMsg')
  347. })
  348. </script>
  349. <style lang="scss" scoped>
  350. .main_container{
  351. gap:16px;
  352. :deep(.top_right){
  353. flex: 1 1;
  354. .header_content{
  355. display: flex;
  356. align-items: center;
  357. gap:10px;
  358. font-weight: 600;
  359. font-size: 20px;
  360. color: #333333;
  361. line-height: 28px;
  362. .status_tag{
  363. height: 25px;
  364. border-radius: 4px ;
  365. padding:0 8px;
  366. font-weight: 400;
  367. font-size: 12px;
  368. color: #2E64FA;
  369. background: rgba(46,100,250,0.1);
  370. }
  371. }
  372. .desc{
  373. display: flex;
  374. gap:5px 16px;
  375. flex-wrap: wrap;
  376. font-size: 12px;
  377. color: #999999;
  378. margin-top: 8px;
  379. margin-bottom: 16px;
  380. }
  381. .action{
  382. display: flex;
  383. gap:16px;
  384. .el-button{
  385. margin:0;
  386. img{
  387. width: 16px;
  388. height: 16px;
  389. margin-right: 4px;
  390. }
  391. }
  392. }
  393. }
  394. .bottom_detail{
  395. overflow: auto;
  396. }
  397. }
  398. .operation_dialog{
  399. .follow_card{
  400. margin-top: 16px;
  401. }
  402. }
  403. </style>