yf-work-hours-allocation-list.vue 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. <template>
  2. <basic-container>
  3. <avue-crud
  4. v-bind="bindVal"
  5. v-on="onEvent"
  6. v-model="form"
  7. :page.sync="page"
  8. :header-cell-style="headerCellStyle"
  9. >
  10. <template slot="menuLeft">
  11. <el-button
  12. type="warning"
  13. size="small"
  14. plain
  15. icon="el-icon-download"
  16. @click="handleExport"
  17. >
  18. 导出
  19. </el-button>
  20. <!-- <print-table-btn @click="printTable" /> -->
  21. </template>
  22. <template slot="body">
  23. <h3 class="page-title">{{ pageTitle }}</h3>
  24. <year-month-select v-model="params.yearAndMonth" :showAllYear="false"></year-month-select>
  25. </template>
  26. <template slot="gslb">
  27. <div class="custom-cell">
  28. <div class="custom-cell-line">研发工时</div>
  29. <div class="custom-cell-line">非研发工时</div>
  30. </div>
  31. </template>
  32. <template v-for="col of allMonthCols" :slot="col" slot-scope="{ row }">
  33. <div class="custom-cell" :key="col">
  34. <div class="custom-cell-line">{{ row.dailyHoursList[0] ? row.dailyHoursList[0][col] : '' }}</div>
  35. <div class="custom-cell-line">{{ row.dailyHoursList[1] ? row.dailyHoursList[1][col] : '' }}</div>
  36. </div>
  37. </template>
  38. <template slot="hoursTotal" slot-scope="{ row }">
  39. <div class="custom-cell">
  40. <div class="custom-cell-line">{{ row.workHoursTotal }}</div>
  41. <div class="custom-cell-line">{{ row.unworkHoursTotal }}</div>
  42. </div>
  43. </template>
  44. <template slot="hoursRate" slot-scope="{ row }">
  45. <div class="custom-cell">
  46. <div class="custom-cell-line">{{ row.workHoursRate }}</div>
  47. <div class="custom-cell-line">{{ row.unworkHoursRate }}</div>
  48. </div>
  49. </template>
  50. </avue-crud>
  51. <WideTablePrinter
  52. ref="printWideTable"
  53. :columns="wideTableColumns"
  54. :data="data"
  55. :print-title="pageTitle"
  56. :rows-per-page="30"
  57. :default-landscape="true"
  58. />
  59. </basic-container>
  60. </template>
  61. <script>
  62. import YearMonthSelect from "@/components/year-month-select";
  63. import {exportBloByPost} from "@/api/common";
  64. import {getToken} from "@/util/auth";
  65. import {downloadXls} from "@/util/util";
  66. import { deepClone, getMonthDatesWithMarkers } from "@/util/util";
  67. import moment from "moment";
  68. import ChineseHoliday from "@chnlib/chinese-holiday";
  69. import { mapGetters } from "vuex";
  70. export default window.$crudCommon({
  71. components: {
  72. YearMonthSelect,
  73. },
  74. data() {
  75. return {
  76. params: {
  77. yearAndMonth: "",
  78. },
  79. defaultColumns: [],
  80. wideTableColumns: [],
  81. printTitle: "",
  82. allMonthCols: [],
  83. };
  84. },
  85. watch: {
  86. 'params.yearAndMonth'(newVal) {
  87. this.refreshTableCol(newVal);
  88. this.page.currentPage = 1;
  89. this.getList(this.page);
  90. }
  91. },
  92. computed: {
  93. ...mapGetters(['tag']),
  94. pageTitle() {
  95. let yearAndMonthCN = this.params.yearAndMonth ? moment(this.params.yearAndMonth).format('yyyy年MM月') : '';
  96. return `${yearAndMonthCN}${this.tag.label}`.replace(/每月/g, '')
  97. }
  98. },
  99. async created() {
  100. this.defaultColumns = deepClone(this.option.column);
  101. this.refreshTableCol(this.params.yearAndMonth);
  102. },
  103. beforeDestroy() {
  104. this.option.column = deepClone(this.defaultColumns);
  105. },
  106. methods: {
  107. refreshTableCol(yearAndMonth) {
  108. let yearMonth = moment(yearAndMonth).format("YYYY-MM").split("-");
  109. const monthDays = getMonthDatesWithMarkers(Number(yearMonth[0]), Number(yearMonth[1]));
  110. let newColumns = deepClone(this.defaultColumns);
  111. this.allMonthCols = [];
  112. monthDays.forEach((item) => {
  113. let col = {
  114. prop: moment(item.dateString).format('yyyyMMDD'),
  115. label: item.dayName + "" + item.day.toString(),
  116. type: 'number',
  117. precision: 1,
  118. min: 0,
  119. width: 50,
  120. align: 'center',
  121. isWorkDay: ChineseHoliday.isWorkday(item.dateString),
  122. showOverflowTooltip: true,
  123. }
  124. if (!ChineseHoliday.isWorkday(item.dateString)) {
  125. col.labelClassName = 'red';
  126. col.labelClassName = 'red';
  127. }
  128. newColumns.push(col);
  129. this.allMonthCols.push(moment(item.dateString).format('yyyyMMDD'));
  130. });
  131. newColumns.push({
  132. prop: "hoursTotal",
  133. label: "合计",
  134. width: 50,
  135. align: 'center',
  136. showOverflowTooltip: true,
  137. display: false,
  138. }, {
  139. prop: "hoursRate",
  140. label: "工时分配率",
  141. width: 60,
  142. align: 'center',
  143. showOverflowTooltip: true,
  144. display: false,
  145. });
  146. this.option.column = [...newColumns];
  147. },
  148. handleExport() {
  149. exportBloByPost(`/api/kd-scientific/xm/technician/hours/myyfgsfpb/export?${this.website.tokenHeader}=${getToken()}`, this.params).then(res => {
  150. downloadXls(res.data, `${this.pageTitle}.xlsx`);
  151. });
  152. },
  153. /**
  154. * 打印表格
  155. * @param isLandscape 是否横向打印
  156. */
  157. printTable(isLandscape) {
  158. this.wideTableColumns = this.$refs.crud.columnOption;
  159. this.$nextTick(() => {
  160. this.$refs.printWideTable.printTable(isLandscape);
  161. })
  162. },
  163. headerCellStyle ({ column }) {
  164. let color = column.labelClassName ? 'red' : 'rgba(0,0,0,.85)';
  165. return {
  166. color
  167. }
  168. }
  169. },
  170. }, {
  171. // 模块路径
  172. name: 'yfCostManage/yfCostStatistics/yfWorkHoursAllocationList',
  173. res: ({ data }) => {
  174. data.records = data.records.map(item => {
  175. if (item.dailyHoursList && item.dailyHoursList.length) {
  176. let newDailyHoursList = [
  177. {gslb: '研发工时', hoursTotal: item.workHoursTotal, hoursRate: (item.workHoursRate * 100).toFixed(2)},
  178. {gslb: '非研发工时', hourTotal: item.unworkHoursTotal, hoursRate: (item.unworkHoursRate * 100).toFixed(2)}
  179. ];
  180. item.dailyHoursList.forEach(hourItem => {
  181. newDailyHoursList[0][hourItem.workDate] = hourItem.workHours;
  182. newDailyHoursList[1][hourItem.workDate] = hourItem.unworkHours;
  183. });
  184. item.dailyHoursList = newDailyHoursList;
  185. item.workHoursRate = (item.workHoursRate * 100).toFixed(2);
  186. item.unworkHoursRate = (item.unworkHoursRate * 100).toFixed(2);
  187. }
  188. return item;
  189. });
  190. return data;
  191. },
  192. });
  193. </script>
  194. <style lang="scss" scoped>
  195. .custom-cell {
  196. margin: 0 -10px;
  197. &-line {
  198. border-bottom: 1px solid #EBEEF5;
  199. line-height: 24px;
  200. &:last-child {
  201. border-bottom: 0;
  202. }
  203. }
  204. }
  205. </style>