jxs.html 127 KB

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