working-hours-records.vue 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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. :before-open="handleBeforeOpen"
  9. :permission="permissionList"
  10. :header-cell-style="headerCellStyle"
  11. >
  12. <template slot="menuLeft">
  13. <el-button
  14. type="danger"
  15. size="small"
  16. icon="el-icon-delete"
  17. plain
  18. @click="handleDelete"
  19. >
  20. 清除工时数据
  21. </el-button>
  22. <el-button
  23. type="success"
  24. size="small"
  25. plain
  26. icon="el-icon-upload2"
  27. @click="handleImport"
  28. >
  29. 导入
  30. </el-button>
  31. <el-button
  32. type="warning"
  33. size="small"
  34. plain
  35. icon="el-icon-download"
  36. @click="handleExport"
  37. >
  38. 导出
  39. </el-button>
  40. <!-- <print-table-btn @click="printTable" /> -->
  41. <div style="display: flex; align-items: center;">
  42. <year-month-select v-model="params.yearAndMonth" :showAllYear="false"></year-month-select>
  43. </div>
  44. </template>
  45. <!-- <template slot="monthlyHoursSearch">
  46. <div style="display: flex; align-items: center;">
  47. <span>使用工时/小时:</span>
  48. <avue-input-number v-model="params.monthlyHoursStart" :min="0" style="width: 100px !important;"></avue-input-number>
  49. <span style="width: 20px; text-align: center;">至</span>
  50. <avue-input-number v-model="params.monthlyHoursEnd" :min="0" style="width: 100px !important;"></avue-input-number>
  51. </div>
  52. </template> -->
  53. </avue-crud>
  54. <upload-excel-dialog ref="uploadExcelDialog" :uploadAfter="uploadAfter"/>
  55. <WideTablePrinter
  56. ref="printWideTable"
  57. :columns="wideTableColumns"
  58. :data="data"
  59. :print-title="printTitle"
  60. :rows-per-page="30"
  61. :default-landscape="true"
  62. />
  63. </basic-container>
  64. </template>
  65. <script>
  66. import YearMonthSelect from "@/components/year-month-select";
  67. import UploadExcelDialog from "@/components/upload-excel-dialog";
  68. import {exportBlob} from "@/api/common";
  69. import {getToken} from "@/util/auth";
  70. import {downloadXls} from "@/util/util";
  71. import { deepClone, getMonthDatesWithMarkers } from "@/util/util";
  72. import moment from "moment";
  73. import ChineseHoliday from "@chnlib/chinese-holiday";
  74. export default window.$crudCommon({
  75. components: {
  76. YearMonthSelect,
  77. UploadExcelDialog,
  78. },
  79. data() {
  80. return {
  81. params: {
  82. yearAndMonth: moment(new Date()).format('YYYYMM'),
  83. },
  84. defaultColumns: [],
  85. oldMonthData: [],
  86. wideTableColumns: [],
  87. printTitle: "",
  88. };
  89. },
  90. watch: {
  91. 'params.yearAndMonth'(newVal) {
  92. this.refreshTableCol(newVal);
  93. this.page.currentPage = 1;
  94. this.getList(this.page);
  95. }
  96. },
  97. async created() {
  98. this.defaultColumns = deepClone(this.option.column);
  99. this.refreshTableCol(this.params.yearAndMonth);
  100. },
  101. beforeDestroy() {
  102. this.option.column = deepClone(this.defaultColumns);
  103. },
  104. methods: {
  105. handleBeforeOpen(done, type) {
  106. this.oldMonthData = this.form.dailyAttendances || [];
  107. done();
  108. },
  109. refreshTableCol(yearAndMonth) {
  110. let yearMonth = moment(yearAndMonth).format("YYYY-MM").split("-");
  111. const monthDays = getMonthDatesWithMarkers(Number(yearMonth[0]), Number(yearMonth[1]));
  112. let newColumns = deepClone(this.defaultColumns);
  113. monthDays.forEach(item => {
  114. let col = {
  115. prop: moment(item.dateString).format('yyyyMMDD'),
  116. label: item.dayName + "" + item.day.toString(),
  117. type: 'number',
  118. precision: 1,
  119. min: 0,
  120. width: 45,
  121. align: 'center',
  122. isWorkDay: ChineseHoliday.isWorkday(item.dateString),
  123. showOverflowTooltip: true,
  124. };
  125. if (!ChineseHoliday.isWorkday(item.dateString)) {
  126. col.labelClassName = 'red';
  127. col.labelClassName = 'red';
  128. }
  129. newColumns.push(col);
  130. });
  131. // newColumns.push({
  132. // prop: "monthlyHours",
  133. // label: "研发出勤/小时",
  134. // type: 'number',
  135. // precision: 1,
  136. // min: 0,
  137. // width: 70,
  138. // align: 'center',
  139. // showOverflowTooltip: true,
  140. // display: false,
  141. // search: true,
  142. // }, {
  143. // prop: "monthlyDays",
  144. // label: "研发出勤/天",
  145. // type: 'number',
  146. // precision: 1,
  147. // min: 0,
  148. // width: 70,
  149. // align: 'center',
  150. // showOverflowTooltip: true,
  151. // display: false,
  152. // });
  153. this.option.column = newColumns;
  154. },
  155. handleImport() {
  156. let excelParams = { yearAndMonth: this.params.yearAndMonth };
  157. this.$refs.uploadExcelDialog.open('/api/kd-scientific/xm/technician/hours/import', excelParams);
  158. },
  159. uploadAfter() {
  160. this.page.currentPage = 1;
  161. this.getList(this.page);
  162. },
  163. getFormData() {
  164. const newFormData = { ...this.form, yearAndMonth: this.params.yearAndMonth };
  165. let dailyAttendances = [];
  166. let _oldMonthData = this.oldMonthData;
  167. Object.keys(this.form).forEach(key => {
  168. if (key.indexOf(this.params.yearAndMonth) > -1) {
  169. let oldObj = _oldMonthData.find(old => old.workDate == key) || {};
  170. if (this.form[key] || oldObj.workHours || oldObj.workHours === 0) {
  171. let workHours = this.form[key];
  172. if (workHours === undefined || workHours === null || workHours === '') {
  173. workHours = null;
  174. }
  175. dailyAttendances.push({
  176. workDate: key,
  177. workHours
  178. });
  179. }
  180. delete newFormData[key];
  181. }
  182. });
  183. // 获取最新修改过的数据
  184. let updatedMonthData = [];
  185. dailyAttendances.forEach(item => {
  186. let oldObj = _oldMonthData.find(old => item.workDate === old.workDate);
  187. if (!!oldObj && item.workHours !== oldObj.workHours) {
  188. updatedMonthData.push(item);
  189. } else if (!oldObj) {
  190. updatedMonthData.push(item);
  191. }
  192. })
  193. newFormData.dailyAttendances = updatedMonthData;
  194. return newFormData;
  195. },
  196. getDelParams(row) {
  197. return { yearAndMonth: this.params.yearAndMonth, xmAndUnicodeList: [{ xmId: row.xmId, unicode: row.unicode }] };
  198. },
  199. getBatchDelParams() {
  200. let xmAndUnicodeList = [];
  201. this.data.forEach(item => {
  202. if (this.ids.indexOf(item.id) > -1) {
  203. xmAndUnicodeList.push({ xmId: item.xmId, unicode: item.unicode });
  204. }
  205. });
  206. return { yearAndMonth: this.params.yearAndMonth, xmAndUnicodeList };
  207. },
  208. handleExport() {
  209. exportBlob(`/api/kd-scientific/xm/technician/hours/export?${this.website.tokenHeader}=${getToken()}`, this.params).then(res => {
  210. downloadXls(res.data, `${this.params.yearAndMonth}研发人员工时记录表.xlsx`);
  211. });
  212. },
  213. /**
  214. * 打印表格
  215. * @param isLandscape 是否横向打印
  216. */
  217. printTable(isLandscape) {
  218. this.wideTableColumns = this.$refs.crud.columnOption;
  219. this.printTitle = `${this.params.yearAndMonth}研发人员工时记录表`;
  220. this.$nextTick(() => {
  221. this.$refs.printWideTable.printTable(isLandscape);
  222. })
  223. },
  224. headerCellStyle ({ column }) {
  225. let color = column.labelClassName ? 'red' : 'rgba(0,0,0,.85)';
  226. return {
  227. color
  228. }
  229. }
  230. },
  231. }, {
  232. // 模块路径
  233. name: 'yfCostManage/basicDataSetting/workHoursRecords',
  234. res: ({ data }) => {
  235. let newList = [];
  236. data.records.forEach((item) => {
  237. let objData = {
  238. ...item,
  239. id: item.unicode+'_'+item.xmId,
  240. monthlyHours: (item.monthlyHours || 0).toFixed(1),
  241. monthlyDays: (item.monthlyDays || 0).toFixed(1)
  242. };
  243. item.dailyAttendances.forEach(hourItem => {
  244. objData[hourItem.workDate] = (hourItem.workHours || 0).toFixed(1);
  245. });
  246. newList.push(objData);
  247. });
  248. data.records = newList;
  249. return data;
  250. },
  251. });
  252. </script>