SalaryConfirmationPDF.vue 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. <template>
  2. <div>
  3. <div id="pdfDom" ref="pdfDom" style="padding: 20px 20px 0; text-align: center;font-size:12px;color:#333333" v-loading="loading">
  4. <table border="1" style="width: 100%" class="table">
  5. <tr>
  6. <td :colspan="salaryStructureData.length+3" class="title">薪资确认单</td>
  7. </tr>
  8. <tr>
  9. <td colspan="2">所属主体</td>
  10. <td colspan="2">{{pdfData.companyName}}</td>
  11. <td colspan="1">部门</td>
  12. <td colspan="2">{{pdfData.deptName}}</td>
  13. <td colspan="1">入职日期</td>
  14. <td colspan="2">{{pdfData.entryDate}}</td>
  15. </tr>
  16. <tr>
  17. <td colspan="2">员工姓名</td>
  18. <td colspan="2">{{pdfData.nickName}}</td>
  19. <td colspan="1">岗位</td>
  20. <td colspan="2">{{pdfData.post}}</td>
  21. <td colspan="1">生效日期</td>
  22. <td colspan="2">{{pdfData.effectiveDate}}</td>
  23. </tr>
  24. <tr>
  25. <td colspan="2">学历</td>
  26. <td colspan="2">{{pdfData.education}}</td>
  27. <td colspan="1">试用期限</td>
  28. <td colspan="2">{{pdfData.probationPeriod}}</td>
  29. <td colspan="1">转正日期</td>
  30. <td colspan="2">{{pdfData.fullTimeDate}}</td>
  31. </tr>
  32. <tr>
  33. <td colspan="2">
  34. 上班时长
  35. </td>
  36. <td :colspan="salaryStructureData.length+3-2" style="text-align:left">
  37. 月休{{pdfData.monthRest}}天,{{pdfData.dailyHours}}小时/天(上午{{pdfData.morningBeginTime}}至{{pdfData.morningEndTime}}
  38. ;下午{{pdfData.afternoonBeginTime}}至{{pdfData.afternoonEndTime}}
  39. )</td>
  40. </tr>
  41. <tr>
  42. <td rowspan="5" style="width:5%">
  43. 薪资
  44. </td>
  45. <td :colspan="salaryStructureData.length+2">
  46. 考勤结算 or 业绩/记件结算
  47. </td>
  48. </tr>
  49. <tr>
  50. <td rowspan="2" style="width:5%">考勤结算</td>
  51. <td v-for="col in salaryStructureData" :key="col.value" :style="`width:${parseFloat(80/salaryStructureData.length).toFixed(2)}%`">
  52. {{col.label}}
  53. </td>
  54. <td style="width:10%">合计</td>
  55. </tr>
  56. <tr>
  57. <td v-for="col in salaryStructureData" :key="col.value" :style="`width:${parseFloat(80/salaryStructureData.length).toFixed(2)}%`">
  58. <el-input-number onmousewheel="return false;" v-model="pdfData.salaryData[col.value+'-10']" placeholder=" " style="width: 100%"
  59. :precision="2" :controls="false" :min="0" @change="changeAmount('10')" />
  60. </td>
  61. <td>{{pdfData.amount}}</td>
  62. </tr>
  63. <tr>
  64. <td rowspan="2">业绩/记件结算</td>
  65. <td v-for="col in salaryStructureData" :key="col.value">
  66. {{col.label}}
  67. </td>
  68. <td>合计</td>
  69. </tr>
  70. <tr>
  71. <td v-for="col in salaryStructureData" :key="col.value">
  72. <el-input-number onmousewheel="return false;" v-model="pdfData.salaryData[col.value+'-20']" placeholder=" " style="width: 100%"
  73. :precision="2" :controls="false" :min="0" @change="changeAmount('20')" />
  74. </td>
  75. <td>{{pdfData.perfAmount}}</td>
  76. </tr>
  77. <tr>
  78. <td colspan="2">
  79. 薪资说明
  80. </td>
  81. <td :colspan="salaryStructureData.length+3-2" style="text-align:left">{{pdfData.salaryRemark}}</td>
  82. </tr>
  83. <tr>
  84. <td colspan="2">
  85. 员工签字
  86. </td>
  87. <td colspan="3"></td>
  88. <td colspan="1">
  89. 主管签字
  90. </td>
  91. <td colspan="4"></td>
  92. </tr>
  93. <tr>
  94. <td colspan="2">
  95. 副总审批
  96. </td>
  97. <td colspan="3"></td>
  98. <td colspan="1">
  99. 总经理审批
  100. </td>
  101. <td colspan="4"></td>
  102. </tr>
  103. </table>
  104. </div>
  105. <div style="text-align: center;margin-top:20px">
  106. <el-button type="primary" v-print="printObj" size="default" v-debounce>打印</el-button>
  107. <el-button type="primary" @click="clickDownload()" size="default" v-debounce>下载PDF</el-button>
  108. <el-button type="primary" @click="exportExcel()" size="default" v-debounce>导出Excel</el-button>
  109. <el-button type="primary" @click="saveData()" size="default" v-debounce>保存</el-button>
  110. </div>
  111. </div>
  112. </template>
  113. <script setup>
  114. import $ from "jquery";
  115. const { proxy } = getCurrentInstance();
  116. const pdfData = ref({});
  117. const props = defineProps({
  118. rowData: Object,
  119. });
  120. const salaryStructureData = ref([]);
  121. const getData = () => {
  122. proxy
  123. .post("/salaryStructure/page", {
  124. pageNum: 1,
  125. pageSize: 999,
  126. })
  127. .then((res) => {
  128. salaryStructureData.value = res.rows
  129. .map((item) => {
  130. return {
  131. label: item.name,
  132. value: item.id,
  133. };
  134. })
  135. .reverse();
  136. });
  137. };
  138. getData();
  139. const loading = ref(false);
  140. const getPdfData = (query) => {
  141. loading.value = true;
  142. proxy.post("/userSalaryManage/detail", query).then((res) => {
  143. res.salaryData = {};
  144. if (res.userSalaryDetailList && res.userSalaryDetailList.length > 0) {
  145. for (let i = 0; i < res.userSalaryDetailList.length; i++) {
  146. const row = res.userSalaryDetailList[i];
  147. res.salaryData[row.salaryStructureId + "-" + row.type] = row.money;
  148. }
  149. }
  150. console.log(res.salaryData);
  151. pdfData.value = res;
  152. loading.value = false;
  153. });
  154. };
  155. watch(
  156. () => props.rowData,
  157. (val) => {
  158. if (props.rowData.id) {
  159. getPdfData({ userId: props.rowData.id });
  160. }
  161. },
  162. {
  163. immediate: true,
  164. deep: true,
  165. }
  166. );
  167. const printObj = ref({
  168. id: "pdfDom",
  169. popTitle: "",
  170. extraCss:
  171. "https://cdn.bootcdn.net/ajax/libs/animate.css/4.1.1/animate.compat.css, https://cdn.bootcdn.net/ajax/libs/hover.css/2.3.1/css/hover-min.css",
  172. extraHead: '<meta http-equiv="Content-Language"content="zh-cn"/>',
  173. });
  174. const clickDownload = () => {
  175. proxy.getPdf("薪资确认单PDF文件");
  176. };
  177. const pdfDom = ref(null);
  178. const exportExcel = () => {
  179. // pdfDom.value.exportExcel();
  180. // isShowImg.value = false;
  181. loading.value = true;
  182. setTimeout(() => {
  183. $("#pdfDom").table2excel({
  184. exclude: ".noExl",
  185. sheetName: `${pdfData.value.nickName} 薪资确认单`,
  186. filename: `${pdfData.value.nickName} 薪资确认单`,
  187. exclude_img: false,
  188. exclude_links: false,
  189. exclude_inputs: true,
  190. });
  191. // isShowImg.value = true;
  192. loading.value = false;
  193. }, 500);
  194. };
  195. const saveData = () => {
  196. let userSalaryDetailList = [];
  197. for (const key in pdfData.value.salaryData) {
  198. let arr = key.split("-");
  199. userSalaryDetailList.push({
  200. salaryStructureId: arr[0],
  201. type: arr[1],
  202. money: pdfData.value.salaryData[key],
  203. });
  204. }
  205. pdfData.value.userSalaryDetailList = userSalaryDetailList;
  206. proxy.post("/userSalaryManage/edit", pdfData.value).then((res) => {
  207. getPdfData({ userId: props.rowData.id });
  208. proxy.msgTip("操作成功", 1);
  209. proxy.$emit("getList");
  210. });
  211. };
  212. const changeAmount = (type) => {
  213. let userSalaryDetailList = [];
  214. for (const key in pdfData.value.salaryData) {
  215. let arr = key.split("-");
  216. userSalaryDetailList.push({
  217. salaryStructureId: arr[0],
  218. type: arr[1],
  219. money: pdfData.value.salaryData[key],
  220. });
  221. }
  222. pdfData.value.userSalaryDetailList = userSalaryDetailList;
  223. let amount = pdfData.value.userSalaryDetailList
  224. .filter((x) => x.type == "10")
  225. .reduce(
  226. (total, x) => Number(parseFloat((total += Number(x.money))).toFixed(2)),
  227. 0
  228. );
  229. pdfData.value.amount = amount;
  230. let perfAmount = pdfData.value.userSalaryDetailList
  231. .filter((x) => x.type == "20")
  232. .reduce(
  233. (total, x) => Number(parseFloat((total += Number(x.money))).toFixed(2)),
  234. 0
  235. );
  236. pdfData.value.perfAmount = perfAmount;
  237. };
  238. </script>
  239. <style lang="scss" scoped>
  240. .table {
  241. .title {
  242. font-size: 26px;
  243. // font-weight: 700;
  244. }
  245. border-collapse: collapse;
  246. border-spacing: 0;
  247. width: 100%;
  248. td {
  249. text-align: center;
  250. padding: 6px;
  251. font-size: 12px;
  252. // padding: 5px 10px;
  253. }
  254. .align-right {
  255. text-align: right;
  256. }
  257. }
  258. :deep(.el-input__wrapper) {
  259. box-shadow: none;
  260. }
  261. </style>