miniJxs.html 130 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport"
  7. content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no, viewport-fit=cover" />
  8. <title></title>
  9. <!-- 引入样式文件 -->
  10. <link rel="stylesheet"
  11. href="https://wl-1306604067.cos.ap-guangzhou.myqcloud.com/production/ct/103548289110001/1758012584633/vant.css" />
  12. <!-- 必须先引入vue, 后使用vant-ui -->
  13. <script
  14. src="https://wl-1306604067.cos.ap-guangzhou.myqcloud.com/production/ct/103548289110001/1742017957144/vue.js"></script>
  15. <!-- 引入vant的组件库-->
  16. <!-- 引入 Vant 的 JS 文件 -->
  17. <script
  18. src="https://wl-1306604067.cos.ap-guangzhou.myqcloud.com/production/ct/103548289110001/1758012748487/vant.min.js"></script>
  19. <script src="https://res.wx.qq.com/open/js/jweixin-1.6.0.js"></script>
  20. <script src="https://open.work.weixin.qq.com/wwopen/js/jwxwork-1.0.0.js"></script>
  21. <script src="js/select-date.js"></script>
  22. <script
  23. src="https://wl-1306604067.cos.ap-guangzhou.myqcloud.com/production/ct/103548289110001/1758187289797/echarts.js"></script>
  24. <script src="js/echarts-wordcloud.js"></script>
  25. <!-- <script src="js/vconsole.min.js"></script>
  26. <script>
  27. var vConsole = new window.VConsole();
  28. </script> -->
  29. </head>
  30. <style>
  31. body {
  32. margin: 0;
  33. padding: 0;
  34. }
  35. .box {
  36. width: 100vw;
  37. /* height: 100vh; */
  38. box-sizing: border-box;
  39. background: #FAFAFA;
  40. }
  41. .page4 {
  42. width: 100vw;
  43. /* height: 100vh; */
  44. box-sizing: border-box;
  45. display: flex;
  46. flex-direction: column;
  47. }
  48. .popup_list {
  49. width: 100%;
  50. height: 100%;
  51. box-sizing: border-box;
  52. display: flex;
  53. flex-direction: column;
  54. padding: 44px 30px 10px;
  55. }
  56. .popup_item {
  57. padding: 15px 0;
  58. font-weight: bold;
  59. font-size: 16px;
  60. color: #222222;
  61. line-height: 24px;
  62. }
  63. .popup_line {
  64. height: 1px;
  65. background: linear-gradient(90deg, #000000 0%, rgba(0, 0, 0, 0) 100%);
  66. opacity: 0.1;
  67. }
  68. .mer_item {
  69. padding: 15px 0;
  70. font-weight: bold;
  71. font-size: 16px;
  72. color: #222222;
  73. line-height: 24px;
  74. border-bottom: 1px solid transparent;
  75. /* 占位 */
  76. border-image: linear-gradient(90deg, rgba(0, 0, 0, 0.1) 0%, transparent 100%) 1;
  77. }
  78. .mer_item_active {
  79. color: #1677FF;
  80. }
  81. .van-nav-bar__content {
  82. height: 44px;
  83. }
  84. .van-nav-bar__title {
  85. font-weight: bold;
  86. font-size: 14px;
  87. color: #222222;
  88. }
  89. .explain_list {
  90. display: flex;
  91. flex-direction: column;
  92. padding: 10px;
  93. font-weight: 400;
  94. font-size: 12px;
  95. color: #FFFFFF;
  96. line-height: 18px;
  97. }
  98. .explain_list div {
  99. padding-bottom: 10px;
  100. }
  101. .explain_list div:last-child {
  102. padding-bottom: 0;
  103. }
  104. .explain_icon {
  105. width: 20px;
  106. height: 20px;
  107. margin-left: 5px;
  108. }
  109. .navbar_icon {
  110. width: 24px;
  111. height: 24px;
  112. }
  113. .box_title {
  114. padding-left: 5px;
  115. }
  116. .van-nav-bar__left {
  117. padding: 0 10px;
  118. }
  119. .van-nav-bar__right {
  120. padding: 0 10px;
  121. }
  122. .van-hairline--bottom::after {
  123. border-bottom: none;
  124. }
  125. .top_data {
  126. display: flex;
  127. align-items: center;
  128. justify-content: flex-end;
  129. padding: 10px;
  130. height: 54px;
  131. background: #FFFFFF;
  132. box-sizing: border-box;
  133. position: fixed;
  134. top: 44px;
  135. left: 0;
  136. width: 100%;
  137. z-index: 2;
  138. }
  139. .top_data_bottom {
  140. display: flex;
  141. align-items: center;
  142. justify-content: flex-end;
  143. position: fixed;
  144. top: 98px;
  145. right: 0;
  146. width: 100%;
  147. z-index: 1;
  148. padding-right: 10px;
  149. background: #FAFAFA;
  150. }
  151. .outlet_data {
  152. display: flex;
  153. align-items: center;
  154. justify-content: flex-end;
  155. height: 34px;
  156. background: #FAFAFA;
  157. box-sizing: border-box;
  158. }
  159. .close_icon {
  160. width: 24px;
  161. height: 24px;
  162. }
  163. .memberReply_title {
  164. font-weight: 500;
  165. font-size: 14px;
  166. color: #222222;
  167. line-height: 20px;
  168. background: #FFFFFF;
  169. display: flex;
  170. align-items: center;
  171. justify-content: space-between;
  172. height: 44px;
  173. padding: 0 10px;
  174. width: 100%;
  175. box-sizing: border-box;
  176. }
  177. .pop_content {
  178. padding: 10px 10px 10px;
  179. background: #FAFAFA;
  180. height: calc(100vh - 44px);
  181. overflow: auto;
  182. box-sizing: border-box;
  183. }
  184. .select_box {
  185. display: flex;
  186. margin-bottom: 10px;
  187. }
  188. .select_day {
  189. display: flex;
  190. align-items: center;
  191. background: #FFFFFF;
  192. box-sizing: border-box;
  193. padding: 10px 15px;
  194. font-weight: 400;
  195. font-size: 12px;
  196. color: #222222;
  197. margin-right: 10px;
  198. border-radius: 10px;
  199. }
  200. .search_input {
  201. width: 160px;
  202. height: 38px;
  203. border-radius: 10px;
  204. }
  205. .van-search__content {
  206. background: #FFFFFF;
  207. padding-left: 0;
  208. }
  209. .van-search__label {
  210. font-weight: 400;
  211. font-size: 12px;
  212. color: #222222;
  213. width: unset;
  214. }
  215. .van-popover__wrapper {
  216. height: unset;
  217. }
  218. .top_data_title {
  219. display: flex;
  220. align-items: center;
  221. }
  222. .top_data_right {
  223. display: flex;
  224. align-items: center;
  225. }
  226. .item_gap {
  227. margin-right: 10px;
  228. }
  229. .top_data_title_text {
  230. font-weight: 500;
  231. font-size: 14px;
  232. color: #222222;
  233. padding-left: 5px;
  234. }
  235. .top_data_title_branch {
  236. font-weight: 400;
  237. font-size: 12px;
  238. color: #222222;
  239. max-width: 90px;
  240. white-space: nowrap;
  241. /* 禁止换行 */
  242. overflow: hidden;
  243. /* 隐藏溢出内容 */
  244. text-overflow: ellipsis;
  245. /* 显示省略号 */
  246. }
  247. .triangle {
  248. width: 0;
  249. height: 0;
  250. border: 6px solid transparent;
  251. border-top-color: #222222;
  252. margin-top: 6px;
  253. border-radius: 5px;
  254. margin-left: 5px;
  255. }
  256. .page4_content {
  257. padding: 131px 10px 10px;
  258. }
  259. .page4_content2 {
  260. padding: 131px 10px 10px;
  261. }
  262. .box_connect {
  263. width: 100%;
  264. background: #FFFFFF;
  265. padding: 10px 10px 15px;
  266. box-sizing: border-box;
  267. border-radius: 10px;
  268. margin-bottom: 15px;
  269. }
  270. .clientCharts_title_box {
  271. display: flex;
  272. align-items: center;
  273. justify-content: space-between;
  274. margin-bottom: 15px;
  275. }
  276. .clientCharts_titleA{
  277. font-weight: 500;
  278. font-size: 12px;
  279. color: #222222;
  280. display: flex;
  281. align-items: center;
  282. margin-bottom: 15px;
  283. }
  284. .clientCharts_title {
  285. font-weight: 500;
  286. font-size: 12px;
  287. color: #222222;
  288. display: flex;
  289. align-items: center;
  290. margin-bottom: 15px;
  291. }
  292. .clientCharts_title::before {
  293. content: '';
  294. width: 2px;
  295. height: 13px;
  296. background: #1677FF;
  297. border-radius: 1px;
  298. margin-right: 5px;
  299. display: inline-block;
  300. }
  301. .clientCharts_title_right {
  302. font-weight: 400;
  303. font-size: 12px;
  304. color: #1677FF;
  305. text-decoration-line: underline;
  306. }
  307. .all_data {
  308. display: flex;
  309. align-items: center;
  310. flex-wrap: wrap;
  311. margin-top: 15px;
  312. }
  313. .add_data_p {
  314. font-weight: 400;
  315. font-size: 12px;
  316. color: #999999;
  317. padding: 4px 10px;
  318. background: #FFFFFF;
  319. border-radius: 5px;
  320. border: 1px solid #CCCCCC;
  321. margin-top: 0;
  322. margin-right: 15px;
  323. margin-bottom: 10px;
  324. }
  325. .allData_bg {
  326. background: #1677FF;
  327. border-radius: 5px;
  328. border: 1px solid #1677FF;
  329. color: #FFFFFF;
  330. }
  331. /* 选择日期组件开始 */
  332. .select_date {
  333. display: flex;
  334. align-items: center;
  335. }
  336. .date_list {
  337. width: 212px;
  338. box-sizing: border-box;
  339. display: flex;
  340. align-items: center;
  341. justify-content: space-between;
  342. background: #EDF3F8;
  343. border-radius: 20px;
  344. padding: 2px;
  345. }
  346. .filter_time_item {
  347. padding: 4px 0 3px;
  348. font-weight: 400;
  349. font-size: 12px;
  350. color: #222222;
  351. line-height: 17px;
  352. white-space: nowrap;
  353. }
  354. .filter_time1 {
  355. padding-left: 14px;
  356. padding-right: 14px;
  357. }
  358. .filter_time2 {
  359. padding-left: 11px;
  360. padding-right: 11px;
  361. }
  362. .filter_time3 {
  363. padding-left: 7px;
  364. padding-right: 7px;
  365. }
  366. .filter_time4 {
  367. padding-left: 8px;
  368. padding-right: 8px;
  369. }
  370. .current_date {
  371. font-weight: 400;
  372. font-size: 12px;
  373. color: #1677FF;
  374. line-height: 17px;
  375. background: #FFFFFF;
  376. border-radius: 12px;
  377. }
  378. /* 选择日期组件结束 */
  379. .num_item_title {
  380. font-weight: 400;
  381. font-size: 12px;
  382. line-height: 17px;
  383. padding-bottom: 5px;
  384. color: #666666;
  385. }
  386. .num_item_count {
  387. font-weight: bold;
  388. font-size: 16px;
  389. line-height: 24px;
  390. padding-bottom: 5px;
  391. color: #222222;
  392. }
  393. .num_item_data {
  394. display: flex;
  395. align-items: center;
  396. font-weight: 400;
  397. font-size: 10px;
  398. color: #999999;
  399. }
  400. .selected_color {
  401. color: #1677FF;
  402. }
  403. .client_item_icon {
  404. width: 12px;
  405. height: 12px;
  406. }
  407. .branch_table {
  408. overflow-x: auto;
  409. width: 100%;
  410. }
  411. .branch_header {
  412. padding: 10px;
  413. display: flex;
  414. align-items: center;
  415. justify-content: space-between;
  416. background: #F7F9FC;
  417. border-radius: 10px;
  418. font-weight: 500;
  419. font-size: 12px;
  420. color: #222222;
  421. min-width: max-content;
  422. text-align: center;
  423. }
  424. .branch_header div {
  425. min-width: 30px;
  426. }
  427. .branch_item {
  428. padding: 10px;
  429. display: flex;
  430. align-items: center;
  431. justify-content: space-between;
  432. font-weight: 400;
  433. font-size: 12px;
  434. color: #222222;
  435. border-bottom: 1px solid #E5E8ED;
  436. text-align: center;
  437. word-wrap: break-word;
  438. min-width: max-content;
  439. }
  440. .branch_item div {
  441. min-width: 30px;
  442. }
  443. .interact_box_bottom {
  444. display: flex;
  445. align-items: center;
  446. justify-content: space-between;
  447. }
  448. .interact_box_bottom {
  449. display: flex;
  450. align-items: center;
  451. justify-content: space-between;
  452. }
  453. .interact_line {
  454. width: 1px;
  455. /* margin: 0 8px; */
  456. height: 66px;
  457. background: linear-gradient(180deg, rgba(229, 232, 237, 0) 0%, #E5E8ED 51%, rgba(229, 232, 237, 0) 100%);
  458. }
  459. .interact_item {
  460. display: flex;
  461. flex-direction: column;
  462. align-items: center;
  463. text-align: center;
  464. }
  465. .leadGen_box {
  466. padding: 10px;
  467. background: #FAFAFA;
  468. border-radius: 10px;
  469. }
  470. .leadGen_box {
  471. padding: 10px;
  472. background: #FAFAFA;
  473. border-radius: 10px;
  474. }
  475. .table_carList {
  476. width: 100%;
  477. display: flex;
  478. align-items: center;
  479. overflow-x: auto;
  480. margin-bottom: 20px;
  481. }
  482. .table_carBox {
  483. display: flex;
  484. flex-direction: column;
  485. align-items: center;
  486. font-weight: 400;
  487. font-size: 12px;
  488. color: #222222;
  489. border-radius: 34px;
  490. margin-right: 10px;
  491. padding: 0 15px;
  492. }
  493. .table_carBox_bg {
  494. background: linear-gradient(#FFFFFF 0%, #E6F0FF 100%);
  495. }
  496. .table_car {
  497. width: 90px;
  498. height: 45px;
  499. }
  500. .table_carline {
  501. width: 16px;
  502. height: 3px;
  503. border-radius: 34px;
  504. margin-top: 2px;
  505. }
  506. .table_carline_bg {
  507. background: #1677FF;
  508. }
  509. .data_tips {
  510. font-weight: 400;
  511. font-size: 12px;
  512. line-height: 17px;
  513. color: #C4CFDA;
  514. text-align: center;
  515. margin: 5px 0 24px;
  516. }
  517. .step_list {
  518. width: 100%;
  519. display: flex;
  520. align-items: center;
  521. overflow-x: auto;
  522. }
  523. .step_box {
  524. min-width: 125px;
  525. padding: 10px;
  526. font-weight: 400;
  527. font-size: 12px;
  528. color: #666666;
  529. background: #F7F9FC;
  530. border-radius: 10px;
  531. margin-right: 10px;
  532. }
  533. .step_box_bg {
  534. background: #1677FF;
  535. color: #FFFFFF;
  536. }
  537. .step_num {
  538. font-weight: bold;
  539. font-size: 16px;
  540. color: #1677FF;
  541. padding-top: 10px;
  542. line-height: 24px;
  543. }
  544. .step_num_bg {
  545. color: #FFFFFF;
  546. }
  547. .van_loading {
  548. height: 400px;
  549. display: flex;
  550. align-items: center;
  551. justify-content: center;
  552. }
  553. </style>
  554. <body>
  555. <div id="box" class="box">
  556. <!-- 数据查看 -->
  557. <div class="page4">
  558. <van-nav-bar :title="jxsName" class="navbar" fixed>
  559. <template #left>
  560. <image class="navbar_icon" src="./img/jxs1.png"></image>
  561. </template>
  562. <template #right>
  563. <image class="navbar_icon" src="./img/jxs2.png" @click="handleShowPopup"></image>
  564. </template>
  565. </van-nav-bar>
  566. <div class="top_data">
  567. <!-- <div class="top_data_title">
  568. <image class="navbar_icon" src="./img/jxs6.png"></image>
  569. <div class="top_data_title_text">{{pageTitle}}</div>
  570. </div> -->
  571. <!-- <div class="top_data_right" v-if="pageTitle === '客户资产'">
  572. <div class="top_data_title item_gap" @click="showPicker = true">
  573. <div class="top_data_title_branch">网点:{{outletName}}</div>
  574. <div class="triangle"></div>
  575. </div>
  576. <div class="top_data_title" @click="showDeptPicker = true">
  577. <div class="top_data_title_branch">部门:{{deptName}}</div>
  578. <div class="triangle"></div>
  579. </div>
  580. </div> -->
  581. <select-date :page-date="pageDate" @change-date="handleChangeDate"></select-date>
  582. </div>
  583. <div class="top_data_bottom">
  584. <div class="outlet_data item_gap" @click="showPicker = true">
  585. <div class="top_data_title_branch">网点:{{outletName}}</div>
  586. <div class="triangle"></div>
  587. </div>
  588. <div class="outlet_data" @click="showDeptPicker = true">
  589. <div class="top_data_title_branch">部门:{{deptName}}</div>
  590. <div class="triangle"></div>
  591. </div>
  592. </div>
  593. <van-popup v-model="showPopup" duration="0.2" closeable position="top" :lock-scroll="false"
  594. :style="{ height: '100vh' }" @close="handleClosePopup">
  595. <div class="popup_list" v-show="!showMer">
  596. <!-- <div class="popup_item" @click="handlePage(1)">客户资产</div>
  597. <div class="popup_line"></div>
  598. <div class="popup_item" @click="handlePage(2)">聊天分析</div>
  599. <div class="popup_line"></div>
  600. <div class="popup_item" @click="handlePage(3)">员工监测</div>
  601. <div class="popup_line"></div>
  602. <div class="popup_item" @click="handlePage(4)">运营任务</div>
  603. <div class="popup_line"></div> -->
  604. <!-- <div class="popup_item" @click="showMer = true">切换商户</div>
  605. <div class="popup_line"></div> -->
  606. <div class="popup_item" @click="handleLoginOut">退出登录</div>
  607. </div>
  608. <div class="popup_list" v-show="showMer">
  609. <div class="mer_item" :class="{'mer_item_active': tenancyId == item.id}" v-for="(item, index) in merList"
  610. :key="index" @click="handleSelectMer(item)">{{item.name}}</div>
  611. </div>
  612. </van-popup>
  613. <van-popup v-model="showPicker" duration="0.2" round position="bottom">
  614. <van-picker title="网点" show-toolbar :columns="outletsData" @confirm="onConfirm" @cancel="showPicker = false" />
  615. </van-popup>
  616. <van-popup v-model="showDeptPicker" duration="0.2" round position="bottom">
  617. <van-picker title="部门" show-toolbar :columns="deptData" @confirm="onDeptConfirm"
  618. @cancel="showDeptPicker = false" />
  619. </van-popup>
  620. <!-- 顾问响应统计 -->
  621. <van-popup v-model="showMemberReply" duration="0.2" position="right" :overlay="false" :lock-scroll="false"
  622. :style="{ width: '100%', height: '100vh' }">
  623. <div class="memberReply_title">
  624. <image class="close_icon" src="./img/close.png" @click="closeReply"></image>
  625. <div>顾问响应统计</div>
  626. <div class="close_icon"></div>
  627. </div>
  628. <div class="pop_content">
  629. <div class="select_box">
  630. <van-popover v-model="showDatePicker" trigger="click" close-on-click-action close-on-click-outside
  631. :actions="actions" @select="onSelect">
  632. <template #reference>
  633. <div class="select_day">
  634. <div class="top_data_title_branch">时间:{{timeData}}</div>
  635. <div class="triangle"></div>
  636. </div>
  637. </template>
  638. </van-popover>
  639. <van-search class="search_input" v-model="keyword" search :clearable="false" label="顾问:" left-icon=""
  640. right-icon="search" @search="handleSearch" @click-right-icon="handleSearch"></van-search>
  641. <van-calendar type="range" v-model="showSelfDate" @confirm="onSelfConfirm" color="#1677FF"
  642. :min-date="minDate" :max-date="maxDate" :allow-same-day="true"></van-calendar>
  643. </div>
  644. <div class="box_connect">
  645. <van-loading type="spinner" color="#1989fa" class="van_loading" v-if="loading"></van-loading>
  646. <div class="branch_table" style="margin-bottom: 20px;" v-if="!loading">
  647. <div class="branch_header" style="box-sizing: border-box;">
  648. <div style="width: 80px;">顾问</div>
  649. <div style="width: 50px;">今日处理<br />消息数</div>
  650. <div style="width: 40px;">超时<br />消息数</div>
  651. <div style="width: 50px;">平均响应<br />时间</div>
  652. <div style="width: 30px;">管理</div>
  653. </div>
  654. <div class="branch_item" style="box-sizing: border-box;" v-for="(item, index) in memberReplyData"
  655. :key="index">
  656. <div style="width: 80px;max-width: 80px;">{{item.memberName}}</div>
  657. <div style="width: 50px;">{{item.replyMsg}}</div>
  658. <div style="width: 40px;">{{item.timeoutMsg}}</div>
  659. <div style="width: 50px;">{{formatTime(item.avgReplyDuration)}}</div>
  660. <div style="width: 30px;color: #1677FF;" @click="handleItemMemberReply(item)">详情</div>
  661. </div>
  662. </div>
  663. <van-pagination v-model="currentPage" :total-items="totalItems" :show-page-size="3" force-ellipses
  664. @change="handleChangePage" />
  665. </div>
  666. </div>
  667. </van-popup>
  668. <!-- 顾问响应统计详情 -->
  669. <van-popup v-model="showItemMemberReply" position="right" duration="0.2" :lock-scroll="false" :overlay="false"
  670. :style="{ width: '100%', height: '100vh' }">
  671. <div class="memberReply_title">
  672. <image class="close_icon" src="./img/close.png" @click="closeItemMemberReply"></image>
  673. <div>顾问:{{currentMemberName}}</div>
  674. <div class="close_icon"></div>
  675. </div>
  676. <div class="pop_content">
  677. <div class="select_box">
  678. <van-popover v-model="showDatePicker2" trigger="click" close-on-click-action close-on-click-outside
  679. :actions="actions" @select="onSelect">
  680. <template #reference>
  681. <div class="select_day">
  682. <div class="top_data_title_branch">时间:{{timeData}}</div>
  683. <div class="triangle"></div>
  684. </div>
  685. </template>
  686. </van-popover>
  687. <van-calendar type="range" v-model="showSelfDate" @confirm="onSelfConfirm" color="#1677FF"
  688. :min-date="minDate" :max-date="maxDate" :allow-same-day="true"></van-calendar>
  689. </div>
  690. <div class="box_connect">
  691. <van-loading type="spinner" color="#1989fa" class="van_loading" v-if="loading"></van-loading>
  692. <div class="branch_table" style="margin-bottom: 20px;" v-if="!loading">
  693. <div class="branch_header">
  694. <div style="width: 60px;">客户昵称</div>
  695. <div style="width: 100px;">手机号</div>
  696. <div style="width: 80px;">最新消息<br />时间</div>
  697. <div style="width: 60px;">等待时间</div>
  698. <div style="width: 100px;">最新消息<br />内容</div>
  699. </div>
  700. <div class="branch_item" v-for="(item, index) in memberDetailReplyData" :key="index">
  701. <div style="width: 60px;">{{item.clientName}}</div>
  702. <div style="width: 100px;">{{item.clientPhone}}</div>
  703. <div style="width: 80px;">{{timeFormat(item.msgTime)}}</div>
  704. <div style="width: 60px;">{{formatTime(item.waitSeconds)}}</div>
  705. <div style="width: 100px;">{{item.content}}</div>
  706. </div>
  707. </div>
  708. <van-pagination v-model="currentItemPage" :total-items="itemTotalItems" :show-page-size="3" force-ellipses
  709. @change="handleChangeItemPage" />
  710. </div>
  711. </div>
  712. </van-popup>
  713. <!-- 顾问完成情况统计 -->
  714. <van-popup v-model="showDoneReply" position="right" duration="0.2" :overlay="false" :lock-scroll="false"
  715. :style="{ width: '100%', height: '100vh' }">
  716. <div class="memberReply_title">
  717. <image class="close_icon" src="./img/close.png" @click="closeReply"></image>
  718. <div>顾问完成情况统计</div>
  719. <div class="close_icon"></div>
  720. </div>
  721. <div class="pop_content">
  722. <div class="select_box">
  723. <van-popover v-model="showDatePicker3" trigger="click" close-on-click-action close-on-click-outside
  724. :actions="actions" @select="onSelect">
  725. <template #reference>
  726. <div class="select_day">
  727. <div class="top_data_title_branch">时间:{{timeData}}</div>
  728. <div class="triangle"></div>
  729. </div>
  730. </template>
  731. </van-popover>
  732. <van-calendar type="range" v-model="showSelfDate" @confirm="onSelfConfirm" color="#1677FF"
  733. :min-date="minDate" :max-date="maxDate" :allow-same-day="true"></van-calendar>
  734. </div>
  735. <div class="box_connect">
  736. <div class="branch_table" style="margin-bottom: 20px;">
  737. <div class="branch_header" style="box-sizing: border-box;">
  738. <div style="width: 60px;">顾问</div>
  739. <div style="width: 60px;">网点</div>
  740. <div style="width: 60px;">下发任务数</div>
  741. <div style="width: 60px;">完成任务数</div>
  742. </div>
  743. <div class="branch_item" style="box-sizing: border-box;" v-for="(item, index) in doneReplyData"
  744. :key="index">
  745. <div style="width: 60px;">{{item.memberName}}</div>
  746. <div style="width: 60px;">{{item.outletName}}</div>
  747. <div style="width: 60px;">{{item.taskNum}}</div>
  748. <div style="width: 60px;">{{item.completeNum}}</div>
  749. </div>
  750. </div>
  751. <van-pagination v-model="currentPage" :total-items="totalItems" :show-page-size="3" force-ellipses
  752. @change="handleChangePage" />
  753. </div>
  754. </div>
  755. </van-popup>
  756. <div class="page4_content" v-show="pageTitle === '客户资产'">
  757. <!-- 客户资产 -->
  758. <div class="box_connect">
  759. <div class="clientCharts_titleA" style="margin-bottom: 0;">
  760. <image class="navbar_icon" src="./img/jxs6.png"></image>
  761. <span class="box_title">客户资产总数据</span>
  762. <van-popover style="height: 20px;" v-model="showPopover" trigger="click" theme="dark" placement="right">
  763. <div class="explain_list">
  764. <div>总客户数:添加企微的客户总数</div>
  765. <div>互动客户数:有产生过客户动态(包括不限于内容浏览、活动浏览、聊天等)的客户数</div>
  766. <div>留资报名客户数:填写过表单(含留资/活动报名等)的客户数</div>
  767. <div>到店客户:展厅进店及售后回站客户数</div>
  768. <div>成交客户:已购车的客户数(不含下订客戶)</div>
  769. </div>
  770. <template #reference>
  771. <image class="explain_icon" src="./img/jxs7.png"></image>
  772. </template>
  773. </van-popover>
  774. </div>
  775. <div id="funnelChart" :style="{ width: '100%', height: '200px', marginBottom: '20px' }"></div>
  776. <!-- <select-date :page-date="pageDate" @change-date="handleChangeDate"></select-date> -->
  777. <div class="all_data">
  778. <p class="add_data_p" :class="{'allData_bg': index === 1}" @click="handleClickItem(1)">总客户数</p>
  779. <p class="add_data_p" :class="{'allData_bg': index === 2}" @click="handleClickItem(2)">互动客户数</p>
  780. <p class="add_data_p" :class="{'allData_bg': index === 3}" @click="handleClickItem(3)">留资/报名客户数</p>
  781. <p class="add_data_p" :class="{'allData_bg': index === 4}" @click="handleClickItem(4)">邀约到店客户数</p>
  782. <p class="add_data_p" :class="{'allData_bg': index === 5}" @click="handleClickItem(5)">成交客户数</p>
  783. </div>
  784. <div id="adviserChart" v-if="index === 1" style="width: 100%;height: 200px;"></div>
  785. <div id="labelChart" v-else style="width: 100%;height: 200px;"></div>
  786. </div>
  787. <div class="box_connect">
  788. <div class="clientCharts_title">客群包分布</div>
  789. <div class="table_carList">
  790. <div class="table_carBox" :class="{'table_carBox_bg': carIndex === index}"
  791. v-for="(item, index) in tableList" :key="index" @click="handleClickCar(item, index)">
  792. <image class="table_car" :src="item.carModelImg"></image>
  793. <div>{{item.carModel}}</div>
  794. <div class="table_carline" :class="{'table_carline_bg': carIndex === index}"></div>
  795. </div>
  796. </div>
  797. <div class="branch_table" v-if="carStepData.length > 0">
  798. <div class="branch_header">
  799. <div style="width: 40px;">阶段</div>
  800. <div style="width: 60px;" v-for="(item, index) in carStepData[0].packageList[0].cols" :key="index">
  801. {{item.name}}
  802. </div>
  803. </div>
  804. <div class="branch_item" v-for="(item, index) in carStepData[0].packageList" :key="index">
  805. <div style="width: 40px;">{{item.stepName}}</div>
  806. <!-- 此处先循环carStepData[0].packageList[0].cols,是表格头以第一条数据为准 -->
  807. <div style="min-width: 60px;" v-for="(val, valIndex) in carStepData[0].packageList[0].cols"
  808. :key="valIndex">
  809. <span style="min-width: 60px;" v-for="(col, colIndex) in item.cols" :key="colIndex">
  810. {{val.name === col.name ? col.value[0] : ''}}
  811. </span>
  812. </div>
  813. </div>
  814. </div>
  815. </div>
  816. <div class="box_connect">
  817. <div class="clientCharts_title">意向车型标签排名</div>
  818. <div id="intentRankChart" style="width: 100%;height: 100%;"></div>
  819. </div>
  820. <div class="box_connect">
  821. <div class="clientCharts_title">已购车型标签排名</div>
  822. <div id="buyRankChart" style="width: 100%;height: 100%;"></div>
  823. </div>
  824. <!-- </div>
  825. <div class="page4_content2" v-show="pageTitle === '聊天分析'">
  826. <div class="box_connect">
  827. <div class="clientCharts_title">总数据</div>
  828. <div class="leadGen_box">
  829. <div class="interact_box_bottom">
  830. <div class="interact_item">
  831. <div class="num_item_title">私聊客户数</div>
  832. <div class="num_item_count">{{chatIndicators.total.privateChat}}</div>
  833. <div class="num_item_data">
  834. <div>昨日新增:
  835. <span class="selected_color">{{chatIndicators.yda.privateChat}}</span>
  836. </div>
  837. <image class="client_item_icon" src="./img/jxs-up1.png"></image>
  838. </div>
  839. </div>
  840. <div class="interact_line"></div>
  841. <div class="interact_item">
  842. <div class="num_item_title">私聊消息数</div>
  843. <div class="num_item_count">{{chatIndicators.total.privateMsgNum}}</div>
  844. <div class="num_item_data">
  845. <div>昨日新增:
  846. <span class="selected_color">{{chatIndicators.yda.privateMsgNum}}</span>
  847. </div>
  848. <image class="client_item_icon" src="./img/jxs-up1.png"></image>
  849. </div>
  850. </div>
  851. <div class="interact_line"></div>
  852. <div class="interact_item">
  853. <div class="num_item_title">群消息数</div>
  854. <div class="num_item_count">{{chatIndicators.total.groupMsgNum}}</div>
  855. <div class="num_item_data">
  856. <div>昨日新增:
  857. <span class="selected_color">{{chatIndicators.yda.groupMsgNum}}</span>
  858. </div>
  859. <image class="client_item_icon" src="./img/jxs-up1.png"></image>
  860. </div>
  861. </div>
  862. </div>
  863. </div>
  864. <div id="interactChart" style="width: 100%;height: 200px"></div>
  865. </div>
  866. <div class="box_connect">
  867. <div class="clientCharts_title">员工服务</div>
  868. <div class="leadGen_box">
  869. <div class="interact_box_bottom">
  870. <div class="interact_item">
  871. <div class="num_item_title">主动服务会话数</div>
  872. <div class="num_item_count">{{chatIndicators.total.proactiveServe}}</div>
  873. <div class="num_item_data">
  874. <div>昨日新增:
  875. <span class="selected_color">{{chatIndicators.yda.proactiveServe}}</span>
  876. </div>
  877. <image class="client_item_icon" src="./img/jxs-up1.png"></image>
  878. </div>
  879. </div>
  880. <div class="interact_line"></div>
  881. <div class="interact_item">
  882. <div class="num_item_title">客户回复会话数</div>
  883. <div class="num_item_count">{{chatIndicators.total.clientReply}}</div>
  884. <div class="num_item_data">
  885. <div>昨日新增:
  886. <span class="selected_color">{{chatIndicators.yda.clientReply}}</span>
  887. </div>
  888. <image class="client_item_icon" src="./img/jxs-up1.png"></image>
  889. </div>
  890. </div>
  891. <div class="interact_line"></div>
  892. <div class="interact_item">
  893. <div class="num_item_title">客户回复率</div>
  894. <div class="num_item_count">{{chatIndicators.total.clientReplyPercent ?
  895. chatIndicators.total.clientReplyPercent + '%' : ''}}</div>
  896. <div class="num_item_data">
  897. <div>较昨日:
  898. <span v-if="chatIndicators.yda.clientReplyPercent" class="selected_color"
  899. :style="{color: chatIndicators.yda.clientReplyPercent > 0 ? '#1677FF' : '#FF4E4E'}">
  900. {{chatIndicators.yda.clientReplyPercent > 0 ? '+' :
  901. ''}}{{chatIndicators.yda.clientReplyPercent}}%</span>
  902. </div>
  903. <image class="client_item_icon" v-if="chatIndicators.yda.clientReplyPercent"
  904. :src="chatIndicators.yda.clientReplyPercent > 0 ? './img/jxs-up1.png' : './img/jxs-down2.png'">
  905. </image>
  906. </div>
  907. </div>
  908. </div>
  909. </div>
  910. <div id="staffChart" style="width: 100%;height: 200px"></div>
  911. </div>
  912. <div class="box_connect">
  913. <div class="clientCharts_title">客户咨询</div>
  914. <div class="leadGen_box">
  915. <div class="interact_box_bottom">
  916. <div class="interact_item">
  917. <div class="num_item_title">主动咨询会话数</div>
  918. <div class="num_item_count">{{chatIndicators.total.proactiveConsult}}</div>
  919. <div class="num_item_data">
  920. <div>昨日新增:
  921. <span class="selected_color">{{chatIndicators.yda.proactiveConsult}}</span>
  922. </div>
  923. <image class="client_item_icon" src="./img/jxs-up1.png"></image>
  924. </div>
  925. </div>
  926. <div class="interact_line"></div>
  927. <div class="interact_item">
  928. <div class="num_item_title">员工回复会话数</div>
  929. <div class="num_item_count">{{chatIndicators.total.memberReply}}</div>
  930. <div class="num_item_data">
  931. <div>昨日新增:
  932. <span class="selected_color">{{chatIndicators.yda.memberReply}}</span>
  933. </div>
  934. <image class="client_item_icon" src="./img/jxs-up1.png"></image>
  935. </div>
  936. </div>
  937. <div class="interact_line"></div>
  938. <div class="interact_item">
  939. <div class="num_item_title">员工平均响应时长</div>
  940. <div class="num_item_count">{{chatIndicators.total.avgReplyDuration ?
  941. formatTime(chatIndicators.total.avgReplyDuration) : ''}}</div>
  942. <div class="num_item_data">
  943. <div>较昨日:
  944. <span v-if="chatIndicators.yda.avgReplyDuration" class="selected_color"
  945. :style="{color: chatIndicators.yda.avgReplyDuration > 0 ? '#FF4E4E' : '#1677FF'}">
  946. {{chatIndicators.yda.avgReplyDuration > 0 ? '+' :
  947. ''}}{{formatTime(chatIndicators.yda.avgReplyDuration)}}</span>
  948. </div>
  949. <image class="client_item_icon" v-if="chatIndicators.yda.avgReplyDuration"
  950. :src="chatIndicators.yda.avgReplyDuration > 0 ? './img/jxs-up2.png' : './img/jxs-down1.png'">
  951. </image>
  952. </div>
  953. </div>
  954. </div>
  955. </div>
  956. <div id="clientChart" style="width: 100%;height: 200px"></div>
  957. </div>
  958. <div class="box_connect">
  959. <div class="clientCharts_title">消息舆情分析</div>
  960. <div id="opinionChart" style="width: 100%;height: 380px"></div>
  961. </div>
  962. <div class="box_connect">
  963. <div class="clientCharts_title">客户关注词云图</div>
  964. <div id="wordCloudChart" style="width: 100%;height: 200px"></div>
  965. </div>
  966. <div class="data_tips">—— 每日5:00更新数据 ——</div>
  967. </div>
  968. <div class="page4_content2" v-show="pageTitle === '员工监测'">
  969. <div class="box_connect">
  970. <div class="clientCharts_title">销售进程客户数</div>
  971. <div class="step_list">
  972. <div class="step_box" :class="{'step_box_bg': clientIndex === index}"
  973. v-for="(item, index) in saleIndicators" :key="index" @click="handleClickClient(item, index)">
  974. <div>{{item.processName}}</div>
  975. <div class="step_num" :class="{'step_num_bg': clientIndex === index}">{{item.clientNum}}</div>
  976. </div>
  977. </div>
  978. <div id="clientStepChart" style="width: 100%;height: 200px"></div>
  979. </div>
  980. <div class="box_connect">
  981. <div class="clientCharts_title">销售统计排名</div>
  982. <div class="branch_table" v-if="saleRankData.length > 0">
  983. <div class="branch_header">
  984. <div style="width: 30px;">排名</div>
  985. <div style="width: 80px;">顾问</div>
  986. <div style="width: 40px;">网点</div>
  987. <div style="width: 60px;" v-for="(item, index) in saleRankData[0].cols" :key="index">
  988. {{item.name}}
  989. </div>
  990. </div>
  991. <div class="branch_item" v-for="(item, index) in saleRankData" :key="index">
  992. <div style="width: 30px;">{{index + 1}}</div>
  993. <div style="width: 80px;max-width: 80px;">{{item.memberName}}</div>
  994. <div style="width: 40px;">{{item.outletName}}</div>
  995. <div style="min-width: 60px;" v-for="(val, valIndex) in saleRankData[0].cols" :key="valIndex">
  996. <span style="min-width: 60px;" v-for="(col, colIndex) in item.cols" :key="colIndex">
  997. {{val.name === col.name ? (col.value ? col.value[0] : '-') : ''}}
  998. </span>
  999. </div>
  1000. </div>
  1001. </div>
  1002. </div>
  1003. <div class="box_connect">
  1004. <div class="clientCharts_title_box">
  1005. <div class="clientCharts_title">聊天超时监测</div>
  1006. <div class="clientCharts_title_right" @click="handleMemberReply">查看详情</div>
  1007. </div>
  1008. <div id="timeOutTrendChart" style="width: 100%;height: 230px"></div>
  1009. </div>
  1010. <div class="box_connect">
  1011. <div class="clientCharts_title">聊天排行榜</div>
  1012. <div class="branch_table">
  1013. <div class="branch_header" style="box-sizing: border-box;">
  1014. <div style="width: 30px;">排名</div>
  1015. <div style="width: 80px;">员工</div>
  1016. <div style="width: 50px;">聊天客户数</div>
  1017. <div style="width: 50px;">主动会话<br />服务数</div>
  1018. <div style="width: 50px;">客户回复<br />会话数</div>
  1019. </div>
  1020. <div class="branch_item" style="box-sizing: border-box;" v-for="(item, index) in chatRankData" :key="index">
  1021. <div style="width: 30px;">{{index + 1}}</div>
  1022. <div style="width: 80px;max-width: 80px;">{{item.memberName}}</div>
  1023. <div style="width: 50px;">{{item.privateChat}}</div>
  1024. <div style="width: 50px;">{{item.proactiveServe}}</div>
  1025. <div style="width: 50px;">{{item.clientReply}}</div>
  1026. </div>
  1027. </div>
  1028. </div>
  1029. <div class="data_tips">—— 每日5:00更新数据 ——</div>
  1030. </div>
  1031. <div class="page4_content2" v-show="pageTitle === '运营任务'"> -->
  1032. <div class="box_connect">
  1033. <div class="clientCharts_title_box">
  1034. <div class="clientCharts_titleA" style="margin-bottom: 0;">
  1035. <image class="navbar_icon" src="./img/jxs6.png"></image>
  1036. <span class="box_title">运营任务总数据</span>
  1037. </div>
  1038. <div class="clientCharts_title_right" @click="handleDoneReply">查看更多</div>
  1039. </div>
  1040. <div class="branch_table">
  1041. <div class="branch_header" style="box-sizing: border-box;">
  1042. <div style="width: 60px;">网点</div>
  1043. <div style="width: 60px;">下发任务数</div>
  1044. <div style="width: 60px;">任务完成率</div>
  1045. <div style="width: 60px;">互动客户数</div>
  1046. <div>激活率</div>
  1047. </div>
  1048. <div class="branch_item" style="box-sizing: border-box;" v-for="(item, index) in outletCount" :key="index">
  1049. <div style="width: 60px;">{{item.outletName}}</div>
  1050. <div style="width: 60px;">{{item.taskNum}}</div>
  1051. <div style="width: 60px;">{{item.taskCompletePercent ? item.taskCompletePercent + '%' : '-'}}</div>
  1052. <div style="width: 60px;">{{item.interactClient}}</div>
  1053. <div>{{item.activatePercent ? item.activatePercent + '%' : '-'}}</div>
  1054. </div>
  1055. </div>
  1056. </div>
  1057. <div class="box_connect">
  1058. <div class="clientCharts_title">任务完成率</div>
  1059. <div id="taskCompleteChart" style="width: 100%;height: 200px"></div>
  1060. </div>
  1061. <div class="box_connect">
  1062. <div class="clientCharts_title">互动客户数</div>
  1063. <div id="opInteractChart" style="width: 100%;height: 200px"></div>
  1064. </div>
  1065. <div class="box_connect">
  1066. <div class="clientCharts_title">素材排行榜</div>
  1067. <div id="contentRank" style="width: 100%;"></div>
  1068. </div>
  1069. <div class="data_tips">—— 每日5:00更新数据 ——</div>
  1070. </div>
  1071. </div>
  1072. </div>
  1073. </body>
  1074. <script>
  1075. new Vue({
  1076. el: '#box',
  1077. data() {
  1078. return {
  1079. httpUrl: '',
  1080. bId: null,
  1081. env: '',
  1082. jxsName: '',
  1083. token: '',
  1084. tenancyId: '',
  1085. showPopup: false,
  1086. showMer: false,
  1087. showDatePicker: false,
  1088. showDatePicker2: false,
  1089. showDatePicker3: false,
  1090. actions: [
  1091. { text: '昨日' }, { text: '近7天' }, { text: '近30天' }, { text: '自定义' }
  1092. ],
  1093. keyword: '',
  1094. showSelfDate: false,
  1095. minDate: '',
  1096. maxDate: '',
  1097. merList: [], // 商户列表
  1098. outletsList: [], // 网点列表
  1099. outletsData: [], // 网点列表数据
  1100. deptList: [], // 部门列表
  1101. deptData: [], // 部门列表数据
  1102. pageTitle: '客户资产',
  1103. showPicker: false, // 网点选择器
  1104. showDeptPicker: false, // 部门选择器
  1105. deptName: '', // 部门名称
  1106. deptId: null, // 部门id
  1107. outletName: '', // 网点名称
  1108. outletId: null, // 网点id
  1109. clientIndicators: [], // 客户资产-总数据
  1110. pageStartTime: '',
  1111. pageEndTime: '',
  1112. index: 1,
  1113. showPopover: false,
  1114. lineDate: [], // 客户资产-统计趋势图
  1115. saleAdd: [],
  1116. serveAdd: [],
  1117. interactClient: [],
  1118. formClient: [],
  1119. storeClient: [],
  1120. dealClient: [],
  1121. tableList: [], // 客群包阶段车型
  1122. carIndex: 0,
  1123. carStepData: [], // 客群包阶段车型数据
  1124. intentRankData: [], // 意向车型标签排名
  1125. buyRankData: [], // 已购车型标签排名
  1126. chatIndicators: {
  1127. dayList: [], // 聊天分析-日数据
  1128. opinion: {},
  1129. total: {
  1130. privateChat: 0,
  1131. privateMsgNum: 0,
  1132. groupMsgNum: 0,
  1133. proactiveServe: 0,
  1134. clientReply: 0,
  1135. clientReplyPercent: 0,
  1136. proactiveConsult: 0,
  1137. memberReply: 0,
  1138. avgReplyDuration: 0,
  1139. },
  1140. yda: {
  1141. privateChat: 0,
  1142. privateMsgNum: 0,
  1143. groupMsgNum: 0,
  1144. proactiveServe: 0,
  1145. clientReply: 0,
  1146. clientReplyPercent: 0,
  1147. proactiveConsult: 0,
  1148. memberReply: 0,
  1149. avgReplyDuration: 0,
  1150. },
  1151. },
  1152. interactDate: [], // 聊天分析-总数据图数据
  1153. privateChat: [],
  1154. privateMsgNum: [],
  1155. groupMsgNum: [],
  1156. proactiveServe: [],
  1157. clientReply: [],
  1158. clientReplyPercent: [],
  1159. proactiveConsult: [],
  1160. memberReply: [],
  1161. showItemMemberReply: false, // 显示客户详情响应数据
  1162. currentMemberName: '', // 当前客户名称
  1163. memberId: '', // 当前客户id
  1164. memberDetailReplyData: [], // 客户详情响应数据
  1165. currentItemPage: 1, // 当前客户详情响应数据页码
  1166. itemTotalItems: 0, // 客户详情响应数据总页数
  1167. avgReplyDuration: [],
  1168. totalMsg: [],
  1169. privateMsg: [],
  1170. groupMsg: [],
  1171. maxValue: null,
  1172. wordCloudMap: [], // 客户关注词云图
  1173. saleIndicators: [], // 销售进程客户数
  1174. clientIndex: 0, // 销售进程客户数索引
  1175. clientStepDate: [], // 销售进程客户数-日期
  1176. clientStepNum: [], // 销售进程客户数-客户数
  1177. saleRankData: [], // 销售统计排名数据
  1178. timeOutDate: [], // 聊天超时监测-日期
  1179. timeoutMember: [], // 聊天超时监测-超时客户数
  1180. timeData: '',
  1181. memberStartTime: '',
  1182. memberEndTime: '',
  1183. showDoneReply: false, // 显示已完成响应数据
  1184. doneReplyData: [], // 已完成响应数据
  1185. showMemberReply: false,
  1186. currentPage: 1,
  1187. totalItems: 0,
  1188. memberReplyData: [], // 顾问响应统计数据
  1189. chatRankData: [], // 聊天排行榜数据
  1190. outletCount: [], // 运营任务-总数据
  1191. taskCompleteDate: [], // 运营任务-任务完成率-日期
  1192. taskCompletePercent: [], // 运营任务-任务完成率
  1193. opInteractDate: [], // 运营任务-互动客户数-日期
  1194. opInteractClient: [], // 运营任务-互动客户数
  1195. contentRankData: [], // 运营任务-素材排行榜
  1196. loading: false,
  1197. pageDate: [], // 日期范围
  1198. }
  1199. },
  1200. created() {
  1201. let nowDat = new Date();
  1202. let dateY = nowDat.getFullYear()
  1203. let dateM = nowDat.getMonth()
  1204. let dateD = nowDat.getDate()
  1205. // 设置日期可选最小值minDate、最大值maxDate
  1206. this.minDate = new Date(dateY - 1, dateM, dateD)
  1207. //日历可选范围为一年,dateY + 1
  1208. this.maxDate = new Date(dateY, dateM, dateD - 1)
  1209. this.bId = this.getQueryParam('bId')
  1210. this.env = this.getQueryParam('env')
  1211. if (!this.env || this.env === 'prod') {
  1212. this.httpUrl = 'https://wlapi.wefanbot.com'
  1213. // this.httpUrl = 'http://192.168.1.128:18993'
  1214. } else {
  1215. this.httpUrl = 'http://test.wefanbot.com:18993'
  1216. // this.httpUrl = 'http://192.168.1.128:18993'
  1217. }
  1218. this.token = localStorage.getItem('tokenValue')
  1219. this.tenancyId = localStorage.getItem('tenancyIdValue')
  1220. this.jxsName = localStorage.getItem('tenancyNameValue') || ''
  1221. this.pageStartTime = this.getDateTime(-7)
  1222. this.pageEndTime = this.getDateTime(-1)
  1223. this.memberStartTime = this.getDateTime(-7)
  1224. this.memberEndTime = this.getDateTime(-1)
  1225. this.initialization()
  1226. this.getAdminList()
  1227. },
  1228. methods: {
  1229. // 初始化
  1230. initialization() {
  1231. this.clientIndicators = []
  1232. this.pageStartTime = this.getDateTime(-7)
  1233. this.pageEndTime = this.getDateTime(-1)
  1234. this.index = 1
  1235. this.outletName = ''
  1236. this.outletId = null
  1237. this.getOutletsData()
  1238. this.deptName = ''
  1239. this.deptId = null
  1240. this.getDeptData() // 部门列表数据
  1241. },
  1242. requestData() {
  1243. if (this.pageTitle === '客户资产') {
  1244. this.getClientIndicators() // 客户资产-总数据
  1245. this.getTrend() // 客户资产-统计趋势图
  1246. this.stepStatistic() // 客户资产-客群包分布
  1247. this.getIntentRank() // 意向车型标签排名
  1248. this.getBuyRank() // 已购车型标签排名
  1249. this.getOutletCount() // 运营任务 - 总数据
  1250. this.getTaskCompleteChart() // 运营任务 - 任务完成率
  1251. this.getOpInteractChart() // 运营任务 - 互动客户数
  1252. this.getContentRank() // 运营任务 - 素材排行榜
  1253. this.$nextTick(() => {
  1254. this.funnelDraw()
  1255. this.passValue()
  1256. this.intentRankChart()
  1257. this.buyRankChart()
  1258. // })
  1259. // } else if (this.pageTitle === '聊天分析') {
  1260. // this.handlePage(2)
  1261. // this.$nextTick(() => {
  1262. // this.interactChart()
  1263. // this.staffChart()
  1264. // this.clientChart()
  1265. // this.opinionChart()
  1266. // this.wordCloudChart()
  1267. // })
  1268. // } else if (this.pageTitle === '员工监测') {
  1269. // this.handlePage(3)
  1270. // this.$nextTick(() => {
  1271. // this.clientStepChart()
  1272. // this.timeOutTrendChart()
  1273. // })
  1274. // } else if (this.pageTitle === '运营任务') {
  1275. // this.handlePage(4)
  1276. // this.$nextTick(() => {
  1277. this.taskCompleteChart()
  1278. this.opInteractChart()
  1279. this.contentRankChart()
  1280. })
  1281. }
  1282. },
  1283. // 获取商户列表(右上角)
  1284. getAdminList() {
  1285. const headers = new Headers()
  1286. headers.append('token', this.token)
  1287. fetch(this.httpUrl + `/scrm/v1/user-info/o/adminList`, {
  1288. method: 'GET',
  1289. headers: headers
  1290. }).then(res => {
  1291. return res.json()
  1292. }).then(result => {
  1293. let { data, code, msg } = result
  1294. if (code === 1) {
  1295. this.merList = data || []
  1296. } else if (code === 10001) {
  1297. this.loginOut()
  1298. } else {
  1299. vant.Toast.fail(msg)
  1300. }
  1301. })
  1302. },
  1303. // 获取网点列表
  1304. getOutletsData() {
  1305. const headers = new Headers()
  1306. headers.append('token', this.token)
  1307. headers.append('tenancyId', this.tenancyId)
  1308. this.outletsList = []
  1309. this.outletsData = []
  1310. fetch(this.httpUrl + `/scrm/v1/tenancy-outlet/options`, {
  1311. method: 'GET',
  1312. headers: headers
  1313. }).then(res => {
  1314. return res.json()
  1315. }).then(result => {
  1316. let { data, code, msg } = result
  1317. if (code === 1) {
  1318. this.outletsList = data || []
  1319. this.outletsData = data && data.length > 0 ? data.map(item => item.name) : []
  1320. } else if (code === 10001) {
  1321. this.loginOut()
  1322. } else {
  1323. vant.Toast.fail(msg)
  1324. }
  1325. }).finally(() => {
  1326. if (this.outletsList.length === 1) {
  1327. this.outletName = this.outletsData[0]
  1328. this.outletId = this.outletsList.find(item => item.name === this.outletName).id || null
  1329. } else if (this.outletsList.length === 0 || this.outletsList.length > 1) {
  1330. this.outletsData.unshift('全部')
  1331. this.outletName = '全部'
  1332. this.outletId = null
  1333. }
  1334. this.requestData()
  1335. })
  1336. },
  1337. // 获取部门列表
  1338. getDeptData() {
  1339. const headers = new Headers()
  1340. headers.append('token', this.token)
  1341. headers.append('tenancyId', this.tenancyId)
  1342. this.deptList = []
  1343. this.deptData = []
  1344. fetch(this.httpUrl + `/scrm/v1/tenancy-outlet-department/options`, {
  1345. method: 'post',
  1346. body: JSON.stringify({
  1347. outletIds: this.outletId ? [this.outletId] : []
  1348. }),
  1349. headers: {
  1350. 'Content-Type': 'application/json',
  1351. 'token': this.token,
  1352. 'tenancyId': this.tenancyId
  1353. }
  1354. }).then(res => {
  1355. return res.json()
  1356. }).then(result => {
  1357. let { data, code, msg } = result
  1358. if (code === 1) {
  1359. this.deptList = data || []
  1360. this.deptData = data && data.length > 0 ? data.map(item => item.name) : []
  1361. } else if (code === 10001) {
  1362. this.loginOut()
  1363. } else {
  1364. vant.Toast.fail(msg)
  1365. }
  1366. }).finally(() => {
  1367. if (this.deptList.length === 1) {
  1368. this.deptName = this.deptData[0]
  1369. this.deptId = this.deptList.find(item => item.name === this.deptName).id || null
  1370. } else if (this.deptList.length === 0 || this.deptList.length > 1) {
  1371. this.deptData.unshift('全部')
  1372. this.deptName = '全部'
  1373. this.deptId = null
  1374. }
  1375. })
  1376. },
  1377. onConfirm(val) {
  1378. this.outletName = val
  1379. if (this.outletName === '全部') {
  1380. this.outletId = null
  1381. } else {
  1382. this.outletId = this.outletsList.find(item => item.name === this.outletName).id || null
  1383. }
  1384. this.showPicker = false
  1385. this.deptId = null
  1386. this.deptName = '全部'
  1387. this.getDeptData()
  1388. if (this.pageTitle === '客户资产') {
  1389. this.getClientIndicators() // 客户资产-总数据
  1390. this.getTrend() // 客户资产-统计趋势图
  1391. this.stepStatistic() // 客户资产-客群包分布
  1392. this.getIntentRank() // 意向车型标签排名
  1393. this.getBuyRank() // 已购车型标签排名
  1394. // } else if (this.pageTitle === '聊天分析') {
  1395. // this.handlePage(2)
  1396. // } else if (this.pageTitle === '员工监测') {
  1397. // this.handlePage(3)
  1398. // } else if (this.pageTitle === '运营任务') {
  1399. this.getOutletCount() // 运营任务 - 总数据
  1400. this.getTaskCompleteChart() // 运营任务 - 任务完成率
  1401. this.getOpInteractChart() // 运营任务 - 互动客户数
  1402. this.getContentRank() // 运营任务 - 素材排行榜
  1403. }
  1404. },
  1405. onDeptConfirm(val) {
  1406. this.deptName = val
  1407. if (this.deptName === '全部') {
  1408. this.deptId = null
  1409. } else {
  1410. this.deptId = this.deptList.find(item => item.name === this.deptName).id || null
  1411. }
  1412. this.showDeptPicker = false
  1413. if (this.pageTitle === '客户资产') {
  1414. this.getClientIndicators() // 客户资产-总数据
  1415. this.getTrend() // 客户资产-统计趋势图
  1416. this.stepStatistic() // 客户资产-客群包分布
  1417. this.getIntentRank() // 意向车型标签排名
  1418. this.getBuyRank() // 已购车型标签排名
  1419. // } else if (this.pageTitle === '聊天分析') {
  1420. // this.handlePage(2)
  1421. // } else if (this.pageTitle === '员工监测') {
  1422. // this.handlePage(3)
  1423. // } else if (this.pageTitle === '运营任务') {
  1424. this.getOutletCount() // 运营任务 - 总数据
  1425. this.getTaskCompleteChart() // 运营任务 - 任务完成率
  1426. this.getOpInteractChart() // 运营任务 - 互动客户数
  1427. this.getContentRank() // 运营任务 - 素材排行榜
  1428. }
  1429. },
  1430. handlePage(index) {
  1431. // switch (index) {
  1432. // case 1:
  1433. // this.pageTitle = '客户资产'
  1434. // this.initialization()
  1435. // break
  1436. // case 2:
  1437. // this.pageTitle = '聊天分析'
  1438. // this.getChatIndicators() // 聊天分析 - 总数据
  1439. // this.getWordCloudMap() // 聊天分析 - 词云图
  1440. // break
  1441. // case 3:
  1442. // this.pageTitle = '员工监测'
  1443. // this.getSaleIndicators() // 员工监测 - 销售进程
  1444. // this.getSaleRank() // 员工监测 - 销售统计排名
  1445. // this.getTimeOutTrendChart() // 员工监测 - 聊天超时监测
  1446. // this.getChatRank() // 员工监测 - 聊天统计排名
  1447. // break
  1448. // case 4:
  1449. // this.pageTitle = '运营任务'
  1450. // this.getOutletCount() // 运营任务 - 总数据
  1451. // this.getTaskCompleteChart() // 运营任务 - 任务完成率
  1452. // this.getOpInteractChart() // 运营任务 - 互动客户数
  1453. // this.getContentRank() // 运营任务 - 素材排行榜
  1454. // break
  1455. // }
  1456. this.showPopup = false
  1457. },
  1458. // 客户资产-总数据
  1459. getClientIndicators() {
  1460. this.clientIndicators = []
  1461. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/clientIndicators`, {
  1462. method: 'post',
  1463. body: JSON.stringify({
  1464. outletId: this.outletId,
  1465. departmentIds: this.deptId ? [this.deptId] : []
  1466. }),
  1467. headers: {
  1468. 'Content-Type': 'application/json',
  1469. 'token': this.token,
  1470. 'tenancyId': this.tenancyId
  1471. }
  1472. }).then(res => {
  1473. return res.json()
  1474. }).then(result => {
  1475. let { data, code, msg } = result
  1476. if (code === 1) {
  1477. this.clientIndicators = data.reverse() || []
  1478. this.$nextTick(() => {
  1479. this.funnelDraw()
  1480. })
  1481. } else if (code === 10001) {
  1482. this.loginOut()
  1483. } else {
  1484. vant.Toast.fail(msg)
  1485. }
  1486. })
  1487. },
  1488. // 客户资产-总数据(梯形图)
  1489. funnelDraw() {
  1490. let clientIndicators = this.clientIndicators
  1491. let funnelChart = echarts.getInstanceByDom(document.getElementById('funnelChart'))
  1492. if (funnelChart == null) {
  1493. funnelChart = echarts.init(document.getElementById('funnelChart'))
  1494. }
  1495. window.addEventListener('resize', function () {
  1496. funnelChart.resize()
  1497. })
  1498. funnelChart.setOption({
  1499. tooltip: {
  1500. trigger: 'item',
  1501. formatter(param) {
  1502. let label = ''
  1503. clientIndicators.forEach(item => {
  1504. if (item.name === param.data.name) {
  1505. label = item.value
  1506. }
  1507. })
  1508. return param.data.name + ':' + label
  1509. }
  1510. },
  1511. series: [
  1512. {
  1513. type: 'funnel',
  1514. min: 0,
  1515. max: 100,
  1516. width: '50%',
  1517. minSize: '0%', //漏斗最小值的宽度
  1518. maxSize: '100%', //漏斗最大值的宽度
  1519. left: '0%',
  1520. right: '8%',
  1521. top: '8%',
  1522. bottom: '2%',
  1523. gap: 2,
  1524. label: {
  1525. show: false,
  1526. position: 'inside',
  1527. color: '#fff',
  1528. },
  1529. data: clientIndicators.map((item, index) => {
  1530. return {
  1531. value: 40 + (index + 1) * 10,
  1532. name: item.name,
  1533. itemStyle: {
  1534. color: `hsl(215, 100%, ${54 + index * 8}%)`
  1535. },
  1536. }
  1537. })
  1538. },
  1539. {
  1540. type: 'funnel',
  1541. label: {
  1542. position: 'right',
  1543. lineHeight: 20,
  1544. padding: [0, 0, 0, 10],
  1545. formatter: function (param) {
  1546. let label = ''
  1547. let percent = ''
  1548. let showPercent = true; // 默认显示占比
  1549. clientIndicators.forEach(item => {
  1550. if (item.name === param.data.name) {
  1551. label = item.value
  1552. percent = item.percent
  1553. }
  1554. });
  1555. // 特殊处理长文本换行
  1556. const secondLineText = label
  1557. ? `${label}人`
  1558. : (['到店客户', '成交客户'].includes(param.data.name)
  1559. ? '待ONE-ID\n数据打通' // 手动插入换行符
  1560. : '');
  1561. // 关键修改:当显示特殊文本时隐藏占比行
  1562. if (['到店客户', '成交客户'].includes(param.data.name) && !label) {
  1563. showPercent = false;
  1564. }
  1565. const lines = [];
  1566. lines.push(`{firstLine|${param.data.name}:}{secondLine|${secondLineText}}`);
  1567. // 只有需要显示占比时才添加第三行
  1568. if (showPercent) {
  1569. lines.push(`{thirdLine|占比:${percent ? percent + '%' : ''}}`);
  1570. }
  1571. return lines.join('\n');
  1572. },
  1573. // 新增 rich 样式定义
  1574. rich: {
  1575. firstLine: {
  1576. color: '#899EB2', // 第一行颜色
  1577. fontSize: 12, // 第一行字号
  1578. lineHeight: 20 // 保持与外层 lineHeight 一致
  1579. },
  1580. secondLine: {
  1581. color: '#1677FF',
  1582. fontWeight: 'bold',
  1583. fontSize: 14,
  1584. lineHeight: 20,
  1585. width: 150, // 关键:限制宽度触发自动换行
  1586. overflow: 'break', // 允许文本换行
  1587. },
  1588. thirdLine: {
  1589. color: '#1677FF', // 第二行颜色(示例用红色)
  1590. fontSize: 10, // 第二行字号
  1591. lineHeight: 10, // 保持与外层 lineHeight 一致
  1592. }
  1593. }
  1594. },
  1595. labelLine: {
  1596. show: true,
  1597. length: 40, // label拉线的长度根据自己的场景进行设置即可
  1598. lineStyle: {
  1599. width: 1,
  1600. type: 'solid'
  1601. }
  1602. },
  1603. min: 0,
  1604. max: 100,
  1605. minSize: '0%',
  1606. maxSize: 0,
  1607. left: '-20%',
  1608. right: '8%',
  1609. top: '10%',
  1610. bottom: '2%',
  1611. z: 1,
  1612. gap: 2,
  1613. data: clientIndicators.map((item, index) => {
  1614. return {
  1615. value: 40 + (index + 1) * 10,
  1616. name: item.name,
  1617. itemStyle: {
  1618. color: `hsl(215, 100%, ${54 + index * 8}%)`
  1619. },
  1620. }
  1621. })
  1622. }
  1623. ]
  1624. }, true)
  1625. },
  1626. // 切换日期范围
  1627. handleChangeDate(date) {
  1628. this.pageStartTime = date[0]
  1629. this.pageEndTime = date[1]
  1630. this.pageDate = date
  1631. if (this.pageTitle === '客户资产') {
  1632. this.getTrend() // 客户资产-统计趋势图
  1633. // } else if (this.pageTitle === '聊天分析') {
  1634. // this.handlePage(2)
  1635. // } else if (this.pageTitle === '员工监测') {
  1636. // this.handlePage(3)
  1637. // } else if (this.pageTitle === '运营任务') {
  1638. this.getOutletCount() // 运营任务 - 总数据
  1639. this.getTaskCompleteChart() // 运营任务 - 任务完成率
  1640. this.getOpInteractChart() // 运营任务 - 互动客户数
  1641. this.getContentRank() // 运营任务 - 素材排行榜
  1642. }
  1643. },
  1644. // 客户资产-统计趋势图
  1645. getTrend() {
  1646. this.lineDate = []
  1647. this.saleAdd = []
  1648. this.serveAdd = []
  1649. this.interactClient = []
  1650. this.formClient = []
  1651. this.storeClient = []
  1652. this.dealClient = []
  1653. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/trend`, {
  1654. method: 'post',
  1655. body: JSON.stringify({
  1656. outletId: this.outletId,
  1657. departmentIds: this.deptId ? [this.deptId] : [],
  1658. startTime: this.pageStartTime,
  1659. endTime: this.pageEndTime,
  1660. }),
  1661. headers: {
  1662. 'Content-Type': 'application/json',
  1663. 'token': this.token,
  1664. 'tenancyId': this.tenancyId
  1665. }
  1666. }).then(res => {
  1667. return res.json()
  1668. }).then(result => {
  1669. let { data, code, msg } = result
  1670. if (code === 1) {
  1671. if (data && data.length > 0) {
  1672. data.forEach(item => {
  1673. this.lineDate.push(item.time)
  1674. this.saleAdd.push(item.saleAdd)
  1675. this.serveAdd.push(item.serveAdd)
  1676. this.interactClient.push(item.interactClient)
  1677. this.formClient.push(item.formClient)
  1678. this.storeClient.push(item.storeClient)
  1679. this.dealClient.push(item.dealClient)
  1680. })
  1681. }
  1682. this.$nextTick(() => {
  1683. this.passValue()
  1684. })
  1685. } else if (code === 10001) {
  1686. this.loginOut()
  1687. } else {
  1688. vant.Toast.fail(msg)
  1689. }
  1690. })
  1691. },
  1692. // 切换5个模块(总客户数、互动客户数、留资/报名客户数、邀约到店客户数、成交客户数)
  1693. handleClickItem(index) {
  1694. this.index = index
  1695. this.passValue()
  1696. },
  1697. // 切换三个图表(总客户数、一客一群、销售顾问+服务顾问)
  1698. passValue() {
  1699. if (this.index === 1) {
  1700. this.$nextTick(() => {
  1701. this.adviserChart()
  1702. })
  1703. } else {
  1704. this.$nextTick(() => {
  1705. this.labelChart()
  1706. })
  1707. }
  1708. },
  1709. // 互动客户数、留资/报名客户数、邀约到店客户数、成交客户数(趋势图)
  1710. labelChart() {
  1711. let labelChart = echarts.getInstanceByDom(document.getElementById('labelChart'))
  1712. if (labelChart == null) {
  1713. labelChart = echarts.init(document.getElementById('labelChart'))
  1714. }
  1715. window.addEventListener('resize', function () {
  1716. labelChart.resize()
  1717. })
  1718. let dataText = ''
  1719. let labelData = []
  1720. if (this.index === 2) {
  1721. labelData = this.interactClient
  1722. dataText = '互动客户数'
  1723. } else if (this.index === 3) {
  1724. labelData = this.formClient
  1725. dataText = '留资/报名客户数'
  1726. } else if (this.index === 4) {
  1727. labelData = this.storeClient
  1728. dataText = '邀约到店客户数'
  1729. } else if (this.index === 5) {
  1730. labelData = this.dealClient
  1731. dataText = '成交客户数'
  1732. }
  1733. labelChart.setOption({
  1734. legend: {
  1735. data: [dataText],
  1736. orient: 'horizontal',
  1737. x: 'center',
  1738. y: 'top',
  1739. align: 'right',
  1740. itemWidth: 20,
  1741. itemHeight: 5,
  1742. itemGap: 20,
  1743. textStyle: {//图例文字的样式
  1744. color: '#666666', //图例文字颜色
  1745. fontSize: 10//图例文字大小
  1746. }
  1747. },
  1748. tooltip: {
  1749. trigger: 'axis',
  1750. axisPointer: {
  1751. type: 'shadow'
  1752. },
  1753. },
  1754. grid: {
  1755. top: '10%',
  1756. left: '10%',
  1757. right: '10%',
  1758. bottom: '10%'
  1759. },
  1760. xAxis: {
  1761. type: 'category',
  1762. axisLabel: {
  1763. show: true,
  1764. color: "#666666",
  1765. fontSize: '8',
  1766. },
  1767. data: this.lineDate,
  1768. },
  1769. yAxis: [
  1770. {// 第一种方式
  1771. type: 'value',
  1772. min: 0,
  1773. max: Math.max(...labelData),
  1774. splitNumber: 5,
  1775. interval: Math.max(...labelData) / 5,
  1776. position: 'left',
  1777. axisLabel: {
  1778. show: true,
  1779. color: "#222222",
  1780. fontSize: '8',
  1781. formatter: function (v) {
  1782. return v.toFixed(0) //0表示小数为0位,1表示1位小数,2表示2位小数
  1783. }
  1784. },
  1785. splitLine: { //网格线
  1786. lineStyle: {
  1787. type: 'dashed'//设置网格线类型 dotted:虚线 solid:实线
  1788. },
  1789. },
  1790. axisTick: { show: false },
  1791. },
  1792. ],
  1793. series: [
  1794. {
  1795. name: dataText,
  1796. type: 'bar',
  1797. stack: 'total',
  1798. color: '#1677FF ',
  1799. data: labelData,
  1800. itemStyle: {
  1801. // 设置柱形图圆角 [左上角,右上角,右下角,左下角]
  1802. borderRadius: [5, 5, 0, 0]
  1803. }
  1804. }
  1805. ],
  1806. }, true)
  1807. },
  1808. // 销售顾问+服务顾问(趋势图)
  1809. adviserChart() {
  1810. let adviserChart = echarts.getInstanceByDom(document.getElementById('adviserChart'))
  1811. if (adviserChart == null) {
  1812. adviserChart = echarts.init(document.getElementById('adviserChart'))
  1813. }
  1814. window.addEventListener('resize', function () {
  1815. adviserChart.resize()
  1816. })
  1817. adviserChart.setOption({
  1818. legend: {
  1819. show: true,
  1820. data: ['销售', '服务'],
  1821. orient: 'horizontal',
  1822. x: 'center',
  1823. y: 'top',
  1824. align: 'right',
  1825. itemWidth: 20,
  1826. itemHeight: 5,
  1827. itemGap: 20,
  1828. textStyle: {//图例文字的样式
  1829. color: '#666666', //图例文字颜色
  1830. fontSize: 10,//图例文字大小
  1831. }
  1832. },
  1833. tooltip: {
  1834. trigger: 'axis',
  1835. axisPointer: {
  1836. type: 'shadow'
  1837. },
  1838. },
  1839. grid: {
  1840. top: '10%',
  1841. left: '10%',
  1842. right: '10%',
  1843. bottom: '10%'
  1844. },
  1845. xAxis: {
  1846. type: 'category',
  1847. axisLabel: {
  1848. show: true,
  1849. color: '#666666',
  1850. fontSize: '8',
  1851. },
  1852. data: this.lineDate,
  1853. },
  1854. yAxis: [
  1855. {// 第一种方式
  1856. type: 'value',
  1857. min: 0,
  1858. max: Math.max(...this.saleAdd, ...this.serveAdd) * 2,
  1859. splitNumber: 5,
  1860. interval: Math.max(...this.saleAdd, ...this.serveAdd) * 2 / 5,
  1861. position: 'left',
  1862. axisLabel: {
  1863. show: true,
  1864. color: '#222222',
  1865. fontSize: '8',
  1866. formatter: function (v) {
  1867. return v.toFixed(0) //0表示小数为0位,1表示1位小数,2表示2位小数
  1868. }
  1869. },
  1870. splitLine: { //网格线
  1871. lineStyle: {
  1872. type: 'dashed'//设置网格线类型 dotted:虚线 solid:实线
  1873. },
  1874. },
  1875. axisTick: { show: false },
  1876. },
  1877. ],
  1878. series: [
  1879. {
  1880. name: '销售',
  1881. type: 'bar',
  1882. stack: 'total',
  1883. color: '#1677FF',
  1884. data: this.saleAdd,
  1885. },
  1886. {
  1887. name: '服务',
  1888. type: 'bar',
  1889. stack: 'total',
  1890. color: '#5CE56E ',
  1891. data: this.serveAdd,
  1892. itemStyle: {
  1893. // 设置柱形图圆角 [左上角,右上角,右下角,左下角]
  1894. borderRadius: [5, 5, 0, 0]
  1895. }
  1896. }
  1897. ],
  1898. }, true)
  1899. },
  1900. // 切换车型(客户资产-客群包统计)
  1901. handleClickCar(item, index) {
  1902. this.carIndex = index
  1903. this.carStepData = []
  1904. this.carStepData.push(this.tableList.find(ele => ele.carModel === item.carModel))
  1905. },
  1906. // 客户资产-客群包统计数据
  1907. stepStatistic() {
  1908. this.tableList = []
  1909. this.carStepData = []
  1910. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/stepStatistic`, {
  1911. method: 'post',
  1912. body: JSON.stringify({
  1913. outletId: this.outletId,
  1914. departmentIds: this.deptId ? [this.deptId] : [],
  1915. }),
  1916. headers: {
  1917. 'Content-Type': 'application/json',
  1918. 'token': this.token,
  1919. 'tenancyId': this.tenancyId
  1920. }
  1921. }).then(res => {
  1922. return res.json()
  1923. }).then(result => {
  1924. let { data, code, msg } = result
  1925. if (code === 1) {
  1926. this.tableList = data || []
  1927. if (this.tableList.length > 0) {
  1928. this.carStepData.push(this.tableList[0])
  1929. }
  1930. } else if (code === 10001) {
  1931. this.loginOut()
  1932. } else {
  1933. vant.Toast.fail(msg)
  1934. }
  1935. })
  1936. },
  1937. // 意向车型标签排名
  1938. getIntentRank() {
  1939. this.intentRankData = []
  1940. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/intentRank`, {
  1941. method: 'post',
  1942. body: JSON.stringify({
  1943. outletId: this.outletId,
  1944. departmentIds: this.deptId ? [this.deptId] : [],
  1945. }),
  1946. headers: {
  1947. 'Content-Type': 'application/json',
  1948. 'token': this.token,
  1949. 'tenancyId': this.tenancyId
  1950. }
  1951. }).then(res => {
  1952. return res.json()
  1953. }).then(result => {
  1954. let { data, code, msg } = result
  1955. if (code === 1) {
  1956. this.intentRankData = data || []
  1957. this.$nextTick(() => {
  1958. this.intentRankChart()
  1959. })
  1960. } else if (code === 10001) {
  1961. this.loginOut()
  1962. } else {
  1963. vant.Toast.fail(msg)
  1964. }
  1965. })
  1966. },
  1967. intentRankChart() {
  1968. let intentRankData = this.intentRankData.sort((a, b) => a.clientNum - b.clientNum)
  1969. let rankChart = echarts.getInstanceByDom(document.getElementById('intentRankChart'))
  1970. if (rankChart == null) {
  1971. rankChart = echarts.init(document.getElementById('intentRankChart'))
  1972. }
  1973. rankChart.resize({ height: this.intentRankData.length * 50 + 20 })
  1974. window.addEventListener('resize', function () {
  1975. rankChart.resize()
  1976. })
  1977. rankChart.setOption({
  1978. tooltip: {
  1979. trigger: 'item',
  1980. formatter: '{b}: {c}'
  1981. },
  1982. legend: {
  1983. left: 'center',
  1984. icon: 'circle', //小圆点
  1985. itemWidth: 10,
  1986. itemHeight: 10,
  1987. itemGap: 10, //间隔
  1988. bottom: '10%',
  1989. },
  1990. grid: {
  1991. bottom: "0",
  1992. top: "0",
  1993. left: "0",
  1994. containLabel: true,
  1995. },
  1996. xAxis: {
  1997. type: 'value',
  1998. axisLabel: {
  1999. show: true,
  2000. color: '#666666',
  2001. fontSize: '8',
  2002. },
  2003. splitLine: {
  2004. show: true,
  2005. lineStyle: {
  2006. type: 'dashed' // 设置为虚线
  2007. }
  2008. },
  2009. },
  2010. yAxis: {
  2011. type: 'category',
  2012. axisLabel: {
  2013. formatter: function (value) {
  2014. return value.length > 4 ? value.substring(0, 4) + '...' : value
  2015. },
  2016. showTooltip: true,
  2017. },
  2018. data: this.intentRankData.map(item => {
  2019. return item.tagName
  2020. }) || [],
  2021. },
  2022. series: [
  2023. {
  2024. type: 'bar',
  2025. barWidth: 24,
  2026. barGap: 12,
  2027. itemStyle: {
  2028. color: function (p) {
  2029. // 亮度随索引递增实现渐变
  2030. const lightness = 94 - p.dataIndex * 8;
  2031. return `hsl(127.9, 72.5%, ${Math.min(100, lightness)}%)`;
  2032. }
  2033. },
  2034. data: this.intentRankData.map(item => {
  2035. return item.clientNum
  2036. }) || []
  2037. }
  2038. ]
  2039. })
  2040. },
  2041. // 已购车型标签排名
  2042. getBuyRank() {
  2043. this.buyRankData = []
  2044. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/buyRank`, {
  2045. method: 'post',
  2046. body: JSON.stringify({
  2047. outletId: this.outletId,
  2048. departmentIds: this.deptId ? [this.deptId] : [],
  2049. }),
  2050. headers: {
  2051. 'Content-Type': 'application/json',
  2052. 'token': this.token,
  2053. 'tenancyId': this.tenancyId
  2054. }
  2055. }).then(res => {
  2056. return res.json()
  2057. }).then(result => {
  2058. let { data, code, msg } = result
  2059. if (code === 1) {
  2060. this.buyRankData = data || []
  2061. this.$nextTick(() => {
  2062. this.buyRankChart()
  2063. })
  2064. } else if (code === 10001) {
  2065. this.loginOut()
  2066. } else {
  2067. vant.Toast.fail(msg)
  2068. }
  2069. })
  2070. },
  2071. buyRankChart() {
  2072. let buyRankData = this.buyRankData.sort((a, b) => a.clientNum - b.clientNum)
  2073. let rankChart = echarts.getInstanceByDom(document.getElementById('buyRankChart'))
  2074. if (rankChart == null) {
  2075. rankChart = echarts.init(document.getElementById('buyRankChart'))
  2076. }
  2077. rankChart.resize({ height: this.buyRankData.length * 50 + 20 })
  2078. window.addEventListener('resize', function () {
  2079. rankChart.resize()
  2080. })
  2081. rankChart.setOption({
  2082. tooltip: {
  2083. trigger: 'item',
  2084. formatter: '{b}: {c}'
  2085. },
  2086. legend: {
  2087. left: 'center',
  2088. icon: 'circle', //小圆点
  2089. itemWidth: 10,
  2090. itemHeight: 10,
  2091. itemGap: 10, //间隔
  2092. bottom: '10%',
  2093. },
  2094. grid: {
  2095. bottom: "0",
  2096. top: "0",
  2097. left: "0",
  2098. containLabel: true,
  2099. },
  2100. xAxis: {
  2101. type: 'value',
  2102. axisLabel: {
  2103. show: true,
  2104. color: '#666666',
  2105. fontSize: '8',
  2106. },
  2107. splitLine: {
  2108. show: true,
  2109. lineStyle: {
  2110. type: 'dashed' // 设置为虚线
  2111. }
  2112. },
  2113. },
  2114. yAxis: {
  2115. type: 'category',
  2116. axisLabel: {
  2117. formatter: function (value) {
  2118. return value.length > 4 ? value.substring(0, 4) + '...' : value
  2119. },
  2120. showTooltip: true,
  2121. },
  2122. data: this.buyRankData.map(item => {
  2123. return item.tagName
  2124. }) || [],
  2125. },
  2126. series: [
  2127. {
  2128. type: 'bar',
  2129. barWidth: 24,
  2130. barGap: 12,
  2131. itemStyle: {
  2132. color: function (p) {
  2133. // 亮度随索引递增实现渐变
  2134. const lightness = 87 - p.dataIndex * 8;
  2135. return `hsl(215, 100%, ${Math.min(100, lightness)}%)`;
  2136. }
  2137. },
  2138. data: this.buyRankData.map(item => {
  2139. return item.clientNum
  2140. }) || []
  2141. }
  2142. ]
  2143. })
  2144. },
  2145. // 聊天分析 - 总数据
  2146. getChatIndicators() {
  2147. this.chatIndicators = {
  2148. dayList: [], // 聊天分析-日数据
  2149. opinion: {},
  2150. total: {
  2151. privateChat: 0,
  2152. privateMsgNum: 0,
  2153. groupMsgNum: 0,
  2154. proactiveServe: 0,
  2155. clientReply: 0,
  2156. clientReplyPercent: 0,
  2157. proactiveConsult: 0,
  2158. memberReply: 0,
  2159. avgReplyDuration: 0,
  2160. },
  2161. yda: {
  2162. privateChat: 0,
  2163. privateMsgNum: 0,
  2164. groupMsgNum: 0,
  2165. proactiveServe: 0,
  2166. clientReply: 0,
  2167. clientReplyPercent: 0,
  2168. proactiveConsult: 0,
  2169. memberReply: 0,
  2170. avgReplyDuration: 0,
  2171. },
  2172. }
  2173. this.interactDate = []
  2174. this.privateChat = []
  2175. this.privateMsgNum = []
  2176. this.groupMsgNum = []
  2177. this.proactiveServe = []
  2178. this.clientReply = []
  2179. this.clientReplyPercent = []
  2180. this.proactiveConsult = []
  2181. this.memberReply = []
  2182. this.avgReplyDuration = []
  2183. this.totalMsg = []
  2184. this.privateMsg = []
  2185. this.groupMsg = []
  2186. this.maxValue = null
  2187. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/chatIndicators`, {
  2188. method: 'post',
  2189. body: JSON.stringify({
  2190. outletId: this.outletId,
  2191. departmentIds: this.deptId ? [this.deptId] : [],
  2192. startTime: this.pageStartTime,
  2193. endTime: this.pageEndTime,
  2194. }),
  2195. headers: {
  2196. 'Content-Type': 'application/json',
  2197. 'token': this.token,
  2198. 'tenancyId': this.tenancyId
  2199. }
  2200. }).then(res => {
  2201. return res.json()
  2202. }).then(result => {
  2203. let { data, code, msg } = result
  2204. if (code === 1) {
  2205. this.chatIndicators = {
  2206. dayList: data.dayList || [], // 聊天分析-日数据
  2207. opinion: data.opinion ? data.opinion : {
  2208. negativeGroup: 0,
  2209. positiveGroup: 0,
  2210. neutralGroup: 0,
  2211. negativePrivate: 0,
  2212. positivePrivate: 0,
  2213. neutralPrivate: 0,
  2214. negativeTotal: 0,
  2215. positiveTotal: 0,
  2216. neutralTotal: 0,
  2217. },
  2218. total: data.total ? data.total : {
  2219. privateChat: 0,
  2220. privateMsgNum: 0,
  2221. groupMsgNum: 0,
  2222. proactiveServe: 0,
  2223. clientReply: 0,
  2224. clientReplyPercent: 0,
  2225. proactiveConsult: 0,
  2226. memberReply: 0,
  2227. avgReplyDuration: 0,
  2228. },
  2229. yda: data.yda ? data.yda : {
  2230. privateChat: 0,
  2231. privateMsgNum: 0,
  2232. groupMsgNum: 0,
  2233. proactiveServe: 0,
  2234. clientReply: 0,
  2235. clientReplyPercent: 0,
  2236. proactiveConsult: 0,
  2237. memberReply: 0,
  2238. avgReplyDuration: 0,
  2239. }, // 昨日数据
  2240. }
  2241. this.interactDate = []
  2242. this.privateChat = []
  2243. this.privateMsgNum = []
  2244. this.groupMsgNum = []
  2245. this.proactiveServe = []
  2246. this.clientReply = []
  2247. this.clientReplyPercent = []
  2248. this.proactiveConsult = []
  2249. this.memberReply = []
  2250. this.avgReplyDuration = []
  2251. if (data.dayList && data.dayList.length > 0) {
  2252. data.dayList.forEach(item => {
  2253. this.interactDate.push(item.time)
  2254. this.privateChat.push(item.privateChat)
  2255. this.privateMsgNum.push(item.privateMsgNum)
  2256. this.groupMsgNum.push(item.groupMsgNum)
  2257. this.proactiveServe.push(item.proactiveServe)
  2258. this.clientReply.push(item.clientReply)
  2259. this.clientReplyPercent.push(item.clientReplyPercent)
  2260. this.proactiveConsult.push(item.proactiveConsult)
  2261. this.memberReply.push(item.memberReply)
  2262. this.avgReplyDuration.push(item.avgReplyDuration)
  2263. })
  2264. this.$nextTick(() => {
  2265. this.interactChart()
  2266. this.staffChart()
  2267. this.clientChart()
  2268. })
  2269. }
  2270. this.totalMsg = []
  2271. this.privateMsg = []
  2272. this.groupMsg = []
  2273. this.maxValue = null
  2274. if (data.opinion) {
  2275. this.totalMsg = [data.opinion.negativeTotal, data.opinion.positiveTotal, data.opinion.neutralTotal]
  2276. this.privateMsg = [data.opinion.positivePrivate, data.opinion.negativePrivate, data.opinion.neutralPrivate]
  2277. this.groupMsg = [data.opinion.positiveGroup, data.opinion.negativeGroup, data.opinion.neutralGroup]
  2278. this.maxValue = Math.max.apply(null, [...this.totalMsg, ...this.privateMsg, ...this.groupMsg])
  2279. this.$nextTick(() => {
  2280. this.opinionChart()
  2281. })
  2282. }
  2283. } else if (code === 10001) {
  2284. this.loginOut()
  2285. } else {
  2286. vant.Toast.fail(msg)
  2287. }
  2288. })
  2289. },
  2290. // 聊天分析-总数据趋势图数据
  2291. interactChart() {
  2292. let interactChart = echarts.getInstanceByDom(document.getElementById('interactChart'))
  2293. if (interactChart == null) {
  2294. interactChart = echarts.init(document.getElementById('interactChart'))
  2295. }
  2296. window.addEventListener('resize', function () {
  2297. interactChart.resize()
  2298. })
  2299. interactChart.setOption({
  2300. legend: {
  2301. x: 'center',
  2302. y: 10,
  2303. align: 'right',
  2304. itemWidth: 20,
  2305. itemHeight: 5,
  2306. itemGap: 20,
  2307. textStyle: {//图例文字的样式
  2308. color: '#666666', //图例文字颜色
  2309. fontSize: 10//图例文字大小
  2310. },
  2311. data: [
  2312. {
  2313. name: "私聊客户数",
  2314. // 单独设置图例空心圆,通过设置边框颜色+背景颜色白色实现空心圆
  2315. itemStyle: {
  2316. color: "#fff",
  2317. borderColor: '#1677FF',
  2318. borderWidth: 1,
  2319. },
  2320. },
  2321. {
  2322. name: "私聊消息数",
  2323. // 单独设置图例空心圆,通过设置边框颜色+背景颜色白色实现空心圆
  2324. itemStyle: {
  2325. color: "#fff",
  2326. borderColor: '#5CE56E',
  2327. borderWidth: 1,
  2328. },
  2329. },
  2330. {
  2331. name: "群消息数",
  2332. itemStyle: {
  2333. width: 20,
  2334. height: 5,
  2335. color: "#E6F0FF",
  2336. },
  2337. },
  2338. ]
  2339. },
  2340. tooltip: {
  2341. trigger: 'axis'
  2342. },
  2343. grid: {
  2344. top: '20%',
  2345. left: '10%',
  2346. right: '10%',
  2347. bottom: '10%'
  2348. },
  2349. xAxis: {
  2350. type: 'category',
  2351. axisLabel: {
  2352. show: true,
  2353. color: "#666666",
  2354. fontSize: '8',
  2355. },
  2356. data: this.interactDate,
  2357. },
  2358. yAxis: [
  2359. {// 第一种方式
  2360. type: 'value',
  2361. min: 0,
  2362. max: Math.max(...this.privateMsgNum, ...this.privateChat, ...this.groupMsgNum),
  2363. splitNumber: 5,
  2364. interval: Math.max(...this.privateMsgNum, ...this.privateChat, ...this.groupMsgNum) / 5,
  2365. axisLabel: {
  2366. show: true,
  2367. color: "#222222",
  2368. fontSize: '8',
  2369. formatter: function (v) {
  2370. return v.toFixed(0) //0表示小数为0位,1表示1位小数,2表示2位小数
  2371. }
  2372. },
  2373. splitLine: { //网格线
  2374. lineStyle: {
  2375. type: 'dashed'//设置网格线类型 dotted:虚线 solid:实线
  2376. },
  2377. },
  2378. axisTick: { show: false },
  2379. },
  2380. ],
  2381. series: [
  2382. {
  2383. name: '私聊客户数',
  2384. type: 'line',
  2385. color: '#1677FF',
  2386. data: this.privateChat,
  2387. symbol: 'none', //去掉折线图中的节点
  2388. smooth: true, //true 为平滑曲线,false为直线
  2389. },
  2390. {
  2391. name: '私聊消息数',
  2392. type: 'line',
  2393. color: '#5CE56E',
  2394. data: this.privateMsgNum,
  2395. symbol: 'none', //去掉折线图中的节点
  2396. smooth: true, //true 为平滑曲线,false为直线
  2397. },
  2398. {
  2399. name: '群消息数',
  2400. type: 'bar', //形状为柱状图
  2401. data: this.groupMsgNum,
  2402. itemStyle: {
  2403. color: ' #E6F0FF',
  2404. },
  2405. emphasis: {
  2406. itemStyle: {
  2407. color: 'rgb(0, 157, 255)'
  2408. }
  2409. },
  2410. }
  2411. ],
  2412. }, true)
  2413. },
  2414. // 聊天分析-员工服务趋势图数据
  2415. staffChart() {
  2416. let staffChart = echarts.getInstanceByDom(document.getElementById('staffChart'))
  2417. if (staffChart == null) {
  2418. staffChart = echarts.init(document.getElementById('staffChart'))
  2419. }
  2420. window.addEventListener('resize', function () {
  2421. staffChart.resize()
  2422. })
  2423. staffChart.setOption({
  2424. legend: {
  2425. orient: 'horizontal',
  2426. x: 'center',
  2427. y: 10,
  2428. align: 'right',
  2429. itemWidth: 20,
  2430. itemHeight: 5,
  2431. itemGap: 20,
  2432. textStyle: {//图例文字的样式
  2433. color: '#666666', //图例文字颜色
  2434. fontSize: 10//图例文字大小
  2435. },
  2436. data: [
  2437. {
  2438. name: "主动服务会话数",
  2439. // 单独设置图例空心圆,通过设置边框颜色+背景颜色白色实现空心圆
  2440. itemStyle: {
  2441. width: 20,
  2442. height: 5,
  2443. color: "#1677FF",
  2444. },
  2445. },
  2446. {
  2447. name: "客户回复会话数",
  2448. // 单独设置图例空心圆,通过设置边框颜色+背景颜色白色实现空心圆
  2449. itemStyle: {
  2450. width: 20,
  2451. height: 5,
  2452. color: "#5CE56E",
  2453. },
  2454. },
  2455. {
  2456. name: "客户回复率",
  2457. itemStyle: {
  2458. color: "#fff",
  2459. borderColor: '#FFA64E',
  2460. borderWidth: 1,
  2461. },
  2462. },
  2463. ]
  2464. },
  2465. tooltip: {
  2466. trigger: 'axis'
  2467. },
  2468. grid: {
  2469. top: '20%',
  2470. left: '10%',
  2471. right: '10%',
  2472. bottom: '10%'
  2473. },
  2474. xAxis: {
  2475. type: 'category',
  2476. axisLabel: {
  2477. show: true,
  2478. color: "#666666",
  2479. fontSize: '8',
  2480. },
  2481. data: this.interactDate,
  2482. },
  2483. yAxis: [
  2484. {// 第一种方式
  2485. type: 'value',
  2486. min: 0,
  2487. max: Math.max(...this.proactiveServe, ...this.clientReply),
  2488. splitNumber: 5,
  2489. interval: Math.max(...this.proactiveServe, ...this.clientReply) / 5,
  2490. axisLabel: {
  2491. show: true,
  2492. color: "#222222",
  2493. fontSize: '8',
  2494. formatter: function (v) {
  2495. return v.toFixed(0) //0表示小数为0位,1表示1位小数,2表示2位小数
  2496. }
  2497. },
  2498. splitLine: { //网格线
  2499. lineStyle: {
  2500. type: 'dashed'//设置网格线类型 dotted:虚线 solid:实线
  2501. },
  2502. },
  2503. axisTick: { show: false },
  2504. },
  2505. {// 第二种方式
  2506. type: 'value',
  2507. min: 0,
  2508. max: Math.max(...this.clientReplyPercent),
  2509. splitNumber: 5,
  2510. interval: Math.max(...this.clientReplyPercent) / 5,
  2511. axisLabel: {
  2512. show: true,
  2513. color: "#222222",
  2514. fontSize: '8',
  2515. formatter: function (v) {
  2516. return v.toFixed(0) + ' %'; //0表示小数为0位,1表示1位小数,2表示2位小数
  2517. }
  2518. },
  2519. splitLine: { //网格线
  2520. lineStyle: {
  2521. type: 'dashed'//设置网格线类型 dotted:虚线 solid:实线
  2522. },
  2523. },
  2524. axisTick: { show: false },
  2525. },
  2526. ],
  2527. series: [
  2528. {
  2529. name: '主动服务会话数',
  2530. type: 'bar', //形状为柱状图
  2531. data: this.proactiveServe,
  2532. itemStyle: {
  2533. color: ' #1677FF',
  2534. borderRadius: [5, 5, 0, 0]
  2535. },
  2536. emphasis: {
  2537. itemStyle: {
  2538. color: 'rgb(0, 157, 255)'
  2539. }
  2540. },
  2541. },
  2542. {
  2543. name: '客户回复会话数',
  2544. type: 'bar', //形状为柱状图
  2545. data: this.clientReply,
  2546. itemStyle: {
  2547. color: ' #5CE56E',
  2548. borderRadius: [5, 5, 0, 0]
  2549. },
  2550. emphasis: {
  2551. itemStyle: {
  2552. color: 'rgb(0, 157, 255)'
  2553. }
  2554. },
  2555. },
  2556. {
  2557. name: '客户回复率',
  2558. type: 'line',
  2559. color: '#FFA64E',
  2560. symbol: 'none',
  2561. yAxisIndex: 1,
  2562. data: this.clientReplyPercent,
  2563. tooltip: {
  2564. valueFormatter: function (value) {
  2565. return value ? value + ' %' : ''
  2566. }
  2567. },
  2568. smooth: true, //true 为平滑曲线,false为直线
  2569. }
  2570. ],
  2571. }, true)
  2572. },
  2573. // 聊天分析-客户咨询趋势图数据
  2574. clientChart() {
  2575. let clientChart = echarts.getInstanceByDom(document.getElementById('clientChart'))
  2576. if (clientChart == null) {
  2577. clientChart = echarts.init(document.getElementById('clientChart'))
  2578. }
  2579. window.addEventListener('resize', function () {
  2580. clientChart.resize()
  2581. })
  2582. clientChart.setOption({
  2583. legend: {
  2584. orient: 'horizontal',
  2585. x: 'center',
  2586. y: 10,
  2587. align: 'right',
  2588. itemWidth: 16,
  2589. itemHeight: 4,
  2590. itemGap: 10,
  2591. textStyle: {//图例文字的样式
  2592. color: '#666666', //图例文字颜色
  2593. fontSize: 10//图例文字大小
  2594. },
  2595. data: [
  2596. {
  2597. name: "主动咨询会话数",
  2598. // 单独设置图例空心圆,通过设置边框颜色+背景颜色白色实现空心圆
  2599. itemStyle: {
  2600. width: 20,
  2601. height: 5,
  2602. color: "#1677FF",
  2603. },
  2604. },
  2605. {
  2606. name: "员工回复会话数",
  2607. // 单独设置图例空心圆,通过设置边框颜色+背景颜色白色实现空心圆
  2608. itemStyle: {
  2609. width: 20,
  2610. height: 5,
  2611. color: "#5CE56E",
  2612. },
  2613. },
  2614. {
  2615. name: "员工平均响应时长",
  2616. itemStyle: {
  2617. color: "#fff",
  2618. borderColor: '#FFA64E',
  2619. borderWidth: 1,
  2620. },
  2621. },
  2622. ]
  2623. },
  2624. tooltip: {
  2625. trigger: 'axis'
  2626. },
  2627. grid: {
  2628. top: '20%',
  2629. left: '10%',
  2630. right: '10%',
  2631. bottom: '10%'
  2632. },
  2633. xAxis: {
  2634. type: 'category',
  2635. axisLabel: {
  2636. show: true,
  2637. color: "#666666",
  2638. fontSize: '8',
  2639. },
  2640. data: this.interactDate,
  2641. },
  2642. yAxis: [
  2643. {// 第一种方式
  2644. type: 'value',
  2645. min: 0,
  2646. max: Math.max(...this.proactiveConsult, ...this.memberReply),
  2647. splitNumber: 5,
  2648. interval: Math.max(...this.proactiveConsult, ...this.memberReply) / 5,
  2649. axisLabel: {
  2650. show: true,
  2651. color: "#222222",
  2652. fontSize: '8',
  2653. formatter: function (v) {
  2654. return v.toFixed(0) //0表示小数为0位,1表示1位小数,2表示2位小数
  2655. }
  2656. },
  2657. splitLine: { //网格线
  2658. lineStyle: {
  2659. type: 'dashed'//设置网格线类型 dotted:虚线 solid:实线
  2660. },
  2661. },
  2662. axisTick: { show: false },
  2663. },
  2664. {// 第二种方式
  2665. type: 'value',
  2666. min: 0,
  2667. max: Math.max(...this.avgReplyDuration),
  2668. splitNumber: 5,
  2669. interval: Math.max(...this.avgReplyDuration) / 5,
  2670. axisLabel: {
  2671. show: true,
  2672. color: "#222222",
  2673. fontSize: '8',
  2674. formatter: function (v) {
  2675. return v.toFixed(0) + ' s'; //0表示小数为0位,1表示1位小数,2表示2位小数
  2676. }
  2677. },
  2678. splitLine: { //网格线
  2679. lineStyle: {
  2680. type: 'dashed'//设置网格线类型 dotted:虚线 solid:实线
  2681. },
  2682. },
  2683. axisTick: { show: false },
  2684. },
  2685. ],
  2686. series: [
  2687. {
  2688. name: '主动咨询会话数',
  2689. type: 'bar', //形状为柱状图
  2690. data: this.proactiveConsult,
  2691. itemStyle: {
  2692. color: ' #1677FF',
  2693. borderRadius: [5, 5, 0, 0]
  2694. },
  2695. emphasis: {
  2696. itemStyle: {
  2697. color: 'rgb(0, 157, 255)'
  2698. }
  2699. },
  2700. },
  2701. {
  2702. name: '员工回复会话数',
  2703. type: 'bar', //形状为柱状图
  2704. data: this.memberReply,
  2705. itemStyle: {
  2706. color: ' #5CE56E',
  2707. borderRadius: [5, 5, 0, 0]
  2708. },
  2709. emphasis: {
  2710. itemStyle: {
  2711. color: 'rgb(0, 157, 255)'
  2712. }
  2713. },
  2714. },
  2715. {
  2716. name: '员工平均响应时长',
  2717. type: 'line',
  2718. color: '#FFA64E',
  2719. symbol: 'none',
  2720. yAxisIndex: 1,
  2721. tooltip: {
  2722. valueFormatter: function (value) {
  2723. return value ? value.toFixed(0) + ' s' : ''
  2724. }
  2725. },
  2726. data: this.avgReplyDuration,
  2727. smooth: true, //true 为平滑曲线,false为直线
  2728. }
  2729. ],
  2730. }, true)
  2731. },
  2732. // 聊天分析-消息舆情分析
  2733. opinionChart() {
  2734. let opinionChart = echarts.getInstanceByDom(document.getElementById('opinionChart'))
  2735. if (opinionChart == null) {
  2736. opinionChart = echarts.init(document.getElementById('opinionChart'))
  2737. }
  2738. window.addEventListener('resize', function () {
  2739. opinionChart.resize()
  2740. })
  2741. opinionChart.setOption({
  2742. legend: {
  2743. orient: 'horizontal',
  2744. align: 'right',
  2745. itemWidth: 20,
  2746. itemHeight: 4,
  2747. itemGap: 20,
  2748. textStyle: {//图例文字的样式
  2749. color: '#666666', //图例文字颜色
  2750. fontSize: 10//图例文字大小
  2751. }
  2752. },
  2753. radar: {
  2754. indicator: [
  2755. { name: '负面', max: this.maxValue },
  2756. { name: '中性', max: this.maxValue },
  2757. { name: '正面', max: this.maxValue },
  2758. ],
  2759. radius: 150,
  2760. },
  2761. series: [
  2762. {
  2763. type: 'radar',
  2764. color: '#1677FF',
  2765. data: [
  2766. {
  2767. value: this.totalMsg,
  2768. name: '全部消息',
  2769. itemStyle: {
  2770. color: '#1677FF',
  2771. lineStyle: {
  2772. color: '#1677FF',
  2773. },
  2774. },
  2775. },
  2776. {
  2777. value: this.privateMsg,
  2778. name: '单聊消息',
  2779. itemStyle: {
  2780. color: '#5CE56E',
  2781. lineStyle: {
  2782. color: '#5CE56E',
  2783. },
  2784. },
  2785. },
  2786. {
  2787. value: this.groupMsg,
  2788. name: '群聊消息',
  2789. itemStyle: {
  2790. color: '#FFA64E',
  2791. lineStyle: {
  2792. color: '#FFA64E',
  2793. },
  2794. },
  2795. }
  2796. ]
  2797. },
  2798. ]
  2799. }, true)
  2800. },
  2801. // 聊天分析-词云图
  2802. getWordCloudMap() {
  2803. this.wordCloudMap = []
  2804. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/wordCloudMap`, {
  2805. method: 'post',
  2806. body: JSON.stringify({
  2807. outletId: this.outletId,
  2808. departmentIds: this.deptId ? [this.deptId] : [],
  2809. startTime: this.pageStartTime,
  2810. endTime: this.pageEndTime,
  2811. }),
  2812. headers: {
  2813. 'Content-Type': 'application/json',
  2814. 'token': this.token,
  2815. 'tenancyId': this.tenancyId
  2816. }
  2817. }).then(res => {
  2818. return res.json()
  2819. }).then(result => {
  2820. let { data, code, msg } = result
  2821. if (code === 1) {
  2822. this.wordCloudMap = data || []
  2823. this.$nextTick(() => {
  2824. this.wordCloudChart()
  2825. })
  2826. } else if (code === 10001) {
  2827. this.loginOut()
  2828. } else {
  2829. vant.Toast.fail(msg)
  2830. }
  2831. })
  2832. },
  2833. wordCloudChart() {
  2834. let wordCloudChart = echarts.getInstanceByDom(document.getElementById('wordCloudChart'))
  2835. if (wordCloudChart == null) {
  2836. wordCloudChart = echarts.init(document.getElementById('wordCloudChart'))
  2837. }
  2838. window.addEventListener('resize', function () {
  2839. wordCloudChart.resize()
  2840. })
  2841. wordCloudChart.setOption({
  2842. series: [{
  2843. type: 'wordCloud',
  2844. //maskImage: maskImage,
  2845. sizeRange: [12, 24],
  2846. rotationRange: [0, 0],
  2847. rotationStep: 45,
  2848. gridSize: 8,
  2849. shape: 'pentagon',
  2850. width: '100%',
  2851. height: '100%',
  2852. textStyle: {
  2853. fontFamily: '微软雅黑',
  2854. color: (v) => {
  2855. switch (true) {
  2856. case v.dataIndex <= 5:
  2857. return '#1677FF'
  2858. case 5 < v.dataIndex && v.dataIndex <= 10:
  2859. return 'rgba(22, 119, 255, 0.6)'
  2860. default:
  2861. return 'rgba(22, 119, 255, 0.4)'
  2862. }
  2863. }
  2864. },
  2865. data: this.wordCloudMap,
  2866. }]
  2867. }, true)
  2868. },
  2869. // 销售进程客户数
  2870. getSaleIndicators() {
  2871. this.saleIndicators = []
  2872. this.clientStepDate = []
  2873. this.clientStepNum = []
  2874. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/saleIndicators`, {
  2875. method: 'post',
  2876. body: JSON.stringify({
  2877. outletId: this.outletId,
  2878. departmentIds: this.deptId ? [this.deptId] : [],
  2879. startTime: this.pageStartTime,
  2880. endTime: this.pageEndTime,
  2881. }),
  2882. headers: {
  2883. 'Content-Type': 'application/json',
  2884. 'token': this.token,
  2885. 'tenancyId': this.tenancyId
  2886. }
  2887. }).then(res => {
  2888. return res.json()
  2889. }).then(result => {
  2890. let { data, code, msg } = result
  2891. if (code === 1) {
  2892. this.saleIndicators = data || []
  2893. if (data && data.length) {
  2894. data[0].dayList.forEach(item => {
  2895. this.clientStepDate.push(item.time)
  2896. this.clientStepNum.push(item.clientNum)
  2897. })
  2898. this.$nextTick(() => {
  2899. this.clientStepChart()
  2900. })
  2901. }
  2902. } else if (code === 10001) {
  2903. this.loginOut()
  2904. } else {
  2905. vant.Toast.fail(msg)
  2906. }
  2907. })
  2908. },
  2909. handleClickClient(item, index) {
  2910. this.clientIndex = index
  2911. this.clientStepDate = []
  2912. this.clientStepNum = []
  2913. if (item.dayList && item.dayList.length) {
  2914. this.clientStepDate = item.dayList.map(item => item.time)
  2915. this.clientStepNum = item.dayList.map(item => item.clientNum)
  2916. this.$nextTick(() => {
  2917. this.clientStepChart()
  2918. })
  2919. }
  2920. },
  2921. clientStepChart() {
  2922. let clientStepChart = echarts.getInstanceByDom(document.getElementById('clientStepChart'))
  2923. if (clientStepChart == null) {
  2924. clientStepChart = echarts.init(document.getElementById('clientStepChart'))
  2925. }
  2926. window.addEventListener('resize', function () {
  2927. clientStepChart.resize()
  2928. })
  2929. let text = this.saleIndicators[this.clientIndex].processName
  2930. clientStepChart.setOption({
  2931. legend: {
  2932. show: false,
  2933. },
  2934. tooltip: {
  2935. trigger: 'axis',
  2936. formatter: function (params) {
  2937. return params[0].name + '<br>'
  2938. + text + ': ' + params[0].value
  2939. }
  2940. },
  2941. grid: {
  2942. top: '10%',
  2943. left: '10%',
  2944. right: '10%',
  2945. bottom: '10%'
  2946. },
  2947. xAxis: {
  2948. type: 'category',
  2949. axisLabel: {
  2950. show: true,
  2951. color: "#666666",
  2952. fontSize: '8',
  2953. },
  2954. data: this.clientStepDate,
  2955. },
  2956. yAxis: [
  2957. {// 第一种方式
  2958. type: 'value',
  2959. min: 0,
  2960. max: Math.max(...this.clientStepNum),
  2961. splitNumber: 5,
  2962. interval: Math.max(...this.clientStepNum) / 5,
  2963. position: 'left',
  2964. axisLabel: {
  2965. show: true,
  2966. color: "#222222",
  2967. fontSize: '8',
  2968. formatter: function (v) {
  2969. return v.toFixed(0) //0表示小数为0位,1表示1位小数,2表示2位小数
  2970. }
  2971. },
  2972. splitLine: { //网格线
  2973. lineStyle: {
  2974. type: 'dashed'//设置网格线类型 dotted:虚线 solid:实线
  2975. },
  2976. },
  2977. axisTick: { show: false },
  2978. },
  2979. ],
  2980. series: [
  2981. {
  2982. type: 'line',
  2983. color: '#1677FF',
  2984. areaStyle: {
  2985. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  2986. { offset: 0, color: 'rgba(22,119,255,0.43)' },
  2987. { offset: 1, color: 'rgba(22,119,255,0)' }
  2988. ])
  2989. }, //填充区域样式
  2990. data: this.clientStepNum,
  2991. symbol: 'none', //去掉折线图中的节点
  2992. smooth: true, //true 为平滑曲线,false为直线
  2993. }
  2994. ],
  2995. }, true)
  2996. },
  2997. // 销售统计排名
  2998. getSaleRank() {
  2999. this.saleRankData = []
  3000. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/saleRank`, {
  3001. method: 'post',
  3002. body: JSON.stringify({
  3003. outletId: this.outletId,
  3004. departmentIds: this.deptId ? [this.deptId] : [],
  3005. startTime: this.pageStartTime,
  3006. endTime: this.pageEndTime,
  3007. }),
  3008. headers: {
  3009. 'Content-Type': 'application/json',
  3010. 'token': this.token,
  3011. 'tenancyId': this.tenancyId
  3012. }
  3013. }).then(res => {
  3014. return res.json()
  3015. }).then(result => {
  3016. let { data, code, msg } = result
  3017. if (code === 1) {
  3018. this.saleRankData = data || []
  3019. } else if (code === 10001) {
  3020. this.loginOut()
  3021. } else {
  3022. vant.Toast.fail(msg)
  3023. }
  3024. })
  3025. },
  3026. // 聊天超时监测
  3027. getTimeOutTrendChart() {
  3028. this.timeOutDate = []
  3029. this.timeoutMember = []
  3030. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/timeOutTrend`, {
  3031. method: 'post',
  3032. body: JSON.stringify({
  3033. outletId: this.outletId,
  3034. departmentIds: this.deptId ? [this.deptId] : [],
  3035. startTime: this.pageStartTime,
  3036. endTime: this.pageEndTime,
  3037. }),
  3038. headers: {
  3039. 'Content-Type': 'application/json',
  3040. 'token': this.token,
  3041. 'tenancyId': this.tenancyId
  3042. }
  3043. }).then(res => {
  3044. return res.json()
  3045. }).then(result => {
  3046. let { data, code, msg } = result
  3047. if (code === 1) {
  3048. if (data && data.length) {
  3049. data.forEach(item => {
  3050. this.timeOutDate.push(item.time)
  3051. this.timeoutMember.push(item.timeoutMember)
  3052. })
  3053. this.$nextTick(() => {
  3054. this.timeOutTrendChart()
  3055. })
  3056. }
  3057. } else if (code === 10001) {
  3058. this.loginOut()
  3059. } else {
  3060. vant.Toast.fail(msg)
  3061. }
  3062. })
  3063. },
  3064. timeOutTrendChart() {
  3065. let timeOutTrendChart = echarts.getInstanceByDom(document.getElementById('timeOutTrendChart'))
  3066. if (timeOutTrendChart == null) {
  3067. timeOutTrendChart = echarts.init(document.getElementById('timeOutTrendChart'))
  3068. }
  3069. window.addEventListener('resize', function () {
  3070. timeOutTrendChart.resize()
  3071. })
  3072. timeOutTrendChart.setOption({
  3073. legend: {
  3074. show: false,
  3075. },
  3076. tooltip: {
  3077. trigger: 'axis',
  3078. formatter: function (params) {
  3079. return params[0].name + ': ' + params[0].value
  3080. }
  3081. },
  3082. grid: {
  3083. top: '10%',
  3084. left: '10%',
  3085. right: '10%',
  3086. bottom: '10%'
  3087. },
  3088. xAxis: {
  3089. type: 'category',
  3090. axisLabel: {
  3091. show: true,
  3092. color: "#666666",
  3093. fontSize: '8',
  3094. },
  3095. data: this.timeOutDate,
  3096. },
  3097. yAxis: [
  3098. {// 第一种方式
  3099. type: 'value',
  3100. min: 0,
  3101. max: Math.max(...this.timeoutMember),
  3102. splitNumber: 5,
  3103. interval: Math.max(...this.timeoutMember) / 5,
  3104. position: 'left',
  3105. axisLabel: {
  3106. show: true,
  3107. color: "#222222",
  3108. fontSize: '8',
  3109. formatter: function (v) {
  3110. return v.toFixed(0) //0表示小数为0位,1表示1位小数,2表示2位小数
  3111. }
  3112. },
  3113. splitLine: { //网格线
  3114. lineStyle: {
  3115. type: 'dashed'//设置网格线类型 dotted:虚线 solid:实线
  3116. },
  3117. },
  3118. axisTick: { show: false },
  3119. },
  3120. ],
  3121. series: [
  3122. {
  3123. type: 'line',
  3124. color: '#FF4E4E',
  3125. areaStyle: {
  3126. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  3127. { offset: 0, color: 'rgba(255, 78, 78,0.43)' },
  3128. { offset: 1, color: 'rgba(255, 78, 78,0)' }
  3129. ])
  3130. }, //填充区域样式
  3131. data: this.timeoutMember,
  3132. symbol: 'none', //去掉折线图中的节点
  3133. smooth: true, //true 为平滑曲线,false为直线
  3134. }
  3135. ],
  3136. }, true)
  3137. },
  3138. returnOutsideDate() {
  3139. this.memberStartTime = this.pageStartTime
  3140. this.memberEndTime = this.pageEndTime
  3141. if (this.pageStartTime === this.getDateTime(-1) && this.pageEndTime === this.getDateTime(-1)) {
  3142. this.timeData = '昨日'
  3143. } else if (this.pageStartTime === this.getDateTime(-7) && this.pageEndTime === this.getDateTime(-1)) {
  3144. this.timeData = '近7天'
  3145. } else if (this.pageStartTime === this.getDateTime(-30) && this.pageEndTime === this.getDateTime(-1)) {
  3146. this.timeData = '近30天'
  3147. } else {
  3148. this.timeData = '自定义'
  3149. }
  3150. },
  3151. // 顾问响应统计
  3152. handleMemberReply() {
  3153. this.showMemberReply = true
  3154. this.returnOutsideDate()
  3155. this.getMemberReply()
  3156. },
  3157. getMemberReply() {
  3158. this.loading = true
  3159. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/memberReply`, {
  3160. method: 'post',
  3161. body: JSON.stringify({
  3162. outletId: this.outletId,
  3163. departmentIds: this.deptId ? [this.deptId] : [],
  3164. startTime: this.memberStartTime,
  3165. endTime: this.memberEndTime,
  3166. page: this.currentPage,
  3167. pageCount: 10,
  3168. keyword: this.keyword,
  3169. }),
  3170. headers: {
  3171. 'Content-Type': 'application/json',
  3172. 'token': this.token,
  3173. 'tenancyId': this.tenancyId
  3174. }
  3175. }).then(res => {
  3176. return res.json()
  3177. }).then(result => {
  3178. let { data, code, msg } = result
  3179. if (code === 1) {
  3180. this.memberReplyData = data.records || []
  3181. this.totalItems = data.total || 0
  3182. } else if (code === 10001) {
  3183. this.loginOut()
  3184. } else {
  3185. vant.Toast.fail(msg)
  3186. }
  3187. }).finally(() => {
  3188. this.loading = false
  3189. })
  3190. },
  3191. onSelect(val) {
  3192. this.timeData = val.text
  3193. if (this.timeData === '自定义') {
  3194. this.showSelfDate = true
  3195. } else {
  3196. if (this.timeData === '昨日') {
  3197. this.memberStartTime = this.getDateTime(-1)
  3198. this.memberEndTime = this.getDateTime(-1)
  3199. } else if (this.timeData === '近7天') {
  3200. this.memberStartTime = this.getDateTime(-7)
  3201. this.memberEndTime = this.getDateTime(-1)
  3202. } else if (this.timeData === '近30天') {
  3203. this.memberStartTime = this.getDateTime(-30)
  3204. this.memberEndTime = this.getDateTime(-1)
  3205. }
  3206. this.$nextTick(() => {
  3207. if (this.showDoneReply) {
  3208. this.getDoneReply()
  3209. } else {
  3210. if (this.memberId) {
  3211. this.handleItemMemberReplyDetail()
  3212. } else {
  3213. this.getMemberReply()
  3214. }
  3215. }
  3216. })
  3217. }
  3218. },
  3219. onSelfConfirm(date) {
  3220. const [start, end] = date
  3221. if (this.formatDate(new Date()) === this.formatDate(end)) {
  3222. this.formatDate(end) = this.formatDate(start)
  3223. }
  3224. this.memberStartTime = this.formatDate(start)
  3225. this.memberEndTime = this.formatDate(end)
  3226. this.showSelfDate = false
  3227. if (this.showDoneReply) {
  3228. this.getDoneReply()
  3229. } else {
  3230. if (this.memberId) {
  3231. this.handleItemMemberReplyDetail()
  3232. } else {
  3233. this.getMemberReply()
  3234. }
  3235. }
  3236. },
  3237. formatDate(date) {
  3238. return `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`
  3239. },
  3240. handleSearch() {
  3241. this.getMemberReply()
  3242. },
  3243. handleChangePage(val) {
  3244. this.currentPage = val
  3245. if (this.showDoneReply) {
  3246. this.getDoneReply()
  3247. } else {
  3248. this.getMemberReply()
  3249. }
  3250. },
  3251. closeReply() {
  3252. this.currentPage = 1
  3253. this.totalItems = 0
  3254. this.keyword = ''
  3255. this.timeData = '近7天'
  3256. this.memberStartTime = this.getDateTime(-7)
  3257. this.memberEndTime = this.getDateTime(-1)
  3258. this.memberReplyData = []
  3259. this.showMemberReply = false
  3260. this.showDoneReply = false
  3261. },
  3262. handleItemMemberReply(item) {
  3263. this.showItemMemberReply = true
  3264. this.currentMemberName = item.memberName
  3265. this.memberId = item.memberId
  3266. this.currentItemPage = 1
  3267. this.itemTotalItems = 0
  3268. this.memberDetailReplyData = []
  3269. this.handleItemMemberReplyDetail(item)
  3270. },
  3271. closeItemMemberReply() {
  3272. this.showItemMemberReply = false
  3273. },
  3274. handleChangeItemPage(val) {
  3275. this.currentItemPage = val
  3276. this.handleItemMemberReplyDetail()
  3277. },
  3278. // 顾客响应统计-详情
  3279. handleItemMemberReplyDetail() {
  3280. this.loading = true
  3281. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/memberReplyDetail`, {
  3282. method: 'post',
  3283. body: JSON.stringify({
  3284. outletId: this.outletId,
  3285. departmentIds: this.deptId ? [this.deptId] : [],
  3286. startTime: this.memberStartTime,
  3287. endTime: this.memberEndTime,
  3288. page: this.currentItemPage,
  3289. pageCount: 10,
  3290. memberId: this.memberId,
  3291. }),
  3292. headers: {
  3293. 'Content-Type': 'application/json',
  3294. 'token': this.token,
  3295. 'tenancyId': this.tenancyId
  3296. }
  3297. }).then(res => {
  3298. return res.json()
  3299. }).then(result => {
  3300. let { data, code, msg } = result
  3301. if (code === 1) {
  3302. this.memberDetailReplyData = data.records || []
  3303. this.itemTotalItems = data.total || 0
  3304. } else if (code === 10001) {
  3305. this.loginOut()
  3306. } else {
  3307. vant.Toast.fail(msg)
  3308. }
  3309. }).finally(() => {
  3310. this.loading = false
  3311. })
  3312. },
  3313. // 顾客完成情况统计
  3314. handleDoneReply() {
  3315. this.showDoneReply = true
  3316. this.returnOutsideDate()
  3317. this.getDoneReply()
  3318. },
  3319. getDoneReply() {
  3320. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/operationMemberCnt`, {
  3321. method: 'post',
  3322. body: JSON.stringify({
  3323. outletId: this.outletId,
  3324. departmentIds: this.deptId ? [this.deptId] : [],
  3325. startTime: this.memberStartTime,
  3326. endTime: this.memberEndTime,
  3327. page: this.currentPage,
  3328. pageCount: 10,
  3329. }),
  3330. headers: {
  3331. 'Content-Type': 'application/json',
  3332. 'token': this.token,
  3333. 'tenancyId': this.tenancyId
  3334. }
  3335. }).then(res => {
  3336. return res.json()
  3337. }).then(result => {
  3338. let { data, code, msg } = result
  3339. if (code === 1) {
  3340. this.doneReplyData = data.records || []
  3341. this.totalItems = data.total || 0
  3342. } else if (code === 10001) {
  3343. this.loginOut()
  3344. } else {
  3345. vant.Toast.fail(msg)
  3346. }
  3347. })
  3348. },
  3349. // 聊天排行榜
  3350. getChatRank() {
  3351. this.chatRankData = []
  3352. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/chatRank`, {
  3353. method: 'post',
  3354. body: JSON.stringify({
  3355. outletId: this.outletId,
  3356. departmentIds: this.deptId ? [this.deptId] : [],
  3357. startTime: this.pageStartTime,
  3358. endTime: this.pageEndTime,
  3359. }),
  3360. headers: {
  3361. 'Content-Type': 'application/json',
  3362. 'token': this.token,
  3363. 'tenancyId': this.tenancyId
  3364. }
  3365. }).then(res => {
  3366. return res.json()
  3367. }).then(result => {
  3368. let { data, code, msg } = result
  3369. if (code === 1) {
  3370. this.chatRankData = data || []
  3371. } else if (code === 10001) {
  3372. this.loginOut()
  3373. } else {
  3374. vant.Toast.fail(msg)
  3375. }
  3376. })
  3377. },
  3378. // 运营任务-总数据
  3379. getOutletCount() {
  3380. this.outletCount = []
  3381. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/outletCount`, {
  3382. method: 'post',
  3383. body: JSON.stringify({
  3384. outletId: this.outletId,
  3385. departmentIds: this.deptId ? [this.deptId] : [],
  3386. startTime: this.pageStartTime,
  3387. endTime: this.pageEndTime,
  3388. }),
  3389. headers: {
  3390. 'Content-Type': 'application/json',
  3391. 'token': this.token,
  3392. 'tenancyId': this.tenancyId
  3393. }
  3394. }).then(res => {
  3395. return res.json()
  3396. }).then(result => {
  3397. let { data, code, msg } = result
  3398. if (code === 1) {
  3399. this.outletCount = data || []
  3400. } else if (code === 10001) {
  3401. this.loginOut()
  3402. } else {
  3403. vant.Toast.fail(msg)
  3404. }
  3405. })
  3406. },
  3407. // 运营任务-任务完成率
  3408. getTaskCompleteChart() {
  3409. this.taskCompleteDate = []
  3410. this.taskCompletePercent = []
  3411. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/taskCompletePercent`, {
  3412. method: 'post',
  3413. body: JSON.stringify({
  3414. outletId: this.outletId,
  3415. departmentIds: this.deptId ? [this.deptId] : [],
  3416. startTime: this.pageStartTime,
  3417. endTime: this.pageEndTime,
  3418. }),
  3419. headers: {
  3420. 'Content-Type': 'application/json',
  3421. 'token': this.token,
  3422. 'tenancyId': this.tenancyId
  3423. }
  3424. }).then(res => {
  3425. return res.json()
  3426. }).then(result => {
  3427. let { data, code, msg } = result
  3428. if (code === 1) {
  3429. if (data && data.length) {
  3430. data.forEach(item => {
  3431. this.taskCompleteDate.push(item.time)
  3432. this.taskCompletePercent.push(item.taskCompletePercent)
  3433. })
  3434. this.$nextTick(() => {
  3435. this.taskCompleteChart()
  3436. })
  3437. }
  3438. } else if (code === 10001) {
  3439. this.loginOut()
  3440. } else {
  3441. vant.Toast.fail(msg)
  3442. }
  3443. })
  3444. },
  3445. taskCompleteChart() {
  3446. let taskCompleteChart = echarts.getInstanceByDom(document.getElementById('taskCompleteChart'))
  3447. if (taskCompleteChart == null) {
  3448. taskCompleteChart = echarts.init(document.getElementById('taskCompleteChart'))
  3449. }
  3450. window.addEventListener('resize', function () {
  3451. taskCompleteChart.resize()
  3452. })
  3453. taskCompleteChart.setOption({
  3454. legend: {
  3455. show: false,
  3456. },
  3457. tooltip: {
  3458. trigger: 'axis',
  3459. valueFormatter: function (value) {
  3460. return value ? value.toFixed(2) + ' %' : ''
  3461. }
  3462. },
  3463. grid: {
  3464. top: '10%',
  3465. left: '10%',
  3466. right: '10%',
  3467. bottom: '10%'
  3468. },
  3469. xAxis: {
  3470. type: 'category',
  3471. axisLabel: {
  3472. show: true,
  3473. color: "#666666",
  3474. fontSize: '8',
  3475. },
  3476. data: this.taskCompleteDate,
  3477. },
  3478. yAxis: [
  3479. {// 第一种方式
  3480. type: 'value',
  3481. min: 0,
  3482. max: Math.max(...this.taskCompletePercent),
  3483. splitNumber: 5,
  3484. interval: Math.max(...this.taskCompletePercent) / 5,
  3485. position: 'left',
  3486. axisLabel: {
  3487. show: true,
  3488. color: "#222222",
  3489. fontSize: '8',
  3490. formatter: function (v) {
  3491. return v.toFixed(0) //0表示小数为0位,1表示1位小数,2表示2位小数
  3492. }
  3493. },
  3494. splitLine: { //网格线
  3495. lineStyle: {
  3496. type: 'dashed'//设置网格线类型 dotted:虚线 solid:实线
  3497. },
  3498. },
  3499. axisTick: { show: false },
  3500. },
  3501. ],
  3502. series: [
  3503. {
  3504. type: 'line',
  3505. color: '#1677FF',
  3506. areaStyle: {
  3507. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  3508. { offset: 0, color: 'rgba(22,119,255,0.43)' },
  3509. { offset: 1, color: 'rgba(22,119,255,0)' }
  3510. ])
  3511. }, //填充区域样式
  3512. data: this.taskCompletePercent,
  3513. symbol: 'none', //去掉折线图中的节点
  3514. smooth: true, //true 为平滑曲线,false为直线
  3515. }
  3516. ],
  3517. }, true)
  3518. },
  3519. // 运营任务 - 互动客户数
  3520. getOpInteractChart() {
  3521. this.opInteractDate = []
  3522. this.opInteractClient = []
  3523. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/interact`, {
  3524. method: 'post',
  3525. body: JSON.stringify({
  3526. outletId: this.outletId,
  3527. departmentIds: this.deptId ? [this.deptId] : [],
  3528. startTime: this.pageStartTime,
  3529. endTime: this.pageEndTime,
  3530. }),
  3531. headers: {
  3532. 'Content-Type': 'application/json',
  3533. 'token': this.token,
  3534. 'tenancyId': this.tenancyId
  3535. }
  3536. }).then(res => {
  3537. return res.json()
  3538. }).then(result => {
  3539. let { data, code, msg } = result
  3540. if (code === 1) {
  3541. if (data && data.length) {
  3542. data.forEach(item => {
  3543. this.opInteractDate.push(item.time)
  3544. this.opInteractClient.push(item.interactClient)
  3545. })
  3546. this.$nextTick(() => {
  3547. this.opInteractChart()
  3548. })
  3549. }
  3550. } else if (code === 10001) {
  3551. this.loginOut()
  3552. } else {
  3553. vant.Toast.fail(msg)
  3554. }
  3555. })
  3556. },
  3557. opInteractChart() {
  3558. let opInteractChart = echarts.getInstanceByDom(document.getElementById('opInteractChart'))
  3559. if (opInteractChart == null) {
  3560. opInteractChart = echarts.init(document.getElementById('opInteractChart'))
  3561. }
  3562. window.addEventListener('resize', function () {
  3563. opInteractChart.resize()
  3564. })
  3565. opInteractChart.setOption({
  3566. legend: {
  3567. show: false,
  3568. },
  3569. tooltip: {
  3570. trigger: 'axis',
  3571. formatter: function (params) {
  3572. return params[0].name + '<br>'
  3573. + '互动客户数: ' + params[0].value
  3574. }
  3575. },
  3576. grid: {
  3577. top: '10%',
  3578. left: '10%',
  3579. right: '10%',
  3580. bottom: '10%'
  3581. },
  3582. xAxis: {
  3583. type: 'category',
  3584. axisLabel: {
  3585. show: true,
  3586. color: "#666666",
  3587. fontSize: '8',
  3588. },
  3589. data: this.opInteractDate,
  3590. },
  3591. yAxis: [
  3592. {// 第一种方式
  3593. type: 'value',
  3594. min: 0,
  3595. max: Math.max(...this.opInteractClient),
  3596. splitNumber: 5,
  3597. interval: Math.max(...this.opInteractClient) / 5,
  3598. position: 'left',
  3599. axisLabel: {
  3600. show: true,
  3601. color: "#222222",
  3602. fontSize: '8',
  3603. formatter: function (v) {
  3604. return v.toFixed(0) //0表示小数为0位,1表示1位小数,2表示2位小数
  3605. }
  3606. },
  3607. splitLine: { //网格线
  3608. lineStyle: {
  3609. type: 'dashed'//设置网格线类型 dotted:虚线 solid:实线
  3610. },
  3611. },
  3612. axisTick: { show: false },
  3613. },
  3614. ],
  3615. series: [
  3616. {
  3617. type: 'line',
  3618. color: '#FFA64E',
  3619. areaStyle: {
  3620. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
  3621. { offset: 0, color: 'rgba(255, 166, 78 ,0.43)' },
  3622. { offset: 1, color: 'rgba(255, 166, 78 ,0)' }
  3623. ])
  3624. }, //填充区域样式
  3625. data: this.opInteractClient,
  3626. symbol: 'none', //去掉折线图中的节点
  3627. smooth: true, //true 为平滑曲线,false为直线
  3628. }
  3629. ],
  3630. }, true)
  3631. },
  3632. // 运营任务 - 素材排行榜
  3633. getContentRank() {
  3634. this.contentRankData = []
  3635. fetch(this.httpUrl + `/scrm/v1/dw-dealer/m/contentRank`, {
  3636. method: 'post',
  3637. body: JSON.stringify({
  3638. outletId: this.outletId,
  3639. departmentIds: this.deptId ? [this.deptId] : [],
  3640. startTime: this.pageStartTime,
  3641. endTime: this.pageEndTime,
  3642. }),
  3643. headers: {
  3644. 'Content-Type': 'application/json',
  3645. 'token': this.token,
  3646. 'tenancyId': this.tenancyId
  3647. }
  3648. }).then(res => {
  3649. return res.json()
  3650. }).then(result => {
  3651. let { data, code, msg } = result
  3652. if (code === 1) {
  3653. this.contentRankData = data.reverse() || []
  3654. this.$nextTick(() => {
  3655. this.contentRankChart()
  3656. })
  3657. } else if (code === 10001) {
  3658. this.loginOut()
  3659. } else {
  3660. vant.Toast.fail(msg)
  3661. }
  3662. })
  3663. },
  3664. contentRankChart() {
  3665. let contentRankData = this.contentRankData.sort((a, b) => a.clientNum - b.clientNum)
  3666. let rankChart = echarts.getInstanceByDom(document.getElementById('contentRank'))
  3667. if (rankChart == null) {
  3668. rankChart = echarts.init(document.getElementById('contentRank'))
  3669. }
  3670. rankChart.resize({ height: this.contentRankData.length * 50 + 20 })
  3671. window.addEventListener('resize', function () {
  3672. rankChart.resize()
  3673. })
  3674. rankChart.setOption({
  3675. tooltip: {
  3676. trigger: 'item',
  3677. confine: true,
  3678. extraCssText: 'max-width:200px; white-space:pre-wrap',
  3679. formatter: '{b}: {c}'
  3680. },
  3681. legend: {
  3682. left: 'center',
  3683. icon: 'circle', //小圆点
  3684. itemWidth: 10,
  3685. itemHeight: 10,
  3686. itemGap: 10, //间隔
  3687. bottom: '10%',
  3688. },
  3689. grid: {
  3690. bottom: "0",
  3691. top: "0",
  3692. left: "0",
  3693. containLabel: true,
  3694. },
  3695. xAxis: {
  3696. type: 'value',
  3697. axisLabel: {
  3698. show: true,
  3699. color: '#666666',
  3700. fontSize: '8',
  3701. },
  3702. splitLine: {
  3703. show: true,
  3704. lineStyle: {
  3705. type: 'dashed' // 设置为虚线
  3706. }
  3707. },
  3708. },
  3709. yAxis: {
  3710. type: 'category',
  3711. axisLabel: {
  3712. formatter: function (value) {
  3713. return value.length > 4 ? value.substring(0, 4) + '...' : value
  3714. },
  3715. showTooltip: true,
  3716. },
  3717. data: this.contentRankData.map(item => {
  3718. return item.title
  3719. }) || [],
  3720. },
  3721. series: [
  3722. {
  3723. type: 'bar',
  3724. barWidth: 24,
  3725. barGap: 12,
  3726. itemStyle: {
  3727. color: function (p) {
  3728. // 亮度随索引递增实现渐变
  3729. const lightness = 87 - p.dataIndex * 8;
  3730. return `hsl(215, 100%, ${Math.min(100, lightness)}%)`;
  3731. }
  3732. },
  3733. data: this.contentRankData.map(item => {
  3734. return item.readNum
  3735. }) || []
  3736. }
  3737. ]
  3738. })
  3739. },
  3740. // 打开右上角弹窗
  3741. handleShowPopup() {
  3742. this.showPopup = true
  3743. },
  3744. // 关闭右上角弹窗
  3745. handleClosePopup() {
  3746. this.showPopup = false
  3747. this.showMer = false
  3748. },
  3749. // 切换商户
  3750. handleSelectMer(item) {
  3751. localStorage.setItem('tenancyIdValue', item.id)
  3752. localStorage.setItem('tenancyNameValue', item.name || '')
  3753. this.tenancyId = item.id
  3754. this.jxsName = item.name || ''
  3755. this.showPopup = false
  3756. this.showMer = false
  3757. this.initialization()
  3758. },
  3759. // 退出登录
  3760. handleLoginOut() {
  3761. localStorage.removeItem('tokenValue')
  3762. var currentQueryParams = window.location.search
  3763. window.location.replace('jxsLogin.html' + currentQueryParams)
  3764. },
  3765. // token过期,退出登录
  3766. loginOut() {
  3767. vant.Toast({
  3768. message: '登录信息过期,请重新登录',
  3769. })
  3770. this.handleLoginOut()
  3771. },
  3772. formatTime(seconds) {
  3773. // 处理无效输入(空值/非数字)
  3774. if (seconds == null || seconds === '' || typeof seconds !== 'number') {
  3775. return '--';
  3776. }
  3777. // 确定时间符号和绝对值
  3778. const isNegative = seconds < 0;
  3779. const absSeconds = Math.abs(seconds);
  3780. // 内部格式化函数(处理绝对值)
  3781. const format = (val, unit) => {
  3782. const num = Math.round(val);
  3783. return `${num}${unit}${num > 1 ? '' : ''}`;
  3784. };
  3785. // 根据绝对值大小转换单位
  3786. let formatted;
  3787. if (absSeconds >= 3600) {
  3788. formatted = format(absSeconds / 3600, '小时');
  3789. } else if (absSeconds >= 60) {
  3790. formatted = format(absSeconds / 60, '分钟');
  3791. } else {
  3792. formatted = format(absSeconds, '秒');
  3793. }
  3794. // 添加负号(当原始值为负时)
  3795. return isNegative ? `-${formatted}` : formatted;
  3796. },
  3797. formatNumber(num) {
  3798. const number = Number(num);
  3799. if (isNaN(number) || !isFinite(number)) {
  3800. return num;
  3801. }
  3802. // 整数直接返回
  3803. if (Number.isInteger(number)) {
  3804. return number.toString();
  3805. }
  3806. // 非整数处理:先保留两位小数,再移除末尾的零
  3807. let str = number.toFixed(2);
  3808. // 正则表达式移除末尾的零(保留有效小数位)
  3809. return str.replace(/(\.[1-9]?0+)$|(\.[1-9])0+$/g, '$1$2');
  3810. },
  3811. // 日期格式处理
  3812. getDateTime(day) {
  3813. let today = new Date()
  3814. let targetday_milliseconds = today.getTime() + 1000 * 60 * 60 * 24 * day
  3815. today.setTime(targetday_milliseconds)
  3816. let tYear = today.getFullYear()
  3817. let tMonth = today.getMonth() + 1
  3818. let tDate = today.getDate()
  3819. if (tMonth < 10) {
  3820. tMonth = '0' + tMonth
  3821. }
  3822. if (tDate < 10) {
  3823. tDate = '0' + tDate
  3824. }
  3825. return tYear + '-' + tMonth + '-' + tDate
  3826. },
  3827. // 截取url中的数据
  3828. getQueryParam(paramName) {
  3829. // 获取当前URL的查询字符串部分
  3830. const queryString = window.location.search;
  3831. // 创建一个URLSearchParams对象
  3832. const urlParams = new URLSearchParams(queryString);
  3833. // 返回指定参数的值,如果不存在则返回null
  3834. return urlParams.get(paramName);
  3835. },
  3836. timeFormat(time, format = 'yyyy-MM-dd hh:mm:ss') {
  3837. if (time === undefined || time === '' || time === null) {
  3838. return '--'
  3839. } else {
  3840. const date = new Date(time)
  3841. const o = {
  3842. 'M+': date.getMonth() + 1,
  3843. 'd+': date.getDate(),
  3844. 'h+': date.getHours(),
  3845. 'm+': date.getMinutes(),
  3846. 's+': date.getSeconds(),
  3847. 'q+': Math.floor((date.getMonth() + 3) / 3),
  3848. 'S': date.getMilliseconds()
  3849. }
  3850. if (/(y+)/.test(format)) {
  3851. format = format.replace(RegExp.$1, (date.getFullYear() + '').substr(4 - RegExp.$1.length))
  3852. }
  3853. for (let k in o) {
  3854. if (new RegExp('(' + k + ')').test(format)) {
  3855. format = format.replace(RegExp.$1, (RegExp.$1.length === 1) ? (o[k]) : (('00' + o[k]).substr(('' + o[k]).length)))
  3856. }
  3857. }
  3858. return format
  3859. }
  3860. },
  3861. }
  3862. })
  3863. </script>
  3864. </html>