Comment.vue 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162
  1. <template>
  2. <Drawer v-model:visible="show" title="评论" @close="emits('close')">
  3. <div class="comment">
  4. <template v-if="isLogin">
  5. <el-input
  6. v-model="message"
  7. type="textarea"
  8. :autosize="{ minRows: 8 }"
  9. placeholder="请留下您的评论,最多200字"
  10. :maxlength="200"
  11. show-word-limit
  12. />
  13. <el-button
  14. :loading="btnLoading"
  15. type="primary"
  16. style="margin: 10px 0 70px; width: 100%; height: 50px"
  17. @click="handleSubmit"
  18. >发表</el-button
  19. >
  20. </template>
  21. <el-empty v-if="noData" description="暂无数据" />
  22. <div class="comment-list" v-infinite-scroll="load">
  23. <div v-for="(item, idx) in list" :key="item.id" class="comment-item">
  24. <div class="comment-item-header">
  25. <p>{{ item.createBy }}</p>
  26. <p class="comment-item-header__date">{{ item.createTime }}</p>
  27. <svg-icon
  28. v-if="item.creatorId === userInfo.id"
  29. class="comment-item-header__del"
  30. name="icon_delete"
  31. width="16px"
  32. height="16px"
  33. color="var(--el-color-primary)"
  34. @click="handleDelete(item, idx)"
  35. />
  36. </div>
  37. <p class="comment-item__inner">
  38. {{ item.content }}
  39. </p>
  40. </div>
  41. </div>
  42. </div>
  43. </Drawer>
  44. </template>
  45. <script setup>
  46. import { computed, ref } from "vue";
  47. import { usePagination } from "@lsq/base";
  48. import { getMessageListApi, saveMessageApi, deleteMessageApi } from "@/api";
  49. import Drawer from "./Drawer.vue";
  50. import { useBaseStore, useDetailStore } from "@/stores";
  51. import { storeToRefs } from "pinia";
  52. const props = defineProps(["visible"]);
  53. const emits = defineEmits(["update:visible", "close"]);
  54. const baseStore = useBaseStore();
  55. const detailStore = useDetailStore();
  56. const btnLoading = ref(false);
  57. const message = ref("");
  58. const { isLogin, userInfo } = storeToRefs(baseStore);
  59. const { pageNum, loading, list, noData, noMore, getList } = usePagination(
  60. async (params) => {
  61. return getMessageListApi({
  62. ...params,
  63. auditStatus: 1,
  64. bookId: detailStore.detail.id,
  65. });
  66. }
  67. );
  68. const show = computed({
  69. get() {
  70. return props.visible;
  71. },
  72. set(v) {
  73. emits("update:visible", v);
  74. },
  75. });
  76. const load = () => {
  77. if (!noMore.value && !loading.value) {
  78. getList();
  79. pageNum.value++;
  80. }
  81. };
  82. const handleSubmit = async () => {
  83. try {
  84. btnLoading.value = true;
  85. await saveMessageApi({
  86. bookId: detailStore.detail.id,
  87. createBy: userInfo.value.nickName,
  88. content: message.value,
  89. });
  90. ElMessage.success("提交成功,等待审核");
  91. message.value = "";
  92. } finally {
  93. btnLoading.value = false;
  94. }
  95. };
  96. const handleDelete = async (item, idx) => {
  97. ElMessageBox.confirm("确认是否删除?", "提示", {
  98. confirmButtonText: "确定",
  99. cancelButtonText: "取消",
  100. type: "warning",
  101. beforeClose: async (action, instance, done) => {
  102. if (action === "confirm") {
  103. try {
  104. instance.confirmButtonLoading = true;
  105. await deleteMessageApi(item.id);
  106. list.value.splice(idx, 1);
  107. done();
  108. } finally {
  109. instance.confirmButtonLoading = false;
  110. }
  111. } else {
  112. done();
  113. }
  114. },
  115. });
  116. };
  117. </script>
  118. <style lang="scss" scoped>
  119. .comment {
  120. padding: 0 25px;
  121. &-item {
  122. &:not(:last-child) {
  123. margin-bottom: 20px;
  124. border-bottom: 1px solid #d9d9d9;
  125. }
  126. &-header {
  127. display: flex;
  128. align-items: center;
  129. gap: 12px;
  130. p {
  131. opacity: 0.5;
  132. }
  133. &__date {
  134. flex: 1;
  135. text-align: right;
  136. }
  137. &__del {
  138. position: relative;
  139. top: -2px;
  140. cursor: pointer;
  141. }
  142. }
  143. &__inner {
  144. margin: 8px 0 25px;
  145. padding-left: 12px;
  146. border-left: 5px solid var(--el-color-primary);
  147. }
  148. }
  149. }
  150. </style>