BookInfo.vue 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. <template>
  2. <view class="book-info">
  3. <template v-if="isShow">
  4. <view class="font-bold mt-12 mb-10" style="padding: 0 20rpx">
  5. {{ bookList.length }}条记录,共{{ detail.totalNum }}本,已审{{ auditNum || 0 }}本
  6. </view>
  7. <view class="font-light" style="padding: 0 20rpx">
  8. 其中已审:良好{{ getAuditCateNum(1) }}本,一般0本,极差{{ getAuditCateNum(3) }}本
  9. </view>
  10. </template>
  11. <view class="book-info-item bg-white mt-12" :style="{ backgroundColor: item.backgroundColor }"
  12. v-for="item in formatList" :key="item.title" :id="item.id" v-show="item?.title">
  13. <view class="book-info-item-title">{{ item.title }}</view>
  14. <view class="book-info-item-list">
  15. <BookItem v-for="book in item.list" :key="book.bookId" :item="book" @click="handleBookClick(book)" />
  16. </view>
  17. </view>
  18. </view>
  19. </template>
  20. <script setup>
  21. import { ref, watch, computed } from 'vue';
  22. import BookItem from './BookItem.vue';
  23. import toPinyin from "@/utils/toPinyin.js"
  24. const props = defineProps({
  25. bookList: {
  26. type: Array,
  27. default: () => [],
  28. },
  29. detail: {
  30. type: Object,
  31. default: () => ({})
  32. },
  33. isShow: {
  34. type: Boolean,
  35. default: true
  36. }
  37. })
  38. const emit = defineEmits(['get-all-firstLetter'])
  39. //计算已审书籍数量
  40. const auditNum = computed(() => {
  41. return props.bookList.reduce((total, item) => total + item.auditCommentList?.length || 0, 0)
  42. })
  43. function handleBookClick(book) {
  44. if (props.detail.status >= 10) {
  45. uni.$u.ttsModule.speak('订单已审核完成')
  46. return
  47. }
  48. uni.navigateTo({
  49. url: `/pages/index/detail/book-audit?isbn=${book.isbn}&orderId=${props.detail.orderId}`
  50. })
  51. uni.setStorageSync('auditBook', book)
  52. }
  53. function getAuditCateNum(cate) {
  54. let auditList = []
  55. props.bookList.forEach(v => {
  56. auditList.push(...(v.auditCommentList || []))
  57. })
  58. return auditList.filter(v => v.sts == cate).length
  59. }
  60. //格式化书籍列表
  61. const formatBookList = (list) => {
  62. const poorBooks = { title: '极差', list: [], backgroundColor: '#de868f', id: 'poor' };
  63. const goodBooks = { title: '良好', list: [], backgroundColor: '#81b337', id: 'good' };
  64. const otherBooks = [];
  65. //获取所有的首字母
  66. const allFirstLetter = [];
  67. const handleBookCategorization = (book) => {
  68. let firstLetter;
  69. // 找到第一个中文
  70. let firstChineseChar = null;
  71. for (let i = 0; i < book.bookName.length; i++) {
  72. const char = book.bookName.charAt(i);
  73. if (/^[\u4E00-\u9FA5]$/.test(char)) { // 检查是否为中文
  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 = book.auditCommentList?.filter(v => v.sts == 1).length || 0
  101. book.badNum = book.auditCommentList?.filter(v => v.sts == 3).length || 0
  102. // Check if book is fully audited (all items have been reviewed)
  103. const totalAudited = book.auditCommentList?.filter(v => v.sts !== 0).length || 0;
  104. const isFullyAudited = totalAudited === book.num;
  105. if (isFullyAudited) {
  106. // If any audit result is poor (sts === 3), push to poorBooks
  107. if (book.auditCommentList.some(v => v.sts === 3)) {
  108. poorBooks.list.push(book);
  109. } else if (book.auditCommentList.every(v => v.sts === 1)) {
  110. // If all audit results are good (sts === 1), push to goodBooks
  111. goodBooks.list.push(book);
  112. } else {
  113. handleBookCategorization(book);
  114. }
  115. } else {
  116. handleBookCategorization(book);
  117. }
  118. });
  119. return { poorBooks, goodBooks, otherBooks };
  120. }
  121. const formatList = ref([]);
  122. watch(() => props.bookList, (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. }, { immediate: true, deep: true });
  130. </script>
  131. <style scoped>
  132. .book-info-item-title {
  133. padding: 10rpx 30rpx;
  134. font-size: 28rpx;
  135. font-weight: 600;
  136. border-bottom: 1px solid #e5e5e5;
  137. }
  138. </style>