OrderSummaryTableNew.vue 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. <!-- src/components/OrderSummaryTable.vue -->
  2. <template>
  3. <div class="table-container">
  4. <h3 class="table-title">{{ title }}</h3>
  5. <el-table
  6. :data="processedTableData"
  7. border
  8. stripe
  9. style="width: 100%; margin-top: 20px;"
  10. :span-method="objectSpanMethod"
  11. show-summary
  12. height="500"
  13. >
  14. <el-table-column prop="name" :label="nameLable" min-width="70" class-name="sticky-column" align="center">
  15. <template slot-scope="scope">
  16. <span :class="{'group-name': scope.row.isGroup}">{{ scope.row.name }}</span>
  17. </template>
  18. </el-table-column>
  19. <el-table-column prop="totalCalls" label="总单数" min-width="40" align="center"></el-table-column>
  20. <el-table-column prop="totalAmount" label="总金额" min-width="70" align="center">
  21. <template slot-scope="scope">
  22. {{ scope.row.totalAmount ? scope.row.totalAmount.toFixed(2) : '0.00' }}
  23. </template>
  24. </el-table-column>
  25. <el-table-column prop="validAmount" label="成单金额" min-width="70" align="center">
  26. <template slot-scope="scope">
  27. {{ scope.row.validAmount ? scope.row.validAmount.toFixed(2) : '0.00' }}
  28. </template>
  29. </el-table-column>
  30. <el-table-column prop="waitingOrders" label="待审数" min-width="40" align="center"></el-table-column>
  31. <el-table-column prop="waitingAmount" label="待审金额" min-width="70" align="center">
  32. <template slot-scope="scope">
  33. {{ scope.row.waitingAmount ? scope.row.waitingAmount.toFixed(2) : '0.00' }}
  34. </template>
  35. </el-table-column>
  36. <el-table-column prop="unPassedOrders" label="未过数" min-width="40" align="center"></el-table-column>
  37. <el-table-column prop="unPassedAmount" label="未过金额" min-width="70" align="center">
  38. <template slot-scope="scope">
  39. {{ scope.row.unpassedAmount ? scope.row.unpassedAmount.toFixed(2) : '0.00' }}
  40. </template>
  41. </el-table-column>
  42. <el-table-column prop="cancelOrders" label="取消数" min-width="40" align="center"></el-table-column>
  43. <el-table-column prop="cancelAmount" label="取消金额" min-width="70" align="center">
  44. <template slot-scope="scope">
  45. {{ scope.row.cancelAmount ? scope.row.cancelAmount.toFixed(2) : '0.00' }}
  46. </template>
  47. </el-table-column>
  48. <el-table-column prop="completeOrders" label="成交数" min-width="40" align="center"></el-table-column>
  49. <el-table-column prop="completeAmount" label="成交金额" min-width="70" align="center">
  50. <template slot-scope="scope">
  51. {{ scope.row.completeAmount ? scope.row.completeAmount.toFixed(2) : '0.00' }}
  52. </template>
  53. </el-table-column>
  54. <el-table-column prop="unshippedOrders" label="成交未发货数" min-width="40" align="center"></el-table-column>
  55. <el-table-column prop="unshippedAmount" label="成交未发货金额" min-width="70" align="center">
  56. <template slot-scope="scope">
  57. {{ scope.row.unshippedAmount ? scope.row.unshippedAmount.toFixed(2) : '0.00' }}
  58. </template>
  59. </el-table-column>
  60. <el-table-column prop="shippedOrders" label="发货数" min-width="40" align="center"></el-table-column>
  61. <el-table-column prop="shippedAmount" label="发货金额" min-width="70" align="center">
  62. <template slot-scope="scope">
  63. {{ scope.row.shippedAmount ? scope.row.shippedAmount.toFixed(2) : '0.00' }}
  64. </template>
  65. </el-table-column>
  66. <el-table-column prop="transitOrders" label="在途数" min-width="40" align="center"></el-table-column>
  67. <el-table-column prop="transitAmount" label="在途金额" min-width="70" align="center">
  68. <template slot-scope="scope">
  69. {{ scope.row.transitAmount ? scope.row.transitAmount.toFixed(2) : '0.00' }}
  70. </template>
  71. </el-table-column>
  72. <el-table-column prop="receivedOrders" label="签收数" min-width="40" align="center"></el-table-column>
  73. <el-table-column prop="receivedAmount" label="签收金额" min-width="70" align="center">
  74. <template slot-scope="scope">
  75. {{ scope.row.receivedAmount ? scope.row.receivedAmount.toFixed(2) : '0.00' }}
  76. </template>
  77. </el-table-column>
  78. <el-table-column prop="returnOrders" label="退货数" min-width="40" align="center"></el-table-column>
  79. <el-table-column prop="returnAmount" label="退货金额" min-width="70" align="center">
  80. <template slot-scope="scope">
  81. {{ scope.row.returnAmount ? scope.row.returnAmount.toFixed(2) : '0.00' }}
  82. </template>
  83. </el-table-column>
  84. <el-table-column prop="paybackOrders" label="回款数" min-width="40" align="center"></el-table-column>
  85. <el-table-column prop="paybackAmount" label="回款金额" min-width="70" align="center">
  86. <template slot-scope="scope">
  87. {{ scope.row.paybackAmount ? scope.row.paybackAmount.toFixed(2) : '0.00' }}
  88. </template>
  89. </el-table-column>
  90. </el-table>
  91. </div>
  92. </template>
  93. <script>
  94. export default {
  95. name: 'OrderSummaryTableNew',
  96. props: {
  97. title: {
  98. type: String,
  99. required: true
  100. },
  101. tableData: {
  102. type: Array,
  103. default: () => []
  104. },
  105. nameLable: {
  106. type: String,
  107. default: '姓名/工号'
  108. }
  109. },
  110. data() {
  111. return {
  112. tableKey: 0
  113. }
  114. },
  115. computed: {
  116. // 添加处理后的数据计算属性
  117. processedTableData() {
  118. if (!this.tableData || this.tableData.length === 0) {
  119. return [];
  120. }
  121. // 按部门分组数据处理逻辑
  122. const result = [];
  123. const deptMap = new Map();
  124. // 分组数据
  125. this.tableData.forEach(item => {
  126. const deptName = item.groupName || '未分配部门';
  127. if (!deptMap.has(deptName)) {
  128. deptMap.set(deptName, []);
  129. }
  130. deptMap.get(deptName).push(item);
  131. });
  132. // 构建展示数据
  133. for (const [deptName, employees] of deptMap) {
  134. // 部门标题行
  135. result.push({
  136. name: deptName,
  137. isGroup: true,
  138. isDeptTitle: true
  139. });
  140. // 员工数据行
  141. employees.forEach(emp => {
  142. result.push({ ...emp });
  143. });
  144. // 部门小计行
  145. const deptSummary = this.calculateDeptSummary(employees, deptName);
  146. result.push(deptSummary);
  147. }
  148. // 添加总计行
  149. const totalSummary = this.calculateTotalSummary();
  150. result.push(totalSummary);
  151. return result;
  152. }
  153. },
  154. methods: {
  155. // 添加表格合并方法
  156. objectSpanMethod({ row, column, rowIndex, columnIndex }) {
  157. // 部门标题行合并
  158. if (row.isDeptTitle) {
  159. if (columnIndex === 0) {
  160. // 第一列显示部门名称,合并所有列
  161. const totalColumns = 24;
  162. return [1, totalColumns];
  163. } else {
  164. // 其他列不显示
  165. return [0, 0];
  166. }
  167. }
  168. // 部门小计行合并
  169. if (row.isDeptSummary) {
  170. if (columnIndex === 0) {
  171. // 第一列显示小计文本
  172. return [1, 1];
  173. }
  174. // 其他列正常显示数据
  175. return [1, 1];
  176. }
  177. // 总计行合并
  178. if (row.isTotalSummary) {
  179. if (columnIndex === 0) {
  180. // 第一列显示总计文本
  181. return [1, 1];
  182. }
  183. // 其他列正常显示数据
  184. return [1, 1];
  185. }
  186. // 普通行
  187. return [1, 1];
  188. },
  189. // 计算部门小计
  190. calculateDeptSummary(employees, deptName) {
  191. const summary = {
  192. name: `${deptName} 小计`,
  193. isGroup: true,
  194. isDeptSummary: true
  195. };
  196. const sumFields = ['totalCalls', 'totalAmount', 'validAmount', 'waitingOrders', 'waitingAmount',
  197. 'unPassedOrders', 'unPassedAmount', 'cancelOrders', 'cancelAmount', 'completeOrders',
  198. 'completeAmount', 'unshippedOrders', 'unshippedAmount', 'shippedOrders', 'shippedAmount',
  199. 'transitOrders', 'transitAmount', 'receivedOrders', 'receivedAmount', 'returnOrders',
  200. 'returnAmount', 'paybackOrders', 'paybackAmount'];
  201. sumFields.forEach(field => {
  202. summary[field] = employees.reduce((sum, emp) => sum + (Number(emp[field]) || 0), 0);
  203. });
  204. return summary;
  205. },
  206. // 计算总计
  207. calculateTotalSummary() {
  208. const summary = {
  209. name: '总计',
  210. isGroup: true,
  211. isTotalSummary: true
  212. };
  213. const sumFields = ['totalCalls', 'totalAmount', 'validAmount', 'waitingOrders', 'waitingAmount',
  214. 'unPassedOrders', 'unPassedAmount', 'cancelOrders', 'cancelAmount', 'completeOrders',
  215. 'completeAmount', 'unshippedOrders', 'unshippedAmount', 'shippedOrders', 'shippedAmount',
  216. 'transitOrders', 'transitAmount', 'receivedOrders', 'receivedAmount', 'returnOrders',
  217. 'returnAmount', 'paybackOrders', 'paybackAmount'];
  218. // 从原始数据计算总计(排除部门标题和小计行)
  219. const validData = this.tableData.filter(item => !item.isGroup);
  220. sumFields.forEach(field => {
  221. summary[field] = validData.reduce((sum, item) => sum + (Number(item[field]) || 0), 0);
  222. });
  223. return summary;
  224. }
  225. }
  226. }
  227. </script>
  228. <style scoped>
  229. /* .table-container {
  230. margin-top: 30px;
  231. } */
  232. .table-title {
  233. font-size: 16px;
  234. font-weight: bold;
  235. color: #333;
  236. margin-bottom: 10px;
  237. }
  238. </style>