Compare commits

...

11 Commits

Author SHA1 Message Date
ab486dd71b 首页样式调整 2025-07-07 15:49:00 +08:00
0b689b5452 首页样式 2025-07-04 17:02:20 +08:00
zwq
bbd9972761 ry-bug 2025-03-10 16:33:55 +08:00
zwq
8e9b2f6444 更新 2025-02-27 13:54:28 +08:00
zwq
c83a7afadb 更新 2025-02-24 14:10:34 +08:00
zwq
b43876fe67 更新 2025-02-19 14:13:47 +08:00
zwq
f143c5e2d9 . 2025-01-16 08:34:17 +08:00
zwq
0b03e6d44b 更新 2025-01-15 13:35:15 +08:00
zwq
19dbe38458 更新 2025-01-10 15:07:05 +08:00
zwq
43ba33062b 更新 2024-11-29 16:42:13 +08:00
zwq
ca390fd764 更新汝阳bug 2024-11-26 16:51:07 +08:00
128 changed files with 27812 additions and 11551 deletions

View File

@@ -1,7 +1,7 @@
### ###
# @Author: Do not edit # @Author: Do not edit
# @Date: 2023-08-29 09:40:39 # @Date: 2023-08-29 09:40:39
# @LastEditTime: 2024-09-10 14:43:39 # @LastEditTime: 2024-11-25 14:31:39
# @LastEditors: zwq # @LastEditors: zwq
# @Description: # @Description:
### ###
@@ -9,13 +9,11 @@
ENV = 'development' ENV = 'development'
# 页面标题 # 页面标题
VUE_APP_TITLE = 成本管理系统 VUE_APP_TITLE = 智能监控分析系统
# 芋道管理系统/开发环境 # 芋道管理系统/开发环境
# VUE_APP_BASE_API = 'http://192.168.1.49:48080' # VUE_APP_BASE_API = 'http://192.168.8.22:48080'
VUE_APP_BASE_API = 'http://line.kszny.picaiba.com' VUE_APP_BASE_API = 'http://172.16.32.79:48082'
# VUE_APP_BASE_API = 'http://192.168.1.40:48080'
# VUE_APP_BASE_API = 'http://192.168.1.188:48080'
# 路由懒加载 # 路由懒加载
VUE_CLI_BABEL_TRANSPILE_MODULES = true VUE_CLI_BABEL_TRANSPILE_MODULES = true

View File

@@ -2,14 +2,14 @@
# @Author: zwq # @Author: zwq
# @Date: 2024-03-27 15:49:55 # @Date: 2024-03-27 15:49:55
# @LastEditors: zwq # @LastEditors: zwq
# @LastEditTime: 2024-09-10 15:19:19 # @LastEditTime: 2024-10-30 11:08:47
# @Description: # @Description:
### ###
# 生产环境配置 # 生产环境配置
ENV = 'production' ENV = 'production'
# 页面标题 # 页面标题
VUE_APP_TITLE = 成本管理系统 VUE_APP_TITLE = 智能监控分析系统
# 芋道管理系统/生产环境 # 芋道管理系统/生产环境
# VUE_APP_BASE_API = '/prod-api' # VUE_APP_BASE_API = '/prod-api'

View File

@@ -42,6 +42,7 @@
}, },
"dependencies": { "dependencies": {
"@babel/parser": "7.18.4", "@babel/parser": "7.18.4",
"@jiaminghi/data-view": "^2.10.0",
"@riophae/vue-treeselect": "0.4.0", "@riophae/vue-treeselect": "0.4.0",
"axios": "0.27.2", "axios": "0.27.2",
"benz-amr-recorder": "^1.1.5", "benz-amr-recorder": "^1.1.5",
@@ -52,6 +53,7 @@
"crypto-js": "^4.0.0", "crypto-js": "^4.0.0",
"diagram-js": "^12.3.0", "diagram-js": "^12.3.0",
"echarts": "5.4.0", "echarts": "5.4.0",
"el-tree-transfer": "^2.4.7",
"element-ui": "2.15.12", "element-ui": "2.15.12",
"file-saver": "^2.0.5", "file-saver": "^2.0.5",
"fuse.js": "6.6.2", "fuse.js": "6.6.2",

View File

@@ -1,3 +1,10 @@
/*
* @Author: zwq
* @Date: 2024-10-29 09:47:40
* @LastEditors: zwq
* @LastEditTime: 2025-02-26 16:27:48
* @Description:
*/
import request from '@/utils/request' import request from '@/utils/request'
// 创建实时数据采集配置 // 创建实时数据采集配置
@@ -52,3 +59,11 @@ export function exportEquipmentPlcExcel(query) {
responseType: 'blob' responseType: 'blob'
}) })
} }
// 获得code
export function getCode() {
return request({
url: '/base/equipment-group/getCode',
method: 'get'
})
}

View File

@@ -1,3 +1,10 @@
/*
* @Author: zwq
* @Date: 2024-10-29 09:47:40
* @LastEditors: zwq
* @LastEditTime: 2025-02-12 09:25:11
* @Description:
*/
import request from '@/utils/request' import request from '@/utils/request'
// 获得工厂产线工段设备树形结构 // 获得工厂产线工段设备树形结构
export function getTree() { export function getTree() {

View File

@@ -51,6 +51,13 @@ export function getCode() {
}) })
} }
// 获得可用的班次列表
export function listClassesEnabled() {
return request({
url: '/base/group-classes/listEnable',
method: 'get'
})
}
// 导出班次基础信息 Excel // 导出班次基础信息 Excel
export function exportGroupClassesExcel(query) { export function exportGroupClassesExcel(query) {
return request({ return request({

View File

@@ -0,0 +1,125 @@
import request from '@/utils/request'
// 创建排班计划配置基础信息
export function createGroupPlan(data) {
return request({
url: '/base/group-scheduling-plan/create',
method: 'post',
data: data
})
}
// 更新排班计划配置基础信息
export function updateGroupPlan(data) {
return request({
url: '/base/group-scheduling-plan/update',
method: 'put',
data: data
})
}
// 删除排班计划配置基础信息
export function deleteGroupPlan(id) {
return request({
url: '/base/group-scheduling-plan/delete?id=' + id,
method: 'delete'
})
}
// 获得排班计划配置基础信息
export function getGroupPlan(id) {
return request({
url: '/base/group-scheduling-plan/get?id=' + id,
method: 'get'
})
}
// 获得排班计划配置基础信息分页
export function getGroupPlanPage(query) {
return request({
url: '/base/group-scheduling-plan/page',
method: 'get',
params: query
})
}
// 获得所有排班计划列表
export function groupPlanList() {
return request({
url: '/base/group-scheduling-plan/listAll',
method: 'get'
})
}
// 获得排班计划相关班组列表
export function groupPlanTeamList(id) {
return request({
url: '/base/group-scheduling-plan-team/teamListByPlanId?planId=' + id,
method: 'get'
})
}
// 获得排班计划相关班次列表
export function groupPlanClassesList(id) {
return request({
url: '/base/group-scheduling-plan-classes/classesListByPlanId?planId=' + id,
method: 'get'
})
}
// 获取code
export function getCode() {
return request({
url: '/base/group-scheduling-plan/getCode',
method: 'get'
})
}
// 导出排班计划配置基础信息 Excel
export function exportGroupPlanExcel(query) {
return request({
url: '/base/group-scheduling-plan/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}
// 获得产线工段树形结构
export function getGroupPlanTree() {
return request({
url: '/base/group-scheduling-plan/getLineSectionTree',
method: 'get'
})
}
// 创建排班计划产线工段
export function createGroupPlanLine(data) {
return request({
url: '/base/group-scheduling-plan-line-section/createPlanLineSection',
method: 'post',
data: data
})
}
// 更新排班计划产线工段
export function updateGroupPlanLine(data) {
return request({
url: '/base/group-scheduling-plan-line-section/updatePlanLineSection',
method: 'put',
data: data
})
}
// 获得排班计划配置基础信息
export function getGroupPlanLine(id) {
return request({
url: '/base/group-scheduling-plan-line-section/getLineSectionByPlanId?planId=' + id,
method: 'get'
})
}
// 获得当前登录用户所在部门id
export function getLoginUserDeptId() {
return request({
url: '/base/group-scheduling-plan-line-section/getLoginUserDeptId',
method: 'get'
})
}

View File

@@ -0,0 +1,60 @@
import request from '@/utils/request'
// 创建排班规则基础信息
export function createGroupRule(data) {
return request({
url: '/base/group-scheduling-rule/create',
method: 'post',
data: data
})
}
// 作废排班规则
export function disableGroupRule(id) {
return request({
url: '/base/group-scheduling-rule/disable?id=' + id,
method: 'post',
})
}
// 更新排班规则基础信息
export function updateGroupRule(data) {
return request({
url: '/base/group-scheduling-rule/update',
method: 'put',
data: data
})
}
// 删除排班规则基础信息
export function deleteGroupRule(id) {
return request({
url: '/base/group-scheduling-rule/delete?id=' + id,
method: 'delete'
})
}
// 获得排班规则基础信息
export function getGroupRule(id) {
return request({
url: '/base/group-scheduling-rule/get?id=' + id,
method: 'get'
})
}
// 获得排班规则基础信息分页
export function getGroupRulePage(query) {
return request({
url: '/base/group-scheduling-rule/page',
method: 'get',
params: query
})
}
// 导出排班规则基础信息 Excel
export function exportGroupRuleExcel(query) {
return request({
url: '/base/group-scheduling-rule/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}

View File

@@ -58,3 +58,49 @@ export function listEnabled() {
method: 'get' method: 'get'
}) })
} }
// 获得班组组员信息分页
export function groupTeamPage(query) {
return request({
url: '/base/group-team-det/page',
method: 'get',
params: query
})
}
// 获得班组组员信息
export function groupTeamDet(query) {
return request({
url: '/base/group-team-det/get',
method: 'get',
params: query
})
}
// 创建班组组员信息
export function teamDetCreate(data) {
return request({
url: '/base/group-team-det/create',
method: 'post',
data: data
})
}
// 更新班组组员信息
export function teamDetUpdate(data) {
return request({
url: '/base/group-team-det/update',
method: 'put',
data: data
})
}
// 删除班组组员信息
export function teamDetDelete(query) {
return request({
url: '/base/group-team-det/delete',
method: 'delete',
params: query
})
}

View File

@@ -8,7 +8,14 @@ export function getPreset(query) {
params: query params: query
}) })
} }
// 获取某月预排班
export function getScheduling(query) {
return request({
url: '/base/group-team-scheduling/getScheduling',
method: 'get',
params: query
})
}
// 批量创建-更新排班信息 // 批量创建-更新排班信息
export function createOrUpdateList(data) { export function createOrUpdateList(data) {
return request({ return request({
@@ -25,4 +32,23 @@ export function autoSet(query) {
method: 'get', method: 'get',
params: query params: query
}) })
} }
// 获得排班信息分页
export function schedulingPage(query) {
return request({
url: '/base/group-team-scheduling/page',
method: 'get',
params: query
})
}
// 导出Excel
export function exportSchedulingExcel(query) {
return request({
url: '/base/group-team-scheduling/export-excel',
method: 'get',
params: query,
responseType: 'blob'
})
}

26
src/api/base/worker.js Normal file
View File

@@ -0,0 +1,26 @@
import request from '@/utils/request'
// 获得所有员工列表
export function getWorkerList() {
return request({
url: '/base/core-worker/listAll',
method: 'get'
})
}
// 获得员工
export function getWorker(query) {
return request({
url: '/base/core-worker/get',
method: 'get',
params: query
})
}
// 获得该班组其他可选组员列表(除去现有组员)
export function otherWorkerList(query) {
return request({
url: '/base/group-team-det/otherWorkerList',
method: 'get',
params: query
})
}

View File

@@ -1,8 +1,8 @@
/* /*
* @Author: zhp * @Author: zhp
* @Date: 2023-09-12 14:07:04 * @Date: 2023-09-12 14:07:04
* @LastEditTime: 2023-09-13 09:53:45 * @LastEditTime: 2025-01-08 15:47:17
* @LastEditors: zhp * @LastEditors: zwq
* @Description: * @Description:
*/ */
import request from '@/utils/request' import request from '@/utils/request'
@@ -22,3 +22,26 @@ export function getCT(data) {
data: data data: data
}) })
} }
// 获取产线平衡分析数据new
export function getNewCTNow(data) {
return request({
url: '/analysis/production-analysis/getNewCTNow',
method: 'post',
data: data
})
}
// 获取产线平衡分析数据趋势图new
export function getNewCTCharts(data) {
return request({
url: '/analysis/production-analysis/getNewCTCharts',
method: 'post',
data: data
})
}
// 获取产线平衡分析数据设备listnew
export function getNewCTDet(id) {
return request({
url: '/analysis/production-analysis/getNewCTDet?lineId='+id,
method: 'get',
})
}

View File

@@ -58,3 +58,12 @@ export function exportFactoryExcel(query) {
responseType: 'blob' responseType: 'blob'
}) })
} }
// 获取产线设备状态
export function getLineEqStatus(data) {
return request({
url: '/base/production-line/getLineEqStatus',
method: 'post',
data: data
})
}

View File

@@ -0,0 +1,28 @@
import request from '@/utils/request'
// 切换工艺
export function switchLineBindProcess(data) {
return request({
url: '/base/line-bind-process/switch',
method: 'put',
data: data
})
}
// 获得产线工艺目前生产工艺
export function getLineBindProcessPage(query) {
return request({
url: '/base/line-bind-process/nowList',
method: 'get',
params: query
})
}
// 获得产线工艺log分页
export function getLineBindProcessLogPage(query) {
return request({
url: '/base/line-bind-process/logPage',
method: 'get',
params: query
})
}

View File

@@ -16,6 +16,14 @@ export function switchLineBindProduct(data) {
data: data data: data
}) })
} }
// 切换产线是否可以自动
export function switchAutoProduct(data) {
return request({
url: '/base/line-bind-product/switchAuto',
method: 'put',
data: data
})
}
// 更新产线目前生产产品表 主要为更新 // 更新产线目前生产产品表 主要为更新
export function updateLineBindProduct(data) { export function updateLineBindProduct(data) {
return request({ return request({

View File

@@ -1,9 +1,9 @@
/* /*
* @Author: Do not edit * @Author: Do not edit
* @Date: 2023-09-12 09:44:53 * @Date: 2023-09-12 09:44:53
* @LastEditTime: 2023-09-13 16:11:41 * @LastEditTime: 2025-01-07 09:57:36
* @LastEditors: DY * @LastEditors: zwq
* @Description: * @Description:
*/ */
import request from '@/utils/request' import request from '@/utils/request'
@@ -17,9 +17,43 @@ export function getPdlAutoReport(data) {
} }
// 获得所有工厂产线列表 // 获得所有工厂产线列表
export function getPdList() { export function getPdList(id) {
return request({ return request({
url: '/base/production-line/listAll', url: '/base/production-line/listAll' + (id ? '?id=' + id : ''),
method: 'get' method: 'get'
}) })
} }
// 获得产线自动报表
export function getLineAuto(data) {
return request({
url: '/monitoring/production-monitor/getPdlAutoReportNew',
method: 'post',
data: data
})
}
// 获得产品自动报表
export function getProductAuto(data) {
return request({
url: '/monitoring/production-monitor/getProcessAutoReportNew',
method: 'post',
data: data
})
}
// 班组自动报表分页
export function getTeamReportPage(data) {
return request({
url: '/monitoring/team-auto-report/page',
method: 'post',
data: data
})
}
// 班组自动报表分页详细
export function getTeamReportPageDet(id) {
return request({
url: '/monitoring/team-auto-report/pageDet?id=' + id,
method: 'get',
})
}

View File

@@ -1,9 +1,9 @@
/* /*
* @Author: Do not edit * @Author: Do not edit
* @Date: 2023-09-12 09:44:53 * @Date: 2023-09-12 09:44:53
* @LastEditTime: 2023-09-14 10:25:46 * @LastEditTime: 2025-03-03 10:43:34
* @LastEditors: DY * @LastEditors: zwq
* @Description: * @Description:
*/ */
import request from '@/utils/request' import request from '@/utils/request'
@@ -22,4 +22,22 @@ export function getPdList() {
url: '/base/production-line/listAll', url: '/base/production-line/listAll',
method: 'get' method: 'get'
}) })
} }
// 产线统计数据查询-历史
export function getPdlAutoReportNewSearch(data) {
return request({
url: '/monitoring/production-monitor/getPdlAutoReportNewSearch',
method: 'post',
data: data
})
}
// 产线统计数据查询-当前
export function getPdlAutoReportNewSearchNow(data) {
return request({
url: '/monitoring/production-monitor/getPdlAutoReportNewSearchNow',
method: 'post',
data: data,
timeout: 60000,
})
}

View File

@@ -1 +1,18 @@
<svg width="128" height="128" xmlns="http://www.w3.org/2000/svg"><path d="M38.47 52L52 38.462l-23.648-23.67L43.209 0H.035L0 43.137l14.757-14.865L38.47 52zm74.773 47.726L89.526 76 76 89.536l23.648 23.672L84.795 128h43.174L128 84.863l-14.757 14.863zM89.538 52l23.668-23.648L128 43.207V.038L84.866 0 99.73 14.76 76 38.472 89.538 52zM38.46 76L14.792 99.651 0 84.794v43.173l43.137.033-14.865-14.757L52 89.53 38.46 76z"/></svg> <?xml version="1.0" encoding="UTF-8"?>
<svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>全屏</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="首页" transform="translate(-1865.000000, -106.000000)" fill="#0B58FF">
<g id="全屏" transform="translate(1865.000000, 106.000000)">
<g>
<rect id="矩形" stroke="#0B58FF" opacity="0" x="0.5" y="0.5" width="31" height="31"></rect>
<path d="M27.3264942,0.842105263 L27.583814,0.850525866 C28.0103146,0.878577843 28.4244403,0.976634518 28.8180051,1.14344343 C29.2746777,1.33424853 29.6828981,1.60928508 30.0368065,1.96319349 C30.3881547,2.31454163 30.6645305,2.72554187 30.8562967,3.18137947 C31.0567273,3.65427262 31.1578947,4.15615812 31.1578947,4.6735058 L31.1578947,26.4843889 L31.1494741,26.7417088 C31.1214222,27.1682093 31.0233655,27.5823351 30.8565566,27.9758999 C30.6657515,28.4325724 30.3907149,28.8407928 30.0368065,29.1947013 C29.6854584,29.5460494 29.2744581,29.8224253 28.8186205,30.0141914 C28.3457274,30.214622 27.8438419,30.3157895 27.3264942,30.3157895 L5.51561106,30.3157895 L5.25829123,30.3073689 C4.83179065,30.2793169 4.41766492,30.1812602 4.02410014,30.0144513 C3.5674276,29.8236462 3.15920715,29.5486097 2.80529875,29.1947013 C2.45395061,28.8433531 2.17757472,28.4323529 1.98580856,27.9765153 C1.785378,27.5036221 1.68421053,27.0017366 1.68421053,26.4843889 L1.68421053,4.6735058 L1.69263113,4.41618596 C1.72068311,3.98968539 1.81873978,3.57555966 1.98554869,3.18199488 C2.17635379,2.72532234 2.45139035,2.31710189 2.80529875,1.96319349 C3.15664689,1.61184534 3.56764713,1.33546946 4.02348473,1.1437033 C4.49637788,0.943272735 4.99826338,0.842105263 5.51561106,0.842105263 L27.3264942,0.842105263 Z M27.3264942,2.75111508 L5.51561106,2.75111508 L5.36543907,2.75690192 C4.37431777,2.83358398 3.59322034,3.6628098 3.59322034,4.6735058 L3.59322034,26.4843889 L3.59900719,26.6345609 C3.67568924,27.6256822 4.50491506,28.4067797 5.51561106,28.4067797 L27.3264942,28.4067797 L27.4766662,28.4009928 C28.4677875,28.3243108 29.2488849,27.4950849 29.2488849,26.4843889 L29.2488849,4.6735058 L29.2430981,4.52333381 C29.166416,3.53221251 28.3371902,2.75111508 27.3264942,2.75111508 Z M6.93907808,16.8656959 L7.04823476,16.8742044 C7.51440654,16.9376019 7.87511151,17.3390325 7.87511151,17.8202498 L7.87511151,22.7419534 L12.5867439,18.0303211 L12.6763037,17.9513367 C13.0496528,17.6617272 13.593961,17.6880553 13.9362267,18.0303211 C14.3070145,18.4011089 14.3070145,19.009016 13.9362267,19.3798038 L9.18746648,24.1248885 L14.0860839,24.1248885 L14.2012238,24.1314959 C14.6923507,24.1882147 15.0747102,24.6029657 15.0673779,25.0991191 C15.056792,25.6176308 14.6323624,26.0338983 14.1128457,26.0338983 L6.94402319,26.0338983 L6.82978436,26.0273339 C6.34272021,25.9709676 5.96610169,25.5584576 5.96610169,25.0559768 L5.96610169,17.8436664 L5.97273726,17.7287345 C6.02968832,17.2384284 6.44595722,16.8559311 6.93907808,16.8656959 Z M25.9047725,5.12399643 L26.0180629,5.13054044 C26.501183,5.1867256 26.8760036,5.59778744 26.8760036,6.09522748 L26.8760036,13.3108831 L26.869368,13.425815 C26.8124169,13.9161211 26.396148,14.2986184 25.9030272,14.2888536 C25.3853261,14.278234 24.9669938,13.8525337 24.9669938,13.3342997 L24.9669938,8.4159413 L20.2553614,13.1275737 L20.1658016,13.2065581 C19.7924524,13.4961675 19.2481443,13.4698394 18.9058786,13.1275737 C18.5350907,12.7567858 18.5350907,12.1488788 18.9058786,11.7780909 L23.6509632,7.03300624 L18.7526762,7.03300624 L18.6375099,7.02640054 C18.1463449,6.96969821 17.7649507,6.5551 17.7747062,6.0600055 C17.7853132,5.54026395 18.2097429,5.12399643 18.7292596,5.12399643 L25.9047725,5.12399643 Z" id="形状结合" fill-rule="nonzero" opacity="0.79078311"></path>
</g>
<g>
<rect id="矩形" stroke="#0B58FF" opacity="0" x="0.5" y="0.5" width="31" height="31"></rect>
<path d="M27.3264942,0.842105263 L27.583814,0.850525866 C28.0103146,0.878577843 28.4244403,0.976634518 28.8180051,1.14344343 C29.2746777,1.33424853 29.6828981,1.60928508 30.0368065,1.96319349 C30.3881547,2.31454163 30.6645305,2.72554187 30.8562967,3.18137947 C31.0567273,3.65427262 31.1578947,4.15615812 31.1578947,4.6735058 L31.1578947,26.4843889 L31.1494741,26.7417088 C31.1214222,27.1682093 31.0233655,27.5823351 30.8565566,27.9758999 C30.6657515,28.4325724 30.3907149,28.8407928 30.0368065,29.1947013 C29.6854584,29.5460494 29.2744581,29.8224253 28.8186205,30.0141914 C28.3457274,30.214622 27.8438419,30.3157895 27.3264942,30.3157895 L5.51561106,30.3157895 L5.25829123,30.3073689 C4.83179065,30.2793169 4.41766492,30.1812602 4.02410014,30.0144513 C3.5674276,29.8236462 3.15920715,29.5486097 2.80529875,29.1947013 C2.45395061,28.8433531 2.17757472,28.4323529 1.98580856,27.9765153 C1.785378,27.5036221 1.68421053,27.0017366 1.68421053,26.4843889 L1.68421053,4.6735058 L1.69263113,4.41618596 C1.72068311,3.98968539 1.81873978,3.57555966 1.98554869,3.18199488 C2.17635379,2.72532234 2.45139035,2.31710189 2.80529875,1.96319349 C3.15664689,1.61184534 3.56764713,1.33546946 4.02348473,1.1437033 C4.49637788,0.943272735 4.99826338,0.842105263 5.51561106,0.842105263 L27.3264942,0.842105263 Z M27.3264942,2.75111508 L5.51561106,2.75111508 L5.36543907,2.75690192 C4.37431777,2.83358398 3.59322034,3.6628098 3.59322034,4.6735058 L3.59322034,26.4843889 L3.59900719,26.6345609 C3.67568924,27.6256822 4.50491506,28.4067797 5.51561106,28.4067797 L27.3264942,28.4067797 L27.4766662,28.4009928 C28.4677875,28.3243108 29.2488849,27.4950849 29.2488849,26.4843889 L29.2488849,4.6735058 L29.2430981,4.52333381 C29.166416,3.53221251 28.3371902,2.75111508 27.3264942,2.75111508 Z M6.93907808,16.8656959 L7.04823476,16.8742044 C7.51440654,16.9376019 7.87511151,17.3390325 7.87511151,17.8202498 L7.87511151,22.7419534 L12.5867439,18.0303211 L12.6763037,17.9513367 C13.0496528,17.6617272 13.593961,17.6880553 13.9362267,18.0303211 C14.3070145,18.4011089 14.3070145,19.009016 13.9362267,19.3798038 L9.18746648,24.1248885 L14.0860839,24.1248885 L14.2012238,24.1314959 C14.6923507,24.1882147 15.0747102,24.6029657 15.0673779,25.0991191 C15.056792,25.6176308 14.6323624,26.0338983 14.1128457,26.0338983 L6.94402319,26.0338983 L6.82978436,26.0273339 C6.34272021,25.9709676 5.96610169,25.5584576 5.96610169,25.0559768 L5.96610169,17.8436664 L5.97273726,17.7287345 C6.02968832,17.2384284 6.44595722,16.8559311 6.93907808,16.8656959 Z M25.9047725,5.12399643 L26.0180629,5.13054044 C26.501183,5.1867256 26.8760036,5.59778744 26.8760036,6.09522748 L26.8760036,13.3108831 L26.869368,13.425815 C26.8124169,13.9161211 26.396148,14.2986184 25.9030272,14.2888536 C25.3853261,14.278234 24.9669938,13.8525337 24.9669938,13.3342997 L24.9669938,8.4159413 L20.2553614,13.1275737 L20.1658016,13.2065581 C19.7924524,13.4961675 19.2481443,13.4698394 18.9058786,13.1275737 C18.5350907,12.7567858 18.5350907,12.1488788 18.9058786,11.7780909 L23.6509632,7.03300624 L18.7526762,7.03300624 L18.6375099,7.02640054 C18.1463449,6.96969821 17.7649507,6.5551 17.7747062,6.0600055 C17.7853132,5.54026395 18.2097429,5.12399643 18.7292596,5.12399643 L25.9047725,5.12399643 Z" id="形状结合" fill-rule="nonzero" opacity="0.79078311"></path>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 421 B

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="16px" height="16px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>更新</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="首页" transform="translate(-474.000000, -116.000000)" fill="#0B58FF" fill-rule="nonzero">
<g id="更新" transform="translate(474.000000, 116.000000)">
<rect id="矩形" opacity="0" x="0" y="0" width="16" height="16"></rect>
<path d="M14.9793977,2.67910156 L13.9879914,3.45429687 C12.6362336,1.72636719 10.5338899,0.6171875 8.17314768,0.6171875 C4.09678049,0.6171875 0.797366431,3.91308594 0.792086694,7.99121094 C0.786819556,12.0728516 4.09326487,15.3828125 8.17314768,15.3828125 C11.3600617,15.3828125 14.0758821,13.3613281 15.1094758,10.5294922 C15.135843,10.4556641 15.0971711,10.3730469 15.023343,10.3484375 L14.0266633,10.0056641 C13.954593,9.98105469 13.8754914,10.0179688 13.8491242,10.0900391 C13.8174836,10.1779297 13.7823274,10.2658203 13.7454133,10.3519531 C13.4413117,11.0726562 13.0053742,11.7195312 12.4499055,12.275 C11.8944367,12.8304687 11.2475617,13.2664062 10.5286164,13.5722656 C9.78506174,13.8869141 8.99228831,14.046875 8.17666331,14.046875 C7.35928049,14.046875 6.56826487,13.8869141 5.82471018,13.5722656 C5.10576487,13.2681641 4.45888987,12.8322266 3.90342112,12.275 C3.34795237,11.7195312 2.91201487,11.0726562 2.60791331,10.3519531 C2.29326487,9.60664063 2.13330393,8.815625 2.13330393,7.99824219 C2.13330393,7.18085937 2.29326487,6.38984375 2.60791331,5.64453125 C2.91201487,4.92382812 3.34795237,4.27695312 3.90342112,3.72148438 C4.45888987,3.16601563 5.10576487,2.73007813 5.82471018,2.42421875 C6.56826487,2.10957031 7.36103831,1.94960938 8.17666331,1.94960938 C8.99404612,1.94960938 9.78506174,2.10957031 10.5286164,2.42421875 C11.2475617,2.72832031 11.8944367,3.16425781 12.4499055,3.72148438 C12.6239289,3.89550781 12.7874055,4.08007812 12.9385774,4.2734375 L11.8803742,5.09960938 C11.7872102,5.17167969 11.8188508,5.31933594 11.9331086,5.34746094 L15.0198274,6.10332031 C15.107718,6.12441406 15.1938508,6.05761719 15.1938508,5.96796875 L15.2079133,2.78808594 C15.2061555,2.67207031 15.0708039,2.60703125 14.9793977,2.67910156 L14.9793977,2.67910156 Z" id="路径" stroke="#0B58FF" stroke-width="0.5"></path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="32px" height="32px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>推出全屏</title>
<g id="页面-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="首页" transform="translate(-1815.000000, -103.000000)" fill="#0B58FF">
<g id="推出全屏" transform="translate(1815.000000, 103.000000)">
<g id="全屏">
<rect id="矩形" stroke="#0B58FF" opacity="0" x="0.5" y="0.5" width="31" height="31"></rect>
<path d="M26.7638125,1.45454545 L27.0177905,1.4628567 C27.4387521,1.49054436 27.8474996,1.58732758 28.2359531,1.75197014 C28.6866948,1.94029725 29.0896137,2.2117619 29.4389259,2.56107409 C29.7857111,2.90785927 30.0584977,3.31352185 30.2477734,3.76343947 C30.4456009,4.23019115 30.5454545,4.72555866 30.5454545,5.23618754 L30.5454545,26.7638125 L30.5371433,27.0177905 C30.5094556,27.4387521 30.4126724,27.8474996 30.2480299,28.2359531 C30.0597028,28.6866948 29.7882381,29.0896137 29.4389259,29.4389259 C29.0921407,29.7857111 28.6864782,30.0584977 28.2365605,30.2477734 C27.7698088,30.4456009 27.2744413,30.5454545 26.7638125,30.5454545 L5.23618754,30.5454545 L4.98220952,30.5371433 C4.56124792,30.5094556 4.15250044,30.4126724 3.7640469,30.2480299 C3.31330516,30.0597028 2.91038628,29.7882381 2.56107409,29.4389259 C2.21428891,29.0921407 1.94150232,28.6864782 1.75222663,28.2365605 C1.55439906,27.7698088 1.45454545,27.2744413 1.45454545,26.7638125 L1.45454545,5.23618754 L1.4628567,4.98220952 C1.49054436,4.56124792 1.58732758,4.15250044 1.75197014,3.7640469 C1.94029725,3.31330516 2.2117619,2.91038628 2.56107409,2.56107409 C2.90785927,2.21428891 3.31352185,1.94150232 3.76343947,1.75222663 C4.23019115,1.55439906 4.72555866,1.45454545 5.23618754,1.45454545 L26.7638125,1.45454545 Z M26.7638125,3.33876293 L5.23618754,3.33876293 L5.08796584,3.34447462 C4.10971624,3.42016081 3.33876293,4.23861746 3.33876293,5.23618754 L3.33876293,26.7638125 L3.34447462,26.9120342 C3.42016081,27.8902838 4.23861746,28.6612371 5.23618754,28.6612371 L26.7638125,28.6612371 L26.9120342,28.6555254 C27.8902838,28.5798392 28.6612371,27.7613825 28.6612371,26.7638125 L28.6612371,5.23618754 L28.6555254,5.08796584 C28.5798392,4.10971624 27.7613825,3.33876293 26.7638125,3.33876293 Z M13.6987866,17.269857 L13.8115418,17.2763362 C14.2922804,17.3319705 14.6640078,17.7391232 14.6640078,18.2350783 L14.6640078,25.3537223 L14.6574584,25.4671616 C14.6012469,25.9511001 14.1903841,26.3286298 13.7036674,26.3189919 L13.5959284,26.3105939 C13.1358108,26.2480197 12.7797903,25.8518025 12.7797903,25.3768348 L12.7797903,20.5190494 L8.12934794,25.1694917 L8.04095127,25.2474504 C7.67245079,25.5332987 7.13521162,25.5073124 6.79739091,25.1694917 C6.43141847,24.8035193 6.43141847,24.2035071 6.79739091,23.8375347 L11.4844789,19.1540745 L6.64947993,19.1540745 L6.53583534,19.1475529 C6.05108664,19.0915708 5.67369292,18.6822061 5.68093001,18.1924962 C5.69137836,17.6807185 6.11029591,17.269857 6.62306566,17.269857 L13.6987866,17.269857 Z M18.2962333,5.68100813 C18.807211,5.69148979 19.2201105,6.11166149 19.2201105,6.62316519 L19.2201105,11.4776488 L23.8705528,6.82720649 L23.9589495,6.74924786 C24.32745,6.46339956 24.8646892,6.48938577 25.2025099,6.82720649 C25.5684823,7.19317893 25.5684823,7.79319108 25.2025099,8.15916352 L20.5190497,12.8426237 L25.3537226,12.8426237 L25.4673933,12.8491436 C25.9521795,12.9051095 26.3286206,13.3143234 26.3189917,13.8029881 C26.3085224,14.3159797 25.8896049,14.7268412 25.3768351,14.7268412 L18.2945107,14.7268412 L18.1826915,14.7203822 C17.7058457,14.6649267 17.335893,14.2592033 17.335893,13.7682235 L17.335893,6.64627767 L17.3424424,6.53283844 C17.3986538,6.04889994 17.8095166,5.67137018 18.2962333,5.68100813 Z" id="形状结合" fill-rule="nonzero" opacity="0.79078311"></path>
</g>
<g id="全屏">
<rect id="矩形" stroke="#0B58FF" opacity="0" x="0.5" y="0.5" width="31" height="31"></rect>
<path d="M26.7638125,1.45454545 L27.0177905,1.4628567 C27.4387521,1.49054436 27.8474996,1.58732758 28.2359531,1.75197014 C28.6866948,1.94029725 29.0896137,2.2117619 29.4389259,2.56107409 C29.7857111,2.90785927 30.0584977,3.31352185 30.2477734,3.76343947 C30.4456009,4.23019115 30.5454545,4.72555866 30.5454545,5.23618754 L30.5454545,26.7638125 L30.5371433,27.0177905 C30.5094556,27.4387521 30.4126724,27.8474996 30.2480299,28.2359531 C30.0597028,28.6866948 29.7882381,29.0896137 29.4389259,29.4389259 C29.0921407,29.7857111 28.6864782,30.0584977 28.2365605,30.2477734 C27.7698088,30.4456009 27.2744413,30.5454545 26.7638125,30.5454545 L5.23618754,30.5454545 L4.98220952,30.5371433 C4.56124792,30.5094556 4.15250044,30.4126724 3.7640469,30.2480299 C3.31330516,30.0597028 2.91038628,29.7882381 2.56107409,29.4389259 C2.21428891,29.0921407 1.94150232,28.6864782 1.75222663,28.2365605 C1.55439906,27.7698088 1.45454545,27.2744413 1.45454545,26.7638125 L1.45454545,5.23618754 L1.4628567,4.98220952 C1.49054436,4.56124792 1.58732758,4.15250044 1.75197014,3.7640469 C1.94029725,3.31330516 2.2117619,2.91038628 2.56107409,2.56107409 C2.90785927,2.21428891 3.31352185,1.94150232 3.76343947,1.75222663 C4.23019115,1.55439906 4.72555866,1.45454545 5.23618754,1.45454545 L26.7638125,1.45454545 Z M26.7638125,3.33876293 L5.23618754,3.33876293 L5.08796584,3.34447462 C4.10971624,3.42016081 3.33876293,4.23861746 3.33876293,5.23618754 L3.33876293,26.7638125 L3.34447462,26.9120342 C3.42016081,27.8902838 4.23861746,28.6612371 5.23618754,28.6612371 L26.7638125,28.6612371 L26.9120342,28.6555254 C27.8902838,28.5798392 28.6612371,27.7613825 28.6612371,26.7638125 L28.6612371,5.23618754 L28.6555254,5.08796584 C28.5798392,4.10971624 27.7613825,3.33876293 26.7638125,3.33876293 Z M13.6987866,17.269857 L13.8115418,17.2763362 C14.2922804,17.3319705 14.6640078,17.7391232 14.6640078,18.2350783 L14.6640078,25.3537223 L14.6574584,25.4671616 C14.6012469,25.9511001 14.1903841,26.3286298 13.7036674,26.3189919 L13.5959284,26.3105939 C13.1358108,26.2480197 12.7797903,25.8518025 12.7797903,25.3768348 L12.7797903,20.5190494 L8.12934794,25.1694917 L8.04095127,25.2474504 C7.67245079,25.5332987 7.13521162,25.5073124 6.79739091,25.1694917 C6.43141847,24.8035193 6.43141847,24.2035071 6.79739091,23.8375347 L11.4844789,19.1540745 L6.64947993,19.1540745 L6.53583534,19.1475529 C6.05108664,19.0915708 5.67369292,18.6822061 5.68093001,18.1924962 C5.69137836,17.6807185 6.11029591,17.269857 6.62306566,17.269857 L13.6987866,17.269857 Z M18.2962333,5.68100813 C18.807211,5.69148979 19.2201105,6.11166149 19.2201105,6.62316519 L19.2201105,11.4776488 L23.8705528,6.82720649 L23.9589495,6.74924786 C24.32745,6.46339956 24.8646892,6.48938577 25.2025099,6.82720649 C25.5684823,7.19317893 25.5684823,7.79319108 25.2025099,8.15916352 L20.5190497,12.8426237 L25.3537226,12.8426237 L25.4673933,12.8491436 C25.9521795,12.9051095 26.3286206,13.3143234 26.3189917,13.8029881 C26.3085224,14.3159797 25.8896049,14.7268412 25.3768351,14.7268412 L18.2945107,14.7268412 L18.1826915,14.7203822 C17.7058457,14.6649267 17.335893,14.2592033 17.335893,13.7682235 L17.335893,6.64627767 L17.3424424,6.53283844 C17.3986538,6.04889994 17.8095166,5.67137018 18.2962333,5.68100813 Z" id="形状结合" fill-rule="nonzero" opacity="0.79078311"></path>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 7.3 KiB

View File

@@ -1,4 +1,4 @@
<!-- <!--
filename: dialogForm.vue filename: dialogForm.vue
author: liubin author: liubin
date: 2023-08-15 10:32:36 date: 2023-08-15 10:32:36
@@ -92,13 +92,13 @@
{{ col.uploadTips || '只能上传jpg/png文件, 大小不超过2MB' }} {{ col.uploadTips || '只能上传jpg/png文件, 大小不超过2MB' }}
</div> </div>
</el-upload> </el-upload>
<uploadedFile <uploadedFile
class="file" class="file"
v-for="file in form[col.prop] || []" v-for="file in form[col.prop] || []"
:file="file" :file="file"
:key="file.fileUrl" :key="file.fileUrl"
@delete="handleDeleteFile(file)" /> @delete="handleDeleteFile(file)"
@Preview="handlePreview(file)" />
</div> </div>
</el-form-item> </el-form-item>
</el-col> </el-col>
@@ -138,6 +138,9 @@ const uploadedFile = {
handleDelete() { handleDelete() {
this.$emit('delete', this.file); this.$emit('delete', this.file);
}, },
handlePreview() {
this.$emit('Preview', this.file);
},
}, },
mounted() {}, mounted() {},
render: function (h) { render: function (h) {
@@ -156,7 +159,7 @@ const uploadedFile = {
cursor: 'pointer', cursor: 'pointer',
display: 'inline-block', display: 'inline-block',
}}> }}>
{this.file.fileName} <el-button onClick={this.handlePreview}>{this.file.fileName}</el-button>
<el-button <el-button
type="text" type="text"
icon="el-icon-close" icon="el-icon-close"
@@ -256,6 +259,20 @@ export default {
resetFields(args) { resetFields(args) {
return this.$refs.form.resetFields(args); return this.$refs.form.resetFields(args);
}, },
async handlePreview(file) {
const data = await this.$axios({
url: file.fileUrl,
method: 'get',
responseType: 'blob',
});
const link = document.createElement('a');
link.href = window.URL.createObjectURL(new Blob([data]));
link.download = file.fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(link.href);
},
// getCode // getCode
async getCode(url) { async getCode(url) {
const response = await this.$axios(url); const response = await this.$axios(url);
@@ -355,7 +372,9 @@ export default {
if (!promiseList.length) this.formLoading = false; if (!promiseList.length) this.formLoading = false;
}, },
// 上传成功的特殊处理 // 上传成功的特殊处理
beforeUpload() {}, beforeUpload(file) {
console.log(file)
},
// 上传前的验证规则可通过 bind 属性传入 // 上传前的验证规则可通过 bind 属性传入
handleUploadSuccess(response, file, fileList) { handleUploadSuccess(response, file, fileList) {
this.form.files.push({ this.form.files.push({

View File

@@ -9,6 +9,7 @@ import store from './store';
import router from './router'; import router from './router';
import directive from './directive'; // directive import directive from './directive'; // directive
import plugins from './plugins'; // plugins import plugins from './plugins'; // plugins
import dataV from '@jiaminghi/data-view'
import './assets/icons'; // icon import './assets/icons'; // icon
import './permission'; // permission control import './permission'; // permission control
@@ -77,6 +78,7 @@ Vue.use(directive);
Vue.use(plugins); Vue.use(plugins);
Vue.use(VueMeta); Vue.use(VueMeta);
// Vue.use(hljs.vuePlugin); // Vue.use(hljs.vuePlugin);
Vue.use(dataV);
// bpmnProcessDesigner 需要引入 // bpmnProcessDesigner 需要引入
import MyPD from '@/components/bpmnProcessDesigner/package/index.js'; import MyPD from '@/components/bpmnProcessDesigner/package/index.js';

View File

@@ -0,0 +1,20 @@
export default {
data() {
return {
tableH: this.tableHeight(260),
};
},
created() {
this.tableH = this?.heightNum ? this.tableHeight(this.heightNum) : this.tableHeight(260);
window.addEventListener('resize', this._setTableHeight);
},
destroyed() {
window.removeEventListener('resize', this._setTableHeight);
},
methods: {
_setTableHeight() {
this.tableH = this?.heightNum ? this.tableHeight(this.heightNum) : this.tableHeight(260);
// this.tableH = this.tableHeight(260);
},
},
};

View File

@@ -76,7 +76,7 @@ export const constantRoutes = [
children: [ children: [
{ {
path: "index", path: "index",
component: (resolve) => require(["@/views/cost/raw/costMaterial/index"], resolve), component: (resolve) => require(["@/views/home/index"], resolve),
name: "首页", name: "首页",
meta: { title: "首页", icon: "dashboard", affix: true }, meta: { title: "首页", icon: "dashboard", affix: true },
hidden: true hidden: true

View File

@@ -86,10 +86,11 @@ export const DICT_TYPE = {
// ============== PRODUCT - 产品模块 ============= // ============== PRODUCT - 产品模块 =============
UNIT_DICT: 'unit_dict', UNIT_DICT: 'unit_dict',
PRODUCT_TYPE: 'product_type', PRODUCT_TYPE: 'product_type',
PROCESS_TYPE: 'process_type',
// ============== ENERGY - 能源模块 ============= // ============== ENERGY - 能源模块 =============
ENERGY_UNIT: 'energy_unit', ENERGY_UNIT: 'energy_unit',
// ============== ENERGY - 能源模块 ============= // ============== ENERGY - 能源模块 =============
EQU_ALARM_LEVEL: 'equ_alarm_level', EQU_ALARM_LEVEL: 'equ_alarm_level',
MONITOR_INDEX_TYPE: 'monitor_index_type', MONITOR_INDEX_TYPE: 'monitor_index_type',

View File

@@ -1,4 +1,4 @@
<!-- <!--
filename: dialogForm.vue filename: dialogForm.vue
author: liubin author: liubin
date: 2023-09-11 15:55:13 date: 2023-09-11 15:55:13
@@ -71,14 +71,14 @@
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="工段排序" prop="sort"> <el-form-item label="工段设备排序" prop="sort">
<el-input-number <el-input-number
v-model="dataForm.sort" v-model="dataForm.sort"
filterable filterable
min="0" min="0"
max="100" max="100"
@change="$emit('update', dataForm)" @change="$emit('update', dataForm)"
placeholder="请输入工段排序" /> placeholder="请输入工段设备排序" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -112,6 +112,7 @@
{ label: '无类型', value: 0 }, { label: '无类型', value: 0 },
{ label: '进口统计', value: 1 }, { label: '进口统计', value: 1 },
{ label: '出口统计', value: 2 }, { label: '出口统计', value: 2 },
{ label: '进出口计数', value: 3 },
]" ]"
:key="opt.value" :key="opt.value"
:label="opt.label" :label="opt.label"

View File

@@ -4,7 +4,8 @@
<SearchBar <SearchBar
:formConfigs="searchBarFormConfig" :formConfigs="searchBarFormConfig"
ref="search-bar" ref="search-bar"
@headBtnClick="handleSearchBarBtnClick" /> @select-changed="handleSearchBarChanged"
@headBtnClick="buttonClick" />
<!-- 列表 --> <!-- 列表 -->
<base-table <base-table
@@ -52,6 +53,8 @@ import {
getEquipmentBindSectionPage, getEquipmentBindSectionPage,
exportEquipmentBindSectionExcel, exportEquipmentBindSectionExcel,
} from '@/api/base/equipmentBindSection'; } from '@/api/base/equipmentBindSection';
import { getPdList } from '@/api/core/monitoring/auto';
import { getFactoryPage } from '@/api/core/base/factory';
import moment from 'moment'; import moment from 'moment';
import basicPageMixin from '@/mixins/lb/basicPageMixin'; import basicPageMixin from '@/mixins/lb/basicPageMixin';
import DialogForm from './dialogForm.vue'; import DialogForm from './dialogForm.vue';
@@ -61,7 +64,7 @@ export default {
mixins: [basicPageMixin], mixins: [basicPageMixin],
data() { data() {
return { return {
searchBarKeys: ['workshopSectionId', 'equipmentName'], searchBarKeys: ['factoryId','productionLineId','workshopSectionId', 'equipmentName'],
tableBtn: [ tableBtn: [
this.$auth.hasPermi('base:equipment-bind-section:update') this.$auth.hasPermi('base:equipment-bind-section:update')
? { ? {
@@ -84,8 +87,9 @@ export default {
width: 180, width: 180,
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'), filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
}, },
{ prop: 'productionLine', label: '产线名称' }, { prop: 'factoryName', label: '工厂' },
{ prop: 'workshopSection', label: '工段名称' }, { prop: 'productionLine', label: '产线' },
{ prop: 'workshopSection', label: '工段' },
{ prop: 'equipment', label: '设备名称' }, { prop: 'equipment', label: '设备名称' },
{ prop: 'sort', label: '工段中排序' }, { prop: 'sort', label: '工段中排序' },
{ {
@@ -98,7 +102,7 @@ export default {
prop: 'sectionDataType', prop: 'sectionDataType',
label: '工段数据类型', label: '工段数据类型',
filter: (val) => filter: (val) =>
val != null ? ['无类型', '进口计数', '出口计数'][val] : '-', val != null ? ['无类型', '进口计数', '出口计数', '进出口计数'][val] : '-',
}, },
// { // {
// action: 'show-alert', // action: 'show-alert',
@@ -129,6 +133,20 @@ export default {
// }, // },
], ],
searchBarFormConfig: [ searchBarFormConfig: [
{
type: 'select',
label: '工厂',
selectOptions: [],
param: 'factoryId',
onchange: true,
},
{
type: 'select',
label: '产线',
selectOptions: [],
param: 'productionLineId',
multiple: true,
},
{ {
type: 'select', type: 'select',
label: '工段', label: '工段',
@@ -209,8 +227,8 @@ export default {
label: '产线数据类型', label: '产线数据类型',
options: [ options: [
{ label: '无类型', value: 0 }, { label: '无类型', value: 0 },
{ label: '进口计', value: 1 }, { label: '进口计', value: 1 },
{ label: '出口计', value: 2 }, { label: '出口计', value: 2 },
], ],
prop: 'lineDataType', prop: 'lineDataType',
}, },
@@ -219,8 +237,9 @@ export default {
label: '工段数据类型', label: '工段数据类型',
options: [ options: [
{ label: '无类型', value: 0 }, { label: '无类型', value: 0 },
{ label: '进口计', value: 1 }, { label: '进口计', value: 1 },
{ label: '出口计', value: 2 }, { label: '出口计', value: 2 },
{ label: '进出口计数', value: 3 },
], ],
prop: 'sectionDataType', prop: 'sectionDataType',
}, },
@@ -234,6 +253,9 @@ export default {
pageSize: 10, pageSize: 10,
workshopSectionId: null, workshopSectionId: null,
equipmentId: null, equipmentId: null,
equipmentName: null,
factoryId: null,
productionLineId: [],
}, },
// 表单参数 // 表单参数
form: {}, form: {},
@@ -242,6 +264,7 @@ export default {
created() { created() {
this.getList(); this.getList();
this.initWorksection(); this.initWorksection();
this.getPdLineList();
}, },
methods: { methods: {
/** 准备工段数据 */ /** 准备工段数据 */
@@ -251,7 +274,7 @@ export default {
method: 'get', method: 'get',
}); });
if (code == 0) { if (code == 0) {
this.searchBarFormConfig[0].selectOptions = data.map((item) => { this.searchBarFormConfig[2].selectOptions = data.map((item) => {
return { return {
name: item.name, name: item.name,
id: item.id, id: item.id,
@@ -259,6 +282,51 @@ export default {
}); });
} }
}, },
getPdLineList() {
getPdList().then((res) => {
this.searchBarFormConfig[1].selectOptions = res.data || [];
});
const params = {
pageSize: 100,
pageNo: 1,
};
getFactoryPage(params).then((res) => {
this.searchBarFormConfig[0].selectOptions = res.data.list || [];
});
},
handleSearchBarChanged({ param, value }) {
this.queryParams.productionLineId = [];
this.$refs['search-bar'].formInline.productionLineId = undefined;
getPdList(value).then((res) => {
this.searchBarFormConfig[1].selectOptions = res.data || [];
});
},
buttonClick(val) {
switch (val.btnName) {
case 'search':
this.queryParams.pageNo = 1;
this.queryParams.pageSize = 10;
this.queryParams.name = val.name;
this.queryParams.workshopSectionId = val.workshopSectionId || undefined;
this.queryParams.equipmentName = val.equipmentName || undefined;
this.queryParams.factoryId = val.factoryId || undefined;
this.queryParams.productionLineId = val.productionLineId || [];
this.handleQuery();
break;
case 'add':
this.handleAdd();
break;
case 'export':
this.handleExport();
break;
case 'reset':
this.$refs['search-bar'].resetForm();
this.resetQuery();
break;
default:
console.log(val);
}
},
/** 查询列表 */ /** 查询列表 */
getList() { getList() {
this.loading = true; this.loading = true;

View File

@@ -0,0 +1,109 @@
<!--
* @Author: zwq
* @Date: 2021-11-18 14:16:25
* @LastEditors: zwq
* @LastEditTime: 2025-02-26 16:37:29
* @Description:
-->
<template>
<el-row :gutter="20">
<el-form
:model="dataForm"
:rules="dataRule"
ref="dataForm"
@keyup.enter.native="dataFormSubmit()"
label-width="80px">
<el-col :span="12">
<el-form-item label="关联表名" prop="plcTableName">
<el-input
v-model="dataForm.plcTableName"
clearable
placeholder="请输入关联表名" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="编码" prop="code">
<el-input
v-model="dataForm.code"
clearable
placeholder="请输入编码" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="标识" prop="name">
<el-input
v-model="dataForm.name"
clearable
placeholder="请输入标识" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="英文名" prop="enName">
<el-input
v-model="dataForm.enName"
clearable
placeholder="请输入英文名" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否采集" prop="collection">
<el-switch
v-model="dataForm.collection"
:active-value="1"
:inactive-value="0"></el-switch>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="描述" prop="description">
<el-input
v-model="dataForm.description"
clearable
placeholder="请输入描述" />
</el-form-item>
</el-col>
</el-form>
</el-row>
</template>
<script>
import basicAdd from '@/mixins/basic-add';
import {
createEquipmentPlc,
updateEquipmentPlc,
getEquipmentPlc,
getCode,
} from '@/api/base/equipmentPlc';
export default {
mixins: [basicAdd],
data() {
return {
urlOptions: {
isGetCode: true,
codeURL: getCode,
createURL: createEquipmentPlc,
updateURL: updateEquipmentPlc,
infoURL: getEquipmentPlc,
},
dataForm: {
id: undefined,
plcTableName: undefined,
code: undefined,
name: undefined,
enName: undefined,
collection: 1,
description: undefined,
},
dataRule: {
plcTableName: [
{ required: true, message: '关联表名不能为空', trigger: 'blur' },
],
code: [{ required: true, message: '编码不能为空', trigger: 'blur' }],
name: [{ required: true, message: '标识不能为空', trigger: 'blur' }],
},
};
},
methods: {},
};
</script>

View File

@@ -1,59 +1,53 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<!-- 搜索工作栏 --> <search-bar
<SearchBar :formConfigs="formConfig"
:formConfigs="searchBarFormConfig" ref="searchBarForm"
ref="search-bar" @headBtnClick="buttonClick" />
@headBtnClick="handleSearchBarBtnClick" />
<!-- 列表 -->
<base-table <base-table
v-loading="dataListLoading"
:table-props="tableProps" :table-props="tableProps"
:page="queryParams.pageNo" :page="listQuery.pageNo"
:limit="queryParams.pageSize" :limit="listQuery.pageSize"
:table-data="list" :table-data="tableData"
ref="pageTable"
@emitFun="handleEmitFun"> @emitFun="handleEmitFun">
<method-btn <method-btn
v-if="tableBtn.length" v-if="tableBtn.length"
slot="handleBtn" slot="handleBtn"
:width="120"
label="操作" label="操作"
:method-list="tableBtn" :method-list="tableBtn"
@clickBtn="handleTableBtnClick" /> @clickBtn="handleClick" />
</base-table> </base-table>
<!-- 分页组件 -->
<pagination <pagination
v-show="total > 0" :limit.sync="listQuery.pageSize"
:total="total" :page.sync="listQuery.pageNo"
:page.sync="queryParams.pageNo" :total="listQuery.total"
:limit.sync="queryParams.pageSize" @pagination="getDataList" />
@pagination="getList" />
<!-- 对话框(添加 / 修改) -->
<base-dialog <base-dialog
:dialogTitle="title" :dialogTitle="addOrEditTitle"
:dialogVisible="open" :dialogVisible="addOrUpdateVisible"
width="700px" @cancel="handleCancel"
@close="cancel" @confirm="handleConfirm"
@cancel="cancel" :before-close="handleCancel"
@confirm="submitForm"> width="50%">
<DialogForm v-if="open" ref="form" v-model="form" :rows="rows" /> <add-or-update
ref="addOrUpdate"
@refreshDataList="successSubmit"></add-or-update>
</base-dialog> </base-dialog>
</div> </div>
</template> </template>
<script> <script>
import AddOrUpdate from './add-or-updata';
import basicPage from '@/mixins/basic-page';
import { parseTime } from '@/filter/code-filter';
import { import {
createEquipmentPlc,
updateEquipmentPlc,
deleteEquipmentPlc, deleteEquipmentPlc,
getEquipmentPlc,
getEquipmentPlcPage, getEquipmentPlcPage,
exportEquipmentPlcExcel, exportEquipmentPlcExcel,
updateEquipmentPlc,
} from '@/api/base/equipmentPlc'; } from '@/api/base/equipmentPlc';
import moment from 'moment';
import basicPageMixin from '@/mixins/lb/basicPageMixin';
const switchBtn = { const switchBtn = {
name: 'SwitchBtn', name: 'SwitchBtn',
@@ -90,49 +84,45 @@ const switchBtn = {
); );
}, },
}; };
const tableProps = [
{ prop: 'code', label: '编码', width: 220 },
{ prop: 'plcTableName', label: '关联表名' },
{ prop: 'name', label: '标识名称' },
{ prop: 'enName', label: '英文名称' },
{
prop: 'collection',
label: '是否采集',
subcomponent: switchBtn,
},
{ prop: 'description', label: '描述' },
];
export default { export default {
name: 'EquipmentPlc', mixins: [basicPage],
mixins: [basicPageMixin],
components: {},
data() { data() {
return { return {
tableKey: Math.random(), urlOptions: {
searchBarKeys: ['name', 'plcTableName'], getDataListURL: getEquipmentPlcPage,
deleteURL: deleteEquipmentPlc,
exportURL: exportEquipmentPlcExcel,
},
tableProps,
tableBtn: [ tableBtn: [
this.$auth.hasPermi('base:equipment-plc:update') this.$auth.hasPermi(`base:equipment-plc:update`)
? { ? {
type: 'edit', type: 'edit',
btnName: '修改', btnName: '编辑',
} }
: undefined, : undefined,
this.$auth.hasPermi('base:equipment-plc:delete') this.$auth.hasPermi(`base:equipment-plc:delete`)
? { ? {
type: 'delete', type: 'delete',
btnName: '删除', btnName: '删除',
} }
: undefined, : undefined,
].filter((v) => v), ].filter((v) => v),
tableProps: [ tableData: [],
// { formConfig: [
// prop: 'createTime',
// label: '添加时间',
// fixed: true,
// width: 180,
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
// },
{ prop: 'code', label: '编码' },
{ prop: 'plcTableName', label: '关联表名' },
{ prop: 'name', label: '标识名称' },
{ prop: 'enName', label: '英文名称' },
{
prop: 'collection',
label: '是否采集',
subcomponent: switchBtn,
},
{ prop: 'description', label: '描述' },
],
searchBarFormConfig: [
{ {
type: 'input', type: 'input',
label: '表名', label: '表名',
@@ -147,231 +137,86 @@ export default {
}, },
{ {
type: 'button', type: 'button',
btnName: '查询', btnName: '搜索',
name: 'search', name: 'search',
color: 'primary', color: 'primary',
}, },
// {
// type: 'separate',
// },
// {
// type: 'button',
// btnName: '重置',
// name: 'reset',
// },
{ {
type: 'separate', type: 'separate',
}, },
{ {
// type: this.$auth.hasPermi('base:equipment-plc:create') type: this.$auth.hasPermi('base:factory:create') ? 'button' : '',
// ? 'button'
// : '',
type: 'button',
btnName: '新增', btnName: '新增',
name: 'add', name: 'add',
plain: true,
color: 'success', color: 'success',
plain: true,
}, },
// { // {
// type: this.$auth.hasPermi('base:equipment-plc:export') ? 'button' : '', // type: this.$auth.hasPermi('base:factory:create') ? 'separate' : '',
// },
// {
// type: this.$auth.hasPermi('base:factory:export') ? 'button' : '',
// btnName: '导出', // btnName: '导出',
// name: 'export', // name: 'export',
// color: 'warning', // color: 'warning',
// }, // },
], ],
rows: [
[
{
input: true,
label: '关联表名',
prop: 'plcTableName',
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
// bind: {
// disabled: true, // some condition, like detail mode...
// }
},
{
input: true,
label: '编码',
prop: 'code',
url: '/base/equipment-group/getCode',
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
},
],
[
{
input: true,
label: '标识',
prop: 'name',
rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
// bind: {
// disabled: true, // some condition, like detail mode...
// }
},
{
input: true,
label: '英文名',
prop: 'enName',
},
],
[
{
switch: true,
label: '是否采集', // 是否采集 0 代表不采集, 1 代表采集
prop: 'collection',
value: 1,
bind: {
'active-value': 1,
'inactive-value': 0,
},
},
],
[
{
textarea: true,
label: '描述',
prop: 'description',
bind: {
placeholder: '请输入备注',
},
},
],
],
// 是否显示弹出
open: false,
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 10,
plcTableName: null,
name: null,
},
// 表单参数
form: {},
}; };
}, },
created() { components: {
this.getList(); AddOrUpdate,
}, },
created() {},
methods: { methods: {
/** 覆盖 handleEmitFun 的默认实现 */ /** 覆盖 handleEmitFun 的默认实现 */
handleEmitFun({ action, payload }) { handleEmitFun({ action, payload }) {
console.log(payload)
switch (action) { switch (action) {
case 'update-collect': case 'update-collect':
this.reset(); updateEquipmentPlc(payload).then((response) => {
const tempForm = {};
Object.keys(this.form).forEach((key) => {
tempForm[key] = payload[key];
});
updateEquipmentPlc(tempForm).then((response) => {
this.$modal.msgSuccess('修改成功'); this.$modal.msgSuccess('修改成功');
this.open = false; this.getDataList();
this.getList();
}); });
break; break;
} }
}, },
/** 查询列表 */ buttonClick(val) {
getList() { switch (val.btnName) {
this.loading = true; case 'search':
// 执行查询 this.listQuery.pageNo = 1;
getEquipmentPlcPage(this.queryParams).then((response) => { this.listQuery.pageSize = 10;
this.list = response.data.list; this.listQuery.name = val.name;
this.total = response.data.total; this.listQuery.plcTableName = val.plcTableName;
this.loading = false; this.getDataList();
// this.tableKey = Math.random(); // method 1 break;
}); case 'reset':
}, this.$refs.searchBarForm.resetForm();
/** 取消按钮 */ this.listQuery = {
cancel() { pageSize: 10,
this.open = false; pageNo: 1,
this.reset(); total: 1,
}, };
/** 表单重置 */ this.getDataList();
reset() { break;
this.form = { case 'add':
id: undefined, this.addOrEditTitle = '新增';
plcTableName: undefined, this.addOrUpdateVisible = true;
code: undefined, this.addOrUpdateHandle();
name: undefined, break;
enName: undefined, case 'export':
description: undefined, this.handleExport();
collection: undefined, break;
}; default:
this.resetForm('form'); console.log(val);
}, }
/** 搜索按钮操作 */
handleQuery() {
this.queryParams.pageNo = 1;
this.getList();
},
/** 重置按钮操作 */
resetQuery() {
this.resetForm('queryForm');
this.handleQuery();
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.title = '添加实时数据采集配置';
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
const id = row.id;
getEquipmentPlc(id).then((response) => {
this.form = response.data;
this.open = true;
this.title = '修改实时数据采集配置';
});
},
/** 提交按钮 */
submitForm() {
this.$refs['form'].validate((valid) => {
if (!valid) {
return;
}
// 修改的提交
if (this.form.id != null) {
updateEquipmentPlc(this.form).then((response) => {
this.$modal.msgSuccess('修改成功');
this.open = false;
this.getList();
});
return;
}
// 添加的提交
createEquipmentPlc(this.form).then((response) => {
this.$modal.msgSuccess('新增成功');
this.open = false;
this.getList();
});
});
},
/** 删除按钮操作 */
handleDelete(row) {
const id = row.id;
this.$modal
.confirm('是否确认删除实时数据采集配置编号为"' + id + '"的数据项?')
.then(function () {
return deleteEquipmentPlc(id);
})
.then(() => {
this.getList();
this.$modal.msgSuccess('删除成功');
})
.catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
// 处理查询参数
let params = { ...this.queryParams };
params.pageNo = undefined;
params.pageSize = undefined;
this.$modal
.confirm('是否确认导出所有实时数据采集配置数据项?')
.then(() => {
this.exportLoading = true;
return exportEquipmentPlcExcel(params);
})
.then((response) => {
this.$download.excel(response, '实时数据采集配置.xls');
this.exportLoading = false;
})
.catch(() => {});
}, },
}, },
}; };

View File

@@ -2,7 +2,7 @@
* @Author: zwq * @Author: zwq
* @Date: 2021-11-18 14:16:25 * @Date: 2021-11-18 14:16:25
* @LastEditors: zwq * @LastEditors: zwq
* @LastEditTime: 2024-04-30 10:01:41 * @LastEditTime: 2025-02-25 16:11:14
* @Description: * @Description:
--> -->
<template> <template>

View File

@@ -0,0 +1,197 @@
<template>
<div
ref="lineChart"
:id="id"
:class="className"
:style="{ height: height, width: width, marginLeft: '10px' }" />
</template>
<script>
import * as echarts from 'echarts';
require('echarts/theme/macarons'); // echarts theme
import resize from '@/utils/chartMixins/resize';
import { parseTime } from '../../mixins/code-filter';
const animationDuration = 1000;
export default {
name: 'lineChart',
mixins: [resize],
props: {
id: {
type: String,
default: 'chart',
},
className: {
type: String,
default: 'chart',
},
title: {
type: String,
default: '',
},
width: {
type: String,
default: '100%',
},
height: {
type: String,
default: '300px',
},
barData: {
type: Object,
default: () => {},
},
},
data() {
return {
chart: null,
};
},
mounted() {
if (!this.chart) {
this.chart = echarts.init(this.$refs.lineChart);
this.$nextTick(() => {
this.initChart();
});
}
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
watch: {
barData: {
handler() {
if (this.chart) {
this.$nextTick(() => {
this.initChart();
});
} else {
this.$nextTick(() => {
this.chart = echarts.init(this.$refs.lineChart);
this.initChart();
});
}
},
deep: true,
immediate: true,
},
},
methods: {
initChart() {
const _this = this;
this.chart.setOption({
title: {
text: this.title
? '{space|}{tip|}{space|}{value|' + this.title + '}'
: '',
textStyle: {
rich: {
tip: {
width: 6,
height: 6,
borderRadius: 50,
backgroundColor: '#288AFF',
},
space: {
width: 8,
},
value: {
fontSize: 14,
color: 'black',
},
},
},
},
color: ['#288AFF', '#8EF0AB', '#FFDC94'],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999',
},
},
},
legend: {
data: ['磨边节拍', '钢化节拍', '下片节拍'],
},
grid: {
containLabel: true,
},
xAxis: {
type: 'category',
data: this.barData.edgeCt.map((item) => {
return parseTime(item.recordTime, '{m}-{d} {h}:{i}');
}),
axisPointer: {
type: 'shadow',
},
},
yAxis: [
{
type: 'value',
name: '节拍 pcs/min',
min: 0,
axisLabel: {
formatter: '{value}',
},
},
],
dataZoom: [
{
type: 'inside',
start: 0,
end: 100,
},
{
start: 0,
end: 100,
},
],
series: [
{
name: '磨边节拍',
type: 'line',
tooltip: {
valueFormatter: function (value) {
return value + 'pcs/min';
},
},
data: this.barData.edgeCt.map((item) => {
return item.ct;
}),
},
{
name: '钢化节拍',
type: 'line',
tooltip: {
valueFormatter: function (value) {
return value + 'pcs/min';
},
},
data: this.barData.temperCt.map((item) => {
return item.ct;
}),
},
{
name: '下片节拍',
type: 'line',
tooltip: {
valueFormatter: function (value) {
return value + 'pcs/min';
},
},
data: this.barData.downCt.map((item) => {
return item.ct;
}),
},
],
});
},
},
};
</script>

View File

@@ -0,0 +1,273 @@
<!--
* @Author: zwq
* @Date: 2023-08-24 14:47:58
* @LastEditors: zwq
* @LastEditTime: 2025-01-09 10:04:17
* @Description:
-->
<template>
<div>
<base-table
:page="1"
:limit="999"
v-loading="dataListLoading"
:table-props="tableProps"
max-height="400"
:table-data="tableData">
<method-btn
v-if="tableData.length"
slot="handleBtn"
:width="80"
label="操作"
:method-list="tableBtn"
@clickBtn="handleClick" />
</base-table>
<div v-if="eqChartData.length > 0" style="margin-top: 10px">
<search-bar
:formConfigs="formConfig"
ref="searchBarForm1"
@headBtnClick="buttonClick" />
<div
ref="lineChart"
id="chart"
:style="{ height: '400px', width: '100%', marginLeft: '10px' }" />
</div>
</div>
</template>
<script>
import { getNewCTDet, getNewCTCharts } from '@/api/core/analysis/index';
import * as echarts from 'echarts';
require('echarts/theme/macarons'); // echarts theme
import resize from '@/utils/chartMixins/resize';
import { parseTime } from '../../mixins/code-filter';
const tableProps = [
{
prop: 'equipmentName',
label: '设备',
},
{
prop: 'size',
label: '规格',
showOverflowtooltip: true,
},
{
prop: 'process',
label: '产品工艺',
},
{
prop: 'standardCt',
label: '标准节拍pcs/min',
},
{
prop: 'ct',
label: '当前节拍pcs/min',
},
];
export default {
mixins: [resize],
data() {
return {
tableProps,
tableData: [],
tableBtn: [
{
type: 'eqChart',
btnName: '趋势图',
},
].filter((v) => v),
dataListLoading: false,
time: {},
eqChartData: [],
eqName: null,
equipmentId: null,
chart: null,
formConfig: [
{
type: 'datePicker',
label: '时间范围',
dateType: 'datetimerange',
format: 'yyyy-MM-dd HH:mm:ss',
valueFormat: 'timestamp',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
defaultTime: ['00:00:00', '23:59:59'],
param: 'timeVal',
width: 350,
clearable: false,
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary',
},
],
};
},
components: {},
created() {},
mounted() {},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
// 获取数据列表
init(lineId, startTime, endTime) {
this.eqChartData = [];
this.time.startTime = startTime;
this.time.endTime = endTime;
this.dataListLoading = true;
getNewCTDet(lineId).then((response) => {
this.tableData = response.data;
this.dataListLoading = false;
});
},
handleClick(val) {
const data = {
...this.time,
equipmentId: val.data.equipmentId,
};
this.eqName = val.data.equipmentName;
this.equipmentId = val.data.equipmentId;
getNewCTCharts(data).then((response) => {
this.eqChartData = response.data;
this.$nextTick(() => {
this.$refs.searchBarForm1.formInline.timeVal = [
this.time.startTime,
this.time.endTime,
];
this.initChart();
});
});
},
buttonClick(val) {
switch (val.btnName) {
case 'search':
this.time.startTime = val.timeVal ? val.timeVal[0] : undefined;
this.time.endTime = val.timeVal ? val.timeVal[1] : undefined;
const data = {
...this.time,
equipmentId: this.equipmentId,
};
getNewCTCharts(data).then((response) => {
this.eqChartData = response.data;
this.$nextTick(() => {
this.initChart();
});
});
break;
default:
console.log(val);
}
},
initChart() {
this.chart = echarts.init(this.$refs.lineChart);
const _this = this;
this.chart.setOption({
title: {
text: this.eqName
? '{space|}{tip|}{space|}{value|' + this.eqName + ' 节拍趋势图' + '}'
: '',
textStyle: {
rich: {
tip: {
width: 6,
height: 6,
borderRadius: 50,
backgroundColor: '#288AFF',
},
space: {
width: 8,
},
value: {
fontSize: 14,
color: 'black',
},
},
},
},
color: ['#288AFF', '#8EF0AB', '#FFDC94'],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999',
},
},
},
legend: {
data: ['当前节拍', '标准节拍'],
},
grid: {
containLabel: true,
},
xAxis: {
type: 'category',
data: this.eqChartData[0].ct.map((item) => {
return parseTime(item.recordTime, '{m}-{d} {h}:{i}');
}),
axisPointer: {
type: 'shadow',
},
},
yAxis: [
{
type: 'value',
name: '节拍',
min: 0,
interval: 20,
axisLabel: {
formatter: '{value} pcs/min',
},
},
],
dataZoom: [
{
type: 'inside',
start: 0,
end: 100,
},
{
start: 0,
end: 100,
},
],
series: [
{
name: '标准节拍',
type: 'line',
tooltip: {
valueFormatter: function (value) {
return value + 'pcs/min';
},
},
data: this.eqChartData[0].ct.map((item) => {
return item.standardCt;
}),
},
{
name: '当前节拍',
type: 'line',
tooltip: {
valueFormatter: function (value) {
return value + 'pcs/min';
},
},
data: this.eqChartData[0].ct.map((item) => {
return item.ct;
}),
},
],
});
},
},
};
</script>

View File

@@ -0,0 +1,296 @@
<template>
<div class="app-container">
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@headBtnClick="buttonClick" />
<div v-if="tableData.length">
<base-table
v-loading="dataListLoading"
:span-method="mergeColumnHandler"
:max-height="tableH"
:table-props="tableProps"
:table-data="tableData" />
<SearchBar :formConfigs="[{ label: '产线平衡分析图', type: 'title' }]" />
<balance-chart ref="lineChart" />
</div>
<div v-else class="no-data-bg"></div>
<!-- <pagination
:limit.sync="listQuery.pageSize"
:page.sync="listQuery.pageNo"
:total="listQuery.total"
@pagination="getDataList" /> -->
</div>
</template>
<script>
// import basicPage from '../../mixins/basic-page';
import { parseTime } from '../../mixins/code-filter';
import { getCT } from '@/api/core/analysis/index';
import { getProductionLinePage } from '@/api/core/base/productionLine';
import BalanceChart from '../balanceChart';
import { time } from 'echarts';
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
// import { getWorkshopSectionPage } from '@/api/core/base/workshopSection';
// const tableProps = [
// // {
// // prop: 'lineName',
// // label: '产线',
// // align: 'center',
// // },
// // {
// // prop: 'sum',
// // label: '合计',
// // align: 'center',
// // },
// // {
// // prop: 'dynamicValue',
// // label: 'dynamicName',
// // align: 'center',
// // children:[
// // ]
// // }
// ];
export default {
components: {
BalanceChart,
},
mixins: [tableHeightMixin],
data() {
return {
urlOptions: {
getDataListURL: getCT,
},
tableProps: [],
dataListLoading: false,
tableData: [],
listQuery: {
// time: ''
endTime: undefined,
lineId: undefined,
startTime: undefined,
},
timeList: [],
spanArr: [],
xData: [],
yData: [],
optionArrUrl: [getProductionLinePage],
formConfig: [
{
type: 'select',
label: '产线',
selectOptions: [],
param: 'lineIds',
defaultSelect: '',
multiple: false,
filterable: true,
},
{
type: 'datePicker',
label: '时间',
dateType: 'datetimerange',
format: 'yyyy-MM-dd',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
width: 350,
param: 'time',
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary',
},
],
};
},
created() {
this.getArr();
},
methods: {
getArr() {
const params = {
page: 1,
limit: 500,
};
this.optionArrUrl.forEach((item, index) => {
item(params).then((response) => {
this.formConfig[index].selectOptions = response.data.list;
});
});
},
setRowSpan(arr) {
let count = 0;
arr.forEach((item, index) => {
if (index === 0) {
this.spanArr.push(1);
} else {
if (item === arr[index - 1]) {
this.spanArr[count] += 1;
this.spanArr.push(0);
} else {
count = index;
this.spanArr.push(1);
}
}
});
},
/** 合并table列的规则 */
mergeColumnHandler({ row, column, rowIndex, columnIndex }) {
if (columnIndex == 0) {
if (this.spanArr[rowIndex]) {
return [
this.spanArr[rowIndex], // row span
1, // col span
];
} else {
return [0, 0];
}
}
},
getData() {
// this.listQuery.lineId = '1672847052717821953'
// this.listQuery.startTime = '1693497600000';
// this.listQuery.endTime = '1693843200000';
this.urlOptions.getDataListURL(this.listQuery).then((res) => {
console.log(res);
let arr = [
{
prop: 'sectionName',
label: '工段',
align: 'center',
},
{
prop: 'equName',
label: '设备',
align: 'center',
width: 150
},
];
let sectionArr = [];
res.data.data.forEach((ele, index) => {
let tempData = [];
let ggData = [];
let sbluData = [];
let sbsjData = [];
let cxluData = [];
let cxsjData = [];
ele.data.forEach((item, index) => {
item.children.forEach((params) => {
if (params.dynamicName === '生产规格') {
tempData[item.dynamicName + '_gg'] = params.dynamicValue;
ggData[index] = params.dynamicValue;
} else if (params.dynamicName === '设备理论速度') {
tempData[item.dynamicName + '_sblu'] = params.dynamicValue;
sbluData[index] = params.dynamicValue;
} else if (params.dynamicName === '设备实际速度') {
tempData[item.dynamicName + '_sbsj'] = params.dynamicValue;
sbsjData[index] = params.dynamicValue;
} else if (params.dynamicName === '产线理论速度') {
tempData[item.dynamicName + '_cxlu'] = params.dynamicValue;
cxluData[index] = params.dynamicValue;
} else if(params.dynamicName === '产线实际速度') {
tempData[item.dynamicName + '_cxsj'] = params.dynamicValue;
cxsjData[index] = params.dynamicValue;
}
});
});
const equipment = {
name: ele.equName,
ggData: ggData,
sbluData: sbluData,
sbsjData: sbsjData,
cxluData: cxluData,
cxsjData: cxsjData,
};
tempData['equName'] = ele.equName;
tempData['sectionName'] = ele.sectionName;
this.tableData.push(tempData);
const { sectionName } = tempData;
sectionArr.push(sectionName);
this.yData.push(equipment);
});
this.setRowSpan(sectionArr);
res.data.nameData.forEach((item) => {
this.timeList.push(item.name);
});
const timeArray = Array.from(new Set(this.timeList));
console.log(timeArray)
for (const times of timeArray) {
if (times !== '生产规格' && times !== '设备理论速度' && times !== '设备实际速度'
&& times !== '产线理论速度' && times !== '产线实际速度'
) {
const subprop = {
label: times,
align: 'center',
children: [
{ prop: times + '_gg', label: '生产规格', align: 'center' },
{ prop: times + '_sblu', label: '设备理论速度[片/min]', align: 'center' },
{ prop: times + '_sbsj', label: '设备实际速度[片/min]', align: 'center' },
{ prop: times + '_cxlu', label: '产线理论速度[片/min]', align: 'center' },
{ prop: times + '_cxsj', label: '产线实际速度[片/min]', align: 'center' },
],
};
arr.push(subprop);
this.xData.push(times);
}
}
this.tableProps = arr;
console.log(this.$refs)
this.$nextTick(()=>{
this.$refs.lineChart.initChart(this.xData, this.yData);
})
// this.total = response.data.total;
// this.dataListLoading = false;
});
},
buttonClick(val) {
// console.log(val)
switch (val.btnName) {
case 'search':
// this.listQuery.pageNo = 1;
// this.listQuery.pageSize = 10;
this.listQuery.lineId = val.lineIds;
this.listQuery.startTime = val.time
? String(new Date(val.time[0]).getTime())
: undefined;
this.listQuery.endTime = val.time
? String(new Date(val.time[1]).getTime())
: undefined;
if (val.time && val.lineIds) {
this.tableData = [];
this.xData = [];
this.yData = [];
this.tableProps = [];
this.spanArr = [];
this.timeList = [];
this.getData();
} else {
this.$message({
message: '请选择产线和时间',
type: 'warning',
});
}
break;
case 'reset':
this.$refs.searchBarForm.resetForm();
this.listQuery = {
pageSize: 10,
pageNo: 1,
total: 1,
};
this.getDataList();
break;
default:
console.log(val);
}
},
},
};
</script>

View File

@@ -1,260 +1,302 @@
<!--
* @Author: Do not edit
* @Date: 2023-08-29 14:59:29
* @LastEditTime: 2025-01-09 10:27:53
* @LastEditors: zwq
* @Description:
-->
<template> <template>
<div class="app-container"> <div class="app-container">
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" /> <search-bar
<div v-if="tableData.length"> :formConfigs="formConfig"
<base-table v-loading="dataListLoading" :span-method="mergeColumnHandler" :table-props="tableProps" :table-data="tableData" /> ref="searchBarForm"
<SearchBar :formConfigs="[{ label: '产线平衡分析图', type: 'title' }]" /> @select-changed="handleSearchBarChanged"
<balance-chart ref="lineChart" /> @headBtnClick="buttonClick" />
</div> <div v-if="showData.length">
<div v-else class="no-data-bg"></div> <base-table
<!-- <pagination class="right-aside"
:limit.sync="listQuery.pageSize" v-loading="dataListLoading"
:page.sync="listQuery.pageNo" :table-props="tableProps"
:total="listQuery.total" :page="1"
@pagination="getDataList" /> --> :limit="999"
</div> :table-data="showData">
<method-btn
v-if="showData.length"
slot="handleBtn"
:width="80"
label="操作"
:method-list="tableBtn"
@clickBtn="handleClick" />
</base-table>
<barChart
v-for="item in chartData"
:key="item.name + 'echart'"
style="margin-top: 50px"
height="600px"
:id="item.name + 'echart'"
:title="item.name + ' 节拍趋势图'"
:bar-data="item" />
</div>
<div v-else class="no-data-bg"></div>
<base-dialog
:dialogTitle="addOrEditTitle"
:dialogVisible="addOrUpdateVisible"
@cancel="handleCancel"
@confirm="handleConfirm"
:before-close="handleCancel"
close-on-click-modal
top="0"
width="50%">
<eq-detail ref="eqDetail" />
<slot name="footer">
<el-row slot="footer" type="flex" justify="end">
<el-col :span="24">
<el-button size="small" class="btnTextStyle" @click="handleCancel">
取消
</el-button>
</el-col>
</el-row>
</slot>
</base-dialog>
</div>
</template> </template>
<script> <script>
// import basicPage from '../../mixins/basic-page'; import eqDetail from './eq-detail';
import { parseTime } from '../../mixins/code-filter'; import { parseTime } from '../../mixins/code-filter';
import { getCT } from '@/api/core/analysis/index'; import { getPdList } from '@/api/core/monitoring/auto';
import { getProductionLinePage } from '@/api/core/base/productionLine'; import { getNewCTNow, getNewCTCharts } from '@/api/core/analysis/index';
import BalanceChart from '../balanceChart' import { getFactoryPage } from '@/api/core/base/factory';
import { time } from 'echarts'; // import codeFilter from '../../mixins/code-filter'
// import { getWorkshopSectionPage } from '@/api/core/base/workshopSection'; import * as XLSX from 'xlsx';
import FileSaver from 'file-saver';
import barChart from './BarChart.vue';
// const tableProps = [ const tableProps = [
// // { {
// // prop: 'lineName', prop: 'factoryName',
// // label: '产线', label: '工厂',
// // align: 'center', },
// // }, {
// // { prop: 'lineName',
// // prop: 'sum', label: '产线',
// // label: '合计', },
// // align: 'center', {
// // }, prop: 'size',
// // { label: '规格',
// // prop: 'dynamicValue', showOverflowtooltip: true,
// // label: 'dynamicName', },
// // align: 'center', {
// // children:[ prop: 'process',
label: '产品工艺',
// // ] },
// // } {
// ]; prop: 'edgeCt',
label: '磨边当前节拍pcs/min',
},
{
prop: 'temperCt',
label: '钢化当前节拍pcs/min',
},
{
prop: 'downCt',
label: '下片当前节拍pcs/min',
},
];
export default { export default {
components: { components: {
BalanceChart barChart,
}, eqDetail,
// mixins: [basicPage], },
data() { data() {
return { return {
urlOptions: { urlOptions: {
getDataListURL: getCT, getDataListURL: getNewCTNow,
}, },
tableProps: [], listQuery: {
dataListLoading: false, lineId: [],
tableData: [], },
listQuery: { fileName: '',
// time: '' dataListLoading: false,
endTime: undefined, tableProps,
lineId:undefined, tableBtn: [
startTime:undefined {
}, type: 'eq',
timeList: [], btnName: '详情',
spanArr: [], },
xData: [], ].filter((v) => v),
yData: [], showData: [],
optionArrUrl: [getProductionLinePage], tableData: [],
formConfig: [ chartData: [],
{ formConfig: [
type: 'select', {
label: '产线', type: 'select',
selectOptions: [], label: '工厂',
param: 'lineIds', selectOptions: [],
defaultSelect: '', param: 'factoryId',
multiple: false, onchange: true,
filterable: true, },
}, {
{ type: 'select',
type: 'datePicker', label: '产线',
label: '时间', selectOptions: [],
dateType: 'datetimerange', param: 'lineId',
format: 'yyyy-MM-dd', multiple: true,
valueFormat: 'yyyy-MM-dd HH:mm:ss', },
rangeSeparator: '-', {
startPlaceholder: '开始时间', type: 'datePicker',
endPlaceholder: '结束时间', label: '时间范围',
width: 350, dateType: 'datetimerange',
param: 'time', format: 'yyyy-MM-dd HH:mm:ss',
}, valueFormat: 'timestamp',
{ rangeSeparator: '-',
type: 'button', startPlaceholder: '开始时间',
btnName: '查询', endPlaceholder: '结束时间',
name: 'search', defaultTime: ['00:00:00', '23:59:59'],
color: 'primary', param: 'timeVal',
} width: 350,
], clearable: false,
}; },
}, {
created() { type: 'button',
this.getArr(); btnName: '查询',
}, name: 'search',
methods: { color: 'primary',
getArr() { },
const params = { // {
page: 1, // type: 'separate',
limit: 500 // },
} // {
this.optionArrUrl.forEach((item, index) => { // // type: this.$auth.hasPermi('base:factory:export') ? 'button' : '',
item(params).then((response) => { // type: 'button',
this.formConfig[index].selectOptions = response.data.list // btnName: '导出',
}); // name: 'export',
}); // color: 'warning',
}, // },
setRowSpan(arr) { ],
let count = 0 addOrEditTitle: '',
arr.forEach((item, index) => { addOrUpdateVisible: false,
if(index === 0) { };
this.spanArr.push(1) },
} else { created() {
if (item === arr[index - 1]) { // 获取当前时间
this.spanArr[count] += 1 const now = new Date();
this.spanArr.push(0) // 获取前一天的同一时间
} else { const yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000);
count = index // 设置为00:00:00
this.spanArr.push(1) yesterday.setHours(0, 0, 0, 0);
} // 设置为23:59:59
} const end = new Date(yesterday.getTime());
}) end.setHours(23, 59, 59, 59);
}, this.listQuery.startTime = yesterday.getTime();
/** 合并table列的规则 */ this.listQuery.endTime = end.getTime();
mergeColumnHandler({ row, column, rowIndex, columnIndex }) { this.$nextTick(() => {
if (columnIndex == 0) { this.$refs.searchBarForm.formInline.timeVal = [
if (this.spanArr[rowIndex]) { yesterday.getTime(),
return [ end.getTime(),
this.spanArr[rowIndex], // row span ];
1, // col span });
]; this.getDataList();
} else { this.getPdLineList();
return [0, 0]; },
} methods: {
handleExport() {
let tables = document.querySelector('.el-table').cloneNode(true);
const fix = tables.querySelector('.el-table__fixed');
const fixRight = tables.querySelector('.el-table__fixed-right');
if (fix) {
tables.removeChild(tables.querySelector('.el-table__fixed'));
}
if (fixRight) {
tables.removeChild(tables.querySelector('.el-table__fixed-right'));
}
let exportTable = XLSX.utils.table_to_book(tables);
var exportTableOut = XLSX.write(exportTable, {
bookType: 'xlsx',
bookSST: true,
type: 'array',
});
// sheetjs.xlsx为导出表格的标题名称
try {
FileSaver.saveAs(
new Blob([exportTableOut], {
type: 'application/octet-stream',
}),
this.fileName + '产线自动报表.xlsx'
);
} catch (e) {
if (typeof console !== 'undefined') console.log(e, exportTableOut);
}
return exportTableOut;
},
getPdLineList() {
getPdList().then((res) => {
this.formConfig[1].selectOptions = res.data || [];
});
const params = {
pageSize: 100,
pageNo: 1,
};
getFactoryPage(params).then((res) => {
this.formConfig[0].selectOptions = res.data.list || [];
});
},
buttonClick(val) {
switch (val.btnName) {
case 'search':
this.listQuery.factoryId = val.factoryId || undefined;
this.listQuery.lineId = val.lineId ? val.lineId : [];
this.listQuery.startTime = val.timeVal ? val.timeVal[0] : undefined;
this.listQuery.endTime = val.timeVal ? val.timeVal[1] : undefined;
this.getDataList();
break;
case 'export':
this.handleExport();
break;
default:
console.log(val);
} }
}, },
getData() { // 获取数据列表
// this.listQuery.lineId = '1672847052717821953' getDataList() {
// this.listQuery.startTime = '1693497600000'; this.dataListLoading = true;
// this.listQuery.endTime = '1693843200000'; this.urlOptions.getDataListURL(this.listQuery).then((response) => {
this.urlOptions.getDataListURL(this.listQuery).then(res => { this.tableData = response.data;
console.log(res) this.dataListLoading = false;
let arr = [ this.showData = this.tableData;
{ });
prop: 'sectionName', getNewCTCharts(this.listQuery).then((response) => {
label: '工段', this.chartData = response.data;
align: 'center', });
}, },
{ handleSearchBarChanged({ param, value }) {
prop: 'equName', this.listQuery.lineId = [];
label: '设备', this.$refs.searchBarForm.formInline.lineId = undefined;
align: 'center', getPdList(value).then((res) => {
} this.formConfig[1].selectOptions = res.data || [];
] });
let sectionArr= [] },
res.data.data.forEach((ele, index) => { handleClick(val) {
let tempData = [] this.addOrUpdateVisible = true;
let eqData = [] this.addOrEditTitle =
let plData = [] val.data?.factoryName + '-' + val.data?.lineName + ' 详情';
ele.data.forEach((item, index) => { this.$nextTick(() => {
item.children.forEach(params => { this.$refs.eqDetail.init(
if (params.dynamicName === '设备CT') { val.data.lineId,
tempData[item.dynamicName + '_eq'] = params.dynamicValue this.listQuery.startTime,
eqData[index] = params.dynamicValue this.listQuery.endTime
} else { );
tempData[item.dynamicName + '_pl'] = params.dynamicValue });
plData[index] = params.dynamicValue },
} handleCancel() {
}) this.addOrUpdateVisible = false;
}) this.addOrEditTitle = '';
const equipment = { },
name: ele.equName, handleConfirm() {
eqData: eqData, this.handleCancel();
plData: plData },
} },
tempData['equName'] = ele.equName
tempData['sectionName'] = ele.sectionName
this.tableData.push(tempData)
const { sectionName } = tempData
sectionArr.push(sectionName)
this.yData.push(equipment)
console.log('看看equ', this.yData)
})
this.setRowSpan(sectionArr)
res.data.nameData.forEach(item => {
this.timeList.push(item.name)
})
const timeArray = Array.from(new Set(this.timeList))
for (const times of timeArray) {
if (times !== '设备CT' && times !== '产线CT') {
const subprop = {
label: times,
align: 'center',
children: [
{ prop: times + '_eq', label: '设备CT', align: 'center' },
{ prop: times + '_pl', label: '产线CT', align: 'center' }
]
}
arr.push(subprop)
this.xData.push(times)
}
}
this.tableProps = arr
console.log('表格横坐标', this.xData)
this.$refs.lineChart.initChart(this.xData, this.yData)
// this.total = response.data.total;
// this.dataListLoading = false;
});
},
buttonClick(val) {
// console.log(val)
switch (val.btnName) {
case 'search':
// this.listQuery.pageNo = 1;
// this.listQuery.pageSize = 10;
this.listQuery.lineId = val.lineIds
this.listQuery.startTime = val.time ? String(new Date(val.time[0]).getTime()) : undefined;
this.listQuery.endTime = val.time ? String(new Date(val.time[1]).getTime()) : undefined;
if (val.time && val.lineIds) {
this.tableData = []
this.xData = []
this.yData = []
this.tableProps = []
this.spanArr = []
this.timeList = []
this.getData()
} else {
this.$message({
message: '请选择产线和时间',
type: 'warning'
});
}
break;
case 'reset':
this.$refs.searchBarForm.resetForm();
this.listQuery = {
pageSize: 10,
pageNo: 1,
total: 1,
};
this.getDataList();
break;
default:
console.log(val);
}
},
},
}; };
</script> </script>

View File

@@ -1,8 +1,8 @@
<!-- <!--
* @Author: zhp * @Author: zhp
* @Date: 2023-09-13 09:02:25 * @Date: 2023-09-13 09:02:25
* @LastEditTime: 2023-10-08 16:36:37 * @LastEditTime: 2024-11-26 15:52:29
* @LastEditors: DY * @LastEditors: zwq
* @Description: * @Description:
--> -->
<template> <template>
@@ -108,13 +108,28 @@ export default {
}, },
series: [ series: [
{ {
name: '设备CT', name: '生产规格',
data: dataList.eqData, data: dataList.ggData,
type: 'line', type: 'line',
}, },
{ {
name: '产线CT', name: '设备理论速度',
data: dataList.plData, data: dataList.sbluData,
type: 'line',
},
{
name: '设备实际速度',
data: dataList.sbsjData,
type: 'line',
},
{
name: '产线理论速度',
data: dataList.cxluData,
type: 'line',
},
{
name: '产线实际速度',
data: dataList.cxsjData,
type: 'line', type: 'line',
} }
] ]

View File

@@ -1,18 +1,25 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" /> <search-bar
<div v-if="tableData.length"> :formConfigs="formConfig"
<base-table v-loading="dataListLoading" :table-props="tableProps" :table-data="tableData" /> ref="searchBarForm"
<SearchBar :formConfigs="[{ label: '产品产量对比图', type: 'title' }]" /> @headBtnClick="buttonClick" />
<line-chart ref="lineChart" /> <div v-if="tableData.length">
</div> <base-table
<div v-else class="no-data-bg"></div> v-loading="dataListLoading"
<!-- <pagination :table-props="tableProps"
:max-height="tableH"
:table-data="tableData" />
<SearchBar :formConfigs="[{ label: '产品产量对比图', type: 'title' }]" />
<line-chart ref="lineChart" />
</div>
<div v-else class="no-data-bg"></div>
<!-- <pagination
:limit.sync="listQuery.pageSize" :limit.sync="listQuery.pageSize"
:page.sync="listQuery.pageNo" :page.sync="listQuery.pageNo"
:total="listQuery.total" :total="listQuery.total"
@pagination="getDataList" /> --> @pagination="getDataList" /> -->
</div> </div>
</template> </template>
<script> <script>
@@ -20,7 +27,8 @@
import { parseTime } from '../../mixins/code-filter'; import { parseTime } from '../../mixins/code-filter';
import { getYieldAnalysisPageData } from '@/api/core/analysis/index'; import { getYieldAnalysisPageData } from '@/api/core/analysis/index';
import { getProductionLinePage } from '@/api/core/base/productionLine'; import { getProductionLinePage } from '@/api/core/base/productionLine';
import lineChart from '../LineChart' import lineChart from '../LineChart';
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
// import { getWorkshopSectionPage } from '@/api/core/base/workshopSection'; // import { getWorkshopSectionPage } from '@/api/core/base/workshopSection';
// const tableProps = [ // const tableProps = [
@@ -45,51 +53,52 @@ import lineChart from '../LineChart'
// ]; // ];
export default { export default {
components: { components: {
lineChart, lineChart,
}, },
// mixins: [basicPage], mixins: [tableHeightMixin],
data() { data() {
return { return {
urlOptions: { urlOptions: {
getDataListURL: getYieldAnalysisPageData, getDataListURL: getYieldAnalysisPageData,
}, },
tableProps:[], tableProps: [],
dataListLoading:false, dataListLoading: false,
tableData: [], tableData: [],
listQuery: { listQuery: {
lineIds: [], lineIds: [],
time: '' time: '',
}, },
dateLabelList: [], dateLabelList: [],
optionArrUrl: [getProductionLinePage ], optionArrUrl: [getProductionLinePage],
formConfig: [ formConfig: [
{ {
type: 'select', type: 'select',
label: '产线', label: '产线',
selectOptions: [], selectOptions: [],
param: 'lineIds', param: 'lineIds',
defaultSelect: '', defaultSelect: [],
multiple:true, multiple: true,
filterable: true, filterable: true,
width: 400,
}, },
{ {
type: 'datePicker', type: 'datePicker',
label: '时间', label: '时间',
dateType: 'month', dateType: 'month',
format: 'yyyy-MM-dd', format: 'yyyy-MM',
valueFormat: 'yyyy-MM-dd HH:mm:ss', valueFormat: 'yyyy-MM-dd HH:mm:ss',
rangeSeparator: '-', rangeSeparator: '-',
startPlaceholder: '开始时间', startPlaceholder: '开始时间',
endPlaceholder: '结束时间', endPlaceholder: '结束时间',
param: 'time', param: 'time',
}, },
{ {
type: 'button', type: 'button',
btnName: '查询', btnName: '查询',
name: 'search', name: 'search',
color: 'primary', color: 'primary',
} },
], ],
}; };
}, },
@@ -104,145 +113,147 @@ export default {
}; };
this.optionArrUrl.forEach((item, index) => { this.optionArrUrl.forEach((item, index) => {
item(params).then((response) => { item(params).then((response) => {
this.formConfig[index].selectOptions = response.data.list this.formConfig[index].selectOptions = response.data.list;
// this.formConfig[0].defaultSelect = response.data.list[0].id // this.formConfig[0].defaultSelect = response.data.list[0].id
this.$set(this.formConfig[0], 'defaultSelect', response.data.list[0].id) // this.$set(this.formConfig[0], 'defaultSelect', response.data.list[0].id)
}); });
}); });
}, },
getData() { getData() {
// this.listQuery.lineIds = ['1672847052717821953'] // this.listQuery.lineIds = ['1672847052717821953']
// this.listQuery.productId = val.productId; // this.listQuery.productId = val.productId;
// this.listQuery.time = '1694486098000'; // this.listQuery.time = '1694486098000';
this.urlOptions.getDataListURL(this.listQuery).then(res => { this.urlOptions.getDataListURL(this.listQuery).then((res) => {
let arr = [ let arr = [
{ {
prop: 'lineName', prop: 'lineName',
label: '产线', label: '产线',
fixed: 'left' fixed: 'left',
}, },
{ {
prop: 'sum', prop: 'sum',
label: '合计', label: '合计[片]',
fixed: 'left' fixed: 'left',
}, },
{ {
prop: res.data ? res.data.nameData[0].name : undefined, prop: res.data ? res.data.nameData[0].name : undefined,
label: res.data ? res.data.nameData[0].name : undefined, label: res.data ? res.data.nameData[0].name : undefined,
align: 'center', align: 'center',
children:[ children: [],
},
];
// console.log(res.data.nameData.slice(1))
let xData = [];
let yAllData = [];
let lineName = [];
if (res.data) {
let tempDateList = [];
res.data.nameData.forEach((date) => {
tempDateList.push(date.name);
});
this.dateLabelList = Array.from(new Set(tempDateList));
] this.dateLabelList.forEach((item) => {
} if (item.indexOf('年') === -1) {
] // 构造表头
// console.log(res.data.nameData.slice(1)) const props = {
let xData = [] prop: item,
let yAllData = [] label: item,
let lineName = [] };
if (res.data) { arr[2].children.push(props);
let tempDateList = []
res.data.nameData.forEach(date => {
tempDateList.push(date.name)
})
this.dateLabelList = Array.from(new Set(tempDateList))
this.dateLabelList.forEach(item => { // 构造echarts横坐标
if (item.indexOf('年') === -1) { xData.push(item);
// 构造表头 }
const props = { });
'prop': item, // res.data.nameData.slice(1).forEach(item => {
'label': item // const props = {
} // 'prop': item.name,
arr[2].children.push(props) // 'label': item.name,
// 'align': 'center'
// }
// arr[2].children.push(props)
// })
let tableDataArr = [];
res.data.data.forEach((item) => {
let obj = {};
(obj.lineName = item.lineName),
(obj.sum = item.sum),
item.data.forEach((ele, index) => {
// console.log(ele)
ele.children.forEach((e) => {
console.log(e.dynamicName);
obj['' + e.dynamicName + ''] = e.dynamicValue;
console.log(obj['' + e.dynamicName + '']);
});
});
tableDataArr.push(obj);
});
this.tableData = tableDataArr;
this.tableProps = arr;
// 构造echarts横坐标 // let tempList = []
xData.push(item) // res.data.nameData.slice(1).forEach(item => {
} // tempList.push(item.name)
}) // // arr[2].children.push(props)
// res.data.nameData.slice(1).forEach(item => { // })
// const props = { // xData = Array.from(new Set(tempList))
// 'prop': item.name,
// 'label': item.name, res.data.data.forEach((item) => {
// 'align': 'center' let yData = [];
// } lineName.push(item.lineName);
// arr[2].children.push(props) // let obj = {}
// }) // obj.lineName = item.lineName,
let tableDataArr =[] // obj.sum = item.sum,
res.data.data.forEach(item => { item.data.forEach((ele, index) => {
let obj = {} // console.log(ele)
obj.lineName= item.lineName, ele.children.forEach((e) => {
obj.sum= item.sum, // let yData = []
item.data.forEach((ele, index) => { yData.push(e.dynamicValue);
// console.log(ele) });
ele.children.forEach((e) => { });
console.log(e.dynamicName) yAllData.push(yData);
obj['' + e.dynamicName + ''] = e.dynamicValue });
console.log(obj['' + e.dynamicName + '']); console.log(lineName);
}) } else {
}) this.tableProps = arr;
tableDataArr.push(obj) this.tableData = [];
}); xData = [];
this.tableData = tableDataArr yAllData = [];
this.tableProps = arr lineName = [];
}
// let tempList = [] // res.data.data[0].data[0].children.forEach((item, index) => {
// res.data.nameData.slice(1).forEach(item => { // // console.log(item)
// tempList.push(item.name) // yData.push(item.dynamicValue)
// // arr[2].children.push(props) // // let data = 'data' + Number(index+1)
// }) // // obj['' + item.dynamicName + ''] = item.dynamicValue
// xData = Array.from(new Set(tempList)) // })
// console.log(this.yData)
res.data.data.forEach(item => { this.$nextTick(() => {
let yData = [] this.$refs.lineChart.initChart(xData, yAllData, lineName);
lineName.push(item.lineName) });
// let obj = {} // this.total = response.data.total;
// obj.lineName = item.lineName, // this.dataListLoading = false;
// obj.sum = item.sum, });
item.data.forEach((ele, index) => { },
// console.log(ele) buttonClick(val) {
ele.children.forEach((e) => {
// let yData = []
yData.push(e.dynamicValue)
})
})
yAllData.push(yData)
});
console.log(lineName)
} else {
this.tableProps = arr
this.tableData = []
xData = []
yAllData = []
lineName = []
}
// res.data.data[0].data[0].children.forEach((item, index) => {
// // console.log(item)
// yData.push(item.dynamicValue)
// // let data = 'data' + Number(index+1)
// // obj['' + item.dynamicName + ''] = item.dynamicValue
// })
// console.log(this.yData)
this.$refs.lineChart.initChart(xData, yAllData, lineName)
// this.total = response.data.total;
// this.dataListLoading = false;
});
},
buttonClick(val) {
switch (val.btnName) { switch (val.btnName) {
case 'search': case 'search':
this.listQuery.lineIds = val.lineIds ? val.lineIds :undefined this.listQuery.lineIds = val.lineIds ? val.lineIds : undefined;
// this.listQuery.productId = val.productId; // this.listQuery.productId = val.productId;
this.listQuery.time = val.time ? new Date(val.time).getTime() : undefined this.listQuery.time = val.time
? new Date(val.time).getTime()
: undefined;
// this.listQuery.pageNo = 1; // this.listQuery.pageNo = 1;
// this.listQuery.pageSize = 10; // this.listQuery.pageSize = 10;
if (val.time) { if (val.time) {
this.getData() this.getData();
} else { } else {
this.$message({ this.$message({
message: '请选择时间', message: '请选择时间',
type: 'warning' type: 'warning',
}); });
} }
break; break;
case 'reset': case 'reset':
this.$refs.searchBarForm.resetForm(); this.$refs.searchBarForm.resetForm();

View File

@@ -59,24 +59,36 @@
<i class="el-icon-delete"></i> <i class="el-icon-delete"></i>
</div> --> </div> -->
<div <div
class="file-list__item"
v-for="(file, index) in files" v-for="(file, index) in files"
:key="file.fileName" :key="file.fileName"
:style="{ style="width: 100%">
background: isPicMode <div
? `url(${file.fileUrl}) no-repeat` class="file-list__item"
: `url(${defaultBg}) no-repeat`, v-if="!isPicMode"
backgroundSize: isPicMode ? '100% 100%' : '64px', :style="{
backgroundPosition: isPicMode ? '0% 0%' : 'center', background: isPicMode
}" ? `url(${file.fileUrl}) no-repeat`
:data-name="file.fileName"> : `url(${defaultBg}) no-repeat`,
<el-button backgroundSize: isPicMode ? '100% 100%' : '64px',
v-if="!disabled" backgroundPosition: isPicMode ? '0% 0%' : 'center',
type="text" }"
class="el-icon-delete" @click="handleDownload(file)"
style="padding: 0" :data-name="file.fileName">
@click="(e) => handleDelete(file)" /> <el-button
</div> v-if="!disabled"
type="text"
class="el-icon-delete"
style="padding: 0"
@click="(e) => handleDelete(file)" />
</div>
<el-image
v-else
class="file-list__item"
style="width: 100%"
:src="file.fileUrl"
:preview-src-list="files.map((item) => item.fileUrl)"></el-image>
</div>
</section> </section>
</div> </div>
</template> </template>
@@ -277,6 +289,32 @@ export default {
// Array // Array
this.$emit('update-filelist', this.appendFilelist); this.$emit('update-filelist', this.appendFilelist);
}, },
async handleDownload(file) {
if (this.isPicMode) {
// this.$emit('preview', file);
const link = document.createElement('a');
link.href = file.fileUrl;
link.target = '_blank';
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
} else {
// this.$emit('download', file);
const data = await this.$axios({
url: file.fileUrl,
method: 'get',
responseType: 'blob',
});
const link = document.createElement('a');
link.href = window.URL.createObjectURL(new Blob([data]));
link.download = file.fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
window.URL.revokeObjectURL(link.href);
}
},
}, },
}; };
</script> </script>

View File

@@ -1,4 +1,4 @@
<!-- <!--
filename: dialogForm.vue filename: dialogForm.vue
author: liubin author: liubin
date: 2023-08-15 10:32:36 date: 2023-08-15 10:32:36
@@ -44,7 +44,7 @@
<el-date-picker <el-date-picker
v-if="col.datetime" v-if="col.datetime"
v-model="form[col.prop]" v-model="form[col.prop]"
type="datetime" type="date"
:placeholder="`请选择${col.label}`" :placeholder="`请选择${col.label}`"
value-format="timestamp" value-format="timestamp"
v-bind="col.bind"></el-date-picker> v-bind="col.bind"></el-date-picker>

View File

@@ -308,6 +308,7 @@ export default {
}); });
if (code == 0) { if (code == 0) {
this.$modal.msgSuccess('更新成功'); this.$modal.msgSuccess('更新成功');
this.$emit('refreshDataList');
} }
this.btnLoading = false; this.btnLoading = false;

View File

@@ -1,4 +1,4 @@
<!-- <!--
filename: dialogForm.vue filename: dialogForm.vue
author: liubin author: liubin
date: 2023-08-15 10:32:36 date: 2023-08-15 10:32:36
@@ -57,6 +57,7 @@
v-model="form.equipmentTypeId" v-model="form.equipmentTypeId"
:disabled="disabled" :disabled="disabled"
filterable filterable
clearable
placeholder="请选择设备类型"> placeholder="请选择设备类型">
<el-option <el-option
v-for="eqType in eqTypeList" v-for="eqType in eqTypeList"
@@ -79,9 +80,9 @@
<el-col :span="8"> <el-col :span="8">
<el-form-item label="生产日期" prop="productionTime" :rules="[]"> <el-form-item label="生产日期" prop="productionTime" :rules="[]">
<el-date-picker <el-date-picker
v-model="form.enterTime" v-model="form.productionTime"
:disabled="disabled" :disabled="disabled"
type="datetime" type="date"
placeholder="请选择生产日期" placeholder="请选择生产日期"
value-format="timestamp"></el-date-picker> value-format="timestamp"></el-date-picker>
</el-form-item> </el-form-item>
@@ -91,14 +92,14 @@
<el-date-picker <el-date-picker
v-model="form.enterTime" v-model="form.enterTime"
:disabled="disabled" :disabled="disabled"
type="datetime" type="date"
placeholder="请选择进场日期" placeholder="请选择进场日期"
value-format="timestamp"></el-date-picker> value-format="timestamp"></el-date-picker>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="8"> <el-col :span="8">
<el-form-item <el-form-item
label="设备TT值" label="设备理论生产能效(片/min)"
prop="tvalue" prop="tvalue"
:rules="[ :rules="[
{ required: true, message: '不能为空', trigger: 'blur' }, { required: true, message: '不能为空', trigger: 'blur' },
@@ -112,7 +113,7 @@
<el-input <el-input
v-model="form.tvalue" v-model="form.tvalue"
:disabled="disabled" :disabled="disabled"
placeholder="请输入设备TT值"></el-input> placeholder="请输入"></el-input>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -316,7 +317,7 @@ export default {
this.form this.form
); );
// 保存原始文件名 // 保存原始文件名
if ('fileNames' in this.form) this.form.fileNames.push(file.name); if ('fileNames' in this.form) this.form.fileNames.push(file.name+Date.now());
// 保存完整地址 // 保存完整地址
if ('fileUrls' in this.form) this.form.fileUrls.push(response.data); if ('fileUrls' in this.form) this.form.fileUrls.push(response.data);
this.$modal.msgSuccess('上传成功'); this.$modal.msgSuccess('上传成功');

View File

@@ -38,7 +38,7 @@
@cancel="cancel" @cancel="cancel"
width="60%" width="60%"
@confirm="submitForm"> @confirm="submitForm">
<DialogForm <DialogForm1
v-if="open" v-if="open"
key="index-dialog-form" key="index-dialog-form"
ref="form" ref="form"
@@ -78,7 +78,7 @@
queryParams: { queryParams: {
equipmentId: form.id, equipmentId: form.id,
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 20,
}, },
tableBtn: [ tableBtn: [
this.$auth.hasPermi('base:equipment-attr:update') this.$auth.hasPermi('base:equipment-attr:update')
@@ -107,6 +107,7 @@
import moment from 'moment'; import moment from 'moment';
import basicPageMixin from '@/mixins/lb/basicPageMixin'; import basicPageMixin from '@/mixins/lb/basicPageMixin';
import EquipmentDrawer from './components/EquipmentDrawer'; import EquipmentDrawer from './components/EquipmentDrawer';
import DialogForm1 from './components/DialogForm';
import { import {
createEquipment, createEquipment,
@@ -124,6 +125,7 @@ export default {
components: { components: {
Editor, Editor,
EquipmentDrawer, EquipmentDrawer,
DialogForm1,
}, },
mixins: [basicPageMixin], mixins: [basicPageMixin],
data() { data() {
@@ -157,7 +159,12 @@ export default {
width: 180, width: 180,
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'), filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
}, },
{ prop: 'name', label: '设备名称' }, {
width: 200,
showOverflowtooltip: true,
prop: 'name',
label: '设备名称',
},
{ width: 256, prop: 'code', label: '设备编码' }, { width: 256, prop: 'code', label: '设备编码' },
{ prop: 'equipmentType', label: '设备类型' }, { prop: 'equipmentType', label: '设备类型' },
{ prop: 'enName', label: '英文名称' }, { prop: 'enName', label: '英文名称' },
@@ -270,6 +277,7 @@ export default {
url: '/base/equipment-type/page?pageNo=1&pageSize=100', url: '/base/equipment-type/page?pageNo=1&pageSize=100',
bind: { bind: {
filterable: true, filterable: true,
clearable: true,
}, },
}, },
// { // {
@@ -294,7 +302,7 @@ export default {
{ {
input: true, input: true,
prop: 'tvalue', prop: 'tvalue',
label: '设备TT值', label: '设备理论生产能效(片/min)',
rules: [ rules: [
{ required: true, message: '不能为空', trigger: 'blur' }, { required: true, message: '不能为空', trigger: 'blur' },
{ {
@@ -435,7 +443,7 @@ export default {
// 查询参数 // 查询参数
queryParams: { queryParams: {
pageNo: 1, pageNo: 1,
pageSize: 10, pageSize: 20,
code: '', code: '',
name: '', name: '',
}, },
@@ -561,6 +569,7 @@ export default {
return; return;
} }
// 添加的提交 // 添加的提交
this.form.files = [];
createEquipment(this.form).then((response) => { createEquipment(this.form).then((response) => {
this.$modal.msgSuccess('新增成功'); this.$modal.msgSuccess('新增成功');
this.open = false; this.open = false;

View File

@@ -153,6 +153,9 @@ export default {
label: '父类', label: '父类',
prop: 'parentId', prop: 'parentId',
url: '/base/equipment-type/page?pageNo=1&pageSize=100', url: '/base/equipment-type/page?pageNo=1&pageSize=100',
bind: {
clearable: true, // some condition, like detail mode...
}
}, },
{}, {},
], ],
@@ -237,25 +240,6 @@ export default {
const id = row.id; const id = row.id;
getEquipmentType(id).then((response) => { getEquipmentType(id).then((response) => {
this.form = response.data; this.form = response.data;
// this.form = {
// code: 'SBLX20230925184444000041',
// name: '测试131',
// remark: '测试可删除',
// id: '1706258479729336322',
// files: [
// { fileName: '1.png', fileUrl: '', fileType: 2 },
// { fileName: '1.asdfaslkjfkasdf.png', fileUrl: '', fileType: 2 },
// { fileName: '2.txt', fileUrl: '', fileType: 2 },
// { fileName: '1.rar', fileUrl: '', fileType: 2 },
// { fileName: '1.kkk', fileUrl: '', fileType: 2 },
// { fileName: 'test.file', fileUrl: '', fileType: 2 },
// { fileName: '222', fileUrl: '', fileType: 2 },
// { fileName: 'g', fileUrl: '', fileType: 2 },
// ],
// createTime: 1695638697000,
// parentId: '1701869972319584257',
// };
// debugger;
this.open = true; this.open = true;
this.title = '修改设备类型'; this.title = '修改设备类型';
}); });

View File

@@ -0,0 +1,99 @@
<!--
* @Author: zwq
* @Date: 2023-08-02 15:12:42
* @LastEditors: zwq
* @LastEditTime: 2024-11-29 13:25:51
* @Description:
-->
<template>
<div class="app-container">
<search-bar
:formConfigs="[{ label: '产线在制工艺', type: 'title' }]"
ref="searchBarForm" />
<base-table
v-loading="dataListLoading"
:table-props="tableProps"
:page="listQuery.pageNo"
:limit="listQuery.pageSize"
:table-data="tableData"
@emitFun="inputChange" />
<pagination
:limit.sync="listQuery.pageSize"
:page.sync="listQuery.pageNo"
:total="listQuery.total"
@pagination="getDataList" />
</div>
</template>
<script>
import basicPage from '../../mixins/basic-page';
import { parseTime } from '../../mixins/code-filter';
import { getLineBindProcessPage } from '@/api/core/base/lineBindProcess';
import selectProduct from './selectProduct';
const tableProps = [
{
prop: 'lineName',
label: '产线'
},
{
prop: 'processDictName',
label: '在制工艺',
list: [],
subcomponent: selectProduct,
},
{
prop: 'recordTime',
label: '开始时间',
filter: parseTime,
},
];
export default {
mixins: [basicPage, selectProduct],
data() {
return {
urlOptions: {
getDataListURL: getLineBindProcessPage,
},
tableProps,
tableData: [],
// formConfig: [
// {
// type: 'button',
// btnName: '同步',
// name: 'search',
// color: 'primary',
// },
// ],
};
},
components: {},
created() {
},
methods: {
// 获取数据列表
getDataList() {
this.dataListLoading = true;
this.urlOptions.getDataListURL(this.listQuery).then(response => {
this.tableData = response.data;
this.dataListLoading = false;
});
},
buttonClick(val) {
switch (val.btnName) {
case 'search':
this.listQuery.pageNo = 1;
this.listQuery.pageSize = 10;
this.getDataList();
break;
default:
console.log(val);
}
},
inputChange() {
this.getDataList();
},
},
};
</script>

View File

@@ -0,0 +1,83 @@
<!--
* @Author: zwq
* @Date: 2023-08-03 14:09:18
* @LastEditors: zwq
* @LastEditTime: 2025-02-24 15:21:07
* @Description:
-->
<template>
<div class="tableInner">
<el-popover
placement="top"
title="切换在制工艺"
width="160"
v-model="visible">
<el-select v-model="list.processDict" style="margin: 5px" filterable>
<el-option
v-for="opt in getDictDatas(DICT_TYPE.PROCESS_TYPE)"
:key="opt.value"
:label="opt.label"
:value="opt.value"></el-option>
</el-select>
<div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="visible = false">
取消
</el-button>
<el-button type="primary" size="mini" @click="changeInput">
确定
</el-button>
</div>
<el-button type="text" slot="reference">
<svg-icon icon-class="changelogo" />
</el-button>
</el-popover>
<el-input
readonly
v-model="list.processDictName"
style="width: 50%; margin-left: 5px"></el-input>
</div>
</template>
<script>
import { switchLineBindProcess } from '@/api/core/base/lineBindProcess';
export default {
props: {
injectData: {
type: Object,
default: () => ({}),
},
},
data() {
return {
list: this.injectData,
visible: false,
};
},
mounted() {
},
methods: {
changeInput() {
const processDictName = this.getDictDatas(this.DICT_TYPE.PROCESS_TYPE).find(item=>
item.value == this.list.processDict
)
const data = {
id: this.list.id,
processDict: this.list.processDict,
processDictName: processDictName.label,
};
switchLineBindProcess(data).then((response) => {
this.$modal.msgSuccess('修改成功');
this.visible = false;
this.$emit('emitData');
});
},
},
};
</script>
<style scoped>
.tableInner .el-input__inner {
border: none;
padding: 0;
height: 33px;
}
</style>

View File

@@ -0,0 +1,164 @@
<template>
<div class="app-container">
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@select-changed="handleSearchBarChanged"
@headBtnClick="buttonClick" />
<base-table
v-loading="dataListLoading"
:table-props="tableProps"
:page="listQuery.pageNo"
:limit="listQuery.pageSize"
:table-data="tableData" />
<pagination
:limit.sync="listQuery.pageSize"
:page.sync="listQuery.pageNo"
:total="listQuery.total"
@pagination="getDataList" />
</div>
</template>
<script>
import basicPage from '../../mixins/basic-page';
import { parseTime } from '../../mixins/code-filter';
import { getLineBindProcessLogPage } from '@/api/core/base/lineBindProcess';
import { getProductionLinePage } from '@/api/core/base/productionLine';
import { getPdList } from '@/api/core/monitoring/auto';
import { getFactoryPage } from '@/api/core/base/factory';
const tableProps = [
{
prop: 'factoryName',
label: '工厂'
},
{
prop: 'lineName',
label: '产线',
},
{
prop: 'processDictName',
label: '在制工艺',
},
{
prop: 'recordTime',
label: '开始时间',
filter: parseTime,
},
];
export default {
mixins: [basicPage],
data() {
return {
urlOptions: {
getDataListURL: getLineBindProcessLogPage,
},
tableProps,
tableData: [],
optionArrUrl: [getFactoryPage,getProductionLinePage],
listQuery: {
productionLineId: [],
},
formConfig: [
{
type: 'select',
label: '工厂',
selectOptions: [],
param: 'factoryId',
onchange: true,
},
{
type: 'select',
label: '产线',
selectOptions: [],
param: 'productionLineId',
multiple: true,
},
{
type: 'select',
label: '在制工艺',
selectOptions: this.getDictDatas(this.DICT_TYPE.PROCESS_TYPE),
labelField: 'label',
valueField: 'value',
param: 'processDict',
defaultSelect: '',
filterable: true,
},
{
type: 'datePicker',
label: '时间',
dateType: 'daterange',
format: 'yyyy-MM-dd',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'startTime',
},
{
type: 'button',
btnName: '搜索',
name: 'search',
color: 'primary',
},
{
type: 'button',
btnName: '重置',
name: 'reset',
},
],
};
},
components: {},
created() {
this.getArr();
},
methods: {
handleSearchBarChanged({ param, value }) {
this.listQuery.productionLineId = [];
this.$refs.searchBarForm.formInline.productionLineId = undefined;
getPdList(value).then((res) => {
this.formConfig[1].selectOptions = res.data || [];
});
},
getArr() {
const params = {
page: 1,
limit: 500,
};
this.optionArrUrl.forEach((item, index) => {
item(params).then((response) => {
this.formConfig[index].selectOptions = response.data.list;
});
});
},
buttonClick(val) {
switch (val.btnName) {
case 'search':
this.listQuery.pageNo = 1;
this.listQuery.pageSize = 10;
this.listQuery.factoryId = val.factoryId || undefined;
this.listQuery.productionLineId = val.productionLineId || [];
this.listQuery.processDict = val.processDict;
this.listQuery.recordTime = val.startTime
? [val.startTime[0], val.startTime[1].substr(0, 10) + ' 23:59:59']
: null;
this.getDataList();
break;
case 'reset':
this.$refs.searchBarForm.resetForm();
this.listQuery = {
pageSize: 10,
pageNo: 1,
total: 1,
};
this.getDataList();
break;
default:
console.log(val);
}
},
},
};
</script>

View File

@@ -0,0 +1,53 @@
<!--
* @Author: zhp
* @Date: 2023-01-31 14:12:10
* @LastEditTime: 2024-11-29 10:49:37
* @LastEditors: zwq
* @Description:
-->
<template>
<span>
<el-switch
@change="changeStatus"
v-model="injectData.allowAuto"
:active-value="true"
:inactive-value="false"></el-switch>
</span>
</template>
<script>
import { switchAutoProduct } from '@/api/core/base/lineBindProduct';
export default {
props: {
injectData: {
type: Object,
default: () => ({}),
},
},
data() {
return {
urlOptions: {
submitURL: switchAutoProduct,
},
};
},
methods: {
// 子级
changeStatus() {
// 路由参数
let obj = {
allowAuto: this.injectData.allowAuto,
id: this.injectData.id,
};
this.urlOptions.submitURL(obj).then((res) => {
console.log(res)
if (res.code !== 0) {
return this.$message.error(res.msg);
}
this.$modal.msgSuccess('切换状态成功');
this.$emit('emitData');
});
},
},
};
</script>

View File

@@ -1,8 +1,8 @@
<!-- <!--
* @Author: zwq * @Author: zwq
* @Date: 2023-08-02 15:12:42 * @Date: 2023-08-02 15:12:42
* @LastEditors: DY * @LastEditors: zwq
* @LastEditTime: 2023-10-13 16:35:03 * @LastEditTime: 2024-11-29 10:47:46
* @Description: * @Description:
--> -->
<template> <template>
@@ -30,6 +30,7 @@ import basicPage from '../../mixins/basic-page';
import { parseTime } from '../../mixins/code-filter'; import { parseTime } from '../../mixins/code-filter';
import { getLineBindProductPage } from '@/api/core/base/lineBindProduct'; import { getLineBindProductPage } from '@/api/core/base/lineBindProduct';
import selectProduct from './selectProduct'; import selectProduct from './selectProduct';
import changeStatus from './changeStatus';
import { getProductPage } from '@/api/core/base/product'; import { getProductPage } from '@/api/core/base/product';
const tableProps = [ const tableProps = [
@@ -43,6 +44,11 @@ const tableProps = [
list: [], list: [],
subcomponent: selectProduct, subcomponent: selectProduct,
}, },
{
prop: 'allowAuto',
label: '允许自动',
subcomponent: changeStatus,
},
{ {
prop: 'recordTime', prop: 'recordTime',
label: '开始时间', label: '开始时间',

View File

@@ -3,6 +3,7 @@
<search-bar <search-bar
:formConfigs="formConfig" :formConfigs="formConfig"
ref="searchBarForm" ref="searchBarForm"
@select-changed="handleSearchBarChanged"
@headBtnClick="buttonClick" /> @headBtnClick="buttonClick" />
<base-table <base-table
v-loading="dataListLoading" v-loading="dataListLoading"
@@ -24,15 +25,21 @@ import { parseTime } from '../../mixins/code-filter';
import { getLineBindProductLogPage } from '@/api/core/base/lineBindProductLog'; import { getLineBindProductLogPage } from '@/api/core/base/lineBindProductLog';
import { getProductionLinePage } from '@/api/core/base/productionLine'; import { getProductionLinePage } from '@/api/core/base/productionLine';
import { getProductPage } from '@/api/core/base/product'; import { getProductPage } from '@/api/core/base/product';
import { getFactoryPage } from '@/api/core/base/factory';
import { getPdList } from '@/api/core/monitoring/auto';
const tableProps = [ const tableProps = [
{
prop: 'factoryName',
label: '工厂'
},
{ {
prop: 'productionLineName', prop: 'productionLineName',
label: '产线' label: '产线',
}, },
{ {
prop: 'productName', prop: 'productName',
label: '在制产品' label: '在制产品',
}, },
{ {
prop: 'startTime', prop: 'startTime',
@@ -55,15 +62,24 @@ export default {
}, },
tableProps, tableProps,
tableData: [], tableData: [],
optionArrUrl: [getProductionLinePage, getProductPage], listQuery: {
productionLineId: [],
},
optionArrUrl: [getFactoryPage,getProductionLinePage, getProductPage],
formConfig: [ formConfig: [
{
type: 'select',
label: '工厂',
selectOptions: [],
param: 'factoryId',
onchange: true,
},
{ {
type: 'select', type: 'select',
label: '产线', label: '产线',
selectOptions: [], selectOptions: [],
param: 'productionLineId', param: 'productionLineId',
defaultSelect: '', multiple: true,
filterable: true,
}, },
{ {
type: 'select', type: 'select',
@@ -83,7 +99,7 @@ export default {
startPlaceholder: '开始时间', startPlaceholder: '开始时间',
endPlaceholder: '结束时间', endPlaceholder: '结束时间',
param: 'startTime', param: 'startTime',
valueFormat: 'timestamp' valueFormat: 'timestamp',
}, },
{ {
type: 'button', type: 'button',
@@ -99,12 +115,18 @@ export default {
], ],
}; };
}, },
components: { components: {},
},
created() { created() {
this.getArr(); this.getArr();
}, },
methods: { methods: {
handleSearchBarChanged({ param, value }) {
this.listQuery.productionLineId = [];
this.$refs.searchBarForm.formInline.productionLineId = undefined;
getPdList(value).then((res) => {
this.formConfig[1].selectOptions = res.data || [];
});
},
getArr() { getArr() {
const params = { const params = {
page: 1, page: 1,
@@ -121,9 +143,10 @@ export default {
case 'search': case 'search':
this.listQuery.pageNo = 1; this.listQuery.pageNo = 1;
this.listQuery.pageSize = 10; this.listQuery.pageSize = 10;
this.listQuery.productionLineId = val.productionLineId; this.listQuery.factoryId = val.factoryId || undefined;
this.listQuery.productionLineId = val.productionLineId || [];
this.listQuery.productId = val.productId; this.listQuery.productId = val.productId;
this.listQuery.startTime = val.startTime; this.listQuery.startTime = val.startTime ? val.startTime : null;
this.getDataList(); this.getDataList();
break; break;
case 'reset': case 'reset':

View File

@@ -72,19 +72,37 @@
</el-row> </el-row>
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
<el-form-item label="规格" prop="specifications"> <el-form-item label="原片规格" prop="originalSpecifications">
<el-input <el-input
:disabled="isdetail" :disabled="isdetail"
v-model="dataForm.specifications" v-model="dataForm.originalSpecifications"
placeholder="请输入规格" /> placeholder="请输入原片规格" />
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="单位平方数" prop="area"> <el-form-item label="原片单位平方数" prop="originalArea">
<el-input
:disabled="isdetail"
v-model="dataForm.originalArea"
placeholder="请输入原片单位平方数" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="深加工规格" prop="specifications">
<el-input
:disabled="isdetail"
v-model="dataForm.specifications"
placeholder="请输入深加工规格" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="深加工单位平方数" prop="area">
<el-input <el-input
:disabled="isdetail" :disabled="isdetail"
v-model="dataForm.area" v-model="dataForm.area"
placeholder="请输入单位平方数" /> placeholder="请输入深加工单位平方数" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -154,7 +172,9 @@
<el-button v-if="isdetail" type="primary" @click="goEdit()"> <el-button v-if="isdetail" type="primary" @click="goEdit()">
编辑 编辑
</el-button> </el-button>
<el-button v-else type="primary" @click="dataFormSubmit()">确定</el-button> <el-button v-else type="primary" @click="dataFormSubmit()">
确定
</el-button>
</div> </div>
<product-attr-add <product-attr-add
@@ -220,11 +240,13 @@ export default {
id: null, id: null,
name: '', // 产品名称 name: '', // 产品名称
code: '', // 产品编码 code: '', // 产品编码
area: 0, // 单位平方数(float only) area: 0, // 深加工单位平方数(float only)
typeDictValue: null, // 产品类型id typeDictValue: null, // 产品类型id
processTime: null, // 单位产品用时 (s) processTime: null, // 单位产品用时 (s)
specifications: '', // 规格 specifications: '', // 深加工规格
unitDictValue: '', // 单位id unitDictValue: '', // 单位id
originalSpecifications: '', // 原片规格
originalArea: 0, // 原片单位平方数
}, },
listQuery: { listQuery: {
pageSize: 10, pageSize: 10,
@@ -371,8 +393,19 @@ export default {
// 添加的提交 // 添加的提交
createProduct(this.dataForm).then((response) => { createProduct(this.dataForm).then((response) => {
this.$modal.msgSuccess('新增成功'); this.$modal.msgSuccess('新增成功');
this.visible = false; this.$confirm(`是否新增产品属性?`, '系统提示', {
this.$emit('refreshDataList'); confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(() => {
this.dataForm.id = response.data
this.addNew();
})
.catch(() => {
this.visible = false;
this.$emit('refreshDataList');
});
}); });
} }
}); });
@@ -382,10 +415,14 @@ export default {
}, },
// 新增 / 修改 // 新增 / 修改
addNew(id) { addNew(id) {
this.addOrUpdateVisible = true; if (this.dataForm.id) {
this.$nextTick(() => { this.addOrUpdateVisible = true;
this.$refs.addOrUpdate.init(id); this.$nextTick(() => {
}); this.$refs.addOrUpdate.init(id);
});
} else {
this.$message('请先创建产品!');
}
}, },
goback() { goback() {
this.$emit('refreshDataList'); this.$emit('refreshDataList');

View File

@@ -1,8 +1,8 @@
<!-- <!--
* @Author: zwq * @Author: zwq
* @Date: 2023-08-01 14:55:51 * @Date: 2023-08-01 14:55:51
* @LastEditors: DY * @LastEditors: zwq
* @LastEditTime: 2023-10-13 10:27:00 * @LastEditTime: 2025-02-24 16:06:59
* @Description: * @Description:
--> -->
<template> <template>
@@ -49,27 +49,31 @@ import {
const tableProps = [ const tableProps = [
{ {
prop: 'code', prop: 'createTime',
label: '产品编码' label: '创建时间',
filter: parseTime
}, },
{ {
prop: 'name', prop: 'name',
label: '产品名称' label: '产品名称'
}, },
{
prop: 'code',
label: '产品编码'
},
{
prop: 'originalSpecifications',
label: '原片规格'
},
{ {
prop: 'specifications', prop: 'specifications',
label: '规格' label: '深加工规格'
}, },
{ {
prop: 'unitDictValue', prop: 'unitDictValue',
label: '单位', label: '单位',
subcomponent: unitDict, subcomponent: unitDict,
}, },
{
prop: 'createTime',
label: '创建时间',
filter: parseTime
},
]; ];
export default { export default {

View File

@@ -2,7 +2,7 @@
* @Author: zwq * @Author: zwq
* @Date: 2023-08-01 13:52:10 * @Date: 2023-08-01 13:52:10
* @LastEditors: zwq * @LastEditors: zwq
* @LastEditTime: 2024-04-10 16:31:51 * @LastEditTime: 2025-02-24 15:32:45
* @Description: * @Description:
--> -->
<template> <template>
@@ -12,6 +12,7 @@
:rules="dataRule" :rules="dataRule"
ref="dataForm" ref="dataForm"
@keyup.enter.native="dataFormSubmit()" @keyup.enter.native="dataFormSubmit()"
label-position="top"
label-width="90px"> label-width="90px">
<el-row :gutter="20"> <el-row :gutter="20">
<el-col :span="12"> <el-col :span="12">
@@ -48,11 +49,11 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="产线TT值(h)" prop="tvalue"> <el-form-item label="产线理论生产能效(片/min)" prop="tvalue">
<el-input <el-input
v-model="dataForm.tvalue" v-model="dataForm.tvalue"
clearable clearable
placeholder="请输入每小时下片数量" /> placeholder="请输入数量" />
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
@@ -80,6 +81,17 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-form-item label="描述" prop="description">
<el-input
v-model="dataForm.description"
type="textarea"
placeholder="请输入内容" />
</el-form-item>
</el-col>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="备注" prop="remark"> <el-form-item label="备注" prop="remark">
<el-input <el-input
@@ -89,17 +101,6 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> </el-row>
<el-row>
<el-col>
<el-form-item label="描述" prop="description">
<el-input
v-model="dataForm.description"
type="textarea"
placeholder="请输入内容" />
</el-form-item>
</el-col>
</el-row>
</el-form> </el-form>
</template> </template>
@@ -139,11 +140,11 @@ export default {
}, },
pdTypeArr: [ pdTypeArr: [
{ {
id: 0, id: '0',
name: '深加工' name: '深加工'
}, },
{ {
id: 1, id: '1',
name: '原片' name: '原片'
} }
], ],
@@ -159,6 +160,7 @@ export default {
], ],
tvalue: [ tvalue: [
{ {
required: true,
type: 'number', type: 'number',
message: '请输入正确的数字', message: '请输入正确的数字',
trigger: 'change', trigger: 'change',

View File

@@ -48,6 +48,7 @@ import {
exportProductionLineExcel, exportProductionLineExcel,
getStatus, getStatus,
} from '@/api/core/base/productionLine'; } from '@/api/core/base/productionLine';
import { getFactoryPage } from '@/api/core/base/factory';
const tableProps = [ const tableProps = [
{ {
@@ -121,6 +122,13 @@ export default {
].filter((v) => v), ].filter((v) => v),
tableData: [], tableData: [],
formConfig: [ formConfig: [
{
type: 'select',
label: '工厂',
selectOptions: [],
param: 'factoryId',
onchange: true,
},
{ {
type: 'input', type: 'input',
label: '产线名称', label: '产线名称',
@@ -168,7 +176,15 @@ export default {
components: { components: {
AddOrUpdate, AddOrUpdate,
}, },
created() {}, created() {
const params = {
pageSize: 100,
pageNo: 1,
};
getFactoryPage(params).then((res) => {
this.formConfig[0].selectOptions = res.data.list || [];
});
},
methods: { methods: {
// 获取数据列表 // 获取数据列表
getDataList() { getDataList() {
@@ -197,6 +213,7 @@ export default {
case 'search': case 'search':
this.listQuery.pageNo = 1; this.listQuery.pageNo = 1;
this.listQuery.pageSize = 10; this.listQuery.pageSize = 10;
this.listQuery.factoryId = val.factoryId || undefined;
this.listQuery.name = val.name; this.listQuery.name = val.name;
this.getDataList(); this.getDataList();
break; break;

View File

@@ -3,6 +3,7 @@
<search-bar <search-bar
:formConfigs="formConfig" :formConfigs="formConfig"
ref="searchBarForm" ref="searchBarForm"
@select-changed="handleSearchBarChanged"
@headBtnClick="buttonClick" /> @headBtnClick="buttonClick" />
<base-table <base-table
v-loading="dataListLoading" v-loading="dataListLoading"
@@ -46,6 +47,8 @@ import {
getWorkshopSectionPage, getWorkshopSectionPage,
exportWorkshopSectionExcel exportWorkshopSectionExcel
} from "@/api/core/base/workshopSection"; } from "@/api/core/base/workshopSection";
import { getPdList } from '@/api/core/monitoring/auto';
import { getFactoryPage } from '@/api/core/base/factory';
const tableProps = [ const tableProps = [
{ {
@@ -56,6 +59,10 @@ const tableProps = [
prop: 'name', prop: 'name',
label: '工段名称' label: '工段名称'
}, },
{
prop: 'factoryName',
label: '工厂'
},
{ {
prop: 'productionLineName', prop: 'productionLineName',
label: '产线' label: '产线'
@@ -99,8 +106,25 @@ export default {
} }
: undefined, : undefined,
].filter((v)=>v), ].filter((v)=>v),
listQuery: {
lineId: [],
},
tableData: [], tableData: [],
formConfig: [ formConfig: [
{
type: 'select',
label: '工厂',
selectOptions: [],
param: 'factoryId',
onchange: true,
},
{
type: 'select',
label: '产线',
selectOptions: [],
param: 'lineId',
multiple: true,
},
{ {
type: 'input', type: 'input',
label: '工段名称', label: '工段名称',
@@ -146,14 +170,37 @@ export default {
components: { components: {
AddOrUpdate, AddOrUpdate,
}, },
created() {}, created() {
this.getPdLineList();
},
methods: { methods: {
getPdLineList() {
getPdList().then((res) => {
this.formConfig[1].selectOptions = res.data || [];
});
const params = {
pageSize: 100,
pageNo: 1,
};
getFactoryPage(params).then((res) => {
this.formConfig[0].selectOptions = res.data.list || [];
});
},
handleSearchBarChanged({ param, value }) {
this.listQuery.lineId = [];
this.$refs.searchBarForm.formInline.lineId = undefined;
getPdList(value).then((res) => {
this.formConfig[1].selectOptions = res.data || [];
});
},
buttonClick(val) { buttonClick(val) {
switch (val.btnName) { switch (val.btnName) {
case 'search': case 'search':
this.listQuery.pageNo = 1; this.listQuery.pageNo = 1;
this.listQuery.pageSize = 10; this.listQuery.pageSize = 10;
this.listQuery.name = val.name; this.listQuery.name = val.name;
this.listQuery.factoryId = val.factoryId || undefined;
this.listQuery.lineId = val.lineId || [];
this.getDataList(); this.getDataList();
break; break;
case 'reset': case 'reset':

View File

@@ -1,8 +1,8 @@
<!-- <!--
* @Author: Do not edit * @Author: Do not edit
* @Date: 2023-08-29 14:59:29 * @Date: 2023-08-29 14:59:29
* @LastEditTime: 2023-10-16 15:10:42 * @LastEditTime: 2024-12-02 13:59:32
* @LastEditors: DY * @LastEditors: zwq
* @Description: * @Description:
--> -->
<template> <template>
@@ -92,7 +92,8 @@ const tableProps = [
}, },
{ {
prop: 'outputArea', prop: 'outputArea',
label: '产出面积/㎡' label: '产出面积/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
{ {
prop: 'lossNum', prop: 'lossNum',
@@ -100,11 +101,13 @@ const tableProps = [
}, },
{ {
prop: 'lossArea', prop: 'lossArea',
label: '损耗面积/㎡' label: '损耗面积/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
{ {
prop: 'lossRatio', prop: 'lossRatio',
label: '损耗比例%' label: '损耗比例%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
} }
]; ];
@@ -180,7 +183,6 @@ export default {
startPlaceholder: '开始时间', startPlaceholder: '开始时间',
endPlaceholder: '结束时间', endPlaceholder: '结束时间',
param: 'timeVal', param: 'timeVal',
defaultSelect: [],
width: 350 width: 350
}, },
{ {
@@ -312,8 +314,8 @@ export default {
this.listQuery.pageSize = 10; this.listQuery.pageSize = 10;
this.listQuery.lineId = val.line ? val.line : undefined; this.listQuery.lineId = val.line ? val.line : undefined;
this.listQuery.reportType = val.reportType ? val.reportType : undefined; this.listQuery.reportType = val.reportType ? val.reportType : undefined;
this.listQuery.reportStartTime = val.timeVal ? [new Date(val.timeVal[0]).getTime()] : undefined; this.listQuery.reportStartTime = val.timeVal ? [new Date(val.timeVal[0]).getTime(),new Date(val.timeVal[1]).getTime()] : undefined;
this.listQuery.reportEndTime = val.timeVal ? [new Date(val.timeVal[1]).getTime()] : undefined; //this.listQuery.reportEndTime = val.timeVal ? [new Date(val.timeVal[1]).getTime()] : undefined;
if (val.timeVal && val.timeVal.length > 0) { if (val.timeVal && val.timeVal.length > 0) {
this.fileName = val.timeVal[0].slice(0, 10) + '-' + val.timeVal[1].slice(0, 10) + '_' this.fileName = val.timeVal[0].slice(0, 10) + '-' + val.timeVal[1].slice(0, 10) + '_'
} }

View File

@@ -0,0 +1,169 @@
<template>
<div
:class="className"
:style="{ height: height, width: width, marginLeft: '10px' }" />
</template>
<script>
import * as echarts from 'echarts';
require('echarts/theme/macarons'); // echarts theme
import resize from '@/utils/chartMixins/resize';
const animationDuration = 1000;
export default {
mixins: [resize],
props: {
className: {
type: String,
default: 'chart',
},
title: {
type: String,
default: '',
},
width: {
type: String,
default: '100%',
},
height: {
type: String,
default: '300px',
},
barData: {
type: Array,
default: () => [],
},
},
data() {
return {
chart: null,
targetId: '',
};
},
beforeDestroy() {
if (!this.chart) {
return;
}
this.chart.dispose();
this.chart = null;
},
methods: {
initChart() {
this.chart = echarts.init(this.$el, 'macarons');
const _this = this;
this.chart.setOption({
title: {
text: this.title
? '{space|}{tip|}{space|}{value|' + this.title + '}'
: '',
textStyle: {
rich: {
tip: {
width: 6,
height: 6,
borderRadius: 50,
backgroundColor: '#288AFF',
},
space: {
width: 8,
},
value: {
fontSize: 14,
color: 'black',
},
},
},
},
color: ['#288AFF', '#8EF0AB', '#FFDC94'],
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'cross',
crossStyle: {
color: '#999',
},
},
},
legend: {
data: ['投入', '产出', '加工成品率'],
},
grid: {
containLabel: true,
},
xAxis: {
type: 'category',
data: this.barData.map((item) => {
return item.lineName;
}),
axisPointer: {
type: 'shadow',
},
},
yAxis: [
{
type: 'value',
name: '投入/产出 片',
min: 0,
axisLabel: {
formatter: '{value}',
},
},
{
type: 'value',
name: '加工成品率',
min: 0,
max: 100,
interval: 10,
axisLabel: {
formatter: '{value} %',
},
},
],
series: [
{
name: '投入',
type: 'bar',
barWidth: '20',
data: this.barData.map((item) => {
return item.inputNum;
}),
tooltip: {
valueFormatter: function (value) {
return value + ' 片';
},
},
animationDuration,
},
{
name: '产出',
type: 'bar',
barWidth: '20',
data: this.barData.map((item) => {
return item.outputNum;
}),
tooltip: {
valueFormatter: function (value) {
return value + ' 片';
},
},
animationDuration,
},
{
name: '加工成品率',
type: 'line',
yAxisIndex: 1,
tooltip: {
valueFormatter: function (value) {
return value + ' %';
},
},
data: this.barData.map((item) => {
return item.processingRatio;
}),
},
],
});
},
},
};
</script>

View File

@@ -0,0 +1,273 @@
<template>
<div class="baseTable">
<el-table
:ref="id"
:data="renderData"
v-bind="$attrs"
:border="cancelBorder ? false : true"
@current-change="currentChange"
@selection-change="handleSelectionChange"
style="width: 100%"
:header-cell-style="{
background: '#F2F4F9',
color: '#606266',
}">
<!-- 多选 -->
<el-table-column
v-if="selectWidth"
type="selection"
:width="selectWidth" />
<!-- 序号 -->
<el-table-column
v-if="page && limit"
prop="_pageIndex"
:width="pageWidth"
align="center"
:fixed="cancelPageFixed ? false : true">
<template slot="header">
<el-popover placement="bottom-start" width="300" trigger="click">
<div
class="setting-box"
style="max-height: 400px; overflow-y: auto">
<el-checkbox
v-for="(item, index) in tableProps"
:key="'cb' + index"
v-model="selectedBox[index]"
:label="item.label" />
</div>
<i slot="reference" class="el-icon-s-tools" />
</el-popover>
</template>
</el-table-column>
<el-table-column
v-for="item in renderTableHeadList"
:key="item.prop"
v-bind="item"
:label="item.label"
:prop="item.prop"
:fixed="item.fixed || false"
:show-overflow-tooltip="item.showOverflowtooltip || false"
:sortable="item.sortable || false">
<template slot="header">
<span>{{ item.label }}</span>
</template>
<!-- 多表头 -->
<template v-if="item.children">
<el-table-column
v-for="sub in item.children"
:prop="sub.prop"
:key="sub.prop"
v-bind="sub"
:label="sub.label">
<template v-if="sub.children">
<el-table-column
v-for="ssub in sub.children"
:prop="ssub.prop"
:key="ssub.prop"
v-bind="ssub"
:label="ssub.label">
<template slot-scope="sscopeInner">
<component
:is="ssub.subcomponent"
v-if="ssub.subcomponent"
:key="sscopeInner.row.id"
:inject-data="{ ...sscopeInner.row, ...ssub }"
@emitData="emitData" />
<span v-else>
{{ sscopeInner.row[ssub.prop] | commonFilter(ssub.filter) }}
</span>
</template>
</el-table-column>
</template>
<template slot-scope="scopeInner">
<component
:is="sub.subcomponent"
v-if="sub.subcomponent"
:key="scopeInner.row.id"
:inject-data="{ ...scopeInner.row, ...sub }"
@emitData="emitData" />
<span v-else>
{{ scopeInner.row[sub.prop] | commonFilter(sub.filter) }}
</span>
</template>
</el-table-column>
</template>
<template slot-scope="scope">
<component
:is="item.subcomponent"
v-if="item.subcomponent"
:key="scope.row.id"
:itemProp="item.prop"
:inject-data="{ ...scope.row, ...item }"
@emitData="emitData" />
<span v-else>
{{ scope.row[item.prop] | commonFilter(item.filter) }}
</span>
</template>
</el-table-column>
<slot name="handleBtn" />
</el-table>
<!-- 表格底部加号 -->
<el-button
v-if="addButtonShow"
class="addButton"
icon="el-icon-plus"
@click="emitButtonClick">
{{ addButtonShow }}
</el-button>
</div>
</template>
<script>
export default {
name: 'BaseTable',
filters: {
commonFilter: (source, filterType = (a) => a) => {
return filterType(source);
},
},
props: {
cancelBorder: {
type: Boolean,
default: false,
},
cancelPageFixed: {
type: Boolean,
default: false,
},
tableData: {
type: Array,
required: true,
default: () => {
return [];
},
},
tableProps: {
type: Array,
default: () => {
return [];
},
},
id: {
type: String,
required: false,
default: '',
},
page: {
type: Number,
required: false,
default: 0,
},
pageWidth: {
type: Number,
required: false,
default: 70,
},
limit: {
type: Number,
required: false,
default: 0,
},
selectWidth: {
type: Number,
required: false,
default: 0,
},
addButtonShow: {
type: String,
required: false,
default: '',
},
},
data() {
return {
selectedBox: new Array(100).fill(true),
};
},
computed: {
renderTableHeadList() {
return this.tableProps.filter((item, index) => {
return this.selectedBox[index];
});
},
renderData() {
return this.tableData.map((item, index) => {
return {
...item,
_pageIndex: (this.page - 1) * this.limit + index + 1,
};
});
},
},
beforeMount() {
this.selectedBox = new Array(100).fill(true);
},
methods: {
currentChange(newVal, oldVal) {
this.$emit('current-change', { newVal, oldVal });
},
handleSelectionChange(val) {
this.$emit('selection-change', val);
},
emitData(val) {
this.$emit('emitFun', val);
},
emitButtonClick() {
this.$emit('emitButtonClick');
},
setCurrent(name, index) {
let _this = this;
let obj = _this.$refs[name].data[index];
_this.$refs[name].setCurrentRow(obj);
},
doLayout(name) {
this.$refs[name].doLayout();
},
},
};
</script>
<style scoped>
.baseTable .show-col-btn {
margin-right: 5px;
line-height: inherit;
cursor: pointer;
}
.baseTable .el-icon-refresh {
cursor: pointer;
}
</style>
<style>
.baseTable .el-table__body tr.current-row > td.el-table__cell {
background-color: #eaf1fc;
}
.baseTable .el-table .el-table__cell {
padding: 0;
height: 35px;
}
.baseTable .addButton {
width: 100%;
height: 35px;
border-top: none;
color: #0b58ff;
border-color: #ebeef5;
border-radius: 0;
}
.baseTable .addButton:hover {
color: #0b58ff;
border-color: #ebeef5;
background-color: #fff;
}
.baseTable .addButton:focus {
border-color: #ebeef5;
background-color: #fff;
}
.el-tooltip__popper.is-dark {
background: rgba(0, 0, 0, 0.6) !important;
}
.el-tooltip__popper .popper__arrow,
.el-tooltip__popper .popper__arrow::after {
border-top-color: rgba(0, 0, 0, 0.4) !important;
}
</style>

View File

@@ -0,0 +1,314 @@
<!--
* @Author: Do not edit
* @Date: 2023-08-29 14:59:29
* @LastEditTime: 2024-12-02 13:43:57
* @LastEditors: zwq
* @Description:
-->
<template>
<div class="app-container">
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@headBtnClick="buttonClick" />
<base-table
v-if="showData.length"
class="right-aside"
v-loading="dataListLoading"
:table-props="tableProps"
:page="listQuery.pageNo"
:limit="listQuery.pageSize"
:selectWidth="55"
:table-data="showData"
@selection-change="selectChange"
>
<method-btn
v-if="tableBtn.length"
slot="handleBtn"
:width="120"
label="操作"
:method-list="tableBtn"
@clickBtn="handleClick" />
</base-table>
<div v-else class="no-data-bg"></div>
<pagination
:limit.sync="listQuery.pageSize"
:page.sync="listQuery.pageNo"
:total="listQuery.total"
@pagination="getDataList" />
<el-dialog
title="提示"
:visible.sync="dialogVisible"
width="30%"
:before-close="handleClose">
<el-button type="primary" @click="exportXlsx">xlsx</el-button>
<el-button type="success" @click="exportPdf">pdf</el-button>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { getPdlDataSearch, getPdList } from '@/api/core/monitoring/data'
import * as XLSX from 'xlsx'
import FileSaver from 'file-saver'
import jsPDF from 'jspdf'
import html2canvas from 'html2canvas'
const tableProps = [
{
prop: 'proLineName',
label: '产线名称'
},
{
prop: 'inputNum',
label: '投入数量/片'
},
{
prop: 'outputNum',
label: '产出数量/片'
},
{
prop: 'outputArea',
label: '产出面积/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'lossNum',
label: '损耗数量/片'
},
{
prop: 'lossArea',
label: '损耗面积/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'lossRate',
label: '损耗比例%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
}
];
export default {
data() {
return {
urlOptions: {
getDataListURL: getPdlDataSearch
},
tableData: [],
listQuery: {
pageSize: 10,
pageNo: 1,
total: 1,
proLineId: undefined
},
exportLoading: false,
dataListLoading: false,
dialogVisible: false,
addOrEditTitle: '',
addOrUpdateVisible: false,
tableProps,
tableBtn: [],
showData: [],
tableData: [],
selectedList: [],
fileName: '',
formConfig: [
{
type: 'select',
label: '产线',
selectOptions: [],
param: 'line'
},
{
type: 'datePicker',
label: '时间范围',
dateType: 'datetimerange',
format: 'yyyy-MM-dd HH:mm:ss',
valueFormat: "yyyy-MM-ddTHH:mm:ss",
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeVal',
defaultSelect: [],
width: 350
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary',
},
{
type: 'separate',
},
{
// type: this.$auth.hasPermi('base:factory:export') ? 'button' : '',
type: 'button',
btnName: '导出',
name: 'export',
color: 'warning',
}
],
};
},
created() {
if (this.$route.params.startTime) {
this.formConfig[1].defaultSelect = [this.$route.params.startTime, this.$route.params.endTime]
}
// const time = new Date()
// this.formConfig[1].defaultSelect = [time, time]
this.getDataList()
this.getPdLineList()
},
methods: {
test() {
var target = document.getElementsByClassName("right-aside")[0]
target.style.background = '#FFFFFF'
var that = this
setTimeout(() => {
html2canvas(target).then(function(canvas) {
var contentWidth = canvas.width
var contentHeight = canvas.height
// 一页pdf显示html页面生成的canvas高度
var pageHeight = contentHeight / 592.28 * 841.89
// 未生成pdf的html页面高度
var leftHeight = contentHeight
// 页面偏移
var position = 0
// a4纸的尺寸[595.28,841.89]html页面生成的canvas在pdf中图片的高度
var imgWidth = 595.28
var imgHeight = 592.28 / contentWidth * contentHeight
var pageData = canvas.toDataURL('image/jpeg', 1.0)
console.log('nihc URL', leftHeight, pageHeight)
var pdf = new jsPDF('', 'pt', 'a4')
if (leftHeight < pageHeight) {
pdf.addImage(pageData, 'JPEG', 0, 20, imgWidth, imgHeight)
} else {
while(leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
leftHeight -= pageHeight
position -= 841.89
// 避免空白页
if (leftHeight > 0) {
pdf.addPage()
}
}
}
pdf.save(that.fileName + '产线产量.pdf')
})
}, 300)
},
exportECL() {
let tables = document.querySelector('.el-table').cloneNode(true)
const fix = tables.querySelector('.el-table__fixed')
const fixRight = tables.querySelector('.el-table__fixed-right')
if (fix) {
tables.removeChild(tables.querySelector('.el-table__fixed'))
}
if (fixRight) {
tables.removeChild(tables.querySelector('.el-table__fixed-right'))
}
let exportTable = XLSX.utils.table_to_book(tables)
var exportTableOut = XLSX.write(exportTable, {
bookType: 'xlsx', bookSST: true, type: 'array'
})
// sheetjs.xlsx为导出表格的标题名称
try {
FileSaver.saveAs(new Blob([exportTableOut], {
type: 'application/octet-stream'
}), this.fileName + '产线产量.xlsx')
} catch (e) {
if (typeof console !== 'undefined') console.log(e, exportTableOut)
}
return exportTableOut
},
exportPdf() {
this.test()
setTimeout(() =>{
this.dialogVisible = false
this.showData = this.tableData
}, 600)
},
exportXlsx() {
this.exportECL()
this.dialogVisible = false
this.showData = this.tableData
},
handleClose(done) {
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
},
getPdLineList() {
getPdList().then((res) => {
this.formConfig[0].selectOptions = res.data || []
})
},
selectChange(val) {
console.log(val)
this.selectedList = val
},
buttonClick(val) {
switch (val.btnName) {
case 'search':
this.listQuery.pageNo = 1;
this.listQuery.pageSize = 10;
this.listQuery.proLineId = val.line ? val.line : undefined;
this.listQuery.startTime = val.timeVal ? new Date(val.timeVal[0]).getTime() : undefined;
this.listQuery.endTime = val.timeVal ? new Date(val.timeVal[1]).getTime() : undefined;
if (val.timeVal && val.timeVal.length > 0) {
this.fileName = val.timeVal[0].slice(0, 10) + '-' + val.timeVal[1].slice(0, 10) + '_'
}
this.getDataList();
break;
case 'export':
this.handleExport();
break;
default:
console.log(val);
}
},
// 获取数据列表
getDataList() {
this.dataListLoading = true;
this.urlOptions.getDataListURL(this.listQuery).then(response => {
this.tableData = response.data;
this.listQuery.total = response.data.length;
this.dataListLoading = false;
this.showData = this.tableData
});
},
// 每页数
sizeChangeHandle(val) {
this.listQuery.pageSize = val;
this.listQuery.pageNo = 1;
this.getDataList();
},
// 当前页
currentChangeHandle(val) {
this.listQuery.pageNo = val;
this.getDataList();
},
handleExport() {
if (this.selectedList.length > 0) {
this.showData = this.selectedList
}
this.dialogVisible = true
}
},
};
</script>

View File

@@ -1,138 +1,313 @@
<!--
* @Author: Do not edit
* @Date: 2023-08-29 14:59:29
* @LastEditTime: 2023-10-16 15:18:23
* @LastEditors: DY
* @Description:
-->
<template> <template>
<div class="app-container"> <div>
<search-bar <div style="background: #f2f4f9; height: 40px; width: 100%">
:formConfigs="formConfig" <ButtonNav :menus="['当前', '历史']" @change="currentMenu">
ref="searchBarForm" <template v-slot:tab1>
@headBtnClick="buttonClick" /> <div>当前</div>
<base-table </template>
v-if="showData.length" <template v-slot:tab2>
class="right-aside" <div>历史</div>
v-loading="dataListLoading" </template>
:table-props="tableProps" </ButtonNav>
:page="listQuery.pageNo" </div>
:limit="listQuery.pageSize" <div class="app-container energyOverlimitLog">
:selectWidth="55" <div v-show="activeName === 'his'">
:table-data="showData" <!-- 搜索工作栏 -->
@selection-change="selectChange" <search-bar
> :formConfigs="formConfig"
<method-btn ref="searchBarForm"
v-if="tableBtn.length" @select-changed="handleSearchBarChanged"
slot="handleBtn" @headBtnClick="buttonClick" />
:width="120" </div>
label="操作" <div v-show="activeName === 'now'"></div>
:method-list="tableBtn" <!-- 列表 -->
@clickBtn="handleClick" /> <div v-if="activeName === 'his'">
</base-table> <base-table-s
<div v-else class="no-data-bg"></div> :page="1"
<pagination :limit="100"
:limit.sync="listQuery.pageSize" :table-props="tableProps"
:page.sync="listQuery.pageNo" :table-data="tableData"
:total="listQuery.total" :max-height="tableH / 2"></base-table-s>
@pagination="getDataList" /> <div v-if="listQuery.lineId.length !== 1 && tableData.length > 0">
<el-dialog <barChart
title="提示" style="margin-top: 50px"
:visible.sync="dialogVisible" ref="barChart"
width="30%" height="600px"
:before-close="handleClose"> :bar-data="tableData" />
<el-button type="primary" @click="exportXlsx">xlsx</el-button> </div>
<el-button type="success" @click="exportPdf">pdf</el-button> </div>
<span slot="footer" class="dialog-footer"> <div v-if="activeName === 'now'">
<el-button @click="dialogVisible = false"> </el-button> <span class="blue-block"></span>
<el-button type="primary" @click="dialogVisible = false"> </el-button> <span class="tip">当班数据</span>
</span> <base-table-s
</el-dialog> :page="1"
:limit="100"
:table-props="tableProps"
:table-data="tableData2"
:max-height="tableH / 2" />
<span class="blue-block"></span>
<span class="tip">当天数据</span>
<base-table-s
:page="1"
:limit="100"
:table-props="tableProps"
:table-data="tableData3"
:max-height="tableH / 2" />
</div>
</div>
</div> </div>
</template> </template>
<script> <script>
import { getPdlDataSearch, getPdList } from '@/api/core/monitoring/data' import {
import * as XLSX from 'xlsx' getPdlAutoReportNewSearch,
import FileSaver from 'file-saver' getPdlAutoReportNewSearchNow,
import jsPDF from 'jspdf' } from '@/api/core/monitoring/data';
import html2canvas from 'html2canvas' import { getPdList } from '@/api/core/monitoring/auto';
import { getFactoryPage } from '@/api/core/base/factory';
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
import ButtonNav from '@/components/ButtonNav';
import baseTableS from './baseTable.vue';
import barChart from './BarChart.vue';
import * as XLSX from 'xlsx';
import FileSaver from 'file-saver';
const tableProps = [ const tableProps = [
{ {
prop: 'proLineName', prop: 'factoryName',
label: '产线名称' label: '工厂',
fixed: true
}, },
{ {
prop: 'inputNum', prop: 'lineName',
label: '投入数量/片' label: '产线',
fixed: true
}, },
{ {
prop: 'outputNum', prop: 'sizes',
label: '产出数量/片' label: '规格',
width: 105,
showOverflowtooltip: true,
fixed: true
}, },
{
prop: 'outputArea',
label: '产出面积/㎡'
},
{
prop: 'lossNum',
label: '损耗数量/片'
},
{
prop: 'lossArea',
label: '损耗面积/㎡'
},
{
prop: 'lossRate',
label: '损耗比例%'
}
];
{
prop: 'inputN',
label: '投入',
align: 'center',
children: [
{
prop: 'inputNum',
label: '投入数量/片',
},
{
prop: 'inputArea',
label: '投入面积/m²',
},
],
},
{
prop: 'outputN',
label: '产出',
align: 'center',
children: [
{
prop: 'outputNum',
label: '产出数量/片',
},
{
prop: 'outputArea',
label: '产出面积/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'lossN',
label: '不良',
align: 'center',
children: [
{
prop: 'lossNum',
label: '不良数量/片',
},
{
prop: 'lossArea',
label: '不良面积/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'lossRatio',
label: '不良率/%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'outputRatio',
label: '投入产出率/%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'processingRatio',
label: '加工成品率/%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'lossD',
label: '不良详情',
align: 'center',
children: [
{
prop: 'original',
label: '原片',
align: 'center',
children: [
{
prop: 'originalLossNum',
label: '原片不良/片',
},
{
prop: 'originalLossArea',
label: '原片不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'edge',
label: '磨边',
align: 'center',
children: [
{
prop: 'edgeLossNum',
label: '磨边不良/片',
},
{
prop: 'edgeLossArea',
label: '磨边不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'drill',
label: '打孔',
align: 'center',
children: [
{
prop: 'drillLossNum',
label: '打孔不良/片',
},
{
prop: 'drillLossArea',
label: '打孔不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'coating',
label: '镀膜',
align: 'center',
children: [
{
prop: 'coatingLossNum',
label: '镀膜不良/片',
},
{
prop: 'coatingLossArea',
label: '镀膜不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'silk',
label: '丝印',
align: 'center',
children: [
{
prop: 'silkLossNum',
label: '丝印不良/片',
},
{
prop: 'silkLossArea',
label: '丝印不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'tempering',
label: '钢化',
align: 'center',
children: [
{
prop: 'temperingLossNum',
label: '钢化不良/片',
},
{
prop: 'temperingLossArea',
label: '钢化不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'packing',
label: '包装',
align: 'center',
children: [
{
prop: 'packingLossNum',
label: '包装不良/片',
},
{
prop: 'packingLossArea',
label: '包装不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
],
},
];
export default { export default {
name: '',
mixins: [tableHeightMixin],
data() { data() {
return { return {
urlOptions: { urlOptions: {
getDataListURL: getPdlDataSearch getDataListURL: getPdlAutoReportNewSearch,
}, },
tableData: [],
listQuery: {
pageSize: 10,
pageNo: 1,
total: 1,
proLineId: undefined
},
exportLoading: false,
dataListLoading: false,
dialogVisible: false,
addOrEditTitle: '',
addOrUpdateVisible: false,
tableProps,
tableBtn: [],
showData: [],
tableData: [],
selectedList: [],
fileName: '',
formConfig: [ formConfig: [
{
type: 'select',
label: '工厂',
selectOptions: [],
param: 'factoryId',
onchange: true,
},
{ {
type: 'select', type: 'select',
label: '产线', label: '产线',
selectOptions: [], selectOptions: [],
param: 'line' param: 'lineId',
multiple: true,
}, },
{ {
type: 'datePicker', type: 'datePicker',
label: '时间范围', label: '时间范围',
dateType: 'datetimerange', dateType: 'daterange',
format: 'yyyy-MM-dd HH:mm:ss', format: 'yyyy-MM-dd',
valueFormat: "yyyy-MM-ddTHH:mm:ss", valueFormat: 'timestamp',
rangeSeparator: '-', rangeSeparator: '-',
startPlaceholder: '开始时间', startPlaceholder: '开始时间',
endPlaceholder: '结束时间', endPlaceholder: '结束时间',
param: 'timeVal', param: 'timeVal',
defaultSelect: [], width: 350,
width: 350 },
},
{ {
type: 'button', type: 'button',
btnName: '查询', btnName: '查询',
@@ -148,129 +323,51 @@ export default {
btnName: '导出', btnName: '导出',
name: 'export', name: 'export',
color: 'warning', color: 'warning',
} },
], ],
listQuery: {
lineId: [],
},
activeName: 'now',
tableProps,
tableData: [],
tableData2: [],
tableData3: [],
}; };
}, },
components: {
ButtonNav,
baseTableS,
barChart,
},
created() { created() {
if (this.$route.params.startTime) { this.getPdLineList();
this.formConfig[1].defaultSelect = [this.$route.params.startTime, this.$route.params.endTime]
}
// const time = new Date()
// this.formConfig[1].defaultSelect = [time, time]
this.getDataList()
this.getPdLineList()
}, },
methods: { methods: {
test() {
var target = document.getElementsByClassName("right-aside")[0]
target.style.background = '#FFFFFF'
var that = this
setTimeout(() => {
html2canvas(target).then(function(canvas) {
var contentWidth = canvas.width
var contentHeight = canvas.height
// 一页pdf显示html页面生成的canvas高度
var pageHeight = contentHeight / 592.28 * 841.89
// 未生成pdf的html页面高度
var leftHeight = contentHeight
// 页面偏移
var position = 0
// a4纸的尺寸[595.28,841.89]html页面生成的canvas在pdf中图片的高度
var imgWidth = 595.28
var imgHeight = 592.28 / contentWidth * contentHeight
var pageData = canvas.toDataURL('image/jpeg', 1.0)
console.log('nihc URL', leftHeight, pageHeight)
var pdf = new jsPDF('', 'pt', 'a4')
if (leftHeight < pageHeight) {
pdf.addImage(pageData, 'JPEG', 0, 20, imgWidth, imgHeight)
} else {
while(leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
leftHeight -= pageHeight
position -= 841.89
// 避免空白页
if (leftHeight > 0) {
pdf.addPage()
}
}
}
pdf.save(that.fileName + '产线产量.pdf')
})
}, 300)
},
exportECL() {
let tables = document.querySelector('.el-table').cloneNode(true)
const fix = tables.querySelector('.el-table__fixed')
const fixRight = tables.querySelector('.el-table__fixed-right')
if (fix) {
tables.removeChild(tables.querySelector('.el-table__fixed'))
}
if (fixRight) {
tables.removeChild(tables.querySelector('.el-table__fixed-right'))
}
let exportTable = XLSX.utils.table_to_book(tables)
var exportTableOut = XLSX.write(exportTable, {
bookType: 'xlsx', bookSST: true, type: 'array'
})
// sheetjs.xlsx为导出表格的标题名称
try {
FileSaver.saveAs(new Blob([exportTableOut], {
type: 'application/octet-stream'
}), this.fileName + '产线产量.xlsx')
} catch (e) {
if (typeof console !== 'undefined') console.log(e, exportTableOut)
}
return exportTableOut
},
exportPdf() {
this.test()
setTimeout(() =>{
this.dialogVisible = false
this.showData = this.tableData
}, 600)
},
exportXlsx() {
this.exportECL()
this.dialogVisible = false
this.showData = this.tableData
},
handleClose(done) {
this.$confirm('确认关闭?')
.then(_ => {
done();
})
.catch(_ => {});
},
getPdLineList() { getPdLineList() {
getPdList().then((res) => { getPdList().then((res) => {
this.formConfig[0].selectOptions = res.data || [] this.formConfig[1].selectOptions = res.data || [];
}) });
const params = {
pageSize: 100,
pageNo: 1,
};
getFactoryPage(params).then((res) => {
this.formConfig[0].selectOptions = res.data.list || [];
});
}, },
selectChange(val) {
console.log(val)
this.selectedList = val
},
buttonClick(val) { buttonClick(val) {
switch (val.btnName) { switch (val.btnName) {
case 'search': case 'search':
this.listQuery.pageNo = 1; this.listQuery.factoryId = val.factoryId || undefined;
this.listQuery.pageSize = 10; this.listQuery.lineId = val.lineId || [];
this.listQuery.proLineId = val.line ? val.line : undefined; this.listQuery.startTime = val.timeVal ? val.timeVal[0] : undefined;
this.listQuery.startTime = val.timeVal ? new Date(val.timeVal[0]).getTime() : undefined; this.listQuery.endTime = val.timeVal ? val.timeVal[1] : undefined;
this.listQuery.endTime = val.timeVal ? new Date(val.timeVal[1]).getTime() : undefined; if (this.activeName === 'his') {
if (val.timeVal && val.timeVal.length > 0) { this.getDataList();
this.fileName = val.timeVal[0].slice(0, 10) + '-' + val.timeVal[1].slice(0, 10) + '_' } else {
} this.getDataList2();
this.getDataList(); }
break; break;
case 'export': case 'export':
this.handleExport(); this.handleExport();
@@ -279,33 +376,199 @@ export default {
console.log(val); console.log(val);
} }
}, },
// 获取数据列表 currentMenu(val) {
getDataList() { this.activeName = val === '历史' ? 'his' : 'now';
this.dataListLoading = true; if (this.activeName === 'his') {
this.urlOptions.getDataListURL(this.listQuery).then(response => { this.$refs.searchBarForm.resetForm();
this.tableData = response.data; this.listQuery.factoryId = undefined;
this.listQuery.total = response.data.length; this.listQuery.lineId = [];
this.dataListLoading = false; // 获取当前时间
this.showData = this.tableData const now = new Date();
}); // 获取前一天的同一时间
}, const yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000);
// 每页数 // 设置为00:00:00
sizeChangeHandle(val) { yesterday.setHours(0, 0, 0, 0);
this.listQuery.pageSize = val; // 设置为23:59:59
this.listQuery.pageNo = 1; const end = new Date(yesterday.getTime());
this.getDataList(); end.setHours(23, 59, 59, 59);
}, this.listQuery.startTime = yesterday.getTime();
// 当前页 this.listQuery.endTime = end.getTime();
currentChangeHandle(val) { this.$nextTick(() => {
this.listQuery.pageNo = val; this.$refs.searchBarForm.formInline.timeVal = [
this.getDataList(); yesterday.getTime(),
}, end.getTime(),
handleExport() { ];
if (this.selectedList.length > 0) { });
this.showData = this.selectedList this.getDataList();
} else {
this.getDataList2();
} }
this.dialogVisible = true },
} // 获取数据列表
getDataList() {
if (this.listQuery.startTime) {
this.dataListLoading = true;
this.urlOptions.getDataListURL(this.listQuery).then((response) => {
this.tableData = response.data.map((item, index) => {
item.originalLossNum = item.original?.lossNum;
item.originalLossArea = item.original?.lossArea;
item.edgeLossNum = item.edge?.lossNum;
item.edgeLossArea = item.edge?.lossArea;
item.drillLossNum = item.drill?.lossNum;
item.drillLossArea = item.drill?.lossArea;
item.coatingLossNum = item.coating?.lossNum;
item.coatingLossArea = item.coating?.lossArea;
item.silkLossNum = item.silk?.lossNum;
item.silkLossArea = item.silk?.lossArea;
item.temperingLossNum = item.tempering?.lossNum;
item.temperingLossArea = item.tempering?.lossArea;
item.packingLossNum = item.packing?.lossNum;
item.packingLossArea = item.packing?.lossArea;
return item;
});
this.$nextTick(() => {
if(this.tableData.length>0){
this.$refs.barChart.initChart();
}
});
this.dataListLoading = false;
});
} else {
this.$message.warning('请选择时间范围');
}
},
// 获取数据2列表
getDataList2() {
getPdlAutoReportNewSearchNow().then((response) => {
this.tableData2 = response.data.classData.map((item, index) => {
item.originalLossNum = item.original?.lossNum;
item.originalLossArea = item.original?.lossArea;
item.edgeLossNum = item.edge?.lossNum;
item.edgeLossArea = item.edge?.lossArea;
item.drillLossNum = item.drill?.lossNum;
item.drillLossArea = item.drill?.lossArea;
item.coatingLossNum = item.coating?.lossNum;
item.coatingLossArea = item.coating?.lossArea;
item.silkLossNum = item.silk?.lossNum;
item.silkLossArea = item.silk?.lossArea;
item.temperingLossNum = item.tempering?.lossNum;
item.temperingLossArea = item.tempering?.lossArea;
item.packingLossNum = item.packing?.lossNum;
item.packingLossArea = item.packing?.lossArea;
return item;
});
this.tableData3 = response.data.todayData.map((item, index) => {
item.originalLossNum = item.original?.lossNum;
item.originalLossArea = item.original?.lossArea;
item.edgeLossNum = item.edge?.lossNum;
item.edgeLossArea = item.edge?.lossArea;
item.drillLossNum = item.drill?.lossNum;
item.drillLossArea = item.drill?.lossArea;
item.coatingLossNum = item.coating?.lossNum;
item.coatingLossArea = item.coating?.lossArea;
item.silkLossNum = item.silk?.lossNum;
item.silkLossArea = item.silk?.lossArea;
item.temperingLossNum = item.tempering?.lossNum;
item.temperingLossArea = item.tempering?.lossArea;
item.packingLossNum = item.packing?.lossNum;
item.packingLossArea = item.packing?.lossArea;
return item;
});
});
},
handleSearchBarChanged({ param, value }) {
this.listQuery.lineId = [];
this.$refs.searchBarForm.formInline.lineId = undefined;
getPdList(value).then((res) => {
this.formConfig[1].selectOptions = res.data || [];
});
},
/** 导出按钮操作 */
handleExport() {
let tables = document.querySelector('.el-table').cloneNode(true);
const fix = tables.querySelector('.el-table__fixed');
const fixRight = tables.querySelector('.el-table__fixed-right');
if (fix) {
tables.removeChild(tables.querySelector('.el-table__fixed'));
}
if (fixRight) {
tables.removeChild(tables.querySelector('.el-table__fixed-right'));
}
let exportTable = XLSX.utils.table_to_book(tables);
exportTable.Sheets.Sheet1.A1.v = '序号' //导出表格第一列表头为序号
var exportTableOut = XLSX.write(exportTable, {
bookType: 'xlsx',
bookSST: true,
type: 'array',
});
// sheetjs.xlsx为导出表格的标题名称
try {
FileSaver.saveAs(
new Blob([exportTableOut], {
type: 'application/octet-stream',
}),
'产线统计数据.xlsx'
);
} catch (e) {
if (typeof console !== 'undefined') console.log(e, exportTableOut);
}
return exportTableOut;
},
}, },
}; };
</script> </script>
<style lang="scss">
.energyOverlimitLog {
.el-tabs__nav::after {
content: '';
position: absolute;
left: 0;
bottom: 0;
width: 100%;
height: 2px;
background-color: #e4e7ed;
}
.el-tabs__nav-wrap::after {
width: 0;
}
.el-tabs__item {
padding: 0 10px;
}
.el-tabs__item:hover {
color: rgba(0, 0, 0, 0.85);
}
.el-tabs__item.is-active {
color: rgba(0, 0, 0, 0.85);
}
.el-tabs__item {
color: rgba(0, 0, 0, 0.45);
}
.searchBarBox {
margin-bottom: 0;
}
.blue-block {
float: left;
display: inline-block;
width: 4px;
height: 16px;
background-color: #0b58ff;
border-radius: 1px;
margin-right: 8px;
margin-top: 12px;
}
.tip {
display: inline-block;
font-size: 16px;
margin-right: 8px;
margin-top: 10px;
}
}
</style>

View File

@@ -1,4 +1,4 @@
<!-- <!--
filename: index.vue filename: index.vue
author: liubin author: liubin
date: 2023-08-04 14:44:58 date: 2023-08-04 14:44:58
@@ -16,6 +16,7 @@
v-if="tableData && tableData.length > 0" v-if="tableData && tableData.length > 0"
:table-props="tableProps" :table-props="tableProps"
:table-data="tableData" :table-data="tableData"
:max-height="tableH"
@emitFun="handleEmitFun" @emitFun="handleEmitFun"
/> />
</div> </div>
@@ -24,11 +25,13 @@
<script> <script>
import { getPdlDataOneDay } from '@/api/core/monitoring/data24' import { getPdlDataOneDay } from '@/api/core/monitoring/data24'
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
export default { export default {
name: 'productionLineData24', name: 'productionLineData24',
components: {}, components: {},
props: {}, props: {},
mixins: [tableHeightMixin],
data() { data() {
return { return {
urlOptions: { urlOptions: {
@@ -41,7 +44,7 @@ export default {
}, },
list: [], list: [],
arr: [], arr: [],
spanArr: [], spanArr: [],
timeList: [], timeList: [],
tableData: [], tableData: [],
tableProps: [], tableProps: [],
@@ -66,10 +69,14 @@ export default {
label: times.slice(0, 10) + ' ' + times.slice(11), label: times.slice(0, 10) + ' ' + times.slice(11),
align: 'center', align: 'center',
children: [ children: [
{ prop: times + '_in', label: '投入数量' }, { prop: times + '_in', label: '投入数量',
{ prop: times + '_out', label: '产出数量' }, filter: (val) => (val != null ? val.toFixed(2) : '-'), },
{ prop: times + '_junk', label: '报废数量' }, { prop: times + '_out', label: '产出数量',
{ prop: times + '_area', label: '产出面积' } filter: (val) => (val != null ? val.toFixed(2) : '-'), },
{ prop: times + '_junk', label: '报废数量',
filter: (val) => (val != null ? val.toFixed(2) : '-'), },
{ prop: times + '_area', label: '产出面积',
filter: (val) => (val != null ? val.toFixed(2) : '-'), }
] ]
} }
this.arr.push(subprop) this.arr.push(subprop)
@@ -168,7 +175,7 @@ export default {
// // console.log('recent-24', data); // // console.log('recent-24', data);
// this.initing = true; // this.initing = true;
// this.queryParams.pageSize = this.list.length; // this.queryParams.pageSize = this.list.length;
// setTimeout(() => { // setTimeout(() => {

View File

@@ -0,0 +1,273 @@
<template>
<div class="baseTable">
<el-table
:ref="id"
:data="renderData"
v-bind="$attrs"
:border="cancelBorder ? false : true"
@current-change="currentChange"
@selection-change="handleSelectionChange"
style="width: 100%"
:header-cell-style="{
background: '#F2F4F9',
color: '#606266',
}">
<!-- 多选 -->
<el-table-column
v-if="selectWidth"
type="selection"
:width="selectWidth" />
<!-- 序号 -->
<el-table-column
v-if="page && limit"
prop="_pageIndex"
:width="pageWidth"
align="center"
:fixed="cancelPageFixed ? false : true">
<template slot="header">
<el-popover placement="bottom-start" width="300" trigger="click">
<div
class="setting-box"
style="max-height: 400px; overflow-y: auto">
<el-checkbox
v-for="(item, index) in tableProps"
:key="'cb' + index"
v-model="selectedBox[index]"
:label="item.label" />
</div>
<i slot="reference" class="el-icon-s-tools" />
</el-popover>
</template>
</el-table-column>
<el-table-column
v-for="item in renderTableHeadList"
:key="item.prop"
v-bind="item"
:label="item.label"
:prop="item.prop"
:fixed="item.fixed || false"
:show-overflow-tooltip="item.showOverflowtooltip || false"
:sortable="item.sortable || false">
<template slot="header">
<span>{{ item.label }}</span>
</template>
<!-- 多表头 -->
<template v-if="item.children">
<el-table-column
v-for="sub in item.children"
:prop="sub.prop"
:key="sub.prop"
v-bind="sub"
:label="sub.label">
<template v-if="sub.children">
<el-table-column
v-for="ssub in sub.children"
:prop="ssub.prop"
:key="ssub.prop"
v-bind="ssub"
:label="ssub.label">
<template slot-scope="sscopeInner">
<component
:is="ssub.subcomponent"
v-if="ssub.subcomponent"
:key="sscopeInner.row.id"
:inject-data="{ ...sscopeInner.row, ...ssub }"
@emitData="emitData" />
<span v-else>
{{ sscopeInner.row[ssub.prop] | commonFilter(ssub.filter) }}
</span>
</template>
</el-table-column>
</template>
<template slot-scope="scopeInner">
<component
:is="sub.subcomponent"
v-if="sub.subcomponent"
:key="scopeInner.row.id"
:inject-data="{ ...scopeInner.row, ...sub }"
@emitData="emitData" />
<span v-else>
{{ scopeInner.row[sub.prop] | commonFilter(sub.filter) }}
</span>
</template>
</el-table-column>
</template>
<template slot-scope="scope">
<component
:is="item.subcomponent"
v-if="item.subcomponent"
:key="scope.row.id"
:itemProp="item.prop"
:inject-data="{ ...scope.row, ...item }"
@emitData="emitData" />
<span v-else>
{{ scope.row[item.prop] | commonFilter(item.filter) }}
</span>
</template>
</el-table-column>
<slot name="handleBtn" />
</el-table>
<!-- 表格底部加号 -->
<el-button
v-if="addButtonShow"
class="addButton"
icon="el-icon-plus"
@click="emitButtonClick">
{{ addButtonShow }}
</el-button>
</div>
</template>
<script>
export default {
name: 'BaseTable',
filters: {
commonFilter: (source, filterType = (a) => a) => {
return filterType(source);
},
},
props: {
cancelBorder: {
type: Boolean,
default: false,
},
cancelPageFixed: {
type: Boolean,
default: false,
},
tableData: {
type: Array,
required: true,
default: () => {
return [];
},
},
tableProps: {
type: Array,
default: () => {
return [];
},
},
id: {
type: String,
required: false,
default: '',
},
page: {
type: Number,
required: false,
default: 0,
},
pageWidth: {
type: Number,
required: false,
default: 70,
},
limit: {
type: Number,
required: false,
default: 0,
},
selectWidth: {
type: Number,
required: false,
default: 0,
},
addButtonShow: {
type: String,
required: false,
default: '',
},
},
data() {
return {
selectedBox: new Array(100).fill(true),
};
},
computed: {
renderTableHeadList() {
return this.tableProps.filter((item, index) => {
return this.selectedBox[index];
});
},
renderData() {
return this.tableData.map((item, index) => {
return {
...item,
_pageIndex: (this.page - 1) * this.limit + index + 1,
};
});
},
},
beforeMount() {
this.selectedBox = new Array(100).fill(true);
},
methods: {
currentChange(newVal, oldVal) {
this.$emit('current-change', { newVal, oldVal });
},
handleSelectionChange(val) {
this.$emit('selection-change', val);
},
emitData(val) {
this.$emit('emitFun', val);
},
emitButtonClick() {
this.$emit('emitButtonClick');
},
setCurrent(name, index) {
let _this = this;
let obj = _this.$refs[name].data[index];
_this.$refs[name].setCurrentRow(obj);
},
doLayout(name) {
this.$refs[name].doLayout();
},
},
};
</script>
<style scoped>
.baseTable .show-col-btn {
margin-right: 5px;
line-height: inherit;
cursor: pointer;
}
.baseTable .el-icon-refresh {
cursor: pointer;
}
</style>
<style>
.baseTable .el-table__body tr.current-row > td.el-table__cell {
background-color: #eaf1fc;
}
.baseTable .el-table .el-table__cell {
padding: 0;
height: 35px;
}
.baseTable .addButton {
width: 100%;
height: 35px;
border-top: none;
color: #0b58ff;
border-color: #ebeef5;
border-radius: 0;
}
.baseTable .addButton:hover {
color: #0b58ff;
border-color: #ebeef5;
background-color: #fff;
}
.baseTable .addButton:focus {
border-color: #ebeef5;
background-color: #fff;
}
.el-tooltip__popper.is-dark {
background: rgba(0, 0, 0, 0.6) !important;
}
.el-tooltip__popper .popper__arrow,
.el-tooltip__popper .popper__arrow::after {
border-top-color: rgba(0, 0, 0, 0.4) !important;
}
</style>

View File

@@ -0,0 +1,481 @@
<!--
* @Author: Do not edit
* @Date: 2023-08-29 14:59:29
* @LastEditTime: 2025-03-03 10:38:00
* @LastEditors: zwq
* @Description:
-->
<template>
<div class="app-container">
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@select-changed="handleSearchBarChanged"
@headBtnClick="buttonClick" />
<base-table-s
v-if="showData.length"
class="right-aside"
v-loading="dataListLoading"
:table-props="tableProps"
:page="listQuery.pageNo"
:limit="listQuery.pageSize"
:table-data="showData"></base-table-s>
<div v-else class="no-data-bg"></div>
<pagination
:limit.sync="listQuery.pageSize"
:page.sync="listQuery.pageNo"
:total="listQuery.total"
@pagination="getDataList" />
</div>
</template>
<script>
import { parseTime } from '@/filter/code-filter';
import { getLineAuto, getPdList } from '@/api/core/monitoring/auto';
import { getFactoryPage } from '@/api/core/base/factory';
// import codeFilter from '../../mixins/code-filter'
import * as XLSX from 'xlsx';
import FileSaver from 'file-saver';
import baseTableS from './baseTable.vue';
const tableProps = [
{
prop: 'reportType',
label: '报表类型',
fixed: true
},
{
prop: 'reportDate',
label: '日期',
width: 130,
fixed: true
},
{
prop: 'factoryName',
label: '工厂',
fixed: true
},
{
prop: 'lineName',
label: '产线',
fixed: true
},
{
prop: 'sizes',
label: '规格',
width: 105,
showOverflowtooltip: true,
fixed: true
},
{
prop: 'process',
label: '产品工艺',
fixed: true
},
{
prop: 'inputN',
label: '投入',
align: 'center',
children: [
{
prop: 'inputNum',
label: '投入数量/片',
},
{
prop: 'inputArea',
label: '投入面积/m²',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'outputN',
label: '产出',
align: 'center',
children: [
{
prop: 'outputNum',
label: '产出数量/片',
},
{
prop: 'outputArea',
label: '产出面积/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'lossN',
label: '不良',
align: 'center',
children: [
{
prop: 'lossNum',
label: '不良数量/片',
},
{
prop: 'lossArea',
label: '不良面积/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'lossRatio',
label: '不良率/%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'outputRatio',
label: '投入产出率/%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'processingRatio',
label: '加工成品率/%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'lossD',
label: '不良详情',
align: 'center',
children: [
{
prop: 'original',
label: '原片',
align: 'center',
children: [
{
prop: 'originalLossNum',
label: '原片不良/片',
},
{
prop: 'originalLossArea',
label: '原片不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'edge',
label: '磨边',
align: 'center',
children: [
{
prop: 'edgeLossNum',
label: '磨边不良/片',
},
{
prop: 'edgeLossArea',
label: '磨边不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'drill',
label: '打孔',
align: 'center',
children: [
{
prop: 'drillLossNum',
label: '打孔不良/片',
},
{
prop: 'drillLossArea',
label: '打孔不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'coating',
label: '镀膜',
align: 'center',
children: [
{
prop: 'coatingLossNum',
label: '镀膜不良/片',
},
{
prop: 'coatingLossArea',
label: '镀膜不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'silk',
label: '丝印',
align: 'center',
children: [
{
prop: 'silkLossNum',
label: '丝印不良/片',
},
{
prop: 'silkLossArea',
label: '丝印不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'tempering',
label: '钢化',
align: 'center',
children: [
{
prop: 'temperingLossNum',
label: '钢化不良/片',
},
{
prop: 'temperingLossArea',
label: '钢化不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
{
prop: 'packing',
label: '包装',
align: 'center',
children: [
{
prop: 'packingLossNum',
label: '包装不良/片',
},
{
prop: 'packingLossArea',
label: '包装不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
],
},
];
export default {
components: {
baseTableS,
},
data() {
return {
urlOptions: {
getDataListURL: getLineAuto,
},
listQuery: {
lineId: [],
pageSize: 10,
pageNo: 1,
total: 1,
},
fileName: '',
dataListLoading: false,
tableProps,
tableBtn: [],
showData: [],
tableData: [],
formConfig: [
{
type: 'select',
label: '工厂',
selectOptions: [],
param: 'factoryId',
onchange: true,
},
{
type: 'select',
label: '维度',
selectOptions: [
{
id: 1,
name: '日',
},
{
id: 2,
name: '周',
},
{
id: 3,
name: '月',
},
{
id: 4,
name: '年',
},
],
param: 'reportType',
},
{
type: 'select',
label: '产线',
selectOptions: [],
param: 'lineId',
},
{
type: 'datePicker',
label: '时间范围',
dateType: 'daterange',
format: 'yyyy-MM-dd',
valueFormat: 'timestamp',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeVal',
width: 350,
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary',
},
{
type: 'separate',
},
{
// type: this.$auth.hasPermi('base:factory:export') ? 'button' : '',
type: 'button',
btnName: '导出',
name: 'export',
color: 'warning',
},
],
};
},
created() {
// 获取当前时间
const now = new Date();
// 获取前一天的同一时间
const yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000);
// 设置为00:00:00
yesterday.setHours(0, 0, 0, 0);
// 设置为23:59:59
const end = new Date(yesterday.getTime());
end.setHours(23, 59, 59, 59);
this.listQuery.startTime = yesterday.getTime();
this.listQuery.endTime = end.getTime();
this.$nextTick(() => {
this.$refs.searchBarForm.formInline.timeVal = [
yesterday.getTime(),
end.getTime(),
];
});
this.getDataList();
this.getPdLineList();
},
methods: {
handleExport() {
let tables = document.querySelector('.el-table').cloneNode(true);
const fix = tables.querySelector('.el-table__fixed');
const fixRight = tables.querySelector('.el-table__fixed-right');
if (fix) {
tables.removeChild(tables.querySelector('.el-table__fixed'));
}
if (fixRight) {
tables.removeChild(tables.querySelector('.el-table__fixed-right'));
}
let exportTable = XLSX.utils.table_to_book(tables);
exportTable.Sheets.Sheet1.A1.v = '序号' //导出表格第一列表头为序号
var exportTableOut = XLSX.write(exportTable, {
bookType: 'xlsx',
bookSST: true,
type: 'array',
});
// sheetjs.xlsx为导出表格的标题名称
try {
FileSaver.saveAs(
new Blob([exportTableOut], {
type: 'application/octet-stream',
}),
this.fileName + '产线自动报表.xlsx'
);
} catch (e) {
if (typeof console !== 'undefined') console.log(e, exportTableOut);
}
return exportTableOut;
},
getPdLineList() {
getPdList().then((res) => {
this.formConfig[2].selectOptions = res.data || [];
});
const params = {
pageSize: 100,
pageNo: 1,
};
getFactoryPage(params).then((res) => {
this.formConfig[0].selectOptions = res.data.list || [];
});
},
buttonClick(val) {
switch (val.btnName) {
case 'search':
this.listQuery.pageNo = 1;
this.listQuery.pageSize = 10;
this.listQuery.factoryId = val.factoryId || undefined;
this.listQuery.lineId = val.lineId ? [val.lineId] : [];
this.listQuery.reportType = val.reportType || undefined;
this.listQuery.startTime = val.timeVal ? val.timeVal[0] : undefined;
this.listQuery.endTime = val.timeVal ? val.timeVal[1] : undefined;
this.getDataList();
break;
case 'export':
this.handleExport();
break;
default:
console.log(val);
}
},
// 获取数据列表
getDataList() {
this.dataListLoading = true;
const arr = ['日', '周', '月', '年'];
this.urlOptions.getDataListURL(this.listQuery).then((response) => {
this.tableData = response.data.list.map((item, index) => {
item.reportType = arr[item.reportType - 1];
item.originalLossNum = item.original?.lossNum;
item.originalLossArea = item.original?.lossArea;
item.edgeLossNum = item.edge?.lossNum;
item.edgeLossArea = item.edge?.lossArea;
item.drillLossNum = item.drill?.lossNum;
item.drillLossArea = item.drill?.lossArea;
item.coatingLossNum = item.coating?.lossNum;
item.coatingLossArea = item.coating?.lossArea;
item.silkLossNum = item.silk?.lossNum;
item.silkLossArea = item.silk?.lossArea;
item.temperingLossNum = item.tempering?.lossNum;
item.temperingLossArea = item.tempering?.lossArea;
item.packingLossNum = item.packing?.lossNum;
item.packingLossArea = item.packing?.lossArea;
return item;
});
this.listQuery.total = response.data.total;
this.dataListLoading = false;
this.showData = this.tableData;
});
},
// 每页数
sizeChangeHandle(val) {
this.listQuery.pageSize = val;
this.listQuery.pageNo = 1;
this.getDataList();
},
// 当前页
currentChangeHandle(val) {
this.listQuery.pageNo = val;
this.getDataList();
},
handleSearchBarChanged({ param, value }) {
this.listQuery.lineId = [];
this.$refs.searchBarForm.formInline.lineId = undefined;
getPdList(value).then((res) => {
this.formConfig[2].selectOptions = res.data || [];
});
},
},
};
</script>

View File

@@ -0,0 +1,366 @@
<!--
* @Author: Do not edit
* @Date: 2023-08-29 14:59:29
* @LastEditTime: 2025-02-26 16:42:12
* @LastEditors: zwq
* @Description:
-->
<template>
<div class="app-container">
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@headBtnClick="buttonClick" />
<base-table
v-if="showData.length"
class="right-aside"
v-loading="dataListLoading"
:table-props="tableProps"
:page="listQuery.pageNo"
:limit="listQuery.pageSize"
:table-data="showData"></base-table>
<div v-else class="no-data-bg"></div>
<pagination
:limit.sync="listQuery.pageSize"
:page.sync="listQuery.pageNo"
:total="listQuery.total"
@pagination="getDataList" />
</div>
</template>
<script>
import { parseTime } from '../../mixins/code-filter';
import { getProductAuto, getPdList } from '@/api/core/monitoring/auto';
import { listData } from '@/api/system/dict/data';
import { getFactoryPage } from '@/api/core/base/factory';
// import codeFilter from '../../mixins/code-filter'
import * as XLSX from 'xlsx';
import FileSaver from 'file-saver';
const tableProps1 = [
{
prop: 'processType',
label: '工艺类型',
filter: (val) => (val === 1 ? '面板' : '背板'),
fixed: true
},
{
prop: 'reportType',
label: '报表类型',
fixed: true
},
{
prop: 'reportDate',
label: '日期',
width: 130,
fixed: true
},
{
prop: 'factoryName',
label: '工厂',
fixed: true
},
{
prop: 'process',
label: '产品工艺',
fixed: true
},
{
prop: 'all',
label: '合计',
align: 'center',
children: [
{
prop: 'inputArea',
label: '投入面积/m²',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'outputArea',
label: '产出面积/m²',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'lossArea',
label: '不良面积//m²',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'originalLossArea',
label: '原片不良/m²',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'outputRatio',
label: '投入产出率/%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'processingRatio',
label: '加工成品率/%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
},
];
export default {
data() {
return {
urlOptions: {
getDataListURL: getProductAuto,
},
listQuery: {
pageSize: 10,
pageNo: 1,
total: 1,
},
fileName: '',
dataListLoading: false,
tableProps1,
tableProps: [],
tableBtn: [],
showData: [],
tableData: [],
formConfig: [
{
type: 'select',
label: '工厂',
selectOptions: [],
param: 'factoryId',
onchange: true,
},
{
type: 'select',
label: '维度',
selectOptions: [
{
id: 1,
name: '日',
},
{
id: 2,
name: '周',
},
{
id: 3,
name: '月',
},
{
id: 4,
name: '年',
},
],
param: 'reportType',
},
{
type: 'select',
label: '产品工艺',
selectOptions: [],
param: 'process',
labelField: 'label',
valueField: 'label',
},
{
type: 'datePicker',
label: '时间范围',
dateType: 'daterange',
format: 'yyyy-MM-dd',
valueFormat: 'timestamp',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeVal',
width: 350,
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary',
},
{
type: 'separate',
},
{
// type: this.$auth.hasPermi('base:factory:export') ? 'button' : '',
type: 'button',
btnName: '导出',
name: 'export',
color: 'warning',
},
],
};
},
created() {
// 获取当前时间
const now = new Date();
// 获取前一天的同一时间
const yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000);
// 设置为00:00:00
yesterday.setHours(0, 0, 0, 0);
// 设置为23:59:59
const end = new Date(yesterday.getTime());
end.setHours(23, 59, 59, 59);
this.listQuery.startTime = yesterday.getTime();
this.listQuery.endTime = end.getTime();
this.$nextTick(() => {
this.$refs.searchBarForm.formInline.timeVal = [
yesterday.getTime(),
end.getTime(),
];
});
const queryParams = {
pageNo: 1,
pageSize: 99,
dictType: 'process_type',
};
listData(queryParams).then((response) => {
this.formConfig[2].selectOptions = response.data.list;
});
this.getDataList();
this.getPdLineList();
},
methods: {
handleExport() {
let tables = document.querySelector('.el-table').cloneNode(true);
const fix = tables.querySelector('.el-table__fixed');
const fixRight = tables.querySelector('.el-table__fixed-right');
if (fix) {
tables.removeChild(tables.querySelector('.el-table__fixed'));
}
if (fixRight) {
tables.removeChild(tables.querySelector('.el-table__fixed-right'));
}
let exportTable = XLSX.utils.table_to_book(tables);
exportTable.Sheets.Sheet1.A1.v = '序号' //导出表格第一列表头为序号
var exportTableOut = XLSX.write(exportTable, {
bookType: 'xlsx',
bookSST: true,
type: 'array',
});
// sheetjs.xlsx为导出表格的标题名称
try {
FileSaver.saveAs(
new Blob([exportTableOut], {
type: 'application/octet-stream',
}),
this.fileName + '产品自动报表.xlsx'
);
} catch (e) {
if (typeof console !== 'undefined') console.log(e, exportTableOut);
}
return exportTableOut;
},
getPdLineList() {
const params = {
pageSize: 100,
pageNo: 1,
};
getFactoryPage(params).then((res) => {
this.formConfig[0].selectOptions = res.data.list || [];
});
},
buttonClick(val) {
switch (val.btnName) {
case 'search':
this.listQuery.pageNo = 1;
this.listQuery.pageSize = 10;
this.listQuery.factoryId = val.factoryId || undefined;
this.listQuery.process = val.process || undefined;
this.listQuery.reportType = val.reportType || undefined;
this.listQuery.startTime = val.timeVal ? val.timeVal[0] : undefined;
this.listQuery.endTime = val.timeVal ? val.timeVal[1] : undefined;
this.getDataList();
break;
case 'export':
this.handleExport();
break;
default:
console.log(val);
}
},
// 获取数据列表
getDataList() {
this.dataListLoading = true;
const arr = ['日', '周', '月', '年'];
this.tableProps = [];
this.urlOptions.getDataListURL(this.listQuery).then((response) => {
if (response.data) {
let tableArr = [];
this.tableData = response.data?.list?.map((item, stop) => {
item.reportType = arr[item.reportType - 1];
if (stop === 0) {
item.lineDetList.forEach((prop, index) => {
item['inputArea' + index] = prop.inputArea;
item['outputArea' + index] = prop.outputArea;
item['lossArea' + index] = prop.lossArea;
item['originalLossArea' + index] = prop.originalLossArea;
item['outputRatio' + index] = prop.outputRatio;
item['processingRatio' + index] = prop.processingRatio;
const subprop = {
label: prop.lineName,
align: 'center',
children: [
{
prop: 'inputArea' + index,
label: '投入面积/m²',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'outputArea' + index,
label: '产出面积/m²',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'lossArea' + index,
label: '不良面积/m²',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'originalLossArea' + index,
label: '原片不良/m²',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'outputRatio' + index,
label: '投入产出率/%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'processingRatio' + index,
label: '加工成品率/%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
],
};
tableArr.push(subprop);
});
}
return item;
});
this.tableProps.push(...this.tableProps1);
this.tableProps.splice(5, 0, ...tableArr);
this.listQuery.total = response.data.total;
}
this.listQuery.total = 0;
this.dataListLoading = false;
this.showData = this.tableData||[];
});
},
// 每页数
sizeChangeHandle(val) {
this.listQuery.pageSize = val;
this.listQuery.pageNo = 1;
this.getDataList();
},
// 当前页
currentChangeHandle(val) {
this.listQuery.pageNo = val;
this.getDataList();
},
},
};
</script>

View File

@@ -1,8 +1,8 @@
<!-- <!--
* @Author: Do not edit * @Author: Do not edit
* @Date: 2023-08-29 14:59:29 * @Date: 2023-08-29 14:59:29
* @LastEditTime: 2023-10-16 15:19:04 * @LastEditTime: 2024-12-02 13:44:47
* @LastEditors: DY * @LastEditors: zwq
* @Description: * @Description:
--> -->
<template> <template>
@@ -69,11 +69,13 @@ const tableProps = [
prop: 'reportStartTime', prop: 'reportStartTime',
label: '统计开始时间', label: '统计开始时间',
filter: parseTime, filter: parseTime,
width:160
}, },
{ {
prop: 'reportEndTime', prop: 'reportEndTime',
label: '统计结束时间', label: '统计结束时间',
filter: parseTime, filter: parseTime,
width:160
}, },
{ {
prop: 'lineName', prop: 'lineName',
@@ -93,7 +95,8 @@ const tableProps = [
}, },
{ {
prop: 'outputArea', prop: 'outputArea',
label: '产出面积/㎡' label: '产出面积/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
{ {
prop: 'lossNum', prop: 'lossNum',
@@ -101,11 +104,13 @@ const tableProps = [
}, },
{ {
prop: 'lossArea', prop: 'lossArea',
label: '损耗面积/㎡' label: '损耗面积/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
{ {
prop: 'lossRatio', prop: 'lossRatio',
label: '损耗比例%' label: '损耗比例%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
} }
]; ];
@@ -309,8 +314,8 @@ export default {
this.listQuery.lineId = val.line ? val.line : undefined; this.listQuery.lineId = val.line ? val.line : undefined;
this.listQuery.sectionId = val.section ? val.section : undefined; this.listQuery.sectionId = val.section ? val.section : undefined;
this.listQuery.reportType = val.reportType ? val.reportType : undefined; this.listQuery.reportType = val.reportType ? val.reportType : undefined;
this.listQuery.reportStartTime = val.timeVal ? [new Date(val.timeVal[0]).getTime()] : undefined; this.listQuery.reportStartTime = val.timeVal ? [new Date(val.timeVal[0]).getTime(),new Date(val.timeVal[1]).getTime()] : undefined;
this.listQuery.reportEndTime = val.timeVal ? [new Date(val.timeVal[1]).getTime()] : undefined; //this.listQuery.reportEndTime = val.timeVal ? [new Date(val.timeVal[1]).getTime()] : undefined;
if (val.timeVal && val.timeVal.length > 0) { if (val.timeVal && val.timeVal.length > 0) {
this.fileName = val.timeVal[0].slice(0, 10) + '-' + val.timeVal[1].slice(0, 10) + '_' this.fileName = val.timeVal[0].slice(0, 10) + '-' + val.timeVal[1].slice(0, 10) + '_'
} }

View File

@@ -14,8 +14,7 @@
:limit="listQuery.pageSize" :limit="listQuery.pageSize"
:selectWidth="55" :selectWidth="55"
:table-data="showData" :table-data="showData"
@selection-change="selectChange" @selection-change="selectChange" />
/>
<div v-else class="no-data-bg"></div> <div v-else class="no-data-bg"></div>
<pagination <pagination
:limit.sync="listQuery.pageSize" :limit.sync="listQuery.pageSize"
@@ -28,10 +27,12 @@
width="30%" width="30%"
:before-close="handleClose"> :before-close="handleClose">
<el-button type="primary" @click="exportXlsx">xlsx</el-button> <el-button type="primary" @click="exportXlsx">xlsx</el-button>
<el-button type="success" @click="exportPdf">pdf</el-button> <el-button type="success" @click="exportPdf">pdf</el-button>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false"> </el-button> <el-button @click="dialogVisible = false"> </el-button>
<el-button type="primary" @click="dialogVisible = false"> </el-button> <el-button type="primary" @click="dialogVisible = false">
</el-button>
</span> </span>
</el-dialog> </el-dialog>
</div> </div>
@@ -42,40 +43,43 @@
import { getSectionDataSearch } from '@/api/core/monitoring'; import { getSectionDataSearch } from '@/api/core/monitoring';
import { getProductionLinePage } from '@/api/core/base/productionLine'; import { getProductionLinePage } from '@/api/core/base/productionLine';
import { getWorkshopSectionPage } from '@/api/core/base/workshopSection'; import { getWorkshopSectionPage } from '@/api/core/base/workshopSection';
import * as XLSX from 'xlsx' import { parseTime } from '@/filter/code-filter';
import FileSaver from 'file-saver' import * as XLSX from 'xlsx';
import jsPDF from 'jspdf' import FileSaver from 'file-saver';
import html2canvas from 'html2canvas' import jsPDF from 'jspdf';
import html2canvas from 'html2canvas';
const tableProps = [ const tableProps = [
{ {
prop: 'proLineName', prop: 'proLineName',
label: '产线名称' label: '产线名称',
},
{
prop: 'sectionName',
label: '工段名称',
},
{
prop: 'inputNum',
label: '进片数量/片',
},
{
prop: 'outputNum',
label: '出片数量/片',
},
{
prop: 'lossNum',
label: '损耗数量/片',
},
{
prop: 'lossArea',
label: '损耗面积/m²',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
prop: 'lossRate',
label: '损耗比例/%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
{
prop: 'sectionName',
label: '工段名称'
},
{
prop: 'inputNum',
label: '进片数量/片'
},
{
prop: 'outputNum',
label: '出片数量/片'
},
{
prop: 'lossNum',
label: '损耗数量/片'
},
{
prop: 'lossArea',
label: '损耗面积/m²'
},
{
prop: 'lossRate',
label: '损耗比例/%'
}
]; ];
export default { export default {
@@ -83,29 +87,29 @@ export default {
data() { data() {
return { return {
urlOptions: { urlOptions: {
getDataListURL: getSectionDataSearch, getDataListURL: getSectionDataSearch,
}, },
tableProps, tableProps,
tableData: [], tableData: [],
showData: [], showData: [],
selectedList: [], selectedList: [],
listQuery: { listQuery: {
proLineId:undefined, proLineId: undefined,
sectionId: undefined, sectionId: undefined,
startTime: undefined, startTime: undefined,
endTime: undefined, endTime: undefined,
total: 0 total: 0,
}, },
dataListLoading: false, dataListLoading: false,
dialogVisible: false, dialogVisible: false,
fileName: [], fileName: [],
optionArrUrl: [getProductionLinePage, getWorkshopSectionPage], optionArrUrl: [getProductionLinePage, getWorkshopSectionPage],
formConfig: [ formConfig: [
{ {
type: 'select', type: 'select',
label: '产线', label: '产线',
selectOptions: [], selectOptions: [],
param: 'proLineId', param: 'proLineId',
defaultSelect: '', defaultSelect: '',
filterable: true, filterable: true,
onchange: true, onchange: true,
@@ -114,7 +118,7 @@ export default {
type: 'select', type: 'select',
label: '工段', label: '工段',
selectOptions: [], selectOptions: [],
param: 'sectionId', param: 'sectionId',
defaultSelect: '', defaultSelect: '',
filterable: true, filterable: true,
}, },
@@ -143,15 +147,21 @@ export default {
btnName: '导出', btnName: '导出',
name: 'export', name: 'export',
color: 'warning', color: 'warning',
} },
], ],
}; };
}, },
components: { components: {},
},
created() { created() {
this.getArr(); this.getArr();
// this.getDataList() const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 1);
this.listQuery.startTime = start.getTime();
this.listQuery.endTime = end.getTime();
this.formConfig[2].startPlaceholder = parseTime(start).substr(0, 10);
this.formConfig[2].endPlaceholder = parseTime(end).substr(0, 10);
this.getDataList();
}, },
methods: { methods: {
/** 根据产线获取工段 */ /** 根据产线获取工段 */
@@ -184,92 +194,96 @@ export default {
} }
}, },
test() { test() {
var target = document.getElementsByClassName("right-aside")[0] var target = document.getElementsByClassName('right-aside')[0];
target.style.background = '#FFFFFF' target.style.background = '#FFFFFF';
var that = this var that = this;
setTimeout(() => { setTimeout(() => {
html2canvas(target).then(function(canvas) { html2canvas(target).then(function (canvas) {
var contentWidth = canvas.width var contentWidth = canvas.width;
var contentHeight = canvas.height var contentHeight = canvas.height;
// 一页pdf显示html页面生成的canvas高度 // 一页pdf显示html页面生成的canvas高度
var pageHeight = contentHeight / 592.28 * 841.89 var pageHeight = (contentHeight / 592.28) * 841.89;
// 未生成pdf的html页面高度 // 未生成pdf的html页面高度
var leftHeight = contentHeight var leftHeight = contentHeight;
// 页面偏移 // 页面偏移
var position = 0 var position = 0;
// a4纸的尺寸[595.28,841.89]html页面生成的canvas在pdf中图片的高度 // a4纸的尺寸[595.28,841.89]html页面生成的canvas在pdf中图片的高度
var imgWidth = 595.28 var imgWidth = 595.28;
var imgHeight = 592.28 / contentWidth * contentHeight var imgHeight = (592.28 / contentWidth) * contentHeight;
var pageData = canvas.toDataURL('image/jpeg', 1.0) var pageData = canvas.toDataURL('image/jpeg', 1.0);
console.log('nihc URL', leftHeight, pageHeight) console.log('nihc URL', leftHeight, pageHeight);
var pdf = new jsPDF('', 'pt', 'a4') var pdf = new jsPDF('', 'pt', 'a4');
if (leftHeight < pageHeight) { if (leftHeight < pageHeight) {
pdf.addImage(pageData, 'JPEG', 0, 20, imgWidth, imgHeight) pdf.addImage(pageData, 'JPEG', 0, 20, imgWidth, imgHeight);
} else { } else {
while(leftHeight > 0) { while (leftHeight > 0) {
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight) pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight);
leftHeight -= pageHeight leftHeight -= pageHeight;
position -= 841.89 position -= 841.89;
// 避免空白页 // 避免空白页
if (leftHeight > 0) { if (leftHeight > 0) {
pdf.addPage() pdf.addPage();
}
} }
} }
}
pdf.save(that.fileName[0] + '-' + that.fileName[1] + '_工段统计.pdf') pdf.save(that.fileName[0] + '-' + that.fileName[1] + '_工段统计.pdf');
}) });
}, 300) }, 300);
}, },
exportECL() { exportECL() {
let tables = document.querySelector('.el-table').cloneNode(true) let tables = document.querySelector('.el-table').cloneNode(true);
const fix = tables.querySelector('.el-table__fixed') const fix = tables.querySelector('.el-table__fixed');
const fixRight = tables.querySelector('.el-table__fixed-right') const fixRight = tables.querySelector('.el-table__fixed-right');
if (fix) { if (fix) {
tables.removeChild(tables.querySelector('.el-table__fixed')) tables.removeChild(tables.querySelector('.el-table__fixed'));
} }
if (fixRight) { if (fixRight) {
tables.removeChild(tables.querySelector('.el-table__fixed-right')) tables.removeChild(tables.querySelector('.el-table__fixed-right'));
} }
let exportTable = XLSX.utils.table_to_book(tables) let exportTable = XLSX.utils.table_to_book(tables);
var exportTableOut = XLSX.write(exportTable, { var exportTableOut = XLSX.write(exportTable, {
bookType: 'xlsx', bookSST: true, type: 'array' bookType: 'xlsx',
}) bookSST: true,
// sheetjs.xlsx为导出表格的标题名称 type: 'array',
try { });
FileSaver.saveAs(new Blob([exportTableOut], { // sheetjs.xlsx为导出表格的标题名称
type: 'application/octet-stream' try {
}), this.fileName[0] + '-' + this.fileName[1] + '_工段统计.xlsx') FileSaver.saveAs(
} catch (e) { new Blob([exportTableOut], {
if (typeof console !== 'undefined') console.log(e, exportTableOut) type: 'application/octet-stream',
} }),
return exportTableOut this.fileName[0] + '-' + this.fileName[1] + '_工段统计.xlsx'
}, );
} catch (e) {
if (typeof console !== 'undefined') console.log(e, exportTableOut);
}
return exportTableOut;
},
exportPdf() { exportPdf() {
this.test() this.test();
setTimeout(() =>{ setTimeout(() => {
this.dialogVisible = false this.dialogVisible = false;
this.showData = this.tableData this.showData = this.tableData;
}, 600) }, 600);
}, },
exportXlsx() { exportXlsx() {
this.exportECL() this.exportECL();
this.dialogVisible = false this.dialogVisible = false;
this.showData = this.tableData this.showData = this.tableData;
}, },
handleClose(done) { handleClose(done) {
this.$confirm('确认关闭?') this.$confirm('确认关闭?')
.then(_ => { .then((_) => {
done(); done();
}) })
.catch(_ => {}); .catch((_) => {});
}, },
getArr() { getArr() {
const params = { const params = {
@@ -281,61 +295,63 @@ export default {
this.formConfig[index].selectOptions = response.data.list; this.formConfig[index].selectOptions = response.data.list;
}); });
}); });
}, },
getDataList() { getDataList() {
// this.listQuery.proLineId = '1672847052717821953'; this.urlOptions.getDataListURL(this.listQuery).then((res) => {
// this.listQuery.startTime = '1690626657000' this.tableData = res.data;
// this.listQuery.endTime = '1693564257000' this.listQuery.total = this.tableData.length;
this.urlOptions.getDataListURL(this.listQuery).then(res => { this.dataListLoading = false;
this.tableData = res.data
this.listQuery.total = this.tableData.length;
this.dataListLoading = false;
this.showData = this.tableData; this.showData = this.tableData;
}); });
}, },
// 每页数 // 每页数
sizeChangeHandle(val) { sizeChangeHandle(val) {
this.listQuery.pageSize = val; this.listQuery.pageSize = val;
this.listQuery.pageNo = 1; this.listQuery.pageNo = 1;
this.getDataList(); this.getDataList();
}, },
// 当前页 // 当前页
currentChangeHandle(val) { currentChangeHandle(val) {
this.listQuery.pageNo = val; this.listQuery.pageNo = val;
this.getDataList(); this.getDataList();
}, },
handleExport() { handleExport() {
if (this.selectedList.length > 0) { if (this.selectedList.length > 0) {
this.showData = this.selectedList this.showData = this.selectedList;
} }
this.dialogVisible = true this.dialogVisible = true;
}, },
selectChange(val) { selectChange(val) {
console.log(val) console.log(val);
this.selectedList = val this.selectedList = val;
}, },
buttonClick(val) { buttonClick(val) {
console.log(val) console.log(val);
switch (val.btnName) { switch (val.btnName) {
case 'search': case 'search':
console.log(val.timeSlot); console.log(val.timeSlot);
this.formConfig[2].startPlaceholder = '开始时间';
this.formConfig[2].endPlaceholder = '结束时间';
// this.listQuery.pageNo = 1; // this.listQuery.pageNo = 1;
// this.listQuery.pageSize = 10; // this.listQuery.pageSize = 10;
this.listQuery.proLineId = val.proLineId ? val.proLineId : undefined this.listQuery.proLineId = val.proLineId ? val.proLineId : undefined;
this.listQuery.sectionId = val.sectionId ? val.sectionId : undefined this.listQuery.sectionId = val.sectionId ? val.sectionId : undefined;
this.listQuery.startTime = val.timeSlot ? new Date(val.timeSlot[0]).getTime() : undefined this.listQuery.startTime = val.timeSlot
this.listQuery.endTime = val.timeSlot ? new Date(val.timeSlot[1]).getTime() : undefined ? new Date(val.timeSlot[0]).getTime()
: undefined;
this.listQuery.endTime = val.timeSlot
? new Date(val.timeSlot[1]).getTime()
: undefined;
if (val.timeSlot && val.timeSlot.length > 0) { if (val.timeSlot && val.timeSlot.length > 0) {
this.fileName[0] = val.timeSlot[0].slice(0, 10) this.fileName[0] = val.timeSlot[0].slice(0, 10);
this.fileName[1] = val.timeSlot[1].slice(0, 10) this.fileName[1] = val.timeSlot[1].slice(0, 10);
this.getDataList() this.getDataList();
} else { } else {
this.$message({ this.$message({
message: '请选择时间', message: '请选择时间',
type: 'warning' type: 'warning',
}); });
} }
break; break;
case 'reset': case 'reset':
this.$refs.searchBarForm.resetForm(); this.$refs.searchBarForm.resetForm();
@@ -349,12 +365,12 @@ export default {
case 'export': case 'export':
if (val.timeSlot && val.timeSlot.length > 0) { if (val.timeSlot && val.timeSlot.length > 0) {
this.handleExport(); this.handleExport();
} else { } else {
this.$message({ this.$message({
message: '请选择时间', message: '请选择时间',
type: 'warning' type: 'warning',
}); });
} }
break; break;
default: default:
console.log(val); console.log(val);

View File

@@ -1,4 +1,4 @@
<!-- <!--
filename: pieChart.vue filename: pieChart.vue
author: liubin author: liubin
date: 2023-09-06 15:02:49 date: 2023-09-06 15:02:49
@@ -10,7 +10,7 @@
<div <div
class="pie-chart" class="pie-chart"
ref="pieChart" ref="pieChart"
style="overflow: inherit;" style="overflow: inherit"
:data-eqname="value.equipmentName || 'Default'"></div> :data-eqname="value.equipmentName || 'Default'"></div>
<div class="data-view"> <div class="data-view">
<div class="data-view__item"> <div class="data-view__item">
@@ -64,7 +64,7 @@ export default {
}, },
subtext: '设备', //<========= subtext: '设备', //<=========
subtextStyle: { subtextStyle: {
fontSize: 14, fontSize: 13,
}, },
}, },
color: ['#3da8fd', '#8ef0ab', '#6b5cfd', '#FFC72A', 'transparent'], color: ['#3da8fd', '#8ef0ab', '#6b5cfd', '#FFC72A', 'transparent'],
@@ -194,22 +194,31 @@ export default {
mttr, mttr,
} = item; } = item;
this.config.title.text = lineName; this.config.title.text = lineName;
this.config.title.subtext = equipmentName; // 找到第一个 '-' 的位置
let firstDashIndex = equipmentName.indexOf('-');
// 找到第二个 '-' 的位置
let secondDashIndex = equipmentName.indexOf('-', firstDashIndex + 1);
// 截取第二个 '-' 后面的字符串
let result = equipmentName.substring(secondDashIndex + 1);
this.config.title.subtext = result ? result : '-';
this.config.series[0].data = [ this.config.series[0].data = [
{ name: '工作时长', value: workTime }, { name: '工作时长', value: workTime ? workTime.toFixed(2) : '0.00' },
{ name: '停机时长', value: stopTime }, { name: '停机时长', value: stopTime ? stopTime.toFixed(2) : '0.00' },
{ name: '故障时长', value: downTime }, { name: '故障时长', value: downTime ? downTime.toFixed(2) : '0.00' },
]; ];
this.config.series[1].data = [ this.config.series[1].data = [
{ name: '速度开动率', value: peEfficiency }, {
name: '速度开动率',
value: peEfficiency ? peEfficiency.toFixed(2) : '0.00',
},
{ name: '', value: Math.ceil(peEfficiency) - peEfficiency }, { name: '', value: Math.ceil(peEfficiency) - peEfficiency },
]; ];
//
this.textData = { this.textData = {
workTime: +workTime.toFixed(2), workTime: workTime ? workTime.toFixed(2) : '0.00',
stopTime: +stopTime.toFixed(2), stopTime: stopTime ? stopTime.toFixed(2) : '0.00',
downTime: +downTime.toFixed(2), downTime: downTime ? downTime.toFixed(2) : '0.00',
peEfficiency: +peEfficiency.toFixed(2), peEfficiency: peEfficiency ? peEfficiency.toFixed(2) : '0.00',
}; };
}, },
}, },

View File

@@ -1,4 +1,4 @@
<!-- <!--
filename: index.vue filename: index.vue
author: liubin author: liubin
date: 2023-09-04 09:34:52 date: 2023-09-04 09:34:52
@@ -25,8 +25,9 @@
class="base-table__margin" class="base-table__margin"
:table-props="tableProps" :table-props="tableProps"
:page="1" :page="1"
:limit="10" :limit="999"
:table-data="list" :table-data="list"
:max-height="tableH"
@emitFun="handleEmitFun"></base-table> @emitFun="handleEmitFun"></base-table>
</el-tab-pane> </el-tab-pane>
<el-tab-pane <el-tab-pane
@@ -88,11 +89,13 @@
<script> <script>
// import moment from 'moment'; // import moment from 'moment';
import basicPageMixin from '@/mixins/lb/basicPageMixin'; import basicPageMixin from '@/mixins/lb/basicPageMixin';
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
import PieChart from './components/pieChart.vue'; import PieChart from './components/pieChart.vue';
import { parseTime } from '@/filter/code-filter';
export default { export default {
name: 'EfficiencyAnalysis', name: 'EfficiencyAnalysis',
mixins: [basicPageMixin], mixins: [basicPageMixin, tableHeightMixin],
components: { PieChart }, components: { PieChart },
props: {}, props: {},
data() { data() {
@@ -118,8 +121,18 @@ export default {
tableProps: [ tableProps: [
{ prop: 'factoryName', label: '工厂' }, { prop: 'factoryName', label: '工厂' },
{ prop: 'lineName', label: '产线' }, { prop: 'lineName', label: '产线' },
{ prop: 'sectionName', label: '工段' }, {
{ prop: 'equipmentName', label: '设备' }, prop: 'sectionName',
width: 120,
showOverflowtooltip: true,
label: '工段',
},
{
prop: 'equipmentName',
width: 150,
showOverflowtooltip: true,
label: '设备',
},
{ {
label: '有效时间', label: '有效时间',
children: [ children: [
@@ -127,12 +140,13 @@ export default {
width: 128, width: 128,
prop: 'workTime', prop: 'workTime',
label: '工作时长[h]', label: '工作时长[h]',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
{ {
width: 128, width: 128,
prop: 'workRate', prop: 'workRate',
label: '百分比[%]', label: '百分比[%]',
filter: (val) => (val != null ? +val.toFixed(3) : '-'), filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
], ],
}, },
@@ -143,8 +157,14 @@ export default {
width: 128, width: 128,
prop: 'stopTime', prop: 'stopTime',
label: '停机时长[h]', label: '停机时长[h]',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
width: 128,
prop: 'stopRate',
label: '百分比[%]',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
{ width: 128, prop: 'stopRate', label: '百分比[%]' },
], ],
}, },
{ {
@@ -154,14 +174,19 @@ export default {
width: 128, width: 128,
prop: 'downTime', prop: 'downTime',
label: '故障时长[h]', label: '故障时长[h]',
filter: (val) => (val != null ? +val.toFixed(3) : '-'), filter: (val) => (val != null ? val.toFixed(2) : '-'),
},
{
width: 128,
prop: 'downRate',
label: '百分比[%]',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
{ width: 128, prop: 'downRate', label: '百分比[%]' },
{ {
width: 128, width: 128,
prop: 'timeEfficiency', prop: 'timeEfficiency',
label: '时间开动率', label: '时间开动率',
filter: (val) => (val != null ? +val.toFixed(3) : '-'), filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
], ],
}, },
@@ -172,29 +197,31 @@ export default {
width: 128, width: 128,
prop: 'realProcSpeed', prop: 'realProcSpeed',
label: '实际加工速度', label: '实际加工速度',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
{ {
width: 128, width: 128,
prop: 'designProcSpeed', prop: 'designProcSpeed',
label: '理论加工速度', label: '理论加工速度',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
{ {
width: 128, width: 128,
prop: 'peEfficiency', prop: 'peEfficiency',
label: '速度开动率', label: '速度开动率',
filter: (val) => (val != null ? +val.toFixed(3) : '-'), filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
], ],
}, },
{ // {
prop: 'oee', // prop: 'oee',
label: 'OEE', // label: 'OEE',
filter: (val) => (val != null ? +val.toFixed(3) : '-'), // filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, // },
{ {
prop: 'teep', prop: 'teep',
label: 'TEEP', label: '设备生产能效比例',
filter: (val) => (val != null ? +val.toFixed(3) : '-'), filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
// { // {
// _action: 'view-trend', // _action: 'view-trend',
@@ -324,6 +351,20 @@ export default {
}; };
}, },
created() { created() {
const end = new Date();
const start = new Date();
start.setTime(start.getTime() - 3600 * 1000 * 24 * 1);
this.queryParams.recordTime[0] =
parseTime(start).substr(0, 10) + ' 00:00:00';
this.queryParams.recordTime[1] = parseTime(end).substr(0, 10) + ' 00:00:00';
this.$nextTick(() => {
this.searchBarFormConfig[2].extraOptions[0].startPlaceholder = parseTime(
start
).substr(0, 10);
this.searchBarFormConfig[2].extraOptions[0].endPlaceholder = parseTime(
end
).substr(0, 10);
});
this.getFactory(); this.getFactory();
this.getLine(); this.getLine();
this.getList(); this.getList();
@@ -374,6 +415,7 @@ export default {
/** 查询列表 */ /** 查询列表 */
async getList() { async getList() {
this.loading = true; this.loading = true;
this.list = [];
const { code, data } = await this.$axios({ const { code, data } = await this.$axios({
url: '/analysis/equipment-analysis/efficiency', url: '/analysis/equipment-analysis/efficiency',
method: 'get', method: 'get',
@@ -385,7 +427,6 @@ export default {
}, },
handleSearchBarBtnClick({ btnName, ...payload }) { handleSearchBarBtnClick({ btnName, ...payload }) {
console.log('handleSearchBarBtnClick', btnName, payload);
if (btnName == 'visualization') { if (btnName == 'visualization') {
// 可视化 // 可视化
this.visualizationOpen = true; this.visualizationOpen = true;
@@ -395,12 +436,26 @@ export default {
this.queryParams.factoryId = payload.factoryId || null; this.queryParams.factoryId = payload.factoryId || null;
this.queryParams.lineId = payload.lineId || null; this.queryParams.lineId = payload.lineId || null;
if (0 == payload.dateFilterType) { if (0 == payload.dateFilterType) {
this.queryParams.recordTime = payload.timerange; if (payload.timerange) {
this.searchBarFormConfig[2].extraOptions[0].startPlaceholder =
'开始时间';
this.searchBarFormConfig[2].extraOptions[0].endPlaceholder =
'结束时间';
this.queryParams.recordTime = payload.timerange;
}
} else if (1 == payload.dateFilterType) { } else if (1 == payload.dateFilterType) {
this.queryParams.recordTime = [ this.searchBarFormConfig[2].extraOptions[0].startPlaceholder =
`${payload.timeday} 00:00:00`, '开始时间';
`${payload.timeday} 23:59:59`, this.searchBarFormConfig[2].extraOptions[0].endPlaceholder =
]; '结束时间';
if (payload.timeday) {
this.queryParams.recordTime = [
`${payload.timeday} 00:00:00`,
`${payload.timeday} 23:59:59`,
];
} else {
this.queryParams.recordTime = null;
}
} }
} else { } else {
this.queryParams.recordTime = null; this.queryParams.recordTime = null;

View File

@@ -1,4 +1,4 @@
<!-- <!--
filename: index.vue filename: index.vue
author: liubin author: liubin
date: 2023-09-04 09:34:52 date: 2023-09-04 09:34:52
@@ -19,6 +19,7 @@
:page="queryParams.pageNo" :page="queryParams.pageNo"
:limit="queryParams.pageSize" :limit="queryParams.pageSize"
:table-data="list" :table-data="list"
:max-height="tableH"
@emitFun="handleEmitFun"> @emitFun="handleEmitFun">
<!-- <method-btn <!-- <method-btn
v-if="tableBtn.length" v-if="tableBtn.length"
@@ -41,10 +42,11 @@
<script> <script>
import moment from 'moment'; import moment from 'moment';
import basicPageMixin from '@/mixins/lb/basicPageMixin'; import basicPageMixin from '@/mixins/lb/basicPageMixin';
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
export default { export default {
name: 'ExceptionAnalysis', name: 'ExceptionAnalysis',
mixins: [basicPageMixin], mixins: [basicPageMixin, tableHeightMixin],
components: {}, components: {},
props: {}, props: {},
data() { data() {
@@ -82,14 +84,18 @@ export default {
width: 240, width: 240,
prop: 'mtbf', prop: 'mtbf',
label: '平均故障间隔时间[MTBF](h)', label: '平均故障间隔时间[MTBF](h)',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
{ {
width: 240, width: 240,
prop: 'mttr', prop: 'mttr',
label: '平均维修时间[MTTR](h)', label: '平均维修时间[MTTR](h)',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
{ width: 128, prop: 'workTime', label: '工作时长(h)' }, { width: 128, prop: 'workTime', label: '工作时长(h)',
{ width: 128, prop: 'downTime', label: '故障时长(h)' }, filter: (val) => (val != null ? val.toFixed(2) : '-'), },
{ width: 128, prop: 'downTime', label: '故障时长(h)',
filter: (val) => (val != null ? val.toFixed(2) : '-'), },
{ prop: 'downCount', label: '故障次数' }, { prop: 'downCount', label: '故障次数' },
], ],
searchBarFormConfig: [ searchBarFormConfig: [

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,8 @@
<!-- <!--
filename: lineChart.vue filename: lineChart.vue
author: liubin author: liubin
date: 2023-09-04 13:45:00 date: 2023-09-04 13:45:00
description: description:
--> -->
<template> <template>
@@ -11,6 +11,7 @@
<script> <script>
import * as echarts from 'echarts'; import * as echarts from 'echarts';
import edata from './data';
export default { export default {
name: 'LineChart', name: 'LineChart',
@@ -43,7 +44,7 @@ export default {
eq.okQuantity, eq.okQuantity,
eq.nokQuantity, eq.nokQuantity,
eq.totalQuantity, eq.totalQuantity,
eq.passRate?.toFixed(4), typeof eq.passRate === "number" ? eq.passRate.toFixed(4) : "0.0000"
]); ]);
}); });
return { return {

View File

@@ -1,4 +1,4 @@
<!-- <!--
filename: index.vue filename: index.vue
author: liubin author: liubin
date: 2023-09-04 09:34:52 date: 2023-09-04 09:34:52
@@ -26,6 +26,7 @@
:page="queryParams.pageNo" :page="queryParams.pageNo"
:limit="queryParams.pageSize" :limit="queryParams.pageSize"
:table-data="list" :table-data="list"
:max-height="tableH"
@emitFun="handleEmitFun"></base-table> @emitFun="handleEmitFun"></base-table>
</el-tab-pane> </el-tab-pane>
<el-tab-pane :label="'\u3000柱状图\u3000'" name="graph"> <el-tab-pane :label="'\u3000柱状图\u3000'" name="graph">
@@ -47,10 +48,13 @@
<script> <script>
import moment from 'moment'; import moment from 'moment';
import LineChart from './components/lineChart.vue'; import LineChart from './components/lineChart.vue';
import { parseTime } from '@/filter/code-filter';
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
export default { export default {
name: 'QualityAnalysis', name: 'QualityAnalysis',
components: { LineChart }, components: { LineChart },
mixins: [tableHeightMixin],
props: {}, props: {},
data() { data() {
const now = new Date(); const now = new Date();
@@ -92,24 +96,6 @@ export default {
endPlaceholder: '结束日期', endPlaceholder: '结束日期',
defaultTime: ['00:00:00', '23:59:59'], defaultTime: ['00:00:00', '23:59:59'],
param: 'recordTime', param: 'recordTime',
defaultSelect: [
new Date(y, m, d)
.toLocaleString()
.split('/')
.map((item, index) => {
if (index == 1 || index == 2) return item.padStart(2, '0');
return item;
})
.join('-'),
new Date(y, m, d, 23, 59, 59)
.toLocaleString()
.split('/')
.map((item, index) => {
if (index == 1 || index == 2) return item.padStart(2, '0');
return item;
})
.join('-'),
],
}, },
{ {
type: 'button', type: 'button',
@@ -156,22 +142,23 @@ export default {
{ {
// width: 160, // width: 160,
prop: 'inQuantity', prop: 'inQuantity',
label: '进片数量', label: '进片数量[片]',
}, },
{ {
// width: 160, // width: 160,
prop: 'outQuantity', prop: 'outQuantity',
label: '出片数量', label: '出片数量[片]',
}, },
{ {
// width: 160, // width: 160,
prop: 'nokQuantity', prop: 'nokQuantity',
label: '破损/不合格数', label: '破损/不合格数[片]',
}, },
{ {
// width: 160, // width: 160,
prop: 'passRate', prop: 'passRate',
label: '合格率', label: '合格率',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
}, },
], ],
lineChartConfig: { lineChartConfig: {
@@ -248,11 +235,23 @@ export default {
}, },
computed: {}, computed: {},
created() { created() {
const end = new Date();
const start = new Date();
this.queryParams.recordTime = [
parseTime(start).substr(0, 10) + ' 00:00:00',
parseTime(end).substr(0, 10) + ' 23:59:59',
];
this.searchBarFormConfig[2].startPlaceholder = parseTime(start).substr(
0,
10
);
this.searchBarFormConfig[2].endPlaceholder = parseTime(end).substr(0, 10);
this.fillLineOptions(); this.fillLineOptions();
this.fillProductOptions(); this.fillProductOptions();
this.getList();
}, },
mounted() { mounted() {
this.$refs['search-bar'].headBtnClick('search'); //this.$refs['search-bar'].headBtnClick('search');
}, },
methods: { methods: {
handleTabClick(tab, event) { handleTabClick(tab, event) {
@@ -316,6 +315,8 @@ export default {
// debugger; // debugger;
switch (btn.btnName) { switch (btn.btnName) {
case 'search': case 'search':
this.searchBarFormConfig[2].startPlaceholder = '开始时间';
this.searchBarFormConfig[2].endPlaceholder = '结束时间';
this.queryParams.lineId = btn.lineId; this.queryParams.lineId = btn.lineId;
this.queryParams.productId = btn.productId; this.queryParams.productId = btn.productId;
this.queryParams.recordTime = btn.recordTime this.queryParams.recordTime = btn.recordTime

View File

@@ -1,8 +1,15 @@
<!-- <!--
* @Author: zwq
* @Date: 2024-10-29 09:47:40
* @LastEditors: zwq
* @LastEditTime: 2024-11-26 14:41:52
* @Description:
-->
<!--
filename: lineChart.vue filename: lineChart.vue
author: liubin author: liubin
date: 2023-09-04 13:45:00 date: 2023-09-04 13:45:00
description: description:
--> -->
<template> <template>
@@ -32,6 +39,12 @@ export default {
mounted() { mounted() {
this.init(); this.init();
}, },
activated() {
// 由于给echart添加了resize事件, 在组件激活时需要重新resize绘画一次, 否则出现空白bug
if (this.chart) {
this.echart.resize();
}
},
beforeDestroy() { beforeDestroy() {
if (this.chart) { if (this.chart) {
this.chart.dispose(); this.chart.dispose();
@@ -43,7 +56,10 @@ export default {
this.setOption(this.config); this.setOption(this.config);
}, },
setOption(option) { setOption(option) {
if (this.chart) this.chart.setOption(option); if (this.chart) this.chart.setOption(option,true);
window.addEventListener("resize", () => {
this.chart.resize();
});
}, },
}, },
}; };

View File

@@ -144,28 +144,18 @@ export default {
eqList: [], eqList: [],
graphList: [], graphList: [],
templateConfig: { templateConfig: {
color: [
'#283D68',
'#FFB61F',
'#4481FF',
'#5AD8A6',
'#E97466',
'#ccc', //<=== 需按情况更新
'#ccc',
'#ccc',
'#ccc',
'#ccc',
],
grid: { grid: {
top: 48, top: 48,
left: 48, left: 48,
right: 24, right: 90,
bottom: 24, bottom: 24,
}, },
legend: { legend: {
top: 0, type: 'scroll',
right: 12, orient: 'vertical',
padding: 6, right: 10,
top: 20,
bottom: 20,
itemWidth: 16, itemWidth: 16,
itemHeight: 8, itemHeight: 8,
itemGap: 20, itemGap: 20,
@@ -495,6 +485,7 @@ export default {
return; return;
} }
this.graphList.push(...newEqlist); this.graphList.push(...newEqlist);
this.templateConfig.series = [];
newEqlist.forEach(this.setSeries); newEqlist.forEach(this.setSeries);
} }
this.open = false; this.open = false;

View File

@@ -86,7 +86,7 @@ export default class GanttGraph {
<span class="eq-name" style="margin-left: 4px;">${params.seriesName}</span> <span class="eq-name" style="margin-left: 4px;">${params.seriesName}</span>
</div> </div>
<span class="run-status" style="margin-left: 8px; opacity: 0.6">${params.name}</span> <span class="run-status" style="margin-left: 8px; opacity: 0.6">${params.name}</span>
</div> </div>
` `
} }
} }
@@ -112,7 +112,7 @@ export default class GanttGraph {
// top: 12 + 128 * this.gridIndex, // top: 12 + 128 * this.gridIndex,
top: 12 + 104 * this.gridIndex, top: 12 + 104 * this.gridIndex,
right: 48, right: 48,
left: 88, left: 100,
height: 56 height: 56
} }
} }
@@ -175,7 +175,7 @@ export default class GanttGraph {
nameGap: 14, nameGap: 14,
nameRotate: 0, nameRotate: 0,
nameTextStyle: { nameTextStyle: {
fontSize: 16, fontSize: 12,
color: '#000A' color: '#000A'
}, },
axisLine: { axisLine: {
@@ -325,4 +325,4 @@ export default class GanttGraph {
console.log(JSON.stringify(this.option, null, 2)); console.log(JSON.stringify(this.option, null, 2));
} }
} }

View File

@@ -0,0 +1,302 @@
import * as echarts from 'echarts'
function getStartTime(timestamp) {
return new Date(new Date(timestamp).toLocaleDateString()).getTime();
}
function renderItem(params, api) {
var categoryIndex = api.value(0);
var start = api.coord([api.value(1), categoryIndex]);
var end = api.coord([api.value(2), categoryIndex]);
var height = api.size([0, 1])[1] * 0.5;
var rectShape = echarts.graphic.clipRectByRect(
{
x: start[0],
y: start[1] - height / 2,
width: end[0] - start[0],
height: height,
},
{
x: params.coordSys.x,
y: params.coordSys.y - 16,
width: params.coordSys.width,
height: params.coordSys.height,
}
);
return (
rectShape && {
type: 'rect',
transition: ['shape'],
shape: rectShape,
style: api.style(),
}
);
}
// unused
function getXaxisRange(startTime) {
return Array(24)
.fill(startTime)
.map((item, index) => {
return new Date(item + index * 3600 * 1000)
.toLocaleTimeString()
.split(':')
.slice(0, 2)
.join(':');
});
}
function getTodayStart(today) {
const [y, m, d] = [
today.getFullYear(),
today.getMonth(),
today.getDate(),
];
// debugger;
return new Date(y, m, d).getTime();
}
/** 颜色配置 */
const types = [
{ name: '运行', color: '#288AFF' },
{ name: '计划停机', color: '#FFDC94' },
{ name: '故障', color: '#FC9C91' },
{ name: '空白', color: '#F2F4F9' },
];
export default class GanttGraph {
// tooltip - 基本是固定的
tooltip = {
trigger: 'item',
axisPointer: {
type: 'none',
},
formatter: (params) => {
// debugger;
return `
<div style="display: flex; flex-direction: column;">
<span>${new Date(params.value[1]).toLocaleTimeString()} ~ ${new Date(params.value[2]).toLocaleTimeString()}</span>
<div style="display: flex; align-items: center; justify-content: space-between;">
<div style="display: flex; align-items: center;">
<span class="icon" style="width: 8px; height: 8px; border-radius: 2px; background: ${params.color}"></span>
<span class="eq-name" style="margin-left: 4px;">${params.data.showName}</span>
</div>
<span class="run-status" style="margin-left: 8px; opacity: 0.6">${params.name}</span>
</div>
`
}
}
grid = []
xAxis = []
yAxis = []
series = []
constructor(el, startTime) {
this.el = el;
this.startTime = new Date(startTime);
// this.startTime = new Date(new Date('2023/10/8').toLocaleDateString());
// console.log('<> Gantt Created', this.startTime);
}
// 构造一个新的 grid
makeGrid() {
return {
top: 0,
right: 20,
left: 100,
bottom: 50,
}
}
// 构造一个 xAxis
makeXaxis() {
return [
{
axisTick: {
alignWithLabel: true,
inside: true,
},
type: 'time',
min: getTodayStart(this.startTime),
max: getStartTime(this.startTime.getTime() + 3600 * 24 * 1000),
splitNumber: 10,
axisLabel: {
margin: 12,
formatter: function (val) {
return new Date(val)
.toLocaleTimeString()
.split(':')
.slice(0, 2)
.join(':');
},
},
axisLine: {
lineStyle: {
color: '#0005',
},
},
boundaryGap: false,
// data: getXaxisRange(getTodayStart(new Date())),
},
]
}
// 构造一个 yAxis
makeYaxis(equipmentName) {
return [
// 主y轴
{
data: equipmentName,
}
]
}
// 构造一个 series
makeSeries(xdata) {
const bgStartTime = this.startTime.getTime();
const bgEndTime = bgStartTime + 3600 * 24 * 1000;
return [
{
type: 'custom',
renderItem: renderItem,
itemStyle: {
opacity: 0.8,
},
encode: {
x: [1, 2],
y: 0,
},
data: xdata,
},
]
}
init(data) {
if (!this.el) throw new Error('没有可供echarts初始化的容器')
if (typeof this.el == 'string') {
this.el = document.querySelector(this.el);
}
this.chart = echarts.init(this.el);
this.handleProps(data);
setTimeout(() => {
// debugger;
this.chart.setOption(this.option);
}, 200);
}
update(data) {
this.clear();
this.init(data);
}
resize() {
this.chart.resize();
}
get option() {
return {
tooltip: this.tooltip,
grid: this.grid,
xAxis: this.xAxis,
yAxis: this.yAxis,
series: this.series,
dataZoom: [
{
type: 'slider',
xAxisIndex: 0,
filterMode: 'weakFilter',
height: 20,
bottom: 0,
start: 0,
end: 80,
handleIcon:
'path://M10.7,11.9H9.3c-4.9,0.3-8.8,4.4-8.8,9.4c0,5,3.9,9.1,8.8,9.4h1.3c4.9-0.3,8.8-4.4,8.8-9.4C19.5,16.3,15.6,12.2,10.7,11.9z M13.3,24.4H6.7V23h6.6V24.4z M13.3,19.6H6.7v-1.4h6.6V19.6z',
handleSize: '80%',
showDetail: false
},
{
type: 'inside',
id: 'insideX',
xAxisIndex: 0,
filterMode: 'weakFilter',
start: 0,
end: 80,
zoomOnMouseWheel: true,
moveOnMouseMove: true
},
{
type: 'slider',
yAxisIndex: 0,
zoomLock: true,
width: 10,
right: 10,
top: 70,
bottom: 20,
start: 0,
end: 100,
handleSize: 0,
showDetail: false
},
{
type: 'inside',
id: 'insideY',
yAxisIndex: 0,
start: 0,
end: 100,
zoomOnMouseWheel: true,
moveOnMouseMove: true,
moveOnMouseWheel: true
}
],
}
}
// 每次 graphList 刷新都会重新渲染整个所有图表
// 可以改进的地方:添加一个 handleAdd() 方法,一次添加一个新的
handleProps(props) {
// props 是父组件的 graphList
console.log('props: ', props);
let ylist = []
let xdata = []
props.forEach((eqArr, index) => {
ylist.push(eqArr.key)
eqArr.forEach(item => {
xdata.push({
name: ['运行', '计划停机', '故障'][item.status],
showName: eqArr.key,
value: [index, item.startTime, item.startTime + item.duration * 60 * 1000, 0],
itemStyle: {
color: types[item.status].color,
}
}
)
})
});
this.grid.push(this.makeGrid());
this.xAxis.push(...this.makeXaxis());
this.yAxis.push(...this.makeYaxis(ylist));
this.series.push(...this.makeSeries(xdata))
}
// handleAdd
handleAdd() { }
clear() {
this.grid = [];
this.xAxis = [];
this.yAxis = [];
this.series = [];
this.chart.dispose();
}
// print option
print() {
console.log(JSON.stringify(this.option, null, 2));
}
}

View File

@@ -0,0 +1,529 @@
<!--
filename: index.vue
author: liubin
date: 2023-09-04 09:34:52
description: 设备状态时序图
-->
<template>
<div class="status-timegraph-container" style="background: #f2f4f9; flex: 1; display: flex; flex-direction: column">
<el-row class="" style="
margin-bottom: 12px;
background: #fff;
padding: 16px 16px 0;
border-radius: 8px;
">
<div class="blue-title">生产节拍时序图</div>
<SearchBar :formConfigs="searchBarFormConfig" ref="search-bar" :remove-blue="true"
@select-changed="handleSearchBarSelectChange" @headBtnClick="handleSearchBarBtnClick" />
</el-row>
<el-row class="" style="
height: 1px;
flex: 1;
margin-bottom: 12px;
background: #fff;
padding: 16px 16px 32px;
border-radius: 8px;
display: flex;
flex-direction: column;
">
<el-row :gutter="20">
<el-col :span="6">
<div class="blue-title">设备状态时序图</div>
</el-col>
<el-col :span="18" class="legend-row">
<div class="legend">
<div class="icon running"></div>
<div>运行中</div>
</div>
<div class="legend">
<div class="icon fault"></div>
<div>故障</div>
</div>
<div class="legend">
<div class="icon stop"></div>
<div>计划停机</div>
</div>
</el-col>
</el-row>
<div class="main-area" style="flex: 1; display: flex; flex-direction: column;">
<div class="graphs" v-show="graphList.length" id="status-chart" style="height: 1px; flex: 1;"></div>
<h2 v-if="!graphList || graphList.length == 0" class="no-data-bg"></h2>
</div>
</el-row>
<!-- 对话框(添加 / 修改) -->
<base-dialog dialogTitle="添加设备" :dialogVisible="open" width="500px" @close="open = false" @cancel="open = false"
@confirm="submitForm">
<el-select v-if="open" style="width: 100%" v-model="queryParams.equipmentId" placeholder="请选择一个设备">
<el-option v-for="eq in eqList" :key="eq.id" :value="eq.id" :label="eq.name"></el-option>
</el-select>
</base-dialog>
</div>
</template>
<script>
import Gantt from './gantt';
export default {
name: 'SGStatus',
components: {},
props: {},
data() {
return {
chart: null,
searchBarFormConfig: [
{
type: 'select',
label: '产线',
placeholder: '请选择产线',
selectOptions: [],
param: 'lineId',
onchange: true,
},
{
type: 'select',
label: '工段',
placeholder: '请选择工段',
selectOptions: [],
param: 'sectionId',
},
// 时间段
{
type: 'datePicker',
label: '时间段',
dateType: 'date',
format: 'yyyy-MM-dd',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
rangeSeparator: '-',
placeholder: '选择日期',
param: 'recordTime',
required: true,
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary',
},
{
type: 'separate',
},
{
type: 'button',
btnName: '添加对比',
name: 'compare',
color: 'primary',
plain: true,
},
],
queryParams: {
lineId: null,
sectionId: null,
equipmentId: null,
recordTime: null,
},
graphList: [],
existingEquipments: [],
open: false,
eqList: [],
startTime: null,
gantt: null
// demo: [
// [
// {
// equipmentName: '下片机',
// duration: 30,
// relativeDuration: 0.6,
// status: 0,
// startPos: 0,
// startTime: 1691568181000,
// },
// {
// equipmentName: '下片机',
// duration: 20,
// relativeDuration: 0.4,
// status: 2,
// startPos: 30,
// startTime: 1691569981000
// },
// ],
// ],
};
},
computed: {},
created() {
this.initProductline();
this.initWorksection();
this.initEquipment();
// this.getList();
},
mounted() { },
watch: {
graphList: {
handler(val) {
if (val && val.length) {
this.$nextTick(() => {
if (!this.gantt) {
this.gantt = new Gantt('#status-chart', this.startTime);
this.gantt.init(val);
return;
}
this.gantt.update(val);
});
}
return;
},
deep: true,
immediate: true,
},
},
methods: {
findMin() {
let min = 0;
this.graphList.forEach((arr) => {
arr.forEach((item) => {
if (min < item.startTime) min = item.startTime;
});
});
return min;
},
/** 重置查询条件 */
initQuery() {
this.queryParams.lineId = null;
this.queryParams.equipmentId = null;
this.queryParams.sectionId = null;
this.queryParams.recordTime = null;
},
/** 对象到数组的转换 */
objectToArray(obj) {
return Object.keys(obj).map((key) => {
obj[key].sort((a, b) => a.startTime - b.startTime);
obj[key].key = key;
return obj[key];
});
},
async getList() {
const { code, data } = await this.$axios({
url: '/analysis/equipment-analysis/status',
method: 'get',
params: this.queryParams,
});
if (code == 0) {
this.existingEquipments = Object.values(data).map((eq) => eq[0].equipmentId);
this.graphList = this.objectToArray(data);
}
},
/** 准备设备数据 */
async initEquipment() {
const { code, data } = await this.$axios({
url: '/base/equipment/listAll',
method: 'get',
});
if (code == 0) {
this.eqList = data.map((item) => {
return {
name: item.name,
id: item.id,
};
});
}
},
/** 准备产线数据 */
async initProductline() {
const { code, data } = await this.$axios({
url: '/base/production-line/listAll',
method: 'get',
});
if (code == 0) {
this.searchBarFormConfig[0].selectOptions = data.map((item) => {
return {
name: item.name,
id: item.id,
};
});
}
},
/** 准备工段数据 */
async initWorksection() {
const { code, data } = await this.$axios({
url: '/base/workshop-section/listAll',
method: 'get',
});
if (code == 0) {
this.searchBarFormConfig[1].selectOptions = data.map((item) => {
return {
name: item.name,
id: item.id,
};
});
}
},
handleSearchBarSelectChange({ param, value }) {
if (!value) {
this.searchBarFormConfig[1].selectOptions = [];
return;
}
switch (param) {
case 'lineId':
this.$axios({
url: '/base/workshop-section/listByParentId',
method: 'get',
params: {
id: value,
},
}).then(({ code, data }) => {
if (code == 0) {
this.searchBarFormConfig[1].selectOptions = data.map((item) => {
return {
name: item.name,
id: item.id,
};
});
}
});
}
},
handleSearchBarBtnClick({ btnName, ...payload }) {
switch (btnName) {
case 'search':
if (!payload.recordTime || payload.recordTime.length <= 0) {
this.$message.warning('请选择时间段');
return;
}
this.startTime = new Date(payload.recordTime)
this.queryParams.lineId = payload.lineId || null;
this.queryParams.sectionId = payload.sectionId || null;
this.queryParams.equipmentId = payload.equipmentId || null;
this.queryParams.recordTime = payload.recordTime
? [
payload.recordTime,
new Date(
new Date(payload.recordTime).getTime() + 24 * 3600 * 1000
)
.toLocaleDateString()
.split('/')
.map((value, index) => {
if (index == 1 || index == 2) {
return value.padStart(2, '0');
}
return value;
})
.join('-') + ' 00:00:00',
]
: null;
this.getList();
break;
case 'compare':
this.open = true;
break;
}
},
async submitForm() {
if (this.existingEquipments.indexOf(this.queryParams.equipmentId) >= 0) {
this.$message.warning('该设备已存在');
return;
}
const {sectionId,...params} = this.queryParams
const { code, data } = await this.$axios({
url: '/analysis/equipment-analysis/status',
method: 'get',
params: params,
});
if (code == 0) {
const newEqlist = this.objectToArray(data);
if (!newEqlist || newEqlist.length == 0) {
this.$message.warning('该设备没有状态数据');
return;
}
this.graphList.push(newEqlist[0]);
}
this.open = false;
},
},
};
</script>
<style scoped lang="scss">
.graph {
// border: 1px solid #ccc;
// padding: 12px 12px 28px 12px;
// margin: 64px 0;
position: relative;
display: flex;
}
.graph-title {
// position: absolute;
// top: -64px;
// left: -1px;
// padding: 8px 18px;
padding: 0 12px;
font-size: 14px;
line-height: 1;
}
.graph-content {
display: flex;
flex: 1;
padding: 22px 12px;
border: 1px solid #ccc;
border-bottom-width: 2px;
border-top: none;
position: relative;
}
.graph-content::after,
.graph-content::before {
content: '';
position: absolute;
width: 3px;
height: 80%;
background: #fff;
right: -1px;
top: 0;
}
.graph-content::before {
right: unset;
left: -1px;
}
.graph-item,
.graph-item-fixed {
// height: 88px;
// width: 24px;
flex: 1;
// border: 1px solid #ccc;
position: relative;
}
.graph-item-fixed {
flex: unset;
}
.graph-item::before,
.graph-item-fixed::before {
position: absolute;
bottom: -16px;
left: 0;
content: attr(data-time);
// font-size - js
// rotate - js
// color - js, default:
color: #777;
transform-origin: left top;
transform: rotate(12deg);
}
.graph-item-fixed::after,
.graph-item::after {
content: '';
position: absolute;
left: 0;
bottom: -3px;
display: inline-block;
}
.graph-item.tick::after,
.graph-item-fixed.tick::after {
width: 1px;
height: 6px;
border-left: 1px solid #777;
}
.running {
background-color: #288AFF;
// background-color: #84f04e;
}
.waiting {
background-color: #5ad8a6;
// background-color: #409eff;
}
.fault {
// background-color: #ea5b5b;
background-color: #FC9C91;
}
.full {
// background-color: #e6a23c;
background-color: #598fff;
}
.lack {
// background-color: #a69c8d;
background-color: #7585a2;
}
.stop {
background-color: #FFDC94;
}
.legend-row {
margin: 6px 0;
padding-right: 12px;
display: flex;
justify-content: flex-end;
>.legend:not(:last-child) {
margin-right: 12px;
}
.legend {
display: flex;
align-items: center;
}
.icon {
width: 8px;
height: 8px;
border-radius: 2px;
margin-right: 4px;
margin-top: 1px;
}
}
.blue-title {
position: relative;
padding: 4px 0;
padding-left: 12px;
font-size: 14px;
color: #606266;
font-weight: 700;
margin-bottom: 12px;
&::before {
content: '';
position: absolute;
left: 0;
top: 6px;
height: 16px;
width: 4px;
border-radius: 1px;
background: #0b58ff;
}
}
.echarts__status-chart {
background: #ccc;
}
.echarts__status-chart>div {
height: 100% !important;
width: 100% !important;
}
</style>

View File

@@ -6,19 +6,28 @@
--> -->
<template> <template>
<div class="status-timegraph-container" style="background: #f2f4f9; flex: 1; display: flex; flex-direction: column"> <div
<el-row class="" style=" class="status-timegraph-container"
style="background: #f2f4f9; flex: 1; display: flex; flex-direction: column">
<el-row
class=""
style="
margin-bottom: 12px; margin-bottom: 12px;
background: #fff; background: #fff;
padding: 16px 16px 0; padding: 16px 16px 0;
border-radius: 8px; border-radius: 8px;
"> ">
<div class="blue-title">生产节拍时序图</div> <div class="blue-title">生产节拍时序图</div>
<SearchBar :formConfigs="searchBarFormConfig" ref="search-bar" :remove-blue="true" <SearchBar
@select-changed="handleSearchBarSelectChange" @headBtnClick="handleSearchBarBtnClick" /> :formConfigs="searchBarFormConfig"
ref="search-bar"
:remove-blue="true"
@headBtnClick="handleSearchBarBtnClick" />
</el-row> </el-row>
<el-row class="" style=" <el-row
class=""
style="
height: 1px; height: 1px;
flex: 1; flex: 1;
margin-bottom: 12px; margin-bottom: 12px;
@@ -47,24 +56,43 @@
</div> </div>
</el-col> </el-col>
</el-row> </el-row>
<div class="main-area" style="flex: 1; display: flex; flex-direction: column"> <div
<div class="graphs" v-show="graphList.length" id="status-chart" style="height: 1px; flex: 1"></div> class="main-area"
style="flex: 1; display: flex; flex-direction: column">
<div
class="graphs"
v-show="graphList.length"
id="status-chart"
style="height: 1px; flex: 1"></div>
<h2 v-if="!graphList || graphList.length == 0" class="no-data-bg"></h2> <h2 v-if="!graphList || graphList.length == 0" class="no-data-bg"></h2>
</div> </div>
</el-row> </el-row>
<!-- 对话框(添加 / 修改) --> <!-- 对话框(添加 / 修改) -->
<base-dialog dialogTitle="添加设备" :dialogVisible="open" width="500px" @close="open = false" @cancel="open = false" <base-dialog
dialogTitle="添加设备"
:dialogVisible="open"
width="500px"
@close="open = false"
@cancel="open = false"
@confirm="submitForm"> @confirm="submitForm">
<el-select v-if="open" style="width: 100%" v-model="queryParams.equipmentId" placeholder="请选择一个设备"> <el-select
<el-option v-for="eq in eqList" :key="eq.id" :value="eq.id" :label="eq.name"></el-option> v-if="open"
style="width: 100%"
v-model="queryParams.equipmentId"
placeholder="请选择一个设备">
<el-option
v-for="eq in eqList"
:key="eq.id"
:value="eq.id"
:label="eq.name"></el-option>
</el-select> </el-select>
</base-dialog> </base-dialog>
</div> </div>
</template> </template>
<script> <script>
import Gantt from './chart'; import Gantt from './gantt';
export default { export default {
name: 'SGStatus', name: 'SGStatus',
@@ -74,21 +102,6 @@ export default {
return { return {
chart: null, chart: null,
searchBarFormConfig: [ searchBarFormConfig: [
{
type: 'select',
label: '产线',
placeholder: '请选择产线',
selectOptions: [],
param: 'lineId',
onchange: true,
},
{
type: 'select',
label: '工段',
placeholder: '请选择工段',
selectOptions: [],
param: 'sectionId',
},
// 时间段 // 时间段
{ {
type: 'datePicker', type: 'datePicker',
@@ -119,8 +132,6 @@ export default {
}, },
], ],
queryParams: { queryParams: {
lineId: null,
sectionId: null,
equipmentId: null, equipmentId: null,
recordTime: null, recordTime: null,
}, },
@@ -129,37 +140,41 @@ export default {
open: false, open: false,
eqList: [], eqList: [],
startTime: null, startTime: null,
gantt: null gantt: null,
// demo: [
// [
// {
// equipmentName: '下片机',
// duration: 30,
// relativeDuration: 0.6,
// status: 0,
// startPos: 0,
// startTime: 1691568181000,
// },
// {
// equipmentName: '下片机',
// duration: 20,
// relativeDuration: 0.4,
// status: 2,
// startPos: 30,
// startTime: 1691569981000
// },
// ],
// ],
}; };
}, },
computed: {}, computed: {},
created() { created() {
this.initProductline(); const now = new Date();
this.initWorksection(); const year = now.getFullYear();
const month = String(now.getMonth() + 1).padStart(2, '0');
const day = String(now.getDate()).padStart(2, '0');
const formattedDate = `${year}-${month}-${day} 00:00:00`;
this.$nextTick(() => {
this.$refs['search-bar'].formInline.recordTime = formattedDate;
});
this.queryParams.equipmentId = Number(this.$route.query.eqid);
this.startTime = new Date(formattedDate);
this.queryParams.recordTime = formattedDate
? [
formattedDate,
new Date(new Date(formattedDate).getTime() + 24 * 3600 * 1000)
.toLocaleDateString()
.split('/')
.map((value, index) => {
if (index == 1 || index == 2) {
return value.padStart(2, '0');
}
return value;
})
.join('-') + ' 00:00:00',
]
: null;
this.getList();
this.initEquipment(); this.initEquipment();
// this.getList();
}, },
mounted() { }, mounted() {
},
watch: { watch: {
graphList: { graphList: {
handler(val) { handler(val) {
@@ -171,7 +186,6 @@ export default {
return; return;
} }
this.gantt.update(val); this.gantt.update(val);
}); });
} }
return; return;
@@ -193,9 +207,7 @@ export default {
/** 重置查询条件 */ /** 重置查询条件 */
initQuery() { initQuery() {
this.queryParams.lineId = null;
this.queryParams.equipmentId = null; this.queryParams.equipmentId = null;
this.queryParams.sectionId = null;
this.queryParams.recordTime = null; this.queryParams.recordTime = null;
}, },
@@ -215,7 +227,9 @@ export default {
params: this.queryParams, params: this.queryParams,
}); });
if (code == 0) { if (code == 0) {
this.existingEquipments = Object.values(data).map((eq) => eq[0].equipmentId); this.existingEquipments = Object.values(data).map(
(eq) => eq[0].equipmentId
);
this.graphList = this.objectToArray(data); this.graphList = this.objectToArray(data);
} }
}, },
@@ -236,65 +250,8 @@ export default {
} }
}, },
/** 准备产线数据 */
async initProductline() {
const { code, data } = await this.$axios({
url: '/base/production-line/listAll',
method: 'get',
});
if (code == 0) {
this.searchBarFormConfig[0].selectOptions = data.map((item) => {
return {
name: item.name,
id: item.id,
};
});
}
},
/** 准备工段数据 */
async initWorksection() {
const { code, data } = await this.$axios({
url: '/base/workshop-section/listAll',
method: 'get',
});
if (code == 0) {
this.searchBarFormConfig[1].selectOptions = data.map((item) => {
return {
name: item.name,
id: item.id,
};
});
}
},
handleSearchBarSelectChange({ param, value }) {
if (!value) {
this.searchBarFormConfig[1].selectOptions = [];
return;
}
switch (param) {
case 'lineId':
this.$axios({
url: '/base/workshop-section/listByParentId',
method: 'get',
params: {
id: value,
},
}).then(({ code, data }) => {
if (code == 0) {
this.searchBarFormConfig[1].selectOptions = data.map((item) => {
return {
name: item.name,
id: item.id,
};
});
}
});
}
},
handleSearchBarBtnClick({ btnName, ...payload }) { handleSearchBarBtnClick({ btnName, ...payload }) {
this.queryParams.equipmentId = Number(this.$route.query.eqid);
switch (btnName) { switch (btnName) {
case 'search': case 'search':
if (!payload.recordTime || payload.recordTime.length <= 0) { if (!payload.recordTime || payload.recordTime.length <= 0) {
@@ -302,26 +259,23 @@ export default {
return; return;
} }
this.startTime = new Date(payload.recordTime) this.startTime = new Date(payload.recordTime);
this.queryParams.lineId = payload.lineId || null;
this.queryParams.sectionId = payload.sectionId || null;
this.queryParams.equipmentId = payload.equipmentId || null;
this.queryParams.recordTime = payload.recordTime this.queryParams.recordTime = payload.recordTime
? [ ? [
payload.recordTime, payload.recordTime,
new Date( new Date(
new Date(payload.recordTime).getTime() + 24 * 3600 * 1000 new Date(payload.recordTime).getTime() + 24 * 3600 * 1000
) )
.toLocaleDateString() .toLocaleDateString()
.split('/') .split('/')
.map((value, index) => { .map((value, index) => {
if (index == 1 || index == 2) { if (index == 1 || index == 2) {
return value.padStart(2, '0'); return value.padStart(2, '0');
} }
return value; return value;
}) })
.join('-') + ' 00:00:00', .join('-') + ' 00:00:00',
] ]
: null; : null;
this.getList(); this.getList();
break; break;
@@ -336,10 +290,11 @@ export default {
this.$message.warning('该设备已存在'); this.$message.warning('该设备已存在');
return; return;
} }
const { ...params } = this.queryParams;
const { code, data } = await this.$axios({ const { code, data } = await this.$axios({
url: '/analysis/equipment-analysis/status', url: '/analysis/equipment-analysis/status',
method: 'get', method: 'get',
params: this.queryParams, params: params,
}); });
if (code == 0) { if (code == 0) {
const newEqlist = this.objectToArray(data); const newEqlist = this.objectToArray(data);
@@ -444,7 +399,7 @@ export default {
} }
.running { .running {
background-color: #288AFF; background-color: #288aff;
// background-color: #84f04e; // background-color: #84f04e;
} }
@@ -455,7 +410,7 @@ export default {
.fault { .fault {
// background-color: #ea5b5b; // background-color: #ea5b5b;
background-color: #FC9C91; background-color: #fc9c91;
} }
.full { .full {
@@ -469,7 +424,7 @@ export default {
} }
.stop { .stop {
background-color: #FFDC94; background-color: #ffdc94;
} }
.legend-row { .legend-row {
@@ -478,7 +433,7 @@ export default {
display: flex; display: flex;
justify-content: flex-end; justify-content: flex-end;
>.legend:not(:last-child) { > .legend:not(:last-child) {
margin-right: 12px; margin-right: 12px;
} }
@@ -521,7 +476,7 @@ export default {
background: #ccc; background: #ccc;
} }
.echarts__status-chart>div { .echarts__status-chart > div {
height: 100% !important; height: 100% !important;
width: 100% !important; width: 100% !important;
} }

View File

@@ -1,188 +1,182 @@
<template> <template>
<el-form ref="form" :rules="rules" label-width="110px" :model="form"> <el-form ref="form" :rules="rules" label-width="110px" :model="form">
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="班次名称" prop="name"> <el-form-item label="工厂" prop="factoryId">
<el-input v-model="form.name"></el-input> <el-select
</el-form-item> v-model="form.factoryId"
</el-col> filterable
<el-col :span="12"> clearable
<el-form-item label="编码" prop="code"> style="width: 100%"
<el-input v-model="form.code" disabled></el-input> placeholder="请选择工厂">
</el-form-item> <el-option
</el-col> v-for="item in factoryArr"
</el-row> :key="item.id"
<el-row> :label="item.name"
<el-col :span="12"> :value="item.id"></el-option>
<el-form-item label="生效时间" prop="enableTime"> </el-select>
<el-date-picker </el-form-item>
v-model="form.enableTime" </el-col>
type="datetime" <el-col :span="12">
placeholder="选择日期时间" <el-form-item label="班次名称" prop="name">
label-format="yyyy-MM-dd HH:mm:ss" <el-input v-model="form.name"></el-input>
value-format="timestamp" </el-form-item>
style="width: 100%;"> </el-col>
</el-date-picker> <el-col :span="12">
</el-form-item> <el-form-item label="编码" prop="code">
</el-col> <el-input v-model="form.code" disabled></el-input>
<el-col :span="12"> </el-form-item>
<el-form-item label="失效时间" prop="disableTime"> </el-col>
<el-date-picker <el-col :span="12">
v-model="form.disableTime" <el-form-item label="班次开始时间" prop="startTime">
type="datetime" <el-time-picker
placeholder="选择日期时间" v-model="form.startTime"
label-format="yyyy-MM-dd HH:mm:ss" format="HH:mm"
value-format="timestamp" value-format="HH:mm"
style="width: 100%;"> style="width: 100%"
</el-date-picker> @change="timeFun('start')"></el-time-picker>
</el-form-item> </el-form-item>
</el-col> </el-col>
</el-row> <el-col :span="12">
<el-row> <el-form-item label="班次结束时间" prop="endTime">
<el-col :span="12"> <el-time-picker
<el-form-item label="班次开始时间" prop="startTime"> v-model="form.endTime"
<el-time-picker format="HH:mm"
v-model="form.startTime" value-format="HH:mm"
format='HH:mm' style="width: 100%"
value-format='HH:mm' @change="timeFun('end')"></el-time-picker>
style="width: 100%;" </el-form-item>
@change="timeFun('start')" </el-col>
> <el-col :span="12">
</el-time-picker> <el-form-item label="是否跨天" prop="daySpan">
</el-form-item> <el-select
</el-col> v-model="form.daySpan"
<el-col :span="12"> placeholder="请选择"
<el-form-item label="班次结束时间" prop="endTime"> disabled
<el-time-picker style="width: 100%">
v-model="form.endTime" <el-option label="否" :value="0"></el-option>
format='HH:mm' <el-option label="是" :value="1"></el-option>
value-format='HH:mm' </el-select>
style="width: 100%;" </el-form-item>
@change="timeFun('end')" </el-col>
> <el-col :span="12">
</el-time-picker> <el-form-item label="备注" prop="remark">
</el-form-item> <el-input v-model="form.remark"></el-input>
</el-col> </el-form-item>
</el-row> </el-col>
<el-row> </el-row>
<el-col :span="12"> </el-form>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark"></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="是否跨天" prop="daySpan">
<el-select v-model="form.daySpan" placeholder="请选择" disabled style="width: 100%;">
<el-option label="否" :value= '0' ></el-option>
<el-option label="是" :value= '1' ></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template> </template>
<script> <script>
import { getGroupClasses, updateGroupClasses, createGroupClasses, getCode } from '@/api/base/groupClasses' import {
getGroupClasses,
updateGroupClasses,
createGroupClasses,
getCode,
} from '@/api/base/groupClasses';
import { getFactoryPage } from '@/api/core/base/factory';
export default { export default {
name: 'groupClassAdd', name: 'groupClassAdd',
data() { data() {
return { return {
form: { form: {
id: '', id: '',
name: '', factoryId: '',
code: '', name: '',
enableTime: '', code: '',
disableTime: '', startTime: '',
startTime: '', endTime: '',
endTime: '', daySpan: '',
daySpan: '', remark: '',
remark: '' },
}, isEdit: false, //是否是编辑
isEdit: false, //是否是编辑 factoryArr: [],
rules: { rules: {
name: [{ required: true, message: '请输入班组名称', trigger: 'blur' }], factoryId: [
enableTime: [{ required: true, message: '请选择班次开始时间', trigger: 'change' }], { required: true, message: '请选择工厂', trigger: 'change' },
code: [{ required: true, message: '请输入编码', trigger: 'blur' }], ],
startTime: [{ required: true, message: '请输入生效时间', trigger: 'change' }], name: [{ required: true, message: '请输入班组名称', trigger: 'blur' }],
endTime: [{ required: true, message: '请选择班次结束时间', trigger: 'change' }] code: [{ required: true, message: '请输入编码', trigger: 'blur' }],
} startTime: [
} { required: true, message: '请选择班次开始时间', trigger: 'change' },
}, ],
methods: { endTime: [
init(id) { { required: true, message: '请选择班次结束时间', trigger: 'change' },
if (id) { ],
this.isEdit = true },
this.form.id = id };
getGroupClasses(id).then((res) => { },
if (res.code === 0) { created() {
this.form = res.data const params = {
} pageSize: 100,
}) pageNo: 1,
} else { };
this.isEdit = false getFactoryPage(params).then((res) => {
this.form.id = '' this.factoryArr = res.data.list || [];
getCode().then((res) => { });
this.form.code = res.data },
}) methods: {
} init(id) {
}, if (id) {
timeFun(val) { this.isEdit = true;
if (this.form.startTime && this.form.endTime) { this.form.id = id;
if (this.form.startTime > this.form.endTime) { getGroupClasses(id).then((res) => {
this.form.daySpan = 1 if (res.code === 0) {
} else if (this.form.startTime < this.form.endTime) { this.form = res.data;
this.form.daySpan = 0 }
} else { });
if (val === 'start') { } else {
this.form.startTime = '' this.isEdit = false;
} else { this.form.id = '';
this.form.endTime = '' getCode().then((res) => {
} this.form.code = res.data;
this.$modal.msgWarning('班次开始时间和结束时间不能相同') });
} }
} },
}, timeFun(val) {
submitForm() { if (this.form.startTime && this.form.endTime) {
this.$refs['form'].validate((valid) => { if (this.form.startTime > this.form.endTime) {
if (valid) { this.form.daySpan = 1;
let obj = {} } else if (this.form.startTime < this.form.endTime) {
if (this.form.disableTime) { this.form.daySpan = 0;
obj = this.form } else {
} else { if (val === 'start') {
obj.id = this.form.id this.form.startTime = '';
obj.name = this.form.name } else {
obj.code = this.form.code this.form.endTime = '';
obj.enableTime = this.form.enableTime }
obj.startTime = this.form.startTime this.$modal.msgWarning('班次开始时间和结束时间不能相同');
obj.endTime = this.form.endTime }
obj.daySpan = this.form.daySpan }
obj.remark = this.form.remark },
} submitForm() {
if (this.isEdit) { this.$refs['form'].validate((valid) => {
//编辑 if (valid) {
updateGroupClasses({ ...obj }).then((res) => { if (this.isEdit) {
if (res.code === 0) { //编辑
this.$modal.msgSuccess("操作成功"); updateGroupClasses({ ...this.form }).then((res) => {
this.$emit('successSubmit') if (res.code === 0) {
} this.$modal.msgSuccess('操作成功');
}) this.$emit('successSubmit');
} else { }
createGroupClasses({ ...obj }).then((res) => { });
if (res.code === 0) { } else {
this.$modal.msgSuccess("操作成功"); createGroupClasses({ ...this.form }).then((res) => {
this.$emit('successSubmit') if (res.code === 0) {
} this.$modal.msgSuccess('操作成功');
}) this.$emit('successSubmit');
} }
} else { });
return false }
} } else {
}) return false;
}, }
formClear() { });
this.$refs.form.resetFields() },
this.isEdit = false formClear() {
} this.$refs.form.resetFields();
} this.isEdit = false;
} },
},
};
</script> </script>

View File

@@ -0,0 +1,53 @@
<!--
* @Author: zwq
* @Date: 2024-07-01 14:53:55
* @LastEditors: zwq
* @LastEditTime: 2025-01-14 13:09:33
* @Description:
-->
<template>
<el-switch v-model="state" type="text" size="small" :disabled="readonly" @change="changeHandler" />
</template>
<script>
export default {
props: {
injectData: {
type: Object,
default: () => ({})
}
},
data() {
return {
state: false
}
},
computed: {
readonly() {
return !!this.injectData.readonly
}
},
mounted() {
this.mapToState()
},
methods: {
mapToState() {
if (this.injectData.prop === 'enabled') {
this.state = this.injectData.enabled === 1 ? true : false
}
},
changeHandler() {
let params = {}
let payload = {}
params.name = 'state'
payload.id = this.injectData.id
payload.enabled = this.state ? '1' : '0'
payload.startTime = this.injectData.startTime
payload.endTime = this.injectData.endTime
payload.factoryId = this.injectData.factoryId
params.payload = payload
this.$emit('emitData', params)
}
}
}
</script>

View File

@@ -1,260 +1,293 @@
<!--
* @Author: zwq
* @Date: 2024-07-01 14:53:55
* @LastEditors: zwq
* @LastEditTime: 2025-02-24 16:02:39
* @Description:
-->
<template> <template>
<div class="app-container"> <div class="app-container">
<!-- 搜索工作栏 -->
<!-- 搜索工作栏 --> <search-bar
<search-bar :formConfigs="formConfig"
:formConfigs="formConfig" ref="searchBarForm"
ref="searchBarForm" @headBtnClick="buttonClick" />
@headBtnClick="buttonClick" <!-- 列表 -->
/> <base-table
<!-- 列表 --> :page="queryParams.pageNo"
<base-table :limit="queryParams.pageSize"
:page="queryParams.pageNo" :table-props="tableProps"
:limit="queryParams.pageSize" :table-data="list"
:table-props="tableProps" :max-height="tableH"
:table-data="list" @emitFun="handleTableEvents">
:max-height="tableH" <method-btn
> v-if="tableBtn.length"
<method-btn slot="handleBtn"
v-if="tableBtn.length" :width="120"
slot="handleBtn" label="操作"
:width="120" :method-list="tableBtn"
label="操作" @clickBtn="handleClick" />
:method-list="tableBtn" </base-table>
@clickBtn="handleClick" <pagination
/> :page.sync="queryParams.pageNo"
</base-table> :limit.sync="queryParams.pageSize"
<pagination :total="total"
:page.sync="queryParams.pageNo" @pagination="getList" />
:limit.sync="queryParams.pageSize" <!-- 新增 -->
:total="total" <base-dialog
@pagination="getList" :dialogTitle="addOrEditTitle"
/> :dialogVisible="centervisible"
<!-- 新增 --> @cancel="handleCancel"
<base-dialog @confirm="handleConfirm"
:dialogTitle="addOrEditTitle" :before-close="handleCancel"
:dialogVisible="centervisible" width="50%">
@cancel="handleCancel" <group-class-add ref="classList" @successSubmit="successSubmit" />
@confirm="handleConfirm" </base-dialog>
:before-close="handleCancel" </div>
width='50%'
>
<group-class-add ref="classList" @successSubmit="successSubmit" />
</base-dialog>
</div>
</template> </template>
<script> <script>
import { getGroupClassesPage, deleteGroupClasses, updateGroupClasses } from "@/api/base/groupClasses"; import {
import GroupClassAdd from './components/groupClassAdd.vue' getGroupClassesPage,
import { formatDate } from '@/utils' deleteGroupClasses,
updateGroupClasses,
} from '@/api/base/groupClasses';
import GroupClassAdd from './components/groupClassAdd.vue';
import StatusBtn from './components/statusBtn';
import tableHeightMixin from '@/mixins/tableHeightMixin';
import { getFactoryPage } from '@/api/core/base/factory';
const tableProps = [ const tableProps = [
{ {
prop: 'enableTimeStr', prop: 'factoryName',
label: '生效时段', label: '工厂',
minWidth: 300 },
}, {
{ prop: 'name',
prop: 'name', label: '班次名称',
label: '班次名称' },
}, {
{ prop: 'timeStr',
prop: 'timeStr', label: '班次时间',
label: '班次时间', minWidth: 100,
minWidth: 100 },
}, {
{ prop: 'code',
prop: 'code', label: '班次编码',
label: '班次编码', minWidth: 200,
minWidth: 200 },
}, {
{ prop: 'enabled',
prop: 'status', label: '班次状态',
label: '班次状态' subcomponent: StatusBtn,
}, },
{ // {
prop: 'remark', // prop: 'remark',
label: '备注' // label: '备注',
} // },
] ];
export default { export default {
name: "GroupClass", name: 'GroupClass',
components: { GroupClassAdd }, components: { GroupClassAdd },
data() { mixins: [tableHeightMixin],
return { data() {
formConfig: [ return {
{ formConfig: [
type: 'input', {
label: '班次名称', type: 'select',
placeholder: '班次名称', label: '工厂',
param: 'name' selectOptions: [],
}, param: 'factoryId',
{ onchange: true,
type: 'button', },
btnName: '查询', {
name: 'search', type: 'input',
color: 'primary' label: '班次名称',
}, placeholder: '班次名称',
{ param: 'name',
type: 'separate' },
}, {
{ type: 'button',
type: this.$auth.hasPermi('base:group-classes:create') ? 'button' : '', btnName: '查询',
btnName: '新增', name: 'search',
name: 'add', color: 'primary',
color: 'success', },
plain: true {
} type: 'separate',
], },
tableProps, {
tableBtn: [ type: this.$auth.hasPermi('base:group-classes:create')
{ ? 'button'
type: 'cancel', : '',
btnName: '作废', btnName: '新增',
showParam: { name: 'add',
type: '&', color: 'success',
data: [ plain: true,
{ },
type: 'unequal', ],
name: 'status', tableProps,
value: '不可用' tableBtn: [
} this.$auth.hasPermi('base:group-classes:update')
] ? {
} type: 'edit',
}, btnName: '编辑',
this.$auth.hasPermi('base:group-classes:update') }
? { : undefined,
type: 'edit', this.$auth.hasPermi('base:group-classes:delete')
btnName: '编辑' ? {
} type: 'delete',
: undefined, btnName: '删除',
this.$auth.hasPermi('base:group-classes:delete') }
? { : undefined,
type: 'delete', ].filter((v) => v),
btnName: '删除' // 总条数
} total: 0,
: undefined // 班次基础信息列表
].filter((v) => v), list: [],
tableH: this.tableHeight(260), // 弹出层标题
// 总条数 addOrEditTitle: '',
total: 0, // 是否显示弹出层
// 班次基础信息列表 centervisible: false,
list: [], // 查询参数
// 弹出层标题 queryParams: {
addOrEditTitle: "", pageNo: 1,
// 是否显示弹出层 pageSize: 20,
centervisible: false, name: null,
// 查询参数 },
queryParams: { };
pageNo: 1, },
pageSize: 20, created() {
name: null this.getList();
} this.getPdLineList();
}; },
}, methods: {
created() { getPdLineList() {
window.addEventListener('resize', () => { const params = {
this.tableH = this.tableHeight(260) pageSize: 100,
}) pageNo: 1,
this.getList() };
}, getFactoryPage(params).then((res) => {
methods: { this.formConfig[0].selectOptions = res.data.list || [];
buttonClick(val) { });
switch (val.btnName) { },
case 'search': buttonClick(val) {
this.queryParams.pageNo = 1; switch (val.btnName) {
this.queryParams.name = val.name case 'search':
this.getList() this.queryParams.pageNo = 1;
break this.queryParams.name = val.name;
default: this.queryParams.factoryId = val.factoryId || undefined;
this.addOrEditTitle = '新增' this.getList();
this.centervisible = true break;
this.$nextTick(() => { default:
this.$refs.classList.init() this.addOrEditTitle = '新增';
}) this.centervisible = true;
} this.$nextTick(() => {
}, this.$refs.classList.init();
/** 查询列表 */ });
getList() { }
getGroupClassesPage(this.queryParams).then(res => { },
if (res.code === 0 && res.data.list.length > 0) { // 班组状态
res.data.list.map(item => { handleTableEvents(params) {
item.enableTimeStr = formatDate(item.enableTime) + '至' + (item.disableTime ? formatDate(item.disableTime) : '永久') if (params.name === 'state') {
item.timeStr = item.startTime.slice(0, 5) + '-' + item.endTime.slice(0, 5) // 班组状态
item.status = item.status === true ? '可用' : '不可用' updateGroupClasses({ ...params.payload })
}) .then((res) => {
this.list = res.data.list; if (res.code === 0) {
this.total = res.data.total; this.$modal.msgSuccess('操作成功');
} else { this.getList();
this.list = [] }
this.total = 0 })
} .catch((res) => {
}); this.getList();
}, });
handleClick(val) { }
switch (val.type) { },
case 'edit': /** 查询列表 */
this.addOrEditTitle = '编辑' getList() {
this.$nextTick(() => { getGroupClassesPage(this.queryParams).then((res) => {
this.$refs.classList.init(val.data.id) if (res.code === 0 && res.data.list && res.data.list.length > 0) {
}) res.data.list.map((item) => {
this.centervisible = true item.timeStr =
break item.startTime.slice(0, 5) + '-' + item.endTime.slice(0, 5);
case 'cancel': });
this.discard(val.data) this.list = res.data.list;
break this.total = res.data.total;
default: } else {
this.handleDelete(val.data) this.list = [];
} this.total = 0;
}, }
handleCancel() { });
this.$refs.classList.formClear() },
this.centervisible = false handleClick(val) {
this.addOrEditTitle = '' switch (val.type) {
}, case 'edit':
handleConfirm() { this.addOrEditTitle = '编辑';
this.$refs.classList.submitForm() this.$nextTick(() => {
}, this.$refs.classList.init(val.data.id);
successSubmit() { });
this.handleCancel() this.centervisible = true;
this.getList() break;
}, default:
discard(row) { this.handleDelete(val.data);
let obj = {} }
obj.id = row.id },
obj.startTime = row.startTime handleCancel() {
obj.endTime = row.endTime this.$refs.classList.formClear();
obj.enableTime = row.enableTime this.centervisible = false;
obj.disableTime = Date.parse(new Date()) this.addOrEditTitle = '';
this.$modal.confirm('是否确认作废班次名称为"' + row.name + '"的数据项?').then(function() { },
return updateGroupClasses({ ...obj }) handleConfirm() {
}).then(() => { this.$refs.classList.submitForm();
this.getList(); },
this.$modal.msgSuccess("操作成功"); successSubmit() {
}).catch(() => {}); this.handleCancel();
}, this.getList();
/** 删除按钮操作 */ },
handleDelete(row) { /** 删除按钮操作 */
console.log(row) handleDelete(row) {
let _this = this let _this = this;
if (row.status === '可用') {// 可用 if (row.enabled) {
_this.$modal.confirm('删除的班次"' + row.name + '"可能会影响交接班计划,请点取消再次确认!').then(function() { // 可用
return _this.$modal.confirm('是否确认删除班次名称为"' + row.name + '"的数据项?').then(function() { this.$confirm(
return deleteGroupClasses(row.id); `是否确认删除 ${row.name} 的数据项?`,
}).then(() => { '可能会影响交接班计划!',
_this.getList(); {
_this.$modal.msgSuccess("删除成功"); confirmButtonText: '确定',
}).catch(() => {}); cancelButtonText: '取消',
}) type: 'warning',
} else { }
_this.$modal.confirm('是否确认删除班次名称为"' + row.name + '"的数据项?').then(function() { ).then(function () {
return deleteGroupClasses(row.id); return _this
}).then(() => { .$confirm(`是否确认删除 ${row.name} 的数据项?`, '系统提示', {
_this.getList(); confirmButtonText: '确定',
_this.$modal.msgSuccess("删除成功"); cancelButtonText: '取消',
}).catch(() => {}); type: 'warning',
} })
} .then(function () {
} return deleteGroupClasses(row.id);
})
.then(() => {
_this.getList();
_this.$modal.msgSuccess('删除成功');
})
.catch(() => {});
});
} else {
this.$confirm(`是否确认删除 ${row.name} 的数据项?`, '系统提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(function () {
return deleteGroupClasses(row.id);
})
.then(() => {
_this.getList();
_this.$modal.msgSuccess('删除成功');
})
.catch(() => {});
}
},
},
}; };
</script> </script>

View File

@@ -0,0 +1,278 @@
<template>
<div class="baseTable">
<el-table
:ref="id"
:data="renderData"
v-bind="$attrs"
:border="cancelBorder ? false : true"
@current-change="currentChange"
@selection-change="handleSelectionChange"
style="width: 100%"
:header-cell-style="{
background: '#F2F4F9',
color: '#606266',
}">
<!-- 多选 -->
<el-table-column
v-if="selectWidth"
type="selection"
:width="selectWidth" />
<!-- 序号 -->
<el-table-column
v-if="page && limit"
prop="_pageIndex"
:width="pageWidth"
align="center"
:fixed="cancelPageFixed ? false : true">
<template slot="header">
<el-popover placement="bottom-start" width="300" trigger="click">
<div
class="setting-box"
style="max-height: 400px; overflow-y: auto">
<el-checkbox
v-for="(item, index) in tableProps"
:key="'cb' + index"
v-model="selectedBox[index]"
:label="item.label" />
</div>
<i slot="reference" class="el-icon-s-tools" />
</el-popover>
</template>
</el-table-column>
<el-table-column
v-for="item in renderTableHeadList"
:key="item.prop"
v-bind="item"
:label="item.label"
:prop="item.prop"
:fixed="item.fixed || false"
:show-overflow-tooltip="item.showOverflowtooltip || false"
:sortable="item.sortable || false">
<template slot="header">
<span>{{ item.label }}</span>
</template>
<!-- 多表头 -->
<template v-if="item.children">
<el-table-column
v-for="sub in item.children"
:prop="sub.prop"
:key="sub.prop"
v-bind="sub"
:label="sub.label">
<template v-if="sub.children">
<el-table-column
v-for="ssub in sub.children"
:prop="ssub.prop"
:key="ssub.prop"
v-bind="ssub"
:label="ssub.label">
<template slot-scope="sscopeInner">
<component
:is="ssub.subcomponent"
v-if="ssub.subcomponent"
:key="sscopeInner.row.id"
:inject-data="{ ...sscopeInner.row, ...ssub }"
@emitData="emitData" />
<span v-else>
{{ sscopeInner.row[ssub.prop] | commonFilter(ssub.filter) }}
</span>
</template>
</el-table-column>
</template>
<template slot-scope="scopeInner">
<component
:is="sub.subcomponent"
v-if="sub.subcomponent"
:key="scopeInner.row.id"
:inject-data="{ ...scopeInner.row, ...sub }"
@emitData="emitData" />
<span v-else>
{{ scopeInner.row[sub.prop] | commonFilter(sub.filter) }}
</span>
</template>
</el-table-column>
</template>
<template slot-scope="scope">
<component
:is="item.subcomponent"
v-if="item.subcomponent"
:key="scope.row.id"
:itemProp="item.prop"
:inject-data="{ ...scope.row, ...item }"
@emitData="emitData" />
<span v-else>
{{ scope.row[item.prop] | commonFilter(item.filter) }}
</span>
</template>
</el-table-column>
<slot name="handleBtn" />
</el-table>
<!-- 表格底部加号 -->
<el-button
v-if="addButtonShow"
class="addButton"
icon="el-icon-plus"
@click="emitButtonClick">
{{ addButtonShow }}
</el-button>
</div>
</template>
<script>
export default {
name: 'BaseTable',
filters: {
commonFilter: (source, filterType = (a) => a) => {
return filterType(source);
},
},
props: {
cancelBorder: {
type: Boolean,
default: false,
},
cancelPageFixed: {
type: Boolean,
default: false,
},
tableData: {
type: Array,
required: true,
default: () => {
return [];
},
},
tableProps: {
type: Array,
default: () => {
return [];
},
},
id: {
type: String,
required: false,
default: '',
},
page: {
type: Number,
required: false,
default: 0,
},
pageWidth: {
type: Number,
required: false,
default: 70,
},
limit: {
type: Number,
required: false,
default: 0,
},
selectWidth: {
type: Number,
required: false,
default: 0,
},
addButtonShow: {
type: String,
required: false,
default: '',
},
},
data() {
return {
selectedBox: new Array(100).fill(true),
};
},
computed: {
renderTableHeadList() {
return this.tableProps.filter((item, index) => {
return this.selectedBox[index];
});
},
renderData() {
return this.tableData.map((item, index) => {
return {
...item,
_pageIndex: (this.page - 1) * this.limit + index + 1,
};
});
},
},
beforeMount() {
this.selectedBox = new Array(100).fill(true);
},
methods: {
currentChange(newVal, oldVal) {
this.$emit('current-change', { newVal, oldVal });
},
handleSelectionChange(val) {
this.$emit('selection-change', val);
},
emitData(val) {
this.$emit('emitFun', val);
},
emitButtonClick() {
this.$emit('emitButtonClick');
},
setCurrent(name, index) {
let _this = this;
let obj = _this.$refs[name].data[index];
_this.$refs[name].setCurrentRow(obj);
},
doLayout(name) {
this.$refs[name].doLayout();
},
},
};
</script>
<style scoped>
.baseTable .show-col-btn {
margin-right: 5px;
line-height: inherit;
cursor: pointer;
}
.baseTable .el-icon-refresh {
cursor: pointer;
}
.baseTable >>> .el-table .el-table__cell {
padding: 0;
height: 35px;
border: 1px solid rgb(220, 220, 220);
}
</style>
<style>
.baseTable .el-table__body tr.current-row > td.el-table__cell {
background-color: #eaf1fc;
}
.baseTable .el-table .el-table__cell {
padding: 0;
height: 35px;
}
.baseTable .addButton {
width: 100%;
height: 35px;
border-top: none;
color: #0b58ff;
border-color: #ebeef5;
border-radius: 0;
}
.baseTable .addButton:hover {
color: #0b58ff;
border-color: #ebeef5;
background-color: #fff;
}
.baseTable .addButton:focus {
border-color: #ebeef5;
background-color: #fff;
}
.el-tooltip__popper.is-dark {
background: rgba(0, 0, 0, 0.6) !important;
}
.el-tooltip__popper .popper__arrow,
.el-tooltip__popper .popper__arrow::after {
border-top-color: rgba(0, 0, 0, 0.4) !important;
}
</style>

View File

@@ -0,0 +1,307 @@
<!--
* @Author: zwq
* @Date: 2023-08-24 14:47:58
* @LastEditors: zwq
* @LastEditTime: 2025-02-25 14:03:40
* @Description:
-->
<template>
<div>
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@headBtnClick="buttonClick" />
<el-table
id="detail"
:data="tableData"
:header-cell-style="{
background: '#F2F4F9',
color: '#606266',
}"
border
:span-method="arraySpanMethod"
v-loading="dataListLoading"
style="width: 100%"
ref="dataList">
<el-table-column prop="lineName" label="产线" align="center" />
<el-table-column
prop="sizes"
width="105"
showOverflowtooltip
align="center"
label="规格" />
<el-table-column prop="process" label="产品工艺" align="center" />
<el-table-column prop="inputN" label="投入" align="center">
<el-table-column prop="inputNum" label="投入数量/片" />
<el-table-column prop="inputArea" label="投入面积/m²">
<template v-slot="scope">
<span>
{{
scope.row.inputArea != null
? scope.row.inputArea.toFixed(2)
: '-'
}}
</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column prop="outputN" label="产出" align="center">
<el-table-column prop="outputNum" label="产出数量/片" />
<el-table-column prop="outputArea" label="产出面积/m²">
<template v-slot="scope">
<span>
{{
scope.row.outputArea != null
? scope.row.outputArea.toFixed(2)
: '-'
}}
</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column prop="lossN" label="不良" align="center">
<el-table-column prop="lossNum" label="不良数量/片" />
<el-table-column prop="lossArea" label="不良面积/m²">
<template v-slot="scope">
<span>
{{
scope.row.lossArea != null ? scope.row.lossArea.toFixed(2) : '-'
}}
</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column prop="lossRatio" label="不良率/%">
<template v-slot="scope">
<span>
{{
scope.row.lossRatio != null ? scope.row.lossRatio.toFixed(2) : '-'
}}
</span>
</template>
</el-table-column>
<el-table-column prop="outputRatio" label="投入产出率/%">
<template v-slot="scope">
<span>
{{
scope.row.outputRatio != null
? scope.row.outputRatio.toFixed(2)
: '-'
}}
</span>
</template>
</el-table-column>
<el-table-column prop="processingRatio" label="加工成品率/%">
<template v-slot="scope">
<span>
{{
scope.row.processingRatio != null
? scope.row.processingRatio.toFixed(2)
: '-'
}}
</span>
</template>
</el-table-column>
<el-table-column prop="lossD" label="不良详情" align="center">
<el-table-column prop="original" label="原片" align="center">
<el-table-column prop="originalLossNum" label="原片不良/片" />
<el-table-column prop="originalLossArea" label="原片不良/m²">
<template v-slot="scope">
<span>
{{
scope.row.originalLossArea != null
? scope.row.originalLossArea.toFixed(2)
: '-'
}}
</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column prop="edge" label="磨边" align="center">
<el-table-column prop="edgeLossNum" label="磨边不良/片" />
<el-table-column prop="edgeLossArea" label="磨边不良/m²">
<template v-slot="scope">
<span>
{{
scope.row.edgeLossArea != null
? scope.row.edgeLossArea.toFixed(2)
: '-'
}}
</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column prop="drill" label="打孔" align="center">
<el-table-column prop="drillLossNum" label="打孔不良/片" />
<el-table-column prop="drillLossArea" label="打孔不良/m²">
<template v-slot="scope">
<span>
{{
scope.row.drillLossArea != null
? scope.row.drillLossArea.toFixed(2)
: '-'
}}
</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column prop="coating" label="镀膜" align="center">
<el-table-column prop="coatingLossNum" label="镀膜不良/片" />
<el-table-column prop="coatingLossArea" label="镀膜不良/m²">
<template v-slot="scope">
<span>
{{
scope.row.coatingLossArea != null
? scope.row.coatingLossArea.toFixed(2)
: '-'
}}
</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column prop="silk" label="丝印" align="center">
<el-table-column prop="silkLossNum" label="丝印不良/片" />
<el-table-column prop="silkLossArea" label="丝印不良/m²">
<template v-slot="scope">
<span>
{{
scope.row.silkLossArea != null
? scope.row.silkLossArea.toFixed(2)
: '-'
}}
</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column prop="tempering" label="钢化" align="center">
<el-table-column prop="temperingLossNum" label="钢化不良/片" />
<el-table-column prop="temperingLossArea" label="钢化不良/m²">
<template v-slot="scope">
<span>
{{
scope.row.temperingLossArea != null
? scope.row.temperingLossArea.toFixed(2)
: '-'
}}
</span>
</template>
</el-table-column>
</el-table-column>
<el-table-column prop="packing" label="包装" align="center">
<el-table-column prop="packingLossNum" label="包装不良/片" />
<el-table-column prop="packingLossArea" label="包装不良/m²">
<template v-slot="scope">
<span>
{{
scope.row.packingLossArea != null
? scope.row.packingLossArea.toFixed(2)
: '-'
}}
</span>
</template>
</el-table-column>
</el-table-column>
</el-table-column>
</el-table>
</div>
</template>
<script>
import { getTeamReportPageDet } from '@/api/core/monitoring/auto';
import * as XLSX from 'xlsx';
import FileSaver from 'file-saver';
export default {
components: {},
data() {
return {
tableData: [],
dataListLoading: false,
formConfig: [
{
// type: this.$auth.hasPermi('base:factory:export') ? 'button' : '',
type: 'button',
btnName: '导出',
name: 'export',
color: 'warning',
},
],
};
},
components: {},
created() {},
mounted() {},
methods: {
// 获取数据列表
init(id) {
this.dataListLoading = true;
getTeamReportPageDet(id).then((response) => {
this.tableData = response.data?.map((item, index) => {
item.originalLossNum = item.original?.lossNum;
item.originalLossArea = item.original?.lossArea;
item.edgeLossNum = item.edge?.lossNum;
item.edgeLossArea = item.edge?.lossArea;
item.drillLossNum = item.drill?.lossNum;
item.drillLossArea = item.drill?.lossArea;
item.coatingLossNum = item.coating?.lossNum;
item.coatingLossArea = item.coating?.lossArea;
item.silkLossNum = item.silk?.lossNum;
item.silkLossArea = item.silk?.lossArea;
item.temperingLossNum = item.tempering?.lossNum;
item.temperingLossArea = item.tempering?.lossArea;
item.packingLossNum = item.packing?.lossNum;
item.packingLossArea = item.packing?.lossArea;
if (item.isSummaryReport) {
item.lineName = '合计';
}
return item;
});
this.dataListLoading = false;
});
},
arraySpanMethod({ row, column, rowIndex, columnIndex }) {
if (row.isSummaryReport) {
if (columnIndex === 0) {
return [1, 3];
} else if (columnIndex === 1) {
return [0, 0];
} else if (columnIndex === 2) {
return [0, 0];
}
}
},
buttonClick(val) {
switch (val.btnName) {
case 'export':
this.handleExport();
break;
default:
console.log(val);
}
},
handleExport() {
let tables = document.querySelector('#detail').cloneNode(true);
let exportTable = XLSX.utils.table_to_book(tables);
var exportTableOut = XLSX.write(exportTable, {
bookType: 'xlsx',
bookSST: true,
type: 'array',
});
// sheetjs.xlsx为导出表格的标题名称
try {
FileSaver.saveAs(
new Blob([exportTableOut], {
type: 'application/octet-stream',
}),
'班组生产报表-详情.xlsx'
);
} catch (e) {
if (typeof console !== 'undefined') console.log(e, exportTableOut);
}
return exportTableOut;
},
},
};
</script>

View File

@@ -0,0 +1,546 @@
<!--
* @Author: Do not edit
* @Date: 2023-08-29 14:59:29
* @LastEditTime: 2025-02-25 14:26:04
* @LastEditors: zwq
* @Description:
-->
<template>
<div class="app-container">
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@headBtnClick="buttonClick" />
<base-table-s
v-if="showData.length"
class="right-aside"
v-loading="dataListLoading"
:table-props="tableProps"
:page="listQuery.pageNo"
:limit="listQuery.pageSize"
:table-data="showData">
<method-btn
v-if="showData.length"
slot="handleBtn"
:width="80"
label="操作"
:method-list="tableBtn"
@clickBtn="handleClick" />
</base-table-s>
<div v-else class="no-data-bg"></div>
<pagination
:limit.sync="listQuery.pageSize"
:page.sync="listQuery.pageNo"
:total="listQuery.total"
@pagination="getDataList" />
<base-dialog
:dialogTitle="addOrEditTitle"
:dialogVisible="addOrUpdateVisible"
@cancel="handleCancel"
@confirm="handleConfirm"
:before-close="handleCancel"
close-on-click-modal
top="0"
width="80%">
<gr-detail ref="grDetail" />
<slot name="footer">
<el-row slot="footer" type="flex" justify="end">
<el-col :span="24">
<el-button size="small" class="btnTextStyle" @click="handleCancel">
取消
</el-button>
</el-col>
</el-row>
</slot>
</base-dialog>
</div>
</template>
<script>
import grDetail from './gr-detail';
import { getTeamReportPage } from '@/api/core/monitoring/auto';
import { getFactoryPage } from '@/api/core/base/factory';
import { getGroupTeamPage } from '@/api/base/groupTeam';
// import codeFilter from '../../mixins/code-filter'
import * as XLSX from 'xlsx';
import FileSaver from 'file-saver';
import baseTableS from './baseTable.vue';
import { parseTime } from '@/filter/code-filter';
const tableProps = [
{
prop: 'reportType',
label: '报表类型',
fixed: true
},
{
prop: 'reportName',
label: '日期',
width: 180,
fixed: true
},
{
prop: 'factoryName',
label: '工厂',
fixed: true
},
{
prop: 'teamName',
label: '班组',
fixed: true
},
{
prop: 'inputN',
label: '投入',
align: 'center',
children: [
{
prop: 'inputNum',
label: '投入数量/片',
width:100
},
{
prop: 'inputArea',
label: '投入面积/m²',
width:100
},
],
},
{
prop: 'outputN',
label: '产出',
align: 'center',
children: [
{
prop: 'outputNum',
label: '产出数量/片',
width:100
},
{
prop: 'outputArea',
label: '产出面积/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
width:100
},
],
},
{
prop: 'lossN',
label: '不良',
align: 'center',
children: [
{
prop: 'lossNum',
label: '不良数量/片',
width:100
},
{
prop: 'lossArea',
label: '不良面积/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
width:100
},
],
},
{
prop: 'lossRatio',
label: '不良率/%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
width:100
},
{
prop: 'outputRatio',
label: '投入产出率/%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
width:110
},
{
prop: 'processingRatio',
label: '加工成品率/%',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
width:110
},
{
prop: 'lossD',
label: '不良详情',
align: 'center',
children: [
{
prop: 'original',
label: '原片',
align: 'center',
children: [
{
prop: 'originalLossNum',
label: '原片不良/片',
width:100
},
{
prop: 'originalLossArea',
label: '原片不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
width:100
},
],
},
{
prop: 'edge',
label: '磨边',
align: 'center',
children: [
{
prop: 'edgeLossNum',
label: '磨边不良/片',
width:100
},
{
prop: 'edgeLossArea',
label: '磨边不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
width:100
},
],
},
{
prop: 'drill',
label: '打孔',
align: 'center',
children: [
{
prop: 'drillLossNum',
label: '打孔不良/片',
width:100
},
{
prop: 'drillLossArea',
label: '打孔不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
width:100
},
],
},
{
prop: 'coating',
label: '镀膜',
align: 'center',
children: [
{
prop: 'coatingLossNum',
label: '镀膜不良/片',
width:100
},
{
prop: 'coatingLossArea',
label: '镀膜不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
width:100
},
],
},
{
prop: 'silk',
label: '丝印',
align: 'center',
children: [
{
prop: 'silkLossNum',
label: '丝印不良/片',
width:100
},
{
prop: 'silkLossArea',
label: '丝印不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
width:100
},
],
},
{
prop: 'tempering',
label: '钢化',
align: 'center',
children: [
{
prop: 'temperingLossNum',
label: '钢化不良/片',
width:100
},
{
prop: 'temperingLossArea',
label: '钢化不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
width:100
},
],
},
{
prop: 'packing',
label: '包装',
align: 'center',
children: [
{
prop: 'packingLossNum',
label: '包装不良/片',
width:100
},
{
prop: 'packingLossArea',
label: '包装不良/㎡',
filter: (val) => (val != null ? val.toFixed(2) : '-'),
width:100
},
],
},
],
},
];
export default {
components: {
baseTableS,
grDetail,
},
data() {
return {
urlOptions: {
getDataListURL: getTeamReportPage,
},
listQuery: {
reportType: 1,
pageSize: 10,
pageNo: 1,
total: 1,
},
fileName: '',
dataListLoading: false,
tableProps,
tableBtn: [
{
type: 'eq',
btnName: '详情',
},
].filter((v) => v),
showData: [],
tableData: [],
formConfig: [
{
type: 'select',
label: '工厂',
selectOptions: [],
param: 'factoryId',
},
{
type: 'select',
label: '班组',
selectOptions: [],
param: 'teamId',
},
{
type: 'select',
label: '报表类型',
selectOptions: [
{
id: 1,
name: '日',
},
{
id: 2,
name: '周',
},
{
id: 3,
name: '月',
},
{
id: 4,
name: '年',
},
],
defaultSelect: 1,
param: 'reportType',
},
{
type: 'datePicker',
label: '时间范围',
dateType: 'daterange',
format: 'yyyy-MM-dd',
valueFormat: 'timestamp',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeVal',
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary',
},
{
type: 'separate',
},
{
// type: this.$auth.hasPermi('base:factory:export') ? 'button' : '',
type: 'button',
btnName: '导出',
name: 'export',
color: 'warning',
},
],
addOrEditTitle: '',
addOrUpdateVisible: false,
};
},
created() {
// 获取当前时间
const now = new Date();
// 获取前一天的同一时间
const yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000);
// 设置为00:00:00
yesterday.setHours(0, 0, 0, 0);
// 设置为23:59:59
const end = new Date(yesterday.getTime());
end.setHours(23, 59, 59, 59);
this.listQuery.reportStartTime = [yesterday.getTime(),end.getTime()];
this.$nextTick(() => {
this.$refs.searchBarForm.formInline.timeVal = [yesterday.getTime(),end.getTime()];
});
this.getDataList();
this.getPdLineList();
},
methods: {
handleExport() {
let tables = document.querySelector('.el-table').cloneNode(true);
const fix = tables.querySelector('.el-table__fixed');
const fixRight = tables.querySelector('.el-table__fixed-right');
if (fix) {
tables.removeChild(tables.querySelector('.el-table__fixed'));
}
if (fixRight) {
tables.removeChild(tables.querySelector('.el-table__fixed-right'));
}
let exportTable = XLSX.utils.table_to_book(tables);
exportTable.Sheets.Sheet1.A1.v = '序号' //导出表格第一列表头为序号
var exportTableOut = XLSX.write(exportTable, {
bookType: 'xlsx',
bookSST: true,
type: 'array',
});
// sheetjs.xlsx为导出表格的标题名称
try {
FileSaver.saveAs(
new Blob([exportTableOut], {
type: 'application/octet-stream',
}),
this.fileName + '班组生产报表.xlsx'
);
} catch (e) {
if (typeof console !== 'undefined') console.log(e, exportTableOut);
}
return exportTableOut;
},
getPdLineList() {
const params = {
pageSize: 100,
pageNo: 1,
};
getGroupTeamPage(params).then((res) => {
this.formConfig[1].selectOptions = res.data.list || [];
});
getFactoryPage(params).then((res) => {
this.formConfig[0].selectOptions = res.data.list || [];
});
},
buttonClick(val) {
switch (val.btnName) {
case 'search':
this.listQuery.pageNo = 1;
this.listQuery.pageSize = 10;
this.listQuery.factoryId = val.factoryId || undefined;
this.listQuery.teamId = val.teamId || undefined;
this.listQuery.reportType = val.reportType || undefined;
this.listQuery.reportStartTime = val.timeVal
? val.timeVal
: undefined;
this.getDataList();
break;
case 'export':
this.handleExport();
break;
default:
console.log(val);
}
},
// 获取数据列表
getDataList() {
this.dataListLoading = true;
const arr = ['日', '周', '月', '年'];
this.urlOptions.getDataListURL(this.listQuery).then((response) => {
if (!response.data.list) {
this.showData = [];
this.dataListLoading = false;
return;
}
this.tableData = response.data?.list.map((item, index) => {
item.reportType = arr[item.reportType - 1];
item.originalLossNum = item.original?.lossNum;
item.originalLossArea = item.original?.lossArea;
item.edgeLossNum = item.edge?.lossNum;
item.edgeLossArea = item.edge?.lossArea;
item.drillLossNum = item.drill?.lossNum;
item.drillLossArea = item.drill?.lossArea;
item.coatingLossNum = item.coating?.lossNum;
item.coatingLossArea = item.coating?.lossArea;
item.silkLossNum = item.silk?.lossNum;
item.silkLossArea = item.silk?.lossArea;
item.temperingLossNum = item.tempering?.lossNum;
item.temperingLossArea = item.tempering?.lossArea;
item.packingLossNum = item.packing?.lossNum;
item.packingLossArea = item.packing?.lossArea;
return item;
});
this.listQuery.total = response.data?.total;
this.dataListLoading = false;
this.showData = this.tableData;
});
},
handleClick(val) {
this.addOrUpdateVisible = true;
const time = val.data.reportName?val.data.reportName:'- '
const teamName = val.data.teamName?val.data.teamName:'- '
const teamLeader = val.data.teamLeader?val.data.teamLeader:'- '
this.addOrEditTitle =
'时间:' +
time +
' 班组:' +
teamName +
' 组长:' +
teamLeader +
' 详情';
this.$nextTick(() => {
this.$refs.grDetail.init(val.data.id);
});
},
handleCancel() {
this.addOrUpdateVisible = false;
this.addOrEditTitle = '';
},
handleConfirm() {
this.handleCancel();
},
// 每页数
sizeChangeHandle(val) {
this.listQuery.pageSize = val;
this.listQuery.pageNo = 1;
this.getDataList();
},
// 当前页
currentChangeHandle(val) {
this.listQuery.pageNo = val;
this.getDataList();
},
},
};
</script>

View File

@@ -1,96 +1,144 @@
<template> <template>
<el-form ref="form" :rules="rules" label-width="80px" :model="form"> <el-form ref="form" :rules="rules" label-width="100px" :model="form">
<el-row> <el-row>
<el-col :span="12"> <el-col :span="12">
<el-form-item label="班组名称" prop="name"> <el-form-item label="工厂" prop="factoryId">
<el-input v-model="form.name"></el-input> <el-select
</el-form-item> v-model="form.factoryId"
</el-col> filterable
<el-col :span="12"> clearable
<el-form-item label="班组编码" prop="code"> style="width: 100%"
<el-input v-model="form.code" disabled></el-input> placeholder="请选择工厂">
</el-form-item> <el-option
</el-col> v-for="item in factoryArr"
</el-row> :key="item.id"
<el-row> :label="item.name"
<el-col :span="12"> :value="item.id"></el-option>
<el-form-item label="班组人数" prop="num"> </el-select>
<el-input-number v-model="form.num" :min="1" :max="99999999" style="width: 100%;"></el-input-number> </el-form-item>
</el-form-item> </el-col>
</el-col> <el-col :span="12">
<el-col :span="12"> <el-form-item label="班组名称" prop="name">
<el-form-item label="班组组长" prop="leaderName"> <el-input v-model="form.name"></el-input>
<el-input v-model="form.leaderName"></el-input> </el-form-item>
</el-form-item> </el-col>
</el-col> <el-col :span="12">
</el-row> <el-form-item label="班组编码" prop="code">
</el-form> <el-input v-model="form.code" disabled></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="班组组长" prop="leaderName">
<el-input v-model="form.leaderName" clearable></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="手机号" prop="leaderPhone">
<el-input v-model="form.leaderPhone" clearable></el-input>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="班组人数" prop="num">
<el-input-number
style="width: 100%"
v-model="form.num"
:step="1"
step-strictly></el-input-number>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template> </template>
<script> <script>
import { getGroupTeam, updateGroupTeam, createGroupTeam, getCode } from '@/api/base/groupTeam' import {
getGroupTeam,
updateGroupTeam,
createGroupTeam,
getCode,
} from '@/api/base/groupTeam';
import { getFactoryPage } from '@/api/core/base/factory';
export default { export default {
name: 'groupTeamAdd', name: 'groupTeamAdd',
data() { data() {
return { return {
form: { form: {
id: '', id: '',
name: '', factoryId: '',
code: '', name: '',
num: null, code: '',
leaderName: '' leaderName: '',
}, leaderPhone: '',
isEdit: false, //是否是编辑 num: '',
rules: { },
name: [{ required: true, message: '请输入班组名称', trigger: 'blur' }] factoryArr: [], //工厂
} isEdit: false, //是否是编辑
} rules: {
}, factoryId: [
methods: { { required: true, message: '请选择工厂', trigger: 'change' },
init(id) { ],
if (id) { name: [{ required: true, message: '请输入班组名称', trigger: 'blur' }],
this.isEdit = true code: [{ required: true, message: '请输入班组编码', trigger: 'blur' }],
this.form.id = id leaderName: [
getGroupTeam( id ).then((res) => { { required: true, message: '请输入组长', trigger: 'blur' },
if (res.code === 0) { ],
this.form = res.data },
} };
}) },
} else { created() {
this.isEdit = false const params = {
this.form.id = '' pageSize: 100,
getCode().then((res) => { pageNo: 1,
this.form.code = res.data };
}) getFactoryPage(params).then((res) => {
} this.factoryArr = res.data.list || [];
}, });
submitForm() { },
this.$refs['form'].validate((valid) => { methods: {
if (valid) { init(id) {
if (this.isEdit) { if (id) {
//编辑 this.isEdit = true;
updateGroupTeam({ ...this.form }).then((res) => { this.form.id = id;
if (res.code === 0) { getGroupTeam(id).then((res) => {
this.$modal.msgSuccess("操作成功"); if (res.code === 0) {
this.$emit('successSubmit') this.form = res.data;
} }
}) });
} else { } else {
createGroupTeam({ ...this.form }).then((res) => { this.isEdit = false;
if (res.code === 0) { this.form.id = '';
this.$modal.msgSuccess("操作成功"); getCode().then((res) => {
this.$emit('successSubmit') this.form.code = res.data;
} });
}) }
} },
} else { submitForm() {
return false this.$refs['form'].validate((valid) => {
} if (valid) {
}) if (this.isEdit) {
}, //编辑
formClear() { updateGroupTeam({ ...this.form }).then((res) => {
this.$refs.form.resetFields() if (res.code === 0) {
this.isEdit = false this.$modal.msgSuccess('操作成功');
} this.$emit('successSubmit');
} }
} });
} else {
createGroupTeam({ ...this.form }).then((res) => {
if (res.code === 0) {
this.$modal.msgSuccess('操作成功');
this.$emit('successSubmit');
}
});
}
} else {
return false;
}
});
},
formClear() {
this.$refs.form.resetFields();
this.isEdit = false;
},
},
};
</script> </script>

View File

@@ -1,3 +1,10 @@
<!--
* @Author: zwq
* @Date: 2024-07-01 14:53:55
* @LastEditors: zwq
* @LastEditTime: 2024-07-10 10:00:03
* @Description:
-->
<template> <template>
<el-switch v-model="state" type="text" size="small" :disabled="readonly" @change="changeHandler" /> <el-switch v-model="state" type="text" size="small" :disabled="readonly" @change="changeHandler" />
</template> </template>
@@ -12,8 +19,7 @@ export default {
}, },
data() { data() {
return { return {
state: false, state: false
payload: {}
} }
}, },
computed: { computed: {
@@ -31,9 +37,17 @@ export default {
} }
}, },
changeHandler() { changeHandler() {
this.payload.id = this.injectData.id let params = {}
this.payload.enabled = this.state ? '1' : '0' let payload = {}
this.$emit('emitData', this.payload) params.name = 'state'
payload.id = this.injectData.id
payload.enabled = this.state ? '1' : '0'
payload.code = this.injectData.code
payload.name = this.injectData.name
payload.factoryId = this.injectData.factoryId
payload.leaderName = this.injectData.leaderName
params.payload = payload
this.$emit('emitData', params)
} }
} }
} }

View File

@@ -0,0 +1,305 @@
<template>
<div>
<el-drawer :title="title" :visible.sync="visible" size="70%" @close='closeD' :show-close='false'>
<div class="box">
<el-row class="topBox">
<el-col :span="6">
<p class="boldTitle">班组名称</p>
<p class="lightText">{{ teamData.teamName }}</p>
</el-col>
<el-col :span="6">
<p class="boldTitle">班组长</p>
<p class="lightText">{{ teamData.leaderName }}</p>
</el-col>
<el-col :span="6">
<p class="boldTitle">班组人数</p>
<p class="lightText">{{ teamData.teamNum }}</p>
</el-col>
<el-col :span="6">
<p class="boldTitle">手机号</p>
<p class="lightText">{{ teamData.leaderTelephone }}</p>
</el-col>
</el-row>
<div class="bottomBox">
<!-- 搜索工作栏 -->
<search-bar
v-if="visible"
:formConfigs="formConfig"
@headBtnClick="buttonClick"
/>
<base-table
:page="queryParams.pageNo"
:limit="queryParams.pageSize"
:table-props="tableProps"
:table-data="tableData"
>
<method-btn
v-if="tableBtn.length"
slot="handleBtn"
:width="100"
label="操作"
:method-list="tableBtn"
@clickBtn="handleClick"
/>
</base-table>
<pagination
:page.sync="queryParams.pageNo"
:limit.sync="queryParams.pageSize"
:total="total"
@pagination="getList"
/>
</div>
</div>
</el-drawer>
<!-- 新增编辑组员 -->
<base-dialog
:dialogTitle="addOrEditTitle"
:dialogVisible="centervisible"
@cancel="handleCancel"
@confirm="handleConfirm"
:before-close="handleCancel"
width='40%'
>
<worker-team-add ref="workerTeamAdd" @successSubmit="successSubmit" />
</base-dialog>
</div>
</template>
<script>
const tableProps = [
{
prop: 'workerName',
label: '人员姓名'
},
{
prop: 'workerMajorName',
label: '专业'
},
{
prop: 'workerTelephone',
label: '手机'
},
{
prop: 'remark',
label: '备注'
}
]
import { groupTeamPage, teamDetDelete } from '@/api/base/groupTeam'
import { getWorker } from '@/api/base/worker'
import WorkerTeamAdd from './workerTeamAdd.vue'
export default {
name: 'WorkerEdit',
data() {
return {
visible: false,
title: '',
formConfig: [],
teamData: {
teamName: '',
leaderName: '',
teamNum: '',
leaderTelephone: '-',
teamId: ''
},
queryParams: {
pageNo: 1,
pageSize: 20,
teamId: '',
workerName: ''
},
tableProps,
tableData: [],
tableBtn: [],
total: 0,
// 弹出层标题
addOrEditTitle: "",
// 是否显示弹出层
centervisible: false
}
},
components: { WorkerTeamAdd },
created() {
},
methods: {
init(val) {
this.visible = true
this.teamData.teamName = val.payload.name
this.teamData.leaderName = val.payload.leaderName
this.teamData.teamNum = val.payload.num
this.teamData.teamId = val.payload.teamId
this.queryParams.teamId = val.payload.id
getWorker({id:val.payload.leaderId}).then(res => {// 获取组长手机号
this.teamData.leaderTelephone = res.data.telephone || '-'
})
this.getList()
if (val.name === 'view') {
this.title = '查看组员'
this.tableBtn = []
this.formConfig = [
{
type: 'input',
label: '关键字',
placeholder: '姓名',
param: 'workerName'
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary'
}
]
}else{
this.title = '编辑组员'
this.tableBtn = [
{
type: 'edit',
btnName: '编辑'
},
{
type: 'delete',
btnName: '删除'
}
]
this.formConfig = [
{
type: 'input',
label: '关键字',
placeholder: '姓名',
param: 'workerName'
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary'
},
{
type: 'separate'
},
{
type: 'button',
btnName: '新增',
name: 'add',
color: 'success',
plain: true
}
]
}
},
getList() {
groupTeamPage({ ...this.queryParams }).then(res => {
if (res.code === 0 && res.data.list && res.data.list.length > 0) {
let arr = []
res.data.list.map(item => {
let obj = {}
obj.workerName = item.worker.name
obj.workerMajorName = item.worker.majorName
obj.workerTelephone = item.worker.telephone
obj.remark = item.remark
obj.id = item.id
arr.push(obj)
})
this.tableData = arr
this.total = res.data.total
} else {
this.tableData = []
this.total = 0
}
})
},
buttonClick(val) {
console.log(val)
if (val.btnName === 'search') {
this.queryParams.workerName = val.workerName
this.queryParams.pageNo = 1
this.getList()
}else if (val.btnName === 'add') {
this.addNew()
}
},
// 新增
addNew() {
this.addOrEditTitle = '新增'
this.centervisible = true
this.$nextTick(() => {
this.$refs.workerTeamAdd.init({'teamId': this.queryParams.teamId, id: ''})
})
},
handleCancel() {
this.$refs.workerTeamAdd.formClear()
this.centervisible = false
this.addOrEditTitle = ''
},
handleConfirm() {
this.$refs.workerTeamAdd.submitForm()
},
successSubmit() {
this.handleCancel()
this.getList()
},
handleClick(val) {
console.log(val)
switch (val.type) {
case 'edit':
this.addOrEditTitle = '编辑'
this.centervisible = true
this.$nextTick(() => {
this.$refs.workerTeamAdd.init({'teamId': this.queryParams.teamId, 'id': val.data.id, 'workName':val.data.workerName, 'majorName':val.data.workerMajorName})
})
break
default:
this.handleDelete(val.data)
}
},
/** 删除按钮操作 */
handleDelete(row) {
console.log(row)
this.$modal.confirm('是否确认删除人员"' + row.workerName + '"的数据项?').then(function() {
return teamDetDelete({id: row.id});
}).then(() => {
this.queryParams.pageNo = 1;
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
},
closeD() {
this.teamData.teamName = ''
this.teamData.leaderName = ''
this.teamData.teamNum = ''
this.teamData.leaderTelephone = ''
this.teamData.teamId = ''
this.queryParams.pageNo = 1
this.queryParams.pageSize = 20
this.queryParams.teamId = ''
this.queryParams.workerName = ''
this.total = 0
this.$emit('closeDrawer')
}
}
}
</script>
<style lang='scss' scoped>
.box {
padding:0 30px;
.topBox {
padding-bottom: 30px;
border-bottom: 1px solid #E9E9E9;
.boldTitle {
font-size: 14px;
font-weight: 600;
color: rgba(0,0,0,0.85);
margin: 0;
margin-bottom: 10px;
}
.lightText {
font-size: 14px;
font-weight: 400;
color: rgba(102,102,102,0.75);
margin: 0;
}
}
.bottomBox {
padding-top: 30px;
}
}
</style>

View File

@@ -0,0 +1,41 @@
<template>
<div class="workerOperate">
<div class="operateBtn">
<span class="view" v-if="this.$auth.hasPermi('base:group-team:view-worker')" @click="emitParams('view')">查看</span>
<span class="edit" v-if="this.$auth.hasPermi('base:group-team:edit-worker')" @click="emitParams('edit')">编辑</span>
</div>
</div>
</template>
<script>
export default {
name: 'WorkerOperate',
props: {
injectData: {
type: Object,
default: () => ({})
}
},
methods: {
emitParams(data) {
let params = {}
params.name = data
params.payload = this.injectData
this.$emit('emitData', params)
}
}
}
</script>
<style lang='scss' scoped>
.workerOperate {
.operateBtn{
color: #0B58FF;
.view {
margin-right: 10px;
cursor: pointer;
}
.edit {
cursor: pointer;
}
}
}
</style>

View File

@@ -0,0 +1,121 @@
<template>
<el-form ref="form" :rules="rules" label-width="100px" :model="form">
<el-form-item label="员工" prop="workerId" v-if='!isEdit'>
<el-select v-model="form.workerId" placeholder="请选择" filterable style="width: 100%;" @change="selectWorker()">
<el-option
v-for="item in workerList"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="员工" prop="workerId" v-if='isEdit'>
<el-input v-model="workName" disabled></el-input>
</el-form-item>
<el-form-item label="专业" prop="majorName">
<el-input v-model="form.majorName" disabled></el-input>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark"></el-input>
</el-form-item>
</el-form>
</template>
<script>
import { otherWorkerList } from '@/api/base/worker'
import { teamDetCreate, teamDetUpdate, groupTeamDet } from '@/api/base/groupTeam'
export default {
name: 'WorkerTeamAdd',
data() {
return {
workerList: [],
form: {
teamId: '',
workerId: '',
remark: '',
majorName: '',
id: ''
},
isEdit: false,
workName: '',//编辑时用
rules: {
workerId: [{ required: true, message: '员工不能为空', trigger: 'change' }]
}
}
},
methods: {
init(param) {
this.form.teamId = param.teamId
this.form.majorName = param.majorName
this.workName = param.workName
otherWorkerList({teamId:this.form.teamId}).then(res => {
this.workerList = res.data || []
if (param.id) {
this.isEdit = true
this.form.id = param.id
groupTeamDet({id: this.form.id}).then((res) => {
if (res.code === 0) {
this.form.workerId = res.data.workerId
this.form.remark = res.data.remark
}
})
} else {
this.isEdit = false
this.form.id = ''
}
})
},
selectWorker() {
if (this.form.workerId) {
this.workerList.map(item => {
if (item.id === this.form.workerId) {
this.form.majorName = item.majorName
}
})
}else{
this.form.majorName = ''
}
},
// 确定
submitForm() {
this.$refs['form'].validate((valid) => {
if (valid) {
if (this.isEdit) {
// 编辑
teamDetUpdate({
teamId: this.form.teamId,
workerId: this.form.workerId,
remark: this.form.remark,
id: this.form.id
}).then((res) => {
if (res.code === 0) {
this.$modal.msgSuccess("操作成功");
this.$emit('successSubmit')
}
})
} else {
teamDetCreate({
teamId: this.form.teamId,
workerId: this.form.workerId,
remark: this.form.remark
}).then((res) => {
if (res.code === 0) {
this.$modal.msgSuccess("操作成功");
this.$emit('successSubmit')
}
})
}
} else {
return false
}
})
},
formClear() {
this.$refs.form.resetFields()
this.workName = ''
this.form.majorName = ''
this.isEdit = false
}
}
}
</script>

View File

@@ -1,225 +1,264 @@
<template> <template>
<div class="app-container"> <div class="app-container">
<!-- 搜索工作栏 -->
<!-- 搜索工作栏 --> <search-bar
<search-bar :formConfigs="formConfig"
:formConfigs="formConfig" ref="searchBarForm"
ref="searchBarForm" @headBtnClick="buttonClick" />
@headBtnClick="buttonClick" <!-- 列表 -->
/> <base-table
<!-- 列表 --> :page="queryParams.pageNo"
<base-table :limit="queryParams.pageSize"
:page="queryParams.pageNo" :table-props="tableProps"
:limit="queryParams.pageSize" :table-data="list"
:table-props="tableProps" :max-height="tableH"
:table-data="list" @emitFun="handleTableEvents">
:max-height="tableH" <method-btn
@emitFun="handleTableEvents" v-if="tableBtn.length"
> slot="handleBtn"
<method-btn :width="80"
v-if="tableBtn.length" label="操作"
slot="handleBtn" :method-list="tableBtn"
:width="80" @clickBtn="handleClick" />
label="操作" </base-table>
:method-list="tableBtn" <pagination
@clickBtn="handleClick" :page.sync="queryParams.pageNo"
/> :limit.sync="queryParams.pageSize"
</base-table> :total="total"
<pagination @pagination="getList" />
:page.sync="queryParams.pageNo" <!-- 新增 -->
:limit.sync="queryParams.pageSize" <base-dialog
:total="total" :dialogTitle="addOrEditTitle"
@pagination="getList" :dialogVisible="centervisible"
/> @cancel="handleCancel"
<!-- 新增 --> @confirm="handleConfirm"
<base-dialog :before-close="handleCancel"
:dialogTitle="addOrEditTitle" width="40%">
:dialogVisible="centervisible" <group-team-add ref="groupList" @successSubmit="successSubmit" />
@cancel="handleCancel" </base-dialog>
@confirm="handleConfirm" </div>
:before-close="handleCancel"
>
<group-team-add ref="groupList" @successSubmit="successSubmit" />
</base-dialog>
</div>
</template> </template>
<script> <script>
import { getGroupTeamPage, deleteGroupTeam, updateGroupTeam } from "@/api/base/groupTeam"; import {
import { parseTime } from '@/utils/ruoyi' getGroupTeamPage,
import GroupTeamAdd from './components/groupTeamAdd.vue' deleteGroupTeam,
import StatusBtn from './components/statusBtn.vue' updateGroupTeam,
} from '@/api/base/groupTeam';
import { parseTime } from '@/utils/ruoyi';
import GroupTeamAdd from './components/groupTeamAdd';
import StatusBtn from './components/statusBtn';
import tableHeightMixin from '@/mixins/tableHeightMixin';
import { getFactoryPage } from '@/api/core/base/factory';
const tableProps = [ const tableProps = [
{ {
prop: 'createTime', prop: 'createTime',
label: '创建时间', label: '创建时间',
filter: parseTime, filter: parseTime,
minWidth: 150 minWidth: 160,
}, },
{ {
prop: 'name', prop: 'factoryName',
label: '班组名称' label: '工厂',
}, },
{ {
prop: 'code', prop: 'name',
label: '班组编码', label: '班组名称',
minWidth: 220 },
}, {
{ prop: 'code',
prop: 'num', label: '编码',
label: '班组人数' minWidth: 220,
}, },
{ {
prop: 'leaderName', prop: 'num',
label: '班组组长' label: '班组人数',
}, },
{ {
prop: 'enabled', prop: 'leaderName',
label: '班组状态', label: '组长',
subcomponent: StatusBtn },
} {
] prop: 'enabled',
label: '班组状态',
subcomponent: StatusBtn,
},
];
export default { export default {
name: "GroupTeam", name: 'GroupTeam',
components: { GroupTeamAdd }, components: { GroupTeamAdd },
data() { mixins: [tableHeightMixin],
return { data() {
formConfig: [ return {
{ formConfig: [
type: 'input', {
label: '班组名称', type: 'select',
placeholder: '班组名称', label: '工厂',
param: 'name' selectOptions: [],
}, param: 'factoryId',
{ onchange: true,
type: 'input', },
label: '班组编码', {
placeholder: '班组编码', type: 'input',
param: 'code' label: '班组名称',
}, placeholder: '班组名称',
{ param: 'name',
type: 'button', },
btnName: '查询', {
name: 'search', type: 'input',
color: 'primary' label: '组长',
}, placeholder: '组长',
{ param: 'leaderName',
type: 'separate' },
}, {
{ type: 'button',
type: this.$auth.hasPermi('base:group-team:create') ? 'button' : '', btnName: '查询',
btnName: '新增', name: 'search',
name: 'add', color: 'primary',
color: 'success', },
plain: true {
} type: 'separate',
], },
tableProps, {
tableBtn: [ type: this.$auth.hasPermi('base:group-team:create') ? 'button' : '',
this.$auth.hasPermi('base:group-team:update') btnName: '新增',
? { name: 'add',
type: 'edit', color: 'success',
btnName: '编辑' plain: true,
} },
: undefined, ],
this.$auth.hasPermi('base:group-team:delete') tableProps,
? { tableBtn: [
type: 'delete', this.$auth.hasPermi('base:group-team:update')
btnName: '删除' ? {
} type: 'edit',
: undefined btnName: '编辑',
].filter((v) => v), }
tableH: this.tableHeight(260), : undefined,
// 总条数 this.$auth.hasPermi('base:group-team:delete')
total: 0, ? {
// 班次基础信息列表 type: 'delete',
list: [], btnName: '删除',
// 弹出层标题 }
addOrEditTitle: "", : undefined,
// 是否显示弹出层 ].filter((v) => v),
centervisible: false, // 总条数
// 查询参数 total: 0,
queryParams: { // 班次基础信息列表
pageNo: 1, list: [],
pageSize: 20, // 弹出层标题
name: null, addOrEditTitle: '',
code: null // 是否显示弹出层
} centervisible: false,
}; // 查询参数
}, queryParams: {
created() { pageNo: 1,
window.addEventListener('resize', () => { pageSize: 20,
this.tableH = this.tableHeight(260) name: null,
}) code: null,
this.getList(); },
}, };
methods: { },
buttonClick(val) { created() {
switch (val.btnName) { this.getList();
case 'search': this.getPdLineList();
this.queryParams.pageNo = 1; },
this.queryParams.name = val.name methods: {
this.queryParams.code = val.code getPdLineList() {
this.getList() const params = {
break pageSize: 100,
default: pageNo: 1,
this.addOrEditTitle = '新增' };
this.centervisible = true getFactoryPage(params).then((res) => {
this.$nextTick(() => { this.formConfig[0].selectOptions = res.data.list || [];
this.$refs.groupList.init() });
}) },
} buttonClick(val) {
}, switch (val.btnName) {
/** 查询列表 */ case 'search':
getList() { this.queryParams.pageNo = 1;
getGroupTeamPage(this.queryParams).then(response => { this.queryParams.leaderName = val.leaderName;
this.list = response.data.list; this.queryParams.factoryId = val.factoryId || undefined;
this.total = response.data.total; this.queryParams.name = val.name;
}); this.getList();
}, break;
handleClick(val) { default:
switch (val.type) { this.addOrEditTitle = '新增';
case 'edit': this.centervisible = true;
this.addOrEditTitle = '编辑' this.$nextTick(() => {
this.$nextTick(() => { this.$refs.groupList.init();
this.$refs.groupList.init(val.data.id) });
}) }
this.centervisible = true },
break /** 查询列表 */
default: getList() {
this.handleDelete(val.data) getGroupTeamPage(this.queryParams).then((response) => {
} this.list = response.data.list;
}, this.total = response.data.total;
// 班组状态 });
handleTableEvents(data) { },
updateGroupTeam({ ...data }).then((res) => { handleClick(val) {
if (res.code === 0) { switch (val.type) {
this.$modal.msgSuccess("操作成功"); case 'edit':
} this.addOrEditTitle = '编辑';
this.$nextTick(() => {
this.$refs.groupList.init(val.data.id);
});
this.centervisible = true;
break;
default:
this.handleDelete(val.data);
}
},
// 班组状态
handleTableEvents(params) {
if (params.name === 'state') {
// 班组状态
updateGroupTeam({ ...params.payload })
.then((res) => {
if (res.code === 0) {
this.$modal.msgSuccess('操作成功');
this.getList();
}
})
.catch((res) => {
this.getList();
});
}
},
handleCancel() {
this.$refs.groupList.formClear();
this.centervisible = false;
this.addOrEditTitle = '';
},
handleConfirm() {
this.$refs.groupList.submitForm();
},
successSubmit() {
this.handleCancel();
this.getList();
},
/** 删除按钮操作 */
handleDelete(row) {
this.$confirm(`是否确认删除 ${row.name} 的数据项?`, "系统提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
}) })
}, .then(function () {
handleCancel() { return deleteGroupTeam(row.id);
this.$refs.groupList.formClear() })
this.centervisible = false .then(() => {
this.addOrEditTitle = '' this.queryParams.pageNo = 1;
}, this.getList();
handleConfirm() { this.$modal.msgSuccess('删除成功');
this.$refs.groupList.submitForm() })
}, .catch(() => {});
successSubmit() { },
this.handleCancel() closeDrawer() {
this.getList() this.getList();
}, },
/** 删除按钮操作 */ },
handleDelete(row) {
this.$modal.confirm('是否确认删除班组名称为"' + row.name + '"的数据项?').then(function() {
return deleteGroupTeam(row.id);
}).then(() => {
this.queryParams.pageNo = 1;
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
}
}
}; };
</script> </script>

View File

@@ -95,7 +95,8 @@ export default {
type: this.$auth.hasPermi('base:group-team:create') ? 'button' : '', type: this.$auth.hasPermi('base:group-team:create') ? 'button' : '',
btnName: '导出', btnName: '导出',
name: 'export', name: 'export',
color: 'warning', color: 'success',
plain: true
} }
], ],
tableProps, tableProps,
@@ -143,4 +144,4 @@ export default {
.box { .box {
padding: 0 32px; padding: 0 32px;
} }
</style> </style>

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,213 @@
<!--
* @Author: zwq
* @Date: 2025-01-15 11:20:41
* @LastEditors: zwq
* @LastEditTime: 2025-02-25 09:37:50
* @Description:
-->
<template>
<div class="app-container">
<!-- 搜索工作栏 -->
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@headBtnClick="buttonClick" />
<!-- 列表 -->
<base-table
:page="queryParams.pageNo"
:limit="queryParams.pageSize"
:table-props="tableProps"
:table-data="list"
:max-height="tableH">
</base-table>
<pagination
:page.sync="queryParams.pageNo"
:limit.sync="queryParams.pageSize"
:total="total"
@pagination="getList" />
</div>
</template>
<script>
import { parseTime } from '@/utils/ruoyi';
import tableHeightMixin from '@/mixins/tableHeightMixin';
import { schedulingPage,exportSchedulingExcel } from '@/api/base/groupTeamScheduling';
import { getFactoryPage } from '@/api/core/base/factory';
import {
getGroupClassesPage,
} from '@/api/base/groupClasses';
import {
getGroupTeamPage,
} from '@/api/base/groupTeam';
import * as XLSX from 'xlsx';
import FileSaver from 'file-saver';
const tableProps = [
{
prop: 'factoryName',
label: '工厂',
},
{
prop: 'startDay',
label: '上班日期',
filter: (val) => (val ? parseTime(val, '{y}-{m}-{d}') : '-'),
},
{
prop: 'startTime',
label: '上班时间',
filter: (val) => (val ? parseTime(val, '{h}:{i}') : '-'),
width: 100,
},
{
prop: 'endTime',
label: '下班时间',
filter: (val) => (val ? parseTime(val, '{h}:{i}') : '-'),
width: 100,
},
{
prop: 'classesName',
label: '班次名称',
},
{
prop: 'teamName',
label: '班组名称',
},
];
export default {
mixins: [tableHeightMixin],
data() {
return {
formConfig: [
{
type: 'select',
label: '工厂',
selectOptions: [],
param: 'factoryId',
onchange: true,
},
{
type: 'select',
label: '班次',
selectOptions: [],
param: 'classesId',
},
{
type: 'select',
label: '班组',
selectOptions: [],
param: 'teamId',
},
{
type: 'datePicker',
label: '上班日期',
dateType: 'daterange',
format: 'yyyy-MM-dd',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeVal',
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary',
},
{
type: 'separate',
},
{
// type: this.$auth.hasPermi('base:factory:export') ? 'button' : '',
type: 'button',
btnName: '导出',
name: 'export',
color: 'warning',
},
],
tableProps,
// 总条数
total: 0,
// 班次基础信息列表
list: [],
// 弹出层标题
addOrEditTitle: '',
// 是否显示弹出层
centervisible: false,
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 20,
},
};
},
created() {
this.getList();
this.getPdLineList();
},
methods: {
/** 导出按钮操作 */
handleExport() {
// 处理查询参数
let params = { ...this.queryParams };
params.pageNo = undefined;
params.pageSize = undefined;
this.$modal.confirm('是否确认导出所有数据项?').then(() => {
this.exportLoading = true;
return exportSchedulingExcel(params);
}).then(response => {
this.$download.excel(response, '上班记录报表.xls');
this.exportLoading = false;
}).catch(() => { });
},
getPdLineList() {
const params = {
pageSize: 100,
pageNo: 1,
};
getGroupClassesPage(params).then((res) => {
this.formConfig[1].selectOptions = res.data.list || [];
});
getGroupTeamPage(params).then((res) => {
this.formConfig[2].selectOptions = res.data.list || [];
});
getFactoryPage(params).then((res) => {
this.formConfig[0].selectOptions = res.data.list || [];
});
},
buttonClick(val) {
switch (val.btnName) {
case 'search':
this.queryParams.pageNo = 1;
this.queryParams.factoryId = val.factoryId || undefined;
this.queryParams.classesId = val.classesId || undefined;
this.queryParams.teamName = val.teamId || undefined;
this.queryParams.startDay = val.timeVal
? val.timeVal
: undefined;
this.getList();
break;
case 'export':
this.queryParams.pageNo = 1;
this.queryParams.factoryId = val.factoryId || undefined;
this.queryParams.classesId = val.classesId || undefined;
this.queryParams.teamName = val.teamId || undefined;
this.queryParams.startDay = val.timeVal
? val.timeVal
: undefined;
this.handleExport();
break;
default:
console.log(val);
}
},
/** 查询列表 */
getList() {
schedulingPage(this.queryParams).then((response) => {
this.list = response.data.list;
this.total = response.data.total;
});
},
},
};
</script>

View File

@@ -0,0 +1,240 @@
<!--
* @Author: zwq
* @Date: 2024-07-10 13:43:41
* @LastEditors: zwq
* @LastEditTime: 2025-01-14 11:06:24
* @Description:
-->
<template>
<el-form ref="form" :rules="rules" label-width="110px" :model="form">
<el-row>
<el-col :span="12">
<el-form-item label="工厂" prop="factoryId">
<el-select
v-model="form.factoryId"
filterable
clearable
style="width: 100%"
placeholder="请选择工厂">
<el-option
v-for="item in factoryArr"
:key="item.id"
:label="item.name"
:value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="计划名称" prop="name">
<el-input v-model="form.name" clearable />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="相关班组" prop="teamIdList">
<el-select
v-model="form.teamIdList"
filterable
clearable
multiple
style="width: 100%"
placeholder="请选择班组">
<el-option
v-for="item in teamList"
:key="item.id"
:label="item.name"
:value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="相关班次" prop="classesIdList">
<el-select
v-model="form.classesIdList"
filterable
clearable
multiple
style="width: 100%"
placeholder="请选择班次">
<el-option
v-for="item in classList"
:key="item.id"
:label="item.name"
:value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark"></el-input>
</el-form-item>
</el-col>
<el-col :span="12" v-if="false">
<el-form-item label="是否生产班组" prop="isProduction">
<el-radio-group v-model="form.isProduction">
<el-radio :label="true"></el-radio>
<el-radio :label="false"></el-radio>
</el-radio-group>
</el-form-item>
</el-col>
<el-col :span="24" v-show="form.isProduction">
<tree-transfer
:title="title"
:from_data="fromData"
:to_data="toData"
@add-btn="add"
@remove-btn="remove"
pid="productionLineId"
:defaultProps="{ label: 'name' }"
height="450px"
:mode="mode"
filter
openAll></tree-transfer>
</el-col>
</el-row>
</el-form>
</template>
<script>
import {
getGroupPlan,
updateGroupPlan,
createGroupPlan,
getGroupPlanTree,
createGroupPlanLine,
updateGroupPlanLine,
getGroupPlanLine,
getLoginUserDeptId,
} from '@/api/base/groupSchedulingPlan';
import { getFactoryPage } from '@/api/core/base/factory';
import { listDept } from '@/api/system/dept';
import { listEnabled } from '@/api/base/groupTeam';
import { listClassesEnabled } from '@/api/base/groupClasses';
import treeTransfer from 'el-tree-transfer';
export default {
components: { treeTransfer },
name: '',
data() {
return {
form: {
id: '',
name: '',
factoryId: '',
teamIdList: [],
classesIdList: [],
remark: '',
},
factoryArr: [], //工厂
teamList: [], //班组
classList: [], //班次
rules: {
name: [{ required: true, message: '请输入计划名称', trigger: 'blur' }],
factoryId: [
{ required: true, message: '请选择工厂', trigger: 'change' },
],
teamIdList: [
{ required: true, message: '请选择相关班组', trigger: 'change' },
],
classesIdList: [
{ required: true, message: '请选择相关班次', trigger: 'change' },
],
},
title: ['待选', '已选'], //标题 类型Array 必填false 默认:["源列表", "目标列表"]
mode: 'transfer',
fromData: [], //左边内容
toData: [], //右边已选内容
};
},
methods: {
init(id) {
this.form.id = id || undefined;
this.fromData = [];
this.toData = [];
this.getArr();
this.$nextTick(() => {
this.$refs['form'].resetFields();
if (this.form.id) {
getGroupPlan(id).then((response) => {
this.form = response.data;
});
}
});
},
getArr() {
const params = {
pageSize: 100,
pageNo: 1,
};
getFactoryPage(params).then((res) => {
this.factoryArr = res.data.list || [];
});
listEnabled().then((res) => {
this.teamList = res.data || [];
});
listClassesEnabled().then((res) => {
this.classList = res.data || [];
});
getGroupPlanTree().then((res) => {
this.fromData = res.data;
this.fromData.forEach((item) => {
item.productionLineId = 0;
});
});
},
// 监听穿梭框组件添加
add(fromData, toData, obj) {
console.log('fromData:', fromData);
console.log('toData:', toData);
},
// 监听穿梭框组件移除
remove(fromData, toData, obj) {
console.log('fromData:', fromData);
console.log('toData:', toData);
},
submitForm() {
this.$refs['form'].validate((valid) => {
if (valid) {
if (this.form.id) {
//编辑
updateGroupPlan({ ...this.form }).then((res) => {
if (res.code === 0) {
this.$modal.msgSuccess('操作成功');
this.$emit('successSubmit');
}
});
} else {
createGroupPlan({ ...this.form }).then((res) => {
if (res.code === 0) {
this.$modal.msgSuccess('操作成功');
this.$emit('successSubmit');
}
});
}
} else {
return false;
}
});
},
formClear() {
this.$refs.form.resetFields();
},
/** 消除组件左边与右边选中数据相同项 */
// 处理过滤数据
getFilterLeftData(data, selData) {
for (let i = data.length - 1; i >= 0; i--) {
for (let j = selData.length - 1; j >= 0; j--) {
if (data[i] && data[i].id === selData[j].id) {
// 当id相等可以删除的情况 即:没有子级可以删除;
if (!data[i].children) {
data.splice(i, 1);
} else {
this.getFilterLeftData(data[i].children, selData[j].children);
}
}
}
}
},
},
};
</script>

View File

@@ -0,0 +1,230 @@
<!--
* @Author: zwq
* @Date: 2024-07-10 11:08:48
* @LastEditors: zwq
* @LastEditTime: 2025-01-14 13:28:40
* @Description:
-->
<template>
<div class="app-container">
<!-- 搜索工作栏 -->
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@headBtnClick="buttonClick" />
<!-- 列表 -->
<base-table
:page="queryParams.pageNo"
:limit="queryParams.pageSize"
:table-props="tableProps"
:table-data="list"
:max-height="tableH">
<method-btn
v-if="tableBtn.length"
slot="handleBtn"
:width="120"
label="操作"
:method-list="tableBtn"
@clickBtn="handleClick" />
</base-table>
<pagination
:page.sync="queryParams.pageNo"
:limit.sync="queryParams.pageSize"
:total="total"
@pagination="getList" />
<!-- 新增 -->
<base-dialog
:dialogTitle="addOrEditTitle"
:dialogVisible="centervisible"
@cancel="handleCancel"
@confirm="handleConfirm"
:before-close="handleCancel"
width="50%">
<schedulingPlanConfigAdd ref="classList" @successSubmit="successSubmit" />
</base-dialog>
</div>
</template>
<script>
import {
getGroupPlanPage,
deleteGroupPlan,
} from '@/api/base/groupSchedulingPlan';
import schedulingPlanConfigAdd from './components/schedulingPlanConfigAdd.vue';
import tableHeightMixin from '@/mixins/tableHeightMixin';
import { getFactoryPage } from '@/api/core/base/factory';
const tableProps = [
{
prop: 'factoryName',
label: '工厂',
},
{
prop: 'name',
label: '计划名称',
},
{
prop: 'teamName',
label: '班组名称',
},
{
prop: 'classesName',
label: '班次名称',
},
];
export default {
name: 'schedulingPlanConfig',
components: { schedulingPlanConfigAdd },
mixins: [tableHeightMixin],
data() {
return {
formConfig: [
{
type: 'select',
label: '工厂',
selectOptions: [],
param: 'factoryId',
onchange: true,
},
{
type: 'input',
label: '计划名称',
placeholder: '计划名称',
param: 'name',
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary',
},
{
type: 'separate',
},
{
type: this.$auth.hasPermi('base:group-scheduling-plan:create')
? 'button'
: '',
btnName: '新增',
name: 'add',
color: 'success',
plain: true,
},
],
tableProps,
tableBtn: [
this.$auth.hasPermi('base:group-scheduling-plan:update')
? {
type: 'edit',
btnName: '编辑',
}
: undefined,
this.$auth.hasPermi('base:group-scheduling-plan:delete')
? {
type: 'delete',
btnName: '删除',
}
: undefined,
].filter((v) => v),
// 总条数
total: 0,
// 列表
list: [],
// 弹出层标题
addOrEditTitle: '',
// 是否显示弹出层
centervisible: false,
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 20,
name: null,
},
};
},
created() {
this.getList();
this.getPdLineList();
},
methods: {
getPdLineList() {
const params = {
pageSize: 100,
pageNo: 1,
};
getFactoryPage(params).then((res) => {
this.formConfig[0].selectOptions = res.data.list || [];
});
},
buttonClick(val) {
switch (val.btnName) {
case 'search':
this.queryParams.pageNo = 1;
this.queryParams.name = val.name || undefined;
this.queryParams.factoryId = val.factoryId || undefined;
this.getList();
break;
default:
this.addOrEditTitle = '新增';
this.centervisible = true;
this.$nextTick(() => {
this.$refs.classList.init();
});
}
},
/** 查询列表 */
getList() {
getGroupPlanPage(this.queryParams).then((res) => {
if (res.code === 0 && res.data.list && res.data.list.length > 0) {
this.list = res.data.list;
this.total = res.data.total;
} else {
this.list = [];
this.total = 0;
}
});
},
handleClick(val) {
switch (val.type) {
case 'edit':
this.addOrEditTitle = '编辑';
this.$nextTick(() => {
this.$refs.classList.init(val.data.id);
});
this.centervisible = true;
break;
default:
this.handleDelete(val.data);
}
},
handleCancel() {
this.$refs.classList.formClear();
this.centervisible = false;
this.addOrEditTitle = '';
},
handleConfirm() {
this.$refs.classList.submitForm();
},
successSubmit() {
this.handleCancel();
this.getList();
},
/** 删除按钮操作 */
handleDelete(row) {
let _this = this;
this.$confirm(`是否确认删除 ${row.name} 的数据项?`, "系统提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
return deleteGroupPlan(row.id);
})
.then(() => {
_this.getList();
_this.$modal.msgSuccess('删除成功');
})
.catch(() => {});
},
},
};
</script>

View File

@@ -0,0 +1,340 @@
<!--
* @Author: zwq
* @Date: 2024-07-11 09:30:21
* @LastEditors: zwq
* @LastEditTime: 2025-01-14 15:35:03
* @Description:
-->
<template>
<el-form ref="form" :rules="rules" label-width="110px" :model="form">
<el-row>
<el-col :span="12">
<el-form-item label="工厂" prop="factoryId">
<el-select
v-model="form.factoryId"
filterable
clearable
style="width: 100%"
placeholder="请选择工厂">
<el-option
v-for="item in factoryArr"
:key="item.id"
:label="item.name"
:value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="排班开始日期" prop="startDay">
<el-date-picker
v-model="form.startDay"
type="datetime"
placeholder="选择日期时间"
label-format="yyyy-MM-dd HH:mm:ss"
value-format="timestamp"
style="width: 100%"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="排班结束日期" prop="endDay">
<el-date-picker
v-model="form.endDay"
type="datetime"
placeholder="选择日期时间"
label-format="yyyy-MM-dd HH:mm:ss"
value-format="timestamp"
style="width: 100%"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="排班计划" prop="planId">
<el-select
v-model="form.planId"
filterable
clearable
@change="setTableArr"
style="width: 100%"
placeholder="请选择排班计划">
<el-option
v-for="item in planArr"
:key="item.id"
:label="item.name"
:value="item.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24">
<div class="min-title">班组上班顺序</div>
</el-col>
<el-col :span="12">
<el-form-item prop="groupTeamNum">
<el-input-number
v-model="form.groupTeamNum"
:step="1"
:min="1"
step-strictly></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-select
v-model="teamList"
clearable
style="width: 100%; display: inline-block; margin-bottom: 28px"
@change="teamRuleMore"
@visible-change="teamRuleLess"
multiple
placeholder="请选择班组">
<el-option
v-for="item in teamArr"
:key="item.id"
:label="item.name"
:value="item.id">
<span slot="default" style="width: 100%">
{{ item.name }}
<span v-if="teamList.includes(item.id)" style="float: right">
{{ teamList.findIndex((v) => v === item.id) + 1 }}
</span>
</span>
</el-option>
</el-select>
</el-col>
<el-col :span="12">
<el-form-item prop="groupClassesNum">
<el-input-number
v-model="form.groupClassesNum"
:step="1"
:min="1"
step-strictly></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-select
v-model="classesList"
clearable
style="width: 100%; display: inline-block; margin-bottom: 28px"
@change="classesRuleMore"
@visible-change="classesRuleLess"
multiple
placeholder="请选择班次">
<el-option
v-for="item in classesArr"
:key="item.id"
:label="item.name"
:value="item.id">
<span slot="default" style="width: 100%">
{{ item.name }}
<span v-if="classesList.includes(item.id)" style="float: right">
{{ classesList.findIndex((v) => v === item.id) + 1 }}
</span>
</span>
</el-option>
</el-select>
</el-col>
<el-col :span="12">
<el-form-item label="备注" prop="remark">
<el-input v-model="form.remark"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
import {
getGroupRule,
updateGroupRule,
createGroupRule,
} from '@/api/base/groupSchedulingRule';
import {
groupPlanList,
groupPlanTeamList,
groupPlanClassesList,
} from '@/api/base/groupSchedulingPlan';
import { getFactoryPage } from '@/api/core/base/factory';
import tableSelect from './tableSelect';
export default {
name: 'schedulingRuleConfigAdd',
data() {
return {
form: {
id: '',
factoryId: '',
startDay: '',
endDay: '',
planId: '',
groupTeamNum: 1,
groupClassesNum: 1,
groupClassesList: [],
groupTeamList: [],
remark: '',
},
factoryArr: [], //工厂
planArr: [], //排班计划数组
classesArr: [],
teamArr: [],
classesList: [],
teamList: [],
rules: {
factoryId: [
{ required: true, message: '请选择工厂', trigger: 'change' },
],
startDay: [
{ required: true, message: '请选择排班开始时间', trigger: 'change' },
],
endDay: [
{ required: true, message: '请选择排班结束时间', trigger: 'change' },
],
planId: [
{ required: true, message: '请选择排班计划', trigger: 'change' },
],
},
};
},
methods: {
init(id) {
this.form = {
id: id || undefined,
factoryId: '',
startDay: '',
endDay: '',
planId: '',
groupClassesList: [],
groupTeamList: [],
remark: '',
};
this.classesList = [];
this.teamList = [];
this.getArr();
this.$nextTick(() => {
this.$refs['form'].resetFields();
if (this.form.id) {
getGroupRule(id).then((response) => {
this.form = response.data;
response.data.teamSequenceList.forEach(item=>{
this.teamList.push(item.teamId)
})
response.data.classesSequenceList.forEach(item=>{
this.classesList.push(item.classesId)
})
this.form.groupTeamNum = response.data.teamSequenceList.length
this.form.groupClassesNum = response.data.classesSequenceList.length
this.getTableArr(response.data.planId);
});
}
});
},
getArr() {
const params = {
pageSize: 100,
pageNo: 1,
};
getFactoryPage(params).then((res) => {
this.factoryArr = res.data.list || [];
});
groupPlanList().then((res) => {
this.planArr = res.data || [];
});
},
setTableArr() {
if (this.form.planId) {
this.getTableArr(this.form.planId);
}
},
async getTableArr(id) {
//获取下拉框
const res0 = await groupPlanClassesList(id);
this.classesArr = res0.data || [];
const res1 = await groupPlanTeamList(id);
this.teamArr = res1.data || [];
},
teamRuleMore() {
if (this.teamList.length > this.form.groupTeamNum) {
this.$message('选择班组数 超过 排班数');
}
},
teamRuleLess(val) {
if (val === false) {
if (this.teamList.length < this.form.groupTeamNum) {
this.$message('选择班组数 小于 排班数');
}
}
},
classesRuleMore() {
if (this.classesList.length > this.form.groupClassesNum) {
this.$message('选择班次数 超过 倒班数');
}
},
classesRuleLess(val) {
if (val === false) {
if (this.classesList.length < this.form.groupClassesNum) {
this.$message('选择班组数 小于 倒班数');
}
}
},
submitForm() {
this.$refs['form'].validate((valid) => {
if (valid) {
if (this.teamList.length > this.form.groupTeamNum) {
this.$message('选择班组数 超过 排班数');
return
} else if (this.teamList.length < this.form.groupTeamNum) {
this.$message('选择班组数 小于 排班数');
return
}
if (this.classesList.length > this.form.groupClassesNum) {
this.$message('选择班次数 超过 倒班数');
return
} else if (this.classesList.length < this.form.groupClassesNum) {
this.$message('选择班组数 小于 倒班数');
return
}
this.form.groupTeamList = []
this.teamList.forEach((item,index)=>{
this.form.groupTeamList.push({
teamId: item,
sequence:index+1
})
})
this.form.groupClassesList = []
this.classesList.forEach((item,index)=>{
this.form.groupClassesList.push({
classesId: item,
sequence:index+1
})
})
if (this.form.id) {
//编辑
updateGroupRule({ ...this.form }).then((res) => {
this.$modal.msgSuccess('操作成功');
this.$emit('successSubmit');
});
} else {
createGroupRule({ ...this.form }).then((res) => {
this.$modal.msgSuccess('操作成功');
this.$emit('successSubmit');
});
}
} else {
return false;
}
});
},
formClear() {
this.$refs.form.resetFields();
},
},
};
</script>
<style scoped>
.min-title {
margin-bottom: 5px;
}
.min-title::before {
content: '*';
color: #ff5454;
margin-right: 4px;
}
</style>

View File

@@ -0,0 +1,44 @@
<template>
<div class="tableInner">
<el-select :key="itemProp+list._pageIndex" v-model="list[itemProp]" @change="changeInput">
<el-option
v-for="item in itemProp==='classesId'?list.classesArr:list.teamArr"
:key="item.id"
:label="item.name"
:value="item.id"></el-option>
</el-select>
</div>
</template>
<script>
export default {
name: 'tableSelect',
props: {
injectData: {
type: Object,
default: () => ({}),
},
itemProp: {
type: String,
},
},
data() {
return {
list: this.injectData,
};
},
methods: {
changeInput() {
this.$emit('emitData', this.list);
},
},
};
</script>
<style scoped>
.tableInner >>> .el-input__inner {
color: #409EFF;
border: 1px rgb(232, 231, 231) solid;
padding: 0;
text-align: center;
height: 30px;
}
</style>

View File

@@ -0,0 +1,284 @@
<template>
<div class="app-container">
<!-- 搜索工作栏 -->
<search-bar
:formConfigs="formConfig"
ref="searchBarForm"
@headBtnClick="buttonClick" />
<!-- 列表 -->
<base-table
:page="queryParams.pageNo"
:limit="queryParams.pageSize"
:table-props="tableProps"
:table-data="list"
:max-height="tableH">
<method-btn
v-if="tableBtn.length"
slot="handleBtn"
:width="120"
label="操作"
:method-list="tableBtn"
@clickBtn="handleClick" />
</base-table>
<pagination
:page.sync="queryParams.pageNo"
:limit.sync="queryParams.pageSize"
:total="total"
@pagination="getList" />
<!-- 新增 -->
<base-dialog
:dialogTitle="addOrEditTitle"
:dialogVisible="centervisible"
@cancel="handleCancel"
@confirm="handleConfirm"
:before-close="handleCancel"
width="50%">
<schedulingRuleConfigAdd ref="classList" @successSubmit="successSubmit" />
</base-dialog>
</div>
</template>
<script>
import {
getGroupRulePage,
deleteGroupRule,
updateGroupRule,
getGroupRule,
disableGroupRule
} from '@/api/base/groupSchedulingRule';
import schedulingRuleConfigAdd from './components/schedulingRuleConfigAdd.vue';
import { formatDate } from '@/utils';
import tableHeightMixin from '@/mixins/tableHeightMixin';
import { getFactoryPage } from '@/api/core/base/factory';
const tableProps = [
{
prop: 'factoryName',
label: '工厂',
},
{
prop: 'enableTimeStr',
label: '排班日期',
minWidth: 200,
},
{
prop: 'planName',
label: '排班计划',
},
{
prop: 'str',
label: '排班规则',
minWidth: 100,
},
{
prop: 'enabled',
label: '状态',
filter: (val) => (val ? '正常' : '作废'),
},
];
export default {
name: 'schedulingRuleConfig',
components: { schedulingRuleConfigAdd },
mixins: [tableHeightMixin],
data() {
return {
formConfig: [
{
type: 'select',
label: '工厂',
selectOptions: [],
param: 'factoryId',
onchange: true,
},
{
type: 'input',
label: '班次',
placeholder: '班次',
param: 'name',
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary',
},
{
type: 'separate',
},
{
type: this.$auth.hasPermi('base:group-scheduling-rule:create')
? 'button'
: '',
btnName: '新增',
name: 'add',
color: 'success',
plain: true,
},
],
tableProps,
tableBtn: [
this.$auth.hasPermi('base:group-scheduling-rule:cancel')
? {
type: 'cancel',
btnName: '作废',
showParam: {
type: '&',
data: [
{
type: 'unequal',
name: 'enabled',
value: 0,
},
],
},
}
: undefined,
this.$auth.hasPermi('base:group-scheduling-rule:update')
? {
type: 'edit',
btnName: '编辑',
showParam: {
type: '&',
data: [
{
type: 'unequal',
name: 'enabled',
value: 0,
},
],
},
}
: undefined,
this.$auth.hasPermi('base:group-scheduling-rule:delete')
? {
type: 'delete',
btnName: '删除',
}
: undefined,
].filter((v) => v),
// 总条数
total: 0,
// 班次基础信息列表
list: [],
// 弹出层标题
addOrEditTitle: '',
// 是否显示弹出层
centervisible: false,
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 20,
name: null,
},
};
},
created() {
this.getList();
this.getPdLineList();
},
methods: {
getPdLineList() {
const params = {
pageSize: 100,
pageNo: 1,
};
getFactoryPage(params).then((res) => {
this.formConfig[0].selectOptions = res.data.list || [];
});
},
buttonClick(val) {
switch (val.btnName) {
case 'search':
this.queryParams.pageNo = 1;
this.queryParams.classesName = val.name || undefined;
this.queryParams.factoryId = val.factoryId || undefined;
this.getList();
break;
default:
this.addOrEditTitle = '新增';
this.centervisible = true;
this.$nextTick(() => {
this.$refs.classList.init();
});
}
},
/** 查询列表 */
getList() {
getGroupRulePage(this.queryParams).then((res) => {
if (res.code === 0 && res.data.list && res.data.list.length > 0) {
res.data.list.map((item) => {
item.enableTimeStr =
formatDate(item.startDay) +
'至' +
(item.endDay ? formatDate(item.endDay) : '永久');
item.str = item.strList.join(',');
});
this.list = res.data.list;
this.total = res.data.total;
} else {
this.list = [];
this.total = 0;
}
});
},
handleClick(val) {
switch (val.type) {
case 'edit':
this.addOrEditTitle = '编辑';
this.$nextTick(() => {
this.$refs.classList.init(val.data.id);
});
this.centervisible = true;
break;
case 'cancel':
this.discard(val.data);
break;
default:
this.handleDelete(val.data);
}
},
handleCancel() {
this.$refs.classList.formClear();
this.centervisible = false;
this.addOrEditTitle = '';
},
handleConfirm() {
this.$refs.classList.submitForm();
},
successSubmit() {
this.handleCancel();
this.getList();
},
discard(row) {
let _this = this
this.$confirm(`是否确认作废 ${row.planName} 的数据项?`, "系统提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(() => {
disableGroupRule(row.id).then((response) => {
_this.getList();
_this.$modal.msgSuccess('操作成功');
});
})
.catch(() => {});
},
/** 删除按钮操作 */
handleDelete(row) {
this.$confirm(`是否确认删除 ${row.planName} 的数据项?`, "系统提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning",
})
.then(function () {
return deleteGroupRule(row.id);
})
.then(() => {
this.getList();
this.$modal.msgSuccess('删除成功');
})
.catch(() => {});
},
},
};
</script>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Some files were not shown because too many files have changed in this diff Show More