index.vue 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737
  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-scrollbar
  10. height="70vh"
  11. >
  12. <el-tree
  13. :data="treeData"
  14. :props="defaultProps"
  15. highlight-current="true"
  16. @node-click="handleNodeClick"
  17. />
  18. </el-scrollbar>
  19. </div>
  20. </el-aside>
  21. </el-scrollbar>
  22. <el-container>
  23. <el-main>
  24. <div class="gva-table-box">
  25. <!-- 按钮区域 -->
  26. <div class="gva-btn-list">
  27. <el-row :span="6">
  28. <el-input
  29. v-model="searchInfo"
  30. style="width: 150px;"
  31. placeholder="输入工单编号"
  32. />
  33. </el-row>
  34. <el-button
  35. type="primary"
  36. :icon="Search"
  37. @click="handleSearch"
  38. >搜索
  39. </el-button>
  40. <el-button
  41. type="primary"
  42. :icon="Delete"
  43. @click="handleDelete"
  44. >删除
  45. </el-button>
  46. <div style="margin-left: auto;">
  47. <el-button
  48. type="primary"
  49. :icon="Download"
  50. @click="handleExportExcel"
  51. >导出到Excel
  52. </el-button>
  53. </div>
  54. </div>
  55. <!-- 数据展示 -->
  56. <el-table
  57. ref="multipleTable"
  58. style="width: 100%"
  59. :data="tableData"
  60. row-key="ID"
  61. highlight-current-row
  62. border
  63. :row-style="{ height: '20px' }"
  64. :cell-style="{ padding: '0px' }"
  65. :header-row-style="{ height: '20px' }"
  66. :header-cell-style="{ padding: '0px' }"
  67. @selection-change="handleSelectionChange"
  68. @row-dblclick="doubleClick"
  69. >
  70. <el-table-column
  71. type="selection"
  72. width="55"
  73. />
  74. <!-- 循环渲染列 -->
  75. <el-table-column
  76. v-for=" column in tableColumns "
  77. :key="column.prop"
  78. :prop="column.prop"
  79. :label="column.label"
  80. :width="column.width"
  81. show-overflow-tooltip="true"
  82. />
  83. </el-table>
  84. <!-- 分页 -->
  85. <div class="gva-pagination">
  86. <el-pagination
  87. v-model:current-page="page"
  88. v-model:page-size="limit"
  89. layout="total, sizes, prev, pager, next, jumper"
  90. :page-sizes="[10, 30, 50, 100]"
  91. :total="total"
  92. @current-change="handleCurrentChange"
  93. @size-change="handleSizeChange"
  94. />
  95. </div>
  96. </div>
  97. <!-- 弹出框 -->
  98. <el-dialog
  99. v-model="dialogFormVisible"
  100. :before-close="closeDialog"
  101. :title="type === 'create' ? '添加' : '修改'"
  102. destroy-on-close
  103. width="1200px"
  104. >
  105. <el-form
  106. ref="elFormRef"
  107. :model="detailData"
  108. inline="true"
  109. label-position="left"
  110. :rules="rule"
  111. >
  112. <el-form-item
  113. label="日期"
  114. >
  115. <el-input
  116. v-model="detailData.sczl_rq"
  117. style="width: 120px;"
  118. />
  119. </el-form-item>
  120. <el-form-item
  121. label="员工编号"
  122. @keyup.enter="handleGetYg"
  123. >
  124. <el-input
  125. v-model="detailData.sczl_bh"
  126. style="width: 100px;"
  127. />
  128. <el-input
  129. v-model="detailData.name"
  130. style="width: 100px; padding-left: 5px;"
  131. readonly
  132. />
  133. </el-form-item>
  134. <el-form-item label="组别">
  135. <el-input
  136. v-model="detailData.sczl_bzdh"
  137. style="width: 50px;"
  138. />
  139. </el-form-item>
  140. <br>
  141. <el-form-item
  142. label="计时时数"
  143. style="padding-left: 195px;"
  144. >
  145. <el-input
  146. v-model="detailData.sczl_jsss"
  147. style="width: 100px;"
  148. />
  149. </el-form-item>
  150. <el-form-item label="冲月定额">
  151. <el-input
  152. v-model="detailData.sczl_冲定额"
  153. style="width: 50px;"
  154. />
  155. </el-form-item>
  156. <el-table
  157. :data="detailData.table"
  158. border
  159. tooltip-effect="dark"
  160. :row-style="{ height: '20px' }"
  161. :cell-style="{ padding: '0px' }"
  162. :header-row-style="{ height: '20px' }"
  163. :header-cell-style="{ padding: '0px' }"
  164. >
  165. <el-table-column
  166. label="工单编号"
  167. width="100"
  168. >
  169. <template #default="{ row, $index }">
  170. <el-input
  171. v-model="row.sczl_gdbh"
  172. @keyup.enter="handleEnter($index, row)"
  173. />
  174. </template>
  175. </el-table-column>
  176. <el-table-column
  177. label="印件工序"
  178. width="100"
  179. >
  180. <template #default="{ row }">
  181. <el-input
  182. v-model="row.sczl_yjGx"
  183. readonly
  184. />
  185. </template>
  186. </el-table-column>
  187. <el-table-column
  188. label="工序名称"
  189. width="100"
  190. >
  191. <template #default="{ row }">
  192. <el-input
  193. v-model="row.sczl_gxmc"
  194. readonly
  195. />
  196. </template>
  197. </el-table-column>
  198. <el-table-column label="印件名称">
  199. <template #default="{ row }">
  200. <el-input
  201. v-model="row.Gd_cpmc"
  202. readonly
  203. />
  204. </template>
  205. </el-table-column>
  206. <el-table-column
  207. label="包装产量"
  208. width="100"
  209. >
  210. <template #default="{ row }">
  211. <el-input v-model="row.sczl_cl" />
  212. </template>
  213. </el-table-column>
  214. <el-table-column
  215. label="返工产量"
  216. width="100"
  217. >
  218. <template #default="{ row }">
  219. <el-input v-model="row.sczl_返工产量" />
  220. </template>
  221. </el-table-column>
  222. <el-table-column
  223. label="每箱数量"
  224. width="100"
  225. >
  226. <template #default="{ row }">
  227. <el-input v-model="row.sczl_PgCl" />
  228. </template>
  229. </el-table-column>
  230. <el-table-column
  231. label="计产系数"
  232. width="100"
  233. >
  234. <template #default="{ row }">
  235. <el-input v-model="row.sczl_计产系数" />
  236. </template>
  237. </el-table-column>
  238. <el-table-column
  239. label="来源"
  240. width="100"
  241. >
  242. <template #default="{ row }">
  243. <el-input v-model="row.sczl_Jtbh1" />
  244. </template>
  245. </el-table-column>
  246. <el-table-column
  247. label="定额代号"
  248. width="100"
  249. >
  250. <template #default="{ row }">
  251. <el-input v-model="row.sczl_dedh" />
  252. </template>
  253. </el-table-column>
  254. </el-table>
  255. <el-form-item
  256. label="其他备注"
  257. style="margin-top: 10px;"
  258. >
  259. <el-input v-model="detailData.sczl_desc" />
  260. </el-form-item>
  261. </el-form>
  262. <template #footer>
  263. <div class="dialog-footer">
  264. <el-button @click="closeDialog">取 消</el-button>
  265. <el-button
  266. type="primary"
  267. @click="enterDialog"
  268. >确 定
  269. </el-button>
  270. </div>
  271. </template>
  272. </el-dialog>
  273. <!-- 弹出选项框 -->
  274. <el-dialog
  275. v-model="dialogSelectVisible"
  276. title="选择"
  277. destroy-on-close
  278. width="600px"
  279. >
  280. <el-table
  281. tooltip-effect="dark"
  282. :data="selectData"
  283. row-key="ID"
  284. highlight-current-row
  285. border
  286. style="width:100%"
  287. @row-dblclick="handleSelectClick"
  288. >
  289. <el-table-column
  290. prop="Gd_cpmc"
  291. label="产品名称"
  292. width="300"
  293. />
  294. <el-table-column
  295. prop="Gy0_gxmc"
  296. label="产品名称"
  297. width="100"
  298. />
  299. <el-table-column
  300. prop="jyGx"
  301. label="产品名称"
  302. width="100"
  303. />
  304. </el-table>
  305. </el-dialog>
  306. </el-main>
  307. </el-container>
  308. </el-container>
  309. </div>
  310. </template>
  311. <script setup>
  312. import { createCompany, deleteCompanyByIds, updateCompany } from '@/api/company'
  313. // 全量引入格式化工具 请按需保留
  314. import { ElMessage, ElMessageBox } from 'element-plus'
  315. import { Download, Search, Delete } from '@element-plus/icons-vue'
  316. import { reactive, ref } from 'vue'
  317. import { getGxMc, getInfo, getLocate, getPackingSideTable, getPackingTable, updatePackingTable, getYg, DeletePackingTable } from '@/api/mes_api_gty/myapi'
  318. defineOptions({
  319. name: '06PackingDocuments',
  320. })
  321. // 侧边栏数据
  322. const treeData = reactive([])
  323. const getSideData = async() => {
  324. try {
  325. const response = await getPackingSideTable()
  326. if (response.code === 0) {
  327. const transformedData = response.data.map(item => ({
  328. label: `${item.date.replace(/-/g, '.')}【单据数: ${item.counts}张】`,
  329. children: item.sys.map(sysItem => ({
  330. label: `${sysItem.sys_id} 【记录数: ${sysItem.count}张】`,
  331. params: {
  332. date: item.date.replace(/\./g, '-'),
  333. sys_id: sysItem.sys_id,
  334. },
  335. })),
  336. }))
  337. treeData.splice(0, treeData.length, ...transformedData)
  338. }
  339. } catch (e) {
  340. console.log(e)
  341. }
  342. }
  343. getSideData()
  344. // 验证规则
  345. const rule = reactive({})
  346. const elFormRef = ref()
  347. const elSearchFormRef = ref()
  348. // ============== 表格页面 ==============
  349. const tableColumns = [
  350. { label: '员工编号', prop: 'sczl_bh', width: '100' },
  351. { label: '员工姓名', prop: 'name', width: '100' },
  352. { label: '生产日期', prop: 'sczl_rq', width: '100' },
  353. { label: '班组', prop: 'sczl_bzdh', width: '100' },
  354. { label: '包装产量', prop: 'sczl_cl', width: '100' },
  355. { label: '返工产量', prop: 'sczl_fgsl', width: '100' },
  356. { label: '计件产量', prop: 'sczl_jjcl', width: '100' },
  357. { label: '相关工单', prop: 'sczl_gdbh1', width: '100' },
  358. { label: '创建用户', prop: 'sys_id', width: '120' },
  359. { label: '创建时间', prop: 'sys_rq', width: '180' },
  360. { label: '修改时间', prop: 'mod_rq', width: '180' },
  361. { label: 'UNIQID', prop: 'UniqId', width: '100' },
  362. ]
  363. const tableData = reactive([])
  364. const total = ref(0)
  365. const page = ref(1)
  366. const limit = ref(10)
  367. const searchInfo = ref('')
  368. const params = {
  369. type: '',
  370. date: '',
  371. sys_id: '',
  372. gdbh: '',
  373. }
  374. // 多选数据
  375. const multipleSelection = ref([])
  376. // 获取列表数据
  377. const getTableData = async() => {
  378. try {
  379. const response = await getPackingTable({
  380. date: params.date, sys_id: params.sys_id,
  381. page: page.value.toString(), limit: limit.value.toString(),
  382. })
  383. if (response.code === 0) {
  384. total.value = response.data.total
  385. tableData.splice(0, tableData.length, ...response.data.rows)
  386. }
  387. } catch (e) {
  388. console.log(e)
  389. }
  390. }
  391. // 获取定位数据
  392. const getLocateTable = async() => {
  393. try {
  394. const response = await getLocate({
  395. gdbh: params.gdbh,
  396. page: page.value.toString(), limit: limit.value.toString(),
  397. })
  398. if (response.code === 0) {
  399. total.value = response.data.total
  400. tableData.splice(0, tableData.length, ...response.data.rows)
  401. }
  402. } catch (e) {
  403. console.log(e)
  404. }
  405. }
  406. const deleteTableData = async(id) => {
  407. try {
  408. const res = await DeletePackingTable({ UniqId: id })
  409. if (res.code === 0) {
  410. return 0
  411. }
  412. } catch (e) {
  413. console.log(e)
  414. }
  415. }
  416. // 左侧树结构点击
  417. const handleNodeClick = (node, check) => {
  418. if (node.params) {
  419. params.date = node.params.date
  420. params.sys_id = node.params.sys_id
  421. params.type = 'getTableData'
  422. page.value = 1
  423. getTableData()
  424. }
  425. }
  426. // 定位
  427. function handleSearch() {
  428. console.log(searchInfo.value)
  429. params.gdbh = searchInfo.value
  430. params.type = 'getLocateTable'
  431. page.value = 1
  432. getLocateTable()
  433. }
  434. // 删除方法
  435. const handleSelectionChange = (val) => {
  436. multipleSelection.value = val
  437. }
  438. const handleDelete = () => {
  439. console.log(multipleSelection.value)
  440. if (multipleSelection.value.length === 1) {
  441. ElMessageBox.confirm(
  442. `确认删除这条数据么?`,
  443. '警告',
  444. {
  445. confirmButtonText: '确认',
  446. cancelButtonText: '取消',
  447. type: 'warning',
  448. }
  449. )
  450. .then(async() => {
  451. const ret = await deleteTableData(multipleSelection.value[0].UniqId)
  452. console.log(ret)
  453. if (ret === 0) {
  454. ElMessage({
  455. type: 'success',
  456. message: '删除成功',
  457. })
  458. } else {
  459. ElMessage({
  460. type: 'error',
  461. message: '删除失败',
  462. })
  463. }
  464. })
  465. .catch(() => {
  466. ElMessage({
  467. type: 'info',
  468. message: '取消删除',
  469. })
  470. })
  471. } else {
  472. ElMessage({
  473. type: 'info',
  474. message: '仅支持单条数据删除',
  475. })
  476. }
  477. }
  478. // 分页设置
  479. const handleSizeChange = () => {
  480. switch (params.type) {
  481. case 'getTableData':
  482. getTableData()
  483. break
  484. case 'getLocateTable':
  485. getLocateTable()
  486. break
  487. default:
  488. break
  489. }
  490. }
  491. // 页面跳转
  492. const handleCurrentChange = () => {
  493. switch (params.type) {
  494. case 'getTableData':
  495. getTableData()
  496. break
  497. case 'getLocateTable':
  498. getLocateTable()
  499. break
  500. default:
  501. break
  502. }
  503. }
  504. // ============== 详情页面 ==============
  505. const detailData = reactive({
  506. UniqId: '',
  507. selectIndex: 0,
  508. sczl_rq: '',
  509. sczl_bh: '',
  510. name: '',
  511. sczl_bzdh: '',
  512. sczl_jsss: '',
  513. sczl_冲定额: '',
  514. sczl_desc: '',
  515. table: [],
  516. })
  517. const selectData = reactive([])
  518. // 行为控制标记(弹窗内部需要增还是改)
  519. const type = ref('')
  520. // 弹窗控制标记
  521. const dialogFormVisible = ref(false)
  522. const dialogSelectVisible = ref(false)
  523. // 获取详细信息
  524. const getTableInfo = async(id) => {
  525. try {
  526. const response = await getInfo({ UniqId: id })
  527. if (response.code === 0) {
  528. const { sczl_rq, sczl_bh, name, sczl_bzdh, sczl_jsss, sczl_冲定额, sczl_desc, ...rest } = response.data
  529. // 直接赋值基础属性
  530. Object.assign(detailData, { sczl_rq, sczl_bh, name, sczl_bzdh, sczl_jsss, sczl_冲定额, sczl_desc })
  531. // 生成表格数据
  532. detailData.table = Array.from({ length: 6 }, (_, i) => i + 1) // 创建一个长度为6的数组 [1, 2, 3, 4, 5, 6]
  533. .map(num => {
  534. return {
  535. sczl_gdbh: rest[`sczl_gdbh${num}`],
  536. sczl_yjGx: rest[`sczl_yjGx${num}`],
  537. sczl_gxmc: rest[`sczl_gxmc${num}`],
  538. Gd_cpmc: rest[`Gd_cpmc${num}`],
  539. sczl_cl: rest[`sczl_cl${num}`],
  540. sczl_返工产量: rest[`sczl_返工产量${num}`],
  541. sczl_PgCl: rest[`sczl_PgCl${num}`],
  542. sczl_计产系数: rest[`sczl_计产系数${num}`],
  543. sczl_Jtbh1: rest[`sczl_Jtbh${num}`],
  544. sczl_dedh: rest[`sczl_dedh${num}`],
  545. }
  546. })
  547. // .filter(item => item.sczl_gdbh !== '') // 过滤掉空的工单编号
  548. detailData.UniqId = id
  549. dialogFormVisible.value = true
  550. }
  551. } catch (e) {
  552. console.log(e)
  553. }
  554. }
  555. // 获取工序名称
  556. const getTableGxMc = async(index, row) => {
  557. try {
  558. const response = await getGxMc({ gdbh: row.sczl_gdbh })
  559. if (response.code === 0) {
  560. const { Gd_cpmc, Gy0_gxmc, jyGx } = response.data[0]
  561. if (response.data.length === 1) {
  562. detailData.table[index].Gd_cpmc = Gd_cpmc
  563. detailData.table[index].sczl_yjGx = jyGx
  564. detailData.table[index].sczl_gxmc = Gy0_gxmc
  565. } else {
  566. selectData.splice(0, selectData.length, ...response.data)
  567. detailData.selectIndex = index
  568. dialogSelectVisible.value = true
  569. }
  570. }
  571. } catch (e) {
  572. console.log(e)
  573. }
  574. }
  575. // 更新数据
  576. const updateDetailData = async() => {
  577. const restoredData = {
  578. UniqId: detailData.UniqId,
  579. sczl_rq: detailData.sczl_rq,
  580. sczl_bh: detailData.sczl_bh,
  581. name: detailData.name,
  582. sczl_bzdh: detailData.sczl_bzdh,
  583. sczl_jsss: detailData.sczl_jsss,
  584. sczl_冲定额: detailData.sczl_冲定额,
  585. sczl_desc: detailData.sczl_desc,
  586. }
  587. detailData.table.forEach((item, index, array) => {
  588. const num = index + 1
  589. restoredData[`sczl_gdbh${num}`] = item.sczl_gdbh
  590. restoredData[`sczl_yjGx${num}`] = item.sczl_yjGx
  591. restoredData[`sczl_gxmc${num}`] = item.sczl_gxmc
  592. restoredData[`Gd_cpmc${num}`] = item.Gd_cpmc
  593. restoredData[`sczl_cl${num}`] = item.sczl_cl
  594. restoredData[`sczl_返工产量${num}`] = item.sczl_返工产量
  595. restoredData[`sczl_PgCl${num}`] = item.sczl_PgCl
  596. restoredData[`sczl_计产系数${num}`] = item.sczl_计产系数
  597. restoredData[`sczl_Jtbh${num}`] = item.sczl_Jtbh1
  598. restoredData[`sczl_dedh${num}`] = item.sczl_dedh
  599. })
  600. const res = await updatePackingTable(restoredData)
  601. if (res.code === 0) {
  602. ElMessage({
  603. type: 'success',
  604. message: '更新成功',
  605. })
  606. dialogFormVisible.value = false
  607. }
  608. }
  609. // 双击打开详情页
  610. function doubleClick(row, column, event) {
  611. type.value = 'update'
  612. getTableInfo(row.UniqId)
  613. }
  614. const handleGetYg = async() => {
  615. try {
  616. const res = await getYg({ sczl_bh: detailData.sczl_bh })
  617. if (res.code === 0) {
  618. detailData.name = res.data.ygxm
  619. }
  620. } catch (e) {
  621. console.log(e)
  622. }
  623. }
  624. // 处理选择框回车操作
  625. const handleEnter = (index, row) => {
  626. if (row.sczl_gdbh === '') {
  627. detailData.table[index].sczl_yjGx = ''
  628. detailData.table[index].sczl_gxmc = ''
  629. detailData.table[index].Gd_cpmc = ''
  630. } else {
  631. getTableGxMc(index, row)
  632. }
  633. }
  634. // 处理选择框
  635. const handleSelectClick = (row, column, event) => {
  636. const { Gd_cpmc, Gy0_gxmc, jyGx } = row
  637. const index = detailData.selectIndex
  638. detailData.table[index].Gd_cpmc = Gd_cpmc
  639. detailData.table[index].sczl_yjGx = jyGx
  640. detailData.table[index].sczl_gxmc = Gy0_gxmc
  641. dialogSelectVisible.value = false
  642. }
  643. // 弹窗确定
  644. const enterDialog = () => {
  645. switch (type.value) {
  646. case 'create':
  647. break
  648. case 'update':
  649. updateDetailData()
  650. break
  651. default:
  652. break
  653. }
  654. }
  655. // 关闭弹窗
  656. const closeDialog = () => {
  657. dialogFormVisible.value = false
  658. }
  659. // 导出excel
  660. function handleExportExcel() {
  661. console.log('导出到excel')
  662. }
  663. // 生命周期钩子
  664. </script>
  665. <style scoped>
  666. .JKWTree-container {
  667. display: flex;
  668. }
  669. .JKWTree-tree {
  670. width: 300px;
  671. background-color: #fff;
  672. padding: 10px;
  673. margin-right: 20px;
  674. }
  675. .JKWTree-tree h3 {
  676. font-size: 15px;
  677. font-weight: 700;
  678. margin: 10px 0;
  679. }
  680. .JKWTree-content {
  681. flex: 1;
  682. }
  683. /* 选中某行时的背景色 */
  684. :deep(.el-table__body tr.current-row) > td {
  685. background: #ff80ff !important;
  686. }
  687. </style>