index.vue 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  1. <template>
  2. <ele-page flex-table>
  3. <page-search @search="reload" v-if="historyData == '1'" />
  4. <common-table ref="pageRef" :pageConfig="pageConfig" :columns="columns" :tools="false" show-summary
  5. :summary-method="getSummaries" :flex-table="false">
  6. <template #toolbar="{ row }">
  7. <div>
  8. <el-radio-group @change="handleStatusChange" v-model="historyData">
  9. <el-radio-button label="订单审核实时统计" value="0" />
  10. <el-radio-button label="订单审核历史统计" value="1" />
  11. </el-radio-group>
  12. <el-button style="margin-left: 40px" type="success" plain
  13. v-permission="'statistic:recycleOrder:export'" v-if="historyData == '1'"
  14. @click="handleExportExcel(row)">
  15. 导出EXCEL
  16. </el-button>
  17. </div>
  18. </template>
  19. </common-table>
  20. </ele-page>
  21. </template>
  22. <script setup>
  23. import { ref, reactive } from 'vue';
  24. import CommonTable from '@/components/CommonPage/CommonTable.vue';
  25. import pageSearch from './components/page-search.vue';
  26. defineOptions({ name: 'AuditOrder' });
  27. const historyData = ref('0');
  28. function handleStatusChange(val) {
  29. historyData.value = val;
  30. pageConfig.params = { historyData: val };
  31. pageRef.value?.reload();
  32. }
  33. /** 表格列配置 */
  34. const columns = ref([
  35. { type: 'index', label: '#', align: 'center', width: 80 },
  36. { label: '审核员', prop: 'nickName', align: 'center' },
  37. { label: '录入审核订单', prop: 'orderNum', align: 'center' },
  38. { label: '录入书籍数量', prop: 'bookNum', align: 'center' },
  39. { label: '实际回收数量', prop: 'recycleBookNum', align: 'center' },
  40. { label: '品相良好', prop: 'goodNum', align: 'center' },
  41. { label: '品相一般', prop: 'generalNum', align: 'center' },
  42. { label: '品相极差', prop: 'canRefundNum', align: 'center' },
  43. {
  44. label: '不良率',
  45. prop: 'badRate',
  46. align: 'center',
  47. formatter: (row) => {
  48. const rate = Number(row.badRate) || 0;
  49. return rate.toFixed(2) + '%';
  50. }
  51. },
  52. { label: '预估金额', prop: 'expectMoney', align: 'center' },
  53. { label: '审核金额', prop: 'finalMoney', align: 'center' },
  54. { label: '审核日期', prop: 'statDate', align: 'center' }
  55. ]);
  56. /** 页面组件实例 */
  57. const pageRef = ref(null);
  58. const pageConfig = reactive({
  59. pageUrl: '/order/ordercheck/stat/pagelist', // 默认使用实时统计接口
  60. params: { historyData: 0 }, // 默认查询实时数据
  61. exportUrl: '/order/ordercheck/stat/export',
  62. fileName: '审核统计',
  63. cacheKey: 'auditOrderTable'
  64. });
  65. /**
  66. * 自定义表格汇总计算方法
  67. * @param {Object} param0 - 表格数据和列信息
  68. * @returns {Array} - 汇总行显示的数据
  69. */
  70. function getSummaries({ columns, data }) {
  71. const sums = [];
  72. columns.forEach((column, index) => {
  73. if (index === 0) {
  74. sums[index] = '合计';
  75. return;
  76. }
  77. const values = data.map((item) => Number(item[column.property]));
  78. if (!values.length) {
  79. sums[index] = 'N/A';
  80. return;
  81. }
  82. switch (column.property) {
  83. case 'badRate': {
  84. // 不良率 = 品相极差总数 / 录入书籍总数
  85. const totalBadValues = data.map((item) =>
  86. Number(item.canRefundNum || 0)
  87. );
  88. const totalNumValues = data.map((item) =>
  89. Number(item.bookNum || 0)
  90. );
  91. const totalBadSum = totalBadValues.reduce((prev, curr) => {
  92. const value = Number(curr);
  93. if (!isNaN(value)) {
  94. return prev + value;
  95. } else {
  96. return prev;
  97. }
  98. }, 0);
  99. const totalNumSum = totalNumValues.reduce((prev, curr) => {
  100. const value = Number(curr);
  101. if (!isNaN(value)) {
  102. return prev + value;
  103. } else {
  104. return prev;
  105. }
  106. }, 0);
  107. if (totalNumSum > 0) {
  108. sums[index] =
  109. (totalBadSum / totalNumSum).toFixed(2) +
  110. '%';
  111. } else {
  112. sums[index] = '0.00%';
  113. }
  114. break;
  115. }
  116. case 'orderNum':
  117. case 'bookNum':
  118. case 'recycleBookNum':
  119. case 'goodNum':
  120. case 'generalNum':
  121. case 'canRefundNum': {
  122. // 数量类字段求和
  123. const sum = values.reduce((prev, curr) => {
  124. const value = Number(curr);
  125. if (!isNaN(value)) {
  126. return prev + value;
  127. } else {
  128. return prev;
  129. }
  130. }, 0);
  131. sums[index] = sum;
  132. break;
  133. }
  134. case 'expectMoney':
  135. case 'finalMoney': {
  136. // 金额类字段求和,保留两位小数
  137. const sum = values.reduce((prev, curr) => {
  138. const value = Number(curr);
  139. if (!isNaN(value)) {
  140. return prev + value;
  141. } else {
  142. return prev;
  143. }
  144. }, 0);
  145. sums[index] = sum.toFixed(2);
  146. break;
  147. }
  148. default:
  149. sums[index] = '';
  150. }
  151. });
  152. return sums;
  153. }
  154. //刷新表格
  155. function reload(where) {
  156. pageRef.value?.reload(where);
  157. }
  158. //导出excel
  159. function handleExportExcel() {
  160. pageRef.value?.exportData('审核统计');
  161. }
  162. </script>