ReviewBookInfo.vue 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  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. //格式化书籍列表
  60. const formatBookList = (list) => {
  61. const poorBooks = { title: "极差", list: [], backgroundColor: "#de868f", id: "poor" };
  62. const goodBooks = { title: "良好", list: [], backgroundColor: "#81b337", id: "good" };
  63. const otherBooks = [];
  64. //获取所有的首字母
  65. const allFirstLetter = [];
  66. const handleBookCategorization = (book) => {
  67. let firstLetter;
  68. // 找到第一个中文
  69. let firstChineseChar = null;
  70. for (let i = 0; i < book.bookName.length; i++) {
  71. const char = book.bookName.charAt(i);
  72. if (/^[\u4E00-\u9FA5]$/.test(char)) {
  73. // 检查是否为中文
  74. firstChineseChar = char;
  75. break;
  76. }
  77. }
  78. // 如果找到中文,使用其拼音首字母
  79. if (firstChineseChar) {
  80. firstLetter = toPinyin.chineseToInitials(toPinyin.chineseToPinYin(firstChineseChar));
  81. } else {
  82. // 如果没有找到中文,使用第一个字符
  83. const char = book.bookName.charAt(0);
  84. if (/^[A-Za-z]$/.test(char)) {
  85. firstLetter = char.toUpperCase();
  86. } else {
  87. firstLetter = char;
  88. }
  89. }
  90. let bool = otherBooks.some((item) => item.title == firstLetter);
  91. if (!bool) {
  92. otherBooks.push({ id: firstLetter, title: firstLetter, list: [{ ...book }] });
  93. allFirstLetter.push(firstLetter);
  94. emit("get-all-firstLetter", allFirstLetter);
  95. } else {
  96. otherBooks.find((item) => item.title == firstLetter).list.push(book);
  97. }
  98. };
  99. list.forEach((book) => {
  100. book.goodNum = list?.filter((v) => v.sts == 1).length || 0;
  101. book.badNum = list?.filter((v) => v.sts == 3).length || 0;
  102. // Check if book is fully audited (all items have been reviewed)
  103. const totalAudited = list?.filter((v) => v.sts !== 0).length || 0;
  104. const isFullyAudited = totalAudited === list.length;
  105. if (isFullyAudited) {
  106. if (book.auditReviewComment?.sts === 3) {
  107. poorBooks.list.push(book);
  108. } else if (book.auditReviewComment?.sts === 1) {
  109. goodBooks.list.push(book);
  110. } else {
  111. handleBookCategorization(book);
  112. }
  113. } else {
  114. handleBookCategorization(book);
  115. }
  116. });
  117. return { poorBooks, goodBooks, otherBooks };
  118. };
  119. const formatList = ref([]);
  120. watch(
  121. () => props.bookList,
  122. (newVal) => {
  123. let { poorBooks, goodBooks, otherBooks } = formatBookList(newVal);
  124. // 按照首字母排序 A-Z
  125. otherBooks.sort((a, b) => a.id.localeCompare(b.id));
  126. let poor = poorBooks.list.length > 0 ? poorBooks : {};
  127. let good = goodBooks.list.length > 0 ? goodBooks : {};
  128. formatList.value = [...otherBooks, poor, good];
  129. },
  130. { immediate: true, deep: true }
  131. );
  132. </script>
  133. <style scoped>
  134. .book-info-item-title {
  135. padding: 10rpx 30rpx;
  136. font-size: 28rpx;
  137. font-weight: 600;
  138. border-bottom: 1px solid #e5e5e5;
  139. }
  140. </style>