ProductionAchievementRate.vue 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663
  1. <template>
  2. <div>
  3. <layout>
  4. <layout-header>
  5. <div class="">
  6. <!-- 按钮部分-->
  7. <el-form ref="elSearchFormRef" class="demo-form-inline" :rules="searchRule" >
  8. <el-form-item>
  9. <el-button type="primary" class="bt" icon="download" @click="hzToExcel" >导出到Excel(汇总)</el-button>
  10. <el-button type="primary" class="bt" icon="download" @click="mxToExcel" >导出到Excel(明细)</el-button>
  11. <el-button type="primary" class="bt" icon="download" @click="rqToExcel" >按时段导出明细</el-button>
  12. </el-form-item>
  13. </el-form>
  14. </div>
  15. </layout-header>
  16. <layout>
  17. <!-- 左侧树侧形结构-->
  18. <layout-sider :resize-directions="['right']" :width="190" style="margin-right: 10px;">
  19. <div class="JKWTree-tree" style="height: 200px">
  20. <h3>设备生产效率达成统计</h3>
  21. <el-tree :data="treeData" :props="defaultProps" @node-click="handleNodeClick" @node-expand="handleNodeExpand">
  22. </el-tree>
  23. </div>
  24. </layout-sider>
  25. <!-- 右侧区域 -->
  26. <layout-content >
  27. <el-main>
  28. <div class="gva-table-box">
  29. <!-- 表格数据 -->
  30. <el-table ref="multipleTable"
  31. v-if="! ismachine"
  32. :show-overflow-tooltip="true"
  33. @selection-change="selectionChange($event)"
  34. :row-style="{ height: '20px' }" :selectable="checkboxT"
  35. :cell-style="{ padding: '0px' }" :header-row-style="{ height: '20px' }"
  36. :header-cell-style="{ padding: '0px' }" @row-click="pchzRowClick"
  37. :row-class-name="pchzrowClassStyle"
  38. highlight-current-row="true" @row-dblclick="gytableDatadoubleClick" id="pchztable"
  39. style="width: 100%;height: 30vh" border tooltip-effect="dark" :data="pchztableData" row-key="ID" >
  40. <el-table-column fixed align="left" label="机台编号" prop="机台编号" width="110"/>
  41. <el-table-column fixed align="left" label="机台名称" prop="机台名称" width="170"/>
  42. <el-table-column fixed align="left" label="班组" prop="班组" width="60"/>
  43. <el-table-column align="left" label="近7天综合达成率" prop="近7天综合达成率" width="135"/>
  44. <!-- 近七天列表 -->
  45. <template v-for="item in datelist">
  46. <el-table-column align="left" :label="item.display" :prop="item.prop" width="80"/>
  47. </template>
  48. <el-table-column align="left" label="实际总产量" prop="实际总产量" width="100"/>
  49. <el-table-column align="left" label="排产总产量" prop="排产总产量" width="100"/>
  50. <el-table-column align="left" label="实际产量1" prop="实际产量1" width="100"/>
  51. <el-table-column align="left" label="排产产量1" prop="排产产量1" width="100"/>
  52. <el-table-column align="left" label="实际产量2" prop="实际产量2" width="100"/>
  53. <el-table-column align="left" label="排产产量2" prop="排产产量2" width="100"/>
  54. <el-table-column align="left" label="实际产量3" prop="实际产量3" width="100"/>
  55. <el-table-column align="left" label="排产产量3" prop="排产产量3" width="100"/>
  56. <el-table-column align="left" label="实际产量4" prop="实际产量4" width="100"/>
  57. <el-table-column align="left" label="排产产量4" prop="排产产量4" width="100"/>
  58. <el-table-column align="left" label="实际产量5" prop="实际产量5" width="100"/>
  59. <el-table-column align="left" label="排产产量5" prop="排产产量5" width="100"/>
  60. <el-table-column align="left" label="实际产量6" prop="实际产量6" width="100"/>
  61. <el-table-column align="left" label="排产产量6" prop="排产产量6" width="100"/>
  62. <el-table-column align="left" label="实际产量7" prop="实际产量7" width="100"/>
  63. <el-table-column align="left" label="排产产量7" prop="排产产量7" width="100"/>
  64. </el-table>
  65. <el-table ref="JPmultipleTable"
  66. v-if="! ismachine"
  67. :show-overflow-tooltip="true"
  68. @selection-change="selectionChange($event)"
  69. :row-style="{ height: '20px' }" :row-class-name="totalClassName" :cell-class-name="tableDataCellClass"
  70. :cell-style="{ padding: '0px' }" :header-row-style="{ height: '20px' }"
  71. :header-cell-style="{ padding: '0px' }" @row-click="getUid"
  72. highlight-current-row="true" @row-dblclick="JPgytableDatadoubleClick" id="pcmxtable"
  73. style="width: 100%;height: 45vh" border tooltip-effect="dark" :data="pcmxtableData" row-key="ID" >
  74. <el-table-column align="left" fixed label="日期" prop="日期" width="110"/>
  75. <el-table-column align="left" fixed label="机台编号" prop="机台编号" width="90"/>
  76. <el-table-column align="left" fixed label="班组" prop="班组" width="70"/>
  77. <el-table-column align="left" label="工单编号" prop="工单编号" width="90"/>
  78. <el-table-column align="left" label="印件号" prop="印件号" width="70"/>
  79. <el-table-column align="left" label="印件名称" prop="印件名称" width="120"/>
  80. <el-table-column align="left" label="工序号" prop="工序号" width="70"/>
  81. <el-table-column align="left" label="工序名称" prop="工序名称" width="120"/>
  82. <el-table-column align="left" label="实际产量" prop="实际产量" width="90"/>
  83. <el-table-column align="left" label="排产标准产能" prop="排产标准产能" width="110"/>
  84. <el-table-column align="left" label="排产产量" prop="排产产量" width="90"/>
  85. <el-table-column align="left" label="上报运行工时" prop="上报运行工时" width="110"/>
  86. <el-table-column align="left" label="运行工时" prop="运行工时" width="110"/>
  87. <el-table-column align="left" label="工序计划辅助工时" prop="工序计划辅助工时" width="140"/>
  88. <el-table-column align="left" label="装版实际工时" prop="装版实际工时" width="110"/>
  89. <el-table-column align="left" label="保养工时" prop="保养工时" width="110"/>
  90. <el-table-column align="left" label="打样工时" prop="打样工时" width="110"/>
  91. <el-table-column align="left" label="版距" prop="版距" width="110"/>
  92. <el-table-column align="left" label="机台名称" prop="机台名称" width="130"/>
  93. </el-table>
  94. <el-table ref="multipleTable"
  95. v-if="ismachine"
  96. :show-overflow-tooltip="true"
  97. @selection-change="selectionChange($event)"
  98. :row-style="{ height: '20px' }" :selectable="checkboxT"
  99. :cell-style="{ padding: '0px' }" :header-row-style="{ height: '20px' }"
  100. :header-cell-style="{ padding: '0px' }" @row-click="sbhzRowClick"
  101. highlight-current-row="true" @row-dblclick="gytableDatadoubleClick" id="sbhztable"
  102. style="width: 100%;height: 30vh" border tooltip-effect="dark" :data="sbhztableData" row-key="ID" >
  103. <el-table-column fixed align="left" label="机台编号" prop="机台编号" width="90"/>
  104. <el-table-column fixed align="left" label="班组" prop="班组" width="70"/>
  105. <el-table-column align="left" label="实际产量" prop="实际产量" width="85"/>
  106. <el-table-column align="left" label="目标产量" prop="目标产量" width="85"/>
  107. <el-table-column align="left" label="负荷产量" prop="负荷产量" width="85"/>
  108. <el-table-column align="left" label="目标达成" prop="目标达成" width="85"/>
  109. <el-table-column align="left" label="综合利用率" prop="综合利用率" width="95"/>
  110. <el-table-column align="left" label="装版实际工时" prop="装板实际工时" width="110"/>
  111. <el-table-column align="left" label="装版补产工时" prop="装板补产工时" width="110"/>
  112. <el-table-column align="left" label="保养工时" prop="保养工时" width="110"/>
  113. <el-table-column align="left" label="打样总工时" prop="打样总工时" width="110"/>
  114. <el-table-column align="left" label="打样补产工时" prop="打样补产工时" width="110"/>
  115. <el-table-column align="left" label="异常总工时" prop="异常总工时" width="110"/>
  116. <el-table-column align="left" label="异常补时" prop="异常补时" width="110"/>
  117. <el-table-column align="left" label="运行工时" prop="运行工时" width="110"/>
  118. </el-table>
  119. <el-table ref="JPmultipleTable"
  120. v-if="ismachine"
  121. :show-overflow-tooltip="true"
  122. @selection-change="selectionChange($event)"
  123. :row-style="{ height: '20px' }" :cell-class-name="tableDataCellClass"
  124. :cell-style="{ padding: '0px' }" :header-row-style="{ height: '20px' }"
  125. :header-cell-style="{ padding: '0px' }" @row-click="sbmxRowClick"
  126. :row-class-name="sbmxrowClassStyle"
  127. highlight-current-row="true" @row-dblclick="JPgytableDatadoubleClick" id="sbmxtable"
  128. style="width: 100%;height: 45vh" border tooltip-effect="dark" :data="sbmxtableData" row-key="ID" >
  129. <el-table-column align="left" fixed label="机台编号" prop="机台编号" width="90"/>
  130. <el-table-column align="left" fixed label="日期" prop="日期" width="110"/>
  131. <el-table-column align="left" fixed label="班组" prop="班组" width="70"/>
  132. <el-table-column align="left" label="工单编号" prop="工单编号" width="90"/>
  133. <el-table-column align="left" label="印件名称" prop="印件名称" width="110"/>
  134. <el-table-column align="left" label="印件工序" prop="工序名称" width="110"/>
  135. <el-table-column align="left" label="实际产量" prop="实际产量" width="100"/>
  136. <el-table-column align="left" label="目标产量" prop="目标产量" width="90"/>
  137. <el-table-column align="left" label="负荷产量" prop="负荷产量" width="90"/>
  138. <el-table-column align="left" label="目标达成" prop="目标达成" width="90"/>
  139. <el-table-column align="left" label="综合利用率" prop="综合利用率" width="100"/>
  140. <el-table-column align="left" label="装版实际工时" prop="装版实际工时" width="110"/>
  141. <el-table-column align="left" label="装版补产工时" prop="装版补产工时" width="110"/>
  142. <el-table-column align="left" label="保养工时" prop="保养工时" width="100"/>
  143. <el-table-column align="left" label="打样总工时" prop="打样总工时" width="100"/>
  144. <el-table-column align="left" label="打样补产工时" prop="打样补产工时" width="110"/>
  145. <el-table-column align="left" label="异常总工时" prop="异常总工时" width="100"/>
  146. <el-table-column align="left" label="异常补时" prop="异常补时" width="100"/>
  147. <el-table-column align="left" label="运行工时" prop="运行工时" width="100"/>
  148. <el-table-column align="left" label="小时产能" prop="小时产能" width="100"/>
  149. <el-table-column align="left" label="最高限速" prop="平均车速" width="100"/>
  150. <!-- <el-table-column align="left" label="理论生产效率" prop="理论生产效率" width="110"/> -->
  151. <el-table-column align="left" label="难度系数" prop="难度系数" width="100"/>
  152. <!-- <el-table-column align="left" label="版距" prop="版距" width="100"/> -->
  153. </el-table>
  154. </div>
  155. <!-- 按时段导出弹窗 -->
  156. <el-dialog v-model="onrqexcel" title="达成率明细导出" destroy-on-close style="height: 30%;width: 20%;">
  157. <el-form-item label="部门" label-width="100px">
  158. <el-select v-model="excelbm" placeholder="选择部门">
  159. <el-option
  160. v-for="item in bmoptions"
  161. :key="item.value"
  162. :label="item.label"
  163. :value="item.value">
  164. </el-option>
  165. </el-select>
  166. </el-form-item>
  167. <el-form-item label="选择年月" label-width="100px">
  168. <el-date-picker
  169. v-model="excelrq"
  170. type="daterange"
  171. range-separator="至"
  172. start-placeholder="开始日期"
  173. end-placeholder="结束日期"
  174. :default-value="new Date()"
  175. @change="onchange_data"
  176. style="width: 200px;"
  177. />
  178. </el-form-item>
  179. <template #footer>
  180. <div class="dialog-footer" style="text-align: right;">
  181. <el-button @click="rqexcelcloseDialog">取消</el-button>
  182. <el-button type="primary" @click="rqexcelonDialog">确定</el-button>
  183. </div>
  184. </template>
  185. </el-dialog>
  186. </el-main>
  187. </layout-content>
  188. </layout>
  189. </layout>
  190. </div>
  191. </template>
  192. <script setup>
  193. // 全量引入格式化工具 请按需保留
  194. import { Layout, LayoutSider, LayoutContent } from '@arco-design/web-vue';
  195. import {PARLeftmenu,PARlist,PARDetail,PARlistpro,PARDetailpro,PARDateExcel} from "@/api/mes/job.js"
  196. import {ref, reactive} from 'vue'
  197. import * as XLSX from 'xlsx'
  198. import { exportExcelFile } from '@/utils/excel'
  199. import {ElMessage} from "element-plus";
  200. import { start } from 'nprogress';
  201. defineOptions({name: 'Company'})
  202. const treeData = ref([]);
  203. const defaultProps = {
  204. label: 'label',
  205. children: 'children'
  206. };
  207. const getTreeData = async () => {
  208. try {
  209. const response = await PARLeftmenu();
  210. console.log('接口原始数据:', response);
  211. if (!response) {
  212. throw new Error('接口返回数据为空');
  213. }
  214. const rawData = response.data;
  215. const newTreeData = [];
  216. // 1. 处理排产计划达成率统计
  217. if (rawData['排产计划达成率统计']) {
  218. const planCompletionNode = {
  219. label: '排产计划达成率统计',
  220. children: rawData['排产计划达成率统计']
  221. .map(item => ({
  222. label: item['使用部门'].trim() || '未知部门',
  223. }))
  224. };
  225. newTreeData.push(planCompletionNode);
  226. }
  227. // 2. 处理设备工时达成率统计
  228. if (rawData['设备工时达成率统计']) {
  229. const equipmentHoursNode = {
  230. label: '设备工时达成率统计',
  231. children: []
  232. };
  233. // 获取所有年份并按降序排序
  234. const sortedYears = Object.keys(rawData['设备工时达成率统计'])
  235. .sort((a, b) => parseInt(b) - parseInt(a));
  236. for (const year of sortedYears) {
  237. const yearData = rawData['设备工时达成率统计'][year];
  238. if (!yearData) continue;
  239. const yearNode = {
  240. label: year,
  241. children: []
  242. };
  243. // 获取该年所有月份并按降序排序
  244. const sortedMonths = Object.keys(yearData)
  245. .sort((a, b) => {
  246. // 处理格式为YYYYMM的月份键
  247. const monthA = a.length === 6 ? parseInt(a.substring(4)) : parseInt(a);
  248. const monthB = b.length === 6 ? parseInt(b.substring(4)) : parseInt(b);
  249. return monthB - monthA;
  250. });
  251. for (const monthKey of sortedMonths) {
  252. const monthData = yearData[monthKey];
  253. if (!monthData) continue;
  254. const monthName = monthKey.length === 6
  255. ? `${monthKey.substring(4)}月`
  256. : monthKey;
  257. const monthNode = {
  258. label: `${year}年${monthName}`,
  259. children: monthData
  260. .filter(dept => dept) // 过滤空部门
  261. .map(dept => ({
  262. label: dept.trim() || '未知部门',
  263. rq: monthKey, // 添加月份键值
  264. }))
  265. };
  266. yearNode.children.push(monthNode);
  267. }
  268. equipmentHoursNode.children.push(yearNode);
  269. }
  270. newTreeData.push(equipmentHoursNode);
  271. }
  272. console.log('最终树数据:', newTreeData);
  273. treeData.value = newTreeData;
  274. } catch (error) {
  275. console.error('加载树数据失败:', error);
  276. treeData.value = [];
  277. }
  278. };
  279. // 初始化加载数据
  280. getTreeData();
  281. const ismachine = ref(false)
  282. const datelist = ref([]);
  283. const pchztableData = ref([]);
  284. const pcmxtableData = ref([]);
  285. const sbhztableData = ref([]);
  286. const sbmxtableData = ref([]);
  287. // 节点点击事件处理
  288. const handleNodeClick = async (nodeData) => {
  289. console.log('节点点击:', nodeData)
  290. if(!nodeData.children){
  291. console.log('点击了车间')
  292. //根据是否有rq判断点击的是排产还是设备
  293. if(!nodeData.rq){
  294. ismachine.value = false;
  295. const response = await PARlist({Machine:nodeData.label});
  296. // 创建日期映射表
  297. const dateMap = response.data.list.map(fullDate => {
  298. const [year, month, day] = fullDate.split('-');
  299. const shortKey = `${month.padStart(2, '0')}-${day.padStart(2, '0')}`; // 显示用 05-08
  300. const longKey = `${month.padStart(2, '0')}月${day.padStart(2, '0')}日`; // 数据键 05月08日
  301. return {
  302. display: shortKey, // 表头显示
  303. prop: longKey // 对应数据字段
  304. };
  305. });
  306. datelist.value = dateMap; // 存储映射关系
  307. pchztableData.value = response.data.data;
  308. }else{
  309. ismachine.value = true;
  310. const response = await PARlistpro({Machine:nodeData.label,rq:nodeData.rq});
  311. sbhztableData.value = response.data;
  312. }
  313. }
  314. }
  315. // 节点展开事件处理
  316. const handleNodeExpand = (nodeData, node) => {
  317. console.log('节点展开:', nodeData)
  318. }
  319. const currentjtbh = ref('')//储存设备汇总表格当前选中的机台编号
  320. const currentrq = ref('')//储存设备明细表格当前选中的日期
  321. // 排产表格行点击事件处理
  322. const pchzRowClick = async (row) => {
  323. console.log('行点击:', row)
  324. currentjtbh.value = row.机台编号;
  325. const response = await PARDetail({jtbh:row.机台编号,bz:row.班组})
  326. if (response?.code === 0 && Array.isArray(response.data)) {
  327. pcmxtableData.value = response.data;
  328. console.log('表格数据更新成功:', response.data);
  329. }
  330. }
  331. // 设备汇总表格行点击事件处理
  332. const sbhzRowClick = async (row) => {
  333. console.log('行点击:', row)
  334. const response = await PARDetailpro({jtbh:row.机台编号,bz:row.班组,rq:row.sczl_rq})
  335. if (response?.code === 0 && Array.isArray(response.data)) {
  336. sbmxtableData.value = response.data;
  337. console.log('表格数据更新成功:', response.data);
  338. }
  339. }
  340. //设备明细表格行点击事件处理
  341. const sbmxRowClick = async (row) => {
  342. currentrq.value = row.日期;
  343. }
  344. //导出按钮(汇总)
  345. const hzToExcel = async () => {
  346. try {
  347. // 获取数据
  348. const el = document.getElementById(ismachine.value ? 'sbhztable' : 'pchztable');
  349. const filename = '生产效率统计汇总导出.xlsx';
  350. const worksheet = XLSX.utils.table_to_sheet(el, { raw: true });
  351. //从某列开始转化成数字
  352. //设置从C列开始为数字格式
  353. const range = XLSX.utils.decode_range(worksheet['!ref']);
  354. for (let col = 2; col <= range.e.c; col++) { // 从C列(索引2)开始
  355. for (let row = range.s.r + 1; row <= range.e.r; row++) { // 跳过表头行
  356. const cellAddress = XLSX.utils.encode_cell({ r: row, c: col });
  357. if (worksheet[cellAddress]) {
  358. // 尝试转换为数字
  359. const cellValue = worksheet[cellAddress].v;
  360. const numValue = Number(cellValue);
  361. if (!isNaN(numValue)) {
  362. worksheet[cellAddress].t = 'n'; // 数字类型
  363. worksheet[cellAddress].v = numValue; // 更新值
  364. worksheet[cellAddress].z = '0'; // 数字格式
  365. }
  366. }
  367. }
  368. }
  369. // 创建并导出工作簿
  370. const wb = XLSX.utils.book_new();
  371. XLSX.utils.book_append_sheet(wb, worksheet, 'Sheet1');
  372. XLSX.writeFile(wb, filename);
  373. } catch (error) {
  374. console.error('导出失败:', error);
  375. ElMessage.error('导出数据失败,请重试');
  376. }
  377. };
  378. //导出按钮(汇总)
  379. const mxToExcel = async () => {
  380. try {
  381. // 获取数据
  382. const el = document.getElementById(ismachine.value ? 'sbmxtable' : 'pcmxtable');
  383. const filename = '生产效率统计明细导出.xlsx';
  384. const worksheet = XLSX.utils.table_to_sheet(el, { raw: true });
  385. //从某列开始转化成数字
  386. const range = XLSX.utils.decode_range(worksheet['!ref']);
  387. for (let col = 4; col <= range.e.c; col++) { // 从C列(索引2)开始
  388. for (let row = range.s.r + 1; row <= range.e.r; row++) { // 跳过表头行
  389. const cellAddress = XLSX.utils.encode_cell({ r: row, c: col });
  390. if (worksheet[cellAddress]) {
  391. // 尝试转换为数字
  392. const cellValue = worksheet[cellAddress].v;
  393. const numValue = Number(cellValue);
  394. if (!isNaN(numValue)) {
  395. worksheet[cellAddress].t = 'n'; // 数字类型
  396. worksheet[cellAddress].v = numValue; // 更新值
  397. worksheet[cellAddress].z = '0'; // 数字格式
  398. }
  399. }
  400. }
  401. }
  402. // 创建并导出工作簿
  403. const wb = XLSX.utils.book_new();
  404. XLSX.utils.book_append_sheet(wb, worksheet, 'Sheet1');
  405. XLSX.writeFile(wb, filename);
  406. } catch (error) {
  407. console.error('导出失败:', error);
  408. ElMessage.error('导出数据失败,请重试');
  409. }
  410. };
  411. const onrqexcel = ref(false);
  412. const excelbm = ref(''); // 部门
  413. const excelrq = ref([]); // 初始化为数组,用于存储日期范围
  414. const bmoptions = ref([]); // 部门下拉选项
  415. // 打开导出弹窗时
  416. const rqToExcel = async () => {
  417. //动态加载部门数据
  418. if (treeData.value[0]?.children) {
  419. bmoptions.value = treeData.value[0].children.map(item => ({
  420. label: item.label,
  421. value: item.label,
  422. }));
  423. }
  424. onrqexcel.value = true;
  425. };
  426. const onchange_data = (val) => {
  427. if (val && val.length === 2) {
  428. // 格式化单个日期为 "YYYY-MM-DD"
  429. const formatDate = (date) => {
  430. const year = date.getFullYear();
  431. const month = String(date.getMonth() + 1).padStart(2, '0');
  432. const day = String(date.getDate()).padStart(2, '0'); // 获取日,并补零
  433. return `${year}-${month}-${day}`;
  434. };
  435. // 分别格式化开始日期和结束日期
  436. excelrq.value = [formatDate(val[0]), formatDate(val[1])];
  437. } else {
  438. excelrq.value = []; // 清空选择
  439. }
  440. };
  441. // 确定导出
  442. const rqexcelonDialog = async () => {
  443. if (excelrq.value.length !== 2) {
  444. ElMessage.warning('请选择完整的日期范围');
  445. return;
  446. }
  447. try {
  448. // 获取数据
  449. const response = await PARDateExcel({
  450. start_rq: excelrq.value[0],
  451. end_rq: excelrq.value[1],
  452. bm: excelbm.value
  453. });
  454. const data = response.data; // 假设返回的是数组格式的数据
  455. // 1. 准备表头
  456. const headers = Object.keys(data[0] || {});
  457. // 2. 准备工作表数据(包含表头和数据行)
  458. const wsData = [
  459. headers, // 表头行
  460. ...data.map(row => headers.map(key => row[key])) // 数据行
  461. ];
  462. // 3. 创建工作表
  463. const worksheet = XLSX.utils.aoa_to_sheet(wsData);
  464. // 4. 数字类型转换(从第5列开始,索引4)
  465. const range = XLSX.utils.decode_range(worksheet['!ref']);
  466. for (let col = 4; col <= range.e.c; col++) {
  467. for (let row = range.s.r + 1; row <= range.e.r; row++) {
  468. const cellAddress = XLSX.utils.encode_cell({ r: row, c: col });
  469. if (worksheet[cellAddress]) {
  470. const cellValue = worksheet[cellAddress].v;
  471. const numValue = Number(cellValue);
  472. if (!isNaN(numValue)) {
  473. worksheet[cellAddress].t = 'n';
  474. worksheet[cellAddress].v = numValue;
  475. worksheet[cellAddress].z = '0';
  476. }
  477. }
  478. }
  479. }
  480. // 5. 创建并导出工作簿
  481. const wb = XLSX.utils.book_new();
  482. XLSX.utils.book_append_sheet(wb, worksheet, 'Sheet1');
  483. XLSX.writeFile(wb, '生产效率统计按时段明细导出.xlsx');
  484. } catch (error) {
  485. console.error('导出失败:', error);
  486. ElMessage.error('导出数据失败,请重试');
  487. }
  488. };
  489. // 关闭弹窗
  490. const rqexcelcloseDialog = () => {
  491. onrqexcel.value = false;
  492. };
  493. //===============颜色==================================
  494. //排产汇总表格样式
  495. const pchzrowClassStyle = ({row,rowIndex}) =>{
  496. if(row['机台编号']== currentjtbh.value){
  497. return "warning-row"
  498. }
  499. }
  500. //设备明细表格样式
  501. const sbmxrowClassStyle = ({row,rowIndex}) =>{
  502. if(row['日期']== currentrq.value){
  503. return "warning-row"
  504. }
  505. }
  506. </script>
  507. <style scoped>
  508. .form-container {
  509. display: flex;
  510. flex-wrap: wrap;
  511. }
  512. .form-column {
  513. /*flex: 1;*/
  514. margin-right: 15px; /* 调整列之间的间距 */
  515. }
  516. /* 左侧输入框宽度调整 */
  517. .form-column .el-form-item .el-input {
  518. width: 150px; /* 调整左侧输入框的宽度 */
  519. }
  520. :deep(.hui-plan-usage-lows div) {
  521. color: #8c939d !important;
  522. }
  523. :deep(.lan-plan-usage-lows div) {
  524. color: blue !important;
  525. font-weight: bold;
  526. }
  527. /* 媒体查询,根据需要调整断点 */
  528. @media screen and (max-width: 768px) {
  529. .form-column {
  530. flex: 1 0 100%; /* 在小屏幕下变成单列布局 */
  531. margin-right: 0;
  532. }
  533. }
  534. /*:deep(.el-table td .cell) {*/
  535. /* line-height: 30px !important;*/
  536. /*}*/
  537. .JKWTree-container {
  538. display: flex;
  539. }
  540. .JKWTree-tree {
  541. /*width: 300px;*/
  542. background-color: #fff;
  543. padding: 10px;
  544. margin-right: 20px;
  545. }
  546. .JKWTree-tree h3 {
  547. font-size: 15px;
  548. font-weight: 700;
  549. margin: 10px 0;
  550. }
  551. .JKWTree-content {
  552. flex: 1;
  553. }
  554. :deep(.el-table__body .warning-row) {
  555. background: #FFFF80 !important;
  556. }
  557. /* 选中某行时的背景色 */
  558. :deep(.el-table__body tr.current-row) > td {
  559. background: #ff80ff !important;
  560. }
  561. </style>
  562. <style scoped>
  563. :deep(.el-table td .cell) {
  564. line-height: 20px !important;
  565. }
  566. :deep(.el-tabs__header){
  567. margin-bottom: 0;
  568. }
  569. .search{
  570. margin-left: 0px !important;
  571. margin-right: 10px !important;
  572. }
  573. .bt{
  574. margin-left: 2px !important;
  575. padding: 3px !important;
  576. font-size: 12px;
  577. }
  578. .el-tabs__header{
  579. margin: 0px !important;
  580. }
  581. .gva-table-box{
  582. padding: 0px !important;
  583. }
  584. .mab{
  585. margin-bottom: 5px;
  586. }
  587. </style>