index.vue 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. <template>
  2. <div>
  3. <layout>
  4. <layout-header>
  5. <div class="">
  6. <!--按钮部分-->
  7. <el-form
  8. ref="elSearchFormRef"
  9. inline
  10. class="demo-form-inline"
  11. @submit.native.prevent
  12. >
  13. <el-form-item>
  14. <el-input
  15. v-model="searchInfo"
  16. placeholder="搜索产品编号或产品名称"
  17. clearable
  18. style="width: 180px"
  19. />
  20. <el-button
  21. type="primary"
  22. icon="search"
  23. class="search"
  24. @click="handleSearch"
  25. />
  26. <el-button
  27. type="primary"
  28. icon="edit"
  29. class="bt"
  30. @click="
  31. () => {
  32. dialogDetail = true;
  33. }
  34. "
  35. ><i class="el-icon-edit" />查改
  36. </el-button>
  37. <!-- <el-button type="primary" disabled icon="edit" @click="" style="margin-left: 10px">工艺方案复制</el-button>-->
  38. <el-button
  39. type="primary"
  40. icon="edit"
  41. class="bt"
  42. @click="
  43. () => {
  44. dialogGdcjstj = true;
  45. }
  46. "
  47. >工单超节损统计
  48. </el-button>
  49. <el-button
  50. type="primary"
  51. icon="edit"
  52. class="bt"
  53. @click="
  54. () => {
  55. dialogKhsz = true;
  56. }
  57. "
  58. >考核设置
  59. </el-button>
  60. <el-button
  61. type="primary"
  62. icon="edit"
  63. class="bt"
  64. @click="
  65. () => {
  66. dialogXzgdtl = true;
  67. }
  68. "
  69. >修正工单投料
  70. </el-button>
  71. <el-button
  72. type="primary"
  73. icon="edit"
  74. class="bt"
  75. @click="
  76. () => {
  77. dialogGxclhc = true;
  78. }
  79. "
  80. >工序产量核查
  81. </el-button>
  82. <el-button
  83. type="primary"
  84. icon="edit"
  85. class="bt"
  86. @click="
  87. () => {
  88. dialogGdzjfptj = true;
  89. }
  90. "
  91. >工单质检废品统计
  92. </el-button>
  93. <el-button
  94. type="primary"
  95. icon="edit"
  96. class="bt"
  97. @click="
  98. () => {
  99. dialogHjfpfb = true;
  100. }
  101. "
  102. >核检废品分布
  103. </el-button>
  104. <el-button
  105. type="primary"
  106. icon="edit"
  107. class="bt"
  108. @click="handleGddy"
  109. >工单打印
  110. </el-button>
  111. <el-button
  112. type="primary"
  113. icon="edit"
  114. class="bt"
  115. @click="
  116. () => {
  117. pd_lcdlist = true;
  118. pd_lcdProductValue();
  119. }
  120. "
  121. >流程单查询
  122. </el-button>
  123. <el-button
  124. type="primary"
  125. icon="edit"
  126. class="bt"
  127. @click="exportExcel"
  128. >导出Excel
  129. </el-button>
  130. </el-form-item>
  131. </el-form>
  132. <!-- 弹窗 -->
  133. <div>
  134. <!-- 查改 -->
  135. <Detail
  136. v-if="dialogDetail"
  137. :is-show="dialogDetail"
  138. :gdbh="gdbh"
  139. @destroy="
  140. () => {
  141. dialogDetail = false;
  142. }
  143. "
  144. />
  145. <!-- 工单超节损统计 -->
  146. <el-dialog
  147. v-model="dialogGdcjstj"
  148. title="工单超节损统计"
  149. destroy-on-close
  150. >
  151. <Gdcjstj :gdbh="gdbh" />
  152. </el-dialog>
  153. <!-- 修正工单印件质量考核设置 -->
  154. <Khsz
  155. v-if="dialogKhsz"
  156. v-model="dialogKhsz"
  157. :gdbh="gdbh"
  158. />
  159. <!-- 修正工单投料 -->
  160. <Xzgdtl
  161. v-if="dialogXzgdtl"
  162. v-model="dialogXzgdtl"
  163. :date="date"
  164. />
  165. <!-- 工序产量核查 -->
  166. <Gxclhc
  167. v-if="dialogGxclhc"
  168. v-model="dialogGxclhc"
  169. :gdbh="gdbh"
  170. />
  171. <!-- 工单质检废品统计 -->
  172. <Gongdanzhijianfeipintongji
  173. v-if="dialogGdzjfptj"
  174. v-model="dialogGdzjfptj"
  175. :val="gdbh"
  176. />
  177. <!-- 核检废品分布 -->
  178. <Hjfpfb
  179. v-if="dialogHjfpfb"
  180. v-model="dialogHjfpfb"
  181. :val="gdbh"
  182. />
  183. <!-- 工单打印 -->
  184. <PrintPage ref="printPageRef" />
  185. <!--流程单查询【弹窗】-->
  186. <el-dialog
  187. v-model="pd_lcdlist"
  188. title="工单工序生产进程"
  189. fullscreen
  190. >
  191. <div style="width: 100%; height: 100%">
  192. <el-button
  193. type=""
  194. @click="
  195. () => {
  196. pd_lcdlist = false;
  197. }
  198. "
  199. >退出</el-button>
  200. </div>
  201. <div
  202. style="
  203. width: 100%;
  204. height: 100%;
  205. display: flex;
  206. align-items: center;
  207. "
  208. >
  209. <el-form-item
  210. label="工单编号"
  211. style="margin-right: 20px; padding: 0"
  212. >
  213. <el-input
  214. v-model="pd_lcdformData['gdbh']"
  215. @keyup.enter="pd_lcdProductValue"
  216. />
  217. </el-form-item>
  218. <el-form-item
  219. label=""
  220. style="margin-right: 5px; padding: 0"
  221. >
  222. <el-input
  223. v-model="pd_lcdformData['code']"
  224. disabled
  225. />
  226. </el-form-item>
  227. <el-form-item
  228. label=""
  229. style="margin-right: 5px; padding: 0"
  230. >
  231. <el-input
  232. v-model="pd_lcdformData['name']"
  233. disabled
  234. style="width: 500px"
  235. />
  236. </el-form-item>
  237. </div>
  238. <div style="width: 100%; height: 70vh; display: flex">
  239. <layout>
  240. <layout-sider
  241. :resize-directions="['right']"
  242. :width="240"
  243. style="margin-right: 10px; height: 70vh"
  244. >
  245. <div class="JKWTree-tree">
  246. <el-tree
  247. :data="pd_lcd_treeData"
  248. default-expand-all
  249. @node-click="pd_lcd_handleNodeClick"
  250. />
  251. </div>
  252. </layout-sider>
  253. <layout-main>
  254. <!-- 这里放右侧的内容 -->
  255. <el-space wrap>
  256. <!-- 右侧内容 -->
  257. <template v-for="item in processList.total_process">
  258. <el-button
  259. disabled
  260. :type="
  261. !processList.process.includes(item)
  262. ? 'danger'
  263. : 'info'
  264. "
  265. plain
  266. style="width: 50px"
  267. >{{ item }}</el-button>
  268. </template>
  269. </el-space>
  270. </layout-main>
  271. </layout>
  272. </div>
  273. </el-dialog>
  274. </div>
  275. </div>
  276. </layout-header>
  277. <layout>
  278. <!-- 左侧树侧形结构-->
  279. <layout-sider
  280. :resize-directions="['right']"
  281. :width="190"
  282. style="margin-right: 10px"
  283. >
  284. <div
  285. class="JKWTree-tree"
  286. style="height: 70vh"
  287. >
  288. <h3>工单超节损核算</h3>
  289. <el-tree
  290. :data="treeData"
  291. highlight-current
  292. @node-click="handleNodeClick"
  293. />
  294. </div>
  295. </layout-sider>
  296. <!-- 右侧内容区域 -->
  297. <layout-content>
  298. <!-- 上方列表 -->
  299. <div class="gva-table-box">
  300. <el-table
  301. style="width: 100%; height: 30vh"
  302. :data="tableData1"
  303. row-key="ID"
  304. highlight-current-row
  305. border
  306. :row-class-name="rowClassName"
  307. :cell-class-name="cellClassName"
  308. :row-style="{ height: '20px' }"
  309. :cell-style="{ padding: '0px' }"
  310. :header-row-style="{ height: '20px' }"
  311. :header-cell-style="{ padding: '0px' }"
  312. @row-click="showOrderSuperLossGy"
  313. @current-change="
  314. (row, oldRow) => {
  315. currentRow = row;
  316. }
  317. "
  318. >
  319. <el-table-column
  320. type="selection"
  321. width="55"
  322. />
  323. <!-- 使用 v-for 循环渲染每一列 -->
  324. <el-table-column
  325. v-for="column in tableCols1"
  326. :key="column.prop"
  327. :prop="column.prop"
  328. :label="column.label"
  329. :width="column.width"
  330. show-overflow-tooltip="true"
  331. sortable
  332. />
  333. </el-table>
  334. </div>
  335. <!-- 下方表格 -->
  336. <el-table
  337. style="width: 100%; height: 40vh"
  338. row-key="ID"
  339. highlight-current-row
  340. border
  341. :data="tableData2"
  342. :row-style="{ height: '20px' }"
  343. :cell-style="{ padding: '0px' }"
  344. :header-row-style="{ height: '20px' }"
  345. :header-cell-style="{ padding: '0px' }"
  346. >
  347. <el-table-column
  348. type="selection"
  349. width="55"
  350. />
  351. <!-- 使用 v-for 循环渲染每一列 -->
  352. <el-table-column
  353. v-for="column in tableCols2"
  354. :key="column.prop"
  355. :prop="column.prop"
  356. :label="column.label"
  357. :width="column.width"
  358. show-overflow-tooltip="true"
  359. sortable
  360. />
  361. </el-table>
  362. </layout-content>
  363. </layout>
  364. </layout>
  365. </div>
  366. </template>
  367. <script>
  368. import service from '@/utils/request'
  369. import { writeXLSX } from 'xlsx'
  370. // 5.1流程单查询-工单工序生产进程菜单栏
  371. export const getOrderProcessLeft = (params) => {
  372. return service({
  373. url: '/mes_server/work_order_verification/getOrderProcessLeft',
  374. method: 'get',
  375. params,
  376. })
  377. }
  378. // 5.2流程单查询-获取工单工序生产进程右侧
  379. export const getOrderProcessRight = (params) => {
  380. return service({
  381. url: '/mes_server/work_order_verification/getOrderProcessRight',
  382. method: 'get',
  383. params,
  384. })
  385. }
  386. </script>
  387. <script setup>
  388. import {
  389. Layout,
  390. LayoutContent,
  391. LayoutHeader,
  392. LayoutSider,
  393. } from '@arco-design/web-vue'
  394. import { ref, watch } from 'vue'
  395. import {
  396. getOrderSuperLossGy,
  397. getSide,
  398. getTable,
  399. } from '@/api/mes_api_gty/orderAccounting'
  400. import Gdcjstj from '@/view/performance/12-orderAccounting/componets/gdcjstj.vue'
  401. import Khsz from '@/view/performance/12-orderAccounting/componets/khsz.vue'
  402. import Xzgdtl from '@/view/performance/12-orderAccounting/componets/xzgdtl.vue'
  403. import Gxclhc from '@/view/performance/12-orderAccounting/componets/gxclhc.vue'
  404. import Gongdanzhijianfeipintongji from '@/view/performance/09-workOrderVerification/componets/gongdanzhijianfeipintongji.vue'
  405. import Detail from '@/view/performance/12-orderAccounting/componets/detail.vue'
  406. import Hjfpfb from './componets/hjfpfb.vue'
  407. import PrintPage from '@/view/yunyin/shengchanguanli/components/print.vue'
  408. import { reactive } from 'vue'
  409. import { exportExcelFile } from '@/utils/excel'
  410. import { useUserStore } from '@/pinia/modules/user'
  411. const userStore = useUserStore()
  412. const sys_id =
  413. '[' + userStore.userInfo.userName + '/' + userStore.userInfo.nickName + ']'
  414. // 弹窗
  415. const dialogGdcjstj = ref(false)
  416. const dialogDetail = ref(false)
  417. const dialogKhsz = ref(false)
  418. const dialogXzgdtl = ref(false)
  419. const dialogGxclhc = ref(false)
  420. const dialogGdzjfptj = ref(false)
  421. const dialogHjfpfb = ref(false)
  422. // 侧边栏数据
  423. const treeData = ref([])
  424. const getSideData = async() => {
  425. const res = await getSide()
  426. if (res.code === 0) {
  427. const { data } = res
  428. const transformedData = []
  429. for (const [key, value] of Object.entries(data)) {
  430. const [date, total] = key.split('-') // 提取日期和数量
  431. const transformedItem = {
  432. label: `${date}(工单数:${total})`,
  433. date: date,
  434. children: value.map((item) => ({
  435. label: `${item['客户编号']}【${item['客户名称']}】(工单数:${item.total})`,
  436. date: date,
  437. code: item?.['客户编号'],
  438. })),
  439. }
  440. transformedData.push(transformedItem)
  441. }
  442. treeData.value = transformedData
  443. }
  444. }
  445. getSideData()
  446. // 表格数据
  447. const tableCols1 = [
  448. { label: '超损工单', prop: 'csgd', width: '120' },
  449. { label: '工单编号', prop: 'Gd_gdbh', width: '120' },
  450. { label: '印件号', prop: 'jjcp_yjno', width: '100' },
  451. { label: '联数', prop: 'yj_ls', width: '80' },
  452. { label: '产品代号', prop: '成品编码', width: '150' },
  453. { label: '产品名称', prop: '成品名称', width: '250' },
  454. { label: '实际投料', prop: '实际投料', width: '120' },
  455. { label: '计量单位', prop: '计量单位', width: '120' },
  456. { label: '入仓日期', prop: 'warehousing_date', width: '120' },
  457. { label: '入仓数量', prop: 'warehousing_num', width: '120' },
  458. { label: '目标合格率', prop: 'target_rate', width: '120' },
  459. { label: '实际合格率', prop: 'real_rate', width: '120' },
  460. { label: '奖惩系数', prop: 'reward_rate', width: '120' },
  461. // { label: '奖罚金额合计', prop: '', width: '140' },
  462. { label: '废品合计', prop: '废品合计', width: '120' },
  463. { label: '工单无形损', prop: '工单无形损', width: '120' },
  464. { label: '材料废', prop: '材料废', width: '120' },
  465. { label: '零头处理', prop: '零头处理', width: '120' },
  466. { label: '处发废', prop: '外发废', width: '120' },
  467. { label: '外摊废', prop: '分摊废', width: '120' },
  468. { label: '工单计划损耗', prop: '工单计划损耗', width: '140' },
  469. { label: '工单制程废', prop: '', width: '120' },
  470. { label: '工单检验废', prop: '工单质检废', width: '120' },
  471. { label: '年月', prop: 'date', width: '120' },
  472. ]
  473. const tableCols2 = [
  474. { label: '工单编号', prop: 'Gy0_gdbh', width: '120' },
  475. { label: '印件及工序', prop: 'Gy0_yjno', width: '120' },
  476. { label: '工序名称', prop: 'Gy0_gxmc', width: '200' },
  477. { label: '联数', prop: 'Gy0_ls', width: '80' },
  478. { label: '基础损耗', prop: 'Gy0_Rate0', width: '120' },
  479. { label: '损耗率', prop: 'Gy0_Rate1', width: '120' },
  480. { label: '损耗系数', prop: '损耗系数', width: '120' },
  481. { label: '计损色数', prop: 'Gy0_ms', width: '120' },
  482. { label: '计划产量', prop: 'Gy0_计划接货数', width: '120' },
  483. { label: '计划损耗', prop: 'Gy0_计划损耗', width: '120' },
  484. { label: '上报产量', prop: 'total_cl', width: '120' },
  485. { label: '制程废', prop: 'total_fp', width: '120' },
  486. ]
  487. const tableData1 = ref([])
  488. const tableData2 = ref([])
  489. const currentRow = ref({})
  490. const gdbh = ref('')
  491. const date = ref('')
  492. const searchInfo = ref('')
  493. watch(currentRow, (value, oldValue, onCleanup) => {
  494. gdbh.value = value?.['Gd_gdbh']
  495. date.value = value?.['date']
  496. pd_lcdformData['gdbh'] = value?.['Gd_gdbh']
  497. })
  498. // 显示上方表格
  499. const handleNodeClick = async(node) => {
  500. console.log(node)
  501. if (!node.children) {
  502. const { date, code } = node
  503. const res = await getTable({ date, code, limit: 9999, page: 1 })
  504. tableData1.value = res.data.data.map((item) => ({
  505. ...item,
  506. csgd:
  507. parseFloat(item['target_rate']) - parseFloat(item['real_rate']) > 0
  508. ? '√'
  509. : '',
  510. date: date,
  511. }))
  512. console.log(res.data)
  513. } else {
  514. // console.log(node.date, node.code)
  515. }
  516. }
  517. // 显示下方表格
  518. const showOrderSuperLossGy = async() => {
  519. const { Gd_gdbh: order } = currentRow.value
  520. const res = await getOrderSuperLossGy({ order })
  521. if (res.code === 0) {
  522. const { data } = res
  523. tableData2.value = data.map((item) => ({
  524. ...item,
  525. Gy0_yjno: `${item.Gy0_yjno}-${item.Gy0_gxh}`,
  526. Gy0_gxmc:
  527. item.Add_gxmc === ''
  528. ? item.Gy0_gxmc
  529. : `${item.Gy0_gxmc}〖${item.Add_gxmc}〗`,
  530. }))
  531. }
  532. }
  533. // 定位
  534. const handleSearch = () => {
  535. if (searchInfo.value) {
  536. tableData1.value = tableData1.value.filter((item) => {
  537. return item['Gd_gdbh'] === searchInfo.value ?? item
  538. })
  539. }
  540. }
  541. /* const rowClassName = ({ row, rowIndex }) => {
  542. if (row['csgd'] === '√') {
  543. return 'yellow-row'
  544. }
  545. return ''
  546. }*/
  547. const cellClassName = ({ row, column, rowIndex, columnIndex }) => {
  548. if ([7, 11, 13, 21].includes(columnIndex)) {
  549. return 'red-cell'
  550. }
  551. return ''
  552. }
  553. const printPageRef = ref()
  554. function handleGddy() {
  555. printPageRef.value.open(gdbh.value)
  556. }
  557. const pd_lcdlist = ref(false)
  558. const processList = ref([])
  559. const pd_lcdformData = reactive({})
  560. const pd_lcdProductValue = async() => {
  561. _getOrderProcessLeft_list()
  562. }
  563. const pd_lcd_treeData = ref([])
  564. const _getOrderProcessLeft_list = async() => {
  565. const order = pd_lcdformData['gdbh']
  566. console.log(order)
  567. try {
  568. // 5.1流程单查询-工单工序生产进程菜单栏
  569. const getOrderProcessLeft_list = await getOrderProcessLeft({
  570. order: order,
  571. })
  572. console.log(getOrderProcessLeft_list)
  573. pd_lcdformData['code'] = getOrderProcessLeft_list.data.Gd_info['code']
  574. pd_lcdformData['name'] = getOrderProcessLeft_list.data.Gd_info['name']
  575. pd_lcd_treeData.value = [
  576. {
  577. label: order + '-' + getOrderProcessLeft_list.data.Gd_info['name'],
  578. // label: order + '-' + getOrderProcessLeft_list.data.Gd_info['code'] + '-' + getOrderProcessLeft_list.data.Gd_info['name'],
  579. value: undefined,
  580. children: [],
  581. },
  582. ]
  583. const newData = []
  584. for (const key in getOrderProcessLeft_list.data.Gy_info) {
  585. const temp = getOrderProcessLeft_list.data.Gy_info[key]
  586. const concatenatedValue = `${temp.Gy0_yjno}-${temp.Gy0_gxh} ---> ${temp.Gy0_gxmc}`
  587. newData.push({ label: concatenatedValue, value: temp.Gy0_gxh })
  588. }
  589. pd_lcd_treeData.value[0].children = newData
  590. // 5.2流程单查询-获取工单工序生产进程右侧【进入页面默认显示第一个】
  591. const getOrderProcessRight_list = await getOrderProcessRight({
  592. order: order,
  593. gxNo: newData[0].value,
  594. })
  595. processList.value = getOrderProcessRight_list.data
  596. } catch (error) {
  597. console.error(error)
  598. }
  599. }
  600. const pd_lcd_handleNodeClick = async(node) => {
  601. if (node.value === undefined) return
  602. const order = pd_lcdformData['gdbh']
  603. // //5.2流程单查询-获取工单工序生产进程右侧
  604. const getOrderProcessRight_list = await getOrderProcessRight({
  605. order: order,
  606. gxNo: node.value,
  607. })
  608. console.log(getOrderProcessRight_list)
  609. processList.value = getOrderProcessRight_list.data
  610. }
  611. // 导出excel
  612. const exportExcel = () => {
  613. const labels = tableCols1.map((item) => item.label)
  614. const props = tableCols1.map((item) => item.prop)
  615. const data = tableData1.value.map((item) => {
  616. const row = {}
  617. props.forEach((prop, index) => {
  618. row[labels[index]] = item?.[prop]
  619. })
  620. return row
  621. })
  622. if (data[0]?.[labels[0]] === undefined) {
  623. return
  624. }
  625. exportExcelFile(data)
  626. }
  627. </script>
  628. <style scoped>
  629. :deep(.plan-usage-low div) {
  630. color: red !important;
  631. }
  632. .JKWTree-container {
  633. display: flex;
  634. }
  635. .JKWTree-tree {
  636. width: 100%;
  637. background-color: #fff;
  638. /*background-color: rgba(241, 224, 224, 0.99);*/
  639. padding: 10px;
  640. margin-right: 20px;
  641. }
  642. .JKWTree-tree h3 {
  643. font-size: 15px;
  644. font-weight: 700;
  645. margin: 10px 0;
  646. }
  647. .JKWTree-content {
  648. flex: 1;
  649. }
  650. :deep(.el-table .yellow-row) {
  651. background: #ffff80;
  652. }
  653. :deep(.red-cell div) {
  654. color: #ff0000 !important;
  655. }
  656. /* 选中某行时的背景色 */
  657. :deep(.el-table__body tr.current-row) > td {
  658. background: #ff80ff !important;
  659. }
  660. </style>
  661. <style scoped>
  662. :deep(.el-table td .cell) {
  663. line-height: 20px !important;
  664. }
  665. :deep(.el-tabs__header) {
  666. margin-bottom: 0;
  667. }
  668. .search {
  669. margin-left: 0px !important;
  670. margin-right: 10px !important;
  671. }
  672. .bt {
  673. margin-left: 2px !important;
  674. padding: 3px !important;
  675. font-size: 12px;
  676. }
  677. .el-tabs__header {
  678. margin: 0px !important;
  679. }
  680. .gva-table-box {
  681. padding: 0px !important;
  682. }
  683. .mab {
  684. margin-bottom: 5px;
  685. }
  686. </style>