index.vue 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669
  1. <template>
  2. <div>
  3. <el-container>
  4. <!-- 左侧树形结构 -->
  5. <el-scrollbar max-height="75vh">
  6. <el-aside>
  7. <div class="JKWTree-tree">
  8. <h3>计件工计时单维护</h3>
  9. <el-tree
  10. :data="treeData"
  11. :props="defaultProps"
  12. highlight-current="true"
  13. @node-click="handleNodeClick"
  14. />
  15. </div>
  16. </el-aside>
  17. </el-scrollbar>
  18. <el-container>
  19. <el-main>
  20. <!-- 按钮区域 -->
  21. <div class="gva-table-box">
  22. <div class="gva-btn-list">
  23. <el-row :span="6">
  24. <el-input
  25. v-model="searchInfo"
  26. placeholder="输入员工编号"
  27. />
  28. </el-row>
  29. <el-button
  30. type="primary"
  31. :icon="Search"
  32. @click="onSearch"
  33. >搜索</el-button>
  34. <el-button
  35. type="primary"
  36. :icon="Refresh"
  37. >重置</el-button>
  38. <div style="margin-left: auto;">
  39. <el-button
  40. type="primary"
  41. :icon="Download"
  42. @click="exportExcel"
  43. >导出到Excel</el-button>
  44. </div>
  45. </div>
  46. <!-- 数据展示 -->
  47. <el-table
  48. ref="multipleTable"
  49. style="width: 100%"
  50. tooltip-effect="dark"
  51. :data="tableData"
  52. row-key="ID"
  53. highlight-current-row
  54. border
  55. :row-style="{ height: '20px' }"
  56. :cell-style="{ padding: '0px' }"
  57. :header-row-style="{ height: '20px' }"
  58. :header-cell-style="{ padding: '0px' }"
  59. @selection-change="handleSelectionChange"
  60. @row-dblclick="doubleClick"
  61. >
  62. <el-table-column
  63. type="selection"
  64. width="55"
  65. />
  66. <!-- 循环渲染列 -->
  67. <el-table-column
  68. v-for=" column in tableColumns "
  69. :key="column.prop"
  70. :prop="column.prop"
  71. :label="column.label"
  72. :width="column.width"
  73. show-overflow-tooltip="true"
  74. />
  75. </el-table>
  76. <!-- 分页 -->
  77. <div class="gva-pagination">
  78. <el-pagination
  79. v-model:current-page="page"
  80. v-model:page-size="limit"
  81. layout="total, sizes, prev, pager, next, jumper"
  82. :page-sizes="[10, 30, 50, 100]"
  83. :total="total"
  84. @current-change="handleCurrentChange"
  85. @size-change="handleSizeChange"
  86. />
  87. </div>
  88. </div>
  89. <!-- 弹出框 -->
  90. <el-dialog
  91. v-model="dialogFormVisible"
  92. :before-close="closeDialog"
  93. title="计件工计时单维护"
  94. destroy-on-close
  95. width="800px"
  96. >
  97. <!-- <el-scrollbar height="500px"> -->
  98. <el-form
  99. ref="elFormRef"
  100. :model="detailData"
  101. label-position="left"
  102. :rules="rule"
  103. >
  104. <!-- 日期 -->
  105. <el-row>
  106. <el-form-item
  107. label="日期"
  108. prop="name"
  109. >
  110. <el-input
  111. v-model="detailData.wgjs_rq"
  112. :clearable="true"
  113. style="width: 100px;"
  114. />
  115. </el-form-item>
  116. </el-row>
  117. <!-- 标题栏 -->
  118. <el-row :gutter="10">
  119. <el-col :span="3">
  120. <span>员工编号</span>
  121. </el-col>
  122. <el-col :span="3">
  123. <span>员工姓名</span>
  124. </el-col>
  125. <el-col :span="3">
  126. <span>计时</span>
  127. </el-col>
  128. <el-col :span="12">
  129. <span>原因备注</span>
  130. </el-col>
  131. <el-col :span="3">
  132. <span>冲月定额</span>
  133. </el-col>
  134. </el-row>
  135. <!-- 员工1 -->
  136. <el-row
  137. :gutter="5"
  138. style="margin-top: 10px;"
  139. >
  140. <el-col :span="3">
  141. <el-input
  142. v-model="detailData.wgjs_bh1"
  143. :clearable="true"
  144. />
  145. </el-col>
  146. <el-col :span="3">
  147. <el-input
  148. v-model="detailData.name1"
  149. :clearable="true"
  150. />
  151. </el-col>
  152. <el-col :span="3">
  153. <el-input
  154. v-model="detailData.wgjs_js1"
  155. :clearable="true"
  156. />
  157. </el-col>
  158. <el-col :span="12">
  159. <el-input
  160. v-model="detailData.wgjs_yy1"
  161. :clearable="true"
  162. />
  163. </el-col>
  164. <el-col :span="3">
  165. <el-input
  166. v-model="detailData.wgjs_冲定额1"
  167. :clearable="true"
  168. />
  169. </el-col>
  170. </el-row>
  171. <!-- 员工2 -->
  172. <el-row
  173. :gutter="5"
  174. style="margin-top: 10px;"
  175. >
  176. <el-col :span="3">
  177. <el-input
  178. v-model="detailData.wgjs_bh2"
  179. :clearable="true"
  180. />
  181. </el-col>
  182. <el-col :span="3">
  183. <el-input
  184. v-model="detailData.name2"
  185. :clearable="true"
  186. />
  187. </el-col>
  188. <el-col :span="3">
  189. <el-input
  190. v-model="detailData.wgjs_js2"
  191. :clearable="true"
  192. />
  193. </el-col>
  194. <el-col :span="12">
  195. <el-input
  196. v-model="detailData.wgjs_yy2"
  197. :clearable="true"
  198. />
  199. </el-col>
  200. <el-col :span="3">
  201. <el-input
  202. v-model="detailData.wgjs_冲定额2"
  203. :clearable="true"
  204. />
  205. </el-col>
  206. </el-row>
  207. <!-- 员工3 -->
  208. <el-row
  209. :gutter="5"
  210. style="margin-top: 10px;"
  211. >
  212. <el-col :span="3">
  213. <el-input
  214. v-model="detailData.wgjs_bh3"
  215. :clearable="true"
  216. />
  217. </el-col>
  218. <el-col :span="3">
  219. <el-input
  220. v-model="detailData.name3"
  221. :clearable="true"
  222. />
  223. </el-col>
  224. <el-col :span="3">
  225. <el-input
  226. v-model="detailData.wgjs_js3"
  227. :clearable="true"
  228. />
  229. </el-col>
  230. <el-col :span="12">
  231. <el-input
  232. v-model="detailData.wgjs_yy3"
  233. :clearable="true"
  234. />
  235. </el-col>
  236. <el-col :span="3">
  237. <el-input
  238. v-model="detailData.wgjs_冲定额3"
  239. :clearable="true"
  240. />
  241. </el-col>
  242. </el-row>
  243. <!-- 员工4 -->
  244. <el-row
  245. :gutter="5"
  246. style="margin-top: 10px;"
  247. >
  248. <el-col :span="3">
  249. <el-input
  250. v-model="detailData.wgjs_bh4"
  251. :clearable="true"
  252. />
  253. </el-col>
  254. <el-col :span="3">
  255. <el-input
  256. v-model="detailData.name4"
  257. :clearable="true"
  258. />
  259. </el-col>
  260. <el-col :span="3">
  261. <el-input
  262. v-model="detailData.wgjs_js4"
  263. :clearable="true"
  264. />
  265. </el-col>
  266. <el-col :span="12">
  267. <el-input
  268. v-model="detailData.wgjs_yy4"
  269. :clearable="true"
  270. />
  271. </el-col>
  272. <el-col :span="3">
  273. <el-input
  274. v-model="detailData.wgjs_冲定额4"
  275. :clearable="true"
  276. />
  277. </el-col>
  278. </el-row>
  279. <!-- 员工5 -->
  280. <el-row
  281. :gutter="5"
  282. style="margin-top: 10px;"
  283. >
  284. <el-col :span="3">
  285. <el-input
  286. v-model="detailData.wgjs_bh5"
  287. :clearable="true"
  288. />
  289. </el-col>
  290. <el-col :span="3">
  291. <el-input
  292. v-model="detailData.name5"
  293. :clearable="true"
  294. />
  295. </el-col>
  296. <el-col :span="3">
  297. <el-input
  298. v-model="detailData.wgjs_js5"
  299. :clearable="true"
  300. />
  301. </el-col>
  302. <el-col :span="12">
  303. <el-input
  304. v-model="detailData.wgjs_yy5"
  305. :clearable="true"
  306. />
  307. </el-col>
  308. <el-col :span="3">
  309. <el-input
  310. v-model="detailData.wgjs_冲定额5"
  311. :clearable="true"
  312. />
  313. </el-col>
  314. </el-row>
  315. <!-- 员工6 -->
  316. <el-row
  317. :gutter="5"
  318. style="margin-top: 10px;"
  319. >
  320. <el-col :span="3">
  321. <el-input
  322. v-model="detailData.wgjs_bh6"
  323. :clearable="true"
  324. />
  325. </el-col>
  326. <el-col :span="3">
  327. <el-input
  328. v-model="detailData.name6"
  329. :clearable="true"
  330. />
  331. </el-col>
  332. <el-col :span="3">
  333. <el-input
  334. v-model="detailData.wgjs_js6"
  335. :clearable="true"
  336. />
  337. </el-col>
  338. <el-col :span="12">
  339. <el-input
  340. v-model="detailData.wgjs_yy6"
  341. :clearable="true"
  342. />
  343. </el-col>
  344. <el-col :span="3">
  345. <el-input
  346. v-model="detailData.wgjs_冲定额6"
  347. :clearable="true"
  348. />
  349. </el-col>
  350. </el-row>
  351. </el-form>
  352. <template #footer>
  353. <div class="dialog-footer">
  354. <el-button @click="closeDialog">取 消</el-button>
  355. <el-button
  356. type="primary"
  357. @click="enterDialog"
  358. >确 定</el-button>
  359. </div>
  360. </template>
  361. </el-dialog>
  362. </el-main>
  363. </el-container>
  364. </el-container>
  365. </div>
  366. </template>
  367. <script setup>
  368. import {
  369. createCompany,
  370. deleteCompany,
  371. deleteCompanyByIds,
  372. updateCompany,
  373. findCompany,
  374. getCompanyList
  375. } from '@/api/company'
  376. // 全量引入格式化工具 请按需保留
  377. import { getDictFunc, formatDate, formatBoolean, filterDict, ReturnArrImg, onDownloadFile } from '@/utils/format'
  378. import { ElMessage, ElMessageBox } from 'element-plus'
  379. import { Search, Refresh, Download } from '@element-plus/icons-vue'
  380. import { ref, reactive, onMounted, onBeforeMount } from 'vue'
  381. import { getSide, getTable, getDetail, updateData, getLocate } from '@/api/mes_api_gty/timesheet'
  382. defineOptions({
  383. name: '08Timesheet'
  384. })
  385. // 侧边栏数据请求
  386. const treeData = reactive([])
  387. const getSideData = async() => {
  388. const response = await getSide()
  389. if (response.code === 0) {
  390. const transformedData = response.data.map(item => ({
  391. label: item.date,
  392. params: {
  393. date: item.date.substring(0, 4) + '-' + item.date.substring(4),
  394. },
  395. }))
  396. treeData.splice(0, treeData.length, ...transformedData)
  397. }
  398. }
  399. getSideData()
  400. // 验证规则
  401. const rule = reactive({
  402. })
  403. const elFormRef = ref()
  404. const elSearchFormRef = ref()
  405. // ============== 表格页面 ==============
  406. const tableColumns = [
  407. { prop: 'wgjs_rq', label: '日期', width: 100 },
  408. { prop: 'wgjs_bh1', label: '员工编号1', width: 100 },
  409. { prop: 'name1', label: '姓名1', width: 100 },
  410. { prop: 'department', label: '所在部门', width: 100 },
  411. { prop: 'wgjs_js1', label: '计时1', width: 100 },
  412. { prop: 'wgjs_yy1', label: '原因1', width: 100 },
  413. { prop: 'wgjs_bh2', label: '员工编号2', width: 100 },
  414. { prop: 'name2', label: '姓名2', width: 100 },
  415. { prop: 'wgjs_js2', label: '计时2', width: 100 },
  416. { prop: 'wgjs_yy2', label: '原因2', width: 100 },
  417. { prop: 'wgjs_bh3', label: '员工编号3', width: 100 },
  418. { prop: 'name3', label: '姓名3', width: 100 },
  419. { prop: 'wgjs_js3', label: '计时3', width: 100 },
  420. { prop: 'wgjs_yy3', label: '原因3', width: 100 },
  421. { prop: 'wgjs_bh4', label: '员工编号4', width: 100 },
  422. { prop: 'name4', label: '姓名4', width: 100 },
  423. { prop: 'wgjs_js4', label: '计时4', width: 100 },
  424. { prop: 'wgjs_yy4', label: '原因4', width: 100 },
  425. { prop: 'wgjs_bh5', label: '员工编号5', width: 100 },
  426. { prop: 'name5', label: '姓名5', width: 100 },
  427. { prop: 'wgjs_js5', label: '计时5', width: 100 },
  428. { prop: 'wgjs_yy5', label: '原因5', width: 100 },
  429. { prop: 'wgjs_bh6', label: '员工编号6', width: 100 },
  430. { prop: 'name6', label: '姓名6', width: 100 },
  431. { prop: 'wgjs_js6', label: '计时6', width: 100 },
  432. { prop: 'wgjs_yy6', label: '原因6', width: 100 },
  433. ]
  434. const tableData = reactive([])
  435. const page = ref(1)
  436. const total = ref(0)
  437. const limit = ref(10)
  438. const searchInfo = ref('')
  439. const params = {
  440. date: '',
  441. search: '',
  442. type: '',
  443. }
  444. const getTableData = async(params) => {
  445. const response = await getTable(params)
  446. if (response.code === 0) {
  447. total.value = response.data.total
  448. tableData.splice(0, tableData.length, ...response.data.rows)
  449. }
  450. }
  451. // 搜索
  452. const getLocateData = async(params) => {
  453. const res = await getLocate(params)
  454. if (res.code === 0) {
  455. total.value = res.data.total
  456. tableData.splice(0, tableData.length, ...res.data.rows)
  457. }
  458. }
  459. // 分页设置
  460. const handleSizeChange = () => {
  461. switch (params.type) {
  462. case 'getTableData':
  463. getTableData({ date: params.date, page: page.value.toString(), limit: limit.value.toString() })
  464. break
  465. case 'getLocateData':
  466. getLocateData({ date: params.date.replace('-', ''),
  467. search: params.search,
  468. page: page.value.toString(),
  469. limit: limit.value.toString() })
  470. break
  471. default:
  472. break
  473. }
  474. }
  475. // 页面跳转
  476. const handleCurrentChange = () => {
  477. switch (params.type) {
  478. case 'getTableData':
  479. getTableData({ date: params.date, page: page.value.toString(), limit: limit.value.toString() })
  480. break
  481. case 'getLocateData':
  482. getLocateData({ date: params.date.replace('-', ''),
  483. search: params.search,
  484. page: page.value.toString(),
  485. limit: limit.value.toString() })
  486. break
  487. default:
  488. break
  489. }
  490. }
  491. const handleNodeClick = (node, check) => {
  492. if (node.params) {
  493. params.date = node.params.date
  494. params.type = 'getTableData'
  495. page.value = 1
  496. handleCurrentChange()
  497. }
  498. }
  499. // 搜索
  500. function onSearch() {
  501. params.search = searchInfo.value
  502. params.type = 'getLocateData'
  503. page.value = 1
  504. handleCurrentChange()
  505. }
  506. // ============== 详情页面 ==============
  507. const detailData = reactive({})
  508. // 行为控制标记(弹窗内部需要增还是改)
  509. const type = ref('')
  510. // 弹窗控制标记
  511. const dialogFormVisible = ref(false)
  512. // 双击表格操作
  513. async function doubleClick(row, column, event) {
  514. type.value = 'update'
  515. const { wgjs_rq, wgjs_bh1 } = row
  516. const res = await getDetail({ wgjs_rq, wgjs_bh1 })
  517. if (res.code === 0) {
  518. Object.assign(detailData, res.data)
  519. dialogFormVisible.value = true
  520. }
  521. }
  522. // 更新数据
  523. const enterDialog = async() => {
  524. const obj = detailData
  525. for (let i = 1; i <= 6; i++) {
  526. delete obj[`name${i}`]
  527. }
  528. const res = await updateData(obj)
  529. if (res.code === 0) {
  530. ElMessage({
  531. type: 'success',
  532. message: '更新成功'
  533. })
  534. params.type = 'getTableData'
  535. // page.value = 1
  536. handleCurrentChange()
  537. dialogFormVisible.value = false
  538. }
  539. }
  540. // 获取需要的字典 可能为空 按需保留
  541. const setOptions = async() => {
  542. }
  543. // 获取需要的字典 可能为空 按需保留
  544. setOptions()
  545. // 多选数据
  546. const multipleSelection = ref([])
  547. // 多选
  548. const handleSelectionChange = (val) => {
  549. multipleSelection.value = val
  550. }
  551. // 批量删除控制标记
  552. const deleteVisible = ref(false)
  553. // 多选删除
  554. const onDelete = async() => {
  555. const ids = []
  556. if (multipleSelection.value.length === 0) {
  557. ElMessage({
  558. type: 'warning',
  559. message: '请选择要删除的数据'
  560. })
  561. return
  562. }
  563. multipleSelection.value &&
  564. multipleSelection.value.map(item => {
  565. ids.push(item.ID)
  566. })
  567. const res = await deleteCompanyByIds({ ids })
  568. if (res.code === 0) {
  569. ElMessage({
  570. type: 'success',
  571. message: '删除成功'
  572. })
  573. if (tableData.value.length === ids.length && page.value > 1) {
  574. page.value--
  575. }
  576. deleteVisible.value = false
  577. getTableData()
  578. }
  579. }
  580. // 更新行
  581. const updateCompanyFunc = async(row) => {
  582. const res = await findCompany({ ID: row.ID })
  583. type.value = 'update'
  584. if (res.code === 0) {
  585. detailData.value = res.data.recompany
  586. dialogFormVisible.value = true
  587. }
  588. }
  589. // 关闭弹窗
  590. const closeDialog = () => {
  591. dialogFormVisible.value = false
  592. }
  593. // 导出excel
  594. function exportExcel() {
  595. console.log('导出到excel')
  596. }
  597. // 生命周期钩子
  598. onMounted(() => {
  599. })
  600. </script>
  601. <style scoped>
  602. .JKWTree-container {
  603. display: flex;
  604. }
  605. .JKWTree-tree {
  606. width: 300px;
  607. background-color: #fff;
  608. padding: 10px;
  609. margin-right: 20px;
  610. }
  611. .JKWTree-tree h3 {
  612. font-size: 15px;
  613. font-weight: 700;
  614. margin: 10px 0;
  615. }
  616. .JKWTree-content {
  617. flex: 1;
  618. }
  619. /* 选中某行时的背景色 */
  620. :deep(.el-table__body tr.current-row) > td {
  621. background: #ff80ff !important;
  622. }
  623. </style>