journalItem.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  1. <template>
  2. <view
  3. v-if="journalData"
  4. class="journal-item"
  5. @click.stop="handleClick">
  6. <view v-if="journalData.createUser" class="user">
  7. <wk-avatar
  8. :name="journalData.createUser.realname"
  9. :avatar="journalData.createUser.img"
  10. :size="12"
  11. :preview="false"
  12. class="avatar" />
  13. <view class="user-info">
  14. <view class="username">
  15. <text class="text">
  16. {{ journalData.createUser.realname }}
  17. </text>
  18. </view>
  19. <view class="time">
  20. {{ journalData.createTime }}
  21. </view>
  22. </view>
  23. <view class="right">
  24. <image
  25. v-if="showReadMore"
  26. :src="$static('images/oa/log_record.png')"
  27. class="read-more"
  28. @click.stop="handleReadMore" />
  29. <view class="badge">
  30. {{ categoryText }}
  31. </view>
  32. </view>
  33. </view>
  34. <view v-if="sendUserList.length > 0" class="send-user">
  35. 接收人: {{ sendUserList }}
  36. </view>
  37. <view class="content">
  38. <view v-if="journalData.content" class="box">
  39. <view class="box-title">
  40. {{ getCategory(journalData.categoryId, 0) }}工作内容:
  41. </view>
  42. <view class="box-content">
  43. <view>{{ journalData.content }}</view>
  44. </view>
  45. </view>
  46. <view v-if="journalData.tomorrow" class="box">
  47. <view class="box-title">
  48. {{ getCategory(journalData.categoryId, 1) }}工作内容:
  49. </view>
  50. <view class="box-content">
  51. <view>{{ journalData.tomorrow }}</view>
  52. </view>
  53. </view>
  54. <view v-if="journalData.question" class="box">
  55. <view class="box-title">
  56. 遇到的问题:
  57. </view>
  58. <view class="box-content">
  59. <view>{{ journalData.question }}</view>
  60. </view>
  61. </view>
  62. </view>
  63. <view
  64. v-if="!$isEmpty(journalData.bulletin)"
  65. class="sale-box">
  66. <view class="sale-title">
  67. 销售简报
  68. </view>
  69. <view class="sale-list">
  70. <view
  71. v-for="(saleItem, index) in saleList"
  72. :key="index"
  73. class="sale-list-item"
  74. @click.stop="handleToBulletin(saleItem)">
  75. <text
  76. :style="{color: saleItem.color}"
  77. :class="saleItem.icon"
  78. class="wk" />
  79. <text>
  80. {{ getCategory(journalData.categoryId, 0) }}{{ saleItem.label }}
  81. </text>
  82. <text>
  83. <!-- {{ saleItem.num }} -->
  84. {{ journalData[saleItem.key] }}
  85. </text>
  86. </view>
  87. </view>
  88. </view>
  89. <wk-image-content
  90. v-if="!$isEmpty(journalData.img)"
  91. :list="journalData.img" />
  92. <wk-file-content
  93. v-if="!$isEmpty(journalData.file) && isDetail"
  94. :list="journalData.file"
  95. @click.native.stop />
  96. <relevance-section
  97. v-if="showRelevance && isDetail"
  98. :relevance-data="journalData" />
  99. <view class="control-btn" @click.stop>
  100. <view
  101. :class="{active: isFavourFlag}"
  102. class="control-btn-item"
  103. @click.stop="handleToggleFavour">
  104. <image
  105. :src="favPicUrl"
  106. class="icon-pic" />
  107. <text
  108. v-if="favourUserList.length > 0"
  109. class="text">
  110. {{ favourUserList.length }}
  111. </text>
  112. </view>
  113. <view
  114. class="control-btn-item"
  115. @click.stop="handleToComment">
  116. <image
  117. :src="$static('images/oa/log_comment.png')"
  118. class="icon-pic" />
  119. <text
  120. v-if="journalData.replyNum > 0"
  121. class="text">
  122. {{ journalData.replyNum }}
  123. </text>
  124. </view>
  125. </view>
  126. <view
  127. v-if="showFavourContent || showCommentContent"
  128. :class="{
  129. 'padding-bottom': !showCommentContent
  130. }"
  131. class="others">
  132. <view
  133. v-if="showFavourContent"
  134. class="fav-section"
  135. @click.stop="handleToFavour">
  136. <image
  137. :src="$static('images/oa/log_favour.png')"
  138. class="icon-pic" />
  139. <view
  140. v-if="!$isEmpty(favourUserList)"
  141. class="sec-content">
  142. <text
  143. v-for="(user, index) in favourUserList.slice(0, 10)"
  144. :key="user.userId"
  145. class="username">
  146. {{ user.realname }}
  147. <template v-if="index < favourUserList.slice(0, 10).length - 1">
  148. </template>
  149. </text>
  150. <text
  151. v-if="favourUserList.length > 10"
  152. class="more-text">
  153. 等{{ favourUserList.length }}人点赞
  154. </text>
  155. </view>
  156. </view>
  157. <comment-list
  158. v-if="showCommentContent && !$isEmpty(replyDataList)"
  159. :show-avatar="isDetail"
  160. :reply-list="replyDataList"
  161. @choose="handleChooseUser" />
  162. <view
  163. v-if="!isDetail && journalData.replyNum > 5"
  164. class="more-comment">
  165. 查看全部{{ journalData.replyNum }}条评论
  166. <text class="wk wk-arrow-right" />
  167. </view>
  168. </view>
  169. <template v-if="isDetail">
  170. <view
  171. v-if="!journalData.replyNum"
  172. :class="{
  173. 'border-top': !showFavourContent && !showCommentContent
  174. }"
  175. class="empty-reply">
  176. 暂无评论,发表第一条评论吧
  177. </view>
  178. <view v-else class="empty-box" />
  179. </template>
  180. </view>
  181. </template>
  182. <script>
  183. import { FavourOrCancel } from '@/api/oa/journal.js'
  184. import { QueryCommentList } from 'API/oa/comment'
  185. import RelevanceSection from '@/components/base/relevance-section.vue'
  186. import CommentList from '@/components/base/comment-list.vue'
  187. import { calcIcon } from 'UTIL/file'
  188. import { isArray } from '@/utils/types.js'
  189. export default {
  190. name: 'JournalItem',
  191. components: {
  192. RelevanceSection,
  193. CommentList
  194. },
  195. props: {
  196. journalData: {
  197. type: Object,
  198. required: true
  199. },
  200. isDetail: {
  201. type: Boolean,
  202. default: false
  203. },
  204. showReadMore: {
  205. type: Boolean,
  206. default: false
  207. }
  208. },
  209. data() {
  210. return {
  211. saleList: [
  212. {
  213. label: '新增客户',
  214. key: 'customerCount',
  215. module: 'customer',
  216. num: 0,
  217. icon: 'wk-customer',
  218. color: '#487dff',
  219. },
  220. {
  221. label: '新增商机',
  222. key: 'businessCount',
  223. module: 'business',
  224. num: 0,
  225. icon: 'wk-business',
  226. color: '#fb9223',
  227. },
  228. {
  229. label: '新增合同',
  230. key: 'contractCount',
  231. module: 'contract',
  232. num: 0,
  233. icon: 'wk-contract',
  234. color: '#fd5b4a',
  235. },
  236. {
  237. label: '新增回款',
  238. key: 'receivablesMoney',
  239. module: 'receivables_money',
  240. num: 0,
  241. icon: 'wk-receivables',
  242. color: '#ffb940',
  243. },
  244. {
  245. label: '新增跟进记录',
  246. key: 'recordCount',
  247. module: 'record',
  248. num: 0,
  249. icon: 'wk-record',
  250. color: '#19b5f6',
  251. }
  252. ],
  253. replyData: [],
  254. replyDataList: []
  255. }
  256. },
  257. computed: {
  258. sendUserList() {
  259. if (this.$isEmpty(this.journalData.sendUserList)) return ''
  260. let str = ''
  261. this.journalData.sendUserList.forEach(item => {
  262. str = str + item.realname + '、'
  263. })
  264. return str.slice(0, -1)
  265. },
  266. showRelevance() {
  267. let arr = ['customerList', 'contactsList', 'businessList', 'contractList'].map(key => {
  268. return isArray(this.journalData[key]) && this.journalData[key].length > 0
  269. })
  270. let length = arr.filter(flag => {
  271. return !flag
  272. }).length
  273. return length !== arr.length
  274. },
  275. categoryText() {
  276. return {
  277. 1: '日报',
  278. 2: '周报',
  279. 3: '月报'
  280. }[this.journalData.categoryId]
  281. },
  282. showFavourContent() {
  283. return !this.$isEmpty(this.journalData.favourUser)
  284. },
  285. showCommentContent() {
  286. return this.journalData.replyNum > 0
  287. },
  288. isFavourFlag() {
  289. return this.journalData.isFavour
  290. },
  291. favourUserList() {
  292. return this.journalData.favourUser || []
  293. },
  294. favPicUrl() {
  295. if (this.$isEmpty(this.journalData)) return ''
  296. return this.journalData.isFavour ? this.$static('images/oa/log_favour_primary.png') : this.$static('images/oa/log_favour.png')
  297. }
  298. },
  299. watch: {
  300. showCommentContent: {
  301. handler(val) {
  302. if (val) {
  303. this.getReplyList()
  304. }
  305. },
  306. deep: true,
  307. immediate: true
  308. }
  309. },
  310. methods: {
  311. getReplyList(ignore = false) {
  312. if (this.journalData.replyNum === 0 && !ignore) return
  313. QueryCommentList({
  314. typeId: this.journalData.logId,
  315. type: 2
  316. }).then(res => {
  317. if (this.isDetail) {
  318. this.replyDataList = res || []
  319. return
  320. }
  321. this.replyData = res || []
  322. this.replyDataList = []
  323. // console.log('replyList res: ', res)
  324. if (this.$isEmpty(res)) return
  325. const max = 5
  326. let arr = []
  327. let i = 0
  328. let len = 0
  329. do {
  330. len++ // 总长度+1
  331. const child = res[i].childCommentList || []
  332. if (child.length < max - len) { // 子评论长度小于剩余
  333. arr.push(res[i])
  334. } else { // 子评论大于剩余
  335. arr.push({
  336. ...res[i],
  337. childCommentList: child.splice(0, max - len) // 取剩余长度
  338. })
  339. }
  340. len += child.length
  341. i++
  342. } while (len < max && i < res.length)
  343. this.replyDataList = arr
  344. }).catch(() => {})
  345. },
  346. getCategory(categoryId, flag = 0) {
  347. const map = {
  348. 1: ['今日', '明日'],
  349. 2: ['本周', '下周'],
  350. 3: ['本月', '下月']
  351. }
  352. if (!map.hasOwnProperty(categoryId)) {
  353. categoryId = 1
  354. }
  355. return map[categoryId][flag]
  356. },
  357. /**
  358. * 选择回复人
  359. * @param {Object} user
  360. */
  361. handleChooseUser(user, evt) {
  362. // console.log('user --', user)
  363. this.$emit('choose', user)
  364. if (!this.isDetail) {
  365. this.handleClick(evt)
  366. }
  367. },
  368. /**
  369. * 切换点赞状态
  370. */
  371. handleToggleFavour() {
  372. FavourOrCancel({
  373. logId: this.journalData.logId,
  374. isFavour: !this.journalData.isFavour
  375. }).then(res => {
  376. this.$set(this.journalData, 'isFavour', res.isFavour)
  377. this.$set(this.journalData, 'favourUser', res.favourUser)
  378. this.$emit('update-data', this.journalData)
  379. if (this.isDetail) {
  380. this.$refreshAndToPrev(this, false)
  381. }
  382. }).catch(() => {})
  383. },
  384. /**
  385. * 查看销售简报
  386. * @param {Object} item
  387. */
  388. handleToBulletin(item) {
  389. const query = {
  390. logId: this.journalData.logId,
  391. module: item.module,
  392. title: this.getCategory(this.journalData.categoryId, 0) + item.label
  393. }
  394. if (item.module !== 'record') {
  395. query.module = item.module
  396. this.$Router.navigateTo({
  397. url: '/pages_crm/homeReport/report',
  398. query
  399. })
  400. } else {
  401. this.$Router.navigateTo({
  402. url: '/pages_crm/homeReport/recordCountList',
  403. query
  404. })
  405. }
  406. },
  407. handleReadMore() {
  408. this.$emit('read-more', this.journalData)
  409. },
  410. /**
  411. * 查看点赞详情
  412. */
  413. handleToFavour() {
  414. getApp().globalData.cacheDataBridge = null
  415. getApp().globalData.cacheDataBridge = this.journalData.favourUser || []
  416. this.$Router.navigateTo('/pages_log/favour')
  417. },
  418. handleClick(evt) {
  419. this.$emit('click', evt)
  420. },
  421. handleToComment(evt) {
  422. if (this.isDetail) return
  423. this.$emit('comment', evt)
  424. // this.$Router.navigateTo({
  425. // url: '/pages_log/detail',
  426. // query: {
  427. // id: this.journalData.logId,
  428. // action: 'comment'
  429. // }
  430. // })
  431. }
  432. }
  433. }
  434. </script>
  435. <style scoped lang="scss">
  436. .journal-item {
  437. width: 100%;
  438. padding: 28rpx 32rpx 0;
  439. background-color: white;
  440. .user {
  441. margin-bottom: 20rpx;
  442. @include left;
  443. .avatar {
  444. width: 72rpx;
  445. height: 72rpx;
  446. margin-right: 20rpx;
  447. }
  448. .user-info {
  449. .username {
  450. font-size: 30rpx;
  451. color: $dark;
  452. display: flex;
  453. }
  454. .time {
  455. font-size: 24rpx;
  456. color: $light;
  457. }
  458. }
  459. .right {
  460. flex: 1;
  461. @include right;
  462. .read-more {
  463. width: 42rpx;
  464. height: 42rpx;
  465. margin-right: 30rpx;
  466. }
  467. .badge {
  468. font-size: $wk-font-mini;
  469. color: #BBBBBB;
  470. line-height: 1;
  471. background-color: #EEEEEE;
  472. border-radius: 8rpx;
  473. padding: 12rpx 20rpx;
  474. }
  475. }
  476. }
  477. .send-user {
  478. font-size: 26rpx;
  479. color: $light;
  480. margin-bottom: 10rpx;
  481. }
  482. .content {
  483. font-size: 24rpx;
  484. .box {
  485. .box-title {
  486. color: $light;
  487. }
  488. .box-content {
  489. font-size: 28rpx;
  490. color: $dark;
  491. white-space: pre-wrap;
  492. word-wrap: break-word;
  493. padding: 10rpx 0;
  494. }
  495. }
  496. }
  497. .wk-image-content, .wk-file-content {
  498. margin-bottom: 20rpx;
  499. }
  500. .sale-box {
  501. font-size: 26rpx;
  502. margin-bottom: 15rpx;
  503. margin-top: 10rpx;
  504. .sale-title {
  505. color: $light;
  506. margin-bottom: 15rpx;
  507. }
  508. .sale-list {
  509. width: 100%;
  510. font-size: 24rpx;
  511. display: flex;
  512. flex-wrap: wrap;
  513. justify-content: space-between;
  514. .sale-list-item {
  515. width: 45%;
  516. height: 50rpx;
  517. line-height: 50rpx;
  518. background-color: #EFF5FF;
  519. border-radius: 8rpx;
  520. padding: 0 20rpx;
  521. margin-right: 30rpx;
  522. margin-bottom: 15rpx;
  523. .wk {
  524. font-size: 26rpx;
  525. margin-right: 10rpx;
  526. }
  527. }
  528. }
  529. }
  530. .control-btn {
  531. width: 100%;
  532. padding-bottom: 20rpx;
  533. @include right;
  534. .control-btn-item {
  535. color: #666666;
  536. margin-right: 36rpx;
  537. .icon-pic {
  538. width: 38rpx;
  539. height: 38rpx;
  540. vertical-align: middle;
  541. margin-right: 10rpx;
  542. }
  543. .text {
  544. font-size: $wk-font-base;
  545. color: inherit;
  546. vertical-align: middle;
  547. }
  548. &.active {
  549. color: $theme-color;
  550. }
  551. &:last-child {
  552. margin-right: 0;
  553. }
  554. }
  555. }
  556. .others {
  557. border-top: 1rpx solid $border-color;
  558. padding: 15rpx 0 0;
  559. &.padding-bottom {
  560. padding-bottom: 15rpx;
  561. }
  562. .fav-section {
  563. display: flex;
  564. align-items: flex-start;
  565. justify-content: flex-start;
  566. .icon-pic {
  567. width: 34rpx;
  568. height: 34rpx;
  569. margin: 8rpx 0;
  570. }
  571. .sec-content {
  572. flex: 1;
  573. overflow: hidden;
  574. margin-left: 20rpx;
  575. .username {
  576. color: $theme-color;
  577. font-size: $wk-font-base;
  578. }
  579. .more-text {
  580. font-size: $wk-font-base;
  581. }
  582. }
  583. }
  584. .more-comment {
  585. font-size: $wk-font-base;
  586. color: $theme-color;
  587. margin-left: 50rpx;
  588. padding-bottom: 15rpx;
  589. .wk-arrow-right {
  590. font-size: inherit;
  591. }
  592. }
  593. }
  594. .empty-reply {
  595. width: 100%;
  596. font-size: $wk-font-sm;
  597. color: $light;
  598. text-align: center;
  599. padding: 55rpx 0 70rpx;
  600. &.border-top {
  601. border-top: 1rpx solid $border-color;
  602. padding: 70rpx 0;
  603. }
  604. }
  605. .empty-box {
  606. width: 100%;
  607. height: 20rpx;
  608. background-color: white;
  609. }
  610. }
  611. .detail-section {
  612. .bg {
  613. width: calc(100% + 70rpx);
  614. height: 15rpx;
  615. background-color: #F3F3F3;
  616. margin-left: -35rpx;
  617. }
  618. .detail-comment {
  619. font-size: 28rpx;
  620. .detail-comment-title{
  621. padding-top: 30rpx;
  622. }
  623. }
  624. }
  625. </style>