Compare commits

...

47 Commits

Author SHA1 Message Date
lb
5f47cb131f add 添加消防设备 2023-12-12 16:50:18 +08:00
lb
ea21f3d4bc add 安全设备,特种设备 2023-12-12 16:27:37 +08:00
lb
bdda6c9985 add 特殊设备 2023-12-12 13:57:02 +08:00
lb
ae83da6eb9 almost done 2023-12-12 11:29:56 +08:00
lb
b62d0e4096 add israchart 2023-12-12 10:53:00 +08:00
lb
1c123fa22d Merge branch 'projects/mesxc-test' into projects/mesxc-lb 2023-12-11 10:22:51 +08:00
lb
6b3619514d update 驾驶舱 2023-12-11 10:21:45 +08:00
lb
dee9f7ce8b update 2023-12-11 09:47:58 +08:00
lb
b4d2b69004 update 2023-12-11 09:11:51 +08:00
lb
4f64c255af update 2023-12-06 15:29:11 +08:00
lb
cc0d3d8b75 add 烟气处理 2023-12-06 10:38:56 +08:00
lb
f5233001e7 add Energy&Header 2023-12-06 10:18:12 +08:00
f2e38b5e67 Merge pull request 'projects/mesxc-zjl' (#138) from projects/mesxc-zjl into projects/mesxc-test
Reviewed-on: #138
2023-12-06 10:09:07 +08:00
fe0c84bc3a 能源&bug 2023-12-06 10:06:26 +08:00
lb
7cb88fab88 add 用量统计&风机频率 2023-12-06 09:49:38 +08:00
lb
e7263302a7 update line 2023-12-05 17:00:55 +08:00
lb
b26e1d5a7f update switcher 2023-12-05 15:44:22 +08:00
lb
86bdabf358 update 2023-12-05 15:24:20 +08:00
lb
4069e71477 update kiln databoard 2023-12-05 15:08:07 +08:00
0a53bcb57e merge test 2023-12-05 14:40:02 +08:00
1ce61f13b7 原模块修改能源 2023-12-05 14:30:32 +08:00
lb
6c661bedd3 add databoard 2023-12-04 17:00:40 +08:00
lb
a2ed9ed54b fix 添加参数 2023-12-04 09:10:56 +08:00
49d002142f Merge pull request 'projects/mesxc-dy' (#137) from projects/mesxc-dy into projects/mesxc-test
Reviewed-on: #137
2023-12-01 15:34:28 +08:00
helloDy
8399081a6f Merge branch 'projects/mesxc-test' into projects/mesxc-dy 2023-12-01 15:27:02 +08:00
helloDy
cc6c4772d3 ui 2023-12-01 15:25:46 +08:00
ba7dad7fce Merge pull request 'projects/mesxc-dy' (#136) from projects/mesxc-dy into projects/mesxc-test
Reviewed-on: #136
2023-11-30 16:01:21 +08:00
helloDy
8e7e31f918 Merge branch 'projects/mes-dy' into projects/mesxc-dy 2023-11-30 15:53:40 +08:00
helloDy
5e4df4d849 Merge branch 'projects/mes-test' into projects/mes-dy 2023-11-30 15:06:20 +08:00
helloDy
1d3372ed69 ui 2023-11-30 15:04:17 +08:00
86f246eb94 Merge pull request 'projects/mes-lb' (#134) from projects/mes-lb into projects/mes-test
Reviewed-on: #134
2023-11-30 14:24:09 +08:00
lb
e2a16332be Merge branch 'projects/mes-test' into projects/mes-lb 2023-11-30 14:22:56 +08:00
lb
69b6942f35 fix bugs 2023-11-30 14:19:13 +08:00
gtz
be430ebbff Merge branch 'projects/mes-test' of git.picaiba.com:mt-fe-group/yudao-dev into projects/mes-test 2023-11-30 09:08:59 +08:00
gtz
61b4bf784b Merge branch 'projects/mes-test' of git.picaiba.com:mt-fe-group/yudao-dev into projects/mes-test 2023-11-29 10:17:02 +08:00
gtz
b0f10b9002 '1' 2023-11-29 10:16:58 +08:00
gtz
e6b9d75f16 Merge branch 'projects/mes-test' of git.picaiba.com:mt-fe-group/yudao-dev into projects/mes-test 2023-11-28 09:03:13 +08:00
gtz
d9f3434712 Merge branch 'projects/mes-test' of git.picaiba.com:mt-fe-group/yudao-dev into projects/mes-test 2023-11-27 09:31:52 +08:00
gtz
de15716b7c Merge branch 'projects/mes-test' of git.picaiba.com:mt-fe-group/yudao-dev into projects/mes-test 2023-11-22 14:53:49 +08:00
gtz
c736992a34 '1' 2023-11-22 14:49:56 +08:00
gtz
dcbb2c719b Merge branch 'projects/mes-test' of git.picaiba.com:mt-fe-group/yudao-dev into projects/mes-test 2023-11-22 14:15:39 +08:00
gtz
bc2940ca99 Merge branch 'projects/mes-test' of git.picaiba.com:mt-fe-group/yudao-dev into projects/mes-test 2023-11-21 17:30:38 +08:00
gtz
76938951ed Merge branch 'projects/mes-test' of git.picaiba.com:mt-fe-group/yudao-dev into projects/mes-test 2023-11-20 16:07:12 +08:00
gtz
8b91e7812f '1' 2023-11-17 10:38:44 +08:00
gtz
9cffa01414 Merge branch 'projects/mes-test' of git.picaiba.com:mt-fe-group/yudao-dev into projects/mes-test 2023-11-17 10:38:35 +08:00
gtz
905479d5f4 'del_dist' 2023-11-17 10:29:23 +08:00
gtz
c1ae248234 '1' 2023-11-17 10:28:39 +08:00
97 changed files with 15768 additions and 9105 deletions

View File

@@ -15,15 +15,14 @@ VUE_APP_TITLE = MES系统
VUE_APP_BASE_API = '/prod-api'
# 积木报表指向地址
VUE_APP_JIMU_API = 'http://192.168.0.33:48082'
VUE_APP_JIMU_API = 'http://10.70.2.2:8080'
# 根据服务器或域名修改
# PUBLIC_PATH = 'http://my-pi.com:8888/yudao-admin/'
PUBLIC_PATH = 'http://192.168.0.33:8889/'
PUBLIC_PATH = 'http://10.70.2.32'
# 二级部署路径
VUE_APP_APP_NAME ='yudao-admin'
# VUE_APP_APP_NAME ='yudao-admin'
# 多租户的开关
VUE_APP_TENANT_ENABLE = true

View File

@@ -1,16 +1,21 @@
NODE_ENV = production
# 生产环境配置
ENV = 'production'
# 页面标题
VUE_APP_TITLE = 产线监控系统
VUE_APP_TITLE = MES系统
# 测试环境配置
ENV = 'staging'
# 芋道管理系统/生产环境
VUE_APP_BASE_API = '/prod-api'
# 芋道管理系统/测试环境
VUE_APP_BASE_API = 'http://api-dashboard.yudao.iocoder.cn'
# 积木报表指向地址
VUE_APP_JIMU_API = 'http://192.168.0.33:48082'
# 静态资源地址
PUBLIC_PATH = 'http://static.yudao.iocoder.cn/'
# 根据服务器或域名修改
PUBLIC_PATH = 'http://192.168.0.33:8889/'
# 二级部署路径
# VUE_APP_APP_NAME ='yudao-admin'
# 多租户的开关
VUE_APP_TENANT_ENABLE = true
@@ -20,4 +25,3 @@ VUE_APP_DOC_ENABLE = false
# 百度统计
VUE_APP_BAIDU_CODE = fadc1bd5db1a1d6f581df60a1807f8ab

View File

@@ -48,7 +48,7 @@
"benz-amr-recorder": "^1.1.5",
"bpmn-js-token-simulation": "0.10.0",
"clipboard": "2.0.8",
"code-brick-zj": "^1.0.2",
"code-brick-zj": "^1.0.5",
"core-js": "^3.26.0",
"crypto-js": "^4.0.0",
"diagram-js": "^12.3.0",

View File

@@ -0,0 +1,56 @@
import request from '@/utils/request'
// 获得分页数据
export function energyQuantityManualPage(data) {
return request({
url: '/base/energy-quantity-manual/page',
method: 'post',
data: data
})
}
// 创建
export function energyQuantityManualCreate(data) {
return request({
url: '/base/energy-quantity-manual/create',
method: 'post',
data: data
})
}
// 更新
export function energyQuantityManualUpdate(data) {
return request({
url: '/base/energy-quantity-manual/update',
method: 'put',
data: data
})
}
//获得能源抄表(手动)
export function energyQuantityManualGet(query) {
return request({
url: '/base/energy-quantity-manual/get',
method: 'get',
params: query
})
}
//删除
export function energyQuantityManualDelete(query) {
return request({
url: '/base/energy-quantity-manual/delete',
method: 'delete',
params: query
})
}
//导出
export function energyQuantityManualExport(data) {
return request({
url: '/base/energy-quantity-manual/export-excel',
method: 'post',
data: data,
responseType: 'blob'
})
}

View File

@@ -86,8 +86,8 @@
</span>
<!-- :file-list="uploadedFileList" -->
<el-upload
class="upload-in-dialog"
v-if="col.upload"
class="upload-in-dialog"
:key="col.prop + '__el-upload'"
:action="uploadUrl"
:headers="uploadHeaders"
@@ -101,7 +101,7 @@
}
"
v-bind="col.bind">
<el-button size="mini" :disabled="col.bind?.disabled || false">
<el-button size="mini" :disabled="disabled || col.bind?.disabled || false">
<svg-icon
icon-class="icon-upload"
style="color: inherit"></svg-icon>
@@ -117,6 +117,7 @@
v-for="file in form[col.prop]"
:file="file"
:key="file.fileUrl"
:disabled="disabled"
@delete="!disabled && handleDeleteFile(file, col.prop)" />
</div>
</el-form-item>
@@ -143,7 +144,7 @@ function findMaxLabelWidth(rows) {
if (opt.label.length > max) {
max = opt.label.length;
if (opt.label.includes('(')) {
max = max - 3
max = max - 3;
}
}
});
@@ -153,7 +154,7 @@ function findMaxLabelWidth(rows) {
const uploadedFile = {
name: 'UploadedFile',
props: ['file'],
props: ['file', 'disabled'],
data() {
return {};
},
@@ -198,13 +199,15 @@ const uploadedFile = {
display: 'inline-block',
}}>
{this.file.fileName}
<el-button
type="text"
icon="el-icon-close"
style="float: right; position: relative; top: 2px; left: 8px; z-index: 100"
class="dialog__upload_component__close"
onClick={this.handleDelete}
/>
{!this.disabled && (
<el-button
type="text"
icon="el-icon-close"
style="float: right; position: relative; top: 2px; left: 8px; z-index: 100"
class="dialog__upload_component__close"
onClick={this.handleDelete}
/>
)}
</div>
);
},
@@ -242,7 +245,7 @@ export default {
size: {
type: String,
default: '',
}
},
},
data() {
return {

View File

@@ -125,11 +125,8 @@ export default {
// 取消自动聚焦 start
this.Quill?.enable(false);
this.$nextTick(() => {
this.Quill?.enable(true);
this.Quill?.blur();
// if (!this.readOnly) {
// this.Quill?.enable();
// }
this.Quill?.enable(true);
});
// 如果设置了上传地址则自定义图片上传事件
if (this.type === 'url') {

View File

@@ -360,6 +360,7 @@ export default {
ts: Date.now(), // 现在的时间戳
}
reqGet(data).then(res => {
console.log(1)
if (res.repCode === '0000') {
this.backImgBase = res.repData.originalImageBase64
this.blockBackImgBase = res.repData.jigsawImageBase64

View File

@@ -78,7 +78,6 @@ export default {
return this.http(this.infoUrl == '' ? this.infoPath : this.infoUrl, 'get', payload);
},
del(payload) {
debugger;
return this.http(this.deleteUrl == '' ? this.deletePath : this.deleteUrl, 'delete', payload);
},

View File

@@ -104,7 +104,7 @@ export const constantRoutes = [
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '@/views/OperationalOverview/coldBoard.vue')
},
},
{
path: '/processingBoard',
name: 'processingBoard',

View File

@@ -94,6 +94,8 @@ export const DICT_TYPE = {
OBJECT_TYPE: 'object_type',
STATISTIC_TYPE: 'statistic_type',
TIME_DIM: 'time_dim',
TABLE_NAME: 'table_name',
METHOD: 'method',
// ============== ORDER - 订单模块 =============
ORDER_STATUS: 'order_status',

View File

@@ -5,7 +5,7 @@
const baseURL = process.env.VUE_APP_BASE_API
// 日期格式化
// 日期格式化(通用)
export function parseTime(time, pattern) {
if (arguments.length === 0 || !time) {
return null
@@ -48,6 +48,51 @@ export function parseTime(time, pattern) {
return time_str
}
// 日期格式化(仅适用表格)
export function parseTimeTable(pattern) {
return function(time){
if (arguments.length === 0 || !time) {
return null
}
const format = pattern || '{y}-{m}-{d} {h}:{i}:{s}'
let date
if (typeof time === 'object') {
date = time
} else {
if ((typeof time === 'string') && (/^[0-9]+$/.test(time))) {
time = parseInt(time)
} else if (typeof time === 'string') {
time = time.replace(new RegExp(/-/gm), '/').replace('T', ' ').replace(new RegExp(/\.\d{3}/gm),'');
}
if ((typeof time === 'number') && (time.toString().length === 10)) {
time = time * 1000
}
date = new Date(time)
}
const formatObj = {
y: date.getFullYear(),
m: date.getMonth() + 1,
d: date.getDate(),
h: date.getHours(),
i: date.getMinutes(),
s: date.getSeconds(),
a: date.getDay()
}
const time_str = format.replace(/{([ymdhisa])+}/g, (result, key) => {
let value = formatObj[key]
// Note: getDay() returns 0 on Sunday
if (key === 'a') {
return ['日', '一', '二', '三', '四', '五', '六'][value]
}
if (result.length > 0 && value < 10) {
value = '0' + value
}
return value || 0
})
return time_str
}
}
// 表单重置
export function resetForm(refName) {
if (this.$refs[refName]) {

View File

@@ -248,6 +248,9 @@ export default {
label: '设备编码',
prop: 'code',
url: '/base/core-equipment/getCode',
rules: [
{ required: true, message: '设备编码不能为空', trigger: 'blur' },
],
},
{
input: true,

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@@ -0,0 +1,97 @@
<!--
filename: Container.vue
author: liubin
date: 2023-12-05 14:29:53
description: 窑炉容器
-->
<template>
<div class="kiln-container" :class="['kiln-container__' + size]">
<div class="container-hd" style="display: flex; align-items: center">
<i
class=""
style="display: inline-block; margin-left: 12px; padding-top: 4px">
<img :src="imgSrc" width="18" height="16" alt="" />
</i>
<span
style="
color: #fff;
font-size: 20px;
line-height: 2;
margin-left: 6px;
display: inline-block;
">
{{ name }}
</span>
</div>
<div class="container-body">
<slot>
<div class="test-body">something test....</div>
</slot>
</div>
</div>
</template>
<script>
export default {
name: 'KilnContainer',
components: {},
props: ['name', 'width', 'size'],
data() {
return {};
},
computed: {
imgSrc() {
switch (this.name) {
case '原料用量统计':
return require('../assets/move.png');
case '风机运行频率':
return require('../assets/flow.png');
case 'ISRA缺陷检测':
return require('../assets/gas.png');
case '能耗':
return require('../assets/gas.png');
case '窑炉信息':
return require('../assets/gas.png');
case '烟气处理':
return require('../assets/gas.png');
}
},
},
methods: {},
};
</script>
<style scoped lang="scss">
.kiln-container {
display: inline-block;
width: 100%;
height: 100%;
padding: 8px;
display: flex;
flex-direction: column;
position: relative;
&__small {
background: url(../assets/short.png) no-repeat;
background-size: 100% 100%;
background-position: 0 0;
}
&__middle {
background: url(../assets/middle.png) no-repeat;
background-size: 100% 100%;
background-position: 0 0;
}
&__large {
background: url(../assets/high.png) no-repeat;
background-size: 100% 100%;
background-position: 0 0;
}
}
.container-body {
flex: 1;
}
</style>

View File

@@ -0,0 +1,84 @@
<!--
filename: DateBtnGroup.vue
author: liubin
date: 2023-12-05 14:35:14
description: 日期按钮组
-->
<template>
<div class="date-btn-group">
<button
class="btn"
:class="{ 'btn-active': active == '日' }"
@click="handleClick('日')">
</button>
<button
class="btn"
:class="{ 'btn-active': active == '周' }"
@click="handleClick('周')">
</button>
<button
class="btn"
:class="{ 'btn-active': active == '月' }"
@click="handleClick('月')">
</button>
</div>
</template>
<script>
export default {
name: 'DateBtnGroup',
data() {
return {
active: '日',
};
},
methods: {
handleClick(v) {
this.active = v;
this.$emit('change', v);
},
},
};
</script>
<style scoped lang="scss">
button {
appearance: none;
border: none;
outline: none;
background: none;
padding: 6px 8px;
}
.date-btn-group {
// position: absolute;
// top: 40px;
// right: 100px;
// border: 1px solid #ccc;
// padding: 12px;
display: flex;
align-items: center;
gap: 12px;
}
.btn {
cursor: pointer;
border: 1px solid #11e8e4;
border-radius: 4px;
color: #11e8e4;
transition: all 0.3s ease-in-out;
&:hover {
background: #11e8e4;
color: #013433;
}
}
.btn-active {
background: #11e8e4;
color: #013433;
}
</style>

View File

@@ -0,0 +1,150 @@
<!--
filename: GasChart.vue
author: liubin
date: 2023-12-12 10:53:49
description:
-->
<template>
<div class="gas-chart"></div>
</template>
<script>
import * as echarts from 'echarts';
export default {
name: 'GasChart',
components: {},
props: {},
data() {
const colors = [
'#12FFF5',
'#2760FF',
'#FFD160',
'#E80091',
'#8064ff',
'#ff8a3b',
'#8cd26d',
'#2aa1ff',
];
return {
chart: null,
option: {
color: colors,
grid: { top: 32, right: 12, bottom: 20, left: 48 },
xAxis: {
type: 'category',
data: Array(7)
.fill(1)
.map((_, index) => {
const today = new Date();
const dtimestamp = today - index * 24 * 60 * 60 * 1000;
return `${new Date(dtimestamp).getMonth() + 1}.${new Date(
dtimestamp
).getDate()}`;
})
.reverse(),
axisLabel: {
color: '#fff',
fontSize: 12,
},
axisTick: { show: false },
axisLine: {
lineStyle: {
width: 1,
color: '#213259',
},
},
},
yAxis: {
name: '单位m³/h',
nameTextStyle: {
color: '#fff',
fontSize: 10,
align: 'right',
},
type: 'value',
axisLabel: {
color: '#fff',
fontSize: 12,
},
axisLine: {
show: true,
lineStyle: {
color: '#213259',
},
},
splitLine: {
lineStyle: {
color: '#213259a0',
},
},
},
series: [
Array(7)
.fill(1)
.map((_) => Math.ceil(Math.random() * 100)),
Array(7)
.fill(1)
.map((_) => Math.ceil(Math.random() * 100)),
Array(7)
.fill(1)
.map((_) => Math.ceil(Math.random() * 100)),
].map((v, i) => ({
name: ['总量', '白班', '夜班'][i],
data: v,
type: 'line',
symbol: 'circle',
areaStyle: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// i % 8 避免超过8个数据时无颜色的问题
{ offset: 0, color: colors[i % 8] + '40' },
{ offset: 0.5, color: colors[i % 8] + '20' },
{ offset: 1, color: colors[i % 8] + '00' },
]),
},
})),
tooltip: {
trigger: 'axis',
},
},
};
},
inject: ['resizeChart'],
computed: {
sidebarStatus() {
return this.$store.state.app.sidebar.opened;
},
},
watch: {
sidebarStatus(val) {
console.log('sidebarStatus', val);
this.chart && this.chart.dispose();
setTimeout(() => {
this.chart = echarts.init(this.$el);
this.chart.setOption(this.option);
}, 500);
},
// resizeChart(val) {
// console.log('resizeChart', val);
// val && this.chart && this.chart.resize();
// },
},
mounted() {
this.$el.addEventListener('resize', () => {
console.log('resziing.....');
});
this.chart = echarts.init(this.$el);
this.chart.setOption(this.option);
},
methods: {},
};
</script>
<style scoped lang="scss">
.gas-chart {
width: 100%;
height: 100%;
}
</style>

View File

@@ -0,0 +1,75 @@
<!--
filename: Header.vue
author: liubin
date: 2023-12-05 14:30:46
description: 顶部标题
-->
<template>
<header class="kiln-header">
<h1
style="
font-size: 32px;
margin-bottom: 36px;
color: #0ee8e4;
letter-spacing: 5px;
">
窑炉生产运行驾驶舱
</h1>
<!-- left: 312px; -->
<div
class="firm"
style="
position: absolute;
bottom: 24px;
left: 16.5vw;
color: #fff;
font-size: 16px;
letter-spacing: 1px;
">
单位: 河南汇融科技服务有限公司
</div>
<div
class="datetime"
style="
position: absolute;
bottom: 18px;
right: 15.5vw;
color: #fff;
font-size: 16px;
letter-spacing: 1px;
display: flex;
align-items: center;
gap: 16px;
">
<DateBtnGroup />
{{ new Date().toLocaleString() }}
</div>
</header>
</template>
<script>
import DateBtnGroup from './DateBtnGroup.vue';
export default {
name: 'KilnHeader',
components: { DateBtnGroup },
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.kiln-header {
background: url('../assets/head.png') no-repeat;
height: 88px;
background-size: 100%;
background-position: 0 0;
display: grid;
place-content: center;
position: relative;
}
</style>

View File

@@ -0,0 +1,235 @@
<!--
filename: ISRAChart.vue
author: liubin
date: 2023-12-12 09:05:25
description:
-->
<template>
<div class="isra-chart"></div>
</template>
<script>
import * as echarts from 'echarts';
export default {
name: 'ISRAChart',
components: {},
props: {},
data() {
return {
chart: null,
option: {
color: ['#2760ff', '#518eec', '#0ee8e4', '#ddb523'],
tooltip: {
trigger: 'item',
},
title: {
text: 11234,
subtext: '总数',
top: '43%',
left: '49%',
textAlign: 'center',
textStyle: {
fontSize: 32,
lineHeight: 16,
color: '#fff',
},
subtextStyle: {
fontSize: 16,
color: '#fff7',
},
},
series: [
{
name: 'Access From',
type: 'pie',
radius: ['60%', '85%'],
avoidLabelOverlap: true,
label: {
show: true,
position: 'outside',
formatter: ({ dataIndex, percent }) => {
// console.log(
// ['#2760ff', '#518eec', '#0ee8e4', '#ddb523'][dataIndex % 4],
// percent
// );
const styleName = ['a', 'b', 'c', 'd'][dataIndex % 4];
return `{${styleName}|${percent}%}`;
},
rich: {
a: {
color: '#2760ff',
fontSize: 18,
borderWidth: 0,
textBorderWidth: 0,
},
b: {
color: '#518eec',
fontSize: 18,
borderWidth: 0,
textBorderWidth: 0,
},
c: {
color: '#0ee8e4',
fontSize: 18,
borderWidth: 0,
textBorderWidth: 0,
},
d: {
color: '#ddb523',
fontSize: 18,
borderWidth: 0,
textBorderWidth: 0,
},
},
},
labelLine: {
show: true,
},
itemStyle: {
borderRadius: 12,
// borderColor: 'transparent',
// borderWidth: 20
},
data: [
{
value: 1048,
name: '缺陷1',
itemStyle: {
color: {
type: 'linear',
x: 1,
y: 1,
x2: 0,
y2: 0,
colorStops: [
{
offset: 0,
color: '#2760ff', // 0% 处的颜色
},
// {
// offset: 0.6,
// color: 'transparent', // 80% 处的颜色
// },
{
offset: 1,
color: '#2760ff33', // 100% 处的颜色
},
],
global: false, // 缺省为 false
},
},
},
{
value: 735,
name: '缺陷2',
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 0,
colorStops: [
{
offset: 0,
color: '#518eec', // 0% 处的颜色
},
// {
// offset: 0.6,
// color: 'transparent', // 80% 处的颜色
// },
{
offset: 1,
color: '#518eec33', // 100% 处的颜色
},
],
global: false, // 缺省为 false
},
},
},
{
value: 580,
name: '缺陷3',
itemStyle: {
color: {
type: 'linear',
x: 0,
y: 0,
x2: 1,
y2: 1,
colorStops: [
{
offset: 0,
color: '#0ee8e4', // 0% 处的颜色
},
// {
// offset: 0.6,
// color: 'transparent', // 80% 处的颜色
// },
{
offset: 1,
color: '#0ee8e433', // 100% 处的颜色
},
],
global: false, // 缺省为 false
},
},
},
{
value: 484,
name: '缺陷4',
itemStyle: {
color: {
type: 'linear',
x: 1,
y: 0,
x2: 0,
y2: 0,
colorStops: [
{
offset: 0,
color: '#ddb523', // 0% 处的颜色
},
// {
// offset: 0.6,
// color: 'transparent', // 70% 处的颜色
// },
{
offset: 1,
color: '#ddb52333', // 100% 处的颜色
},
],
global: false, // 缺省为 false
},
},
},
],
},
],
},
};
},
mounted() {
this.initChart();
},
activated() {
// this.initChart();
},
computed: {},
methods: {
initChart() {
this.chart = echarts.init(this.$el);
this.chart.setOption(this.option);
},
},
};
</script>
<style scoped lang="scss">
.isra-chart {
width: 100%;
height: 100%;
}
</style>

View File

@@ -0,0 +1,69 @@
<!--
filename: SelectorBtnGroup.vue
author: liubin
date: 2023-12-05 14:28:24
description: 选项按钮组
-->
<template>
<div class="selector-btn-group">
<button
class="btn"
v-for="opt in options"
:key="opt"
@click="active = opt"
:class="active == opt ? 'btn-active' : ''">
{{ opt }}
</button>
</div>
</template>
<script>
export default {
name: 'SelectorBtnGroup',
components: {},
props: ['options'],
data() {
return {
active: this.options[0] || 'default'
};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
button {
border: none;
appearance: none;
outline: none;
color: red;
font-size: 14px;
padding: 8px 12px;
}
button:first-child {
border-top-left-radius: 8px;
border-bottom-left-radius: 8px;
}
button:last-child {
border-top-right-radius: 8px;
border-bottom-right-radius: 8px;
}
.selector-btn-group {
}
.btn {
background: #03233c;
color: #fff;
cursor: pointer;
transition: all 0.3s ease-out;
&.btn-active,
&:hover {
background: #0f3d5c;
}
}
</style>

View File

@@ -0,0 +1,71 @@
<!--
filename: ShadowRect.vue
author: liubin
date: 2023-12-05 14:28:57
description: 阴影矩形
-->
<template>
<div class="shadow-rect" :style="{ borderRadius: rounded ? '8px' : '2px' }">
<slot>
<div
class="test-data"
style="flex: 1; display: flex; align-items: center">
<span
style="
flex: 7;
color: #fff;
text-align: right;
font-size: 18px;
line-height: 1.12;
letter-spacing: 1px;
padding-right: 12px;
">
窑炉压力碹顶加权
</span>
<span
style="
flex: 3;
color: #fff;
text-align: left;
font-size: 18px;
line-height: 1.12;
padding-right: 8px;
">
92Kpa
</span>
</div>
</slot>
</div>
</template>
<script>
export default {
name: '',
components: {},
props: ['rounded'],
data() {
return {};
},
watch: {
rounded(val) {
if (val) {
console.log('val', val);
}
},
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.shadow-rect {
padding: 8px;
border-radius: 2px;
box-shadow: inset 0 0 8px 2px #ccc3;
color: white;
display: flex;
align-items: center;
}
</style>

View File

@@ -0,0 +1,57 @@
<!--
filename: Switcher.vue
author: liubin
date: 2023-12-05 14:29:29
description: 开关
-->
<template>
<div class="switcher" style="display: flex; align-items: center; gap: 12px">
<el-switch v-model="value"></el-switch>
<span style="color: #fff; font-size: 16px">{{ mode }}</span>
;
</div>
</template>
<script>
export default {
name: 'Switcher',
components: {},
props: {},
data() {
return {
value: true,
};
},
computed: {
mode() {
return this.value ? '历史详情' : '实时数据';
},
},
methods: {},
};
</script>
<style scoped lang="scss">
.switcher {
:deep(.el-switch__core) {
border: none;
background-color: #213d566b;
&::after {
background-color: #02457e;
}
}
:deep(.is-checked) {
.el-switch__core {
border: none;
background-color: #b4fffc;
&::after {
background-color: #08d8cd;
}
}
}
}
</style>

View File

@@ -0,0 +1,16 @@
export default {
name: 'KilnLine',
props: ['horizontal'],
render: function (h) {
return (
<div
class="line"
style={{
width: this.horizontal ? '100%' : '4px',
height: this.horizontal ? '4px' : '100%',
background:
'radial-gradient(ellipse at center, #3CE7FF, #3CE7FF66, transparent, transparent)',
}}></div>
);
},
};

View File

@@ -0,0 +1,101 @@
<!--
filename: MaterialCost.vue
author: liubin
date: 2023-12-06 09:09:27
description:
-->
<template>
<Container name="能耗" size="middle" style="">
<EnergeTop />
<SplitLine :horizontal="true" />
<div class="" style="flex: 2; padding: 8px">
<div
class="header-line"
style="margin-bottom: 8px; display: flex; align-items: center">
<h2 class="" style="margin: 0; color: #0ee8fe; margin-right: 12px">
烟气趋势图
</h2>
<Switcher />
<div>
<span class="lgd lgd-total">总量</span>
<!-- <span class="lgd lgd-day">白班</span>
<span class="lgd lgd-night">夜班</span> -->
</div>
</div>
<div
class="select-line"
style="
display: flex;
align-items: center;
justify-content: space-between;
">
<SelectorBtnGroup
:options="['氧气含量', '二氧化硫', '一氧化氢', '二氧化氢']" />
<SelectorBtnGroup :options="['日', '周', '月', '年']" />
</div>
<div class="chart" style="height: 150px; margin-top: 8px;">
<GasChart />
</div>
</div>
</Container>
</template>
<script>
import Container from '../components/Container.vue';
import ShadowRect from '../components/ShadowRect.vue';
import SplitLine from '../components/line';
import Switcher from '../components/Switcher.vue';
import EnergeTop from './EnergeTop.vue';
import GasChart from '../components/GasChart.vue';
import SelectorBtnGroup from '../components/SelectorBtnGroup.vue';
export default {
name: 'EnergeCost',
components: {
Container,
ShadowRect,
SplitLine,
Switcher,
EnergeTop,
GasChart,
SelectorBtnGroup,
},
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.lgd {
color: #fff;
&:not(:last-child) {
margin-right: 12px;
}
}
.lgd::before {
content: '';
display: inline-block;
width: 8px;
height: 8px;
margin-right: 4px;
border-radius: 2px;
}
.lgd.lgd-total::before {
background-color: #ff9e00;
}
.lgd.lgd-day::before {
background-color: #08d8cd;
}
.lgd.lgd-night::before {
background-color: #0b58ff;
}
</style>

View File

@@ -0,0 +1,123 @@
<!--
filename: EnergeTop.vue
author: liubin
date: 2023-12-11 09:31:41
description:
-->
<template>
<div
class="energe-top"
style="
flex: 1;
display: grid;
grid-template-columns: 1fr 1fr 1fr;
grid-template-rows: auto;
gap: 8px;
padding: 4px;
">
<ShadowRect
style="grid-row: 1 / 3; flex-direction: column; justify-content: center">
<span
style="
font-size: 16px;
line-height: 1.55;
text-align: right;
padding-right: 8px;
letter-spacing: 1px;
">
余热发电
</span>
<span
style="
font-size: 16px;
line-height: 1.55;
text-align: right;
padding-right: 8px;
letter-spacing: 1px;
">
1023kWh
</span>
</ShadowRect>
<ShadowRect>
<div
style="
font-size: 16px;
line-height: 1.25;
flex: 1.2;
text-align: right;
padding-right: 8px;
letter-spacing: 3px;
">
<p style="margin: 0; line-height: inherit">水耗量</p>
</div>
<span style="font-size: 16px; line-height: 1.24; flex: 1">32Km³</span>
</ShadowRect>
<ShadowRect>
<div
style="
font-size: 16px;
line-height: 1.25;
flex: 1.2;
text-align: right;
padding-right: 8px;
letter-spacing: 3px;
">
<p style="margin: 0; line-height: inherit">天然气I</p>
</div>
<span style="font-size: 16px; line-height: 1.24; flex: 1">322Km³</span>
</ShadowRect>
<ShadowRect>
<div
style="
font-size: 16px;
line-height: 1.25;
flex: 1.2;
text-align: right;
padding-right: 8px;
letter-spacing: 3px;
">
<p style="margin: 0; line-height: inherit">电耗量</p>
</div>
<span style="font-size: 16px; line-height: 1.24; flex: 1">132kWh</span>
</ShadowRect>
<ShadowRect>
<div
style="
font-size: 16px;
line-height: 1.25;
flex: 1.2;
text-align: right;
padding-right: 8px;
letter-spacing: 3px;
">
<p style="margin: 0; line-height: inherit">天然气II</p>
</div>
<span style="font-size: 16px; line-height: 1.24; flex: 1">992Km³</span>
</ShadowRect>
</div>
</template>
<script>
import ShadowRect from '../components/ShadowRect.vue';
export default {
name: 'EnergeTop',
components: { ShadowRect },
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.energe-top {
}
</style>

View File

@@ -0,0 +1,58 @@
<!--
filename: FanSequence.vue
author: liubin
date: 2023-12-06 09:40:51
description:
-->
<template>
<Container name="风机运行频率" size="middle" style="">
<div class="" style="position: absolute; top: 18px; left: 180px">
<Switcher />
</div>
<div
class="absolute"
style="
padding: 12px;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-auto-rows: auto;
gap: 8px;
">
<ShadowRect v-for="n in 14" :key="n" :rounded="false">
<span
style="
font-size: 16px;
line-height: 1.24;
flex: 1.2;
text-align: right;
padding-right: 8px;
letter-spacing: 1px;
">
{{ n }}#风机
</span>
<span style="font-size: 16px; line-height: 1.24; flex: 1">
{{ Math.floor(Math.random() * 100) }}Hz
</span>
</ShadowRect>
</div>
</Container>
</template>
<script>
import Container from '../components/Container.vue';
import ShadowRect from '../components/ShadowRect.vue';
import Switcher from '../components/Switcher.vue';
export default {
name: 'FanSequence',
components: { Container, ShadowRect, Switcher },
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss"></style>

View File

@@ -0,0 +1,176 @@
<!--
filename: GasHandle.vue
author: liubin
date: 2023-12-11 09:02:40
description:
-->
<template>
<div class="gas-handle" style="flex: 2">
<Container name="烟气处理" size="large" style="">
<div
class=""
style="
flex: 1;
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: auto;
gap: 8px;
padding: 8px;
">
<ShadowRect>
<span
style="
font-size: 16px;
line-height: 1.24;
flex: 1.2;
text-align: right;
padding-right: 8px;
letter-spacing: 1px;
">
氧气含量
</span>
<span style="font-size: 16px; line-height: 1.24; flex: 1">82%</span>
</ShadowRect>
<ShadowRect>
<div
style="
font-size: 16px;
line-height: 1.5;
flex: 1.2;
text-align: right;
padding-right: 8px;
letter-spacing: 3px;
">
<p style="margin: 0; line-height: inherit">一氧化氮</p>
<p style="margin: 0; line-height: inherit">排放浓度</p>
</div>
<span style="font-size: 16px; line-height: 1.24; flex: 1">82%</span>
</ShadowRect>
<ShadowRect>
<div
style="
font-size: 16px;
line-height: 1.5;
flex: 1.2;
text-align: right;
padding-right: 8px;
letter-spacing: 3px;
">
<p style="margin: 0; line-height: inherit">二氧化硫</p>
<p style="margin: 0; line-height: inherit">排放浓度</p>
</div>
<span style="font-size: 16px; line-height: 1.24; flex: 1">82%</span>
</ShadowRect>
<ShadowRect>
<div
style="
font-size: 16px;
line-height: 1.5;
flex: 1.2;
text-align: right;
padding-right: 8px;
letter-spacing: 3px;
">
<p style="margin: 0; line-height: inherit">二氧化氮</p>
<p style="margin: 0; line-height: inherit">排放浓度</p>
</div>
<span style="font-size: 16px; line-height: 1.24; flex: 1">82%</span>
</ShadowRect>
</div>
<KilnLine :horizontal="true" />
<div class="" style="flex: 2; padding: 8px">
<div
class="header-line"
style="margin-bottom: 8px; display: flex; align-items: center">
<h2 class="" style="margin: 0; color: #0ee8fe; margin-right: 12px">
烟气趋势图
</h2>
<Switcher />
<div>
<span class="lgd lgd-total">总量</span>
<span class="lgd lgd-day">白班</span>
<span class="lgd lgd-night">夜班</span>
</div>
</div>
<div
class="select-line"
style="
display: flex;
align-items: center;
justify-content: space-between;
">
<SelectorBtnGroup
:options="['氧气含量', '二氧化硫', '一氧化氢', '二氧化氢']" />
<SelectorBtnGroup :options="['日', '周', '月', '年']" />
</div>
<div class="chart" style="height: 220px">
<GasChart />
</div>
</div>
</Container>
</div>
</template>
<script>
import Container from '../components/Container.vue';
import ShadowRect from '../components/ShadowRect.vue';
import KilnLine from '../components/line';
import Switcher from '../components/Switcher.vue';
import SelectorBtnGroup from '../components/SelectorBtnGroup.vue';
import GasChart from '../components/GasChart.vue';
export default {
name: 'GasHandle',
components: {
Container,
ShadowRect,
KilnLine,
Switcher,
SelectorBtnGroup,
GasChart,
},
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.gas-handle {
}
.lgd {
color: #fff;
&:not(:last-child) {
margin-right: 12px;
}
}
.lgd::before {
content: '';
display: inline-block;
width: 8px;
height: 8px;
margin-right: 4px;
border-radius: 2px;
}
.lgd.lgd-total::before {
background-color: #ff9e00;
}
.lgd.lgd-day::before {
background-color: #08d8cd;
}
.lgd.lgd-night::before {
background-color: #0b58ff;
}
</style>

View File

@@ -0,0 +1,84 @@
<!--
filename: IsraCheck.vue
author: liubin
date: 2023-12-06 09:50:13
description:
-->
<template>
<Container name="ISRA缺陷检测" size="middle" style="">
<div style="padding: 12px; display: flex; flex-direction: column; gap: 8px; height: 100%;">
<div class="f" style="flex: 9;">
<ISRAChart />
</div>
<ul
class="legend"
style="
flex: 1;
padding: 8px;
display: flex;
justify-content: center;
gap: 20px;
color: #fff;
font-size: 14px;
">
<li class="fault-1">缺陷1</li>
<li class="fault-2">缺陷2</li>
<li class="fault-3">缺陷3</li>
<li class="fault-4">缺陷4</li>
</ul>
</div>
</Container>
</template>
<script>
import Container from '../components/Container.vue';
import ShadowRect from '../components/ShadowRect.vue';
import ISRAChart from '../components/ISRAChart.vue';
export default {
name: 'IsraCheck',
components: { Container, ShadowRect, ISRAChart },
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
ul,
li {
margin: 0;
padding: 0;
list-style: none;
position: relative;
}
li::before {
content: '';
display: inline-block;
width: 8px;
height: 8px;
border-radius: 50%;
background: #ccc;
position: absolute;
top: 30%;
left: -12px;
}
li.fault-1::before {
background: #2760ff;
}
li.fault-2::before {
background: #518eec;
}
li.fault-3::before {
background: #0ee8e4;
}
li.fault-4::before {
background: #ddb523;
}
</style>

View File

@@ -0,0 +1,71 @@
<!--
filename: KilnInfo.vue
author: liubin
date: 2023-12-11 09:01:15
description:
-->
<template>
<div class="kiln-info" style="flex: 1">
<Container name="窑炉信息" size="small" style="">
<div
class="absolute"
style="
padding: 12px;
display: grid;
grid-template-columns: repeat(2, 1fr);
grid-auto-rows: auto;
gap: 8px;
">
<ShadowRect v-for="info in kilnInfo" :key="info.name" :rounded="false">
<span
style="
font-size: 16px;
line-height: 1.45;
flex: 1.2;
text-align: right;
padding-right: 8px;
letter-spacing: 1px;
">
{{ info.name }}
</span>
<span style="font-size: 16px; line-height: 1.45; flex: 1">
{{ info.value }}
<!-- {{ Math.floor(Math.random() * 100) }}Hz -->
</span>
</ShadowRect>
</div>
</Container>
</div>
</template>
<script>
import Container from '../components/Container.vue';
import ShadowRect from '../components/ShadowRect.vue';
export default {
name: 'KilnInfo',
components: { Container, ShadowRect },
props: {},
data() {
return {
kilnInfo: [
{ name: '窑炉压力', value: '83Kpa' },
{ name: '循环水温度', value: '53℃' },
{ name: '循环水流量', value: '23m³/h' },
{ name: '循环水压力', value: '33Kpa' },
{ name: '助燃风压力', value: '12Kpa' },
{ name: '碹顶加权温度', value: '32℃' },
{ name: '压缩气压力', value: '83Kpa' },
{ name: '融化加权温度', value: '123℃' },
],
};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.kiln-info {
}
</style>

View File

@@ -0,0 +1,41 @@
<!--
filename: LeftFour.vue
author: liubin
date: 2023-12-06 09:35:30
description:
-->
<template>
<div
class="left-four"
style="
display: grid;
gap: 16px;
grid-template-columns: 1fr 1fr;
grid-template-rows: 1fr 1fr;
">
<MaterialCost />
<IsraCheck />
<EnergeCost />
<FanSequence />
</div>
</template>
<script>
import MaterialCost from './MaterialCost.vue';
import FanSequence from './FanSequence.vue';
import IsraCheck from './IsraCheck.vue';
import EnergeCost from './EnergeCost.vue';
export default {
name: 'LeftFour',
components: { MaterialCost, EnergeCost, IsraCheck, FanSequence },
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss"></style>

View File

@@ -0,0 +1,58 @@
<!--
filename: MaterialCost.vue
author: liubin
date: 2023-12-06 09:09:27
description:
-->
<template>
<Container name="原料用量统计" size="middle" style="">
<div
class="absolute"
style="
padding: 12px;
display: grid;
grid-template-columns: repeat(3, 1fr);
grid-auto-rows: auto;
gap: 8px;
">
<ShadowRect v-for="n in 9" :key="n" :rounded="false">
<div
class="material"
style="
flex: 1;
padding: 6px;
display: flex;
flex-direction: column;
gap: 4px;
align-items: center;
justify-content: center;
">
<span style="color: #0ee8e4; font-weight: 500; font-size: 32px">
234
</span>
<span style="color: #fff; font-size: 14px; letter-spacing: 1px">
- 原料1/ -
</span>
</div>
</ShadowRect>
</div>
</Container>
</template>
<script>
import Container from '../components/Container.vue';
import ShadowRect from '../components/ShadowRect.vue';
export default {
name: 'MaterialCost',
components: { Container, ShadowRect },
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss"></style>

View File

@@ -0,0 +1,37 @@
<!--
filename: RightTwo.vue
author: liubin
date: 2023-12-06 10:19:00
description:
-->
<template>
<div
class="right-two"
style="display: flex; gap: 16px; flex-direction: column">
<KilnInfo />
<GasHandle />
</div>
</template>
<script>
import Container from '../components/Container.vue';
import ShadowRect from '../components/ShadowRect.vue';
import KilnLine from '../components/line';
import Switcher from '../components/Switcher.vue';
import SelectorBtnGroup from '../components/SelectorBtnGroup.vue';
import KilnInfo from './KilnInfo.vue';
import GasHandle from './GasHandle.vue';
export default {
name: 'RightTwo',
components: { Container, Switcher, SelectorBtnGroup, KilnLine, ShadowRect, KilnInfo, GasHandle },
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss"></style>

View File

@@ -0,0 +1,70 @@
<!--
filename: KilnDataBoard.vue
author: liubin
date: 2023-12-04 16:51:00
description:
-->
<template>
<div
class="KilnDataBoard"
style="
position: absolute;
top: -8px;
left: -16px;
width: calc(100% + 28px);
height: calc(100% + 38px);
display: flex;
flex-direction: column;
gap: 16px;
">
<KHeader />
<div
class="main-body"
style="flex: 1; display: flex; gap: 16px; padding: 8px 16px">
<div class="left-side" style="flex: 2">
<LeftFour />
</div>
<div class="right-side" style="flex: 1">
<RightTwo />
</div>
</div>
</div>
</template>
<script>
import KHeader from '../components/Header.vue';
import LeftFour from './LeftFour.vue';
import RightTwo from './RightTwo.vue';
export default {
name: 'KilnDataBoard',
components: {
KHeader,
LeftFour,
RightTwo,
},
// provide() {
// return {
// resizeChart: null,
// };
// },
mounted() {
// this.$el.addEventListener('resize', () => {
// console.log('resizzzze...')
// this.resizeChart = Math.random();
// });
},
data() {
return {};
},
};
</script>
<style scoped lang="scss">
.KilnDataBoard {
background: url(../assets/bg.png) no-repeat;
background-size: cover;
background-position: 0 0;
}
</style>

View File

@@ -0,0 +1,149 @@
<template>
<el-form ref="energyQuantityManualForm" :rules="rules" label-width="90px" :model="form">
<el-row :gutter="20">
<el-col :span='12'>
<el-form-item label="能源类型" prop="energyTypeId">
<el-select v-model="form.energyTypeId" placeholder="请选择" style="width: 100%;" filterable>
<el-option
v-for="item in this.energyTypeList"
: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="tableName">
<el-select v-model="form.tableName" placeholder="请选择" style="width: 100%;" filterable>
<el-option
v-for="item in getDictDatas(DICT_TYPE.TABLE_NAME)"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span='12'>
<el-form-item label="抄表数" prop="readingQuantity">
<el-input-number v-model="form.readingQuantity" :min="0" :max="999999999999" :controls='false' style="width: 50%;"></el-input-number>
<el-select v-model="form.unit" placeholder="单位" style="width: 50%;">
<el-option
v-for="item in getDictDatas(DICT_TYPE.ENERGY_UNIT)"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item label="抄表日期" prop="recordTime">
<el-date-picker
v-model="form.recordTime"
type="date"
format="yyyy-MM-dd"
value-format="timestamp"
placeholder="选择日期"
style="width: 100%;">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
import { energyQuantityManualCreate, energyQuantityManualUpdate, energyQuantityManualGet } from '@/api/base/energyQuantityManual'
import moment from 'moment'
export default {
name: 'EnergyQuantityManualAdd',
props: {
energyTypeList: {
type: Array,
required: true,
default: () => {
return []
}
}
},
data() {
return {
form: {
id: '',
energyTypeId: '',
tableName: '',
readingQuantity: null,
unit: '',
recordTime: ''
},
rules: {
energyTypeId: [{ required: true, message: '能源类型不能为空', trigger: 'change' }],
tableName: [{ required: true, message: '水/气表名不能为空', trigger: 'change' }],
readingQuantity: [{ required: true, message: '抄表数不能为空', trigger: 'blur' }],
recordTime: [{ required: true, message: '抄表日期不能为空', trigger: 'change' }]
},
isEdit: false
}
},
methods: {
init(params) {
this.form.recordTime = moment().valueOf()
if (params.type === 'add') {
this.isEdit = false
} else if (params.type === 'meterReading') {
this.isEdit = false
this.form.energyTypeId = params.energyTypeId
this.form.tableName = params.tableName + ''
}else {
this.isEdit = true
this.form.id = params.id
energyQuantityManualGet({id: this.form.id}).then(res => {
if (res.code === 0) {
this.form.energyTypeId = res.data.energyTypeId
this.form.tableName = res.data.tableName ? res.data.tableName+'' : ''
this.form.readingQuantity = res.data.readingQuantity
this.form.unit = res.data.unit ? res.data.unit+'' : ''
this.form.recordTime = res.data.recordTime ? res.data.recordTime : null
}
})
}
},
submitForm() {
this.$refs['energyQuantityManualForm'].validate((valid) => {
if (valid) {
if (!this.form.unit) {
this.$modal.msgError("抄表数单位不能为空");
return false
}
if (this.isEdit) {
// 编辑
energyQuantityManualUpdate({...this.form}).then((res) => {
if (res.code === 0) {
this.$modal.msgSuccess("操作成功");
this.$emit('successSubmit')
}
})
} else {
energyQuantityManualCreate({...this.form}).then((res) => {
if (res.code === 0) {
this.$modal.msgSuccess("操作成功");
this.$emit('successSubmit')
}
})
}
} else {
return false
}
})
},
formClear() {
this.$refs.energyQuantityManualForm.resetFields()
this.form.unit = ''
this.isEdit = false
}
}
}
</script>

View File

@@ -0,0 +1,309 @@
<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"
@selection-change="selectChange"
>
<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"
>
<energy-quantity-manual-add ref="energyQuantityManualAdd" :energyTypeList="energyTypeList" @successSubmit="successSubmit" />
</base-dialog>
</div>
</template>
<script>
import { energyQuantityManualPage, energyQuantityManualDelete, energyQuantityManualExport } from "@/api/base/energyQuantityManual"
import { getEnergyTypeListAll } from "@/api/base/energyType"
import { publicFormatter } from '@/utils/dict'
import { parseTime, parseTimeTable } from '@/utils/ruoyi'
// import FileSaver from "file-saver"
// import * as XLSX from 'xlsx/xlsx.mjs'
import EnergyQuantityManualAdd from './components/energyQuantityManualAdd'
import moment from 'moment'
const tableProps = [
{
prop: 'energyType',
label: '能源类型',
minWidth: 110,
showOverflowtooltip: true
},
{
prop: 'tableName',
label: '水/气表名',
filter: publicFormatter('table_name'),
minWidth: 110
},
{
prop: 'recordTime',
label: '抄表日期',
filter: parseTimeTable('{y}-{m}-{d}'),
minWidth: 110
},
{
prop: 'readingQuantity',
label: '抄表值'
},
{
prop: 'recordTimeLast',
label: '上期抄表日期',
filter: parseTimeTable('{y}-{m}-{d}'),
minWidth: 110
},
{
prop: 'readingQuantityLast',
label: '上期抄表值',
minWidth: 110
},
{
prop: 'diff',
label: '差值'
}
]
export default {
name: "EnergyQuantityManual",
data() {
return {
formConfig: [
{
type: 'select',
label: '能源类型',
selectOptions: [],
param: 'energyTypeId',
filterable: true
},
{
type: 'datePicker',
label: '时间',
dateType: 'daterange',
format: 'yyyy-MM-dd',
valueFormat: "timestamp",
rangeSeparator: '-',
startPlaceholder: '开始时间',
endPlaceholder: '结束时间',
param: 'timeVal',
defaultSelect: []
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary'
},
{
type: 'separate'
},
{
type: this.$auth.hasPermi('base:energy-quantity-manual:export') ? 'button' : '',
btnName: '导出',
name: 'export',
color: 'primary',
plain: true
},
{
type: this.$auth.hasPermi('base:energy-quantity-manual:create') ? 'button' : '',
btnName: '新增',
name: 'add',
color: 'success',
plain: true
}
],
tableProps,
tableH: this.tableHeight(260),
// 总条数
total: 0,
// 班次基础信息列表
list: [],
tableBtn: [
this.$auth.hasPermi('base:energy-quantity-manual:create')
? {
type: 'meterReading',
btnName: '抄表'
}
: undefined,
this.$auth.hasPermi('base:energy-quantity-manual:update')
? {
type: 'edit',
btnName: '编辑',
showParam: {
type: '&',
data: [
{
type: 'equal',
name: 'latest',
value: 1
}
]
}
}
: undefined,
this.$auth.hasPermi('base:energy-quantity-manual:delete')
? {
type: 'delete',
btnName: '删除'
}
: undefined
],
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 20,
energyTypeId: '',
recordTime: []
},
energyTypeList: [],
exportList: [],
addOrEditTitle: '',
centervisible: false,
};
},
components: { EnergyQuantityManualAdd },
created() {
window.addEventListener('resize', () => {
this.tableH = this.tableHeight(260)
})
let end = moment(moment().format('YYYY-MM-DD 23:59:59')).valueOf()
let start = moment(moment().subtract(7, 'days').format('YYYY-MM-DD 00:00:00')).valueOf()
this.formConfig[1].defaultSelect = [start, end]
this.queryParams.recordTime[0] = start
this.queryParams.recordTime[1] = end
this.getList();
this.getTypeList()
},
methods: {
buttonClick(val) {
this.queryParams.pageNo = 1;
this.queryParams.energyTypeId = val.energyTypeId
this.queryParams.recordTime[0] = val.timeVal ? moment(moment(val.timeVal[0]).format('YYYY-MM-DD 00:00:00')).valueOf() : null
this.queryParams.recordTime[1] = val.timeVal ? moment(moment(val.timeVal[1]).format('YYYY-MM-DD 23:59:59')).valueOf() : null
switch (val.btnName) {
case 'search':
this.getList()
break
case 'add':
this.addOrEditTitle = '新增'
this.centervisible = true
let params = {}
params.type = 'add'
this.$nextTick(() => {
this.$refs.energyQuantityManualAdd.init(params)
})
break
default:
this.$modal.confirm('是否确认导出').then(() => {
return energyQuantityManualExport({...this.queryParams});
}).then(response => {
this.$download.excel(response, '能源报表.xls');
}).catch(() => {})
}
},
/** 查询列表 */
getList() {
energyQuantityManualPage(this.queryParams).then(response => {
let arr = response.data.list || []
arr && arr.map(item => {
item.amount = item.amount ? (!isNaN(parseFloat(item.amount)) && isFinite(item.amount) ? item.amount.toFixed(2) : '') : ''
})
this.list = arr
this.total = response.data.total;
this.exportList = []
});
},
getTypeList() {
getEnergyTypeListAll().then((res) => {
this.formConfig[0].selectOptions = res.data || []
this.energyTypeList = res.data || []
})
},
selectChange(val) {
console.log(val)
this.exportList = val
},
handleClick(val) {
console.log(val)
switch (val.type) {
case 'edit':
this.addOrEditTitle = '编辑'
this.centervisible = true
let paramA = {}
paramA.type = 'edit'
paramA.id = val.data.id
this.$nextTick(() => {
this.$refs.energyQuantityManualAdd.init(paramA)
})
break
case 'meterReading':
this.addOrEditTitle = '新增'
this.centervisible = true
let paramB = {}
paramB.type = 'meterReading'
paramB.energyTypeId = val.data.energyTypeId
paramB.tableName = val.data.tableName
this.$nextTick(() => {
this.$refs.energyQuantityManualAdd.init(paramB)
})
break
default:
this.handleDelete(val.data)
}
},
// 新增
handleCancel() {
this.$refs.energyQuantityManualAdd.formClear()
this.centervisible = false
this.addOrEditTitle = ''
},
handleConfirm() {
this.$refs.energyQuantityManualAdd.submitForm()
},
successSubmit() {
this.handleCancel()
this.getList()
},
/** 删除按钮操作 */
handleDelete(row) {
console.log(row.id)
this.$modal.confirm('是否确认删除能源类型为"' + row.energyType + '"的数据项?').then(function() {
return energyQuantityManualDelete({id: row.id});
}).then(() => {
this.queryParams.pageNo = 1;
this.getList();
this.$modal.msgSuccess("删除成功");
}).catch(() => {});
}
}
};
</script>

View File

@@ -1,12 +1,13 @@
<template>
<el-popover placement="right" width="400" trigger="click">
<span v-if='tableProps.length'>计量维度 {{dim === 4 ? '月' : (dim === 5 ? '年' : '-')}}</span>
<el-table :data="tableData" v-if='tableProps.length'>
<el-table-column
v-for='item in tableProps'
:key="item.prop"
:prop="item.prop"
:label="item.label"
:align="item.align ? item.align : 'left'"
:align="item.align ? item.align : 'left'"
width="120">
</el-table-column>
</el-table>
@@ -70,7 +71,8 @@ export default {
tableProps: [],
singlePrice:'',
temp1,
temp2
temp2,
dim: ''
}
},
methods: {
@@ -78,7 +80,6 @@ export default {
let id = data.id
getEnergyType(id).then((res) => {
if (res.code === 0) {
console.log(res)
if (res.data.pricingMethod === 0) {
this.tableProps = this.temp1
this.singlePrice = ''
@@ -87,6 +88,7 @@ export default {
item.price = item.price.toFixed(2)
}
this.tableData = arr1
this.dim = ''
} else if (res.data.pricingMethod === 1) {
this.tableProps = this.temp2
this.singlePrice = ''
@@ -95,10 +97,12 @@ export default {
item.price = item.price.toFixed(2)
}
this.tableData = arr2
this.dim = res.data.dim
} else {
this.tableProps = []
this.tableData = []
this.singlePrice = res.data.singlePrice
this.dim = ''
}
}
})

View File

@@ -22,7 +22,6 @@ export default {
},
methods: {
changeInput() {
console.log(this.list)
this.$emit('emitData', this.list)
}
}

View File

@@ -28,7 +28,6 @@ export default {
},
methods: {
changeInput() {
console.log(this.list)
this.$emit('emitData', this.list)
}
}

View File

@@ -41,6 +41,14 @@
<el-input-number v-model="form.singlePrice" :precision="2" :min="0" :max="999999999" style="width: 100%;"></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12" v-show="form.pricingMethod === 1">
<el-form-item label="计量维度" prop="dim">
<el-select v-model="form.dim" placeholder="请选择" style="width: 100%;">
<el-option label="月" :value= '4' ></el-option>
<el-option label="年" :value= '5' ></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="24" v-show="form.pricingMethod === 0">
<el-form-item label="时间段" prop="pricingMethod">
<base-table
@@ -213,10 +221,10 @@ export default {
// 增加
emitButtonClick1() {
let n = this.tableData1.length
if (n >=3) {
this.$modal.msgWarning('最多可添加3档计价')
return false
}
// if (n >=3) {
// this.$modal.msgWarning('最多可添加3档计价')
// return false
// }
let obj = {}
obj.startTime = n === 0 ? '' : this.tableData1[n-1].endTime
obj.endTime = ''
@@ -289,6 +297,7 @@ export default {
unit: this.form.unit,
pricingMethod: this.form.pricingMethod,
description: this.form.description,
dim: this.form.pricingMethod === 1 ? this.form.dim: '',
singlePrice: this.form.pricingMethod === 2 ? this.form.singlePrice : '',
segPriceList: this.form.pricingMethod === 0 ? this.tableData1: [],
usedPriceList: this.form.pricingMethod === 1 ? this.tableData2: []
@@ -305,6 +314,7 @@ export default {
unit: this.form.unit,
pricingMethod: this.form.pricingMethod,
description: this.form.description,
dim: this.form.pricingMethod === 1 ? this.form.dim: '',
singlePrice: this.form.pricingMethod === 2 ? this.form.singlePrice : '',
segPriceList: this.form.pricingMethod === 0 ? this.tableData1: [],
usedPriceList: this.form.pricingMethod === 1 ? this.tableData2: []

View File

@@ -2,6 +2,18 @@
<el-form ref="form" :rules="rules" label-width="110px" :model="form">
<el-row>
<el-col :span="12">
<el-form-item label="抄表方式" prop="method">
<el-select v-model="form.method" placeholder="请选择" style="width: 100%;" @change="changeMethod">
<el-option
v-for="item in getDictDatas(DICT_TYPE.METHOD)"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" v-if='form.method == 1'>
<el-form-item label="监控对象" prop="objectId">
<el-cascader
style='width: 100%;'
@@ -13,8 +25,20 @@
clearable></el-cascader>
</el-form-item>
</el-col>
<el-col :span="12" v-if='form.method == 2'>
<el-form-item label="水/气表名" prop="tableName">
<el-select v-model="form.tableName" placeholder="请选择" style="width: 100%;">
<el-option
v-for="item in getDictDatas(DICT_TYPE.TABLE_NAME)"
:key="item.value"
:label="item.label"
:value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="能源类型" prop="energyTypeId">
<el-form-item label="监控能源类型" prop="energyTypeId">
<el-select v-model="form.energyTypeId" placeholder="请选择" style="width: 100%;" filterable @change="toggleType">
<el-option
v-for="item in this.energyTypeList"
@@ -25,11 +49,29 @@
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12" v-if='form.method == 1'>
<el-form-item label="监控模式" prop="type">
<el-select v-model="form.type" placeholder="请选择" style="width: 100%;" @change="typeChange">
<el-option label="合并" :value= "1" ></el-option>
<el-option label="详细" :value= "2" ></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="12" v-if='form.method == 1'>
<el-form-item label="监控详细参数" prop="type" v-if="form.type === 2">
<el-select v-model="form.plcParamId" placeholder="请选择" style="width: 100%;" @change="selectDetail">
<el-option
v-for="item in detailList"
: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="limitType">
<el-select v-model="form.limitType" placeholder="请选择" style="width: 100%;">
<el-select v-model="form.limitType" placeholder="请选择" style="width: 100%;" :disabled='form.method == 2'>
<el-option
v-for="item in getDictDatas(DICT_TYPE.MONITOR_INDEX_TYPE)"
:key="item.value"
@@ -39,34 +81,12 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="监控模式" prop="type">
<el-select v-model="form.type" placeholder="请选择" style="width: 100%;" @change="typeChange">
<el-option label="合并" :value= "1" ></el-option>
<el-option label="详细" :value= "2" ></el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item label="消耗量阈值">
<el-input-number v-model="form.minValue" placeholder="最小值" :max="9999999" style="width: 50%;"></el-input-number>
<el-input-number v-model="form.maxValue" placeholder="最大值" :max="9999999" style="width: 50%;"></el-input-number>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="监控详细参数" prop="type" v-if="form.type === 2">
<el-select v-model="form.plcParamId" placeholder="请选择" style="width: 100%;" @change="selectDetail">
<el-option
v-for="item in detailList"
:key="item.id"
:label="item.name"
:value="item.id">
</el-option>
</el-select>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
@@ -91,6 +111,7 @@ export default {
return {
form: {
id: '',
method: '1',
objectId: '',
objectType: '',
energyTypeId: '',
@@ -103,7 +124,8 @@ export default {
objIds: [],// 回显数组
isEdit: false, //是否是编辑
rules: {
objectId: [{ required: true, message: '对象不能为空', trigger: 'change' }],
method: [{ required: true, message: '抄表方式不能为空', trigger: 'change' }],
objectId: [{ required: true, message: '监控对象不能为空', trigger: 'change' }],
energyTypeId: [{ required: true, message: '能源类型不能为空', trigger: 'change' }],
type: [{ required: true, message: '监控模式不能为空', trigger: 'change' }],
limitType: [{ required: true, message: '指标类型不能为空', trigger: 'change' }]
@@ -120,6 +142,7 @@ export default {
if (res.code === 0) {
this.form = res.data
this.form.plcParamId = res.data.plcParamId || ''
this.form.method = this.form.method ? this.form.method + '' : ''
this.form.limitType = this.form.limitType ? this.form.limitType + '' : ''
this.objIds = this.changeDetSelect(this.form.objectId, this.objList)
if (this.form.type === 2) {
@@ -132,6 +155,14 @@ export default {
this.form.id = ''
}
},
// 切换方式
changeMethod() {
if(this.form.method === '2'){
this.form.limitType = "2"
}else{
this.form.limitType = ''
}
},
// 监控详细参数
getDetailList() {
getEnergyParamList({

View File

@@ -51,6 +51,11 @@ import { getTree } from '@/api/base/factory'
import { publicFormatter } from '@/utils/dict'
import EnergyLimitAdd from './components/energyLimitAdd'
const tableProps = [
{
prop: 'method',
label: '抄表方式',
filter: publicFormatter('method')
},
{
prop: 'objName',
label: '监控对象'
@@ -59,6 +64,11 @@ const tableProps = [
prop: 'objCode',
label: '对象编码'
},
{
prop: 'tableName',
label: '水/气表名',
filter: publicFormatter('table_name')
},
{
prop: 'energyType',
label: '能源类型'

View File

@@ -1,5 +1,5 @@
<template>
<div class="app-container">
<div class="app-container energyOverlimitLog">
<!-- 搜索工作栏 -->
<search-bar
@@ -7,14 +7,29 @@
ref="searchBarForm"
@headBtnClick="buttonClick"
/>
<el-tabs v-model="activeName" @tab-click="toggleTab">
<el-tab-pane label="自动抄表" name="auto"></el-tab-pane>
<el-tab-pane label="手动抄表" name="manual"></el-tab-pane>
</el-tabs>
<!-- 列表 -->
<base-table
:page="queryParams.pageNo"
:limit="queryParams.pageSize"
:table-props="tableProps"
:table-data="list"
:max-height="tableH"
/>
<div v-if="activeName === 'auto'">
<base-table
:page="queryParams.pageNo"
:limit="queryParams.pageSize"
:table-props="tableProps"
:table-data="list"
:max-height="tableH"
/>
</div>
<div v-if="activeName === 'manual'">
<base-table
:page="queryParams.pageNo"
:limit="queryParams.pageSize"
:table-props="tableProps2"
:table-data="list2"
:max-height="tableH"
/>
</div>
<pagination
:page.sync="queryParams.pageNo"
:limit.sync="queryParams.pageSize"
@@ -28,6 +43,7 @@
import { getEnergyOverlimitLogPage } from "@/api/monitoring/energyOverlimitLog";
import { getEnergyTypeListAll } from "@/api/base/energyType";
import { publicFormatter } from '@/utils/dict'
import { parseTime } from '@/utils/ruoyi'
const tableProps = [
{
prop: 'objName',
@@ -65,6 +81,41 @@ const tableProps = [
{
prop: 'overValue',
label: '超出值'
},
{
prop: 'time',
label: '提醒时间',
filter: parseTime,
minWidth: 160
}
]
const tableProps2 = [
{
prop: 'energyType',
label: '能源类型'
},
{
prop: 'limitType',
label: '指标类型',
filter: publicFormatter('monitor_index_type')
},
{
prop: 'realityValue',
label: '实际值'
},
{
prop: 'limitValue',
label: '阈值'
},
{
prop: 'overValue',
label: '超出值'
},
{
prop: 'time',
label: '提醒时间',
filter: parseTime,
minWidth: 160
}
]
export default {
@@ -93,18 +144,20 @@ export default {
color: 'primary'
}
],
activeName: 'auto',
tableProps,
tableProps2,
tableH: this.tableHeight(260),
// 总条数
total: 0,
// 班次基础信息列表
list: [],
list2: [],
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 20,
energyTypeId: '',
indexType: ''
indexType: '',
method: '1'
},
typeList: [
{id: 1, name: '合并'},
@@ -155,7 +208,47 @@ export default {
console.log(res)
this.formConfig[0].selectOptions = res.data || []
})
},
toggleTab() {
if (this.activeName === 'auto') {
this.queryParams.method = '1'
}else{
this.queryParams.method = '2'
}
this.queryParams.pageNo = 1
this.getList()
}
}
};
</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;
}
}
</style>

View File

@@ -27,20 +27,20 @@
<div class="legend">
<div class="legend-item">
<span class="icon blue"></span>
<span class="text">工作时长</span>
<span class="text">有效时长</span>
</div>
<div class="legend-item">
<span class="icon green"></span>
<span class="text">机时长</span>
<span class="text">机时长</span>
</div>
<div class="legend-item">
<span class="icon purple"></span>
<span class="text">故障时长</span>
<span class="text">中断时长</span>
</div>
<div class="legend-item">
<!-- <div class="legend-item">
<span class="icon yellow"></span>
<span class="text">速度开动率</span>
</div>
</div> -->
</div>
<div v-if="list.length" class="graph-grid">
<div class="bg-grid grid-line">
@@ -389,14 +389,14 @@ export default {
position: relative;
padding: 4px 0;
padding-left: 12px;
font-size: 14px;
font-size: 18px;
&::before {
content: '';
position: absolute;
left: 0;
top: 6px;
height: 16px;
height: 20px;
width: 4px;
border-radius: 1px;
background: #0b58ff;

View File

@@ -16,23 +16,22 @@
<div class="data-view__item">
<!-- <div class="data-view__item__value">111</div> -->
<div class="data-view__item__value">{{ textData.workTime }}</div>
<div class="data-view__item__title blue">工作时长</div>
<div class="data-view__item__title blue">有效时长</div>
</div>
<div class="data-view__item">
<!-- <div class="data-view__item__value">22</div> -->
<div class="data-view__item__value">{{ textData.stopTime }}</div>
<div class="data-view__item__title green">机时长</div>
<div class="data-view__item__title green">机时长</div>
</div>
<div class="data-view__item">
<!-- <div class="data-view__item__value">10</div> -->
<div class="data-view__item__value">{{ textData.downTime }}</div>
<div class="data-view__item__title purple">故障时长</div>
<div class="data-view__item__title purple">中断时长</div>
</div>
<div class="data-view__item">
<!-- <div class="data-view__item__value">100%</div> -->
<!-- <div class="data-view__item">
<div class="data-view__item__value">{{ textData.peEfficiency }}</div>
<div class="data-view__item__title yellow">速度开动率</div>
</div>
</div> -->
</div>
</div>
</template>
@@ -93,7 +92,7 @@ export default {
// 外环
name: '',
type: 'pie',
radius: ['75%', '90%'],
radius: ['60%', '90%'],
center: ['50%', '48%'],
label: {
show: false,
@@ -259,7 +258,7 @@ export default {
}
.data-view__item__title {
font-size: 8px;
font-size: 14px;
line-height: 14px;
}

View File

@@ -19,6 +19,7 @@
:page="1"
:limit="10"
:table-data="list"
height="65vh"
@emitFun="handleEmitFun" />
<!-- <el-row>
@@ -122,23 +123,24 @@ export default {
// : undefined,
// ].filter((v) => v),
tableProps: [
{ prop: 'factoryName', label: '工厂' },
{ prop: 'lineName', label: '产线' },
{ prop: 'sectionName', label: '工段' },
{ prop: 'equipmentName', label: '设备' },
{ prop: 'factoryName', label: '工厂', showOverflowtooltip: true },
{ prop: 'lineName', label: '产线', showOverflowtooltip: true },
{ prop: 'sectionName', label: '工段', showOverflowtooltip: true },
{ prop: 'equipmentName', label: '设备', showOverflowtooltip: true },
{
label: '有效时间',
children: [
{
width: 128,
prop: 'workTime',
label: '工作时长[h]',
label: '工作时长(h)',
filter: (val) => (val != null ? +Number(val).toFixed(2) : '-'),
},
{
width: 128,
prop: 'workRate',
label: '百分比[%]',
filter: (val) => (val != null ? +Number(val).toFixed(3) : '-'),
label: '百分比(%)',
filter: (val) => (val != null ? +Number(val).toFixed(0) : '-'),
},
],
},
@@ -148,9 +150,10 @@ export default {
{
width: 128,
prop: 'stopTime',
label: '停机时长[h]',
label: '停机时长(h)',
filter: (val) => (val != null ? +Number(val).toFixed(0) : '-'),
},
{ width: 128, prop: 'stopRate', label: '百分比[%]' },
{ width: 128, prop: 'stopRate', label: '百分比(%)', filter: (val) => (val != null ? +Number(val).toFixed(0) : '-'), },
],
},
{
@@ -159,48 +162,52 @@ export default {
{
width: 128,
prop: 'downTime',
label: '故障时长[h]',
filter: (val) => (val != null ? +val.toFixed(3) : '-'),
label: '故障时长(h)',
filter: (val) => (val != null ? +val.toFixed(2) : '-'),
},
{ width: 128, prop: 'downRate', label: '百分比[%]' },
{ width: 128, prop: 'downRate', label: '百分比(%)', filter: (val) => (val != null ? +Number(val).toFixed(0) : '-'), },
{
width: 128,
prop: 'timeEfficiency',
label: '时间开动率',
filter: (val) => (val != null ? +Number(val).toFixed(3) : '-'),
filter: (val) => (val != null ? +Number(val).toFixed(2) : '-'),
},
],
},
{
label: '速度损失',
showOverflowtooltip: true,
children: [
{
width: 128,
prop: 'realProcSpeed',
label: '实际加工速度',
filter: (val) => (val != null ? +Number(val).toFixed(2) : '-'),
},
{
width: 128,
prop: 'designProcSpeed',
label: '理论加工速度',
showOverflowtooltip: true,
filter: (val) => (val != null ? +Number(val).toFixed(2) : '-'),
},
{
width: 128,
prop: 'peEfficiency',
label: '速度开动率',
filter: (val) => (val != null ? +Number(val).toFixed(3) : '-'),
filter: (val) => (val != null ? +Number(val).toFixed(2) : '-'),
},
],
},
{
prop: 'oee',
label: 'OEE',
filter: (val) => (val != null ? +Number(val).toFixed(3) : '-'),
filter: (val) => (val != null ? +Number(val).toFixed(2) : '-'),
},
{
prop: 'teep',
label: 'TEEP',
filter: (val) => (val != null ? +Number(val).toFixed(3) : '-'),
filter: (val) => (val != null ? +Number(val).toFixed(2) : '-'),
},
// {
// _action: 'view-trend',
@@ -433,6 +440,9 @@ export default {
</script>
<style scoped lang="scss">
.app-container {
overflow: inherit;
}
.visualization {
display: grid;
grid-template-columns: repeat(3, minmax(240px, 1fr));

View File

@@ -94,7 +94,7 @@ export default {
return {
readOnly: false,
chosedLogId: false,
searchBarKeys: ['equipmentName', 'recordTime'],
searchBarKeys: ['equipmentName', 'createTime'],
tableBtn: [
// this.$auth.hasPermi('equipment:spare-parts-config:update')
// ? {
@@ -124,11 +124,11 @@ export default {
label: '报警级别',
filter: publicFormatter(this.DICT_TYPE.EQU_ALARM_LEVEL),
},
{ prop: 'createTime', label: '报警时间', filter: timeFilter }, // 接口缺
{ prop: 'alarmCode', label: '设备报警码' }, // 接口缺
{ prop: 'createTime', label: '报警时间', filter: timeFilter },
{ prop: 'alarmCode', label: '设备报警码' },
{ prop: 'alarmContent', label: '报警内容' },
{ prop: 'opt1', label: '处理记录', name: '查看', subcomponent: btn },
{ prop: 'opt2', label: '处理', name: '报警处理', subcomponent: btn }, // TODO: 是否换成按钮, 群里问
{ prop: 'opt2', label: '处理', name: '报警处理', subcomponent: btn },
// { prop: 'remark', label: '备注' },
],
searchBarFormConfig: [
@@ -145,8 +145,8 @@ export default {
dateType: 'daterange', // datetimerange
// format: 'yyyy-MM-dd HH:mm:ss',
format: 'yyyy-MM-dd',
valueFormat: 'timestamp',
// valueFormat: 'yyyy-MM-dd HH:mm:ss',
// valueFormat: 'timestamp',
valueFormat: 'yyyy-MM-dd HH:mm:ss',
rangeSeparator: '-',
startPlaceholder: '开始日期',
endPlaceholder: '结束日期',

View File

@@ -117,7 +117,7 @@
style="position: absolute; top: -40px; right: 0">
<el-button @click="handleAddAttr" type="text">
<i class="el-icon-plus"></i>
添加属性
添加参数
</el-button>
</div>
<base-table

View File

@@ -84,10 +84,10 @@ export default {
: undefined,
].filter((v) => v),
tableProps: [
{ prop: 'program', label: '巡检项目' },
{ prop: 'content', label: '巡检内容' },
{ prop: 'code', label: '巡检内容编码' },
{ prop: 'remark', label: '备注' },
{ prop: 'program', label: '巡检项目', showOverflowtooltip: true },
{ prop: 'content', label: '巡检内容', minWidth: 150, showOverflowtooltip: true },
{ prop: 'code', label: '巡检内容编码', showOverflowtooltip: true },
{ prop: 'remark', label: '备注', showOverflowtooltip: true },
],
searchBarFormConfig: [
{

View File

@@ -12,7 +12,7 @@
:show-close="false"
:wrapper-closable="isdetail"
class="drawer"
size="60%"
size="55%"
@closed="$emit('destroy')">
<small-title slot="title" :no-padding="true">
{{ isdetail ? '查看详情' : !dataForm.id ? '新增' : '编辑' }}
@@ -24,7 +24,7 @@
label-width="100px"
v-loading="formLoading">
<el-row :gutter="20">
<el-col :span="12">
<el-col :span="8">
<el-form-item label="设备名称" prop="equipmentId">
<el-select
v-model="dataForm.equipmentId"
@@ -41,7 +41,7 @@
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-col :span="8">
<!-- <el-form-item label="物料名称" prop="name">
<el-input v-model="dataForm.name" :disabled="isdetail" clearable placeholder="请输入物料名称" />
</el-form-item> -->
@@ -61,21 +61,19 @@
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-col :span="8">
<el-form-item label="设备编码" prop="equipmentCode">
<el-input v-model="dataForm.equipmentCode" disabled clearable placeholder="请输入设备编码" />
</el-form-item>
</el-col>
<el-col :span="12">
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="巡检人" prop="responsible">
<el-input v-model="dataForm.responsible" :disabled="isdetail" clearable placeholder="请输入巡检人" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-col :span="8">
<el-form-item label="巡检时间" prop="actualTime">
<el-date-picker
v-model="dataForm.actualTime"
@@ -86,7 +84,7 @@
placeholder="选择巡检时间" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-col :span="8">
<el-form-item label="数据来源" prop="origin">
<el-select
v-model="dataForm.origin"
@@ -95,7 +93,7 @@
style="width: 100%"
placeholder="请选择数据来源">
<el-option key="1" label="手动" :value="1" />
<el-option key="2" label="自动" :value="2" />
<el-option key="2" label="PDA" :value="2" />
</el-select>
</el-form-item>
</el-col>
@@ -108,7 +106,8 @@
:table-data="list" />
</el-form-item>
<el-form-item label="巡检详情" prop="description">
<editor v-model="dataForm.description" :read-only="isdetail" :min-height="150"/>
<editor v-if="!isdetail" v-model="dataForm.description" :min-height="150"/>
<div v-else v-html="dataForm.description" style="padding: 5px; margin-left: 5px; border: 1px solid #dfdfdf" />
</el-form-item>
<el-form-item label="附件">
<FileUpload v-model="file" :limit="1" :f-name="fileName" :disabled="isdetail" @name="setFileName" />
@@ -117,7 +116,7 @@
</el-form>
<div v-if="!isdetail" class="drawer-body__footer">
<el-button type="primary" @click="goback()">取消</el-button>
<el-button @click="goback()">取消</el-button>
<el-button type="primary" @click="dataFormSubmit()">确定</el-button>
</div>
</el-drawer>
@@ -185,7 +184,7 @@ export default {
actualTime: undefined,
responsible: undefined,
description: undefined,
origin: undefined,
origin: 1,
files: []
},
list: [],
@@ -220,9 +219,12 @@ export default {
async setConfig() {
const configres = await getcheckConfigByEqList({equipmentId: this.dataForm.equipmentId})
this.configList = configres.data
this.dataForm.configId = this.configList.filter(it => {
return it.id === this.dataForm.configId
})[0]?.id ?? undefined
this.dataForm.equipmentCode = this.eqList.filter(item => {
return item.id === this.dataForm.equipmentId
})[0].code
})[0]?.code ?? undefined
},
goback() {
this.$emit('refreshDataList');
@@ -265,6 +267,7 @@ export default {
this.file = this.dataForm.files[0].fileUrl
this.fileName = this.dataForm.files[0].fileName
}
this.dataForm.description = this.dataForm.description || '无'
this.setConfig()
this.setInspectionContet()
});

View File

@@ -94,7 +94,7 @@ export default {
tableProps: [
{ prop: 'configName', label: '配置名称' },
{ prop: 'equipmentName', label: '设备名称' },
{ prop: 'origin', label: '数据来源', filter: (val) => ['', '手动', '自动'][val] },
{ prop: 'origin', label: '数据来源', filter: (val) => ['', '手动', 'PDA'][val] },
// { prop: 'sectionName', label: '计划巡检时间' },
{ prop: 'actualTime', label: '实际巡检时间', filter: parseTime },
// { prop: 'maintenanceDetail', label: '完成状态' },
@@ -131,6 +131,15 @@ export default {
{
type: 'separate',
},
{
type: this.$auth.hasPermi('equipment:check-record:export')
? 'button'
: '',
btnName: '导出',
name: 'export',
plain: true,
color: 'primary',
},
{
type: this.$auth.hasPermi('equipment:check-record:create')
? 'button'
@@ -140,17 +149,6 @@ export default {
plain: true,
color: 'success',
},
{
type: 'separate',
},
{
type: this.$auth.hasPermi('equipment:check-record:export')
? 'button'
: '',
btnName: '导出',
name: 'export',
color: 'warning',
},
],
rows: [
[

View File

@@ -2,14 +2,14 @@
* @Author: zwq
* @Date: 2021-11-18 14:16:25
* @LastEditors: DY
* @LastEditTime: 2023-11-27 10:48:55
* @LastEditTime: 2023-12-01 11:02:43
* @Description:
-->
<template>
<el-drawer
:visible.sync="visible"
:show-close="false"
:wrapper-closable="false"
:wrapper-closable="true"
class="drawer"
size="50%">
<small-title slot="title" :no-padding="true">
@@ -43,6 +43,8 @@
</el-form>
</div>
<el-divider />
<div class="attr-list">
<small-title
style="margin: 16px 0; padding-left: 8px"
@@ -78,9 +80,9 @@
:page-sizes="[5, 10, 15]"
@pagination="getList" />
<div class="drawer-body__footer">
<!-- <div class="drawer-body__footer">
<el-button type="primary" @click="goback()">关闭</el-button>
</div>
</div> -->
</div>
</div>

View File

@@ -1,7 +1,7 @@
<template>
<el-dialog
:visible.sync="visible"
:width="'35%'"
:width="'30%'"
:append-to-body="true"
:close-on-click-modal="false"
class="dialog">
@@ -17,7 +17,7 @@
ref="dataForm"
:model="dataForm"
:rules="dataRule"
label-width="100px"
label-width="60px"
@keyup.enter.native="dataFormSubmit()">
<el-form-item label="巡检" prop="checkId">
<el-select v-model="dataForm.checkId" filterable placeholder="请选择巡检" style="width: 100%">

View File

@@ -66,6 +66,13 @@ export default {
addOrEditTitle: '',
searchBarKeys: ['equipmentId', 'name'],
tableBtn: [
this.$auth.hasPermi('equipment:check-setting:addInsp')
? {
type: 'add',
btnName: '添加',
showTip: '添加巡检'
}
: undefined,
this.$auth.hasPermi('equipment:check-setting:update')
? {
type: 'edit',
@@ -78,12 +85,6 @@ export default {
btnName: '查看详情',
}
: undefined,
this.$auth.hasPermi('equipment:check-setting:addInsp')
? {
type: 'add',
btnName: '添加巡检',
}
: undefined,
this.$auth.hasPermi('equipment:check-setting:delete')
? {
type: 'delete',
@@ -92,12 +93,12 @@ export default {
: undefined,
].filter((v) => v),
tableProps: [
{ prop: 'name', label: '配置名' },
{ prop: 'code', label: '编码' },
{ prop: 'lineName', label: '产线' },
{ prop: 'sectionName', label: '工段' },
{ prop: 'equipmentName', label: '设备' },
{ prop: 'equipmentCode', label: '设备编码' },
{ prop: 'name', label: '配置名', width: 110, showOverflowtooltip: true },
{ prop: 'code', label: '编码', minWidth: 150, showOverflowtooltip: true },
{ prop: 'lineName', label: '产线', showOverflowtooltip: true },
{ prop: 'sectionName', label: '工段', showOverflowtooltip: true },
{ prop: 'equipmentName', label: '设备', showOverflowtooltip: true },
{ prop: 'equipmentCode', label: '设备编码', minWidth: 150, showOverflowtooltip: true },
// { prop: 'responsible', label: '负责人' },
{ prop: 'checkNumber', label: '巡检条数' }, // TODO: 操作 选项,四个,群里询问
],

View File

@@ -183,7 +183,7 @@ export default {
btnName: '导出',
name: 'export',
plain: true,
color: 'warning',
color: 'primary',
},
],
// 是否显示弹出层

View File

@@ -170,7 +170,7 @@ export default {
btnName: '导出',
name: 'export',
plain: true,
color: 'warning',
color: 'primary',
},
{
type: this.$auth.hasPermi('equipment:maintain-record:create')

View File

@@ -60,110 +60,112 @@
</el-col>
</el-row>
<el-divider style="margin-top: -10px" />
<el-divider />
<small-title style="margin: 16px 0; padding-left: 8px" :no-padding="true">
{{ '设备维修信息' }}
</small-title>
<el-row :gutter="20">
<el-col :span="6">
<el-form-item
label="维修开始时间"
prop="maintenanceStartTime"
:rules="[{ required: true, message: '维修开始时间不能为空', trigger: 'blur' }]">
<el-date-picker
v-model="dataForm.maintenanceStartTime"
type="datetime"
:disabled="disabled"
placeholder="请选择维修开始时间"
value-format="timestamp" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item
label="维修结束时间"
prop="maintenanceFinishTime"
:rules="[{ required: true, message: '维修结束时间不能为空', trigger: 'blur' }]">
<el-date-picker
v-model="dataForm.maintenanceFinishTime"
type="datetime"
:disabled="disabled"
placeholder="请选择维修开始时间"
value-format="timestamp" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item
label="维修方式"
prop="repairMode"
:rules="[{ required: true, message: '维修方式不能为空', trigger: 'blur' }]">
<el-select
:disabled="disabled"
v-model="dataForm.repairMode"
placeholder="请选择维修方式">
<el-option
v-for="opt in getDictDatas('repair-mode')"
:key="opt.value"
:label="opt.label"
:value="opt.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="故障类型" prop="faultType">
<el-select
:disabled="disabled"
v-model="dataForm.faultType"
placeholder="请选择故障类型">
<el-option
v-for="opt in getDictDatas('fault-type')"
:key="opt.value"
:label="opt.label"
:value="opt.value" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<div v-if=" disabled && dataForm.maintenanceStatus === 1 ? true : !disabled ? true : false">
<small-title style="margin: 16px 0; padding-left: 8px" :no-padding="true">
{{ '设备维修信息' }}
</small-title>
<el-row :gutter="20">
<el-col :span="6">
<el-form-item
label="维修开始时间"
prop="maintenanceStartTime"
:rules="[{ required: true, message: '维修开始时间不能为空', trigger: 'blur' }]">
<el-date-picker
v-model="dataForm.maintenanceStartTime"
type="datetime"
:disabled="disabled"
placeholder="请选择维修开始时间"
value-format="timestamp" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item
label="维修结束时间"
prop="maintenanceFinishTime"
:rules="[{ required: true, message: '维修结束时间不能为空', trigger: 'blur' }]">
<el-date-picker
v-model="dataForm.maintenanceFinishTime"
type="datetime"
:disabled="disabled"
placeholder="请选择维修开始时间"
value-format="timestamp" />
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item
label="维修方式"
prop="repairMode"
:rules="[{ required: true, message: '维修方式不能为空', trigger: 'blur' }]">
<el-select
:disabled="disabled"
v-model="dataForm.repairMode"
placeholder="请选择维修方式">
<el-option
v-for="opt in getDictDatas('repair-mode')"
:key="opt.value"
:label="opt.label"
:value="opt.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="故障类型" prop="faultType">
<el-select
:disabled="disabled"
v-model="dataForm.faultType"
placeholder="请选择故障类型">
<el-option
v-for="opt in getDictDatas('fault-type')"
:key="opt.value"
:label="opt.label"
:value="opt.value" />
</el-select>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col>
<el-form-item
label="故障明细"
prop="faultDetail"
:rules="[{ required: true, message: '故障明细不能为空', trigger: 'blur' }]">
<!-- // 富文本 -->
<editor v-model="dataForm.faultDetail" :read-only="disabled" :min-height="150"/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col>
<el-form-item
label="故障明细"
prop="faultDetail"
:rules="[{ required: true, message: '故障明细不能为空', trigger: 'blur' }]">
<!-- // 富文本 -->
<editor v-model="dataForm.faultDetail" :read-only="disabled" :min-height="150"/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col>
<el-form-item label="维修记录" prop="maintenanceDetail">
<!-- // 富文本 -->
<editor v-model="dataForm.maintenanceDetail" :read-only="disabled" :min-height="150"/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col>
<el-form-item label="维修记录" prop="maintenanceDetail">
<!-- // 富文本 -->
<editor v-model="dataForm.maintenanceDetail" :read-only="disabled" :min-height="150"/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col>
<el-form-item label="维修附件" prop="file">
<FileUpload v-model="file" :limit="1" :f-name="fileName" :disabled="disabled" @name="setFileName" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col>
<el-form-item label="维修附件" prop="file">
<FileUpload v-model="file" :limit="1" :f-name="fileName" :disabled="disabled" @name="setFileName" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col>
<el-form-item label="备注" prop="remark">
<el-input
v-model="dataForm.remark"
:placeholder="`请输入备注`"
:disabled="disabled" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col>
<el-form-item label="备注" prop="remark">
<el-input
v-model="dataForm.remark"
:placeholder="`请输入备注`"
:disabled="disabled" />
</el-form-item>
</el-col>
</el-row>
</div>
</el-form>
<div v-if="!disabled" class="drawer-body__footer">
@@ -249,7 +251,7 @@ export default {
getEqRepair(this.dataForm.id).then(response => {
this.formLoading = false
this.dataForm = response.data;
this.dataForm.maintenanceStatus = row.maintenanceStatus || 0
this.dataForm.maintenanceStatus = this.dataForm.maintenanceStatus || 0
if (this.dataForm.files.length > 0) {
this.file = this.dataForm.files[0].fileUrl
this.fileName = this.dataForm.files[0].fileName

View File

@@ -0,0 +1,35 @@
<!--
* @Author: zhp
* @Date: 2023-11-08 14:00:52
* @LastEditTime: 2023-12-01 10:12:27
* @LastEditors: DY
* @Description:
-->
<template>
<div v-html="content" />
</template>
<script>
export default {
props: {
injectData: {
type: Object,
default: () => ({})
}
},
data() {
return {
content: ''
}
},
mounted() {
this.getContent()
},
methods: {
getContent() {
this.content = this.injectData[this.injectData.prop] ?? ''
}
}
}
</script>

View File

@@ -59,6 +59,7 @@ import basicPageMixin from '@/mixins/lb/basicPageMixin';
import CustomDialogForm from './CustomDialogForm.vue';
import { deleteRepair, exportRepairLogExcel } from '@/api/equipment/base/repair'
import { parseTime } from '@/utils/ruoyi'
import htmls from './htmls.vue'
// const timeFilter = (val) => moment(val).format('yyyy-MM-DD HH:mm:ss');
export default {
@@ -121,7 +122,7 @@ export default {
{ prop: 'lineName', label: '产线' },
{ prop: 'sectionName', label: '工段' },
{ prop: 'equipmentName', label: '设备名称', minWidth: 100, showOverflowtooltip: true },
{ prop: 'maintenanceDetail', label: '维修明细' },
{ prop: 'maintenanceDetail', label: '维修明细', subcomponent: htmls, minWidth: 100, showOverflowtooltip: true },
{ prop: 'repairman', label: '维修工', minWidth: 100, showOverflowtooltip: true },
{ prop: 'repairmanPhone', label: '联系方式', minWidth: 100, showOverflowtooltip: true },
{ prop: 'remark', label: '备注', minWidth: 120, showOverflowtooltip: true },
@@ -168,6 +169,13 @@ export default {
{
type: 'separate',
},
{
type: this.$auth.hasPermi('equipment:repair:export') ? 'button' : '',
btnName: '导出',
name: 'export',
plain: true,
color: 'primary',
},
{
type: this.$auth.hasPermi('equipment:repair:create') ? 'button' : '',
btnName: '新增',
@@ -175,13 +183,6 @@ export default {
plain: true,
color: 'success',
},
{
type: this.$auth.hasPermi('equipment:repair:export') ? 'button' : '',
btnName: '导出',
name: 'export',
plain: true,
color: 'warning',
},
],
rows: [
[

View File

@@ -9,72 +9,80 @@
<el-drawer
:visible.sync="visible"
:show-close="false"
:wrapper-closable="false"
:wrapper-closable="disabled"
class="drawer"
size="60%">
size="60%"
@closed="$emit('destroy')">
<small-title slot="title" :no-padding="true">
{{ disabled ? '查看备件' : '添加备件' }}
</small-title>
<el-form
ref="form"
:model="dataForm"
label-width="100px"
v-loading="formLoading">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="配置名" prop="name">
<span>{{ dataForm.name }}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="设备名称" prop="equipmentName">
<span>{{ dataForm.equipmentName }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="12">
<el-form-item label="负责人" prop="responsible">
<span>{{ dataForm.responsible }}</span>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="描述" prop="faultTime">
<editor v-model="dataForm.description" read-only :min-height="200"/>
</el-form-item>
</el-form>
<div class="content">
<el-form
ref="form"
:model="dataForm"
label-width="100px"
label-position="top"
v-loading="formLoading">
<el-row :gutter="20">
<el-col :span="6">
<el-form-item label="配置名" prop="name">
<span>{{ dataForm.name }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="设备名称" prop="equipmentName">
<span>{{ dataForm.equipmentName }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item label="负责人" prop="responsible">
<span>{{ dataForm.responsible }}</span>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="描述" prop="description">
<div v-html="dataForm.description" style="padding: 5px; margin: 0; border: 1px solid #dfdfdf" />
<!-- <editor v-model="dataForm.description" read-only :min-height="200"/> -->
</el-form-item>
</el-form>
<div v-if="!disabled" class="action_btn">
<template>
<span style="display: inline-block;" @click="addNew()">
<svg-icon style="width: 14px; height: 14px" class="item-icon" icon-class="table_add" />
<span class="add">添加</span>
</span>
</template>
</div>
<base-table
:table-props="tableProps"
:page="listQuery.pageNo"
:limit="listQuery.pageSize"
:table-data="list">
<method-btn
v-if="!disabled"
slot="handleBtn"
:width="120"
label="操作"
:method-list="tableBtn"
@clickBtn="handleClick" />
</base-table>
<pagination
v-show="listQuery.total > 0"
:total="listQuery.total"
:page.sync="listQuery.pageNo"
:limit.sync="listQuery.pageSize"
:page-sizes="[5, 10, 15]"
@pagination="getList" />
<div>
<small-title style="margin: 16px 0; padding-left: 8px" :no-padding="true">
{{ '备品备件' }}
</small-title>
<div v-if="!disabled" class="action_btn">
<template>
<span style="display: inline-block;" @click="addNew()">
<svg-icon style="width: 14px; height: 14px" class="item-icon" icon-class="table_add" />
<span class="add">添加</span>
</span>
</template>
</div>
<base-table
:table-props="tableProps"
:page="listQuery.pageNo"
:limit="listQuery.pageSize"
:table-data="list">
<method-btn
v-if="!disabled"
slot="handleBtn"
:width="120"
label="操作"
:method-list="tableBtn"
@clickBtn="handleClick" />
</base-table>
<pagination
v-show="listQuery.total > 0"
:total="listQuery.total"
:page.sync="listQuery.pageNo"
:limit.sync="listQuery.pageSize"
:page-sizes="[5, 10, 15]"
@pagination="getList" />
</div>
<div class="drawer-body__footer">
<el-button type="primary" @click="goback()">关闭</el-button>
<div v-if="!disabled" class="drawer-body__footer">
<el-button type="primary" @click="goback()">关闭</el-button>
</div>
</div>
<attr-add
@@ -255,10 +263,10 @@ export default {
padding: 18px;
}
.action_btn {
/* float: right; */
float: right;
display: flex;
justify-content: right;
margin: 5px 15px;
margin: -35px 15px;
font-size: 14px;
}
.add {
@@ -312,4 +320,7 @@ export default {
justify-content: flex-end;
padding: 18px;
}
.content {
padding: 0 20px;
}
</style>

View File

@@ -17,7 +17,7 @@
v-if="tableBtn.length"
slot="handleBtn"
label="操作"
:width="250"
:width="180"
:method-list="tableBtn"
@clickBtn="handleTableBtnClick" />
</base-table>
@@ -34,7 +34,7 @@
<base-dialog
:dialogTitle="title"
:dialogVisible="open"
width="35%"
width="50%"
@close="cancel"
@cancel="cancel"
@confirm="submitForm">
@@ -44,12 +44,14 @@
v-model="form"
:disabled="mode == 'detail'"
:has-files="false"
:rows="rows" />
:rows="rows"
style="margin: 0 30px" />
</base-dialog>
<addSparts
v-if="addOrUpdateVisible"
ref="addOrUpdate"
@refreshDataList="getList" />
@refreshDataList="getList"
@destroy="addOrUpdateVisible = false" />
</div>
</template>
@@ -79,22 +81,24 @@ export default {
// btnName: '详情',
// }
// : undefined,
this.$auth.hasPermi('equipment:spare-parts-config:update')
this.$auth.hasPermi('equipment:spare-parts-config:addParts')
? {
type: 'edit',
btnName: '修改',
type: 'addParts',
btnName: '添加',
showTip: '添加备件'
}
: undefined,
this.$auth.hasPermi('equipment:spare-parts-config:queryParts')
? {
type: 'queryParts',
btnName: '查看备件',
btnName: '查看',
showTip: '查看备件'
}
: undefined,
this.$auth.hasPermi('equipment:spare-parts-config:addParts')
this.$auth.hasPermi('equipment:spare-parts-config:update')
? {
type: 'addParts',
btnName: '添加备件',
type: 'edit',
btnName: '修改',
}
: undefined,
this.$auth.hasPermi('equipment:spare-parts-config:delete')
@@ -105,15 +109,15 @@ export default {
: undefined,
].filter((v) => v),
tableProps: [
{ prop: 'name', label: '配置名' },
{ prop: 'lineName', label: '产线' },
{ prop: 'sectionName', label: '工段' },
{ prop: 'equipmentName', label: '设备名' },
{ prop: 'equipmentCode', label: '设备编码' },
{ prop: 'responsible', label: '负责人' },
{ prop: 'name', label: '配置名', minWidth: 100, showOverflowtooltip: true },
{ prop: 'lineName', label: '产线', minWidth: 100, showOverflowtooltip: true },
{ prop: 'sectionName', label: '工段', minWidth: 100, showOverflowtooltip: true },
{ prop: 'equipmentName', label: '设备名', minWidth: 120, showOverflowtooltip: true },
{ prop: 'equipmentCode', label: '设备编码', minWidth: 100, showOverflowtooltip: true },
{ prop: 'responsible', label: '负责人', minWidth: 150, showOverflowtooltip: true },
// { prop: 'unit', label: '单位', filter: publicFormatter('unit_dict') },
{ prop: 'description', label: '描述', subcomponent: htmls },
{ prop: 'sparePartNumber', label: '备品备件数量' },
{ prop: 'description', label: '描述', subcomponent: htmls, minWidth: 120, showOverflowtooltip: true },
{ prop: 'sparePartNumber', label: '备品备件数量', width: 130 },
// { prop: 'remark', label: '备注' },
],
searchBarFormConfig: [
@@ -198,7 +202,7 @@ export default {
prop: 'description', // TODO: 富文本
subcomponent: Editor,
bind: {
'min-height': 192
'min-height': 150
}
},
],

View File

@@ -9,81 +9,84 @@
<el-drawer
:visible.sync="visible"
:show-close="false"
:wrapper-closable="false"
:wrapper-closable="!isLog"
class="drawer"
size="60%">
<small-title slot="title" :no-padding="true">
{{ !isLog ? '操作页面' : '更换记录' }}
</small-title>
<el-form
ref="form"
:model="dataForm"
label-width="100px"
v-loading="formLoading">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item v-if="!isLog" label="配置名" prop="name">
<span>{{ dataForm.name }}</span>
</el-form-item>
<el-form-item v-else label="产线名称" prop="lineName">
<span>{{ dataForm.lineName }}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="设备名称" prop="equipmentName">
<span>{{ dataForm.equipmentName }}</span>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="描述" prop="faultTime">
<editor v-model="dataForm.description" read-only :min-height="200"/>
</el-form-item>
</el-form>
<div v-if="!isLog">
<base-table
:table-props="tableProps"
:page="listQuery.pageNo"
:limit="listQuery.pageSize"
:table-data="list">
<method-btn
v-if="!isLog"
slot="handleBtn"
:width="120"
label="操作"
:method-list="tableBtn"
@clickBtn="handleClick" />
</base-table>
<pagination
v-show="listQuery.total > 0"
:total="listQuery.total"
:page.sync="listQuery.pageNo"
:limit.sync="listQuery.pageSize"
:page-sizes="[5, 10, 15]"
@pagination="getList" />
<div class="content">
<el-form
ref="form"
:model="dataForm"
label-width="90px"
v-loading="formLoading">
<el-row :gutter="20">
<el-col :span="12">
<el-form-item v-if="!isLog" label="配置名" prop="name">
<span style="margin-left: 5px">{{ dataForm.name }}</span>
</el-form-item>
<el-form-item v-else label="产线名称" prop="lineName">
<span style="margin-left: 5px">{{ dataForm.lineName }}</span>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item label="设备名称" prop="equipmentName">
<span style="margin-left: 5px">{{ dataForm.equipmentName }}</span>
</el-form-item>
</el-col>
</el-row>
<el-form-item label="描述" prop="description">
<div v-html="dataForm.description" style="padding: 5px; margin-left: 5px; border: 1px solid #dfdfdf" />
<!-- <editor v-model="dataForm.description" :read-only="true" :min-height="200"/> -->
</el-form-item>
</el-form>
<div v-if="!isLog">
<base-table
:table-props="tableProps"
:page="listQuery.pageNo"
:limit="listQuery.pageSize"
:table-data="list">
<method-btn
v-if="!isLog"
slot="handleBtn"
:width="120"
label="操作"
:method-list="tableBtn"
@clickBtn="handleClick" />
</base-table>
<pagination
v-show="listQuery.total > 0"
:total="listQuery.total"
:page.sync="listQuery.pageNo"
:limit.sync="listQuery.pageSize"
:page-sizes="[5, 10, 15]"
@pagination="getList" />
</div>
<div v-else>
<!-- 搜索工作栏 -->
<SearchBar
:formConfigs="formConfig"
ref="search-bar"
@headBtnClick="buttonClick" />
<base-table
:table-props="tableProps1"
:page="listQuery1.pageNo"
:limit="listQuery1.pageSize"
:table-data="list1" />
<pagination
v-show="listQuery1.total > 0"
:total="listQuery1.total"
:page.sync="listQuery1.pageNo"
:limit.sync="listQuery1.pageSize"
:page-sizes="[5, 10, 15]"
@pagination="getList1" />
</div>
</div>
<div v-else>
<!-- 搜索工作栏 -->
<SearchBar
:formConfigs="formConfig"
ref="search-bar"
@headBtnClick="buttonClick" />
<base-table
:table-props="tableProps1"
:page="listQuery1.pageNo"
:limit="listQuery1.pageSize"
:table-data="list1" />
<pagination
v-show="listQuery1.total > 0"
:total="listQuery1.total"
:page.sync="listQuery1.pageNo"
:limit.sync="listQuery1.pageSize"
:page-sizes="[5, 10, 15]"
@pagination="getList1" />
</div>
<div class="drawer-body__footer">
<div v-if="isLog" class="drawer-body__footer">
<el-button type="primary" @click="goback()">关闭</el-button>
</div>
@@ -249,7 +252,7 @@ export default {
type: 'button',
btnName: '导出',
name: 'export',
color: 'warning',
color: 'primary',
plain: true
},
],
@@ -429,4 +432,7 @@ export default {
justify-content: flex-end;
padding: 18px;
}
.content {
padding: 0 20px;
}
</style>

View File

@@ -74,8 +74,7 @@ const remainBox = {
value() {
const temp = this.injectData[this.injectData.prop] || null;
if (temp) {
console.log('12', temp);
return temp === 'Green' ? 'green' : 'red';
return temp === 'Green' ? '未超期' : temp === 'Red' ? '已超期' : '即将超期';
}
return this.injectData[this.injectData.prop] || null;
},
@@ -83,7 +82,7 @@ const remainBox = {
if (this.value) {
// const v = +this.value;
// return v < 0 ? 'red' : v >= 0 && v < 2 ? 'yellow' : 'green';
return this.value;
return this.value === '未超期' ? '#37D97F' : this.value === '已超期' ? '#FF5454' : '#FFD767';
}
return 'unset';
},
@@ -95,9 +94,9 @@ const remainBox = {
this.color
// this.color == 'Green' ? 'green' : this.color == 'Red' ? 'red' : 'yellow'
}; position:absolute; inset: 0; padding: 0 10px; display: flex; align-items: center; color: ${
this.color == 'red' || this.color == 'green' ? '#fff' : 'unset'
'#fff'
}`}>
{this.injectData[this.injectData.prop] || ''}
{this.value}
</div>
);
},
@@ -155,18 +154,19 @@ export default {
// : undefined,
].filter((v) => v),
tableProps: [
{ prop: 'name', label: '配置名' },
{ prop: 'lineName', label: '产线名称' },
{ prop: 'sectionName', label: '工段名' },
{ prop: 'equipmentName', label: '设备名称' },
{ prop: 'responsible', label: '负责人' },
{ prop: 'name', label: '配置名', showOverflowtooltip: true },
{ prop: 'lineName', label: '产线名称', showOverflowtooltip: true },
{ prop: 'sectionName', label: '工段名', showOverflowtooltip: true },
{ prop: 'equipmentName', label: '设备名称', showOverflowtooltip: true },
{ prop: 'responsible', label: '负责人', minWidth: 130, showOverflowtooltip: true },
{ prop: 'color', label: '是否超期', subcomponent: remainBox },
{ prop: 'opt1', label: '备件更换', name: '操作', subcomponent: btn },
{ prop: 'opt1', label: '备件更换', name: '操作', subcomponent: btn, width: 110 },
{
prop: 'opt2',
label: '更换记录',
name: '更新记录',
subcomponent: btn,
width: 110
}, // TODO: 是否换成按钮, 群里问
// { prop: 'remark', label: '备注' },
],

View File

@@ -290,7 +290,6 @@ export default {
break;
case '2': // 能源
this.$router.push({
// path: '/energy/monitoring/energy-report-search?startTime='+this.chooseObj.startTime+'&endTime='+this.chooseObj.endTime
path: '/energy/base/energy-quantity-realtime?startTime='+this.chooseObj.startTime+'&endTime='+this.chooseObj.endTime
})
break;

View File

@@ -0,0 +1,8 @@
<template>
<div>vocDetectionHistory</div>
</template>
<script>
export default {
name: 'VocDetectionHistory'
}
</script>

View File

@@ -0,0 +1,8 @@
<template>
<div>vocDetectionIndication</div>
</template>
<script>
export default {
name: 'VocDetectionIndication'
}
</script>

View File

@@ -0,0 +1,8 @@
<template>
<div>voc</div>
</template>
<script>
export default {
name: 'Voc'
}
</script>

View File

@@ -0,0 +1,8 @@
<template>
<div>wasteGasDetectionHistory</div>
</template>
<script>
export default {
name: 'WasteGasDetectionHistory'
}
</script>

View File

@@ -0,0 +1,8 @@
<template>
<div>wasteGasDetectionIndication</div>
</template>
<script>
export default {
name: 'WasteGasDetectionIndication'
}
</script>

View File

@@ -0,0 +1,8 @@
<template>
<div>wasteGas</div>
</template>
<script>
export default {
name: 'WasteGas'
}
</script>

View File

@@ -0,0 +1,8 @@
<template>
<div>wasteWaterDetectionHistory</div>
</template>
<script>
export default {
name: 'WasteWaterDetectionHistory'
}
</script>

View File

@@ -0,0 +1,161 @@
<template>
<el-form ref="wasteWaterAddForm" :rules="rules" label-width="130px" :model="form">
<el-row :gutter="20">
<el-col :span='12'>
<el-form-item label="指标名称" prop="name">
<el-input v-model="form.name"></el-input>
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item label="指标编码" prop="code">
<el-input v-model="form.code"></el-input>
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item label="指标名称" prop="name1">
<el-input v-model="form.name"></el-input>
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item label="最小值" prop="code11">
<el-input v-model="form.code"></el-input>
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item label="最大值" prop="name12">
<el-input v-model="form.name"></el-input>
</el-form-item>
</el-col>
<el-col :span='12'>
<el-form-item label="备注" prop="code1122">
<el-input v-model="form.code"></el-input>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
export default {
name: 'WasteWaterAdd',
data() {
return {
// rules: {
// name: [{ required: true, message: "订单名称不能为空", trigger: "blur" }],
// code: [{ required: true, message: "订单号不能为空", trigger: "blur" }],
// planQuantity: [{ required: true, message: "计划加工数量不能为空", trigger: "blur" }],
// planProductId: [{ required: true, message: "产品名称不能为空", trigger: "change" }]
// }
}
},
methods: {
// init(id) {
// this.getList()
// if (id) {
// this.isEdit = true
// this.form.id = id
// getOrderById({id: this.form.id}).then(res => {
// if (res.code === 0) {
// this.form.name = res.data.name
// this.form.code = res.data.code
// this.form.planQuantity = res.data.planQuantity
// this.form.planProductId = res.data.planProductId
// this.form.price = res.data.price
// this.form.customerId = res.data.customerId
// this.form.priority = res.data.priority ? res.data.priority + '' : ''
// this.form.planStartTime = res.data.planStartTime ? res.data.planStartTime : null
// this.form.packSpec = res.data.packSpec ? res.data.packSpec+'' : ''
// this.form.workers = res.data.workers
// this.form.processFlowId = res.data.processFlowId
// this.form.materialMethod = res.data.materialMethod
// this.form.planFinishTime = res.data.planFinishTime ? res.data.planFinishTime : null
// this.form.remark = res.data.remark
// // this.form.description = res.data.description
// }
// })
// } else {
// this.isEdit = false
// this.form.id = ''
// // 订单号
// getOrderCode().then(res => {
// this.form.code = res.data || ''
// })
// }
// },
// getList() {
// // 产品
// getProductAll().then(res => {
// this.productList = res.data || []
// })
// // 客户
// getCustomerList().then(res => {
// this.customerList = res.data || []
// })
// // 工艺
// getProcessFlowList().then(res => {
// this.processFlowList = res.data || []
// })
// },
// timeChange() {
// if (this.form.planStartTime && this.form.planFinishTime) {
// if (this.form.planStartTime > this.form.planFinishTime) {
// this.$modal.msgError('计划开始时间不能大于结束时间')
// }
// }
// },
// // 工艺变更
// materialMethodChange(val) {
// if (val === 2 && !this.form.processFlowId) {
// this.form.materialMethod = 1
// this.$modal.msgError("请先选择关联工艺");
// }
// },
// // 工艺变更
// processFlowIdChange(val) {
// console.log(val)
// if (!val) {
// this.form.materialMethod = 1
// }
// },
// submitForm() {
// this.$refs['orderAddForm'].validate((valid) => {
// if (valid) {
// if (this.form.planStartTime && this.form.planFinishTime) {
// if (this.form.planStartTime > this.form.planFinishTime) {
// this.$modal.msgError('计划开始时间不能大于结束时间')
// return false
// }
// }
// // console.log(this.form)
// if (this.isEdit) {
// //编辑
// orderUpdate({ ...this.form }).then((res) => {
// if (res.code === 0) {
// this.$modal.msgSuccess("操作成功");
// this.$emit('successSubmit')
// }
// })
// } else {
// this.form.status = 1
// this.form.triggerOrigin = 1
// orderCreate({ ...this.form }).then((res) => {
// if (res.code === 0) {
// this.$modal.msgSuccess("操作成功");
// this.$emit('successSubmit')
// }
// })
// }
// } else {
// return false
// }
// })
// },
// formClear() {
// this.$refs.orderAddForm.resetFields()
// this.form.materialMethod = 1
// this.form.price = 0.00
// this.form.planQuantity = 0
// this.isEdit = false
// }
}
}
</script>

View File

@@ -0,0 +1,202 @@
<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='60%'
>
<waste-water-add ref="wasteWaterAdd" @successSubmit="successSubmit" />
</base-dialog>
</div>
</template>
<script>
import { parseTime } from '@/utils/ruoyi'
// import { publicFormatter } from '@/utils/dict'
const tableProps = [
{
prop: 'name',
label: '指示名称',
minWidth: 120,
showOverflowtooltip: true
},
{
prop: 'code',
label: '指示编码',
minWidth: 120
},
{
prop: 'customerId',
label: '单位'
},
{
prop: 'customerId1',
label: '最小值'
},
{
prop: 'customerId2',
label: '最大值'
},
{
prop: 'customerId3',
label: '创建人'
},
// {
// prop: 'triggerOrigin',
// label: '来源',
// filter: publicFormatter('order_Origin')
// },
{
prop: 'createTime',
label: '创建时间',
filter: parseTime,
minWidth: 160
}
]
export default {
name: 'WasteWaterDetectionIndication',
data() {
return {
formConfig: [
{
type: 'select',
label: '指标名称',
selectOptions: this.getDictDatas(this.DICT_TYPE.ORDER_STATUS),
labelField: 'label',
valueField: 'value',
param: 'name'
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary'
},
{
type: this.$auth.hasPermi('base:order-manage:create') ? 'separate' : '',
},
{
type: this.$auth.hasPermi('base:order-manage:create') ? 'button' : '',
btnName: '新增',
name: 'add',
color: 'success',
plain: true
}
],
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 20,
name: null,
status: null
},
total: 0,
tableProps,
list: [
{name:'1111'}
],
tableH: this.tableHeight(260),
tableBtn: [
this.$auth.hasPermi('base:order-manage:edit')
? {
type: 'edit',
btnName: '编辑'
}
: undefined,
this.$auth.hasPermi('base:order-manage:delete')
? {
type: 'delete',
btnName: '删除'
}
: undefined
],
addOrEditTitle: '',
centervisible: false
}
},
methods: {
getList() {},
buttonClick(val) {
console.log(val)
if (val.btnName === 'search') {
this.queryParams.name = val.name
this.getList()
} else {
this.addOrEditTitle = '新增'
this.centervisible = true
this.$nextTick(() => {
this.$refs.wasteWaterAdd.init()
})
}
},
handleClick(val) {
console.log(val)
switch (val.type) {
case 'edit':
this.addOrEditTitle = '编辑'
this.centervisible = true
this.$nextTick(() => {
this.$refs.wasteWaterAdd.init(val.data.id)
})
break
default:
this.handleDelete(val.data)
}
},
// 删除
handleDelete(val) {
this.$modal.confirm('是否确认删除"' + val.name + '"的数据项?').then(function() {
// return wasteWaterDelete({ id: val.id })
}).then(() => {
this.getList();
this.$modal.msgSuccess("操作成功");
}).catch(() => {});
},
// 新增
handleCancel() {
this.$refs.wasteWaterAdd.formClear()
this.centervisible = false
this.addOrEditTitle = ''
},
handleConfirm() {
this.$refs.wasteWaterAdd.submitForm()
},
successSubmit() {
this.handleCancel()
this.getList()
}
}
}
</script>

View File

@@ -0,0 +1,8 @@
<template>
<div>wasteWater</div>
</template>
<script>
export default {
name: 'WasteWater'
}
</script>

View File

@@ -0,0 +1,522 @@
<!--
filename: SpecialEquipmentForFireFighting.vue
author: liubin
date: 2023-12-12 13:51:23
description:
-->
<template>
<div class="app-container SpecialEquipmentForFireFighting">
<!-- 搜索工作栏 -->
<SearchBar
:formConfigs="searchBarFormConfig"
ref="search-bar"
@headBtnClick="handleSearchBarBtnClick" />
<!-- 列表 -->
<base-table
:table-props="tableProps"
:page="queryParams.pageNo"
:limit="queryParams.pageSize"
:table-data="list"
@emitFun="handleEmitFun">
<method-btn
v-if="tableBtn.length"
slot="handleBtn"
:width="120"
label="操作"
:method-list="tableBtn"
@clickBtn="handleTableBtnClick" />
</base-table>
<!-- 分页组件 -->
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNo"
:limit.sync="queryParams.pageSize"
@pagination="getList" />
<!-- 对话框(添加) -->
<base-dialog
:dialogTitle="title"
:dialogVisible="open"
@close="cancel"
@cancel="cancel"
width="45%"
@confirm="submitForm">
<DialogForm
v-if="open"
key="index-dialog-form"
ref="form"
label-position="top"
size="small"
v-model="form"
:has-files="true"
:disabled="editMode === 'detail'"
:rows="computedRows" />
<!-- :has-files="['files', 'files2']" -->
</base-dialog>
<!-- 设备 详情 - 编辑 -->
<!-- <EquipmentDrawer
v-if="editVisible"
ref="drawer"
:mode="editMode"
@update-mode="editMode = $event"
:data-id="form.id"
:sections="[
{
name: '基本信息',
key: 'base',
rows: computedRows,
url: '/base/core-equipment/get',
urlUpdate: '/base/core-equipment/update',
urlCreate: '/base/core-equipment/create',
queryParams: { id: form.id },
},
{
name: '属性列表',
key: 'attrs',
props: drawerListProps,
url: '/base/core-equipment-attr/page',
urlCreate: '/base/core-equipment-attr/create',
urlUpdate: '/base/core-equipment-attr/update',
urlDelete: '/base/core-equipment-attr/delete',
urlDetail: '/base/core-equipment-attr/get',
queryParams: {
equipmentId: form.id,
pageNo: 1,
pageSize: 10,
},
tableBtn: [
this.$auth.hasPermi('base:core-equipment-attr:update')
? {
type: 'edit',
btnName: '修改',
}
: undefined,
this.$auth.hasPermi('base:core-equipment-attr:delete')
? {
type: 'delete',
btnName: '删除',
}
: undefined,
].filter((v) => v),
allowAdd: true,
},
]"
@refreshDataList="getList"
@cancel="cancelEdit"
@destroy="cancelEdit" /> -->
</div>
</template>
<script>
import moment from 'moment';
import basicPageMixin from '@/mixins/lb/basicPageMixin';
import EquipmentDrawer from '../components/EquipmentDrawer';
import {
createEquipment,
updateEquipment,
deleteEquipment,
getEquipment,
getEquipmentPage,
exportEquipmentExcel,
} from '@/api/base/equipment';
import Editor from '@/components/Editor';
import AssetsUpload from '../components/AssetsUpload.vue';
export default {
name: 'SpecialEquipmentForFireFighting',
components: {
Editor,
EquipmentDrawer,
},
mixins: [basicPageMixin],
data() {
return {
searchBarKeys: ['name', 'code'],
tableBtn: [
this.$auth.hasPermi(`base:core-equipment:update`)
? {
type: 'detail',
btnName: '详情',
}
: undefined,
this.$auth.hasPermi('base:core-equipment:update')
? {
type: 'edit',
btnName: '修改',
}
: undefined,
this.$auth.hasPermi('base:core-equipment:delete')
? {
type: 'delete',
btnName: '删除',
}
: undefined,
].filter((v) => v),
tableProps: [
// {
// prop: 'createTime',
// label: '添加时间',
// fixed: true,
// width: 180,
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
// },
{ prop: 'name', label: '设备名称' },
{ width: 256, prop: 'code', label: '设备编码' },
{ prop: 'location', label: '位置' },
{ prop: 'responsiblePeopleName', label: '负责人' },
{ prop: 'dueDate', label: '有效期至' },
{ prop: 'remark', label: '备注' },
],
searchBarFormConfig: [
{
type: 'input',
label: '名称',
placeholder: '请输入设备名称',
param: 'name',
},
{
type: 'input',
label: '编码',
placeholder: '请输入设备编码',
param: 'code',
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary',
},
{
type: 'separate',
},
{
type: this.$auth.hasPermi('base:core-equipment:export')
? 'button'
: '',
btnName: '导出',
name: 'export',
plain: true,
color: 'primary',
},
{
type: this.$auth.hasPermi('base:core-equipment:create')
? 'button'
: '',
btnName: '新增',
name: 'add',
plain: true,
color: 'success',
},
],
rows: [
[
{
input: true,
label: '设备名称',
prop: 'name',
rules: [
{ required: true, message: '设备名称不能为空', trigger: 'blur' },
],
},
{
input: true,
label: '设备编码',
prop: 'code',
url: '/base/core-equipment/getCode',
rules: [
{ required: true, message: '设备编码不能为空', trigger: 'blur' },
],
},
],
[
{
input: true,
label: '所在区域',
prop: 'location',
},
{
select: true,
label: '负责人',
prop: 'responsiblePeopleId',
url: '/base/core-worker/listAll',
},
],
[
{
datetime: true,
label: '有效期至',
prop: 'dueDate',
bind: { clearable: true },
},
{},
],
[{ input: true, label: '备注', prop: 'remark' }],
[
{
upload: true,
label: '设备图片',
prop: 'files',
fileType: 1,
},
],
],
editVisible: false,
editMode: 'edit', // 'edit', 'detail'
// drawer 里的设备属性列表配置项
drawerListProps: [
{
prop: 'createTime',
label: '添加时间',
fixed: true,
width: 180,
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
},
{ prop: 'name', label: '属性名称' },
{ prop: 'value', label: '属性值' },
],
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 10,
code: '',
name: '',
},
// 表单参数
form: {
id: null,
files: [],
},
showUploadComponents: false, // 是否显示上传组件
};
},
computed: {
computedRows() {
return this.showUploadComponents
? [
...this.rows,
[
{
assetUpload: true,
key: 'eq-assets', // 用于区分不同的上传组件
label: '上传资料',
fieldName: 'assets',
subcomponent: AssetsUpload,
prop: 'uploadedAssets',
default: [],
bind: {
'is-pic-mode': false,
},
},
],
[
{
assetUpload: true,
key: 'eq-pics', // 用于区分不同的上传组件
label: '上传图片',
fieldName: 'images',
subcomponent: AssetsUpload,
// prop: '',
// default: [],
bind: {
'is-pic-mode': true,
},
},
],
]
: this.rows;
},
},
mounted() {
this.getList();
},
activated() {
this.getList();
},
methods: {
/** 查询列表 */
getList() {
this.loading = true;
// 执行查询
getEquipmentPage({
...this.queryParams,
specialType: 2,
special: true,
}).then((response) => {
this.list = response.data.list;
this.total = response.data.total;
this.loading = false;
});
},
/** 取消按钮 */
cancel() {
this.open = false;
this.reset();
},
cancelEdit() {
this.showUploadComponents = false;
this.editVisible = false;
},
/** 表单重置 */
reset() {
this.form = {
id: undefined,
code: undefined,
name: undefined,
enName: undefined,
abbr: undefined,
enterTime: undefined,
productionTime: undefined,
equipmentTypeId: undefined,
groupId: undefined,
tvalue: undefined,
processingTime: undefined,
manufacturer: undefined,
spec: undefined,
description: undefined,
remark: undefined,
files: [],
files2: [],
};
this.resetForm('form');
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.showUploadComponents = false;
this.title = '添加设备';
this.editMode = 'add';
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
this.showUploadComponents = false;
this.editMode = 'edit';
const id = row.id;
getEquipment(id).then((response) => {
this.form = response.data;
this.open = true;
this.title = '修改设备';
});
},
handleDetail(row) {
this.reset();
this.showUploadComponents = false;
const id = row.id;
this.editMode = 'detail';
getEquipment(id).then((response) => {
this.form = response.data;
this.open = true;
this.title = '查看详情';
});
},
/** 提交按钮 */
submitForm() {
this.$refs['form'].validate((valid) => {
if (!valid) {
return;
}
const payload = Object.assign(
{ special: true, specialType: 2 },
this.form
);
// payload.files = [...payload.files, ...payload.files2];
// delete payload.files2;
// 修改的提交
if (this.form.id != null) {
updateEquipment(payload).then((response) => {
this.$modal.msgSuccess('修改成功');
this.open = false;
this.getList();
});
return;
}
// 添加的提交
createEquipment(payload).then((response) => {
this.$modal.msgSuccess('新增成功');
this.open = false;
this.getList();
});
});
},
/** 删除按钮操作 */
handleDelete(row) {
const id = row.id;
this.$modal
.confirm('是否确认删除设备名称为"' + row.name + '"的数据项?')
.then(function () {
return deleteEquipment(id);
})
.then(() => {
this.getList();
this.$modal.msgSuccess('删除成功');
})
.catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
// 处理查询参数
let params = { ...this.queryParams, special: true, specialType: 2 };
params.pageNo = undefined;
params.pageSize = undefined;
this.$modal
.confirm('是否确认导出所有设备数据项?')
.then(() => {
this.exportLoading = true;
return exportEquipmentExcel(params);
})
.then((response) => {
this.$download.excel(response, '消防设备.xls');
this.exportLoading = false;
})
.catch(() => {});
},
// 查看详情
viewDetail(id) {
this.reset();
this.editMode = 'detail';
this.showUploadComponents = true;
this.form.id = id;
this.editVisible = true;
this.$nextTick(() => {
this.$refs['drawer'].init();
});
},
// overwrite basicPageMixin 里的 处理表格按钮 方法
// handleTableBtnClick({ data, type }) {
// switch (type) {
// case 'edit':
// this.reset();
// this.editMode = 'edit';
// this.showUploadComponents = true;
// this.form.id = data.id;
// this.editVisible = true;
// this.$nextTick(() => {
// this.$refs['drawer'].init();
// });
// break;
// case 'delete':
// this.handleDelete(data);
// break;
// case 'detail':
// const { id } = data;
// this.viewDetail(id);
// break;
// }
// },
},
};
</script>
<style scoped lang="scss">
.SpecialEquipmentForFireFighting {
}
</style>

View File

@@ -0,0 +1,512 @@
<!--
filename: SpecialEquipmentManagement.vue
author: liubin
date: 2023-12-12 13:51:23
description:
-->
<template>
<div class="app-container SpecialEquipmentManagement">
<!-- 搜索工作栏 -->
<SearchBar
:formConfigs="searchBarFormConfig"
ref="search-bar"
@headBtnClick="handleSearchBarBtnClick" />
<!-- 列表 -->
<base-table
:table-props="tableProps"
:page="queryParams.pageNo"
:limit="queryParams.pageSize"
:table-data="list"
@emitFun="handleEmitFun">
<method-btn
v-if="tableBtn.length"
slot="handleBtn"
:width="120"
label="操作"
:method-list="tableBtn"
@clickBtn="handleTableBtnClick" />
</base-table>
<!-- 分页组件 -->
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNo"
:limit.sync="queryParams.pageSize"
@pagination="getList" />
<!-- 对话框(添加) -->
<base-dialog
:dialogTitle="title"
:dialogVisible="open"
@close="cancel"
@cancel="cancel"
width="45%"
@confirm="submitForm">
<DialogForm
v-if="open"
key="index-dialog-form"
ref="form"
label-position="top"
size="small"
v-model="form"
:has-files="true"
:disabled="editMode === 'detail'"
:rows="computedRows" />
<!-- :has-files="['files', 'files2']" -->
</base-dialog>
<!-- 设备 详情 - 编辑 -->
<!-- <EquipmentDrawer
v-if="editVisible"
ref="drawer"
:mode="editMode"
@update-mode="editMode = $event"
:data-id="form.id"
:sections="[
{
name: '基本信息',
key: 'base',
rows: computedRows,
url: '/base/core-equipment/get',
urlUpdate: '/base/core-equipment/update',
urlCreate: '/base/core-equipment/create',
queryParams: { id: form.id },
},
{
name: '属性列表',
key: 'attrs',
props: drawerListProps,
url: '/base/core-equipment-attr/page',
urlCreate: '/base/core-equipment-attr/create',
urlUpdate: '/base/core-equipment-attr/update',
urlDelete: '/base/core-equipment-attr/delete',
urlDetail: '/base/core-equipment-attr/get',
queryParams: {
equipmentId: form.id,
pageNo: 1,
pageSize: 10,
},
tableBtn: [
this.$auth.hasPermi('base:core-equipment-attr:update')
? {
type: 'edit',
btnName: '修改',
}
: undefined,
this.$auth.hasPermi('base:core-equipment-attr:delete')
? {
type: 'delete',
btnName: '删除',
}
: undefined,
].filter((v) => v),
allowAdd: true,
},
]"
@refreshDataList="getList"
@cancel="cancelEdit"
@destroy="cancelEdit" /> -->
</div>
</template>
<script>
import moment from 'moment';
import basicPageMixin from '@/mixins/lb/basicPageMixin';
import EquipmentDrawer from '../components/EquipmentDrawer';
import {
createEquipment,
updateEquipment,
deleteEquipment,
getEquipment,
getEquipmentPage,
exportEquipmentExcel,
} from '@/api/base/equipment';
import Editor from '@/components/Editor';
import AssetsUpload from '../components/AssetsUpload.vue';
export default {
name: 'SpecialEquipmentManagement',
components: {
Editor,
EquipmentDrawer,
},
mixins: [basicPageMixin],
data() {
return {
searchBarKeys: ['name', 'code'],
tableBtn: [
this.$auth.hasPermi(`base:core-equipment:update`)
? {
type: 'detail',
btnName: '详情',
}
: undefined,
this.$auth.hasPermi('base:core-equipment:update')
? {
type: 'edit',
btnName: '修改',
}
: undefined,
this.$auth.hasPermi('base:core-equipment:delete')
? {
type: 'delete',
btnName: '删除',
}
: undefined,
].filter((v) => v),
tableProps: [
// {
// prop: 'createTime',
// label: '添加时间',
// fixed: true,
// width: 180,
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
// },
{ prop: 'name', label: '设备名称' },
{ width: 256, prop: 'code', label: '设备编码' },
{ prop: 'location', label: '位置' },
{ prop: 'responsiblePeopleName', label: '负责人' },
{ prop: 'remark', label: '备注' },
],
searchBarFormConfig: [
{
type: 'input',
label: '名称',
placeholder: '请输入设备名称',
param: 'name',
},
{
type: 'input',
label: '编码',
placeholder: '请输入设备编码',
param: 'code',
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary',
},
{
type: 'separate',
},
{
type: this.$auth.hasPermi('base:core-equipment:export')
? 'button'
: '',
btnName: '导出',
name: 'export',
plain: true,
color: 'primary',
},
{
type: this.$auth.hasPermi('base:core-equipment:create')
? 'button'
: '',
btnName: '新增',
name: 'add',
plain: true,
color: 'success',
},
],
rows: [
[
{
input: true,
label: '设备名称',
prop: 'name',
rules: [
{ required: true, message: '设备名称不能为空', trigger: 'blur' },
],
},
{
input: true,
label: '设备编码',
prop: 'code',
url: '/base/core-equipment/getCode',
rules: [
{ required: true, message: '设备编码不能为空', trigger: 'blur' },
],
},
],
[
{
input: true,
label: '所在区域',
prop: 'location',
},
{
select: true,
label: '负责人',
prop: 'responsiblePeopleId',
url: '/base/core-worker/listAll',
},
],
[{ input: true, label: '备注', prop: 'remark' }],
[
{
upload: true,
label: '设备图片',
prop: 'files',
fileType: 1,
},
],
],
editVisible: false,
editMode: 'edit', // 'edit', 'detail'
// drawer 里的设备属性列表配置项
drawerListProps: [
{
prop: 'createTime',
label: '添加时间',
fixed: true,
width: 180,
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
},
{ prop: 'name', label: '属性名称' },
{ prop: 'value', label: '属性值' },
],
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 10,
code: '',
name: '',
},
// 表单参数
form: {
id: null,
files: [],
},
showUploadComponents: false, // 是否显示上传组件
};
},
computed: {
computedRows() {
return this.showUploadComponents
? [
...this.rows,
[
{
assetUpload: true,
key: 'eq-assets', // 用于区分不同的上传组件
label: '上传资料',
fieldName: 'assets',
subcomponent: AssetsUpload,
prop: 'uploadedAssets',
default: [],
bind: {
'is-pic-mode': false,
},
},
],
[
{
assetUpload: true,
key: 'eq-pics', // 用于区分不同的上传组件
label: '上传图片',
fieldName: 'images',
subcomponent: AssetsUpload,
// prop: '',
// default: [],
bind: {
'is-pic-mode': true,
},
},
],
]
: this.rows;
},
},
mounted() {
this.getList();
},
activated() {
this.getList();
},
methods: {
/** 查询列表 */
getList() {
this.loading = true;
// 执行查询
getEquipmentPage({
...this.queryParams,
specialType: 3,
special: true,
}).then((response) => {
this.list = response.data.list;
this.total = response.data.total;
this.loading = false;
});
},
/** 取消按钮 */
cancel() {
this.open = false;
this.reset();
},
cancelEdit() {
this.showUploadComponents = false;
this.editVisible = false;
},
/** 表单重置 */
reset() {
this.form = {
id: undefined,
code: undefined,
name: undefined,
enName: undefined,
abbr: undefined,
enterTime: undefined,
productionTime: undefined,
equipmentTypeId: undefined,
groupId: undefined,
tvalue: undefined,
processingTime: undefined,
manufacturer: undefined,
spec: undefined,
description: undefined,
remark: undefined,
files: [],
files2: [],
};
this.resetForm('form');
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.showUploadComponents = false;
this.title = '添加设备';
this.editMode = 'add';
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
this.showUploadComponents = false;
this.editMode = 'edit';
const id = row.id;
getEquipment(id).then((response) => {
this.form = response.data;
this.open = true;
this.title = '修改设备';
});
},
handleDetail(row) {
this.reset();
this.showUploadComponents = false;
const id = row.id;
this.editMode = 'detail';
getEquipment(id).then((response) => {
this.form = response.data;
this.open = true;
this.title = '查看详情';
});
},
/** 提交按钮 */
submitForm() {
this.$refs['form'].validate((valid) => {
if (!valid) {
return;
}
const payload = Object.assign(
{ special: true, specialType: 3 },
this.form
);
// payload.files = [...payload.files, ...payload.files2];
// delete payload.files2;
// 修改的提交
if (this.form.id != null) {
updateEquipment(payload).then((response) => {
this.$modal.msgSuccess('修改成功');
this.open = false;
this.getList();
});
return;
}
// 添加的提交
createEquipment(payload).then((response) => {
this.$modal.msgSuccess('新增成功');
this.open = false;
this.getList();
});
});
},
/** 删除按钮操作 */
handleDelete(row) {
const id = row.id;
this.$modal
.confirm('是否确认删除设备名称为"' + row.name + '"的数据项?')
.then(function () {
return deleteEquipment(id);
})
.then(() => {
this.getList();
this.$modal.msgSuccess('删除成功');
})
.catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
// 处理查询参数
let params = { ...this.queryParams, special: true, specialType: 3 };
params.pageNo = undefined;
params.pageSize = undefined;
this.$modal
.confirm('是否确认导出所有设备数据项?')
.then(() => {
this.exportLoading = true;
return exportEquipmentExcel(params);
})
.then((response) => {
this.$download.excel(response, '特种设备.xls');
this.exportLoading = false;
})
.catch(() => {});
},
// 查看详情
viewDetail(id) {
this.reset();
this.editMode = 'detail';
this.showUploadComponents = true;
this.form.id = id;
this.editVisible = true;
this.$nextTick(() => {
this.$refs['drawer'].init();
});
},
// overwrite basicPageMixin 里的 处理表格按钮 方法
// handleTableBtnClick({ data, type }) {
// switch (type) {
// case 'edit':
// this.reset();
// this.editMode = 'edit';
// this.showUploadComponents = true;
// this.form.id = data.id;
// this.editVisible = true;
// this.$nextTick(() => {
// this.$refs['drawer'].init();
// });
// break;
// case 'delete':
// this.handleDelete(data);
// break;
// case 'detail':
// const { id } = data;
// this.viewDetail(id);
// break;
// }
// },
},
};
</script>
<style scoped lang="scss">
.SpecialEquipmentManagement {
}
</style>

View File

@@ -0,0 +1,512 @@
<!--
filename: Safety.vue
author: liubin
date: 2023-12-12 13:51:23
description:
-->
<template>
<div class="app-container SpecialEquipmentForSafety">
<!-- 搜索工作栏 -->
<SearchBar
:formConfigs="searchBarFormConfig"
ref="search-bar"
@headBtnClick="handleSearchBarBtnClick" />
<!-- 列表 -->
<base-table
:table-props="tableProps"
:page="queryParams.pageNo"
:limit="queryParams.pageSize"
:table-data="list"
@emitFun="handleEmitFun">
<method-btn
v-if="tableBtn.length"
slot="handleBtn"
:width="120"
label="操作"
:method-list="tableBtn"
@clickBtn="handleTableBtnClick" />
</base-table>
<!-- 分页组件 -->
<pagination
v-show="total > 0"
:total="total"
:page.sync="queryParams.pageNo"
:limit.sync="queryParams.pageSize"
@pagination="getList" />
<!-- 对话框(添加) -->
<base-dialog
:dialogTitle="title"
:dialogVisible="open"
@close="cancel"
@cancel="cancel"
width="45%"
@confirm="submitForm">
<DialogForm
v-if="open"
key="index-dialog-form"
ref="form"
label-position="top"
size="small"
v-model="form"
:has-files="true"
:disabled="editMode === 'detail'"
:rows="computedRows" />
<!-- :has-files="['files', 'files2']" -->
</base-dialog>
<!-- 设备 详情 - 编辑 -->
<!-- <EquipmentDrawer
v-if="editVisible"
ref="drawer"
:mode="editMode"
@update-mode="editMode = $event"
:data-id="form.id"
:sections="[
{
name: '基本信息',
key: 'base',
rows: computedRows,
url: '/base/core-equipment/get',
urlUpdate: '/base/core-equipment/update',
urlCreate: '/base/core-equipment/create',
queryParams: { id: form.id },
},
{
name: '属性列表',
key: 'attrs',
props: drawerListProps,
url: '/base/core-equipment-attr/page',
urlCreate: '/base/core-equipment-attr/create',
urlUpdate: '/base/core-equipment-attr/update',
urlDelete: '/base/core-equipment-attr/delete',
urlDetail: '/base/core-equipment-attr/get',
queryParams: {
equipmentId: form.id,
pageNo: 1,
pageSize: 10,
},
tableBtn: [
this.$auth.hasPermi('base:core-equipment-attr:update')
? {
type: 'edit',
btnName: '修改',
}
: undefined,
this.$auth.hasPermi('base:core-equipment-attr:delete')
? {
type: 'delete',
btnName: '删除',
}
: undefined,
].filter((v) => v),
allowAdd: true,
},
]"
@refreshDataList="getList"
@cancel="cancelEdit"
@destroy="cancelEdit" /> -->
</div>
</template>
<script>
import moment from 'moment';
import basicPageMixin from '@/mixins/lb/basicPageMixin';
import EquipmentDrawer from '../components/EquipmentDrawer';
import {
createEquipment,
updateEquipment,
deleteEquipment,
getEquipment,
getEquipmentPage,
exportEquipmentExcel,
} from '@/api/base/equipment';
import Editor from '@/components/Editor';
import AssetsUpload from '../components/AssetsUpload.vue';
export default {
name: 'SpecialEquipmentForSafety',
components: {
Editor,
EquipmentDrawer,
},
mixins: [basicPageMixin],
data() {
return {
searchBarKeys: ['name', 'code'],
tableBtn: [
this.$auth.hasPermi(`base:core-equipment:update`)
? {
type: 'detail',
btnName: '详情',
}
: undefined,
this.$auth.hasPermi('base:core-equipment:update')
? {
type: 'edit',
btnName: '修改',
}
: undefined,
this.$auth.hasPermi('base:core-equipment:delete')
? {
type: 'delete',
btnName: '删除',
}
: undefined,
].filter((v) => v),
tableProps: [
// {
// prop: 'createTime',
// label: '添加时间',
// fixed: true,
// width: 180,
// filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
// },
{ prop: 'name', label: '设备名称' },
{ width: 256, prop: 'code', label: '设备编码' },
{ prop: 'location', label: '位置' },
{ prop: 'responsiblePeopleName', label: '负责人' },
{ prop: 'remark', label: '备注' },
],
searchBarFormConfig: [
{
type: 'input',
label: '名称',
placeholder: '请输入设备名称',
param: 'name',
},
{
type: 'input',
label: '编码',
placeholder: '请输入设备编码',
param: 'code',
},
{
type: 'button',
btnName: '查询',
name: 'search',
color: 'primary',
},
{
type: 'separate',
},
{
type: this.$auth.hasPermi('base:core-equipment:export')
? 'button'
: '',
btnName: '导出',
name: 'export',
plain: true,
color: 'primary',
},
{
type: this.$auth.hasPermi('base:core-equipment:create')
? 'button'
: '',
btnName: '新增',
name: 'add',
plain: true,
color: 'success',
},
],
rows: [
[
{
input: true,
label: '设备名称',
prop: 'name',
rules: [
{ required: true, message: '设备名称不能为空', trigger: 'blur' },
],
},
{
input: true,
label: '设备编码',
prop: 'code',
url: '/base/core-equipment/getCode',
rules: [
{ required: true, message: '设备编码不能为空', trigger: 'blur' },
],
},
],
[
{
input: true,
label: '所在区域',
prop: 'location',
},
{
select: true,
label: '负责人',
prop: 'responsiblePeopleId',
url: '/base/core-worker/listAll',
},
],
[{ input: true, label: '备注', prop: 'remark' }],
[
{
upload: true,
label: '设备图片',
prop: 'files',
fileType: 1,
},
],
],
editVisible: false,
editMode: 'edit', // 'edit', 'detail'
// drawer 里的设备属性列表配置项
drawerListProps: [
{
prop: 'createTime',
label: '添加时间',
fixed: true,
width: 180,
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
},
{ prop: 'name', label: '属性名称' },
{ prop: 'value', label: '属性值' },
],
// 是否显示弹出层
open: false,
// 查询参数
queryParams: {
pageNo: 1,
pageSize: 10,
code: '',
name: '',
},
// 表单参数
form: {
id: null,
files: [],
},
showUploadComponents: false, // 是否显示上传组件
};
},
computed: {
computedRows() {
return this.showUploadComponents
? [
...this.rows,
[
{
assetUpload: true,
key: 'eq-assets', // 用于区分不同的上传组件
label: '上传资料',
fieldName: 'assets',
subcomponent: AssetsUpload,
prop: 'uploadedAssets',
default: [],
bind: {
'is-pic-mode': false,
},
},
],
[
{
assetUpload: true,
key: 'eq-pics', // 用于区分不同的上传组件
label: '上传图片',
fieldName: 'images',
subcomponent: AssetsUpload,
// prop: '',
// default: [],
bind: {
'is-pic-mode': true,
},
},
],
]
: this.rows;
},
},
mounted() {
this.getList();
},
activated() {
this.getList();
},
methods: {
/** 查询列表 */
getList() {
this.loading = true;
// 执行查询
getEquipmentPage({
...this.queryParams,
specialType: 1,
special: true,
}).then((response) => {
this.list = response.data.list;
this.total = response.data.total;
this.loading = false;
});
},
/** 取消按钮 */
cancel() {
this.open = false;
this.reset();
},
cancelEdit() {
this.showUploadComponents = false;
this.editVisible = false;
},
/** 表单重置 */
reset() {
this.form = {
id: undefined,
code: undefined,
name: undefined,
enName: undefined,
abbr: undefined,
enterTime: undefined,
productionTime: undefined,
equipmentTypeId: undefined,
groupId: undefined,
tvalue: undefined,
processingTime: undefined,
manufacturer: undefined,
spec: undefined,
description: undefined,
remark: undefined,
files: [],
files2: [],
};
this.resetForm('form');
},
/** 新增按钮操作 */
handleAdd() {
this.reset();
this.open = true;
this.showUploadComponents = false;
this.title = '添加设备';
this.editMode = 'add';
},
/** 修改按钮操作 */
handleUpdate(row) {
this.reset();
this.showUploadComponents = false;
this.editMode = 'edit';
const id = row.id;
getEquipment(id).then((response) => {
this.form = response.data;
this.open = true;
this.title = '修改设备';
});
},
handleDetail(row) {
this.reset();
this.showUploadComponents = false;
const id = row.id;
this.editMode = 'detail';
getEquipment(id).then((response) => {
this.form = response.data;
this.open = true;
this.title = '查看详情';
});
},
/** 提交按钮 */
submitForm() {
this.$refs['form'].validate((valid) => {
if (!valid) {
return;
}
const payload = Object.assign(
{ special: true, specialType: 1 },
this.form
);
// payload.files = [...payload.files, ...payload.files2];
// delete payload.files2;
// 修改的提交
if (this.form.id != null) {
updateEquipment(payload).then((response) => {
this.$modal.msgSuccess('修改成功');
this.open = false;
this.getList();
});
return;
}
// 添加的提交
createEquipment(payload).then((response) => {
this.$modal.msgSuccess('新增成功');
this.open = false;
this.getList();
});
});
},
/** 删除按钮操作 */
handleDelete(row) {
const id = row.id;
this.$modal
.confirm('是否确认删除设备名称为"' + row.name + '"的数据项?')
.then(function () {
return deleteEquipment(id);
})
.then(() => {
this.getList();
this.$modal.msgSuccess('删除成功');
})
.catch(() => {});
},
/** 导出按钮操作 */
handleExport() {
// 处理查询参数
let params = { ...this.queryParams, special: true, specialType: 1 };
params.pageNo = undefined;
params.pageSize = undefined;
this.$modal
.confirm('是否确认导出所有设备数据项?')
.then(() => {
this.exportLoading = true;
return exportEquipmentExcel(params);
})
.then((response) => {
this.$download.excel(response, '安全设备.xls');
this.exportLoading = false;
})
.catch(() => {});
},
// 查看详情
viewDetail(id) {
this.reset();
this.editMode = 'detail';
this.showUploadComponents = true;
this.form.id = id;
this.editVisible = true;
this.$nextTick(() => {
this.$refs['drawer'].init();
});
},
// overwrite basicPageMixin 里的 处理表格按钮 方法
// handleTableBtnClick({ data, type }) {
// switch (type) {
// case 'edit':
// this.reset();
// this.editMode = 'edit';
// this.showUploadComponents = true;
// this.form.id = data.id;
// this.editVisible = true;
// this.$nextTick(() => {
// this.$refs['drawer'].init();
// });
// break;
// case 'delete':
// this.handleDelete(data);
// break;
// case 'detail':
// const { id } = data;
// this.viewDetail(id);
// break;
// }
// },
},
};
</script>
<style scoped lang="scss">
.SpecialEquipmentForSafety {
}
</style>

View File

@@ -0,0 +1,28 @@
<!--
filename: Content.vue
author: liubin
date: 2023-12-12 13:53:22
description:
-->
<template>
<div class="SpecialEquipmentCheckConfig"></div>
</template>
<script>
export default {
name: 'SpecialEquipmentCheckConfig',
components: {},
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.SpecialEquipmentCheckConfig {
}
</style>

View File

@@ -0,0 +1,28 @@
<!--
filename: Content.vue
author: liubin
date: 2023-12-12 13:53:22
description:
-->
<template>
<div class="SpecialEquipmentCheckContent"></div>
</template>
<script>
export default {
name: 'SpecialEquipmentCheckContent',
components: {},
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.SpecialEquipmentCheckContent {
}
</style>

View File

@@ -0,0 +1,28 @@
<!--
filename: Record.vue
author: liubin
date: 2023-12-12 13:53:22
description:
-->
<template>
<div class="SpecialEquipmentCheckRecord"></div>
</template>
<script>
export default {
name: 'SpecialEquipmentCheckRecord',
components: {},
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.SpecialEquipmentCheckRecord {
}
</style>

View File

@@ -0,0 +1,399 @@
<!--
filename: AssetsUpload.vue
author: liubin
date: 2023-10-12 16:40:14
description: 上传资料/图片 组件
-->
<template>
<div class="assets-upload">
<section class="operations">
<el-button type="text" class="expand-btn" @click="expand = !expand">
<i class="el-icon-folder-opened" v-if="expand"></i>
<i class="el-icon-folder" v-else></i>
展开
</el-button>
<!-- <div class="preview-btn">
<i class="el-icon-view"></i>
预览
</div> -->
</section>
<section
class="file-area"
:style="{
height: expand ? 'auto' : isPicMode ? '180px' : '152px',
gap: isPicMode ? '0 24px' : '24px',
gridAutoRows: isPicMode ? '180px' : '152px',
}">
<el-upload
class="equipment-upload"
:disabled="disabled"
drag
:action="uploadUrl"
:headers="headers"
multiple
:show-file-list="false"
:before-upload="beforeUpload"
:on-success="handleSuccess">
<i class="el-icon-upload"></i>
<div class="el-upload__text">
<span>将文件拖到此处或</span>
<em>点击上传</em>
</div>
<div class="el-upload__tip" slot="tip">
{{
isPicMode ? '仅支持上传 .jpg .png 格式文件, 且' : ''
}}文件大小不超过2MB
</div>
</el-upload>
<div
v-for="(file, index) in files"
:key="file.fileName"
style="width: 100%">
<div
class="file-list__item"
v-if="!isPicMode"
:style="{
background: isPicMode
? `url(${file.fileUrl}) no-repeat`
: `url(${defaultBg}) no-repeat`,
backgroundSize: isPicMode ? '100% 100%' : '64px',
backgroundPosition: isPicMode ? '0% 0%' : 'center',
}"
@click="handleDownload(file)"
:data-name="file.fileName">
<el-button
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>
</div>
</template>
<script>
import { getAccessToken } from '@/utils/auth';
import defaultBg from '../../../assets/images/default-file-icon.png';
function checkSize(file, message) {
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
message.error('上传文件大小不能超过 2MB!');
}
return isLt2M;
}
function checkPic(file, message) {
const isJPG = file.type === 'image/jpeg';
const isPNG = file.type === 'image/png';
const isPic = isJPG || isPNG;
if (!isPic) {
message.error('上传图片只能是 JPG/PNG 格式!');
}
return isPic;
}
export default {
name: 'AssetsUpload',
components: {},
model: {
prop: 'dataSource',
event: 'update',
},
props: {
type: {
type: String,
default: 'image',
},
dataSource: {
type: Array,
default: () => [],
},
equipmentId: {
type: String,
default: '',
},
isPicMode: {
type: Boolean,
default: false,
},
disabled: {
type: Boolean,
default: false,
},
},
emits: ['update-filelist'],
data() {
return {
defaultBg,
expand: false,
headers: { Authorization: 'Bearer ' + getAccessToken() }, // 设置上传的请求头部
fileList: [],
uploadUrl: process.env.VUE_APP_BASE_API + '/admin-api/infra/file/upload',
files: [],
updateTimer: null,
};
},
watch: {
dataSource: {
handler(val) {
this.files = JSON.parse(JSON.stringify(val));
},
immediate: true,
deep: true,
},
},
mounted() {},
methods: {
// handle success, per file!
handleSuccess(response, file, fileList) {
this.$notify({
title: '成功',
message: '上传成功! 点击确认保存上传结果',
type: 'success',
});
if (
response == null ||
!('data' in response) ||
response.data == null ||
response.data.trim() == ''
) {
this.$message.error('上传出错了!');
return;
}
this.files.push({
fileName: file.name,
fileUrl: response.data,
fileType: this.isPicMode ? 1 : 2,
});
// debugger;
// 延时更新
if (this.updateTimer) {
clearTimeout(this.updateTimer);
}
this.updateTimer = setTimeout(() => {
// console.log('[AssetsUpload] 更新上传列表');
this.emitFilelist();
clearTimeout(this.updateTimer);
this.updateTimer = null;
}, 500);
},
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);
}
},
emitFilelist() {
this.$emit('update', this.files);
},
handleRemove(file, fileList) {
debugger;
},
handleDelete(file) {
// fileName fileType 都可能一样,但 fileUrl 一定不一样
this.files = this.files.filter((item) => item.fileUrl != file.fileUrl);
this.$notify({
title: '成功',
message: '删除成功! 需点击确认保存删除结果',
type: 'success',
});
this.emitFilelist();
},
beforeUpload(file) {
if (this.isPicMode) {
return checkPic(file, this.$message) && checkSize(file, this.$message);
}
return checkSize(file, this.$message);
},
handleUpload() {
switch (this.type) {
case 'image':
break;
case 'asset':
break;
}
},
updateFileList(appendFilelist) {
// Array
this.$emit('update-filelist', this.appendFilelist);
},
},
};
</script>
<style scoped lang="scss">
.assets-upload {
position: relative;
}
.operations {
position: absolute;
top: -36px;
right: 0;
display: flex;
align-items: center;
}
.expand-btn,
.preview-btn {
font-size: 14px;
line-height: 1.2;
display: inline-block;
padding-left: 20px;
cursor: pointer;
z-index: 1000;
}
.expand-btn {
margin-right: 12px;
}
.preview-btn {
color: #ccc;
}
.expand-btn,
.preview-btn:hover,
.preview-btn.active {
// color: #0042d0;
color: #0b58ff;
}
:deep(.equipment-upload) {
.el-upload-dragger {
width: 188px;
height: 128px;
}
.el-icon-upload {
margin: 12px 0;
font-size: 48px;
}
.el-upload__text {
font-size: 12px;
line-height: 2px;
display: flex;
flex-direction: column;
em {
margin-top: 12px;
}
}
.el-upload__tip {
font-size: 12px;
line-height: 1.5;
color: #d1d1d1;
margin: 0 0 12px;
transform: translateY(-12px);
user-select: none;
}
}
.equipment-upload {
margin-bottom: 24px;
}
.file-list {
padding: 12px;
border: 1px solid #ccc;
}
// custom
.file-area {
display: grid;
grid-template-columns: repeat(auto-fill, 188px);
grid-auto-rows: 152px;
gap: 48px 24px;
overflow: hidden;
}
.file-list__item {
height: 128px;
background-color: #fff;
border: 1px dashed #d9d9d9;
border-radius: 6px;
-webkit-box-sizing: border-box;
box-sizing: border-box;
text-align: center;
cursor: pointer;
position: relative;
// overflow: hidden;
&:hover {
.el-icon-delete {
display: block;
}
}
.el-icon-delete {
color: #ccc;
position: absolute;
top: 8px;
right: 8px;
display: none;
&:hover {
color: rgb(210, 41, 41);
}
}
}
.file-list__item:hover {
border-color: #0b58ff;
}
.file-list__item::after {
content: attr(data-name);
position: absolute;
left: 0;
bottom: -26px;
font-size: 14px;
line-height: 2;
color: #616161;
}
.default-icon {
background: url(../../../assets/images/default-file-icon.png) no-repeat;
background-position: center;
background-size: 64px;
}
</style>

View File

@@ -0,0 +1,313 @@
<!--
filename: dialogForm.vue
author: liubin
date: 2023-08-15 10:32:36
description: 弹窗的表单组件
-->
<template>
<el-form
ref="form"
:model="form"
:label-width="`${labelWidth}px`"
:size="size"
:label-position="labelPosition"
v-loading="formLoading">
<el-row :gutter="20" v-for="(row, rindex) in rows" :key="rindex">
<el-col v-for="col in row" :key="col.label" :span="24 / row.length">
<el-form-item :label="col.label" :prop="col.prop" :rules="col.rules">
<el-input
v-if="col.input"
v-model="form[col.prop]"
@change="$emit('update', form)"
:placeholder="`请输入${col.label}`"
v-bind="col.bind" />
<el-input
v-if="col.textarea"
type="textarea"
v-model="form[col.prop]"
@change="$emit('update', form)"
:placeholder="`请输入${col.label}`"
v-bind="col.bind" />
<el-select
v-if="col.select"
v-model="form[col.prop]"
:placeholder="`请选择${col.label}`"
@change="$emit('update', form)"
v-bind="col.bind">
<el-option
v-for="opt in optionListOf[col.prop]"
:key="opt.value"
:label="opt.label"
:value="opt.value" />
</el-select>
<el-date-picker
v-if="col.datetime"
v-model="form[col.prop]"
type="datetime"
:placeholder="`请选择${col.label}`"
value-format="timestamp"
v-bind="col.bind"></el-date-picker>
<el-upload
class="upload-in-dialog"
v-if="col.upload"
:file-list="uploadedFileList"
:action="col.url"
:on-success="handleUploadSuccess"
v-bind="col.bind">
<el-button
size="small"
type="primary"
:disabled="col.bind?.disabled || false">
点击上传
</el-button>
<div class="el-upload__tip" slot="tip" v-if="col.uploadTips">
{{ col.uploadTips || '只能上传jpg/png文件大小不超过2MB' }}
</div>
</el-upload>
<el-switch
v-if="col.switch"
v-model="form[col.prop]"
active-color="#0b58ff"
inactive-color="#e1e1e1"
v-bind="col.bind"></el-switch>
<component
v-if="col.subcomponent"
:key="col.key"
:is="col.subcomponent"
v-bind="col.bind"
:inlineStyle="col.style"></component>
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
/**
* 找到最长的label
* @param {*} options
*/
function findMaxLabelWidth(rows) {
let max = 0;
rows.forEach((row) => {
row.forEach((opt) => {
// debugger;
if (!opt.label) return 0;
if (opt.label.length > max) {
max = opt.label.length;
}
});
});
return max;
}
export default {
name: 'DialogForm',
model: {
prop: 'dataForm',
event: 'update',
},
emits: ['update'],
components: {},
props: {
rows: {
type: Array,
default: () => [],
},
dataForm: {
type: Object,
default: () => ({}),
},
disabled: {
type: Boolean,
default: false,
},
labelPosition: {
type: String,
default: 'right',
},
size: {
type: String,
default: '',
},
},
data() {
return {
formLoading: true,
optionListOf: {},
uploadedFileList: [],
dataLoaded: false,
};
},
computed: {
labelWidth() {
let max = findMaxLabelWidth(this.rows);
// 每个汉字占20px
return max * 20;
// return max * 20 + 'px';
},
form: {
get() {
// if (this.dataLoaded) return this.dataForm;
// else return {}
return this.dataForm;
},
set(val) {
console.log('set form', val);
},
},
},
watch: {
rows: {
handler() {
console.log('watch triggered!');
this.$nextTick(() => {
this.handleOptions('watch');
});
},
deep: true,
immediate: false,
},
},
mounted() {
// 处理 options
this.handleOptions();
},
methods: {
/** 模拟透传 ref */
validate(cb) {
return this.$refs.form.validate(cb);
},
resetFields(args) {
return this.$refs.form.resetFields(args);
},
// getCode
async getCode(url) {
const response = await this.$axios(url);
return response.data;
},
async handleOptions(trigger = 'monuted') {
console.log('[dialogForm:handleOptions]');
const promiseList = [];
this.rows.forEach((cols) => {
cols.forEach((opt) => {
if (opt.value && !this.form[opt.prop]) {
// 默认值
this.form[opt.prop] = opt.value;
}
if (opt.options) {
this.$set(this.optionListOf, opt.prop, opt.options);
} else if (opt.url) {
// 如果有 depends则暂时先不获取注册一个watcher
if (opt.depends) {
console.log('[handleOptions] setting watch');
this.$watch(
() => this.form[opt.depends],
(id) => {
console.log('<', opt.depends, '>', 'changed', id);
if (id == null) return;
// 清空原有选项
this.form[opt.prop] = null;
// 获取新的选项
this.$axios({
url: `${opt.url}?id=${id}`,
}).then((res) => {
this.$set(
this.optionListOf,
opt.prop,
res.data.map((item) => ({
label: item[opt.labelKey ?? 'name'],
value: item[opt.valueKey ?? 'id'],
}))
);
});
},
{
immediate: true,
}
);
return;
}
// 如果是下拉框,或者新增模式下的输入框,才去请求
if (opt.select || (opt.input && !this.form?.id)) {
promiseList.push(async () => {
const response = await this.$axios(opt.url, {
method: opt.method ?? 'get',
});
console.log('[dialogForm:handleOptions:response]', response);
if (opt.select) {
// 处理下拉框选项
const list =
'list' in response.data
? response.data.list
: response.data;
this.$set(
this.optionListOf,
opt.prop,
list.map((item) => ({
label: item[opt.labelKey ?? 'name'],
value: item[opt.valueKey ?? 'id'],
}))
);
} else if (opt.input) {
console.log('setting code: ', response.data);
// 处理输入框数据
this.form[opt.prop] = response.data;
}
});
}
}
});
});
console.log('[dialogForm:handleOptions] done!');
// 如果是 watch 触发的,不需要执行进一步的请求
if (trigger == 'watch') {
this.formLoading = false;
return;
}
try {
await Promise.all(promiseList.map((fn) => fn()));
this.formLoading = false;
this.dataLoaded = true;
// console.log("[dialogForm:handleOptions:optionListOf]", this.optionListOf)
} catch (error) {
console.log('[dialogForm:handleOptions:error]', error);
this.formLoading = false;
}
if (!promiseList.length) this.formLoading = false;
},
// 上传成功的特殊处理
beforeUpload() {},
// 上传前的验证规则可通过 bind 属性传入
handleUploadSuccess(response, file, fileList) {
console.log(
'[dialogForm:handleUploadSuccess]',
response,
file,
fileList,
this.form
);
// 保存原始文件名
if ('fileNames' in this.form) this.form.fileNames.push(file.name);
// 保存完整地址
if ('fileUrls' in this.form) this.form.fileUrls.push(response.data);
this.$modal.msgSuccess('上传成功');
},
getFileName(fileUrl) {
return fileUrl.split('/').pop();
},
},
};
</script>
<style scoped lang="scss">
.el-date-editor,
.el-select {
width: 100%;
}
</style>

View File

@@ -0,0 +1,550 @@
<!--
filename: EquipmentDrawer.vue
author: liubin
date: 2023-08-22 14:38:56
description:
-->
<template>
<el-drawer
:visible="visible"
:show-close="false"
:wrapper-closable="false"
class="drawer"
custom-class="mes-drawer"
size="60%"
@closed="$emit('destroy')">
<SmallTitle slot="title">
{{
mode.includes('detail')
? '详情'
: mode.includes('edit')
? '编辑'
: '新增'
}}
</SmallTitle>
<div class="drawer-body flex">
<div class="drawer-body__content">
<section v-for="(section, index) in sections" :key="section.key">
<SmallTitle v-if="index != 0">{{ section.name }}</SmallTitle>
<div
class="form-part"
v-if="section.key == 'base'"
style="margin-bottom: 32px">
<el-skeleton v-if="!showForm" animated />
<EquipmentInfoForm
key="drawer-dialog-form"
v-if="showForm"
:disabled="mode.includes('detail')"
:sync-filelist="syncFileListFlag"
v-model="form" />
</div>
<div
v-if="section.key == 'attrs'"
style="margin-top: 12px; position: relative">
<div
v-if="!mode.includes('detail')"
style="position: absolute; top: -40px; right: 0">
<el-button @click="handleAddAttr" type="text">
<i class="el-icon-plus"></i>
添加属性
</el-button>
</div>
<base-table
v-loading="attrListLoading"
:table-props="section.props"
:page="attrQuery?.params.pageNo || 1"
:limit="attrQuery?.params.pageSize || 10"
:table-data="list"
@emitFun="handleEmitFun">
<!-- :add-button-show="mode.includes('detail') ? null : '添加属性'"
@emitButtonClick="handleAddAttr" -->
<method-btn
v-if="section.tableBtn"
slot="handleBtn"
label="操作"
:method-list="tableBtn"
@clickBtn="handleTableBtnClick" />
</base-table>
<!-- 分页组件 -->
<pagination
v-show="total > 0"
:total="total"
:page.sync="attrQuery.params.pageNo"
:limit.sync="attrQuery.params.pageSize"
@pagination="getAttrList" />
</div>
</section>
</div>
<div class="drawer-body__footer">
<el-button style="" @click="handleCancel">取消</el-button>
<el-button v-if="mode == 'detail'" type="primary" @click="toggleEdit">
编辑
</el-button>
<el-button v-else type="primary" @click="handleConfirm">保存</el-button>
<!-- sections的第二项必须是 属性列表 -->
<!-- <el-button
v-if="sections[1].allowAdd"
type="primary"
@click="handleAddAttr">
添加属性
</el-button> -->
</div>
</div>
<!-- 属性对话框 -->
<base-dialog
v-if="sections[1].allowAdd"
:dialogTitle="attrTitle"
:dialogVisible="attrFormVisible"
width="35%"
:append-to-body="true"
custom-class="baseDialog"
@close="closeAttrForm"
@cancel="closeAttrForm"
@confirm="submitAttrForm">
<DialogForm
v-if="attrFormVisible"
ref="attrForm"
:dataForm="attrForm"
:rows="attrRows" />
</base-dialog>
</el-drawer>
</template>
<script>
import DialogForm from './DialogForm';
import EquipmentInfoForm from './EquipmentInfoForm.vue';
const SmallTitle = {
name: 'SmallTitle',
props: ['size'],
components: {},
data() {
return {};
},
methods: {},
render: function (h) {
return h(
'span',
{
class: 'small-title',
style: {
fontSize: '18px',
lineHeight:
this.size == 'lg' ? '24px' : this.size == 'sm' ? '18px' : '20px',
fontWeight: 500,
fontFamily: '微软雅黑, Microsoft YaHei, Arial, Helvetica, sans-serif',
},
},
this.$slots.default
);
},
};
export default {
components: { SmallTitle, DialogForm, EquipmentInfoForm },
props: ['sections', 'mode', 'dataId'], // dataId 作为一个通用的存放id的字段
data() {
return {
visible: false,
showForm: false,
btnLoading: false,
total: 0,
form: {},
list: [],
attrTitle: '',
attrForm: {
id: null,
equipmentId: null,
name: '',
value: '',
},
attrFormVisible: false,
attrRows: [
[
{
input: true,
label: '属性名称',
prop: 'name',
rules: [
{ required: true, message: '属性名称不能为空', trigger: 'blur' },
],
},
],
[
{
input: true,
label: '属性值',
prop: 'value',
},
],
],
attrQuery: {
params: {
pageNo: 1,
pageSize: 10,
},
}, // 属性列表的请求
infoQuery: null, // 基本信息的请求
attrFormSubmitting: false,
attrListLoading: false,
syncFileListFlag: null,
};
},
computed: {
formRows() {
return this.sections[0].rows.map((row) => {
return row.map((col) => {
if (col.key == 'eq-pics') {
// 重置图片的位置
return {
...col,
bind: {
...col.bind,
},
style: {
left: 0,
right: 'unset',
},
};
}
return {
...col,
bind: {
...col.bind,
// 详情 模式下,禁用各种输入
disabled: this.mode == 'detail',
},
};
});
});
},
tableBtn() {
return this.mode == 'detail' ? [] : this.sections[1].tableBtn;
},
},
mounted() {
for (const section of this.sections) {
// 请求具体信息
if ('url' in section) {
const query = {
url: section.url,
method: section.method || 'get',
params: section.queryParams || null,
data: section.data || null,
};
this.$axios(query).then(({ data }) => {
if (section.key == 'base') {
this.form = data;
// this.form = {
// code: 'gj',
// name: '下片机',
// enName: 'unload',
// abbr: '',
// equipmentTypeId: 21084,
// remark: '备注',
// id: '1712367395052384257',
// createTime: 1697095176000,
// enterTime: 0,
// productionTime: 0,
// files: [
// {
// fileName: '测试.xlsx',
// fileUrl: 'https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2022%2F0108%2F0f0c6f30j00r5cle9000sc000hs00gtc.jpg&thumbnail=660x2147483647&quality=80&type=jpg',
// fileType: 1
// },
// {
// fileName: '测试2.xlsx',
// fileUrl: 'https://nimg.ws.126.net/?url=http%3A%2F%2Fdingyue.ws.126.net%2F2022%2F0415%2F2cd23619j00racb96000kc000hs00hsc.jpg&thumbnail=660x2147483647&quality=80&type=jpg',
// fileType: 1
// },
// {
// fileName: '测试3.xlsx',
// fileUrl: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2F1fea91a0-d088-409e-b145-e0e61254b28b%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1700031689&t=2e0fe7d1de7f54adff3007efe133d67c',
// fileType: 1
// },
// {
// fileName: '测试4.xlsx',
// fileUrl: 'https://pics5.baidu.com/feed/b7003af33a87e950cdfb4b4546eed044faf2b40d.jpeg?token=1d7484cfe4b014dd201f8c8725cab945',
// fileType: 2
// },
// {
// fileName: '测试5.xlsx',
// fileUrl: 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fsafe-img.xhscdn.com%2Fbw1%2Fe3500876-9c46-4b70-8d37-4799520cdd13%3FimageView2%2F2%2Fw%2F1080%2Fformat%2Fjpg&refer=http%3A%2F%2Fsafe-img.xhscdn.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1700031689&t=4abc1df930e62730e5361a7d3765e0f2',
// fileType: 2
// },
// ],
// tvalue: 0,
// processingTime: 0,
// manufacturer: '',
// spec: '',
// description: '描述',
// };
this.showForm = true;
this.infoQuery = query;
} else if (section.key == 'attrs') {
this.attrQuery = query;
this.list = data.list;
this.total = data.total;
}
});
}
}
},
methods: {
handleTableBtnClick({ type, data }) {
switch (type) {
case 'edit':
this.handleEditAttr(data.id);
break;
case 'delete':
this.handleDeleteAttr(data.id);
break;
}
},
async handleConfirm() {
this.btnLoading = true;
this.syncFileListFlag = Math.random();
this.$nextTick(async () => {
const { code, data } = await this.$axios({
url: this.sections[0].urlUpdate,
method: 'put',
data: this.form,
});
if (code == 0) {
this.$modal.msgSuccess('更新成功');
}
this.btnLoading = false;
this.handleCancel();
});
},
handleEmitFun(val) {
console.log('handleEmitFun', val);
},
init() {
this.visible = true;
},
async getAttrList() {
this.attrListLoading = true;
const res = await this.$axios(this.attrQuery);
if (res.code == 0) {
this.list = res.data.list;
this.total = res.data.total;
}
this.attrListLoading = false;
},
// 保存表单
handleSave() {
this.$refs['form'][0].validate(async (valid) => {
if (valid) {
const isEdit = this.mode == 'edit';
await this.$axios({
url: this.sections[0][isEdit ? 'urlUpdate' : 'urlCreate'],
method: isEdit ? 'put' : 'post',
data: this.form,
});
this.$modal.msgSuccess(`${isEdit ? '更新' : '创建'}成功`);
this.visible = false;
this.$emit('refreshDataList');
}
});
},
handleCancel() {
this.visible = false;
},
// 开启编辑
toggleEdit() {
this.$emit('update-mode', 'edit');
},
// 新增属性
handleAddAttr() {
if (!this.dataId) return this.$message.error('请先创建设备信息');
this.attrForm = {
id: null,
equipmentId: this.dataId,
name: '',
value: '',
};
this.attrTitle = '添加设备属性';
this.attrFormVisible = true;
},
// 编辑属性
async handleEditAttr(attrId) {
const res = await this.$axios({
url: this.sections[1].urlDetail,
method: 'get',
params: { id: attrId },
});
if (res.code == 0) {
this.attrForm = res.data;
this.attrTitle = '编辑设备属性';
this.attrFormVisible = true;
}
},
// 删除属性
handleDeleteAttr(attrId) {
this.$confirm('确定删除该属性?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
})
.then(async () => {
const res = await this.$axios({
url: this.sections[1].urlDelete,
method: 'delete',
params: { id: attrId },
});
if (res.code == 0) {
this.$message({
message: '删除成功',
type: 'success',
duration: 1500,
onClose: () => {
this.getAttrList();
},
});
}
})
.catch(() => {});
},
// 提交属性表
submitAttrForm() {
this.$refs['attrForm'].validate(async (valid) => {
if (!valid) {
return;
}
try {
const isEdit = this.attrForm.id != null;
this.attrFormSubmitting = true;
const res = await this.$axios({
url: isEdit
? this.sections[1].urlUpdate
: this.sections[1].urlCreate,
method: isEdit ? 'put' : 'post',
data: this.attrForm,
});
if (res.code == 0) {
this.closeAttrForm();
this.$message({
message: `${isEdit ? '更新' : '创建'}成功`,
type: 'success',
duration: 1500,
onClose: () => {
this.getAttrList();
},
});
}
this.attrFormSubmitting = false;
} catch (err) {
this.$message({
message: err,
type: 'error',
duration: 1500,
});
this.attrFormSubmitting = false;
}
});
},
closeAttrForm() {
this.attrFormVisible = false;
},
handleClick(raw) {
if (raw.type === 'delete') {
this.$confirm(
`确定对${
raw.data.name
? '[名称=' + raw.data.name + ']'
: '[序号=' + raw.data._pageIndex + ']'
}进行删除操作?`,
'提示',
{
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}
)
.then(() => {
deleteProductAttr(raw.data.id).then(({ data }) => {
this.$message({
message: '操作成功',
type: 'success',
duration: 1500,
onClose: () => {
this.getList();
},
});
});
})
.catch(() => {});
} else {
this.addNew(raw.data.id);
}
},
},
};
</script>
<style scoped>
.drawer >>> .el-drawer {
border-radius: 8px 0 0 8px;
}
.drawer >>> .el-drawer__header {
margin: 0;
padding: 32px 32px 24px;
border-bottom: 1px solid #dcdfe6;
margin-bottom: 0px;
}
.small-title::before {
content: '';
display: inline-block;
vertical-align: top;
width: 4px;
height: 22px;
border-radius: 1px;
margin-right: 8px;
background-color: #0b58ff;
}
.drawer-body {
display: flex;
flex-direction: column;
height: 100%;
}
.drawer-body__content {
flex: 1;
/* background: #eee; */
padding: 20px 30px;
overflow-y: auto;
}
.drawer-body__footer {
display: flex;
justify-content: flex-end;
padding: 18px;
}
</style>

View File

@@ -0,0 +1,288 @@
<!--
filename: dialogForm.vue
author: liubin
date: 2023-08-15 10:32:36
description: 弹窗的表单组件
-->
<template>
<el-form class="equipment-info-form" ref="form" :model="form" label-width="200px" label-position="top"
v-loading="formLoading">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="设备名称" prop="name" :rules="[{ required: true, message: '设备名称不能为空', trigger: 'blur' }]">
<el-input v-model="form.name" :disabled="disabled" placeholder="请输入设备名称"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="设备编码" prop="code" :rules="[]">
<el-input v-model="form.code" :disabled="disabled" placeholder="请输入设备编码"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="英文名称" prop="enName" :rules="[]">
<el-input v-model="form.enName" :disabled="disabled" placeholder="请输入英文名称"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="缩写" prop="abbr" :rules="[]">
<el-input v-model="form.abbr" :disabled="disabled" placeholder="请输入名称缩写"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="设备类型" prop="equipmentTypeId"
:rules="[{ required: true, message: '设备类型不能为空', trigger: 'blur' }]">
<el-select v-model="form.equipmentTypeId" :disabled="disabled" filterable placeholder="请选择设备类型">
<el-option v-for="eqType in eqTypeList" :key="eqType.id" :label="eqType.name"
:value="eqType.id"></el-option>
</el-select>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="预计生产时间(min/天)" prop="workTime" :rules="[
{ required: true, message: '预计生产时间不能为空', trigger: 'blur' },
{
type: 'number',
message: '请输入正确的数字值',
trigger: 'blur',
transform: (val) => Number(val),
},
]">
<el-input v-model="form.workTime" :disabled="disabled" placeholder="请输入预计生产时间"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="生产日期" prop="productionTime" :rules="[]">
<el-date-picker v-model="form.enterTime" :disabled="disabled" type="datetime" placeholder="请选择生产日期"
value-format="timestamp"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="进场日期" prop="enterTime" :rules="[]">
<el-date-picker v-model="form.enterTime" :disabled="disabled" type="datetime" placeholder="请选择进场日期"
value-format="timestamp"></el-date-picker>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="设备TT值" prop="tvalue" :rules="[
{ required: true, message: '设备TT值不能为空', trigger: 'blur' },
{
type: 'number',
message: '请输入正确的数字值',
trigger: 'blur',
transform: (val) => Number(val),
},
]">
<el-input v-model="form.tvalue" :disabled="disabled" placeholder="请输入设备TT值"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="产品加工时间(s)" prop="processingTime" :rules="[
{ required: true, message: '产品加工时间不能为空', trigger: 'blur' },
{
type: 'number',
message: '请输入正确的数字值',
trigger: 'blur',
transform: (val) => Number(val),
},
]">
<el-input v-model="form.processingTime" :disabled="disabled" placeholder="请输入产品加工时间"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="制造商" prop="manufacturer" :rules="[]">
<el-input v-model="form.manufacturer" :disabled="disabled" placeholder="请输入制造商"></el-input>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="设备规格" prop="spec" :rules="[]">
<el-input v-model="form.spec" :disabled="disabled" placeholder="请输入设备规格"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<!-- 功能描述 -->
<el-col>
<el-form-item label="功能描述" prop="description" :rules="[]">
<el-input type="textarea" :disabled="disabled" v-model="form.description"
placeholder="请填写功能描述"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<!-- 功能描述 -->
<el-col>
<el-form-item label="备注" prop="remark" :rules="[]">
<el-input v-model="form.remark" :disabled="disabled" placeholder="请输入备注"></el-input>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<!-- 上传资料 -->
<el-col>
<el-form-item label="上传资料" prop="assets" :rules="[]">
<AssetsUpload v-model="form.assets" :disabled="disabled" />
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<!-- 上传图片 -->
<el-col>
<el-form-item label="上传图片" prop="pics" :rules="[]">
<AssetsUpload :is-pic-mode="true" v-model="form.pics" :disabled="disabled" />
</el-form-item>
</el-col>
</el-row>
</el-form>
</template>
<script>
import AssetsUpload from './AssetsUpload.vue';
export default {
name: 'EquipmentInfoForm',
model: {
prop: 'dataForm',
event: 'update',
},
emits: ['update'],
components: { AssetsUpload },
props: {
dataForm: {
type: Object,
default: () => ({}),
},
disabled: {
type: Boolean,
default: false,
},
syncFilelist: {
type: Number,
default: null,
required: false,
},
},
data() {
return {
formLoading: false,
form: {
name: '',
code: '',
enName: '',
abbr: '',
equipmentTypeId: '',
remark: '',
productionTime: '',
workTime: '',
enterTime: '',
tvalue: '',
processingTime: '',
manufacturer: '',
spec: '',
description: '',
assets: [],
pics: [],
},
eqTypeList: [],
dataLoaded: false,
};
},
watch: {
dataForm: {
handler(val) {
// debugger;
this.form = JSON.parse(JSON.stringify(val));
this.form.assets =
this.form.files?.filter((item) => item.fileType == '2') || [];
this.form.pics =
this.form.files?.filter((item) => item.fileType == '1') || [];
delete this.form.files;
},
immediate: true,
deep: true,
},
syncFilelist: {
handler(val) {
if (val != null) {
this.updateForm();
}
},
immediate: true,
},
},
mounted() {
this.getEqTypeList();
},
methods: {
updateForm() {
console.log('update form ==> ');
this.form.files = [...this.form.assets, ...this.form.pics];
delete this.form.assets;
delete this.form.pics;
this.$emit('update', this.form);
},
async getEqTypeList() {
this.formLoading = true;
const { code, data } = await this.$axios(
'/base/core-equipment-type/page?pageNo=1&pageSize=100'
);
// debugger;
if (code == 0) {
this.eqTypeList = data.list;
}
this.formLoading = false;
},
/** 模拟透传 ref */
validate(cb) {
return this.$refs.form.validate(cb);
},
resetFields(args) {
return this.$refs.form.resetFields(args);
},
// getCode
async getCode(url) {
const response = await this.$axios(url);
return response.data;
},
// 上传成功的特殊处理
beforeUpload() { },
// 上传前的验证规则可通过 bind 属性传入
handleUploadSuccess(response, file, fileList) {
// 保存原始文件名
if ('fileNames' in this.form) this.form.fileNames.push(file.name);
// 保存完整地址
if ('fileUrls' in this.form) this.form.fileUrls.push(response.data);
this.$modal.msgSuccess('上传成功');
},
getFileName(fileUrl) {
return fileUrl.split('/').pop();
},
},
};
</script>
<style scoped lang="scss">
.el-date-editor,
.el-select {
width: 100%;
}
</style>

View File

@@ -0,0 +1,28 @@
<!--
filename: Monitor.vue
author: liubin
date: 2023-12-12 13:54:53
description:
-->
<template>
<div class="SpecialEquipmentMaintainMonitor"></div>
</template>
<script>
export default {
name: 'SpecialEquipmentMaintainMonitor',
components: {},
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.SpecialEquipmentMaintainMonitor {
}
</style>

View File

@@ -0,0 +1,28 @@
<!--
filename: PlanConfig.vue
author: liubin
date: 2023-12-12 13:54:53
description:
-->
<template>
<div class="SpecialEquipmentPlanConfig"></div>
</template>
<script>
export default {
name: 'SpecialEquipmentPlanConfig',
components: {},
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.SpecialEquipmentPlanConfig {
}
</style>

View File

@@ -0,0 +1,28 @@
<!--
filename: MaintainRecord.vue
author: liubin
date: 2023-12-12 13:54:53
description:
-->
<template>
<div class="SpecialEquipmentMaintainRecord"></div>
</template>
<script>
export default {
name: 'SpecialEquipmentMaintainRecord',
components: {},
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.SpecialEquipmentMaintainRecord {
}
</style>

View File

@@ -0,0 +1,28 @@
<!--
filename: Repair.vue
author: liubin
date: 2023-12-12 13:54:53
description:
-->
<template>
<div class="SpecialEquipmentRepair"></div>
</template>
<script>
export default {
name: 'SpecialEquipmentRepair',
components: {},
props: {},
data() {
return {};
},
computed: {},
methods: {},
};
</script>
<style scoped lang="scss">
.SpecialEquipmentRepair {
}
</style>

View File

@@ -28,6 +28,7 @@
<el-table v-if="refreshTable" v-loading="loading" :data="deptList" row-key="id" :default-expand-all="isExpandAll"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}">
<el-table-column prop="id" label="部门编码" width="260"></el-table-column>
<el-table-column prop="name" label="部门名称" width="260"></el-table-column>
<el-table-column prop="leader" label="负责人" :formatter="userNicknameFormat" width="120"/>
<el-table-column prop="sort" label="排序" width="200"></el-table-column>

17814
yarn.lock

File diff suppressed because it is too large Load Diff