chat.vue 57 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728
  1. <template>
  2. <div class="broadcast-details" :style="'height:'+windowH+'px'">
  3. <view class="hd-wrapper" :class="active === true ? 'on' : ''" :style="viewColor">
  4. <view class="store-wrapper" v-if="storeInfo">
  5. <view class="left">
  6. <image :src="storeInfo.mer_avatar" mode=""></image>
  7. <view class="txt">{{storeInfo.mer_name}}</view>
  8. </view>
  9. <view class="acea-row store-opeation">
  10. <navigator v-if="hide_mer_status != 1 && storeInfo.mer_id" :url="'/pages/store/index?id='+storeInfo.mer_id" class="link" open-type="redirect">进店</navigator>
  11. <text v-if="storeInfo.service_phone" class="iconfont icon-dadianhua01" @click="goCustomer"></text>
  12. </view>
  13. </view>
  14. <scroll-view scroll-y="true" style="height: 100%; overflow: hidden;" :scroll-top="scrollTop" scroll-with-animation="true"
  15. @scrolltoupper="bindScroll">
  16. <div class="chat" ref="chat">
  17. <Loading :loaded="status" :loading="loading"></Loading>
  18. <!-- 客服聊天列表 -->
  19. <block v-for="(items,index) in history" v-if="userId != 0" :key="index">
  20. <div class="create_time">{{items.time}}</div>
  21. <block v-for="(item,j) in items.children" :key="item.service_log_id">
  22. <!-- 左边 -->
  23. <div class="item acea-row row-top" v-if="item.send_type == 0">
  24. <div class="pictrue" @click="userDetail(item.user.uid)">
  25. <image :src="item.user.avatar ? item.user.avatar : '/static/images/f.png'" mode=""></image>
  26. </div>
  27. <div class="text">
  28. <div class="acea-row">
  29. <!--退款订单链接-->
  30. <navigator v-if="item.msn_type === 6 && item.refundOrder && item.refundOrder.refund_order_id" open-type="navigate" :url="'/pages/order_details/index?order_id='+item.refundOrder.order_id">
  31. <div class="broadcast-details_num">
  32. <span>退款单号:{{ item.refundOrder.refund_order_sn }}</span>
  33. </div>
  34. <div class="conter acea-row row-middle">
  35. <div class="broadcast-details_order noPad" v-for="(val, inx) in item.refundOrder.refundProduct" :key="item.service_log_id">
  36. <div class="broadcast-details_box noPad" v-if="inx == 0">
  37. <div class="broadcast_details_img">
  38. <image :src="val.product.cart_info.product.image" />
  39. <div class="broadcast_details_model">
  40. {{item.refundOrder.refund_num}}件商品
  41. </div>
  42. </div>
  43. <div class="broadcast_details_picBox noPad">
  44. <div class="broadcast_details_tit" v-text="val.product.cart_info.product.store_name"></div>
  45. <div class="broadcast_details_pic">
  46. ¥{{ item.refundOrder.refund_price }}
  47. </div>
  48. </div>
  49. </div>
  50. </div>
  51. </div>
  52. </navigator>
  53. <!--订单链接-->
  54. <div v-if="item.msn_type === 5 && item.orderInfo && item.orderInfo.order_id">
  55. <div class="broadcast-details_num acea-row row-middle">
  56. <span>订单号:{{ item.orderInfo.order_sn }}</span>
  57. <!-- #ifdef H5 -->
  58. <button class="copy copy-data" :data-clipboard-text="item.orderInfo.order_sn">复制</button>
  59. <!-- #endif -->
  60. <!-- #ifndef H5 -->
  61. <button class="copy" @tap.stop="copyText(item.orderInfo.order_sn)">复制</button>
  62. <!-- #endif -->
  63. </div>
  64. <navigator :url="'/pages/admin/orderDetail/index?id='+item.orderInfo.order_id+'&mer_id='+item.orderInfo.mer_id" open-type="open-type" class="conter acea-row row-middle">
  65. <div class="broadcast-details_order noPad" v-for="(val, inx) in item.orderInfo.orderProduct" :key="val.id">
  66. <div class="broadcast-details_box noPad" v-if="inx == 0">
  67. <div class="broadcast_details_img">
  68. <image :src="val.cart_info.product.image" />
  69. <div class="broadcast_details_model">
  70. {{item.orderInfo.total_num}}件商品
  71. </div>
  72. </div>
  73. <div class="broadcast_details_picBox noPad">
  74. <div class="broadcast_details_tit" v-text="val.cart_info.product.store_name"></div>
  75. <div class="broadcast_details_pic">
  76. ¥{{ item.orderInfo.pay_price }}
  77. </div>
  78. </div>
  79. </div>
  80. </div>
  81. </navigator>
  82. </div>
  83. <!--商品链接-->
  84. <div class="conter acea-row row-middle" v-if="item.msn_type === 4 && item.product">
  85. <div class=" noPad">
  86. <navigator class="acea-row row-column-around noPad" v-if="item.product.product_id" :url="`/pages/goods_details/index?id=${item.product.product_id}`" open-type="navigate">
  87. <div class="broadcast_details_img_no">
  88. <image :src="item.product.image" />
  89. </div>
  90. <div class="broadcast_details_picBox_no noPad">
  91. <div class="broadcast_details_pic">
  92. ¥{{ item.product.price }}
  93. </div>
  94. <div class="broadcast_details_tit_no line1" v-text="item.product.store_name"></div>
  95. </div>
  96. </navigator>
  97. </div>
  98. </div>
  99. <!--预售商品链接-->
  100. <div class="conter acea-row row-middle" v-if="item.msn_type === 7 && item.presell && item.presell.product">
  101. <div class=" noPad">
  102. <navigator class="acea-row row-column-around noPad" v-if="item.presell.product_presell_id" :url="`/pages/activity/presell_details/index?id=${item.presell.product_presell_id}`" open-type="navigate">
  103. <div class="broadcast_details_img_no">
  104. <image :src="item.presell.product.image" />
  105. </div>
  106. <div class="broadcast_details_picBox_no noPad">
  107. <div class="broadcast_details_pic">
  108. ¥{{ item.presell.price }}
  109. </div>
  110. <div class="broadcast_details_tit_no line1" v-text="item.presell.store_name"></div>
  111. </div>
  112. </navigator>
  113. </div>
  114. </div>
  115. <!--拼团商品链接-->
  116. <div class="conter acea-row row-middle" v-if="item.msn_type === 8 && item.productGroup && item.productGroup.product">
  117. <div class=" noPad">
  118. <navigator class="acea-row row-column-around noPad" v-if="item.productGroup.product_group_id" :url="`/pages/activity/combination_details/index?id=${item.productGroup.product_group_id}`" open-type="navigate">
  119. <div class="broadcast_details_img_no">
  120. <image :src="item.productGroup.product.image" />
  121. </div>
  122. <div class="broadcast_details_picBox_no noPad">
  123. <div class="broadcast_details_pic">
  124. ¥{{ item.productGroup.product.price }}
  125. </div>
  126. <div class="broadcast_details_tit_no line1" v-text="item.productGroup.product.store_name"></div>
  127. </div>
  128. </navigator>
  129. </div>
  130. </div>
  131. <div class="conter acea-row row-middle" v-if="item.msn_type === 3">
  132. <image :src="item.msn" @click="clickImg(item.msn)" mode="heightFix" />
  133. </div>
  134. <div class="conter acea-row row-middle" v-if="item.msn_type === 2">
  135. <i class="em" :class="item.msn"></i>
  136. </div>
  137. <div class="conter acea-row row-middle" v-if="item.msn_type === 1">
  138. {{ item.msn }}
  139. </div>
  140. </div>
  141. </div>
  142. </div>
  143. <!-- 右边 -->
  144. <div class="item acea-row row-top row-right" v-else>
  145. <div class="text textR">
  146. <!-- <div class="name">{{ item.user.nickname }}</div> -->
  147. <div class="acea-row ">
  148. <!--退款订单链接-->
  149. <navigator v-if="item.msn_type === 6 && item.refundOrder.refund_order_id" open-type="navigate">
  150. <div class="broadcast-details_num acea-row row-middle">
  151. <text>订单号:{{ item.refundOrder.refund_order_sn }}</text>
  152. <!-- #ifdef H5 -->
  153. <button class="copy copy-data" :data-clipboard-text="item.refundOrder.refund_order_sn">复制</button>
  154. <!-- #endif -->
  155. <!-- #ifndef H5 -->
  156. <button class="copy" @tap.stop="copyText(item.refundOrder.refund_order_sn)">复制</button>
  157. <!-- #endif -->
  158. </div>
  159. <div class="conter acea-row row-middle">
  160. <div class="broadcast-details_order noPad" v-for="(val, inx) in item.refundOrder.refundProduct" :key="val.id">
  161. <div class="broadcast-details_box noPad" v-if="inx == 0">
  162. <div class="broadcast_details_img">
  163. <image :src="val.product.cart_info.product.image" />
  164. <div class="broadcast_details_model">
  165. {{item.refundOrder.refund_num}}件商品
  166. </div>
  167. </div>
  168. <div class="broadcast_details_picBox noPad">
  169. <div class="broadcast_details_tit" v-text="val.product.cart_info.product.store_name"></div>
  170. <div class="broadcast_details_pic">
  171. ¥{{ item.refundOrder.refund_price }}
  172. </div>
  173. </div>
  174. </div>
  175. </div>
  176. </div>
  177. </navigator>
  178. <!--订单链接-->
  179. <div v-if="item.msn_type === 5 && item.orderInfo.order_id">
  180. <div class="broadcast-details_num acea-row row-middle">
  181. <text>订单号:{{ item.orderInfo.order_sn }}</text>
  182. <!-- #ifdef H5 -->
  183. <button class="copy copy-data" :data-clipboard-text="item.orderInfo.order_sn">复制</button>
  184. <!-- #endif -->
  185. <!-- #ifndef H5 -->
  186. <button class="copy" @tap.stop="copyText(item.orderInfo.order_sn)">复制</button>
  187. <!-- #endif -->
  188. </div>
  189. <navigator :url="'/pages/admin/orderDetail/index?id='+item.orderInfo.order_id+'&mer_id='+item.orderInfo.mer_id" open-type="navigate" class="conter acea-row row-middle">
  190. <div class="broadcast-details_order noPad" v-for="(val, inx) in item.orderInfo.orderProduct" :key="val.id">
  191. <div class="broadcast-details_box noPad" v-if="inx == 0">
  192. <div class="broadcast_details_img">
  193. <image :src="val.cart_info.product.image" />
  194. <div class="broadcast_details_model">
  195. {{item.orderInfo.total_num}}件商品
  196. </div>
  197. </div>
  198. <div class="broadcast_details_picBox noPad">
  199. <div class="broadcast_details_tit" v-text="val.cart_info.product.store_name"></div>
  200. <div class="broadcast_details_pic">
  201. ¥{{ item.orderInfo.pay_price }}
  202. </div>
  203. </div>
  204. </div>
  205. </div>
  206. </navigator>
  207. </div>
  208. <!--商品链接-->
  209. <div class="conter acea-row row-middle" v-if="item.msn_type === 4 && item.product">
  210. <div class=" acea-row row-column-around noPad">
  211. <navigator class="acea-row row-column-around noPad" v-if="item.product.product_id" :url="`/pages/goods_details/index?id=${item.product.product_id}`">
  212. <div class="broadcast_details_img_no">
  213. <image :src="item.product.image" />
  214. </div>
  215. <div class="broadcast_details_picBox_no noPad">
  216. <div class="broadcast_details_pic">
  217. ¥{{ item.product.price }}
  218. </div>
  219. <div class="broadcast_details_tit_no line1" v-text="item.product.store_name"></div>
  220. </div>
  221. </navigator>
  222. </div>
  223. </div>
  224. <!--预售商品链接-->
  225. <div class="conter acea-row row-middle" v-if="item.msn_type === 7 && item.presell && item.presell.product">
  226. <div class=" acea-row row-column-around noPad">
  227. <navigator class="acea-row row-column-around noPad" v-if="item.presell.product_presell_id" :url="`/pages/activity/presell_details/index?id=${item.presell.product_presell_id}`" open-type="navigate">
  228. <div class="broadcast_details_img_no">
  229. <image :src="item.presell.product.image" />
  230. </div>
  231. <div class="broadcast_details_picBox_no noPad">
  232. <div class="broadcast_details_pic">
  233. ¥{{ item.presell.price }}
  234. </div>
  235. <div class="broadcast_details_tit_no line1" v-text="item.presell.store_name"></div>
  236. </div>
  237. </navigator>
  238. </div>
  239. </div>
  240. <!--拼团商品链接-->
  241. <div class="conter acea-row row-middle" v-if="item.msn_type === 8 && item.productGroup && item.productGroup.product">
  242. <div class=" acea-row row-column-around noPad">
  243. <navigator class="acea-row row-column-around noPad" v-if="item.productGroup.product_group_id" :url="`/pages/activity/combination_details/index?id=${item.productGroup.product_group_id}`" open-type="navigate">
  244. <div class="broadcast_details_img_no">
  245. <image :src="item.productGroup.product.image" />
  246. </div>
  247. <div class="broadcast_details_picBox_no noPad">
  248. <div class="broadcast_details_pic">
  249. ¥{{ item.productGroup.product.price }}
  250. </div>
  251. <div class="broadcast_details_tit_no line1" v-text="item.productGroup.product.store_name"></div>
  252. </div>
  253. </navigator>
  254. </div>
  255. </div>
  256. <div class="conter acea-row row-middle" v-if="item.msn_type === 3">
  257. <image :src="item.msn" @click="clickImg(item.msn)" mode="heightFix" />
  258. </div>
  259. <div class="conter acea-row row-middle" v-if="item.msn_type === 2">
  260. <i class="em" :class="item.msn"></i>
  261. </div>
  262. <div class="conter acea-row row-middle" v-if="item.msn_type === 1">
  263. {{ item.msn }}
  264. </div>
  265. </div>
  266. </div>
  267. <div class="pictrue">
  268. <image :src="item.service.avatar ? item.service.avatar : '/static/images/f.png'" />
  269. </div>
  270. </div>
  271. </block>
  272. </block>
  273. <!-- 客户聊天列表 -->
  274. <block v-for="(items,index) in history" v-if="userId == 0" :key="items.time">
  275. <div class="create_time">{{items.time}}</div>
  276. <block v-for="(item,j) in items.children" :key="item.service_log_id">
  277. <!-- 左边 -->
  278. <div class="item acea-row row-top" v-if="item.send_type == 1">
  279. <div class="pictrue">
  280. <image :src="item.service.avatar ? item.service.avatar : '/static/images/f.png'" mode=""></image>
  281. </div>
  282. <div class="text">
  283. <!-- <div class="name">{{ item.service.nickname }}</div> -->
  284. <div class="acea-row">
  285. <!--退款订单链接-->
  286. <navigator v-if="item.msn_type === 6 && item.refundOrder.refund_order_id" open-type="navigate" :url="'/pages/order_details/index?order_id='+item.refundOrder.order_id">
  287. <div class="broadcast-details_num">
  288. <text>退款单号:{{ item.refundOrder.refund_order_sn }}</text>
  289. </div>
  290. <div class="conter acea-row row-middle">
  291. <!-- :key="item.service_log_id" -->
  292. <div class="broadcast-details_order noPad" v-for="(val, inx) in item.refundOrder.refundProduct">
  293. <div class="broadcast-details_box noPad" v-if="inx == 0">
  294. <div class="broadcast_details_img">
  295. <image :src="val.product.cart_info.product.image" />
  296. <div class="broadcast_details_model">
  297. {{item.refundOrder.refund_num}}件商品
  298. </div>
  299. </div>
  300. <div class="broadcast_details_picBox noPad">
  301. <div class="broadcast_details_tit" v-text="val.product.cart_info.product.store_name"></div>
  302. <div class="broadcast_details_pic">
  303. ¥{{ val.product.cart_info.productAttr.price }}
  304. </div>
  305. </div>
  306. </div>
  307. </div>
  308. </div>
  309. </navigator>
  310. <!--订单链接-->
  311. <div v-if="item.msn_type === 5 && item.orderInfo.order_id">
  312. <div class="broadcast-details_num acea-row row-middle">
  313. <text>订单号:{{ item.orderInfo.order_sn }}</text>
  314. <!-- #ifdef H5 -->
  315. <button class="copy copy-data" :data-clipboard-text="item.orderInfo.order_sn">复制</button>
  316. <!-- #endif -->
  317. <!-- #ifndef H5 -->
  318. <button class="copy" @tap.stop="copyText(item.orderInfo.order_sn)">复制</button>
  319. <!-- #endif -->
  320. </div>
  321. <navigator :url="'/pages/order_details/index?order_id='+item.orderInfo.order_id" open-type="navigate" class="conter acea-row row-middle">
  322. <!-- :key="item.service_log_id" -->
  323. <div class="broadcast-details_order noPad" v-for="(val, inx) in item.orderInfo.orderProduct">
  324. <div class="broadcast-details_box noPad" v-if="inx == 0">
  325. <div class="broadcast_details_img">
  326. <image :src="val.cart_info.product.image" />
  327. <div class="broadcast_details_model">
  328. {{item.orderInfo.total_num}}件商品
  329. </div>
  330. </div>
  331. <div class="broadcast_details_picBox noPad">
  332. <div class="broadcast_details_tit" v-text="val.cart_info.product.store_name"></div>
  333. <div class="broadcast_details_pic">
  334. ¥{{ item.orderInfo.pay_price }}
  335. </div>
  336. </div>
  337. </div>
  338. </div>
  339. </navigator>
  340. </div>
  341. <!--商品链接-->
  342. <div class="conter acea-row row-middle" v-if="item.msn_type === 4 && item.product">
  343. <div class=" noPad">
  344. <navigator class="acea-row row-column-around noPad" v-if="item.product.product_id" :url="`/pages/goods_details/index?id=${item.product.product_id}`" open-type="navigate">
  345. <div class="broadcast_details_img_no">
  346. <image :src="item.product.image" />
  347. </div>
  348. <div class="broadcast_details_picBox_no noPad">
  349. <div class="broadcast_details_pic">
  350. ¥{{ item.product.price }}
  351. </div>
  352. <div class="broadcast_details_tit_no line1" v-text="item.product.store_name"></div>
  353. </div>
  354. </navigator>
  355. </div>
  356. </div>
  357. <!--预售商品链接-->
  358. <div class="conter acea-row row-middle" v-if="item.msn_type === 7 && item.presell && item.presell.product">
  359. <div class=" noPad">
  360. <navigator class="acea-row row-column-around noPad" v-if="item.presell.product_presell_id" :url="`/pages/activity/presell_details/index?id=${item.presell.product_presell_id}`" open-type="navigate">
  361. <div class="broadcast_details_img_no">
  362. <image :src="item.presell.product.image" />
  363. </div>
  364. <div class="broadcast_details_picBox_no noPad">
  365. <div class="broadcast_details_pic">
  366. ¥{{ item.presell.price }}
  367. </div>
  368. <div class="broadcast_details_tit_no line1" v-text="item.presell.store_name"></div>
  369. </div>
  370. </navigator>
  371. </div>
  372. </div>
  373. <!--拼团商品链接-->
  374. <div class="conter acea-row row-middle" v-if="item.msn_type === 8 && item.productGroup && item.productGroup.product">
  375. <div class="noPad">
  376. <navigator class="acea-row row-column-around noPad" v-if="item.productGroup.product_group_id" :url="`/pages/activity/combination_details/index?id=${item.productGroup.product_group_id}`" open-type="navigate">
  377. <div class="broadcast_details_img_no">
  378. <image :src="item.productGroup.product.image" />
  379. </div>
  380. <div class="broadcast_details_picBox_no noPad">
  381. <div class="broadcast_details_pic">
  382. ¥{{ item.productGroup.product.price }}
  383. </div>
  384. <div class="broadcast_details_tit_no line1" v-text="item.productGroup.product.store_name"></div>
  385. </div>
  386. </navigator>
  387. </div>
  388. </div>
  389. <div class="conter acea-row row-middle" v-if="item.msn_type === 3">
  390. <image :src="item.msn" @click="clickImg(item.msn)" mode="heightFix" />
  391. </div>
  392. <div class="conter acea-row row-middle" v-if="item.msn_type === 2">
  393. <i class="em" :class="item.msn"></i>
  394. </div>
  395. <div class="conter acea-row row-middle" v-if="item.msn_type === 1">
  396. {{ item.msn }}
  397. </div>
  398. </div>
  399. </div>
  400. </div>
  401. <!-- 右边 -->
  402. <div class="item acea-row row-top row-right" v-else>
  403. <div class="text textR">
  404. <!-- <div class="name">{{ item.user.nickname }}</div> -->
  405. <div class="acea-row ">
  406. <!--退款订单链接-->
  407. <navigator v-if="item.msn_type === 6 && item.refundOrder.refund_order_id" open-type="navigate" :url="'/pages/order_details/index?order_id='+item.refundOrder.order_id">
  408. <div class="broadcast-details_num">
  409. <text>退款单号:{{ item.refundOrder.refund_order_sn }}</text>
  410. </div>
  411. <div class="conter acea-row row-middle">
  412. <!-- :key="item.service_log_id" -->
  413. <div class="broadcast-details_order noPad" v-for="(val, inx) in item.refundOrder.refundProduct">
  414. <div class="broadcast-details_box noPad" v-if="inx == 0">
  415. <div class="broadcast_details_img">
  416. <image :src="val.product.cart_info.product.image" />
  417. <div class="broadcast_details_model"></div>
  418. </div>
  419. <div class="broadcast_details_picBox noPad">
  420. <div class="broadcast_details_tit" v-text="val.product.cart_info.product.store_name"></div>
  421. <div class="broadcast_details_pic">
  422. 共{{item.refundOrder.refund_num}}件商品,
  423. 合计 ¥{{ item.refundOrder.refund_price }}
  424. </div>
  425. </div>
  426. </div>
  427. </div>
  428. </div>
  429. </navigator>
  430. <!--订单链接-->
  431. <div v-if="item.msn_type === 5 && item.orderInfo.order_id">
  432. <div class="broadcast-details_num acea-row row-middle">
  433. <text>订单号:{{ item.orderInfo.order_sn }}</text>
  434. <!-- #ifdef H5 -->
  435. <button class="copy copy-data" :data-clipboard-text="item.orderInfo.order_sn">复制</button>
  436. <!-- #endif -->
  437. <!-- #ifndef H5 -->
  438. <button class="copy" @tap.stop="copyText(item.orderInfo.order_sn)">复制</button>
  439. <!-- #endif -->
  440. </div>
  441. <navigator :url="'/pages/order_details/index?order_id='+item.orderInfo.order_id" open-type="navigate" class="conter acea-row row-middle">
  442. <div class="broadcast-details_order noPad" v-for="(val, inx) in item.orderInfo.orderProduct">
  443. <div class="broadcast-details_box noPad" v-if="inx == 0">
  444. <div class="broadcast_details_img">
  445. <image :src="val.cart_info.product.image" />
  446. <div class="broadcast_details_model">
  447. {{item.orderInfo.total_num}}件商品
  448. </div>
  449. </div>
  450. <div class="broadcast_details_picBox noPad">
  451. <div class="broadcast_details_tit" v-text="val.cart_info.product.store_name"></div>
  452. <div class="broadcast_details_pic">
  453. ¥{{ item.orderInfo.pay_price }}
  454. </div>
  455. </div>
  456. </div>
  457. </div>
  458. </navigator>
  459. </div>
  460. <!--商品链接-->
  461. <div class="conter acea-row row-middle" v-if="item.msn_type === 4 && item.product">
  462. <div class="acea-row row-column-around noPad">
  463. <navigator class="acea-row row-column-around noPad" v-if="item.product.product_id" :url="`/pages/goods_details/index?id=${item.product.product_id}`" open-type="navigate">
  464. <div class="broadcast_details_img_no">
  465. <image :src="item.product.image" />
  466. </div>
  467. <div class="broadcast_details_picBox_no noPad">
  468. <div class="broadcast_details_pic">
  469. ¥{{ item.product.price }}
  470. </div>
  471. <div class="broadcast_details_tit_no line1" v-text="item.product.store_name"></div>
  472. </div>
  473. </navigator>
  474. </div>
  475. </div>
  476. <!--预售商品链接-->
  477. <div class="conter acea-row row-middle" v-if="item.msn_type === 7 && item.presell && item.presell.product">
  478. <div class="acea-row row-column-around noPad">
  479. <navigator class="acea-row row-column-around noPad" v-if="item.presell.product_presell_id" :url="`/pages/activity/presell_details/index?id=${item.presell.product_presell_id}`" open-type="navigate">
  480. <div class="broadcast_details_img_no">
  481. <image :src="item.presell.product.image" />
  482. </div>
  483. <div class="broadcast_details_picBox_no noPad">
  484. <div class="broadcast_details_pic">
  485. ¥{{ item.presell.price }}
  486. </div>
  487. <div class="broadcast_details_tit_no line1" v-text="item.presell.store_name"></div>
  488. </div>
  489. </navigator>
  490. </div>
  491. </div>
  492. <!--拼团商品链接-->
  493. <div class="conter acea-row row-middle" v-if="item.msn_type === 8 && item.productGroup && item.productGroup.product">
  494. <div class=" acea-row row-column-around noPad">
  495. <navigator class="acea-row row-column-around noPad" v-if="item.productGroup.product_group_id" :url="`/pages/activity/combination_details/index?id=${item.productGroup.product_group_id}`" open-type="navigate">
  496. <div class="broadcast_details_img_no">
  497. <image :src="item.productGroup.product.image" />
  498. </div>
  499. <div class="broadcast_details_picBox_no noPad">
  500. <div class="broadcast_details_pic">
  501. ¥{{ item.productGroup.product.price }}
  502. </div>
  503. <div class="broadcast_details_tit_no line1" v-text="item.productGroup.product.store_name"></div>
  504. </div>
  505. </navigator>
  506. </div>
  507. </div>
  508. <div class="conter acea-row row-middle" v-if="item.msn_type === 3">
  509. <image :src="item.msn" @click="clickImg(item.msn)" mode="heightFix" />
  510. </div>
  511. <div class="conter acea-row row-middle" v-if="item.msn_type === 2">
  512. <i class="em" :class="item.msn"></i>
  513. </div>
  514. <div class="conter acea-row row-middle" v-if="item.msn_type === 1">
  515. {{ item.msn }}
  516. </div>
  517. </div>
  518. </div>
  519. <div class="pictrue">
  520. <image :src="item.user.avatar ? item.user.avatar : '/static/images/f.png'"/>
  521. </div>
  522. </div>
  523. </block>
  524. </block>
  525. <view class="footer_box" v-if="productId || orderId || refund_order_id"></view>
  526. <div class="broadcast-details_order footer_count">
  527. <!-- 商品信息 -->
  528. <div class="broadcast-details_box" v-if="productId && productInfo.product_id">
  529. <text class="iconfont icon-guanbi" @click.stop="productId = ''"></text>
  530. <div class="broadcast_details_img">
  531. <image v-if="!presellId" :src="productInfo.image" />
  532. <image v-else :src="productInfo.product.image" />
  533. </div>
  534. <div class="broadcast_details_picBox">
  535. <div class="broadcast_details_tit" v-text="productInfo.store_name"></div>
  536. <div class="acea-row row-between product_price">
  537. <div class="broadcast_details_pic p-color">
  538. ¥{{ productInfo.price}}
  539. </div>
  540. <div class="broadcast_details_btn product_btn" @click="sendProduct">发送商品</div>
  541. </div>
  542. </div>
  543. </div>
  544. <!-- 订单信息 -->
  545. <div class="broadcast_box" v-if="orderId && orderInfo.order_id">
  546. <text class="iconfont icon-guanbi" @click.stop="orderId = ''"></text>
  547. <div class="broadcast-details_num broadcast_num acea-row row-between-wrapper">
  548. <text>订单号:{{ orderInfo.order_sn }}</text>
  549. <!-- <span class="line1">{{ orderInfo.pay_time }}</span> -->
  550. </div>
  551. <div class="broadcast-details_box">
  552. <div class="broadcast_details_img">
  553. <image :src="cartInfo.cart_info.product.image" />
  554. </div>
  555. <div class="broadcast_details_picBox">
  556. <div class="broadcast_details_tit">
  557. {{ cartInfo.cart_info.product.store_name }}
  558. </div>
  559. <div>
  560. <div class="broadcast_details_pic">
  561. 共{{ orderInfo.total_num }}件商品,合计 <text class="p-color">¥{{ orderInfo.pay_price }}</text>
  562. </div>
  563. <div class="broadcast_details_btn" @click="sendOrder">
  564. 发送订单
  565. </div>
  566. </div>
  567. </div>
  568. </div>
  569. </div>
  570. <!-- 退款订单 -->
  571. <div class="broadcast_box" v-if="refund_order_id && refundDetail.refund_order_id">
  572. <text class="iconfont icon-guanbi" @click.stop="refund_order_id = ''"></text>
  573. <div class="broadcast-details_num broadcast_num">
  574. <text>退款单号:{{ refundDetail.refund_order_sn }}</text>
  575. </div>
  576. <div class="broadcast-details_box">
  577. <div class="broadcast_details_img">
  578. <image :src="refundDetail.refundProduct[0].product.cart_info.product.image" />
  579. </div>
  580. <div class="broadcast_details_picBox">
  581. <div class="broadcast_details_tit">
  582. {{ refundDetail.refundProduct[0].product.cart_info.product.store_name }}
  583. </div>
  584. <div>
  585. <div class="broadcast_details_pic">
  586. 共{{ refundDetail.refund_num }}件商品,
  587. 合计 <text class="p-color">¥{{ refundDetail.refund_price}}</text>
  588. </div>
  589. <div class="broadcast_details_btn refund_btn" @click="sendRefundOrder">
  590. 发送退款单
  591. </div>
  592. </div>
  593. </div>
  594. </div>
  595. </div>
  596. </div>
  597. </div>
  598. <div :style=" active === true ? 'height:' + footerConH + 'rem;' : 'height:' + footerH + 'rem;'"></div>
  599. </scroll-view>
  600. </view>
  601. <div class="footerCon" :class="active === true ? 'on' : ''" :style="'transform: translate3d(0,' + percent + '%,0);'"
  602. ref="footerCon">
  603. <form>
  604. <div class="footer acea-row row-between row-bottom" ref="footer">
  605. <text @click="uploadImg" class="iconfont icon-tupian2"></text>
  606. <text @click="emoticon" class="iconfont icon-biaoqing2"></text>
  607. <div class="voice acea-row row-center-wrapper" v-if="voice" @touchstart.prevent="start" @touchmove.prevent="move"
  608. @touchend.prevent="end">
  609. {{ speak }}
  610. </div>
  611. <view class="input_count">
  612. <input type="text" placeholder-class='placeholder' placeholder="输入内容" class="input" ref="input" v-show="!voice" @input="bindInput" @keyup="keyup"
  613. @focus="focus" cursor-spacing="20" v-model="textCon">
  614. <div class="send iconfont icon-fasong" :style="'color:'+iconColor" @click="sendTest"></div>
  615. </view>
  616. </div>
  617. </form>
  618. <div class="banner slider-banner">
  619. <swiper class="swiper-wrapper" :autoplay="autoplay" :circular="circular" :interval="interval" :duration="duration"
  620. v-if="emojiGroup.length > 0">
  621. <block v-for="(emojiList, index) in emojiGroup" :key="index">
  622. <swiper-item>
  623. <i class="em" :class="emoji" v-for="emoji in emojiList" :key="emoji" @click="addEmoji(emoji)"></i>
  624. <image src="/static/images/del.png" class="emoji-outer" />
  625. </swiper-item>
  626. </block>
  627. </swiper>
  628. </div>
  629. </div>
  630. <div class="recording" v-if="recording">
  631. <image src="/static/images/recording.png" />
  632. </div>
  633. <authorize @onLoadFun="onLoadFun" :isAuto="isAuto" :isShowAuth="isShowAuth" @authColse="authColse"></authorize>
  634. </div>
  635. </template>
  636. <script>
  637. // +----------------------------------------------------------------------
  638. // | CRMEB [ CRMEB赋能开发者,助力企业发展 ]
  639. // +----------------------------------------------------------------------
  640. // | Copyright (c) 2016~2021 https://www.crmeb.com All rights reserved.
  641. // +----------------------------------------------------------------------
  642. // | Licensed CRMEB并不是自由软件,未经许可不能去掉CRMEB相关版权
  643. // +----------------------------------------------------------------------
  644. // | Author: CRMEB Team <admin@crmeb.com>
  645. // +----------------------------------------------------------------------
  646. import emojiList from "@/utils/emoji";
  647. import Socket from "@/libs/chat";
  648. // #ifdef H5
  649. import ClipboardJS from "@/plugin/clipboard/clipboard.js";
  650. // #endif
  651. import { getChatRecord, getMerHistory } from "@/api/user";
  652. import { getProductDetail, getPresellProductDetail, getStoreDetail } from "@/api/store";
  653. import { getCombinationDetail } from "@/api/activity";
  654. import { getOrderDetail, refundDetail } from "@/api/order";
  655. import easyUpload from '@/components/easy-upload/easy-upload.vue'
  656. import Loading from "@/components/Loading";
  657. import { TOKENNAME, HTTP_REQUEST_URL } from '@/config/app.js';
  658. import { configMap } from "@/utils";
  659. import { mapGetters } from "vuex";
  660. import authorize from '@/components/Authorize';
  661. const chunk = function(arr, num) {
  662. num = num * 1 || 1;
  663. var ret = [];
  664. arr.forEach(function(item, i) {
  665. if (i % num === 0) {
  666. ret.push([]);
  667. }
  668. ret[ret.length - 1].push(item);
  669. });
  670. return ret;
  671. };
  672. const NAME = "CustomerService";
  673. const PATH = 'pages/chat/customer_list/chat'
  674. const app = getApp();
  675. export default {
  676. name: NAME,
  677. components: {
  678. Loading,
  679. easyUpload,
  680. authorize
  681. },
  682. props: {
  683. couponList: {
  684. type: Array,
  685. default: () => []
  686. }
  687. },
  688. computed: configMap(['hide_mer_status'],mapGetters(['isLogin', 'viewColor'])),
  689. data: function() {
  690. return {
  691. url: `${HTTP_REQUEST_URL}/api/upload/image`,
  692. headers: {
  693. "Authori-zation": "Bearer " + this.$store.state.app.token
  694. },
  695. emojiGroup: chunk(emojiList, 20),
  696. active: false,
  697. voice: false,
  698. speak: "按住 说话",
  699. recording: false,
  700. swiperOption: {
  701. pagination: {
  702. el: ".swiper-pagination",
  703. clickable: true
  704. },
  705. speed: 1000,
  706. observer: true,
  707. observeParents: true
  708. },
  709. percent: 0,
  710. footerConH: 0,
  711. footerH: 1.08,
  712. socket: null,
  713. toUid: 0,
  714. page: 1,
  715. limit: 30,
  716. loading: false,
  717. loaded: false,
  718. history: [],
  719. sendColor: false,
  720. sendtxt: "",
  721. productId: 0,
  722. presellId: 0,
  723. combinationId: 0,
  724. productInfo: {},
  725. orderId: "",
  726. orderInfo: {},
  727. cartInfo: {},
  728. autoplay: false,
  729. circular: true,
  730. interval: 3000,
  731. duration: 500,
  732. upload_max: 2, //图片大小
  733. //上传的图片地址
  734. uploadImages: [],
  735. //展示的图片地址
  736. uploads: [],
  737. // 超出限制数组
  738. exceeded_list: [],
  739. windowH: 0,
  740. isBQ: false,
  741. scrollTop: 0, //滚动距离
  742. textCon: '', //文字
  743. iconColor: '#CCCCCC',
  744. mer_id: 0, //商铺id
  745. refund_order_id: 0, //退款订单id
  746. refundDetail: '', //退款订单详情
  747. userId: 0, //客服----用户id
  748. pageType: 0, //页面区分
  749. status: false, //砍价列表是否获取完成 false 未完成 true 完成
  750. storeInfo: '',
  751. isBack: false,
  752. isAuto: false, //没有授权的不会自动授权
  753. isShowAuth: false, //是否隐藏授权
  754. };
  755. },
  756. watch: {
  757. textCon: function(nval, oVal) {
  758. if (nval == "") {
  759. this.iconColor = '#CCCCCC'
  760. } else {
  761. this.iconColor = '#86C956'
  762. }
  763. }
  764. },
  765. beforeDestroy() {
  766. uni.$off(["socket_open", "reply", "chat", "send_chat", "socket_error", "socket_close"])
  767. },
  768. onUnload() {
  769. this.wsEnd();
  770. },
  771. onLoad(option) {
  772. let self = this
  773. this.toUid = option.uid || 0;
  774. this.productId = parseInt(option.productId) || 0;
  775. this.presellId = parseInt(option.presellId) || 0;
  776. this.combinationId = parseInt(option.combinationId) || 0;
  777. this.orderId = option.order_id || ""
  778. this.mer_id = option.mer_id || 0
  779. this.refund_order_id = option.refund_order_id || 0
  780. this.userId = option.userId || 0
  781. uni.getSystemInfo({
  782. success: function(res) {
  783. self.windowH = res.windowHeight
  784. }
  785. })
  786. // #ifdef H5
  787. this.$nextTick(function() {
  788. var clipboard = new ClipboardJS('.copy-data');
  789. clipboard.on('success', function(e) {
  790. self.$util.Tips({
  791. title:'复制成功'
  792. })
  793. });
  794. clipboard.on('error', function(e) {
  795. self.$util.Tips({
  796. title:'复制失败'
  797. })
  798. });
  799. });
  800. // #endif
  801. },
  802. onReady() {},
  803. mounted: function() {
  804. let that = this
  805. that.height();
  806. if (that.isLogin) {
  807. if (that.userId == 0) {
  808. // 用户
  809. that.getHistory();
  810. that.getproductInfo();
  811. that.getOrderInfo();
  812. that.getRefundDetail();
  813. that.getStoreDetail();
  814. } else {
  815. // 客服
  816. that.getMerHistory();
  817. }
  818. uni.$on("socket_open", () => {
  819. if (that.userId == 0) {
  820. that.socket.send({
  821. data: {
  822. mer_id: that.mer_id
  823. },
  824. type: "chat_start"
  825. });
  826. } else {
  827. that.socket.send({
  828. data: {
  829. uid: that.userId,
  830. mer_id: that.mer_id
  831. },
  832. type: "service_chat_start"
  833. });
  834. }
  835. });
  836. uni.$on(["reply", "chat", "send_chat"], data => {
  837. if(that.history.length>0 && that.history[that.history.length-1]['children'].length > 0){
  838. let index = that.history[that.history.length-1]['children'].length-1
  839. let item = that.history[that.history.length-1]['children'][index]
  840. if(data.send_time - item.send_time > 300){
  841. that.history.push({time: data.create_time,children:[data]})
  842. }else{
  843. that.history[that.history.length-1]['children'].push(data);
  844. }
  845. }else{
  846. that.history.push({time: data.create_time,children:[data]})
  847. }
  848. that.height();
  849. });
  850. uni.$on("socket_error", () => {
  851. if (!that.isBack) {
  852. let self = this
  853. uni.showModal({
  854. title: '提示',
  855. content: '连接失败,是否重新连接',
  856. success: function(res) {
  857. if (res.confirm) {
  858. self.wsStart()
  859. } else if (res.cancel) {
  860. uni.navigateBack();
  861. }
  862. }
  863. });
  864. }
  865. });
  866. uni.$on("err_tip", data => {
  867. if (!this.isBack) {
  868. uni.showModal({
  869. title: '提示',
  870. content: data,
  871. success: function(res) {
  872. if (res.confirm) {
  873. console.log('用户点击确定');
  874. } else if (res.cancel) {
  875. console.log('用户点击取消');
  876. }
  877. }
  878. });
  879. }
  880. });
  881. uni.$on("socket_close", () => {
  882. if (!this.isBack) {
  883. let curRoute = this.$mp.page.route;
  884. let self = this
  885. uni.showModal({
  886. title: '提示',
  887. content: '连接断开,是否重新连接',
  888. success: function(res) {
  889. if (res.confirm) {
  890. self.wsStart()
  891. } else if (res.cancel) {
  892. uni.navigateBack();
  893. }
  894. }
  895. });
  896. }
  897. })
  898. this.wsStart();
  899. } else {
  900. that.isAuto = true;
  901. that.isShowAuth = true
  902. }
  903. },
  904. methods: {
  905. /**
  906. * 登录授权回调
  907. *
  908. */
  909. onLoadFun: function() {
  910. this.isShowAuth = false;
  911. if (this.userId == 0) {
  912. // 用户
  913. this.getHistory();
  914. this.getproductInfo();
  915. this.getOrderInfo();
  916. this.getRefundDetail();
  917. this.getStoreDetail();
  918. } else {
  919. // 客服
  920. this.getMerHistory();
  921. }
  922. },
  923. // 授权关闭
  924. authColse: function(e) {
  925. this.isShowAuth = e;
  926. },
  927. userDetail(uid){
  928. this.wsEnd()
  929. uni.redirectTo({
  930. url: `/pages/chat/customer_info/index?uid=${uid}&mer_id=${this.mer_id}`
  931. })
  932. },
  933. // 联系客服拨打电话
  934. goCustomer(){
  935. uni.makePhoneCall({
  936. // 手机号
  937. phoneNumber: this.storeInfo.service_phone,
  938. // 成功回调
  939. success: (res) => {},
  940. // 失败回调
  941. fail: (res) => {}
  942. });
  943. },
  944. // 获取店铺详情
  945. getStoreDetail() {
  946. getStoreDetail(this.mer_id).then(res => {
  947. this.storeInfo = res.data
  948. })
  949. },
  950. // ws连接
  951. wsStart() {
  952. this.socket = new Socket();
  953. this.height();
  954. },
  955. // ws关闭
  956. wsEnd() {
  957. let that = this;
  958. if (that.userId == 0) {
  959. that.socket.send({
  960. data: {
  961. mer_id: that.mer_id
  962. },
  963. type: "chat_end"
  964. });
  965. } else {
  966. that.socket.send({
  967. data: {
  968. uid: that.userId,
  969. mer_id: that.mer_id
  970. },
  971. type: "service_chat_end"
  972. });
  973. }
  974. that.isBack = true
  975. that.socket && that.socket.onClose();
  976. },
  977. // 退款订单
  978. getRefundDetail() {
  979. if (this.refund_order_id) {
  980. refundDetail(this.refund_order_id).then(res => {
  981. this.refundDetail = res.data
  982. })
  983. }
  984. },
  985. uploadImg() {
  986. let self = this
  987. self.$util.uploadImageOne('upload/image', function(res) {
  988. if(res.status == 200){
  989. self.sendMsg(res.data.path, 3)
  990. }
  991. });
  992. },
  993. getOrderInfo() {
  994. if (!this.orderId) return;
  995. getOrderDetail(this.orderId).then(res => {
  996. this.orderInfo = res.data;
  997. if (this.orderInfo.orderProduct.length) {
  998. this.cartInfo = this.orderInfo.orderProduct[0];
  999. }
  1000. });
  1001. },
  1002. getproductInfo() {
  1003. let that = this;
  1004. if (!that.productId && !that.presellId && !that.combinationId) return;
  1005. if(that.presellId || that.combinationId){
  1006. if(that.presellId){
  1007. getPresellProductDetail(that.presellId).then(res => {
  1008. that.productInfo = res.data;
  1009. });
  1010. }else if(that.combinationId){
  1011. getCombinationDetail(that.combinationId).then(res => {
  1012. that.productInfo = res.data.product;
  1013. });
  1014. }
  1015. }else{
  1016. getProductDetail(that.productId).then(res => {
  1017. that.productInfo = res.data;
  1018. });
  1019. }
  1020. },
  1021. scroll() {
  1022. if (window.scrollY < 300 && !this.loaded && !this.loading)
  1023. this.getHistory();
  1024. },
  1025. imageuploaded(res) {
  1026. if (res.status !== 200)
  1027. return this.$util.Tips({
  1028. title: res.msg || "上传图片失败"
  1029. });
  1030. this.sendMsg(res.data.url, 3);
  1031. },
  1032. // 用户聊天记录
  1033. getHistory() {
  1034. if (this.loading || this.loaded) return;
  1035. this.loading = true;
  1036. getChatRecord(this.mer_id, {
  1037. page: this.page,
  1038. limit: this.limit
  1039. })
  1040. .then(({
  1041. data
  1042. }) => {
  1043. // this.history = data.list.concat(this.history);
  1044. let arr = this.getChatTime(data.list)
  1045. let newArr = []
  1046. for(var j in arr){
  1047. let key = j
  1048. let item = {}
  1049. item.time = key;
  1050. item.children = arr[j]
  1051. newArr.push(item)
  1052. }
  1053. this.history = newArr.concat(this.history);
  1054. if (this.page === 1) {
  1055. this.$nextTick(function() {
  1056. // window.scrollTo(0, document.documentElement.scrollHeight + 999);
  1057. this.height();
  1058. });
  1059. }
  1060. this.page++;
  1061. this.loading = false;
  1062. this.loaded = data.length < this.limit;
  1063. })
  1064. .catch(err => {
  1065. this.$util.Tips({
  1066. title: err.msg || "加载失败"
  1067. });
  1068. });
  1069. },
  1070. // 处理聊天时间
  1071. getChatTime(list){
  1072. let arr = {}
  1073. let currentTime = ''
  1074. for(var i=0; i<list.length;i++){
  1075. if(i == 0){
  1076. let time = list[i]['create_time']
  1077. arr[time] = [list[i]]
  1078. currentTime = time
  1079. }else{
  1080. if((list[i]['send_time'] - list[i-1]['send_time']) <= 300 ){
  1081. arr[currentTime].push(list[i])
  1082. }else{
  1083. let time = list[i]['create_time']
  1084. arr[time] = [list[i]]
  1085. currentTime = time
  1086. }
  1087. }
  1088. }
  1089. return arr;
  1090. },
  1091. // 客服聊天记录
  1092. getMerHistory() {
  1093. if (this.loading || this.loaded) return;
  1094. this.loading = true;
  1095. const last_id = this.history.length ? this.history[0].service_log_id : '';
  1096. getMerHistory(this.userId, this.mer_id, {
  1097. page: this.page,
  1098. limit: this.limit,
  1099. last_id
  1100. })
  1101. .then(({
  1102. data
  1103. }) => {
  1104. let arr = this.getChatTime(data.list)
  1105. let newArr = []
  1106. for(var j in arr){
  1107. let key = j
  1108. let item = {}
  1109. item.time = key;
  1110. item.children = arr[j]
  1111. newArr.push(item)
  1112. }
  1113. this.history = newArr.concat(this.history);
  1114. if (this.page === 1) {
  1115. this.$nextTick(function() {
  1116. this.height();
  1117. });
  1118. }
  1119. this.page++;
  1120. this.loading = false;
  1121. this.loaded = data.length < this.limit;
  1122. })
  1123. .catch(err => {
  1124. this.$util.Tips({
  1125. title: err.msg || "加载失败"
  1126. });
  1127. });
  1128. },
  1129. focus: function() {
  1130. this.active = false;
  1131. },
  1132. keyup: function() {
  1133. if (this.$refs.input.value.length > 0) {
  1134. this.sendColor = true;
  1135. } else {
  1136. this.sendColor = false;
  1137. }
  1138. },
  1139. addEmoji(name) {
  1140. this.sendMsg(name, 2);
  1141. },
  1142. clickImg(url){
  1143. wx.previewImage({
  1144. urls: [url],
  1145. current: "",
  1146. success: function(res){},
  1147. fail: function(res){},
  1148. complate: function(res){}
  1149. })
  1150. },
  1151. sendMsg(msn, type) {
  1152. let self = this;
  1153. if (this.userId == 0) {
  1154. this.height();
  1155. this.socket.send({
  1156. data: {
  1157. msn,
  1158. msn_type: type,
  1159. // to_uid: this.toUid,
  1160. mer_id: self.mer_id
  1161. },
  1162. type: "send_chat",
  1163. })
  1164. } else {
  1165. this.height();
  1166. this.socket.send({
  1167. data: {
  1168. msn,
  1169. msn_type: type,
  1170. // to_uid: this.toUid,
  1171. uid: self.userId,
  1172. mer_id: self.mer_id
  1173. },
  1174. type: "service_chat",
  1175. })
  1176. }
  1177. },
  1178. sendTest() {
  1179. this.sendMsg(this.textCon, 1);
  1180. this.textCon = ''
  1181. this.height();
  1182. },
  1183. sendProduct() {
  1184. if(this.presellId || this.combinationId){
  1185. if(this.presellId){
  1186. this.sendMsg(this.presellId, 7);
  1187. this.presellId = 0;
  1188. }else if(this.combinationId){
  1189. this.sendMsg(this.combinationId, 8);
  1190. this.combinationId = 0;
  1191. }
  1192. }else{
  1193. this.sendMsg(this.productId, 4);
  1194. this.productId = 0;
  1195. }
  1196. this.productInfo = {};
  1197. },
  1198. sendOrder() {
  1199. this.sendMsg(this.orderId, 5);
  1200. this.orderId = 0;
  1201. this.orderInfo = {};
  1202. },
  1203. sendRefundOrder() {
  1204. this.sendMsg(this.refund_order_id, 6);
  1205. this.refund_order_id = 0;
  1206. this.refundDetail = {};
  1207. },
  1208. bindInput: function(e) {
  1209. if (e.detail.value) {
  1210. this.sendColor = true
  1211. } else {
  1212. this.sendColor = false
  1213. }
  1214. this.height();
  1215. },
  1216. start() {
  1217. var that = this;
  1218. this.longClick = 0;
  1219. this.timeOutEvent = setTimeout(function() {
  1220. that.longClick = 1;
  1221. }, 500);
  1222. that.speak = "松开 结束";
  1223. that.recording = true;
  1224. },
  1225. move() {
  1226. clearTimeout(this.timeOutEvent);
  1227. this.timeOutEvent = 0;
  1228. },
  1229. end() {
  1230. clearTimeout(this.timeOutEvent);
  1231. if (this.timeOutEvent !== 0 && this.longClick === 0) {
  1232. //点击
  1233. //此处为点击事件----在此处添加跳转详情页
  1234. }
  1235. this.speak = "按住 说话";
  1236. this.recording = false;
  1237. return false;
  1238. },
  1239. voiceBnt: function() {
  1240. this.active = false;
  1241. if (this.voice === true) {
  1242. this.voice = false;
  1243. this.$nextTick(function() {
  1244. this.$refs.input.focus();
  1245. });
  1246. } else {
  1247. this.voice = true;
  1248. }
  1249. // window.scrollTo(0, document.documentElement.scrollHeight);
  1250. this.percent = 0;
  1251. this.footerConH = 0;
  1252. this.footerH = 0;
  1253. this.$nextTick(function() {
  1254. this.height();
  1255. });
  1256. },
  1257. emoticon: function() {
  1258. this.voice = false;
  1259. if (this.active === true) {
  1260. this.active = false;
  1261. this.isBQ = false
  1262. } else {
  1263. this.active = true;
  1264. this.isBQ = true
  1265. }
  1266. this.height();
  1267. },
  1268. height() {
  1269. let self = this
  1270. var scrollTop = 0
  1271. let info = uni.createSelectorQuery().select(".chat");
  1272. setTimeout(res => {
  1273. (!this.isBack) && info.boundingClientRect(function(data) { //data - 各种参数
  1274. scrollTop = data.height
  1275. if (self.active) {
  1276. self.scrollTop = parseInt(scrollTop) + 500
  1277. } else {
  1278. self.scrollTop = parseInt(scrollTop) + 100
  1279. }
  1280. }).exec()
  1281. }, 1000)
  1282. },
  1283. // 滚动到头部
  1284. bindScroll() {
  1285. if (this.userId == 0) {
  1286. this.getHistory();
  1287. this.getproductInfo();
  1288. this.getOrderInfo();
  1289. this.getRefundDetail();
  1290. this.getStoreDetail();
  1291. } else {
  1292. this.getMerHistory();
  1293. }
  1294. },
  1295. //#ifndef H5
  1296. copyText:function(text){
  1297. uni.setClipboardData({ data: text});
  1298. },
  1299. // #endif
  1300. }
  1301. };
  1302. </script>
  1303. <style lang="scss" scoped>
  1304. page {
  1305. width: 100%;
  1306. height: 100%;
  1307. }
  1308. @import url("@/plugin/emoji-awesome/css/google.min.css");
  1309. .noPad {
  1310. padding: 0 !important;
  1311. margin-bottom: 0 !important;
  1312. height: auto !important;
  1313. }
  1314. .broadcast-details_num {
  1315. width: 100%;
  1316. height: 72rpx;
  1317. line-height: 72rpx;
  1318. color: #666666;
  1319. font-size: 26rpx;
  1320. display: flex;
  1321. justify-content: space-between;
  1322. background: #fff;
  1323. border-bottom: 1px solid #F5F5F5;
  1324. padding: 0 24rpx;
  1325. border-radius: 10rpx 10rpx 0 0;
  1326. .line1{
  1327. max-width: 203rpx;
  1328. }
  1329. }
  1330. uni-swiper-item{
  1331. background: #fff;
  1332. }
  1333. .footer_count{
  1334. margin-top: 20rpx;
  1335. width: 710rpx;
  1336. position: fixed;
  1337. bottom: 120rpx;
  1338. left: 20rpx;
  1339. .broadcast-details_box,.broadcast_box{
  1340. margin-bottom: 0;
  1341. position: relative;
  1342. }
  1343. .icon-guanbi{
  1344. font-size: 20rpx;
  1345. color: #C4C4C4;
  1346. position: absolute;
  1347. right: 20rpx;
  1348. top: 20rpx;
  1349. }
  1350. }
  1351. .broadcast-details_order {
  1352. // padding: 15rpx;
  1353. }
  1354. .copy {
  1355. color: var(--view-theme);
  1356. margin-left: 24rpx;
  1357. font-size: 22rpx;
  1358. opacity: .5;
  1359. }
  1360. .broadcast-details_box {
  1361. padding: 20rpx;
  1362. display: flex;
  1363. background: #fff;
  1364. border-radius: 0 0 10rpx 10rpx;
  1365. margin-bottom: 24rpx;
  1366. }
  1367. .broadcast_details_model {
  1368. width: 100%;
  1369. height: 43rpx;
  1370. background: rgba(0, 0, 0, 0.5);
  1371. border-radius: 0 0 16rpx 16rpx;
  1372. position: absolute;
  1373. z-index: 0;
  1374. bottom: 0;
  1375. font-size: 22rpx;
  1376. color: #fff;
  1377. text-align: center;
  1378. line-height: 43rpx;
  1379. }
  1380. .broadcast_details_img {
  1381. width: 160rpx;
  1382. height: 160rpx;
  1383. border-radius: 10px;
  1384. overflow: hidden;
  1385. position: relative;
  1386. }
  1387. .broadcast_details_img uni-image{
  1388. width: 160rpx;
  1389. height: 160rpx;
  1390. }
  1391. .broadcast_details_img_no {
  1392. width: 456rpx;
  1393. height: 456rpx;
  1394. border-radius: 10px 10px 0px 0px;
  1395. overflow: hidden;
  1396. margin-bottom: 10rpx;
  1397. }
  1398. .broadcast_details_picBox_no {
  1399. width: 100%;
  1400. }
  1401. .broadcast_details_img_no uni-image, .broadcast_details_img_no img{
  1402. width: 100%;
  1403. height: 100%;
  1404. }
  1405. .broadcast_details_tit {
  1406. font-size: 30rpx;
  1407. color: #282828;
  1408. height: 40rpx;
  1409. max-width: 400rpx;
  1410. overflow: hidden;
  1411. text-overflow: ellipsis;
  1412. display: -webkit-box;
  1413. -webkit-line-clamp: 1;
  1414. -webkit-box-orient: vertical;
  1415. text-align: left !important;
  1416. }
  1417. .product_price{
  1418. margin-top: 66rpx;
  1419. }
  1420. .broadcast_details_tit_no {
  1421. font-size: 28rpx;
  1422. color: #333333;
  1423. font-weight: 800;
  1424. text-align: left;
  1425. margin-top: 5rpx;
  1426. max-width: 420rpx;
  1427. }
  1428. .broadcast_details_picBox {
  1429. width: 75%;
  1430. margin-left: 24rpx;
  1431. }
  1432. .broadcast_details_pic {
  1433. margin-top: 15rpx;
  1434. font-size: 24rpx;
  1435. color: #999999;
  1436. text-align: left;
  1437. }
  1438. .broadcast_details_pic_num {
  1439. text-decoration: line-through;
  1440. font-size: 28rpx;
  1441. color: rgba(0, 0, 0, 0.5);
  1442. margin-left: 0.1rem;
  1443. }
  1444. .broadcast_details_btn {
  1445. width: 130rpx;
  1446. height: 50rpx;
  1447. background: var(--view-theme);
  1448. opacity: 1;
  1449. border-radius: 125rpx;
  1450. color: #fff;
  1451. font-size: 24rpx;
  1452. text-align: center;
  1453. line-height: 50rpx;
  1454. margin-top: 16px;
  1455. float: right;
  1456. &.product_btn{
  1457. margin-top: 0;
  1458. float: none;
  1459. }
  1460. &.refund_btn{
  1461. width: 150rpx;
  1462. }
  1463. }
  1464. .p-color {
  1465. color: var(--view-priceColor);
  1466. }
  1467. .broadcast-details .chat {
  1468. padding: 1rpx 23rpx 0 23rpx;
  1469. margin-bottom: 3rpx;
  1470. }
  1471. .broadcast-details .chat .item {
  1472. margin-top: 37rpx;
  1473. }
  1474. .broadcast-details .create_time {
  1475. dislay: block;
  1476. width: 100%;
  1477. text-align: center;
  1478. color: #999999;
  1479. font-size: 22rpx;
  1480. margin: 30rpx 0;
  1481. }
  1482. .broadcast-details .chat .item .pictrue {
  1483. width: 80rpx;
  1484. height: 80rpx;
  1485. margin-top: 10rpx;
  1486. }
  1487. .broadcast-details .chat .item .pictrue image {
  1488. width: 100%;
  1489. height: 100%;
  1490. border-radius: 50%;
  1491. }
  1492. .broadcast-details .chat .item .text {
  1493. margin-left: 20rpx;
  1494. }
  1495. .broadcast-details .chat .item .text.textR {
  1496. text-align: right;
  1497. margin: 0 20rpx 0 0;
  1498. }
  1499. .broadcast-details .chat .item .text .name {
  1500. font-size: 24rpx;
  1501. color: #999;
  1502. }
  1503. .broadcast-details .chat .item .text .name .return {
  1504. color: #509efb;
  1505. margin-left: 17rpx;
  1506. }
  1507. .broadcast-details .chat .item .text.textR .name .return {
  1508. margin: 0 0.17rem 0 0;
  1509. }
  1510. .broadcast-details .chat .item .text .conter {
  1511. background-color: #fff;
  1512. border-radius: 8rpx;
  1513. padding: 16rpx 20rpx;
  1514. font-size: 30rpx;
  1515. color: #333;
  1516. position: relative;
  1517. max-width: 600rpx;
  1518. margin-top: 2rpx;
  1519. word-break: break-all;
  1520. text-align: left;
  1521. .em{
  1522. margin: 0;
  1523. }
  1524. }
  1525. .broadcast-details .chat .item .text .spot {
  1526. width: 15rpx;
  1527. height: 15rpx;
  1528. background-color: #c00000;
  1529. border-radius: 50%;
  1530. margin-left: 20rpx;
  1531. }
  1532. .broadcast-details .chat .item .text .conter:before {
  1533. position: absolute;
  1534. content: "";
  1535. width: 0;
  1536. height: 0;
  1537. border-bottom: 9rpx solid transparent;
  1538. border-right: 14rpx solid #fff;
  1539. border-top: 9rpx solid transparent;
  1540. left: -14rpx;
  1541. top: 25rpx;
  1542. }
  1543. .broadcast-details .chat .item .text.textR .conter:before {
  1544. left: unset;
  1545. right: -14rpx;
  1546. transform: rotateY(180deg);
  1547. }
  1548. .broadcast-details .chat .item .text .conter img {
  1549. /* #ifdef H5 */
  1550. width: 100%;
  1551. /* #endif */
  1552. display: block;
  1553. }
  1554. .broadcast-details .chat .item .text .conter .signal {
  1555. width: 48rpx;
  1556. height: 48rpx;
  1557. }
  1558. .broadcast-details .chat .item .text .conter .signal.signalR {
  1559. transform: rotate(180deg);
  1560. -ms-transform: rotate(180deg);
  1561. -webkit-transform: rotate(180deg);
  1562. }
  1563. .broadcast-details .footerCon {
  1564. height: 100rpx;
  1565. width: 100%;
  1566. transition: all 0.005s cubic-bezier(0.25, 0.5, 0.5, 0.9);
  1567. background-color: #fff;
  1568. }
  1569. .broadcast-details .footerCon.on {
  1570. position: relative;
  1571. top: -300rpx;
  1572. transform: translate3d(0, 0, 0) !important;
  1573. }
  1574. .broadcast-details .footerCon .banner .swiper-slide {
  1575. flex-wrap: wrap;
  1576. -webkit-flex-wrap: wrap;
  1577. background-color: #fff;
  1578. padding-bottom: 50rpx;
  1579. border-top: 1px solid #f5f5f5;
  1580. }
  1581. .broadcast-details .footerCon .banner .swiper-slide .emoji-outer,
  1582. .swiper-slide .em {
  1583. display: block;
  1584. width: 50rpx;
  1585. height: 50rpx;
  1586. margin: 40rpx 0 0 50rpx;
  1587. }
  1588. .broadcast-details .footerCon .banner .swiper-container-horizontal>.swiper-pagination-bullets {
  1589. bottom: 10rpx;
  1590. }
  1591. .broadcast-details .footerCon .slider-banner .swiper-pagination-bullet-active {
  1592. background-color: #999;
  1593. }
  1594. .broadcast-details .recording {
  1595. width: 300rpx;
  1596. height: 300rpx;
  1597. position: fixed;
  1598. top: 40%;
  1599. left: 50%;
  1600. margin-left: -150rpx;
  1601. }
  1602. .broadcast-details .recording img {
  1603. width: 100%;
  1604. height: 100%;
  1605. }
  1606. .broadcast-details .footer {
  1607. width: 100%;
  1608. background-color: #fff;
  1609. padding: 17rpx 26rpx;
  1610. }
  1611. .footer_box{
  1612. margin-top: 260rpx;
  1613. }
  1614. .broadcast-details .footer image {
  1615. width: 61rpx;
  1616. height: 60rpx;
  1617. display: block;
  1618. }
  1619. .broadcast-details .footer .icon-biaoqing2,.broadcast-details .footer .icon-tupian2 {
  1620. font-size: 60rpx;
  1621. display: block;
  1622. }
  1623. .broadcast-details .footer .voice {
  1624. width: 440rpx;
  1625. border-radius: 10rpx;
  1626. background-color: #e5e5e5;
  1627. /* padding: 17rpx 30rpx; */
  1628. height: 60rpx;
  1629. padding-left: 20rpx;
  1630. }
  1631. .broadcast-details .footer .input_count{
  1632. margin-left: 20rpx;
  1633. width: 544rpx;
  1634. border-radius: 38rpx;
  1635. background-color: #F6F6F6;
  1636. padding: 0 80rpx 0 30rpx;
  1637. height: 76rpx;
  1638. position: relative;
  1639. }
  1640. .broadcast-details .footer .placeholder{
  1641. color: #999999;
  1642. font-size: 26rpx;
  1643. }
  1644. .broadcast-details .footer .input{
  1645. max-height: 150rpx;
  1646. overflow-y: auto;
  1647. overflow-x: hidden;
  1648. color: #999999;
  1649. height: 76rpx;
  1650. font-size: 26rpx;
  1651. }
  1652. .broadcast-details .footer .send {
  1653. font-size: 48rpx;
  1654. color: #cccccc;
  1655. position: absolute;
  1656. right: 15rpx;
  1657. top: 15rpx;
  1658. }
  1659. .em {
  1660. display: inline-block;
  1661. width: 50rpx;
  1662. height: 50rpx;
  1663. margin: 40rpx 0 0 50rpx;
  1664. }
  1665. .emoji-outer {
  1666. position: absolute;
  1667. right: 70rpx;
  1668. /* bottom: 12rpx; */
  1669. width: 50rpx;
  1670. height: 50rpx;
  1671. margin: 40rpx 0 0 50rpx;
  1672. }
  1673. .broadcast-details {
  1674. display: flex;
  1675. flex-direction: column;
  1676. width: 100%;
  1677. overflow: hidden;
  1678. .hd-wrapper {
  1679. flex: 1;
  1680. display: flex;
  1681. flex-direction: column;
  1682. overflow: hidden;
  1683. &.on {
  1684. padding-bottom: 300rpx;
  1685. }
  1686. }
  1687. }
  1688. .store-wrapper {
  1689. display: flex;
  1690. align-items: center;
  1691. justify-content: space-between;
  1692. padding: 15rpx 20rpx;
  1693. background-color: #fff;
  1694. image {
  1695. width: 60rpx;
  1696. height: 60rpx;
  1697. margin-right: 10rpx;
  1698. }
  1699. .left {
  1700. display: flex;
  1701. align-items: center;
  1702. }
  1703. .link {
  1704. width: 80rpx;
  1705. height: 40rpx;
  1706. line-height: 38rpx;
  1707. border: 1px solid var(--view-theme);
  1708. border-radius: 20px;
  1709. font-size: 24rpx;
  1710. color: var(--view-theme);
  1711. text-align: center;
  1712. }
  1713. .store-opeation{
  1714. align-items: center;
  1715. .icon-dadianhua01{
  1716. color: var(--view-theme);
  1717. margin-left: 28rpx;
  1718. font-size: 34rpx;
  1719. }
  1720. }
  1721. }
  1722. </style>