ReviewBookInfo.vue 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. <template>
  2. <view class="book-info">
  3. <template v-if="isShow">
  4. <view class="font-bold mt-30 mb-30" style="padding: 0 20rpx">
  5. {{ bookList.length }}条记录,共{{ bookList.length }}本,已审{{ auditNum || 0 }}本
  6. </view>
  7. </template>
  8. <view class="book-info-item bg-white mt-12" :style="{ backgroundColor: item.backgroundColor }"
  9. v-for="item in formatList" :key="item.title" :id="item.id" v-show="item?.title">
  10. <view class="book-info-item-title">{{ item.title }}</view>
  11. <view class="book-info-item-list">
  12. <BookItem v-for="book in item.list" :key="book.bookId" :item="book" @click="handleBookClick(book)"
  13. type="review" />
  14. </view>
  15. </view>
  16. </view>
  17. </template>
  18. <script setup>
  19. import { ref, watch, computed } from "vue";
  20. import BookItem from "./BookItem.vue";
  21. import toPinyin from "@/utils/toPinyin.js";
  22. const props = defineProps({
  23. bookList: {
  24. type: Array,
  25. default: () => [],
  26. },
  27. detail: {
  28. type: Object,
  29. default: () => ({}),
  30. },
  31. isShow: {
  32. type: Boolean,
  33. default: true,
  34. },
  35. });
  36. const emit = defineEmits(["get-all-firstLetter"]);
  37. //计算已审书籍数量
  38. const auditNum = computed(() => {
  39. return props.bookList.filter((v) => !!v.auditReviewComment?.sts).length || 0;
  40. });
  41. function handleBookClick(book) {
  42. // if(book.auditReviewComment?.sts){
  43. // uni.$u.toast("该书已复审完成");
  44. // uni.$u.ttsModule.speak("该书已复审完成");
  45. // return;
  46. // }
  47. uni.navigateTo({
  48. url: `/pages/index/detail/review-book?isbn=${book.isbn}&orderId=${props.detail.orderId}&auditReviewId=${book.auditReviewComment?.auditReviewId || ''}&index=${book.auditReviewComment?.index ?? ''}`,
  49. });
  50. uni.setStorageSync("auditBook", book);
  51. }
  52. function getAuditCateNum(cate) {
  53. let auditList = [];
  54. props.bookList.forEach((v) => {
  55. auditList.push(...(v.detailReviewVoList || []));
  56. });
  57. return auditList.filter((v) => v.sts == cate).length;
  58. }
  59. function getBookFirstLetter(bookName) {
  60. if (!bookName) return "其他";
  61. let firstChineseChar = null;
  62. for (let i = 0; i < bookName.length; i++) {
  63. const char = bookName.charAt(i);
  64. if (/^[\u4E00-\u9FA5]$/.test(char)) {
  65. firstChineseChar = char;
  66. break;
  67. }
  68. }
  69. let firstLetter = "";
  70. if (firstChineseChar) {
  71. const pinyin = toPinyin.chineseToPinYin(firstChineseChar);
  72. firstLetter = toPinyin.chineseToInitials(pinyin);
  73. if (!firstLetter && pinyin) {
  74. firstLetter = pinyin.charAt(0).toUpperCase();
  75. }
  76. } else {
  77. const char = bookName.charAt(0);
  78. if (/^[A-Za-z]$/.test(char)) {
  79. firstLetter = char.toUpperCase();
  80. }
  81. }
  82. if (!firstLetter || !/^[A-Z]$/.test(firstLetter)) {
  83. firstLetter = "其他";
  84. }
  85. return firstLetter;
  86. }
  87. function isBookReviewed(book) {
  88. const sts = book.auditReviewComment?.sts;
  89. return sts != null && sts !== 0 && sts !== "0";
  90. }
  91. function getReviewSts(book) {
  92. return Number(book.auditReviewComment?.sts);
  93. }
  94. //格式化书籍列表
  95. const formatBookList = (list) => {
  96. const poorBooks = { title: "极差", list: [], backgroundColor: "#de868f", id: "poor" };
  97. const goodBooks = { title: "良好", list: [], backgroundColor: "#81b337", id: "good" };
  98. const otherBooks = [];
  99. const handleBookCategorization = (book) => {
  100. const firstLetter = getBookFirstLetter(book.bookName);
  101. let bool = otherBooks.some((item) => item.title == firstLetter);
  102. if (!bool) {
  103. otherBooks.push({ id: firstLetter, title: firstLetter, list: [{ ...book }] });
  104. } else {
  105. otherBooks.find((item) => item.title == firstLetter).list.push(book);
  106. }
  107. };
  108. list.forEach((book) => {
  109. if (isBookReviewed(book)) {
  110. const sts = getReviewSts(book);
  111. if (sts === 3) {
  112. poorBooks.list.push(book);
  113. } else if (sts === 1) {
  114. goodBooks.list.push(book);
  115. } else {
  116. handleBookCategorization(book);
  117. }
  118. } else {
  119. handleBookCategorization(book);
  120. }
  121. });
  122. return { poorBooks, goodBooks, otherBooks };
  123. };
  124. const formatList = ref([]);
  125. watch(
  126. () => props.bookList,
  127. (newVal) => {
  128. let { poorBooks, goodBooks, otherBooks } = formatBookList(newVal);
  129. // 按照首字母排序 A-Z
  130. otherBooks.sort((a, b) => a.id.localeCompare(b.id));
  131. let poor = poorBooks.list.length > 0 ? poorBooks : {};
  132. let good = goodBooks.list.length > 0 ? goodBooks : {};
  133. formatList.value = [...otherBooks, poor, good];
  134. emit("get-all-firstLetter", otherBooks.map((item) => item.id));
  135. },
  136. { immediate: true, deep: true }
  137. );
  138. </script>
  139. <style scoped>
  140. .book-info-item-title {
  141. padding: 10rpx 30rpx;
  142. font-size: 28rpx;
  143. font-weight: 600;
  144. border-bottom: 1px solid #e5e5e5;
  145. }
  146. </style>