MomentsItem.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459
  1. <template>
  2. <view class="moments_item">
  3. <my-avatar
  4. size="48"
  5. :src="moments.faceURL"
  6. :desc="moments.nickname"
  7. @click="toPublisher"
  8. />
  9. <view class="main_content">
  10. <view class="pusher">
  11. {{ moments.nickname }}
  12. </view>
  13. <view class="moments_text" @click="toDetails">
  14. {{ moments.content.text }}
  15. </view>
  16. <!-- <view class="moments_media" :class="{'grid_media':moments.content.metas.length>1}"
  17. :style="{'grid-template-rows':getGridRows}">
  18. <media-item v-for="item in moments.content.metas" :key="item.original" :item="item" />
  19. </view> -->
  20. <u-album
  21. v-if="moments.content.metas.length > 0"
  22. multipleSize="70"
  23. keyName="thumb"
  24. previewKeyName="original"
  25. :isVideo="moments.content.type === 1"
  26. :previewFullImage="moments.content.type === 0"
  27. :urls="moments.content.metas || []"
  28. @clickItem="clickMediaItem"
  29. ></u-album>
  30. <view class="at_list" v-if="moments.atUsers.length > 0">
  31. <text>{{ atStr }}</text>
  32. </view>
  33. <view class="time_line">
  34. <text>{{ publishTimeStr }}</text>
  35. <image
  36. v-if="moments.permission === 1"
  37. class="lock_icon"
  38. src="https://bjyjb-1362704775.cos.ap-chongqing.myqcloud.com/shop/image/moments_lock.png"
  39. />
  40. <image
  41. v-if="moments.permission === 2 || moments.permission === 3"
  42. class="limit_icon"
  43. src="https://bjyjb-1362704775.cos.ap-chongqing.myqcloud.com/shop/image/moments_limit.png"
  44. />
  45. <text
  46. v-if="moments.userID === $store.getters.storeCurrentUserID"
  47. @click="delteMoments"
  48. >删除</text
  49. >
  50. <image
  51. class="action_icon"
  52. src="https://bjyjb-1362704775.cos.ap-chongqing.myqcloud.com/shop/image/moments_more.png"
  53. @click.stop="showAction"
  54. />
  55. <u-overlay
  56. :show="moreMenuVisible"
  57. @click="moreMenuVisible = false"
  58. opacity="0"
  59. >
  60. <view
  61. :style="{ top: popMenuPosition.top, right: popMenuPosition.right }"
  62. class="more_menu">
  63. <view class="menu_item" @click="likeOrNot">
  64. <image :src="likeIcon" mode="" />
  65. <view>赞</view>
  66. </view>
  67. <view
  68. class="menu_item"
  69. @click="$emit('startComent', moments.workMomentID)"
  70. >
  71. <image src="https://bjyjb-1362704775.cos.ap-chongqing.myqcloud.com/shop/image/moments_coment.png" mode="" />
  72. <view>评论</view>
  73. </view>
  74. </view>
  75. </u-overlay>
  76. </view>
  77. <view class="like_list" v-if="likeStr">
  78. <image :src="moments_liked" />
  79. <text>{{ likeStr }}</text>
  80. </view>
  81. <view class="coment_list">
  82. <coment-item
  83. v-for="comment in moments.comments"
  84. :key="comment.commentID"
  85. :momentsUserID="moments.userID"
  86. :comment="comment"
  87. @startComent="$emit('startComent', moments.workMomentID, comment)"
  88. @deleteComent="deleteComent"
  89. />
  90. </view>
  91. </view>
  92. </view>
  93. </template>
  94. <script>
  95. import IMSDK from "openim-uniapp-polyfill";
  96. import MyAvatar from "../../../../components/MyAvatar/index.vue";
  97. import MediaItem from "./MediaItem.vue";
  98. import ComentItem from "./ComentItem.vue";
  99. import { formatConversionTime } from "../../../../util/imCommon";
  100. import { deleteComment, deleteMoments, likeMoments } from "../../../../api/moments";
  101. import { PageEvents } from "../../../../constant";
  102. import { toastWithCallback } from "../../../../util/common";
  103. const moments_like = "https://bjyjb-1362704775.cos.ap-chongqing.myqcloud.com/shop/image/moments_like.png";
  104. const moments_liked = "https://bjyjb-1362704775.cos.ap-chongqing.myqcloud.com/shop/image/moments_liked.png";
  105. export default {
  106. components: {
  107. MyAvatar,
  108. MediaItem,
  109. ComentItem,
  110. },
  111. props: {
  112. moments: Object,
  113. showDetails: Boolean,
  114. inSingle: Boolean,
  115. },
  116. data() {
  117. return {
  118. moreMenuVisible: false,
  119. popMenuPosition: {
  120. top: 0,
  121. right: 0,
  122. },
  123. moments_liked,
  124. };
  125. },
  126. computed: {
  127. publishTimeStr() {
  128. return formatConversionTime(this.moments.createTime);
  129. },
  130. getGridRows() {
  131. if (this.moments.content.metas.length < 3) {
  132. return "100px";
  133. }
  134. if (this.moments.content.metas.length < 6) {
  135. return "100px 100px";
  136. }
  137. return "100px 100px 100px";
  138. },
  139. likeStr() {
  140. let str = "";
  141. const likeNum = this.moments.likeUsers.length;
  142. const tmpList = this.showDetails
  143. ? this.moments.likeUsers
  144. : this.moments.likeUsers.slice(0, 5);
  145. tmpList.map((user) => (str += `${user.nickname}、`));
  146. return (
  147. str.slice(0, str.length - 1) +
  148. (likeNum > 5 && this.showDetails ? `等${likeNum}人点赞` : "")
  149. );
  150. },
  151. atStr() {
  152. let str = "提到了:";
  153. const atNum = this.moments.atUsers.length;
  154. const tmpList = this.showDetails
  155. ? this.moments.atUsers
  156. : this.moments.atUsers.slice(0, 5);
  157. tmpList.map((user) => (str += `${user.nickname}、`));
  158. return (
  159. str.slice(0, str.length - 1) +
  160. (atNum > 5 && this.showDetails ? `等${atNum}人` : "")
  161. );
  162. },
  163. isLiked() {
  164. return (
  165. this.moments.likeUsers.findIndex(
  166. (user) => user.userID === this.$store.getters.storeCurrentUserID,
  167. ) > -1
  168. );
  169. },
  170. likeIcon() {
  171. return this.isLiked ? moments_liked : moments_like;
  172. },
  173. },
  174. methods: {
  175. async showAction() {
  176. const { left, top } = await this.getEl(".action_icon");
  177. this.popMenuPosition.right = `${
  178. uni.getWindowInfo().windowWidth - left + 12
  179. }px`;
  180. this.popMenuPosition.top = `${top}px`;
  181. this.moreMenuVisible = true;
  182. },
  183. getEl(el) {
  184. return new Promise((resolve) => {
  185. const query = uni.createSelectorQuery().in(this);
  186. query
  187. .select(el)
  188. .boundingClientRect((data) => {
  189. resolve(data);
  190. })
  191. .exec();
  192. });
  193. },
  194. likeOrNot() {
  195. likeMoments(this.moments.workMomentID, !this.isLiked)
  196. .then((res) => {
  197. if (this.isLiked) {
  198. const tmpArr = [...this.moments.likeUsers];
  199. const idx = tmpArr.findIndex(
  200. (user) =>
  201. user.userID === this.$store.getters.storeSelfInfo.userID,
  202. );
  203. if (idx > -1) {
  204. tmpArr.splice(idx, 1);
  205. }
  206. this.moments.likeUsers = [...tmpArr];
  207. } else {
  208. this.moments.likeUsers = [
  209. ...this.moments.likeUsers,
  210. {
  211. userID: this.$store.getters.storeSelfInfo.userID,
  212. nickname: this.$store.getters.storeSelfInfo.nickname,
  213. },
  214. ];
  215. }
  216. if (this.showDetails || this.inSingle) {
  217. uni.$emit(
  218. PageEvents.OperateLike,
  219. this.moments.workMomentID,
  220. !this.isLiked,
  221. this.showDetails,
  222. );
  223. }
  224. })
  225. .catch((err) => {
  226. console.log(err);
  227. });
  228. },
  229. toDetails() {
  230. if (!this.showDetails) {
  231. uni.$u.route("/pages_im/pages/moments/momentsDetails/index", {
  232. workMomentID: this.moments.workMomentID,
  233. });
  234. }
  235. },
  236. clickMediaItem(item) {
  237. uni.$u.route("/pages_im/pages/conversation/previewVideo/index", {
  238. previewVideoUrl: item.original,
  239. });
  240. },
  241. delteMoments() {
  242. uni.showModal({
  243. title: "提示",
  244. content: "确定要删除此条内容吗?",
  245. showCancel: true,
  246. confirmText: "确认",
  247. cancelText: "取消",
  248. success: (res) => {
  249. if (res.confirm) {
  250. deleteMoments(this.moments.workMomentID)
  251. .then(() => {
  252. uni.$emit(
  253. PageEvents.DeleteMoments,
  254. this.moments.workMomentID,
  255. this.showDetails,
  256. );
  257. toastWithCallback("删除成功!", uni.navigateBack);
  258. })
  259. .catch((err) => {
  260. uni.$u.toast("删除失败!");
  261. console.log(err);
  262. });
  263. }
  264. },
  265. });
  266. },
  267. deleteComent(commentID) {
  268. uni.showModal({
  269. title: "提示",
  270. content: "确定要删除此条评论吗?",
  271. showCancel: true,
  272. confirmText: "确认",
  273. cancelText: "取消",
  274. success: (res) => {
  275. if (res.confirm) {
  276. deleteComment(this.moments.workMomentID, commentID)
  277. .then(() => {
  278. const tmpArr = [...this.moments.comments];
  279. const idx = tmpArr.findIndex(
  280. (comment) => comment.commentID === commentID,
  281. );
  282. if (idx > -1) {
  283. tmpArr.splice(idx, 1);
  284. }
  285. this.moments.comments = [...tmpArr];
  286. if (this.showDetails || this.inSingle) {
  287. uni.$emit(
  288. PageEvents.DeleteComment,
  289. this.moments.workMomentID,
  290. commentID,
  291. this.showDetails,
  292. );
  293. }
  294. })
  295. .catch((err) => uni.$u.toast("删除失败!"));
  296. }
  297. },
  298. });
  299. },
  300. toPublisher() {
  301. if (!this.inSingle) {
  302. uni.$u.route("/pages_im/pages/common/userCard/index", {
  303. sourceID: this.moments.userID,
  304. });
  305. // uni.$u.route("/pages/moments/designatedMoments/index", {
  306. // baseUserInfo: JSON.stringify({
  307. // userID: this.moments.userID,
  308. // nickname: this.moments.nickname,
  309. // faceURL: this.moments.faceURL,
  310. // }),
  311. // });
  312. }
  313. },
  314. },
  315. };
  316. </script>
  317. <style lang="scss" scoped>
  318. .moments_item {
  319. display: flex;
  320. padding: 32rpx;
  321. background-color: #fff;
  322. border-bottom: 1px solid rgba(126, 134, 142, 0.16);
  323. .main_content {
  324. width: 100%;
  325. margin-left: 24rpx;
  326. .pusher {
  327. @include nomalEllipsis;
  328. max-width: 360rpx;
  329. font-size: 32rpx;
  330. font-weight: 500;
  331. color: #6085b1;
  332. margin-bottom: 8rpx;
  333. }
  334. .moments_text {
  335. @include ellipsisWithLine(5);
  336. color: #333;
  337. margin-bottom: 12rpx;
  338. }
  339. .moments_media {
  340. margin: 24rpx 0;
  341. }
  342. .grid_media {
  343. display: grid;
  344. grid-template-columns: 1fr 1fr 1fr;
  345. grid-gap: 10px;
  346. }
  347. .u-album {
  348. margin-bottom: 12rpx;
  349. /deep/.u-album__row__wrapper {
  350. border-radius: 8rpx;
  351. overflow: hidden;
  352. }
  353. }
  354. .time_line {
  355. position: relative;
  356. font-size: 24rpx;
  357. color: #a2a3a5;
  358. margin-bottom: 12rpx;
  359. text:nth-child(2) {
  360. color: #5a7b98;
  361. margin-left: 24rpx;
  362. }
  363. .limit_icon {
  364. width: 15px;
  365. height: 10px;
  366. padding: 0 12rpx;
  367. }
  368. .lock_icon {
  369. width: 9px;
  370. height: 11px;
  371. padding: 0 12rpx;
  372. }
  373. .action_icon {
  374. width: 18px;
  375. height: 12px;
  376. position: absolute;
  377. right: 0;
  378. top: 50%;
  379. transform: translateY(-50%);
  380. }
  381. }
  382. .at_list {
  383. font-size: 24rpx;
  384. color: #a2a3a4;
  385. margin-bottom: 12rpx;
  386. }
  387. .like_list {
  388. font-size: 24rpx;
  389. color: #5a7b98;
  390. margin-bottom: 12rpx;
  391. image {
  392. width: 12px;
  393. height: 12px;
  394. margin-right: 12rpx;
  395. }
  396. }
  397. }
  398. &:nth-child(2) {
  399. padding-top: 64rpx;
  400. }
  401. &:last-child {
  402. border: none;
  403. }
  404. }
  405. .more_menu {
  406. display: flex;
  407. position: absolute;
  408. z-index: 999;
  409. transform: translateY(-25%);
  410. width: max-content;
  411. border-radius: 6rpx;
  412. background-color: #5d5e61;
  413. box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.3);
  414. padding: 12rpx;
  415. .menu_item {
  416. display: flex;
  417. align-items: center;
  418. color: #fff;
  419. padding: 0 24rpx;
  420. image {
  421. width: 12px;
  422. height: 12px;
  423. margin-right: 12rpx;
  424. }
  425. &:first-child {
  426. border-right: 1px solid #575151;
  427. }
  428. }
  429. }
  430. </style>