Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 

1654 rader
37 KiB

  1. <template>
  2. <view class="translation" @click="changeEditing(false)">
  3. <view style="width: 690rpx;height: 64rpx;margin: 0 auto;margin-top: 30rpx;background: #F2F2F2;border-radius: 32rpx;
  4. display: flex;align-items: center;" @tap="toKeywordsearch()">
  5. <image style="width: 28rpx;height: 28rpx;margin-left: 30rpx;" src="/static/images/search.png" mode=""></image>
  6. <text style="margin-left: 10rpx;color: #999999;font-size: 24rpx;">请输入关键字</text>
  7. </view>
  8. <view class="top" style="margin-top: 30rpx;">
  9. <view class="title">
  10. <view class="call_record_time">{{date}}</view>
  11. <view class="hash" @click="gotoChat" v-if="commentList.length != 0">
  12. 查看全部评论
  13. </view>
  14. </view>
  15. <view class="call_record_time_one" >接待时长 {{alltimeStr}}
  16. <u-icon name="list-dot" color="#333" size="48" @click="showFile"></u-icon>
  17. <view class="file-change" v-if="isshowFile">
  18. <view class="file-item" @click="filechange(item,index)"
  19. :class="csdFileindex == index ? 'fileactive' : ''"
  20. v-for="(item,index) in luyinList"
  21. :key="index">录音文件{{index+1}}</view>
  22. </view>
  23. </view>
  24. <view class="audio-container">
  25. <view class="audio-play" @tap="changePlayState">
  26. <image class="image" mode="widthFix" :src="audioPlay ? 'https://qufang.oss-cn-beijing.aliyuncs.com/upload/icon/xcx/jjycrm/pause.png' : 'https://qufang.oss-cn-beijing.aliyuncs.com/upload/icon/xcx/jjycrm/play.png'"></image>
  27. </view>
  28. <view class="audio-slider">
  29. <view class="audio-time">
  30. <text>{{currentTimeStr}}</text>
  31. </view>
  32. <slider class="slider" min="0" :max="sliderMax" @change="sliderChangeComplate" block-size="14"
  33. :value="sliderValue" activeColor="blue"></slider>
  34. <view class="audio-time">
  35. <text>{{timeStr}}</text>
  36. </view>
  37. </view>
  38. </view>
  39. </view>
  40. <scroll-view :scroll-top="scrollTop"
  41. lower-threshold='20px' @scrolltolower="ltolower()" :scroll-into-view="scrollId" scroll-y="true"
  42. class="text scroll-Y">
  43. <!-- 音频识别模块 -->
  44. <view>
  45. <!-- 聊天记录-->
  46. <view class="dialog-block" v-for="(dialog,i) in dialogList" :key="i">
  47. <view :id="'dialog'+i" class="fileName">录音文件</view>
  48. <view class="text" :id="'dialog'+csdFileindex+'text'+index"
  49. :class="{active: item.bg < playNow && item.ed > playNow && i== 0}"
  50. v-for="(item,index) in dialog.message" :key="index" :data-speaker="item.speaker"
  51. >
  52. <view class="avatar">
  53. <text v-if="item.speaker == 1" style="color: #60CBEC;">A</text>
  54. <text v-if="item.speaker == 2" style="color: #EC8B47;">B</text>
  55. <text v-if="item.speaker == 3" style="color: #4F861E;">C</text>
  56. <text v-if="item.speaker == 4" style="color: #9F61C8;">D</text>
  57. <text v-if="item.speaker == 5" style="color: #4980C8;">E</text>
  58. <text v-if="item.speaker == 6" style="color: #60CBEC;">F</text>
  59. <text v-if="item.speaker == 7" style="color: #EC8B47;">G</text>
  60. <text v-if="item.speaker == 8" style="color: #4F861E;">H</text>
  61. <text v-if="item.speaker == 9" style="color: #9F61C8;">I</text>
  62. </view>
  63. <view class="content">
  64. <view v-html="item.onebest"></view>
  65. </view>
  66. </view>
  67. </view>
  68. <!-- 点赞 -->
  69. <view class="likeArea" :class="{'liked':isLiked}">
  70. <image :src="isLiked?'/static/images/recordingManagement/likeActive.png':'/static/images/recordingManagement/like_gray.png'"
  71. mode=""></image>
  72. </view>
  73. <view class="hash" id="hash">
  74. </view>
  75. <!-- 评语列表 -->
  76. <view class="chat" v-if="commentList.length != 0">
  77. <view class="total">
  78. 全部评论(共{{commentList.length}}条)
  79. </view>
  80. <view class="list">
  81. <view class="message" v-for="(item,index) in commentList" :key="index">
  82. <u-avatar class="avator" size="72" :src="item.commentPic ||'https://qufang.oss-cn-beijing.aliyuncs.com/upload/icon/xcx/jjycrm/my/headPicture.png'"></u-avatar>
  83. <view class="right">
  84. <view class="name">
  85. {{item.commentName||"未知昵称"}}
  86. </view>
  87. <view class="subtitle" v-if="item.commentAutoGraph">
  88. {{item.commentAutoGraph}}
  89. </view>
  90. <view class="answer" v-if="item.replyName">
  91. 回复@{{item.replyName}}
  92. </view>
  93. <view class="content" v-if="item.content">
  94. {{item.content}}
  95. </view>
  96. <view class="pic" v-if="item.picUrl">
  97. <image style="width: 100%;max-width: 240px;" :src="item.picUrl" mode="widthFix"></image>
  98. </view>
  99. <view class="bottom">
  100. <view class="time">
  101. {{item.createTime}}
  102. </view>
  103. <view class="button" v-if="myId != item.commentUser" @click.stop="answer(item.commentUser,item.id)">
  104. 回复
  105. </view>
  106. </view>
  107. </view>
  108. </view>
  109. </view>
  110. </view>
  111. </view>
  112. </scroll-view>
  113. <!-- 写评价 -->
  114. <view class="bottomArea">
  115. <image class="voice" @click.stop="changeVoiceShow" src="/static/images/recordingManagement/voice.png" mode=""></image>
  116. <view class="inputArea">
  117. <textarea :value="content" :focus="textareaFocus" type="text" @input="changeContent" :auto-height="true" class="editor"
  118. :class="{'active':editing}" @click.stop="changeEditing(true)" @confirm="sendComment">
  119. </textarea>
  120. <view class="placeholder" :class="{'editing':editing}" v-if="!content">写评价</view>
  121. <image class="edit" v-if="!editing && content == ''" src="/static/images/recordingManagement/edit.png" mode=""></image>
  122. </view>
  123. <image class="like" v-if="myId != createUser && !editing" @click="changeLike" src="/static/images/recordingManagement/like.png"
  124. mode=""></image>
  125. <image class="add" @click.stop="uploadImage" v-if="!editing && content == ''" src="/static/images/recordingManagement/add.png"
  126. mode=""></image>
  127. <view class="send" @click="sendComment" v-if="content!=''">
  128. 发送
  129. </view>
  130. </view>
  131. <!-- 回到顶部 -->
  132. <!-- <view class="backTop" @click="gotoTop">
  133. <image src="/static/images/backTop.png" mode=""></image>
  134. </view> -->
  135. <!-- 语音输入 -->
  136. <cover-view class="voiceContent" v-if="voiceShow" @click="changeVoiceShow">
  137. <cover-view class="box" @click.stop="" @touchstart="voiceStart" @touchend="voiceEnd">
  138. <cover-view class="center">
  139. <cover-image class="voice" src="/static/images/voice.png" mode="widthFix"></cover-image>
  140. <cover-view class="text">
  141. {{isRecording?'正在输入':'长按语音输入'}}
  142. </cover-view>
  143. </cover-view>
  144. </cover-view>
  145. </cover-view>
  146. </view>
  147. </template>
  148. <script>
  149. var app = getApp();
  150. var util = require("../../../utils/util.js");
  151. var config = require("../../../config");
  152. var plugin = requirePlugin("WechatSI")
  153. let manager = plugin.getRecordRecognitionManager();
  154. export default {
  155. data() {
  156. return {
  157. dialogList: [], // 录音对话转移列表
  158. isshowFile: false, // 录音文件默认隐藏
  159. luyinList: [], //录音文件列表
  160. id: "",
  161. customerId: '',
  162. message: "", //聊天记录表
  163. durationTimeStr: "",
  164. autoLoad: true,
  165. playNow: 0,
  166. scrollTop: 0,
  167. scrollId: "",
  168. editing: false,
  169. isLiked: null,
  170. createUser: null,
  171. commentList: [], //评论列表
  172. content: "",
  173. voiceShow: false,
  174. isRecording: false,
  175. answerUserId: null,
  176. answerId: null,
  177. textareaFocus: false,
  178. myId: uni.getStorageSync("weapp_session_userInfo_data").accountId,
  179. audioPlay: false, //当前的播放状态控制
  180. sliderValue: 0, //进度条最小值
  181. end: false,
  182. sliderMax: 0, //进度条最大值
  183. innerAudioContext: "", //播放实例
  184. currentTimeStr: "00:00", //当前进度的时间
  185. timeStr: "00:00", //总的时间
  186. recordPath: "",
  187. csdFileindex:0,
  188. date: "", //年月日
  189. alltimeStr:"00:00",
  190. num: 0, //上拉 转写文件下标
  191. Bnum: 0, //下拉 转写文件下标
  192. status:0,
  193. };
  194. },
  195. onLoad: function(options) {
  196. this.customerId=options.customerId,
  197. this.getdianzan()
  198. this.getCommentList();
  199. // 当进入页面时调一次接口添加浏览量
  200. this.getView()
  201. let that=this
  202. setTimeout(function(){
  203. that.addHot()
  204. },30000)
  205. },
  206. onShow: function() {
  207. this.initRecord();
  208. let pages = getCurrentPages();
  209. let currPage = pages[pages.length - 1]; //当前页面
  210. let info = currPage.data.info
  211. this.innerAudioContext = uni.createInnerAudioContext();
  212. this.innerAudioContext.autoplay = false;
  213. this.innerAudioContext.title = '音频';
  214. this.onPlay()
  215. this.onPause()
  216. this.onCanplay()
  217. this.onEnded()
  218. this.onSeeking()
  219. this.onSeeked()
  220. this.TimeUpdate()
  221. this.getluyinList(info);
  222. },
  223. // 在组件实例被从页面节点树移除时执行
  224. destroyed: function() {
  225. if (this.innerAudioContext) {
  226. this.innerAudioContext.destroy();
  227. }
  228. },
  229. onUnload:function(){
  230. this.innerAudioContext.destroy();
  231. },
  232. methods: {
  233. toKeywordsearch(){
  234. this.innerAudioContext.destroy();
  235. uni.navigateTo({
  236. url: '/pages/main/Keywordsearch?customerId='+this.customerId +"&status="+this.status
  237. })
  238. },
  239. getView(){
  240. this.$u.get('/addtodigest/addPageviews',{
  241. id:this.customerId
  242. })
  243. .then(res=>{
  244. // console.log(res)
  245. })
  246. },
  247. addHot(){
  248. // console.log('30')
  249. this.$u.get('/addtodigest/addHeat',{
  250. id:this.customerId
  251. })
  252. .then(res=>{
  253. // console.log(res)
  254. })
  255. },
  256. onPlay(){
  257. this.innerAudioContext.onPlay(() => {
  258. // 播放监听
  259. console.log('播放!');
  260. this.audioPlay = true;
  261. });
  262. },
  263. onPause(){
  264. this.innerAudioContext.onPause(() => {
  265. // 暂停监听
  266. console.log('暂停播放!');
  267. this.audioPlay = false
  268. });
  269. },
  270. onCanplay() {
  271. this.innerAudioContext.onCanplay((callback) => {
  272. console.log("缓冲回调",this.innerAudioContext.duration);
  273. })
  274. },
  275. onEnded(){
  276. this.innerAudioContext.onEnded(() => {
  277. // 结束播放监听
  278. console.log('播放结束!');
  279. this.audioPlay = false;
  280. this.qeihuanwenjian()
  281. });
  282. },
  283. onSeeking(){
  284. this.innerAudioContext.onSeeking((res) => {
  285. console.log("进行跳转", res);
  286. })
  287. },
  288. onSeeked(){
  289. this.innerAudioContext.onSeeked((res) => {
  290. console.log("结束跳转", res);
  291. this.$forceUpdate()
  292. });
  293. },
  294. TimeUpdate(){
  295. this.innerAudioContext.onTimeUpdate(() => {
  296. const {
  297. currentTime,
  298. duration
  299. } = this.innerAudioContext;
  300. this.playNow = parseInt(currentTime * 1000)
  301. if (this.dialogList.length == 0) {
  302. } else {
  303. const message = this.dialogList[0].message
  304. for (let i = 0; i < message.length; i++) {
  305. if (Number(message[i].bg) < this.playNow && Number(message[i].ed) > this.playNow) {
  306. this.scrollId = "dialog" + this.csdFileindex + "text" + i;
  307. break;
  308. }
  309. }
  310. }
  311. const currTimeStr = this.formatTime(currentTime);
  312. this.sliderValue = parseInt(currentTime);
  313. // 变动的时间
  314. this.currentTimeStr = currTimeStr;
  315. //进度条最大值
  316. this.sliderMax = this.luyinList[this.csdFileindex].recordDuration;
  317. this.$forceUpdate()
  318. });
  319. },
  320. //下一页
  321. ltolower() {
  322. var lengthcz=this.luyinList.length-1;
  323. if (this.num >= lengthcz) {
  324. uni.showToast({
  325. title: '到底了',
  326. duration: 2000
  327. });
  328. return
  329. }else {
  330. this.num=this.num+1;
  331. uni.showLoading({
  332. title: '加载中'
  333. });
  334. setTimeout(function() {
  335. uni.hideLoading();
  336. }, 2000);
  337. uni.request({
  338. url: config.service.getCorpusAnalysis + '?corpusId=' + this.luyinList[this.num].id+"&customerId="+this.customerId, //仅为示例,并非真实接口地址。
  339. method: "GET",
  340. header: {
  341. 'content-type': 'application/json',
  342. 'Access-Token': uni.getStorageSync('weapp_session_login_data').token
  343. },
  344. success: (data) => {
  345. if (data.data.code == 10000) {
  346. if (data.data.data.audioContent.length == 0) {
  347. setTimeout(function() {
  348. uni.hideLoading();
  349. }, 2000);
  350. } else {
  351. const jsonInfo = JSON.parse(data.data.data.audioContent);
  352. this.dialogList.push({
  353. message: jsonInfo
  354. });
  355. this.dialogList.forEach((asd, idx) => {
  356. asd.message.forEach((qwe, inde) => {
  357. qwe.isshow = false;
  358. })
  359. })
  360. }
  361. }
  362. },
  363. })
  364. }
  365. },
  366. //上一页
  367. rolltoupper() {
  368. if (this.csdFileindex == 0) {
  369. uni.showToast({
  370. title: '到头了',
  371. duration: 2000
  372. });
  373. return
  374. } else if(this.Bnum == 0){
  375. uni.showToast({
  376. title: '到头了',
  377. duration: 2000
  378. });
  379. return
  380. }else {
  381. this.Bnum=this.Bnum-1;
  382. uni.showLoading({
  383. title: '加载中'
  384. });
  385. setTimeout(function() {
  386. uni.hideLoading();
  387. }, 2000);
  388. uni.request({
  389. url: config.service.getCorpusAnalysis + '?corpusId=' + this.luyinList[this.Bnum].id+"&customerId="+this.customerId, //仅为示例,并非真实接口地址。
  390. method: "GET",
  391. header: {
  392. 'content-type': 'application/json',
  393. 'Access-Token': uni.getStorageSync('weapp_session_login_data').token
  394. },
  395. success: (data) => {
  396. if (data.data.code == 10000) {
  397. if (data.data.data.audioContent.length == 0) {
  398. setTimeout(function() {
  399. uni.hideLoading();
  400. }, 2000);
  401. } else {
  402. const jsonInfo = JSON.parse(data.data.data.audioContent);
  403. this.dialogList.unshift({
  404. message: jsonInfo
  405. });
  406. this.dialogList.forEach((asd, idx) => {
  407. asd.message.forEach((qwe, inde) => {
  408. qwe.isshow = false;
  409. })
  410. })
  411. }
  412. }
  413. },
  414. })
  415. }
  416. },
  417. //获取点赞列表isLiked likegetLike
  418. getdianzan(){
  419. uni.request({
  420. url: config.service.likegetLike + '?targetId=' + this.customerId, //仅为示例,并非真实接口地址。
  421. method:"GET",
  422. header: {
  423. 'content-type': 'application/json',
  424. 'Access-Token': uni.getStorageSync('weapp_session_login_data').token
  425. },
  426. success: (data) => {
  427. if(data.data.code==10000){
  428. this.isLiked=data.data.data.like;
  429. }else{
  430. uni.hideLoading();
  431. uni.showModal({
  432. title: '提示',
  433. content: '请求数据失败,请重新尝试',
  434. showCancel: false
  435. });
  436. }
  437. },
  438. fail(error) {
  439. uni.hideLoading();
  440. uni.showModal({
  441. title: '提示',
  442. content: '网络异常,请重新尝试',
  443. showCancel: false
  444. });
  445. return false;
  446. }
  447. });
  448. },
  449. // 获取评论列表
  450. getCommentList() {
  451. const that = this;
  452. util.getRequestPromise(config.service.cmmentList + '?targetId=' + this.customerId, {}, false, "GET").then(data => {
  453. let tmp = data;
  454. tmp.reverse();
  455. that.commentList = tmp;
  456. });
  457. },
  458. // 获取录音记录列表
  459. getluyinList(info) {
  460. this.sliderMax = 0; //进度条最大值
  461. this.timeStr = "00:00"; //总的时间
  462. const parames = {
  463. pageNum: 1,
  464. pageSize: 100,
  465. query: {
  466. customerId: this.customerId
  467. }
  468. }
  469. this.$u.post("/corpus/findByPage", parames).then(res => {
  470. if (res && res.length) {
  471. let alltime = 1;
  472. res.forEach(item => {
  473. alltime += item.recordDuration
  474. })
  475. this.alltimeStr = this.getTime(alltime)
  476. if(info){
  477. res.forEach((item,index) => {
  478. if(item.id==info.id){
  479. this.csdFileindex=index;
  480. this.recordPath = res[index].recordPath
  481. this.sliderMax = this.getTime(res[index].recordDuration)
  482. this.timeStr = this.getTime(res[index].recordDuration)
  483. this.date = res[index].receptionTime;
  484. this.isshowFile = false;
  485. this.getCorpusAnalysis();
  486. this.creatAudio()
  487. var itc=parseInt(info.bg/1000)
  488. this.adasdasdasd(itc)
  489. }
  490. })
  491. }else{
  492. this.recordPath = res[0].recordPath
  493. this.sliderMax = this.getTime(res[0].recordDuration)
  494. this.timeStr = this.getTime(res[0].recordDuration)
  495. this.date = res[0].receptionTime
  496. this.innerAudioContext.src = this.recordPath;
  497. this.changePlayState()
  498. this.luyinList = res;
  499. this.getCorpusAnalysis()
  500. }
  501. }
  502. })
  503. },
  504. //搜索跳转
  505. adasdasdasd(e) {
  506. const currTimeStr = this.formatTime(e)
  507. this.currentTimeStr = currTimeStr
  508. this.innerAudioContext.seek(e);
  509. this.innerAudioContext.play();
  510. },
  511. // 获取转义后的对话结果
  512. getCorpusAnalysis(){
  513. this.dialogList = [];
  514. uni.showLoading({
  515. title: '加载中'
  516. });
  517. uni.request({
  518. url: config.service.getCorpusAnalysis + '?corpusId=' + this.luyinList[this.csdFileindex].id+"&customerId="+this.customerId, //仅为示例,并非真实接口地址。
  519. method:"GET",
  520. header: {
  521. 'content-type': 'application/json',
  522. 'Access-Token': uni.getStorageSync('weapp_session_login_data').token
  523. },
  524. success: (data) => {
  525. if(data.data.code==10000){
  526. if(data.data.data.audioContent.length==0){
  527. setTimeout(function () {
  528. uni.hideLoading();
  529. }, 2000);
  530. }else{
  531. const jsonInfo = JSON.parse(data.data.data.audioContent);
  532. this.dialogList.push({
  533. message: jsonInfo
  534. });
  535. setTimeout(function () {
  536. uni.hideLoading();
  537. }, 2000);
  538. }
  539. }else{
  540. uni.hideLoading();
  541. uni.showModal({
  542. title: '提示',
  543. content: '请求数据失败,请重新尝试',
  544. showCancel: false
  545. });
  546. }
  547. },
  548. fail(error) {
  549. uni.hideLoading();
  550. uni.showModal({
  551. title: '提示',
  552. content: '网络异常,请重新尝试',
  553. showCancel: false
  554. });
  555. return false;
  556. }
  557. });
  558. },
  559. getTime(time) {
  560. return util.formatSecond(time)
  561. },
  562. // 文件切换播放
  563. filechange(item, i) {
  564. this.num=i;//下拉起始位置
  565. this.Bnum=i;
  566. this.innerAudioContext.destroy()
  567. this.csdFileindex=i;
  568. this.recordPath = item.recordPath;
  569. this.sliderMax = this.getTime(item.recordDuration);
  570. this.timeStr = this.getTime(item.recordDuration);
  571. this.date=item.receptionTime;
  572. this.isshowFile=false;
  573. this.creatAudio()
  574. this.getCorpusAnalysis()
  575. },
  576. //录音实例
  577. creatAudio() {
  578. this.innerAudioContext = uni.createInnerAudioContext();
  579. this.innerAudioContext.autoplay = true;
  580. this.innerAudioContext.src = this.recordPath;
  581. this.innerAudioContext.title = '音频';
  582. this.onPlay()
  583. this.onPause()
  584. this.onCanplay()
  585. this.onEnded()
  586. this.onSeeking()
  587. this.onSeeked()
  588. this.TimeUpdate()
  589. },
  590. // 自动播放下一个文件
  591. qeihuanwenjian(){
  592. let index=this.csdFileindex+1;
  593. if(index<this.luyinList.length){
  594. this.csdFileindex=index;
  595. this.getCorpusAnalysis()
  596. let item=this.luyinList[this.csdFileindex];
  597. let i=this.csdFileindex;
  598. this.filechange(item,i)
  599. }
  600. },
  601. // 录音暂停播放
  602. changePlayState() {
  603. if (this.audioPlay == false) {
  604. this.innerAudioContext.play();
  605. } else {
  606. this.innerAudioContext.pause()
  607. }
  608. },
  609. sliderChange() {
  610. },
  611. //音频前进回退
  612. sliderChangeComplate(e) {
  613. const currTimeStr = this.formatTime(e.detail.value)
  614. this.currentTimeStr = currTimeStr
  615. this.innerAudioContext.seek(e.detail.value);
  616. this.innerAudioContext.play();
  617. },
  618. formatTime(num) {
  619. //格式化时间格式
  620. num = num.toFixed(0);
  621. let second = num % 60;
  622. if (second < 10) second = '0' + second;
  623. let min = Math.floor(num / 60);
  624. if (min < 10) min = '0' + min;
  625. return min + ":" + second;
  626. },
  627. //录音文件切换隐藏
  628. showFile() {
  629. this.isshowFile = !this.isshowFile
  630. },
  631. changeVoiceShow() {
  632. this.voiceShow = !this.voiceShow;
  633. },
  634. voiceStart: function() {
  635. manager.start({
  636. lang: "zh_CN"
  637. });
  638. },
  639. voiceEnd: function() {
  640. // uni.showToast();
  641. if (this.isRecording) {
  642. uni.showLoading({
  643. title: "识别中"
  644. })
  645. }
  646. this.voiceShow = false;
  647. this.isRecording = false;
  648. manager.stop();
  649. },
  650. // 语音初始化
  651. initRecord() {
  652. const that = this;
  653. manager.onStart = function(res) {
  654. that.isRecording = true;
  655. // this.voiceState = "onStart:" + res.msg + "正在录音"
  656. };
  657. //有新的识别内容返回,则会调用此事件
  658. manager.onRecognize = (res) => {
  659. console.log('ing' + res.result);
  660. }
  661. // 识别结束事件
  662. manager.onStop = (res) => {
  663. uni.hideLoading();
  664. let newText = that.content + res.result;
  665. if (newText.length > 140) {
  666. newText = newText.substring(0, 140)
  667. }
  668. that.content = newText;
  669. that.textareaFocus = true;
  670. }
  671. // 识别错误事件
  672. manager.onError = (res) => {
  673. uni.hideLoading();
  674. }
  675. },
  676. changeContent(e) {
  677. this.content = e.detail.value;
  678. },
  679. answer(userId, tid) {
  680. this.answerId = tid;
  681. this.answerUserId = userId;
  682. this.editing = true;
  683. this.textareaFocus = true;
  684. },
  685. // 保存评论
  686. sendComment() {
  687. if (this.content == "") {
  688. uni.showToast({
  689. icon: "none",
  690. title: "请输入标题"
  691. })
  692. return;
  693. }
  694. let parames = {
  695. targetId: this.customerId,
  696. content: this.content,
  697. commentType: 1
  698. };
  699. if (this.answerUserId) {
  700. parames.replyCommentId = this.answerId;
  701. parames.replyUser = this.answerUserId;
  702. }
  703. const that = this;
  704. util.getRequestPromise(config.service.saveCmment, parames, false).then(data => {
  705. that.getCommentList();
  706. uni.showToast({
  707. title: "评论成功",
  708. icon: "none"
  709. })
  710. that.textareaFocus = false;
  711. that.content = "";
  712. });
  713. },
  714. uploadImage() {
  715. const that = this;
  716. var parames = {
  717. targetId: that.id,
  718. commentType: 1
  719. };
  720. if (this.answerUserId) {
  721. parames.replyCommentId = this.answerId;
  722. parames.replyUser = this.answerUserId;
  723. }
  724. uni.chooseImage({
  725. count: 1, //默认9
  726. sizeType: ['original', 'compressed'], //可以指定是原图还是压缩图,默认二者都有
  727. sourceType: ['album', 'camera'],
  728. success: function(res) {
  729. uni.showLoading({
  730. title: "上传中"
  731. })
  732. uni.uploadFile({
  733. url: config.service.saveCmmentUpload,
  734. filePath: res.tempFilePaths[0],
  735. name: 'file',
  736. header: {
  737. "Access-Token": uni.getStorageSync('weapp_session_login_data').token
  738. },
  739. formData: parames,
  740. success: (uploadFileRes) => {
  741. that.getCommentList();
  742. uni.hideLoading();
  743. uni.showToast({
  744. icon: "none",
  745. title: "上传成功"
  746. })
  747. console.log(uploadFileRes.data);
  748. }
  749. });
  750. }
  751. });
  752. },
  753. uploadAudio() {
  754. },
  755. changeLike() {
  756. uni.showLoading({
  757. title: "请求中",
  758. mask: true
  759. })
  760. if (this.isLiked) {
  761. this.cancelLike();
  762. } else {
  763. this.saveLike();
  764. }
  765. },
  766. // 点赞
  767. saveLike() {
  768. const that = this;
  769. util.getRequestPromise(config.service.saveLike, {
  770. targetId: this.customerId
  771. }, false).then(data => {
  772. that.isLiked = true;
  773. uni.hideLoading();
  774. uni.showToast({
  775. icon: "none",
  776. title: "点赞成功"
  777. })
  778. });
  779. },
  780. // 取消点赞
  781. cancelLike() {
  782. const that = this;
  783. util.getRequestPromise(config.service.cancelLike, {
  784. targetId: this.customerId
  785. }, false).then(data => {
  786. that.isLiked = false;
  787. uni.hideLoading();
  788. uni.showToast({
  789. icon: "none",
  790. title: "取消点赞成功"
  791. })
  792. });
  793. },
  794. gotoChat() {
  795. this.scrollId = null;
  796. this.$nextTick(() => {
  797. this.scrollId = "hash";
  798. })
  799. },
  800. gotoTop() {
  801. this.scrollId = null;
  802. this.$nextTick(() => {
  803. this.scrollId = "top";
  804. })
  805. },
  806. changeEditing(type) {
  807. this.editing = type;
  808. this.answerId = null;
  809. this.answerUserId = null;
  810. this.textareaFocus = false;
  811. this.dialogList.forEach(res=>{
  812. res.message.forEach(asd=>{
  813. asd.isshow=false;
  814. })
  815. })
  816. }
  817. }
  818. };
  819. </script>
  820. <style lang="scss" scoped>
  821. .biaoqiantom{
  822. background-color: #008EF2;
  823. color: #FFFFFF;
  824. border: none;
  825. }
  826. // 表单
  827. .tian-view{
  828. width: 570upx;
  829. background-color: #FFFFFF;
  830. border-bottom: 1px solid #ededee;
  831. display: flex;
  832. min-height: 96rpx;
  833. .tian-view-t1{
  834. width: 20rpx;
  835. font-size: 34rpx;
  836. height: 34rpx;
  837. line-height: 110rpx;
  838. letter-spacing: 0px;
  839. color: red;
  840. }
  841. .tian-view-t2{
  842. width:30%;
  843. min-height: 96rpx;
  844. line-height: 96rpx;
  845. font-size: 34rpx;
  846. color: #333;
  847. }
  848. .tian-view-t3{
  849. width: 61%;
  850. padding-top: 31rpx;
  851. padding-bottom:31rpx;
  852. display:flex;
  853. .tian-input{
  854. width:98%;
  855. font-size: 34rpx;
  856. border: none;
  857. }
  858. }
  859. }
  860. .zhezhoa {
  861. position: fixed;
  862. top: 0;
  863. left: 0;
  864. z-index: 999;
  865. width: 100%;
  866. height: 100vh;
  867. opacity: 0.5;
  868. background-color: #666666;
  869. }
  870. .bounced {
  871. width: 570upx;
  872. background: #FFFFFF;
  873. z-index: 1000;
  874. border-radius: 10upx;
  875. position: fixed;
  876. left: 50%;
  877. top: 50%;
  878. transform: translate(-50%, -50%);
  879. /* 50%为自身尺寸的一半 */
  880. .jiajinghuatit{
  881. width: 100%;
  882. height: 68rpx;
  883. font-size: 30rpx;
  884. text-align: center;
  885. line-height: 68rpx;
  886. }
  887. .jiajinghuaview{
  888. padding: 18rpx 18rpx 18rpx 18rpx;
  889. display: flex;
  890. flex-wrap:wrap;
  891. .jiajinghuaview1{
  892. padding: 8rpx 8rpx 8rpx 8rpx;
  893. font-size: 26rpx;
  894. border-radius: 12rpx;
  895. border: 1px solid #979797;
  896. margin-left: 8rpx;
  897. }
  898. .jighuaview2{
  899. padding: 8rpx 8rpx 8rpx 8rpx;
  900. font-size: 26rpx;
  901. border-radius: 12rpx;
  902. border: 1px solid #979797;
  903. margin-left: 8rpx;
  904. display: flex;
  905. .view1-text{
  906. text-align: center;
  907. // border-right: 1rpx solid red;
  908. }
  909. .view1-img{
  910. width: 50rpx;
  911. }
  912. }
  913. }
  914. .bounced3 {
  915. height: 100upx;
  916. width: 100%;
  917. margin-top: 40upx;
  918. border-top: 1px solid #dddddd;
  919. display: flex;
  920. }
  921. .bounced3-1 {
  922. width: 50%;
  923. height: 100%;
  924. text-align: center;
  925. line-height: 100upx;
  926. border-right: 1px solid #dddddd;
  927. font-size: 36upx;
  928. color: #999999;
  929. }
  930. .bounced3-2 {
  931. width: 50%;
  932. height: 100%;
  933. text-align: center;
  934. line-height: 100upx;
  935. font-size: 36upx;
  936. color: #108ee9;
  937. }
  938. }
  939. .bosdttom{
  940. color: #008EF2;
  941. }
  942. .tab-box {
  943. width: 100%;
  944. display: flex;
  945. justify-content: center;
  946. align-items: center;
  947. .yinpinshibie {
  948. width: 156rpx;
  949. height: 50rpx;
  950. font-size: 36rpx;
  951. font-weight: 400;
  952. color: #333333;
  953. text-align: center;
  954. line-height: 50rpx;
  955. letter-spacing: 2rpx;
  956. margin-right: 188rpx;
  957. &.active {
  958. position: relative;
  959. &::after {
  960. position: absolute;
  961. content: '';
  962. width: 119rpx;
  963. height: 8rpx;
  964. background: #008EF2;
  965. border-radius: 4rpx;
  966. top: 50rpx;
  967. right: 0;
  968. left: 0;
  969. margin: 0 auto;
  970. }
  971. }
  972. }
  973. .rate {
  974. width: 156rpx;
  975. height: 50rpx;
  976. font-size: 36rpx;
  977. font-weight: 400;
  978. color: #333333;
  979. line-height: 50rpx;
  980. letter-spacing: 2rpx;
  981. text-align: center;
  982. &.active {
  983. position: relative;
  984. &::after {
  985. position: absolute;
  986. content: '';
  987. width: 119rpx;
  988. height: 8rpx;
  989. background: #008EF2;
  990. border-radius: 4rpx;
  991. top: 50rpx;
  992. right: 0;
  993. left: 0;
  994. margin: 0 auto;
  995. }
  996. }
  997. }
  998. }
  999. .dialog-block {
  1000. margin: 20rpx 0;
  1001. border-bottom: 1px solid #ccc;
  1002. .fileName {
  1003. text-align: center;
  1004. margin: 10rpx auto;
  1005. width: 115rpx;
  1006. height: 42rpx;
  1007. line-height: 42rpx;
  1008. background: #EFEFEF;
  1009. border-radius: 4rpx;
  1010. font-size: 20rpx;
  1011. font-weight: 400;
  1012. color: #333333;
  1013. }
  1014. }
  1015. // 评分
  1016. .rate-box {
  1017. padding: 10rpx 20rpx;
  1018. .date {
  1019. width: 300rpx;
  1020. height: 33rpx;
  1021. font-size: 24rpx;
  1022. font-weight: 400;
  1023. color: #333333;
  1024. line-height: 33rpx;
  1025. letter-spacing: 1rpx;
  1026. margin-bottom: 8rpx;
  1027. }
  1028. .title {
  1029. width: 100%;
  1030. height: 42rpx;
  1031. font-size: 30rpx;
  1032. font-weight: 500;
  1033. color: #333333;
  1034. line-height: 42rpx;
  1035. letter-spacing: 2rpx;
  1036. margin-bottom: 20rpx;
  1037. }
  1038. .level1 {
  1039. display: flex;
  1040. align-items: center;
  1041. .level-name {
  1042. width: 104rpx;
  1043. height: 33rpx;
  1044. font-size: 24rpx;
  1045. font-weight: 500;
  1046. color: #333333;
  1047. line-height: 33rpx;
  1048. letter-spacing: 1rpx;
  1049. margin-right: 10rpx;
  1050. }
  1051. .level-progress {
  1052. flex: 1;
  1053. border-radius: 11rpx;
  1054. height: 21rpx;
  1055. background-color: #BEE4FF;
  1056. position: relative;
  1057. .color {
  1058. width: 0;
  1059. position: absolute;
  1060. top: 0;
  1061. left: 0;
  1062. height: 21rpx;
  1063. border-radius: 11rpx 0 0 11rpx;
  1064. background-color: #008EF2;
  1065. }
  1066. }
  1067. .level-rate {
  1068. width: 65rpx;
  1069. height: 33rpx;
  1070. font-size: 24rpx;
  1071. font-weight: 500;
  1072. color: #333333;
  1073. line-height: 33rpx;
  1074. letter-spacing: 1rpx;
  1075. margin: 0 20rpx 0 15rpx;
  1076. }
  1077. .arrow {
  1078. width: 37rpx;
  1079. height: 21rpx;
  1080. padding: 5rpx 20rpx;
  1081. }
  1082. .rotatearrow {
  1083. transform: rotate(270deg);
  1084. }
  1085. }
  1086. .level1-subbox {
  1087. display: flex;
  1088. margin-top: 20rpx;
  1089. flex-wrap: wrap;
  1090. .sub-name {
  1091. width: 50%;
  1092. display: flex;
  1093. margin-bottom: 18rpx;
  1094. .subitem-name {
  1095. width: 104rpx;
  1096. height: 33rpx;
  1097. font-size: 24rpx;
  1098. font-weight: 400;
  1099. color: #999999;
  1100. line-height: 33rpx;
  1101. letter-spacing: 1rpx;
  1102. margin-right: 12rpx;
  1103. }
  1104. .checkimg {
  1105. width: 27rpx;
  1106. height: 27rpx;
  1107. }
  1108. }
  1109. }
  1110. }
  1111. .luyin {
  1112. height: 100rpx;
  1113. width: 100%;
  1114. }
  1115. .translation {
  1116. padding-left: 30rpx;
  1117. padding-right: 30rpx;
  1118. background: #FFFFFF;
  1119. display: flex;
  1120. flex-direction: column;
  1121. height: 100vh;
  1122. }
  1123. .translation .top {
  1124. margin: 0 -30upx;
  1125. padding: 0 30upx;
  1126. background: #ffffff;
  1127. border-bottom: 1rpx solid #F2F2F2;
  1128. padding-bottom: 10rpx;
  1129. }
  1130. .translation .top .title {
  1131. display: flex;
  1132. justify-content: space-between;
  1133. .hash {
  1134. color: rgba(21, 144, 233, 1);
  1135. font-size: 24upx;
  1136. }
  1137. }
  1138. .call_record_time {
  1139. height: 44rpx;
  1140. font-size: 28rpx;
  1141. font-weight: 600;
  1142. color: #008EF2;
  1143. line-height: 44rpx;
  1144. }
  1145. .call_record_time_one {
  1146. height: 48rpx;
  1147. font-size: 24rpx;
  1148. font-weight: 500;
  1149. color: #70798d;
  1150. line-height: 48rpx;
  1151. display: flex;
  1152. justify-content: space-between;
  1153. position: relative;
  1154. .diangweitupian{
  1155. width: 46rpx;
  1156. height: 46rpx;
  1157. // border: 1px solid red;
  1158. position: absolute;
  1159. top: 0rpx;
  1160. right: 75rpx;
  1161. }
  1162. .file-change {
  1163. position: absolute;
  1164. top: 50rpx;
  1165. right: 0rpx;
  1166. width: 184rpx;
  1167. background: #FFFFFF;
  1168. box-shadow: 0rpx 0rpx 6rpx 2rpx rgba(230, 230, 230, 0.5);
  1169. border-radius: 4rpx;
  1170. z-index: 99;
  1171. height: auto;
  1172. max-height: 600rpx;
  1173. overflow: auto;
  1174. }
  1175. .file-item {
  1176. width: 184rpx;
  1177. height: 60rpx;
  1178. line-height: 60rpx;
  1179. text-align: center;
  1180. font-size: 30rpx;
  1181. font-weight: 400;
  1182. color: #333333;
  1183. border-bottom: 1rpx solid #E2E2E2;
  1184. }
  1185. .file-item:last-child {
  1186. border: 0
  1187. }
  1188. .fileactive {
  1189. color: #008EF2
  1190. }
  1191. }
  1192. .scroll-Y {
  1193. font-size: 36upx;
  1194. color: #999999;
  1195. background: #FFFFFF;
  1196. margin-top: 30upx;
  1197. flex: 1;
  1198. overflow-y: scroll;
  1199. width: 100%;
  1200. }
  1201. .scroll-Y .text {
  1202. margin: 50upx 30upx;
  1203. line-height: 80upx;
  1204. display: flex;
  1205. align-items: center;
  1206. }
  1207. .scroll-Y .text[data-speaker="2"],
  1208. .scroll-Y .text[data-speaker="4"],
  1209. .scroll-Y .text[data-speaker="6"] {
  1210. flex-direction: row-reverse;
  1211. text-align: right;
  1212. .content {
  1213. margin-left: 0;
  1214. margin-right: 30upx;
  1215. background: #F6F6F6;
  1216. color: #999999;
  1217. }
  1218. }
  1219. .scroll-Y .text .avatar {
  1220. width: 64upx;
  1221. height: 64upx;
  1222. line-height: 64upx;
  1223. text-align: center;
  1224. // border: 1rpx solid red;
  1225. font-size: 36rpx;
  1226. border-radius: 50%;
  1227. background: #F2F2F2;
  1228. color: #008EF2;
  1229. // display: flex;
  1230. // justify-content: center;
  1231. // align-items: center;
  1232. // image {
  1233. // width: 40upx;
  1234. // }
  1235. }
  1236. .scroll-Y .text .content {
  1237. margin-left: 30upx;
  1238. line-height: 60rpx;
  1239. text-align: left;
  1240. padding: 0 5px;
  1241. background: #2BC805;
  1242. border-radius: 8upx;
  1243. max-width: 442rpx;
  1244. color: #FFFFFF;
  1245. position: relative;
  1246. .tankuangcss{
  1247. position: absolute;
  1248. top: -53rpx;
  1249. left: -80rpx;
  1250. width: 318rpx;
  1251. height: 68rpx;
  1252. background-color: #333333;
  1253. font-size: 24rpx;
  1254. color: #FFFFFF;
  1255. padding-top: 4rpx;
  1256. padding-bottom:4rpx;
  1257. display: flex;
  1258. align-items: center;
  1259. border-radius: 15rpx;
  1260. }
  1261. }
  1262. .scroll-Y .text.active .content {
  1263. color: #38FFF1;
  1264. position: relative;
  1265. }
  1266. .scroll-Y .text.active[data-speaker="2"] .content,
  1267. .scroll-Y .text.active[data-speaker="4"] .content,
  1268. .scroll-Y .text.active[data-speaker="6"] .content {
  1269. color: #FF7538;
  1270. position: relative;
  1271. }
  1272. .likeArea {
  1273. width: 86upx;
  1274. height: 84upx;
  1275. margin: 20upx auto 38upx auto;
  1276. border-radius: 50%;
  1277. display: flex;
  1278. justify-content: center;
  1279. align-items: center;
  1280. border: 1upx solid #C1C2C1;
  1281. &.liked {
  1282. border: 1upx solid rgba(21, 144, 233, 1);
  1283. }
  1284. image {
  1285. width: 38upx;
  1286. height: 39upx;
  1287. }
  1288. }
  1289. .chat {
  1290. display: flex;
  1291. flex-direction: column;
  1292. border-top: 1upx solid rgba(151, 151, 151, 0.4);
  1293. padding-top: 20upx;
  1294. .total {
  1295. color: rgba(21, 144, 233, 1);
  1296. font-size: 24upx;
  1297. }
  1298. .list {
  1299. display: flex;
  1300. flex-direction: column;
  1301. .message {
  1302. display: flex;
  1303. margin-top: 20upx;
  1304. border-bottom: 1upx solid rgba(151, 151, 151, 0.4);
  1305. padding-bottom: 20upx;
  1306. &:last-child {
  1307. border-bottom: 0;
  1308. }
  1309. .avator {
  1310. margin-left: 120upx;
  1311. }
  1312. &:first-child {
  1313. .avator {
  1314. margin-left: 0;
  1315. }
  1316. }
  1317. .right {
  1318. display: flex;
  1319. flex-direction: column;
  1320. margin-left: 20upx;
  1321. flex: 1;
  1322. .name {
  1323. color: rgba(16, 16, 16, 1);
  1324. font-size: 30upx;
  1325. }
  1326. .subtitle {
  1327. color: rgba(120, 120, 120, 1);
  1328. font-size: 24upx;
  1329. margin-top: 16upx;
  1330. }
  1331. .answer {
  1332. font-size: 24upx;
  1333. color: #787878;
  1334. }
  1335. .content {
  1336. color: rgba(49, 48, 48, 1);
  1337. font-size: 30upx;
  1338. margin-top: 20upx;
  1339. position: relative;
  1340. }
  1341. .bottom {
  1342. margin-top: 16upx;
  1343. display: flex;
  1344. justify-content: space-between;
  1345. .time {
  1346. color: rgba(185, 185, 185, 1);
  1347. font-size: 20upx;
  1348. }
  1349. .button {
  1350. color: rgba(144, 144, 144, 1);
  1351. font-size: 30upx;
  1352. width: 111upx;
  1353. height: 44upx;
  1354. border-radius: 22upx;
  1355. border: 1upx solid rgba(151, 151, 151, 1);
  1356. text-align: center;
  1357. }
  1358. }
  1359. }
  1360. }
  1361. }
  1362. }
  1363. .bottomArea {
  1364. min-height: 90upx;
  1365. background: #F0F2F5;
  1366. width: 100vw;
  1367. margin: 0 -30rpx;
  1368. display: flex;
  1369. align-items: center;
  1370. border-top: 1upx solid rgba(151, 151, 151, 0.25);
  1371. .voice {
  1372. width: 44upx;
  1373. height: 44upx;
  1374. margin-left: 38upx;
  1375. }
  1376. .inputArea {
  1377. margin-left: 38upx;
  1378. margin-right: 38upx;
  1379. flex: 1;
  1380. display: flex;
  1381. position: relative;
  1382. .edit {
  1383. width: 30upx;
  1384. height: 28upx;
  1385. position: absolute;
  1386. top: 31upx;
  1387. left: 27upx;
  1388. }
  1389. .editor {
  1390. background: rgba(0, 139, 245, 0.17);
  1391. border-radius: 29upx;
  1392. flex: 1;
  1393. min-height: 58upx;
  1394. width: unset;
  1395. padding: 0 32upx;
  1396. font-size: 30upx;
  1397. margin: 16rpx 0;
  1398. line-height: 29px;
  1399. }
  1400. .placeholder {
  1401. position: absolute;
  1402. left: 70rpx;
  1403. top: 22rpx;
  1404. color: #26A2FF;
  1405. &.editing {
  1406. left: 36rpx;
  1407. }
  1408. }
  1409. }
  1410. .download {
  1411. width: 41upx;
  1412. height: 35upx;
  1413. margin-right: 36upx;
  1414. }
  1415. .like {
  1416. width: 38upx;
  1417. height: 39upx;
  1418. margin-right: 38upx;
  1419. }
  1420. .add {
  1421. width: 50upx;
  1422. height: 50upx;
  1423. margin-right: 38upx;
  1424. }
  1425. .send {
  1426. background: #1590e9;
  1427. color: white;
  1428. padding: 10rpx 20rpx;
  1429. margin: 5px;
  1430. border-radius: 8rpx;
  1431. }
  1432. }
  1433. .backTop {
  1434. width: 60upx;
  1435. height: 60upx;
  1436. background: rgba(211, 235, 253, 1);
  1437. box-shadow: 0upx 0upx 2upx 4upx rgba(38, 161, 255, 0.04);
  1438. border-radius: 50%;
  1439. position: fixed;
  1440. bottom: 200upx;
  1441. right: 8upx;
  1442. display: flex;
  1443. justify-content: center;
  1444. align-items: center;
  1445. image {
  1446. width: 26upx;
  1447. height: 34upx;
  1448. }
  1449. }
  1450. .voiceContent {
  1451. position: fixed;
  1452. top: 0;
  1453. bottom: 0;
  1454. left: 0;
  1455. right: 0;
  1456. width: 100vw;
  1457. height: 100vh;
  1458. display: flex;
  1459. justify-content: center;
  1460. align-items: center;
  1461. background: rgba(30, 30, 30, 0.4592);
  1462. z-index: 10001;
  1463. }
  1464. .box {
  1465. background: rgba(21, 144, 233, 0.299);
  1466. width: 524upx;
  1467. height: 524upx;
  1468. border-radius: 50%;
  1469. display: flex;
  1470. align-items: center;
  1471. justify-content: center;
  1472. .center {
  1473. width: 412upx;
  1474. height: 412upx;
  1475. background: #1590E9;
  1476. border-radius: 50%;
  1477. display: flex;
  1478. align-items: center;
  1479. justify-content: center;
  1480. flex-direction: column;
  1481. .voice {
  1482. width: 110upx;
  1483. height: 133upx;
  1484. }
  1485. .text {
  1486. color: #FFFFFF;
  1487. font-size: 36upx;
  1488. margin-top: 24upx;
  1489. }
  1490. }
  1491. }
  1492. .audio-container {
  1493. width: 100%;
  1494. display: flex;
  1495. justify-content: space-between;
  1496. align-items: center;
  1497. .audio-head {
  1498. width: 60rpx;
  1499. height: 60rpx;
  1500. flex-shrink: 0;
  1501. }
  1502. .audio-head .image {
  1503. width: 100%;
  1504. height: 100%;
  1505. }
  1506. .audio-slider {
  1507. width: 96%;
  1508. position: relative;
  1509. padding: 2px 0rpx 0px 20px;
  1510. display: flex;
  1511. justify-content: space-between;
  1512. align-items: center;
  1513. }
  1514. .audio-slider .slider {
  1515. width: 100%;
  1516. padding: 0px 15rpx;
  1517. box-sizing: border-box;
  1518. }
  1519. .audio-time {
  1520. width: 110rpx;
  1521. text-align: right;
  1522. font-size: 24rpx;
  1523. line-height: 28rpx;
  1524. color: #70798D;
  1525. display: flex;
  1526. justify-content: space-between;
  1527. }
  1528. .audio-play {
  1529. width: 40rpx;
  1530. height: 40rpx;
  1531. flex-shrink: 0;
  1532. }
  1533. .audio-play .image {
  1534. width: 100%;
  1535. height: 100%;
  1536. }
  1537. }
  1538. </style>