Merge pull request '新增设备总览透光率产线产品监控等' (#462) from projects/qhd-line-zhp into projects/qhd-line-test
Reviewed-on: #462
This commit is contained in:
2
.env.dev
2
.env.dev
@@ -13,6 +13,8 @@ VUE_APP_TITLE = 智能监控分析系统
|
|||||||
|
|
||||||
# 芋道管理系统/开发环境
|
# 芋道管理系统/开发环境
|
||||||
VUE_APP_BASE_API = 'http://172.16.32.79:48080'
|
VUE_APP_BASE_API = 'http://172.16.32.79:48080'
|
||||||
|
# VUE_APP_BASE_API = 'http://line.kszny.picaiba.com'
|
||||||
|
|
||||||
|
|
||||||
# 路由懒加载
|
# 路由懒加载
|
||||||
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
VUE_CLI_BABEL_TRANSPILE_MODULES = true
|
||||||
|
|||||||
@@ -59,3 +59,33 @@ export function getEquipmentAll() {
|
|||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
export function getTree(query) {
|
||||||
|
return request({
|
||||||
|
url: '/base/factory/getTreeSimple',
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getEquipmentOverall(data) {
|
||||||
|
return request({
|
||||||
|
url: '/monitoring/equipment-overall/get',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getParamMonitor(data) {
|
||||||
|
return request({
|
||||||
|
url: '/monitoring/equipment-monitor/paramMonitor',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export function getAlarmDet(data) {
|
||||||
|
return request({
|
||||||
|
url: 'monitoring/equipment-overall/alarmDet',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -39,9 +39,10 @@ export function getNewCTCharts(data) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 获取产线平衡分析数据设备list(new)
|
// 获取产线平衡分析数据设备list(new)
|
||||||
export function getNewCTDet(id) {
|
export function getNewCTDet(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/analysis/production-analysis/getNewCTDet?lineId='+id,
|
url: '/analysis/production-analysis/getNewCTDet',
|
||||||
method: 'get',
|
method: 'post',
|
||||||
})
|
data: data,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,55 +5,109 @@
|
|||||||
* @LastEditors: zwq
|
* @LastEditors: zwq
|
||||||
* @Description:
|
* @Description:
|
||||||
*/
|
*/
|
||||||
import request from '@/utils/request'
|
import request from '@/utils/request';
|
||||||
|
|
||||||
// 获得工厂分页
|
// 获得工厂分页
|
||||||
export function getPdlAutoReport(data) {
|
export function getPdlAutoReport(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/monitoring/production-monitor/getPdlAutoReport',
|
url: '/monitoring/production-monitor/getPdlAutoReport',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获得所有工厂产线列表
|
// 获得所有工厂产线列表
|
||||||
export function getPdList(id) {
|
export function getPdList(id) {
|
||||||
return request({
|
return request({
|
||||||
url: '/base/production-line/listAll' + (id ? '?id=' + id : ''),
|
url: '/base/production-line/listAll' + (id ? '?id=' + id : ''),
|
||||||
method: 'get'
|
method: 'get',
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
// 获得产线自动报表
|
// 获得产线自动报表
|
||||||
export function getLineAuto(data) {
|
export function getLineAuto(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/monitoring/production-monitor/getPdlAutoReportNew',
|
url: '/monitoring/production-monitor/getPdlAutoReportNew',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获得产品自动报表
|
// 获得产品自动报表
|
||||||
export function getProductAuto(data) {
|
export function getProductAuto(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/monitoring/production-monitor/getProcessAutoReportNew',
|
url: '/monitoring/production-monitor/getProcessAutoReportNew',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data,
|
||||||
})
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPdlAutoReportNewSearchNow(data) {
|
||||||
|
return request({
|
||||||
|
url: '/monitoring/production-monitor/getPdlAutoReportNewSearchNow',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
timeout: 60000,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getPdlAutoReportNewSearchLastGroup(data) {
|
||||||
|
return request({
|
||||||
|
url: '/monitoring/production-monitor/getPdlAutoReportNewSearchLastGroup',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
timeout: 60000,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 班组自动报表分页
|
// 班组自动报表分页
|
||||||
export function getTeamReportPage(data) {
|
export function getTeamReportPage(data) {
|
||||||
return request({
|
return request({
|
||||||
url: '/monitoring/team-auto-report/page',
|
url: '/monitoring/group-off-record/page',
|
||||||
method: 'post',
|
method: 'post',
|
||||||
data: data
|
data: data,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// 班组自动报表分页详细
|
// 班组自动报表分页详细
|
||||||
export function getTeamReportPageDet(id) {
|
export function getTeamReportPageDet(id) {
|
||||||
return request({
|
return request({
|
||||||
url: '/monitoring/team-auto-report/pageDet?id=' + id,
|
url: '/monitoring/group-off-record/get?id=' + id,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function exportGroupProductReportExcel(data) {
|
||||||
|
return request({
|
||||||
|
url: '/monitoring/group-off-record/export-det-excel',
|
||||||
|
method: 'get',
|
||||||
|
params: data,
|
||||||
|
responseType: 'blob',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 获取产品当班数据
|
||||||
|
export function getProcessAutoReportGroup(data) {
|
||||||
|
return request({
|
||||||
|
url: '/monitoring/production-monitor/getProcessAutoReportGroup',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取产品当天数据
|
||||||
|
export function getProcessAutoReportDay(data) {
|
||||||
|
return request({
|
||||||
|
url: '/monitoring/production-monitor/getProcessAutoReportDay',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// 获取产品历史数据
|
||||||
|
export function getProcessAutoReportNew(data) {
|
||||||
|
return request({
|
||||||
|
url: '/monitoring/production-monitor/getProcessAutoReportNew',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,3 +14,78 @@ export function getSectionDataSearch(data) {
|
|||||||
data: data
|
data: data
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// 获取下片日志分页数据
|
||||||
|
export function getDownLogPage(data) {
|
||||||
|
return request({
|
||||||
|
url: '/base/down-log/page',
|
||||||
|
method: 'get',
|
||||||
|
params: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取下片日志历史数据
|
||||||
|
export function getDownLogHisData(data) {
|
||||||
|
return request({
|
||||||
|
url: '/base/down-log/pagehis',
|
||||||
|
method: 'get',
|
||||||
|
params: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// 导出下片日志Excel
|
||||||
|
export function exportDownLogData(query) {
|
||||||
|
return request({
|
||||||
|
url: '/base/down-log/export-excel',
|
||||||
|
method: 'get',
|
||||||
|
params: query,
|
||||||
|
responseType: 'blob',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 获得所有工厂产线列表
|
||||||
|
export function getPdList() {
|
||||||
|
return request({
|
||||||
|
url: '/base/production-line/listAll',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// 获得玻璃型号列表
|
||||||
|
export function getThick() {
|
||||||
|
return request({
|
||||||
|
url: '/base/down-log/thick',
|
||||||
|
method: 'get',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获得原片报表
|
||||||
|
export function getCostOriginRadioHisData(data) {
|
||||||
|
return request({
|
||||||
|
url: '/monitoring/cost-origin-ratio-his/page',
|
||||||
|
method: 'get',
|
||||||
|
params: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 修改原片报表
|
||||||
|
export function editCostOriginRadioHisData(data) {
|
||||||
|
return request({
|
||||||
|
url: '/monitoring/cost-origin-ratio-his/update',
|
||||||
|
method: 'put',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// 导出原片报表
|
||||||
|
export function exportCostOriginRadioHisData(data) {
|
||||||
|
return request({
|
||||||
|
url: '/monitoring/cost-origin-ratio-his/export-excel',
|
||||||
|
method: 'get',
|
||||||
|
params: data,
|
||||||
|
responseType: 'blob',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
56
src/api/monitoring/defectSummary.js
Normal file
56
src/api/monitoring/defectSummary.js
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
// 创建能源监控配置
|
||||||
|
export function getDefectSummaryTable(data) {
|
||||||
|
return request({
|
||||||
|
url: '/extend/check-gaozhun-record/defectSummaryTable',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export function getTranslucentPage(data) {
|
||||||
|
return request({
|
||||||
|
url: '/monitoring/translucent/page',
|
||||||
|
method: 'get',
|
||||||
|
params: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function exportTranslucent(data) {
|
||||||
|
return request({
|
||||||
|
url: '/monitoring/translucent/export-excel',
|
||||||
|
method: 'get',
|
||||||
|
params: data,
|
||||||
|
responseType: 'blob',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getDefectAnalysis(data) {
|
||||||
|
return request({
|
||||||
|
url: '/extend/check-gaozhun-record/defectAnalysis',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function getSectionDefect(data) {
|
||||||
|
return request({
|
||||||
|
url: '/extend/check-gaozhun-record/sectionDefect',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export function getDefectSummaryChart(data) {
|
||||||
|
return request({
|
||||||
|
url: '/extend/check-gaozhun-record/defectSummaryChart',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
export function getDefectSummaryDet(data) {
|
||||||
|
return request({
|
||||||
|
url: '/extend/check-gaozhun-record/defectSummaryDet',
|
||||||
|
method: 'post',
|
||||||
|
data: data,
|
||||||
|
});
|
||||||
|
}
|
||||||
BIN
src/assets/images/equipmentNum.png
Normal file
BIN
src/assets/images/equipmentNum.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
src/assets/images/equipmentNumImg.png
Normal file
BIN
src/assets/images/equipmentNumImg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.1 KiB |
BIN
src/assets/images/runNum.png
Normal file
BIN
src/assets/images/runNum.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 13 KiB |
BIN
src/assets/images/runNumImg.png
Normal file
BIN
src/assets/images/runNumImg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 51 KiB |
BIN
src/assets/images/stopNum.png
Normal file
BIN
src/assets/images/stopNum.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
BIN
src/assets/images/stopNumImg.png
Normal file
BIN
src/assets/images/stopNumImg.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.1 KiB |
@@ -54,7 +54,7 @@ export default {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.currentMenu = this.menus[0];
|
// this.currentMenu = this.menus[0];
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
currentMenu(val) {
|
currentMenu(val) {
|
||||||
|
|||||||
@@ -6,104 +6,48 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-form
|
<el-form ref="form" :model="form" :label-width="`${labelWidth}px`" :size="size" :label-position="labelPosition"
|
||||||
ref="form"
|
v-loading="formLoading">
|
||||||
:model="form"
|
<el-row :gutter="20" v-for="(row, rindex) in rows" :key="rindex">
|
||||||
:label-width="`${labelWidth}px`"
|
<el-col v-for="col in row" :key="col.label" :span="24 / row.length">
|
||||||
:size="size"
|
<el-form-item :label="col.label" :prop="col.prop" :rules="col.rules">
|
||||||
:label-position="labelPosition"
|
<el-input v-if="col.input" v-model="form[col.prop]" @change="$emit('update', form)"
|
||||||
v-loading="formLoading">
|
:placeholder="`请输入${col.label}`" v-bind="col.bind" />
|
||||||
<el-row :gutter="20" v-for="(row, rindex) in rows" :key="rindex">
|
<el-input v-if="col.textarea" type="textarea" v-model="form[col.prop]" @change="$emit('update', form)"
|
||||||
<el-col v-for="col in row" :key="col.label" :span="24 / row.length">
|
:placeholder="`请输入${col.label}`" v-bind="col.bind" />
|
||||||
<el-form-item :label="col.label" :prop="col.prop" :rules="col.rules">
|
<el-select v-if="col.select" v-model="form[col.prop]" :placeholder="`请选择${col.label}`"
|
||||||
<el-input
|
@change="$emit('update', form)" v-bind="col.bind">
|
||||||
v-if="col.input"
|
<el-option v-for="opt in optionListOf[col.prop]" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||||
v-model="form[col.prop]"
|
</el-select>
|
||||||
@change="$emit('update', form)"
|
<el-date-picker v-if="col.datetime" v-model="form[col.prop]" type="datetime" :placeholder="`请选择${col.label}`"
|
||||||
:placeholder="`请输入${col.label}`"
|
value-format="timestamp" v-bind="col.bind"></el-date-picker>
|
||||||
v-bind="col.bind" />
|
<el-switch v-if="col.switch" v-model="form[col.prop]" active-color="#0b58ff" inactive-color="#e1e1e1"
|
||||||
<el-input
|
v-bind="col.bind" @change="handleSwitchChange(col.prop)"></el-switch>
|
||||||
v-if="col.textarea"
|
<component v-if="col.subcomponent" :key="col.key" :is="col.subcomponent" :inlineStyle="col.style"></component>
|
||||||
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-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"
|
|
||||||
:inlineStyle="col.style"></component>
|
|
||||||
|
|
||||||
<div
|
<div class="upload-area" :class="uploadOpen ? '' : 'height-48'" ref="uploadArea" v-if="col.upload">
|
||||||
class="upload-area"
|
<span class="close-icon" :class="uploadOpen ? 'open' : ''">
|
||||||
:class="uploadOpen ? '' : 'height-48'"
|
<el-button type="text" icon="el-icon-arrow-right" @click="handleFilesOpen" />
|
||||||
ref="uploadArea"
|
</span>
|
||||||
v-if="col.upload">
|
<!-- :file-list="uploadedFileList" -->
|
||||||
<span class="close-icon" :class="uploadOpen ? 'open' : ''">
|
<el-upload class="upload-in-dialog" v-if="col.upload" :action="uploadUrl" :headers="uploadHeaders"
|
||||||
<el-button
|
:show-file-list="false" icon="el-icon-upload2" :before-upload="beforeUpload"
|
||||||
type="text"
|
:on-success="handleUploadSuccess" v-bind="col.bind">
|
||||||
icon="el-icon-arrow-right"
|
<el-button size="mini" :disabled="col.bind?.disabled || false">
|
||||||
@click="handleFilesOpen" />
|
<svg-icon icon-class="icon-upload" style="color: inherit"></svg-icon>
|
||||||
</span>
|
上传文件
|
||||||
<!-- :file-list="uploadedFileList" -->
|
</el-button>
|
||||||
<el-upload
|
<div class="el-upload__tip" slot="tip" v-if="col.uploadTips">
|
||||||
class="upload-in-dialog"
|
{{ col.uploadTips || '只能上传jpg/png文件, 大小不超过2MB' }}
|
||||||
v-if="col.upload"
|
</div>
|
||||||
:action="uploadUrl"
|
</el-upload>
|
||||||
:headers="uploadHeaders"
|
<uploadedFile class="file" v-for="file in form[col.prop] || []" :file="file" :key="file.fileUrl"
|
||||||
:show-file-list="false"
|
@delete="handleDeleteFile(file)" @Preview="handlePreview(file)" />
|
||||||
icon="el-icon-upload2"
|
</div>
|
||||||
:before-upload="beforeUpload"
|
</el-form-item>
|
||||||
:on-success="handleUploadSuccess"
|
</el-col>
|
||||||
v-bind="col.bind">
|
</el-row>
|
||||||
<el-button size="mini" :disabled="col.bind?.disabled || false">
|
</el-form>
|
||||||
<svg-icon
|
|
||||||
icon-class="icon-upload"
|
|
||||||
style="color: inherit"></svg-icon>
|
|
||||||
上传文件
|
|
||||||
</el-button>
|
|
||||||
<div class="el-upload__tip" slot="tip" v-if="col.uploadTips">
|
|
||||||
{{ col.uploadTips || '只能上传jpg/png文件, 大小不超过2MB' }}
|
|
||||||
</div>
|
|
||||||
</el-upload>
|
|
||||||
<uploadedFile
|
|
||||||
class="file"
|
|
||||||
v-for="file in form[col.prop] || []"
|
|
||||||
:file="file"
|
|
||||||
:key="file.fileUrl"
|
|
||||||
@delete="handleDeleteFile(file)"
|
|
||||||
@Preview="handlePreview(file)" />
|
|
||||||
</div>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -115,346 +59,353 @@ import tupleImg from '@/assets/images/tuple.png';
|
|||||||
* @param {*} options
|
* @param {*} options
|
||||||
*/
|
*/
|
||||||
function findMaxLabelWidth(rows) {
|
function findMaxLabelWidth(rows) {
|
||||||
let max = 0;
|
let max = 0;
|
||||||
rows.forEach((row) => {
|
rows.forEach((row) => {
|
||||||
row.forEach((opt) => {
|
row.forEach((opt) => {
|
||||||
// debugger;
|
// debugger;
|
||||||
if (!opt.label) return 0;
|
if (!opt.label) return 0;
|
||||||
if (opt.label.length > max) {
|
if (opt.label.length > max) {
|
||||||
max = opt.label.length;
|
max = opt.label.length;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
return max;
|
return max;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uploadedFile = {
|
const uploadedFile = {
|
||||||
name: 'UploadedFile',
|
name: 'UploadedFile',
|
||||||
props: ['file'],
|
props: ['file'],
|
||||||
data() {
|
data() {
|
||||||
return {};
|
return {};
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleDelete() {
|
|
||||||
this.$emit('delete', this.file);
|
handleDelete() {
|
||||||
},
|
this.$emit('delete', this.file);
|
||||||
handlePreview() {
|
},
|
||||||
this.$emit('Preview', this.file);
|
handlePreview() {
|
||||||
},
|
this.$emit('Preview', this.file);
|
||||||
},
|
},
|
||||||
mounted() {},
|
},
|
||||||
render: function (h) {
|
mounted() { },
|
||||||
return (
|
render: function (h) {
|
||||||
<div
|
return (
|
||||||
title={this.file.fileName}
|
<div
|
||||||
style={{
|
title={this.file.fileName}
|
||||||
background: `url(${tupleImg}) no-repeat`,
|
style={{
|
||||||
backgroundSize: '14px',
|
background: `url(${tupleImg}) no-repeat`,
|
||||||
backgroundPosition: '0 55%',
|
backgroundSize: '14px',
|
||||||
paddingLeft: '20px',
|
backgroundPosition: '0 55%',
|
||||||
paddingRight: '24px',
|
paddingLeft: '20px',
|
||||||
textOverflow: 'ellipsis',
|
paddingRight: '24px',
|
||||||
whiteSpace: 'nowrap',
|
textOverflow: 'ellipsis',
|
||||||
overflow: 'hidden',
|
whiteSpace: 'nowrap',
|
||||||
cursor: 'pointer',
|
overflow: 'hidden',
|
||||||
display: 'inline-block',
|
cursor: 'pointer',
|
||||||
}}>
|
display: 'inline-block',
|
||||||
<el-button onClick={this.handlePreview}>{this.file.fileName}</el-button>
|
}}>
|
||||||
<el-button
|
<el-button onClick={this.handlePreview}>{this.file.fileName}</el-button>
|
||||||
type="text"
|
<el-button
|
||||||
icon="el-icon-close"
|
type="text"
|
||||||
style="float: right; position: relative; top: 2px; left: 8px; z-index: 100"
|
icon="el-icon-close"
|
||||||
class="dialog__upload_component__close"
|
style="float: right; position: relative; top: 2px; left: 8px; z-index: 100"
|
||||||
onClick={this.handleDelete}
|
class="dialog__upload_component__close"
|
||||||
/>
|
onClick={this.handleDelete}
|
||||||
</div>
|
/>
|
||||||
);
|
</div>
|
||||||
},
|
);
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'DialogForm',
|
name: 'DialogForm',
|
||||||
model: {
|
model: {
|
||||||
prop: 'dataForm',
|
prop: 'dataForm',
|
||||||
event: 'update',
|
event: 'update',
|
||||||
},
|
},
|
||||||
emits: ['update'],
|
emits: ['update'],
|
||||||
components: { uploadedFile },
|
components: { uploadedFile },
|
||||||
props: {
|
props: {
|
||||||
rows: {
|
rows: {
|
||||||
type: Array,
|
type: Array,
|
||||||
default: () => [],
|
default: () => [],
|
||||||
},
|
},
|
||||||
dataForm: {
|
dataForm: {
|
||||||
type: Object,
|
type: Object,
|
||||||
default: () => ({}),
|
default: () => ({}),
|
||||||
},
|
},
|
||||||
disabled: {
|
disabled: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
hasFile: {
|
hasFile: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
labelPosition: {
|
labelPosition: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'right',
|
default: 'right',
|
||||||
},
|
},
|
||||||
size: {
|
size: {
|
||||||
type: String,
|
type: String,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
uploadOpen: false,
|
uploadOpen: false,
|
||||||
form: {},
|
form: {},
|
||||||
formLoading: true,
|
formLoading: true,
|
||||||
optionListOf: {},
|
optionListOf: {},
|
||||||
uploadedFileList: [],
|
uploadedFileList: [],
|
||||||
dataLoaded: false,
|
dataLoaded: false,
|
||||||
uploadHeaders: { Authorization: 'Bearer ' + getAccessToken() },
|
uploadHeaders: { Authorization: 'Bearer ' + getAccessToken() },
|
||||||
uploadUrl: process.env.VUE_APP_BASE_API + '/admin-api/infra/file/upload', // 上传有关的headers,url都是固定的
|
uploadUrl: process.env.VUE_APP_BASE_API + '/admin-api/infra/file/upload', // 上传有关的headers,url都是固定的
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
labelWidth() {
|
labelWidth() {
|
||||||
let max = findMaxLabelWidth(this.rows);
|
let max = findMaxLabelWidth(this.rows);
|
||||||
// 每个汉字占20px
|
// 每个汉字占20px
|
||||||
return max * 20;
|
return max * 20;
|
||||||
// return max * 20 + 'px';
|
// return max * 20 + 'px';
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
rows: {
|
rows: {
|
||||||
handler() {
|
handler() {
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.handleOptions('watch');
|
this.handleOptions('watch');
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
deep: true,
|
deep: true,
|
||||||
immediate: false,
|
immediate: false,
|
||||||
},
|
},
|
||||||
dataForm: {
|
dataForm: {
|
||||||
handler(val) {
|
handler(val) {
|
||||||
this.form = JSON.parse(JSON.stringify(val));
|
this.form = JSON.parse(JSON.stringify(val));
|
||||||
if (this.hasFile) {
|
if (this.hasFile) {
|
||||||
this.form.files = this.form.files ?? [];
|
this.form.files = this.form.files ?? [];
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
deep: true,
|
deep: true,
|
||||||
immediate: true,
|
immediate: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
// 处理 options
|
// 处理 options
|
||||||
this.handleOptions();
|
this.handleOptions();
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
/** 模拟透传 ref */
|
handleSwitchChange(prop) {
|
||||||
validate(cb) {
|
// 触发 update 事件,将最新的 form 数据传递给父组件
|
||||||
return this.$refs.form.validate(cb);
|
this.$emit('update', { ...this.form });
|
||||||
},
|
console.log(`switch ${prop} 变化:`, this.form[prop]);
|
||||||
resetFields(args) {
|
},
|
||||||
return this.$refs.form.resetFields(args);
|
/** 模拟透传 ref */
|
||||||
},
|
validate(cb) {
|
||||||
async handlePreview(file) {
|
return this.$refs.form.validate(cb);
|
||||||
const data = await this.$axios({
|
},
|
||||||
url: file.fileUrl,
|
resetFields(args) {
|
||||||
method: 'get',
|
return this.$refs.form.resetFields(args);
|
||||||
responseType: 'blob',
|
},
|
||||||
});
|
async handlePreview(file) {
|
||||||
const link = document.createElement('a');
|
const data = await this.$axios({
|
||||||
link.href = window.URL.createObjectURL(new Blob([data]));
|
url: file.fileUrl,
|
||||||
link.download = file.fileName;
|
method: 'get',
|
||||||
document.body.appendChild(link);
|
responseType: 'blob',
|
||||||
link.click();
|
});
|
||||||
document.body.removeChild(link);
|
const link = document.createElement('a');
|
||||||
window.URL.revokeObjectURL(link.href);
|
link.href = window.URL.createObjectURL(new Blob([data]));
|
||||||
},
|
link.download = file.fileName;
|
||||||
// getCode
|
document.body.appendChild(link);
|
||||||
async getCode(url) {
|
link.click();
|
||||||
const response = await this.$axios(url);
|
document.body.removeChild(link);
|
||||||
return response.data;
|
window.URL.revokeObjectURL(link.href);
|
||||||
},
|
},
|
||||||
async handleOptions(trigger = 'monuted') {
|
// getCode
|
||||||
console.log('[dialogForm:handleOptions]');
|
async getCode(url) {
|
||||||
const promiseList = [];
|
const response = await this.$axios(url);
|
||||||
this.rows.forEach((cols) => {
|
return response.data;
|
||||||
cols.forEach((opt) => {
|
},
|
||||||
if (opt.value && !this.form[opt.prop]) {
|
async handleOptions(trigger = 'monuted') {
|
||||||
// 默认值
|
console.log('[dialogForm:handleOptions]');
|
||||||
this.form[opt.prop] = opt.value;
|
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) {
|
if (opt.options) {
|
||||||
this.$set(this.optionListOf, opt.prop, opt.options);
|
this.$set(this.optionListOf, opt.prop, opt.options);
|
||||||
} else if (opt.url) {
|
} else if (opt.url) {
|
||||||
// 如果有 depends,则暂时先不获取,注册一个watcher
|
// 如果有 depends,则暂时先不获取,注册一个watcher
|
||||||
if (opt.depends) {
|
if (opt.depends) {
|
||||||
console.log('[handleOptions] setting watch');
|
console.log('[handleOptions] setting watch');
|
||||||
this.$watch(
|
this.$watch(
|
||||||
() => this.form[opt.depends],
|
() => this.form[opt.depends],
|
||||||
(id) => {
|
(id) => {
|
||||||
console.log('<', opt.depends, '>', 'changed', id);
|
console.log('<', opt.depends, '>', 'changed', id);
|
||||||
if (id == null) return;
|
if (id == null) return;
|
||||||
// 清空原有选项
|
// 清空原有选项
|
||||||
this.form[opt.prop] = null;
|
this.form[opt.prop] = null;
|
||||||
// 获取新的选项
|
// 获取新的选项
|
||||||
this.$axios({
|
this.$axios({
|
||||||
url: `${opt.url}?id=${id}`,
|
url: `${opt.url}?id=${id}`,
|
||||||
}).then((res) => {
|
}).then((res) => {
|
||||||
this.$set(
|
this.$set(
|
||||||
this.optionListOf,
|
this.optionListOf,
|
||||||
opt.prop,
|
opt.prop,
|
||||||
res.data.map((item) => ({
|
res.data.map((item) => ({
|
||||||
label: item[opt.labelKey ?? 'name'],
|
label: item[opt.labelKey ?? 'name'],
|
||||||
value: item[opt.valueKey ?? 'id'],
|
value: item[opt.valueKey ?? 'id'],
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
immediate: true,
|
immediate: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// 如果是下拉框,或者新增模式下的输入框,才去请求
|
// 如果是下拉框,或者新增模式下的输入框,才去请求
|
||||||
if (opt.select || (opt.input && !this.form?.id)) {
|
if (opt.select || (opt.input && !this.form?.id)) {
|
||||||
promiseList.push(async () => {
|
promiseList.push(async () => {
|
||||||
const response = await this.$axios(opt.url, {
|
const response = await this.$axios(opt.url, {
|
||||||
method: opt.method ?? 'get',
|
method: opt.method ?? 'get',
|
||||||
});
|
});
|
||||||
console.log('[dialogForm:handleOptions:response]', response);
|
console.log('[dialogForm:handleOptions:response]', response);
|
||||||
if (opt.select) {
|
if (opt.select) {
|
||||||
// 处理下拉框选项
|
// 处理下拉框选项
|
||||||
const list =
|
const list =
|
||||||
'list' in response.data
|
'list' in response.data
|
||||||
? response.data.list
|
? response.data.list
|
||||||
: response.data;
|
: response.data;
|
||||||
this.$set(
|
this.$set(
|
||||||
this.optionListOf,
|
this.optionListOf,
|
||||||
opt.prop,
|
opt.prop,
|
||||||
list.map((item) => ({
|
list.map((item) => ({
|
||||||
label: item[opt.labelKey ?? 'name'],
|
label: item[opt.labelKey ?? 'name'],
|
||||||
value: item[opt.valueKey ?? 'id'],
|
value: item[opt.valueKey ?? 'id'],
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
} else if (opt.input) {
|
} else if (opt.input) {
|
||||||
console.log('setting code: ', response.data);
|
console.log('setting code: ', response.data);
|
||||||
// 处理输入框数据
|
// 处理输入框数据
|
||||||
this.form[opt.prop] = response.data;
|
this.form[opt.prop] = response.data;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('[dialogForm:handleOptions] done!');
|
console.log('[dialogForm:handleOptions] done!');
|
||||||
|
|
||||||
// 如果是 watch 触发的,不需要执行进一步的请求
|
// 如果是 watch 触发的,不需要执行进一步的请求
|
||||||
if (trigger == 'watch') {
|
if (trigger == 'watch') {
|
||||||
this.formLoading = false;
|
this.formLoading = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
await Promise.all(promiseList.map((fn) => fn()));
|
await Promise.all(promiseList.map((fn) => fn()));
|
||||||
this.formLoading = false;
|
this.formLoading = false;
|
||||||
this.dataLoaded = true;
|
this.dataLoaded = true;
|
||||||
// console.log("[dialogForm:handleOptions:optionListOf]", this.optionListOf)
|
// console.log("[dialogForm:handleOptions:optionListOf]", this.optionListOf)
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log('[dialogForm:handleOptions:error]', error);
|
console.log('[dialogForm:handleOptions:error]', error);
|
||||||
this.formLoading = false;
|
this.formLoading = false;
|
||||||
}
|
}
|
||||||
if (!promiseList.length) this.formLoading = false;
|
if (!promiseList.length) this.formLoading = false;
|
||||||
},
|
},
|
||||||
// 上传成功的特殊处理
|
// 上传成功的特殊处理
|
||||||
beforeUpload(file) {
|
beforeUpload(file) {
|
||||||
console.log(file)
|
console.log(file)
|
||||||
},
|
},
|
||||||
// 上传前的验证规则可通过 bind 属性传入
|
// 上传前的验证规则可通过 bind 属性传入
|
||||||
handleUploadSuccess(response, file, fileList) {
|
handleUploadSuccess(response, file, fileList) {
|
||||||
this.form.files.push({
|
this.form.files.push({
|
||||||
fileName: file.name,
|
fileName: file.name,
|
||||||
fileUrl: response.data,
|
fileUrl: response.data,
|
||||||
fileType: 2,
|
fileType: 2,
|
||||||
});
|
});
|
||||||
this.$modal.msgSuccess('上传成功');
|
this.$modal.msgSuccess('上传成功');
|
||||||
this.$emit('update', this.form);
|
this.$emit('update', this.form);
|
||||||
},
|
},
|
||||||
|
|
||||||
getFileName(fileUrl) {
|
getFileName(fileUrl) {
|
||||||
return fileUrl.split('/').pop();
|
return fileUrl.split('/').pop();
|
||||||
},
|
},
|
||||||
|
|
||||||
handleFilesOpen() {
|
handleFilesOpen() {
|
||||||
this.uploadOpen = !this.uploadOpen;
|
this.uploadOpen = !this.uploadOpen;
|
||||||
},
|
},
|
||||||
|
|
||||||
handleDeleteFile(file) {
|
handleDeleteFile(file) {
|
||||||
this.form.files = this.form.files.filter(
|
this.form.files = this.form.files.filter(
|
||||||
(item) => item.fileUrl != file.fileUrl
|
(item) => item.fileUrl != file.fileUrl
|
||||||
);
|
);
|
||||||
this.$emit('update', this.form);
|
this.$emit('update', this.form);
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.el-date-editor,
|
.el-date-editor,
|
||||||
.el-select {
|
.el-select {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-area {
|
.upload-area {
|
||||||
// background: #ccc;
|
// background: #ccc;
|
||||||
// display: grid;
|
// display: grid;
|
||||||
// grid-auto-rows: 34px;
|
// grid-auto-rows: 34px;
|
||||||
// grid-template-columns: repeat(6, minmax(32px, max-content));
|
// grid-template-columns: repeat(6, minmax(32px, max-content));
|
||||||
// gap: 8px;
|
// gap: 8px;
|
||||||
// align-items: center;
|
// align-items: center;
|
||||||
position: relative;
|
position: relative;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transition: height 0.3s ease-out;
|
transition: height 0.3s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.upload-in-dialog {
|
.upload-in-dialog {
|
||||||
// display: inline-block;
|
// display: inline-block;
|
||||||
margin-right: 24px;
|
margin-right: 24px;
|
||||||
// background: #ccc;
|
// background: #ccc;
|
||||||
position: relative;
|
position: relative;
|
||||||
// top: -13px;
|
// top: -13px;
|
||||||
float: left;
|
float: left;
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-icon {
|
.close-icon {
|
||||||
// background: #ccc;
|
// background: #ccc;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 12px;
|
right: 12px;
|
||||||
z-index: 100;
|
z-index: 100;
|
||||||
transition: transform 0.3s ease-out;
|
transition: transform 0.3s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.close-icon.open {
|
.close-icon.open {
|
||||||
transform: rotateZ(90deg);
|
transform: rotateZ(90deg);
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.dialog__upload_component__close {
|
.dialog__upload_component__close {
|
||||||
color: #ccc;
|
color: #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dialog__upload_component__close:hover {
|
.dialog__upload_component__close:hover {
|
||||||
/* color: #777; */
|
/* color: #777; */
|
||||||
color: red;
|
color: red;
|
||||||
}
|
}
|
||||||
|
|
||||||
.height-48 {
|
.height-48 {
|
||||||
height: 35px !important;
|
height: 35px !important;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -6,77 +6,47 @@
|
|||||||
* @Description:
|
* @Description:
|
||||||
-->
|
-->
|
||||||
<template>
|
<template>
|
||||||
<el-form
|
<el-form :model="dataForm" :rules="dataRule" ref="dataForm" v-if="visible" @keyup.enter.native="dataFormSubmit()"
|
||||||
:model="dataForm"
|
label-width="100px" label-position="top">
|
||||||
:rules="dataRule"
|
<el-row :gutter="20">
|
||||||
ref="dataForm"
|
<el-col :span="12">
|
||||||
v-if="visible"
|
<el-form-item label="原料名称" prop="materialId">
|
||||||
@keyup.enter.native="dataFormSubmit()"
|
<el-select v-model="dataForm.materialId" filterable @change="setCode" :style="{ width: '100%' }"
|
||||||
label-width="100px"
|
placeholder="请选择原料名称">
|
||||||
label-position="top">
|
<el-option v-for="item in MaterialList" :key="item.id" :label="item.name" :value="item.id"></el-option>
|
||||||
<el-row :gutter="20">
|
</el-select>
|
||||||
<el-col :span="12">
|
</el-form-item>
|
||||||
<el-form-item label="原料名称" prop="materialId">
|
</el-col>
|
||||||
<el-select
|
<el-col :span="12">
|
||||||
v-model="dataForm.materialId"
|
<el-form-item label="原料编码" prop="code">
|
||||||
filterable
|
<el-input v-model="dataForm.code" clearable readonly />
|
||||||
@change="setCode"
|
</el-form-item>
|
||||||
:style="{ width: '100%' }"
|
</el-col>
|
||||||
placeholder="请选择原料名称">
|
<el-col :span="12">
|
||||||
<el-option
|
<el-form-item label="生效开始时间" prop="startTime">
|
||||||
v-for="item in MaterialList"
|
<el-date-picker v-model="dataForm.startTime" type="date" value-format="timestamp" :style="{ width: '100%' }"
|
||||||
:key="item.id"
|
placeholder="选择开始时间"></el-date-picker>
|
||||||
:label="item.name"
|
</el-form-item>
|
||||||
:value="item.id"></el-option>
|
</el-col>
|
||||||
</el-select>
|
<el-col :span="12">
|
||||||
</el-form-item>
|
<el-form-item label="生效结束时间" prop="endTime">
|
||||||
</el-col>
|
<el-date-picker v-model="dataForm.endTime" type="date" value-format="timestamp" :style="{ width: '100%' }"
|
||||||
<el-col :span="12">
|
placeholder="选择结束时间"></el-date-picker>
|
||||||
<el-form-item label="原料编码" prop="code">
|
</el-form-item>
|
||||||
<el-input v-model="dataForm.code" clearable readonly />
|
</el-col>
|
||||||
</el-form-item>
|
<el-col :span="12">
|
||||||
</el-col>
|
<el-form-item label="单价" prop="price">
|
||||||
<el-col :span="12">
|
<el-input-number :min="0" style="width: 75%" v-model="dataForm.price" clearable placeholder="请输入单价" />
|
||||||
<el-form-item label="生效开始时间" prop="startTime">
|
{{ unit }}
|
||||||
<el-date-picker
|
</el-form-item>
|
||||||
v-model="dataForm.startTime"
|
</el-col>
|
||||||
type="date"
|
<el-col :span="12">
|
||||||
value-format="timestamp"
|
<el-form-item label="备注" prop="remark">
|
||||||
:style="{ width: '100%' }"
|
<el-input v-model="dataForm.remark" clearable placeholder="请输入备注" />
|
||||||
placeholder="选择开始时间"></el-date-picker>
|
</el-form-item>
|
||||||
</el-form-item>
|
</el-col>
|
||||||
</el-col>
|
</el-row>
|
||||||
<el-col :span="12">
|
</el-form>
|
||||||
<el-form-item label="生效结束时间" prop="endTime">
|
|
||||||
<el-date-picker
|
|
||||||
v-model="dataForm.endTime"
|
|
||||||
type="date"
|
|
||||||
value-format="timestamp"
|
|
||||||
:style="{ width: '100%' }"
|
|
||||||
placeholder="选择结束时间"></el-date-picker>
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="单价" prop="price">
|
|
||||||
<el-input-number
|
|
||||||
:min="0"
|
|
||||||
style="width: 75%"
|
|
||||||
v-model="dataForm.price"
|
|
||||||
clearable
|
|
||||||
placeholder="请输入允许留存时间" />
|
|
||||||
{{ unit }}
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="备注" prop="remark">
|
|
||||||
<el-input
|
|
||||||
v-model="dataForm.remark"
|
|
||||||
clearable
|
|
||||||
placeholder="请输入备注" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -146,7 +116,7 @@ export default {
|
|||||||
this.dataForm.code = item.code;
|
this.dataForm.code = item.code;
|
||||||
this.unit =
|
this.unit =
|
||||||
'元/' +
|
'元/' +
|
||||||
this.urlOptions.dictArr.dict0.find((d) => d.value === item.unit)
|
this.urlOptions.dictArr.dict0.find((d) => d.value == item.unit)
|
||||||
.label;
|
.label;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -47,15 +47,15 @@ const tableProps = [
|
|||||||
prop: 'equipmentName',
|
prop: 'equipmentName',
|
||||||
label: '设备',
|
label: '设备',
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
prop: 'size',
|
// prop: 'size',
|
||||||
label: '规格',
|
// label: '规格',
|
||||||
showOverflowtooltip: true,
|
// showOverflowtooltip: true,
|
||||||
},
|
// },
|
||||||
{
|
// {
|
||||||
prop: 'process',
|
// prop: 'process',
|
||||||
label: '产品工艺',
|
// label: '产品工艺',
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
prop: 'standardCt',
|
prop: 'standardCt',
|
||||||
label: '标准节拍pcs/min',
|
label: '标准节拍pcs/min',
|
||||||
@@ -119,16 +119,16 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
// 获取数据列表
|
// 获取数据列表
|
||||||
init(lineId, startTime, endTime) {
|
init(lId, startTime, endTime) {
|
||||||
this.eqChartData = [];
|
this.eqChartData = [];
|
||||||
this.time.startTime = startTime;
|
this.time.startTime = startTime;
|
||||||
this.time.endTime = endTime;
|
this.time.endTime = endTime;
|
||||||
this.dataListLoading = true;
|
this.dataListLoading = true;
|
||||||
getNewCTDet(lineId).then((response) => {
|
getNewCTDet({ lineId: [lId], startTime, endTime }).then((response) => {
|
||||||
this.tableData = response.data;
|
this.tableData = response.data;
|
||||||
this.dataListLoading = false;
|
this.dataListLoading = false;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
handleClick(val) {
|
handleClick(val) {
|
||||||
const data = {
|
const data = {
|
||||||
...this.time,
|
...this.time,
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ export default {
|
|||||||
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||||
},
|
},
|
||||||
{ prop: 'name', label: '设备类型名称' },
|
{ prop: 'name', label: '设备类型名称' },
|
||||||
{ prop: 'code', label: '检测类型编码' },
|
{ prop: 'code', label: '设备类型编码' },
|
||||||
{ prop: 'remark', label: '备注' },
|
{ prop: 'remark', label: '备注' },
|
||||||
],
|
],
|
||||||
searchBarFormConfig: [
|
searchBarFormConfig: [
|
||||||
|
|||||||
@@ -1,157 +1,114 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-drawer
|
<el-drawer :visible.sync="visible" :show-close="false" :wrapper-closable="false" class="drawer" size="60%">
|
||||||
:visible.sync="visible"
|
<small-title slot="title" :no-padding="true">
|
||||||
:show-close="false"
|
{{ isdetail ? '详情' : !dataForm.id ? '新增' : '编辑' }}
|
||||||
:wrapper-closable="false"
|
</small-title>
|
||||||
class="drawer"
|
|
||||||
size="60%">
|
|
||||||
<small-title slot="title" :no-padding="true">
|
|
||||||
{{ isdetail ? '详情' : !dataForm.id ? '新增' : '编辑' }}
|
|
||||||
</small-title>
|
|
||||||
|
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="visual-part">
|
<div class="visual-part">
|
||||||
<el-form
|
<el-form ref="dataForm" :model="dataForm" :rules="dataRule" label-width="100px" label-position="top"
|
||||||
ref="dataForm"
|
@keyup.enter.native="dataFormSubmit">
|
||||||
:model="dataForm"
|
<el-row :gutter="20">
|
||||||
:rules="dataRule"
|
<el-col :span="12">
|
||||||
label-width="100px"
|
<el-form-item label="产品编码" prop="code">
|
||||||
label-position="top"
|
<el-input v-model="dataForm.code" clearable :disabled="isdetail" placeholder="请输入产品编码" />
|
||||||
@keyup.enter.native="dataFormSubmit">
|
</el-form-item>
|
||||||
<el-row :gutter="20">
|
</el-col>
|
||||||
<el-col :span="12">
|
<el-col :span="12">
|
||||||
<el-form-item label="产品编码" prop="code">
|
<el-form-item label="产品名称" prop="name">
|
||||||
<el-input
|
<el-input v-model="dataForm.name" clearable :disabled="isdetail" placeholder="请输入产品名称" />
|
||||||
v-model="dataForm.code"
|
</el-form-item>
|
||||||
clearable
|
</el-col>
|
||||||
:disabled="isdetail"
|
</el-row>
|
||||||
placeholder="请输入产品编码" />
|
<el-row :gutter="20">
|
||||||
</el-form-item>
|
<el-col :span="12">
|
||||||
</el-col>
|
<el-form-item label="产品类型" prop="typeDictValue">
|
||||||
<el-col :span="12">
|
<el-select v-model="dataForm.typeDictValue" style="width: 100%" :disabled="isdetail"
|
||||||
<el-form-item label="产品名称" prop="name">
|
placeholder="请选择产品类型">
|
||||||
<el-input
|
<el-option v-for="dict in getDictDatas(DICT_TYPE.PRODUCT_TYPE)" :key="dict.value" :label="dict.label"
|
||||||
v-model="dataForm.name"
|
:value="dict.value" />
|
||||||
clearable
|
</el-select>
|
||||||
:disabled="isdetail"
|
</el-form-item>
|
||||||
placeholder="请输入产品名称" />
|
</el-col>
|
||||||
</el-form-item>
|
<el-col :span="12">
|
||||||
</el-col>
|
<el-form-item label="单位" prop="unitDictValue">
|
||||||
</el-row>
|
<el-select v-model="dataForm.unitDictValue" style="width: 100%" :disabled="isdetail"
|
||||||
<el-row :gutter="20">
|
placeholder="请选择单位">
|
||||||
<el-col :span="12">
|
<el-option v-for="dict in getDictDatas(DICT_TYPE.UNIT_DICT)" :key="dict.value" :label="dict.label"
|
||||||
<el-form-item label="产品类型" prop="typeDictValue">
|
:value="dict.value" />
|
||||||
<el-select
|
</el-select>
|
||||||
v-model="dataForm.typeDictValue"
|
</el-form-item>
|
||||||
style="width: 100%"
|
</el-col>
|
||||||
:disabled="isdetail"
|
</el-row>
|
||||||
placeholder="请选择产品类型">
|
<el-row :gutter="20">
|
||||||
<el-option
|
<el-col :span="12">
|
||||||
v-for="dict in getDictDatas(DICT_TYPE.PRODUCT_TYPE)"
|
<el-form-item label="原片规格" prop="originalSpecifications">
|
||||||
:key="dict.value"
|
<el-input :disabled="isdetail" v-model="dataForm.originalSpecifications" placeholder="请输入原片规格" />
|
||||||
:label="dict.label"
|
</el-form-item>
|
||||||
:value="dict.value" />
|
</el-col>
|
||||||
</el-select>
|
<el-col :span="12">
|
||||||
</el-form-item>
|
<el-form-item label="原片单位平方数" prop="originalArea">
|
||||||
</el-col>
|
<el-input :disabled="isdetail" v-model="dataForm.originalArea" placeholder="请输入原片单位平方数" />
|
||||||
<el-col :span="12">
|
</el-form-item>
|
||||||
<el-form-item label="单位" prop="unitDictValue">
|
</el-col>
|
||||||
<el-select
|
</el-row>
|
||||||
v-model="dataForm.unitDictValue"
|
<el-row :gutter="20">
|
||||||
style="width: 100%"
|
<el-col :span="12">
|
||||||
:disabled="isdetail"
|
<el-form-item label="深加工规格" prop="specifications">
|
||||||
placeholder="请选择单位">
|
<el-input :disabled="isdetail" v-model="dataForm.specifications" placeholder="请输入深加工规格" />
|
||||||
<el-option
|
</el-form-item>
|
||||||
v-for="dict in getDictDatas(DICT_TYPE.UNIT_DICT)"
|
</el-col>
|
||||||
:key="dict.value"
|
<el-col :span="12">
|
||||||
:label="dict.label"
|
<el-form-item label="深加工单位平方数" prop="area">
|
||||||
:value="dict.value" />
|
<el-input :disabled="isdetail" v-model="dataForm.area" placeholder="请输入深加工单位平方数" />
|
||||||
</el-select>
|
</el-form-item>
|
||||||
</el-form-item>
|
</el-col>
|
||||||
</el-col>
|
</el-row>
|
||||||
</el-row>
|
<el-row :gutter="20">
|
||||||
<el-row :gutter="20">
|
<el-col :span="12">
|
||||||
<el-col :span="12">
|
<el-form-item label="完成单位产品用时(S)" prop="processTime">
|
||||||
<el-form-item label="原片规格" prop="originalSpecifications">
|
<el-input :disabled="isdetail" v-model="dataForm.processTime" placeholder="请输入完成单位产品用时(S)" />
|
||||||
<el-input
|
</el-form-item>
|
||||||
:disabled="isdetail"
|
</el-col>
|
||||||
v-model="dataForm.originalSpecifications"
|
<el-col :span="12">
|
||||||
placeholder="请输入原片规格" />
|
<el-form-item label=" 产品工艺" prop="processTypes">
|
||||||
</el-form-item>
|
<el-select :disabled="isdetail" collapse-tags multiple v-model="dataForm.processTypes" clearable
|
||||||
</el-col>
|
style="width: 100%" placeholder="请选择产品工艺">
|
||||||
<el-col :span="12">
|
<el-option v-for="dict in processTypeList" :key="dict.value" :label="dict.label"
|
||||||
<el-form-item label="原片单位平方数" prop="originalArea">
|
:value="dict.value" />
|
||||||
<el-input
|
</el-select>
|
||||||
:disabled="isdetail"
|
</el-form-item>
|
||||||
v-model="dataForm.originalArea"
|
</el-col>
|
||||||
placeholder="请输入原片单位平方数" />
|
</el-row>
|
||||||
</el-form-item>
|
<el-row :gutter="20">
|
||||||
</el-col>
|
<el-col :span="12">
|
||||||
</el-row>
|
<el-form-item label=" 基板类型" prop="typeDictValue">
|
||||||
<el-row :gutter="20">
|
<el-select :disabled="isdetail" v-model="dataForm.typeDictValue" clearable style="width: 100%"
|
||||||
<el-col :span="12">
|
placeholder="请选择基板类型">
|
||||||
<el-form-item label="深加工规格" prop="specifications">
|
<el-option v-for="dict in typeList" :key="dict.value" :label="dict.label" :value="dict.value" />
|
||||||
<el-input
|
</el-select>
|
||||||
:disabled="isdetail"
|
</el-form-item>
|
||||||
v-model="dataForm.specifications"
|
</el-col>
|
||||||
placeholder="请输入深加工规格" />
|
</el-row>
|
||||||
</el-form-item>
|
</el-form>
|
||||||
</el-col>
|
|
||||||
<el-col :span="12">
|
|
||||||
<el-form-item label="深加工单位平方数" prop="area">
|
|
||||||
<el-input
|
|
||||||
:disabled="isdetail"
|
|
||||||
v-model="dataForm.area"
|
|
||||||
placeholder="请输入深加工单位平方数" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="20">
|
|
||||||
<el-col :span="24">
|
|
||||||
<el-form-item label="完成单位产品用时" prop="processTime">
|
|
||||||
<el-input
|
|
||||||
:disabled="isdetail"
|
|
||||||
v-model="dataForm.processTime"
|
|
||||||
placeholder="请输入完成单位产品用时" />
|
|
||||||
</el-form-item>
|
|
||||||
</el-col>
|
|
||||||
</el-row>
|
|
||||||
</el-form>
|
|
||||||
|
|
||||||
<small-title
|
<small-title style="margin: 16px 0; padding-left: 8px" :no-padding="true">
|
||||||
style="margin: 16px 0; padding-left: 8px"
|
产品属性列表
|
||||||
:no-padding="true">
|
</small-title>
|
||||||
产品属性列表
|
|
||||||
</small-title>
|
|
||||||
|
|
||||||
<div class="attr-list">
|
<div class="attr-list">
|
||||||
<base-table
|
<base-table :table-props="tableProps" :page="listQuery.pageNo" :limit="listQuery.pageSize"
|
||||||
:table-props="tableProps"
|
:add-button-show="isdetail ? null : '添加属性'" @emitButtonClick="addNew()" :table-data="productAttributeList">
|
||||||
:page="listQuery.pageNo"
|
<method-btn v-if="!isdetail" slot="handleBtn" :width="120" label="操作" :method-list="tableBtn"
|
||||||
:limit="listQuery.pageSize"
|
@clickBtn="handleClick" />
|
||||||
:add-button-show="isdetail ? null : '添加属性'"
|
</base-table>
|
||||||
@emitButtonClick="addNew()"
|
<pagination v-show="listQuery.total > 0" :total="listQuery.total" :page.sync="listQuery.pageNo"
|
||||||
:table-data="productAttributeList">
|
:limit.sync="listQuery.pageSize" :page-sizes="[5, 10, 15]" @pagination="getList" />
|
||||||
<method-btn
|
</div>
|
||||||
v-if="!isdetail"
|
</div>
|
||||||
slot="handleBtn"
|
</div>
|
||||||
: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>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!-- <div style="position: absolute; bottom: 24px; right: 24px">
|
<!-- <div style="position: absolute; bottom: 24px; right: 24px">
|
||||||
<el-button style="margin-right: 10px" @click="goback()">返回</el-button>
|
<el-button style="margin-right: 10px" @click="goback()">返回</el-button>
|
||||||
<el-button v-if="isdetail" type="primary" @click="goEdit()">
|
<el-button v-if="isdetail" type="primary" @click="goEdit()">
|
||||||
编辑
|
编辑
|
||||||
@@ -167,319 +124,378 @@
|
|||||||
</span>
|
</span>
|
||||||
</div> -->
|
</div> -->
|
||||||
|
|
||||||
<div class="drawer-body__footer">
|
<div class="drawer-body__footer">
|
||||||
<el-button style="" @click="goback()">取消</el-button>
|
<el-button style="" @click="goback()">取消</el-button>
|
||||||
<el-button v-if="isdetail" type="primary" @click="goEdit()">
|
<el-button v-if="isdetail" type="primary" @click="goEdit()">
|
||||||
编辑
|
编辑
|
||||||
</el-button>
|
</el-button>
|
||||||
<el-button v-else type="primary" @click="dataFormSubmit()">
|
<el-button v-else type="primary" @click="dataFormSubmit()">
|
||||||
确定
|
确定
|
||||||
</el-button>
|
</el-button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<product-attr-add
|
<product-attr-add v-if="addOrUpdateVisible" ref="addOrUpdate" :product-id="dataForm.id"
|
||||||
v-if="addOrUpdateVisible"
|
@refreshDataList="getList" />
|
||||||
ref="addOrUpdate"
|
</el-drawer>
|
||||||
:product-id="dataForm.id"
|
|
||||||
@refreshDataList="getList" />
|
|
||||||
</el-drawer>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
deleteProductAttr,
|
deleteProductAttr,
|
||||||
getProductAttrPage,
|
getProductAttrPage,
|
||||||
} from '@/api/core/base/productAttr';
|
} from '@/api/core/base/productAttr';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createProduct,
|
createProduct,
|
||||||
updateProduct,
|
updateProduct,
|
||||||
getProduct,
|
getProduct,
|
||||||
getCode,
|
getCode,
|
||||||
} from '@/api/core/base/product';
|
} from '@/api/core/base/product';
|
||||||
import productAttrAdd from './attr-add';
|
import productAttrAdd from './attr-add';
|
||||||
import { parseTime } from '../../mixins/code-filter';
|
import { parseTime } from '../../mixins/code-filter';
|
||||||
import SmallTitle from './SmallTitle';
|
import SmallTitle from './SmallTitle';
|
||||||
|
import { listData } from "@/api/system/dict/data"; //数据字典接口
|
||||||
const tableBtn = [
|
const tableBtn = [
|
||||||
{
|
{
|
||||||
type: 'edit',
|
type: 'edit',
|
||||||
btnName: '编辑',
|
btnName: '编辑',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'delete',
|
type: 'delete',
|
||||||
btnName: '删除',
|
btnName: '删除',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
const tableProps = [
|
const tableProps = [
|
||||||
{
|
{
|
||||||
prop: 'createTime',
|
prop: 'createTime',
|
||||||
label: '添加时间',
|
label: '添加时间',
|
||||||
filter: parseTime,
|
filter: parseTime,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
prop: 'name',
|
prop: 'name',
|
||||||
label: '属性名',
|
label: '属性名',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
prop: 'value',
|
prop: 'value',
|
||||||
label: '属性值',
|
label: '属性值',
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: { productAttrAdd, SmallTitle },
|
components: { productAttrAdd, SmallTitle },
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
visible: false,
|
visible: false,
|
||||||
addOrUpdateVisible: false,
|
addOrUpdateVisible: false,
|
||||||
tableBtn,
|
tableBtn,
|
||||||
tableProps,
|
tableProps,
|
||||||
productAttributeList: [],
|
productAttributeList: [],
|
||||||
dataForm: {
|
dataForm: {
|
||||||
id: null,
|
id: null,
|
||||||
name: '', // 产品名称
|
name: '', // 产品名称
|
||||||
code: '', // 产品编码
|
code: '', // 产品编码
|
||||||
area: 0, // 深加工单位平方数(float only)
|
area: 0, // 深加工单位平方数(float only)
|
||||||
typeDictValue: null, // 产品类型id
|
typeDictValue: null, // 产品类型id
|
||||||
processTime: null, // 单位产品用时 (s)
|
processTime: null, // 单位产品用时 (s)
|
||||||
specifications: '', // 深加工规格
|
specifications: '', // 深加工规格
|
||||||
unitDictValue: '', // 单位id
|
unitDictValue: '', // 单位id
|
||||||
originalSpecifications: '', // 原片规格
|
originalSpecifications: '', // 原片规格
|
||||||
originalArea: 0, // 原片单位平方数
|
originalArea: 0, // 原片单位平方数
|
||||||
},
|
processTypes: [],
|
||||||
listQuery: {
|
typeDictValue: null,
|
||||||
pageSize: 10,
|
},
|
||||||
pageNo: 1,
|
typeList: [],
|
||||||
total: 0,
|
listQuery: {
|
||||||
},
|
pageSize: 10,
|
||||||
dataRule: {
|
pageNo: 1,
|
||||||
code: [
|
total: 0,
|
||||||
{
|
},
|
||||||
required: true,
|
processTypeList: [
|
||||||
message: '产品编码不能为空',
|
// {
|
||||||
trigger: 'blur',
|
// value: '1',
|
||||||
},
|
// label: '压花丝印'
|
||||||
// {
|
// },
|
||||||
// type: 'number',
|
// {
|
||||||
// message: '产品编码为数字类型',
|
// value: '2',
|
||||||
// trigger: 'blur',
|
// label: '无印打孔'
|
||||||
// transfom: 'val => Number(val)',
|
// },
|
||||||
// },
|
// {
|
||||||
],
|
// value: '3',
|
||||||
name: [
|
// label: '单层镀膜'
|
||||||
{
|
// }, {
|
||||||
required: true,
|
// value: '4',
|
||||||
message: '产品名称不能为空',
|
// label: '双层镀膜'
|
||||||
trigger: 'blur',
|
// }
|
||||||
},
|
],
|
||||||
],
|
dataRule: {
|
||||||
typeDictValue: [
|
code: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '产品类型不能为空',
|
message: '产品编码不能为空',
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
},
|
},
|
||||||
],
|
// {
|
||||||
area: [
|
// type: 'number',
|
||||||
{
|
// message: '产品编码为数字类型',
|
||||||
type: 'number',
|
// trigger: 'blur',
|
||||||
message: '请输入正确的数值',
|
// transfom: 'val => Number(val)',
|
||||||
trigger: 'change',
|
// },
|
||||||
transform: (val) => Number(val),
|
],
|
||||||
},
|
name: [
|
||||||
],
|
{
|
||||||
processTime: [
|
required: true,
|
||||||
{
|
message: '产品名称不能为空',
|
||||||
required: true,
|
trigger: 'blur',
|
||||||
message: '完成单位产品用时不能为空',
|
},
|
||||||
trigger: 'blur',
|
],
|
||||||
},
|
typeDictValue: [
|
||||||
{
|
{
|
||||||
type: 'number',
|
required: true,
|
||||||
message: '请输入正确的数值',
|
message: '产品类型不能为空',
|
||||||
trigger: 'blur',
|
trigger: 'blur',
|
||||||
transform: (val) => Number(val),
|
},
|
||||||
},
|
],
|
||||||
],
|
area: [
|
||||||
},
|
{
|
||||||
isdetail: false,
|
type: 'number',
|
||||||
};
|
message: '请输入正确的数值',
|
||||||
},
|
trigger: 'change',
|
||||||
methods: {
|
transform: (val) => Number(val),
|
||||||
initData() {
|
},
|
||||||
this.productAttributeList.splice(0);
|
],
|
||||||
this.listQuery.total = 0;
|
processTime: [
|
||||||
},
|
{
|
||||||
init(id, isdetail) {
|
required: true,
|
||||||
this.initData();
|
message: '完成单位产品用时不能为空',
|
||||||
this.isdetail = isdetail || false;
|
trigger: 'blur',
|
||||||
this.dataForm.id = id || null;
|
},
|
||||||
this.visible = true;
|
{
|
||||||
|
type: 'number',
|
||||||
|
message: '请输入正确的数值',
|
||||||
|
trigger: 'blur',
|
||||||
|
transform: (val) => Number(val),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
isdetail: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async initData() {
|
||||||
|
this.productAttributeList.splice(0);
|
||||||
|
this.listQuery.total = 0;
|
||||||
|
const typeRes = await listData({
|
||||||
|
pageNo:
|
||||||
|
1,
|
||||||
|
pageSize
|
||||||
|
: 10,
|
||||||
|
dictType
|
||||||
|
: 'product_type'
|
||||||
|
})
|
||||||
|
|
||||||
this.$nextTick(() => {
|
this.typeList = typeRes.data.list
|
||||||
this.$refs['dataForm'].resetFields();
|
console.log('typeRes', this.typeList);
|
||||||
|
const processTypeRes = await listData({
|
||||||
|
pageNo:
|
||||||
|
1,
|
||||||
|
pageSize
|
||||||
|
: 10,
|
||||||
|
dictType
|
||||||
|
: 'process_type'
|
||||||
|
})
|
||||||
|
|
||||||
if (this.dataForm.id) {
|
this.processTypeList = processTypeRes.data.list
|
||||||
// 获取产品详情
|
console.log('typeRes', this.typeList);
|
||||||
getProduct(id).then((response) => {
|
},
|
||||||
this.dataForm = response.data;
|
init(id, isdetail) {
|
||||||
});
|
this.initData();
|
||||||
// 获取产品的属性列表
|
this.isdetail = isdetail || false;
|
||||||
this.getList();
|
this.dataForm.id = id || null;
|
||||||
} else {
|
// this.dataForm.processTypes = [] // 清空工艺选择
|
||||||
getCode().then((res) => {
|
this.visible = true;
|
||||||
this.dataForm.code = res.data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
getList() {
|
this.$nextTick(() => {
|
||||||
// 获取产品的属性列表
|
this.$refs['dataForm'].resetFields();
|
||||||
getProductAttrPage({
|
|
||||||
...this.listQuery,
|
if (this.dataForm.id) {
|
||||||
productId: this.dataForm.id,
|
// 获取产品详情
|
||||||
}).then((response) => {
|
getProduct(id).then((res) => {
|
||||||
this.productAttributeList = response.data.list;
|
const resData = res.data || {};
|
||||||
this.listQuery.total = response.data.total;
|
// 逐个字段赋值(保留响应式)
|
||||||
});
|
this.dataForm.name = resData.name || '';
|
||||||
},
|
this.dataForm.code = resData.code || '';
|
||||||
handleClick(raw) {
|
this.dataForm.area = resData.area || 0;
|
||||||
if (raw.type === 'delete') {
|
this.dataForm.typeDictValue = resData.typeDictValue || null;
|
||||||
this.$confirm(
|
this.dataForm.processTime = resData.processTime || null;
|
||||||
`确定对${
|
this.dataForm.specifications = resData.specifications || '';
|
||||||
raw.data.name
|
this.dataForm.unitDictValue = resData.unitDictValue || '';
|
||||||
? '[名称=' + raw.data.name + ']'
|
this.dataForm.originalSpecifications = resData.originalSpecifications || '';
|
||||||
: '[序号=' + raw.data._pageIndex + ']'
|
this.dataForm.originalArea = resData.originalArea || 0;
|
||||||
}进行删除操作?`,
|
|
||||||
'提示',
|
// 处理工艺列表:确保是数组,过滤空值
|
||||||
{
|
this.dataForm.processTypes = resData.processType
|
||||||
confirmButtonText: '确定',
|
? resData.processType.split(',').filter(Boolean)
|
||||||
cancelButtonText: '取消',
|
: [];
|
||||||
type: 'warning',
|
|
||||||
}
|
console.log('工艺列表(编辑时):', this.dataForm.processTypes); // 验证是否为 ["1","2"] 格式
|
||||||
)
|
});
|
||||||
.then(() => {
|
// 获取产品的属性列表
|
||||||
deleteProductAttr(raw.data.id).then(({ data }) => {
|
this.getList();
|
||||||
this.$message({
|
} else {
|
||||||
message: '操作成功',
|
getCode().then((res) => {
|
||||||
type: 'success',
|
this.dataForm.code = res.data;
|
||||||
duration: 1500,
|
});
|
||||||
onClose: () => {
|
}
|
||||||
this.getList();
|
});
|
||||||
},
|
},
|
||||||
});
|
|
||||||
});
|
getList() {
|
||||||
})
|
// 获取产品的属性列表
|
||||||
.catch(() => {});
|
getProductAttrPage({
|
||||||
} else {
|
...this.listQuery,
|
||||||
this.addNew(raw.data.id);
|
productId: this.dataForm.id,
|
||||||
}
|
}).then((response) => {
|
||||||
},
|
this.productAttributeList = response.data.list;
|
||||||
// 表单提交
|
this.listQuery.total = response.data.total;
|
||||||
dataFormSubmit() {
|
});
|
||||||
this.$refs['dataForm'].validate((valid) => {
|
},
|
||||||
if (valid) {
|
handleClick(raw) {
|
||||||
// 修改的提交
|
if (raw.type === 'delete') {
|
||||||
if (this.dataForm.id) {
|
this.$confirm(
|
||||||
updateProduct(this.dataForm).then((response) => {
|
`确定对${raw.data.name
|
||||||
this.$modal.msgSuccess('修改成功');
|
? '[名称=' + raw.data.name + ']'
|
||||||
this.visible = false;
|
: '[序号=' + raw.data._pageIndex + ']'
|
||||||
this.$emit('refreshDataList');
|
}进行删除操作?`,
|
||||||
});
|
'提示',
|
||||||
return;
|
{
|
||||||
}
|
confirmButtonText: '确定',
|
||||||
// 添加的提交
|
cancelButtonText: '取消',
|
||||||
createProduct(this.dataForm).then((response) => {
|
type: 'warning',
|
||||||
this.$modal.msgSuccess('新增成功');
|
}
|
||||||
this.$confirm(`是否新增产品属性?`, '系统提示', {
|
)
|
||||||
confirmButtonText: '确定',
|
.then(() => {
|
||||||
cancelButtonText: '取消',
|
deleteProductAttr(raw.data.id).then(({ data }) => {
|
||||||
type: 'warning',
|
this.$message({
|
||||||
})
|
message: '操作成功',
|
||||||
.then(() => {
|
type: 'success',
|
||||||
|
duration: 1500,
|
||||||
|
onClose: () => {
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(() => { });
|
||||||
|
} else {
|
||||||
|
this.addNew(raw.data.id);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 表单提交
|
||||||
|
dataFormSubmit() {
|
||||||
|
this.$refs['dataForm'].validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
|
||||||
|
// 修改的提交
|
||||||
|
if (this.dataForm.id) {
|
||||||
|
updateProduct(this.dataForm).then((response) => {
|
||||||
|
this.$modal.msgSuccess('修改成功');
|
||||||
|
this.visible = false;
|
||||||
|
this.$emit('refreshDataList');
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 添加的提交
|
||||||
|
createProduct(this.dataForm).then((response) => {
|
||||||
|
this.$modal.msgSuccess('新增成功');
|
||||||
|
this.$confirm(`是否新增产品属性?`, '系统提示', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning',
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
this.dataForm.id = response.data
|
this.dataForm.id = response.data
|
||||||
this.addNew();
|
this.addNew();
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
this.visible = false;
|
this.visible = false;
|
||||||
this.$emit('refreshDataList');
|
this.$emit('refreshDataList');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
goEdit() {
|
goEdit() {
|
||||||
this.isdetail = false;
|
this.isdetail = false;
|
||||||
},
|
},
|
||||||
// 新增 / 修改
|
// 新增 / 修改
|
||||||
addNew(id) {
|
addNew(id) {
|
||||||
if (this.dataForm.id) {
|
if (this.dataForm.id) {
|
||||||
this.addOrUpdateVisible = true;
|
this.addOrUpdateVisible = true;
|
||||||
this.$nextTick(() => {
|
this.$nextTick(() => {
|
||||||
this.$refs.addOrUpdate.init(id);
|
this.$refs.addOrUpdate.init(id);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.$message('请先创建产品!');
|
this.$message('请先创建产品!');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
goback() {
|
goback() {
|
||||||
this.$emit('refreshDataList');
|
this.$emit('refreshDataList');
|
||||||
this.visible = false;
|
this.visible = false;
|
||||||
this.initData();
|
this.initData();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.drawer >>> .el-drawer {
|
.drawer>>>.el-drawer {
|
||||||
border-radius: 8px 0 0 8px;
|
border-radius: 8px 0 0 8px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer >>> .el-form-item__label {
|
.drawer>>>.el-form-item__label {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer >>> .el-drawer__header {
|
.drawer>>>.el-drawer__header {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 32px 32px 24px;
|
padding: 32px 32px 24px;
|
||||||
border-bottom: 1px solid #dcdfe6;
|
border-bottom: 1px solid #dcdfe6;
|
||||||
}
|
|
||||||
.drawer >>> .el-drawer__body {
|
|
||||||
flex: 1;
|
|
||||||
height: 1px;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer >>> .content {
|
.drawer>>>.el-drawer__body {
|
||||||
padding: 30px 24px;
|
flex: 1;
|
||||||
flex: 1;
|
height: 1px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
/* height: 100%; */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer >>> .visual-part {
|
.drawer>>>.content {
|
||||||
flex: 1 auto;
|
padding: 30px 24px;
|
||||||
max-height: 76vh;
|
flex: 1;
|
||||||
overflow: hidden;
|
display: flex;
|
||||||
overflow-y: scroll;
|
flex-direction: column;
|
||||||
padding-right: 10px; /* 调整滚动条样式 */
|
/* height: 100%; */
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer >>> .el-form,
|
.drawer>>>.visual-part {
|
||||||
.drawer >>> .attr-list {
|
flex: 1 auto;
|
||||||
padding: 0 16px;
|
max-height: 76vh;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
padding-right: 10px;
|
||||||
|
/* 调整滚动条样式 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer>>>.el-form,
|
||||||
|
.drawer>>>.attr-list {
|
||||||
|
padding: 0 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawer-body__footer {
|
.drawer-body__footer {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
padding: 18px;
|
padding: 18px;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
278
src/views/core/monitoring/groupReport/baseTable.vue
Normal file
278
src/views/core/monitoring/groupReport/baseTable.vue
Normal file
@@ -0,0 +1,278 @@
|
|||||||
|
<template>
|
||||||
|
<div class="baseTable">
|
||||||
|
<el-table
|
||||||
|
:ref="id"
|
||||||
|
:data="renderData"
|
||||||
|
v-bind="$attrs"
|
||||||
|
:border="cancelBorder ? false : true"
|
||||||
|
@current-change="currentChange"
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
|
style="width: 100%"
|
||||||
|
:header-cell-style="{
|
||||||
|
background: '#F2F4F9',
|
||||||
|
color: '#606266',
|
||||||
|
}">
|
||||||
|
<!-- 多选 -->
|
||||||
|
<el-table-column
|
||||||
|
v-if="selectWidth"
|
||||||
|
type="selection"
|
||||||
|
:width="selectWidth" />
|
||||||
|
<!-- 序号 -->
|
||||||
|
<el-table-column
|
||||||
|
v-if="page && limit"
|
||||||
|
prop="_pageIndex"
|
||||||
|
:width="pageWidth"
|
||||||
|
align="center"
|
||||||
|
:fixed="cancelPageFixed ? false : true">
|
||||||
|
<template slot="header">
|
||||||
|
<el-popover placement="bottom-start" width="300" trigger="click">
|
||||||
|
<div
|
||||||
|
class="setting-box"
|
||||||
|
style="max-height: 400px; overflow-y: auto">
|
||||||
|
<el-checkbox
|
||||||
|
v-for="(item, index) in tableProps"
|
||||||
|
:key="'cb' + index"
|
||||||
|
v-model="selectedBox[index]"
|
||||||
|
:label="item.label" />
|
||||||
|
</div>
|
||||||
|
<i slot="reference" class="el-icon-s-tools" />
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
v-for="item in renderTableHeadList"
|
||||||
|
:key="item.prop"
|
||||||
|
v-bind="item"
|
||||||
|
:label="item.label"
|
||||||
|
:prop="item.prop"
|
||||||
|
:fixed="item.fixed || false"
|
||||||
|
:show-overflow-tooltip="item.showOverflowtooltip || false"
|
||||||
|
:sortable="item.sortable || false">
|
||||||
|
<template slot="header">
|
||||||
|
<span>{{ item.label }}</span>
|
||||||
|
</template>
|
||||||
|
<!-- 多表头 -->
|
||||||
|
<template v-if="item.children">
|
||||||
|
<el-table-column
|
||||||
|
v-for="sub in item.children"
|
||||||
|
:prop="sub.prop"
|
||||||
|
:key="sub.prop"
|
||||||
|
v-bind="sub"
|
||||||
|
:label="sub.label">
|
||||||
|
<template v-if="sub.children">
|
||||||
|
<el-table-column
|
||||||
|
v-for="ssub in sub.children"
|
||||||
|
:prop="ssub.prop"
|
||||||
|
:key="ssub.prop"
|
||||||
|
v-bind="ssub"
|
||||||
|
:label="ssub.label">
|
||||||
|
<template slot-scope="sscopeInner">
|
||||||
|
<component
|
||||||
|
:is="ssub.subcomponent"
|
||||||
|
v-if="ssub.subcomponent"
|
||||||
|
:key="sscopeInner.row.id"
|
||||||
|
:inject-data="{ ...sscopeInner.row, ...ssub }"
|
||||||
|
@emitData="emitData" />
|
||||||
|
<span v-else>
|
||||||
|
{{ sscopeInner.row[ssub.prop] | commonFilter(ssub.filter) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</template>
|
||||||
|
<template slot-scope="scopeInner">
|
||||||
|
<component
|
||||||
|
:is="sub.subcomponent"
|
||||||
|
v-if="sub.subcomponent"
|
||||||
|
:key="scopeInner.row.id"
|
||||||
|
:inject-data="{ ...scopeInner.row, ...sub }"
|
||||||
|
@emitData="emitData" />
|
||||||
|
<span v-else>
|
||||||
|
{{ scopeInner.row[sub.prop] | commonFilter(sub.filter) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</template>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<component
|
||||||
|
:is="item.subcomponent"
|
||||||
|
v-if="item.subcomponent"
|
||||||
|
:key="scope.row.id"
|
||||||
|
:itemProp="item.prop"
|
||||||
|
:inject-data="{ ...scope.row, ...item }"
|
||||||
|
@emitData="emitData" />
|
||||||
|
<span v-else>
|
||||||
|
{{ scope.row[item.prop] | commonFilter(item.filter) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<slot name="handleBtn" />
|
||||||
|
</el-table>
|
||||||
|
<!-- 表格底部加号 -->
|
||||||
|
<el-button
|
||||||
|
v-if="addButtonShow"
|
||||||
|
class="addButton"
|
||||||
|
icon="el-icon-plus"
|
||||||
|
@click="emitButtonClick">
|
||||||
|
{{ addButtonShow }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'BaseTable',
|
||||||
|
filters: {
|
||||||
|
commonFilter: (source, filterType = (a) => a) => {
|
||||||
|
return filterType(source);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
cancelBorder: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
cancelPageFixed: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
tableData: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
default: () => {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tableProps: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
page: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
pageWidth: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: 70,
|
||||||
|
},
|
||||||
|
limit: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
selectWidth: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
addButtonShow: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectedBox: new Array(100).fill(true),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
renderTableHeadList() {
|
||||||
|
return this.tableProps.filter((item, index) => {
|
||||||
|
return this.selectedBox[index];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
renderData() {
|
||||||
|
return this.tableData.map((item, index) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
_pageIndex: (this.page - 1) * this.limit + index + 1,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
beforeMount() {
|
||||||
|
this.selectedBox = new Array(100).fill(true);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
currentChange(newVal, oldVal) {
|
||||||
|
this.$emit('current-change', { newVal, oldVal });
|
||||||
|
},
|
||||||
|
handleSelectionChange(val) {
|
||||||
|
this.$emit('selection-change', val);
|
||||||
|
},
|
||||||
|
emitData(val) {
|
||||||
|
this.$emit('emitFun', val);
|
||||||
|
},
|
||||||
|
emitButtonClick() {
|
||||||
|
this.$emit('emitButtonClick');
|
||||||
|
},
|
||||||
|
setCurrent(name, index) {
|
||||||
|
let _this = this;
|
||||||
|
let obj = _this.$refs[name].data[index];
|
||||||
|
_this.$refs[name].setCurrentRow(obj);
|
||||||
|
},
|
||||||
|
doLayout(name) {
|
||||||
|
this.$refs[name].doLayout();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<!-- <style scoped>
|
||||||
|
.baseTable .show-col-btn {
|
||||||
|
margin-right: 5px;
|
||||||
|
line-height: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.baseTable .el-icon-refresh {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.baseTable >>> .el-table .el-table__cell {
|
||||||
|
padding: 0;
|
||||||
|
height: 35px;
|
||||||
|
border: 1px solid rgb(220, 220, 220);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
.baseTable .el-table__body tr.current-row > td.el-table__cell {
|
||||||
|
background-color: #eaf1fc;
|
||||||
|
}
|
||||||
|
.baseTable .el-table .el-table__cell {
|
||||||
|
padding: 0;
|
||||||
|
height: 35px;
|
||||||
|
}
|
||||||
|
.baseTable .addButton {
|
||||||
|
width: 100%;
|
||||||
|
height: 35px;
|
||||||
|
border-top: none;
|
||||||
|
color: #0b58ff;
|
||||||
|
border-color: #ebeef5;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.baseTable .addButton:hover {
|
||||||
|
color: #0b58ff;
|
||||||
|
border-color: #ebeef5;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
.baseTable .addButton:focus {
|
||||||
|
border-color: #ebeef5;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tooltip__popper.is-dark {
|
||||||
|
background: rgba(0, 0, 0, 0.6) !important;
|
||||||
|
}
|
||||||
|
.el-tooltip__popper .popper__arrow,
|
||||||
|
.el-tooltip__popper .popper__arrow::after {
|
||||||
|
border-top-color: rgba(0, 0, 0, 0.4) !important;
|
||||||
|
}
|
||||||
|
</style> -->
|
||||||
331
src/views/core/monitoring/groupReport/gr-detail.vue
Normal file
331
src/views/core/monitoring/groupReport/gr-detail.vue
Normal file
@@ -0,0 +1,331 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: zwq
|
||||||
|
* @Date: 2023-08-24 14:47:58
|
||||||
|
* @LastEditors: zwq
|
||||||
|
* @LastEditTime: 2025-02-25 14:03:40
|
||||||
|
* @Description:
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||||
|
<el-table id="detail" :data="tableData" :header-cell-style="{
|
||||||
|
background: '#F2F4F9',
|
||||||
|
color: '#606266',
|
||||||
|
}" border v-loading="dataListLoading" style="width: 100%" ref="dataList">
|
||||||
|
<el-table-column prop="lineName" label="产线" align="center" />
|
||||||
|
<!-- <el-table-column prop="sizes" width="105" showOverflowtooltip align="center" label="规格" /> -->
|
||||||
|
<!-- <el-table-column prop="process" label="产品工艺" align="center" /> -->
|
||||||
|
<el-table-column prop="inputN" label="磨边" align="center">
|
||||||
|
<el-table-column prop="edgeNum" label="投入数量/片" />
|
||||||
|
<el-table-column prop="edgeTime" label="数据上报时间">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
scope.row.reportType === 0
|
||||||
|
? parseTime(scope.row.edgeTime)
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="outputN" label="打孔/丝印" align="center">
|
||||||
|
<el-table-column prop="drillCoating" label="投入数量">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
(scope.row.drillNum ?? '-')
|
||||||
|
+ '/'
|
||||||
|
+ (scope.row.coatingNum ?? '-')
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="coatingTime" label="数据上报时间">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
scope.row.reportType === 0
|
||||||
|
? parseTime(scope.row.coatingTime)
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="lossN" label="镀膜" align="center">
|
||||||
|
<el-table-column prop="silkNum" label="投入数量" />
|
||||||
|
<el-table-column prop="silkTime" label="数据上报时间">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
scope.row.reportType === 0
|
||||||
|
? parseTime(scope.row.silkTime)
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="lossN" label="钢化" align="center">
|
||||||
|
<el-table-column prop="temperingNum" label="投入数量" />
|
||||||
|
<el-table-column prop="temperingTime" label="数据上报时间">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
scope.row.reportType === 0
|
||||||
|
? parseTime(scope.row.temperingTime)
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="lossN" label="包装" align="center">
|
||||||
|
<el-table-column prop="packingNum" label="投入数量" />
|
||||||
|
<el-table-column prop="packingTime" label="数据上报时间">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
scope.row.reportType === 0
|
||||||
|
? parseTime(scope.row.packingTime)
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table-column>
|
||||||
|
<!-- <el-table-column prop="lossRatio" label="不良率/%">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
scope.row.lossRatio != null ? scope.row.lossRatio.toFixed(2) : '-'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="outputRatio" label="投入产出率/%">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
scope.row.outputRatio != null
|
||||||
|
? scope.row.outputRatio.toFixed(2)
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="processingRatio" label="加工成品率/%">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
scope.row.processingRatio != null
|
||||||
|
? scope.row.processingRatio.toFixed(2)
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="lossD" label="不良详情" align="center">
|
||||||
|
<el-table-column prop="original" label="原片" align="center">
|
||||||
|
<el-table-column prop="originalLossNum" label="原片不良/片" />
|
||||||
|
<el-table-column prop="originalLossArea" label="原片不良/m²">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
scope.row.originalLossArea != null
|
||||||
|
? scope.row.originalLossArea.toFixed(2)
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="edge" label="磨边" align="center">
|
||||||
|
<el-table-column prop="edgeLossNum" label="磨边不良/片" />
|
||||||
|
<el-table-column prop="edgeLossArea" label="磨边不良/m²">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
scope.row.edgeLossArea != null
|
||||||
|
? scope.row.edgeLossArea.toFixed(2)
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="drill" label="打孔" align="center">
|
||||||
|
<el-table-column prop="drillLossNum" label="打孔不良/片" />
|
||||||
|
<el-table-column prop="drillLossArea" label="打孔不良/m²">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
scope.row.drillLossArea != null
|
||||||
|
? scope.row.drillLossArea.toFixed(2)
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="coating" label="镀膜" align="center">
|
||||||
|
<el-table-column prop="coatingLossNum" label="镀膜不良/片" />
|
||||||
|
<el-table-column prop="coatingLossArea" label="镀膜不良/m²">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
scope.row.coatingLossArea != null
|
||||||
|
? scope.row.coatingLossArea.toFixed(2)
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="silk" label="丝印" align="center">
|
||||||
|
<el-table-column prop="silkLossNum" label="丝印不良/片" />
|
||||||
|
<el-table-column prop="silkLossArea" label="丝印不良/m²">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
scope.row.silkLossArea != null
|
||||||
|
? scope.row.silkLossArea.toFixed(2)
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table-column>
|
||||||
|
<el-table-column prop="tempering" label="钢化" align="center">
|
||||||
|
<el-table-column prop="temperingLossNum" label="钢化不良/片" />
|
||||||
|
<el-table-column prop="temperingLossArea" label="钢化不良/m²">
|
||||||
|
<template v-slot="scope">
|
||||||
|
<span>
|
||||||
|
{{
|
||||||
|
scope.row.temperingLossArea != null
|
||||||
|
? scope.row.temperingLossArea.toFixed(2)
|
||||||
|
: '-'
|
||||||
|
}}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table-column> -->
|
||||||
|
<el-table-column prop="down" label="下片" align="center">
|
||||||
|
<el-table-column prop="downNum" label="成品数量" />
|
||||||
|
<el-table-column prop="scrapNum" label="废片数量" />
|
||||||
|
<el-table-column prop="inputOutputRate" label="投入产出率" />
|
||||||
|
<el-table-column prop="yieldRate" label="加工成品率" />
|
||||||
|
</el-table-column>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getTeamReportPageDet, exportGroupProductReportExcel } from '@/api/core/monitoring/auto';
|
||||||
|
import * as XLSX from 'xlsx';
|
||||||
|
import FileSaver from 'file-saver';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tableData: [],
|
||||||
|
id:null,
|
||||||
|
dataListLoading: false,
|
||||||
|
formConfig: [
|
||||||
|
{
|
||||||
|
// type: this.$auth.hasPermi('base:factory:export') ? 'button' : '',
|
||||||
|
type: 'button',
|
||||||
|
btnName: '导出',
|
||||||
|
name: 'export',
|
||||||
|
color: 'warning',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
components: {},
|
||||||
|
created() {},
|
||||||
|
mounted() {},
|
||||||
|
methods: {
|
||||||
|
// 获取数据列表
|
||||||
|
init(id) {
|
||||||
|
this.id = id
|
||||||
|
this.dataListLoading = true;
|
||||||
|
getTeamReportPageDet(id).then((response) => {
|
||||||
|
this.tableData = response.data?.map((item, index) => {
|
||||||
|
item.originalLossNum = item.original?.lossNum;
|
||||||
|
item.originalLossArea = item.original?.lossArea;
|
||||||
|
item.edgeLossNum = item.edge?.lossNum;
|
||||||
|
item.edgeLossArea = item.edge?.lossArea;
|
||||||
|
item.drillLossNum = item.drill?.lossNum;
|
||||||
|
item.drillLossArea = item.drill?.lossArea;
|
||||||
|
item.coatingLossNum = item.coating?.lossNum;
|
||||||
|
item.coatingLossArea = item.coating?.lossArea;
|
||||||
|
item.silkLossNum = item.silk?.lossNum;
|
||||||
|
item.silkLossArea = item.silk?.lossArea;
|
||||||
|
item.temperingLossNum = item.tempering?.lossNum;
|
||||||
|
item.temperingLossArea = item.tempering?.lossArea;
|
||||||
|
item.packingLossNum = item.packing?.lossNum;
|
||||||
|
item.packingLossArea = item.packing?.lossArea;
|
||||||
|
if (item.isSummaryReport) {
|
||||||
|
item.lineName = '合计';
|
||||||
|
}
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
this.dataListLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// arraySpanMethod({ row, column, rowIndex, columnIndex }) {
|
||||||
|
// if (row.isSummaryReport) {
|
||||||
|
// if (columnIndex === 0) {
|
||||||
|
// return [1, 3];
|
||||||
|
// } else if (columnIndex === 1) {
|
||||||
|
// return [0, 0];
|
||||||
|
// } else if (columnIndex === 2) {
|
||||||
|
// return [0, 0];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
|
||||||
|
buttonClick(val) {
|
||||||
|
switch (val.btnName) {
|
||||||
|
case 'export':
|
||||||
|
this.handleExport();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log(val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleExport() {
|
||||||
|
this.$modal.confirm('是否确认导出').then(() => {
|
||||||
|
return exportGroupProductReportExcel({id:this.id});
|
||||||
|
}).then(response => {
|
||||||
|
console.log(response)
|
||||||
|
this.$download.excel(response, '班组生产报表-详情.xls');
|
||||||
|
}).catch(() => {})
|
||||||
|
// let tables = document.querySelector('#detail').cloneNode(true);
|
||||||
|
// let exportTable = XLSX.utils.table_to_book(tables);
|
||||||
|
|
||||||
|
// var exportTableOut = XLSX.write(exportTable, {
|
||||||
|
// bookType: 'xlsx',
|
||||||
|
// bookSST: true,
|
||||||
|
// type: 'array',
|
||||||
|
// });
|
||||||
|
// // sheetjs.xlsx为导出表格的标题名称
|
||||||
|
// try {
|
||||||
|
// FileSaver.saveAs(
|
||||||
|
// new Blob([exportTableOut], {
|
||||||
|
// type: 'application/octet-stream',
|
||||||
|
// }),
|
||||||
|
// '班组生产报表-详情.xlsx'
|
||||||
|
// );
|
||||||
|
// } catch (e) {
|
||||||
|
// if (typeof console !== 'undefined') console.log(e, exportTableOut);
|
||||||
|
// }
|
||||||
|
// return exportTableOut;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
594
src/views/core/monitoring/groupReport/index.vue
Normal file
594
src/views/core/monitoring/groupReport/index.vue
Normal file
@@ -0,0 +1,594 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: Do not edit
|
||||||
|
* @Date: 2023-08-29 14:59:29
|
||||||
|
* @LastEditTime: 2025-02-25 14:26:04
|
||||||
|
* @LastEditors: zwq
|
||||||
|
* @Description:
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<search-bar
|
||||||
|
:formConfigs="formConfig"
|
||||||
|
ref="searchBarForm"
|
||||||
|
@headBtnClick="buttonClick" />
|
||||||
|
<base-table-s
|
||||||
|
v-if="showData.length"
|
||||||
|
class="right-aside"
|
||||||
|
v-loading="dataListLoading"
|
||||||
|
:table-props="tableProps"
|
||||||
|
:page="listQuery.pageNo"
|
||||||
|
:limit="listQuery.pageSize"
|
||||||
|
:table-data="showData">
|
||||||
|
<method-btn
|
||||||
|
v-if="showData.length"
|
||||||
|
slot="handleBtn"
|
||||||
|
:width="80"
|
||||||
|
label="操作"
|
||||||
|
:method-list="tableBtn"
|
||||||
|
@clickBtn="handleClick" />
|
||||||
|
</base-table-s>
|
||||||
|
<div v-else class="no-data-bg"></div>
|
||||||
|
<pagination
|
||||||
|
:limit.sync="listQuery.pageSize"
|
||||||
|
:page.sync="listQuery.pageNo"
|
||||||
|
:total="listQuery.total"
|
||||||
|
@pagination="getDataList" />
|
||||||
|
<base-dialog
|
||||||
|
:dialogTitle="addOrEditTitle"
|
||||||
|
:dialogVisible="addOrUpdateVisible"
|
||||||
|
@cancel="handleCancel"
|
||||||
|
@confirm="handleConfirm"
|
||||||
|
:before-close="handleCancel"
|
||||||
|
close-on-click-modal
|
||||||
|
top="0"
|
||||||
|
width="80%">
|
||||||
|
<gr-detail ref="grDetail" />
|
||||||
|
<slot name="footer">
|
||||||
|
<el-row slot="footer" type="flex" justify="end">
|
||||||
|
<el-col :span="24">
|
||||||
|
<el-button size="small" class="btnTextStyle" @click="handleCancel">
|
||||||
|
取消
|
||||||
|
</el-button>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</slot>
|
||||||
|
</base-dialog>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import grDetail from './gr-detail';
|
||||||
|
import { getTeamReportPage } from '@/api/core/monitoring/auto';
|
||||||
|
import { getFactoryPage } from '@/api/core/base/factory';
|
||||||
|
import { getGroupTeamPage } from '@/api/base/groupTeam';
|
||||||
|
// import codeFilter from '../../mixins/code-filter'
|
||||||
|
import * as XLSX from 'xlsx';
|
||||||
|
import FileSaver from 'file-saver';
|
||||||
|
import baseTableS from './baseTable.vue';
|
||||||
|
import { parseTime } from '@/filter/code-filter';
|
||||||
|
|
||||||
|
const tableProps = [
|
||||||
|
{
|
||||||
|
prop: 'reportType',
|
||||||
|
label: '报表类型',
|
||||||
|
fixed: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'reportDate',
|
||||||
|
label: '日期',
|
||||||
|
width: 180,
|
||||||
|
fixed: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'factoryName',
|
||||||
|
label: '工厂',
|
||||||
|
fixed: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'teamName',
|
||||||
|
label: '班组',
|
||||||
|
fixed: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'edgeNum',
|
||||||
|
label: '磨边',
|
||||||
|
fixed: true
|
||||||
|
}, {
|
||||||
|
prop: 'drillOrCoating',
|
||||||
|
label: '打孔/丝印',
|
||||||
|
fixed: true
|
||||||
|
}, {
|
||||||
|
prop: 'silkNum',
|
||||||
|
label: '镀膜',
|
||||||
|
fixed: true
|
||||||
|
}, {
|
||||||
|
prop: 'temperingNum',
|
||||||
|
label: '钢化',
|
||||||
|
fixed: true
|
||||||
|
}, {
|
||||||
|
prop: 'packingNum',
|
||||||
|
label: '包装',
|
||||||
|
fixed: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'inputN',
|
||||||
|
label: '下片',
|
||||||
|
align: 'center',
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
prop: 'downNum',
|
||||||
|
label: '成品数量',
|
||||||
|
width:100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'scrapNum',
|
||||||
|
label: '废片数量',
|
||||||
|
width:100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'inputOutputRate',
|
||||||
|
label: '投入产出率',
|
||||||
|
width: 100
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'yieldRate',
|
||||||
|
label: '加工成品率',
|
||||||
|
width: 100
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// prop: 'outputN',
|
||||||
|
// label: '产出',
|
||||||
|
// align: 'center',
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// prop: 'outputNum',
|
||||||
|
// label: '产出数量/片',
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'outputArea',
|
||||||
|
// label: '产出面积/㎡',
|
||||||
|
// filter: (val) => (val != null ? val.toFixed(2) : '-'),
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'lossN',
|
||||||
|
// label: '不良',
|
||||||
|
// align: 'center',
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// prop: 'lossNum',
|
||||||
|
// label: '不良数量/片',
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'lossArea',
|
||||||
|
// label: '不良面积/㎡',
|
||||||
|
// filter: (val) => (val != null ? val.toFixed(2) : '-'),
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'lossRatio',
|
||||||
|
// label: '不良率/%',
|
||||||
|
// filter: (val) => (val != null ? val.toFixed(2) : '-'),
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'outputRatio',
|
||||||
|
// label: '投入产出率/%',
|
||||||
|
// filter: (val) => (val != null ? val.toFixed(2) : '-'),
|
||||||
|
// width:110
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'processingRatio',
|
||||||
|
// label: '加工成品率/%',
|
||||||
|
// filter: (val) => (val != null ? val.toFixed(2) : '-'),
|
||||||
|
// width:110
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'lossD',
|
||||||
|
// label: '不良详情',
|
||||||
|
// align: 'center',
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// prop: 'original',
|
||||||
|
// label: '原片',
|
||||||
|
// align: 'center',
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// prop: 'originalLossNum',
|
||||||
|
// label: '原片不良/片',
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'originalLossArea',
|
||||||
|
// label: '原片不良/㎡',
|
||||||
|
// filter: (val) => (val != null ? val.toFixed(2) : '-'),
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'edge',
|
||||||
|
// label: '磨边',
|
||||||
|
// align: 'center',
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// prop: 'edgeLossNum',
|
||||||
|
// label: '磨边不良/片',
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'edgeLossArea',
|
||||||
|
// label: '磨边不良/㎡',
|
||||||
|
// filter: (val) => (val != null ? val.toFixed(2) : '-'),
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'drill',
|
||||||
|
// label: '打孔',
|
||||||
|
// align: 'center',
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// prop: 'drillLossNum',
|
||||||
|
// label: '打孔不良/片',
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'drillLossArea',
|
||||||
|
// label: '打孔不良/㎡',
|
||||||
|
// filter: (val) => (val != null ? val.toFixed(2) : '-'),
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'coating',
|
||||||
|
// label: '镀膜',
|
||||||
|
// align: 'center',
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// prop: 'coatingLossNum',
|
||||||
|
// label: '镀膜不良/片',
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'coatingLossArea',
|
||||||
|
// label: '镀膜不良/㎡',
|
||||||
|
// filter: (val) => (val != null ? val.toFixed(2) : '-'),
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'silk',
|
||||||
|
// label: '丝印',
|
||||||
|
// align: 'center',
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// prop: 'silkLossNum',
|
||||||
|
// label: '丝印不良/片',
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'silkLossArea',
|
||||||
|
// label: '丝印不良/㎡',
|
||||||
|
// filter: (val) => (val != null ? val.toFixed(2) : '-'),
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'tempering',
|
||||||
|
// label: '钢化',
|
||||||
|
// align: 'center',
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// prop: 'temperingLossNum',
|
||||||
|
// label: '钢化不良/片',
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'temperingLossArea',
|
||||||
|
// label: '钢化不良/㎡',
|
||||||
|
// filter: (val) => (val != null ? val.toFixed(2) : '-'),
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'packing',
|
||||||
|
// label: '包装',
|
||||||
|
// align: 'center',
|
||||||
|
// children: [
|
||||||
|
// {
|
||||||
|
// prop: 'packingLossNum',
|
||||||
|
// label: '包装不良/片',
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// prop: 'packingLossArea',
|
||||||
|
// label: '包装不良/㎡',
|
||||||
|
// filter: (val) => (val != null ? val.toFixed(2) : '-'),
|
||||||
|
// width:100
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// },
|
||||||
|
];
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
baseTableS,
|
||||||
|
grDetail,
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
urlOptions: {
|
||||||
|
getDataListURL: getTeamReportPage,
|
||||||
|
},
|
||||||
|
listQuery: {
|
||||||
|
reportType: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
pageNo: 1,
|
||||||
|
startTime: undefined,
|
||||||
|
endTime: undefined,
|
||||||
|
total: 1,
|
||||||
|
},
|
||||||
|
fileName: '',
|
||||||
|
dataListLoading: false,
|
||||||
|
tableProps,
|
||||||
|
tableBtn: [
|
||||||
|
this.$auth.hasPermi(`monitoring:group-off:update`)
|
||||||
|
? {
|
||||||
|
type: 'eq',
|
||||||
|
btnName: '详情',
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
|
||||||
|
].filter((v) => v),
|
||||||
|
showData: [],
|
||||||
|
tableData: [],
|
||||||
|
formConfig: [
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '工厂',
|
||||||
|
selectOptions: [],
|
||||||
|
param: 'factoryId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '班组',
|
||||||
|
selectOptions: [],
|
||||||
|
param: 'teamId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '报表类型',
|
||||||
|
selectOptions: [
|
||||||
|
{
|
||||||
|
id: 0,
|
||||||
|
name: '班',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
name: '日',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// id: 2,
|
||||||
|
// name: '周',
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
name: '月',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
name: '年',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
defaultSelect: 1,
|
||||||
|
param: 'reportType',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'datePicker',
|
||||||
|
label: '时间范围',
|
||||||
|
dateType: 'daterange',
|
||||||
|
format: 'yyyy-MM-dd',
|
||||||
|
valueFormat: 'timestamp',
|
||||||
|
rangeSeparator: '-',
|
||||||
|
startPlaceholder: '开始时间',
|
||||||
|
endPlaceholder: '结束时间',
|
||||||
|
param: 'timeVal',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: this.$auth.hasPermi('monitoring:group-off:query') ? 'button' : '',
|
||||||
|
|
||||||
|
btnName: '查询',
|
||||||
|
name: 'search',
|
||||||
|
color: 'primary',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: this.$auth.hasPermi('monitoring:group-off:export') ? 'button' : '',
|
||||||
|
// type: 'button',
|
||||||
|
btnName: '导出',
|
||||||
|
name: 'export',
|
||||||
|
color: 'warning',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
addOrEditTitle: '',
|
||||||
|
addOrUpdateVisible: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
// 获取当前时间
|
||||||
|
const now = new Date();
|
||||||
|
// 获取前一天的同一时间
|
||||||
|
const yesterday = new Date(now.getTime() - 24 * 60 * 60 * 1000);
|
||||||
|
// 设置为00:00:00
|
||||||
|
yesterday.setHours(0, 0, 0, 0);
|
||||||
|
// 设置为23:59:59
|
||||||
|
const end = new Date(yesterday.getTime());
|
||||||
|
end.setHours(23, 59, 59, 59);
|
||||||
|
this.listQuery.startTime = yesterday.getTime(), [end.getTime()];
|
||||||
|
this.listQuery.endTime = end.getTime()
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.searchBarForm.formInline.timeVal = [yesterday.getTime(),end.getTime()];
|
||||||
|
});
|
||||||
|
this.getDataList();
|
||||||
|
this.getPdLineList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleExport() {
|
||||||
|
let tables = document.querySelector('.el-table').cloneNode(true);
|
||||||
|
const fix = tables.querySelector('.el-table__fixed');
|
||||||
|
const fixRight = tables.querySelector('.el-table__fixed-right');
|
||||||
|
if (fix) {
|
||||||
|
tables.removeChild(tables.querySelector('.el-table__fixed'));
|
||||||
|
}
|
||||||
|
if (fixRight) {
|
||||||
|
tables.removeChild(tables.querySelector('.el-table__fixed-right'));
|
||||||
|
}
|
||||||
|
let exportTable = XLSX.utils.table_to_book(tables);
|
||||||
|
exportTable.Sheets.Sheet1.A1.v = '序号' //导出表格第一列表头为序号
|
||||||
|
|
||||||
|
var exportTableOut = XLSX.write(exportTable, {
|
||||||
|
bookType: 'xlsx',
|
||||||
|
bookSST: true,
|
||||||
|
type: 'array',
|
||||||
|
});
|
||||||
|
// sheetjs.xlsx为导出表格的标题名称
|
||||||
|
try {
|
||||||
|
FileSaver.saveAs(
|
||||||
|
new Blob([exportTableOut], {
|
||||||
|
type: 'application/octet-stream',
|
||||||
|
}),
|
||||||
|
this.fileName + '班组生产报表.xlsx'
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
if (typeof console !== 'undefined') console.log(e, exportTableOut);
|
||||||
|
}
|
||||||
|
return exportTableOut;
|
||||||
|
},
|
||||||
|
getPdLineList() {
|
||||||
|
const params = {
|
||||||
|
pageSize: 100,
|
||||||
|
pageNo: 1,
|
||||||
|
};
|
||||||
|
getGroupTeamPage(params).then((res) => {
|
||||||
|
this.formConfig[1].selectOptions = res.data.list || [];
|
||||||
|
});
|
||||||
|
getFactoryPage(params).then((res) => {
|
||||||
|
this.formConfig[0].selectOptions = res.data.list || [];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
buttonClick(val) {
|
||||||
|
switch (val.btnName) {
|
||||||
|
case 'search':
|
||||||
|
this.listQuery.pageNo = 1;
|
||||||
|
this.listQuery.pageSize = 10;
|
||||||
|
this.listQuery.factoryId = val.factoryId || undefined;
|
||||||
|
this.listQuery.teamId = val.teamId || undefined;
|
||||||
|
this.listQuery.reportType = val.reportType || undefined;
|
||||||
|
this.listQuery.startTime = val.timeVal
|
||||||
|
? val.timeVal[0]
|
||||||
|
: undefined;
|
||||||
|
this.listQuery.endTime = val.timeVal
|
||||||
|
? val.timeVal[1]
|
||||||
|
: undefined;
|
||||||
|
this.getDataList();
|
||||||
|
break;
|
||||||
|
case 'export':
|
||||||
|
this.handleExport();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log(val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 获取数据列表
|
||||||
|
getDataList() {
|
||||||
|
this.dataListLoading = true;
|
||||||
|
console.log(this.listQuery);
|
||||||
|
|
||||||
|
const arr = ['班', '日', '', '月', '年']; // 索引0对应班,1对应日,3对应月,4对应年,索引2留空
|
||||||
|
this.urlOptions.getDataListURL(this.listQuery).then((response) => {
|
||||||
|
if (!response.data.list) {
|
||||||
|
this.showData = [];
|
||||||
|
this.dataListLoading = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
this.tableData = response.data?.list.map((item, index) => {
|
||||||
|
item.reportType = arr[item.reportType] || item.reportType;
|
||||||
|
item.drillOrCoating = item.drillNum + "/" + item.coatingNum
|
||||||
|
item.originalLossNum = item.original?.lossNum;
|
||||||
|
item.originalLossArea = item.original?.lossArea;
|
||||||
|
item.edgeLossNum = item.edge?.lossNum;
|
||||||
|
item.edgeLossArea = item.edge?.lossArea;
|
||||||
|
item.drillLossNum = item.drill?.lossNum;
|
||||||
|
item.drillLossArea = item.drill?.lossArea;
|
||||||
|
item.coatingLossNum = item.coating?.lossNum;
|
||||||
|
item.coatingLossArea = item.coating?.lossArea;
|
||||||
|
item.silkLossNum = item.silk?.lossNum;
|
||||||
|
item.silkLossArea = item.silk?.lossArea;
|
||||||
|
item.temperingLossNum = item.tempering?.lossNum;
|
||||||
|
item.temperingLossArea = item.tempering?.lossArea;
|
||||||
|
item.packingLossNum = item.packing?.lossNum;
|
||||||
|
item.packingLossArea = item.packing?.lossArea;
|
||||||
|
return item;
|
||||||
|
});
|
||||||
|
this.listQuery.total = response.data?.total;
|
||||||
|
this.dataListLoading = false;
|
||||||
|
this.showData = this.tableData;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleClick(val) {
|
||||||
|
this.addOrUpdateVisible = true;
|
||||||
|
const time = val.data.timeVal ? parseTime(val.data.timeVal[0]) + '-' + parseTime(val.data.timeVal[1]) : '- '
|
||||||
|
const teamName = val.data.teamName?val.data.teamName:'- '
|
||||||
|
const teamLeader = val.data.teamLeader?val.data.teamLeader:'- '
|
||||||
|
this.addOrEditTitle =
|
||||||
|
'时间:' +
|
||||||
|
time +
|
||||||
|
' 班组:' +
|
||||||
|
teamName +
|
||||||
|
' 组长:' +
|
||||||
|
teamLeader +
|
||||||
|
' 详情';
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.grDetail.init(val.data.id);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleCancel() {
|
||||||
|
this.addOrUpdateVisible = false;
|
||||||
|
this.addOrEditTitle = '';
|
||||||
|
},
|
||||||
|
handleConfirm() {
|
||||||
|
this.handleCancel();
|
||||||
|
},
|
||||||
|
// 每页数
|
||||||
|
sizeChangeHandle(val) {
|
||||||
|
this.listQuery.pageSize = val;
|
||||||
|
this.listQuery.pageNo = 1;
|
||||||
|
this.getDataList();
|
||||||
|
},
|
||||||
|
// 当前页
|
||||||
|
currentChangeHandle(val) {
|
||||||
|
this.listQuery.pageNo = val;
|
||||||
|
this.getDataList();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
280
src/views/core/monitoring/lineAuto/BarChart.vue
Normal file
280
src/views/core/monitoring/lineAuto/BarChart.vue
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="className" :style="{ height: height, width: width, marginLeft: '10px' }" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
require('echarts/theme/macarons'); // 引入主题
|
||||||
|
import resize from '@/utils/chartMixins/resize';
|
||||||
|
|
||||||
|
const animationDuration = 1000;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [resize], // 混入 resize 逻辑(自适应窗口)
|
||||||
|
props: {
|
||||||
|
className: {
|
||||||
|
type: String,
|
||||||
|
default: 'chart',
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: String,
|
||||||
|
default: '100%',
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: String,
|
||||||
|
default: '300px',
|
||||||
|
},
|
||||||
|
barData: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
chart: null, // 图表实例
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
// 监听 barData 变化(深度监听数组内部元素)
|
||||||
|
barData: {
|
||||||
|
deep: true,
|
||||||
|
handler: 'handleBarDataChange', // 调用处理方法
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// 组件挂载后初始化图表(确保 DOM 已就绪)
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.initChart();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
// 组件销毁前清理图表实例
|
||||||
|
if (this.chart) {
|
||||||
|
this.chart.dispose();
|
||||||
|
this.chart = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// barData 变化时的处理方法
|
||||||
|
handleBarDataChange() {
|
||||||
|
// 确保 DOM 存在再更新图表
|
||||||
|
this.$nextTick(() => {
|
||||||
|
// 如果图表未初始化,先初始化;否则直接更新数据
|
||||||
|
if (!this.chart) {
|
||||||
|
this.initChart();
|
||||||
|
} else {
|
||||||
|
this.updateChart();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 初始化图表
|
||||||
|
initChart() {
|
||||||
|
// 避免重复初始化(先销毁旧实例)
|
||||||
|
if (this.chart) {
|
||||||
|
this.chart.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保 DOM 元素存在
|
||||||
|
if (!this.$el) {
|
||||||
|
console.error('图表容器 DOM 元素不存在');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化图表实例
|
||||||
|
this.chart = echarts.init(this.$el, 'macarons');
|
||||||
|
// 设置图表配置
|
||||||
|
this.setChartOption();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新图表数据(复用配置逻辑)
|
||||||
|
updateChart() {
|
||||||
|
if (!this.chart) return;
|
||||||
|
this.setChartOption();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 图表配置项(抽离为单独方法,方便初始化和更新复用)
|
||||||
|
setChartOption() {
|
||||||
|
const dataValues = this.barData.flatMap(item => [item.inputNum || 0, item.outputNum || 0]);
|
||||||
|
const maxData = Math.max(...dataValues, 0); // 加 0 确保无数据时 maxData 为 0
|
||||||
|
|
||||||
|
// 2. 计算 Y 轴最大值(留 10% 余量,避免数据顶到顶部)
|
||||||
|
let yMax = 0;
|
||||||
|
if (maxData > 0) {
|
||||||
|
yMax = Math.ceil(maxData * 1.1); // 向上取整,确保刻度为整数
|
||||||
|
} else {
|
||||||
|
yMax = 100; // 无数据时默认最大值为 100,避免 Y 轴消失
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 计算 interval(5 个刻度对应 4 个间隔,向上取整确保间隔为整数)
|
||||||
|
const yInterval = Math.ceil((yMax - 0) / 4); // min 固定为 0,直接减 0
|
||||||
|
|
||||||
|
this.chart.setOption({
|
||||||
|
title: {
|
||||||
|
text: this.title
|
||||||
|
? '{space|}{tip|}{space|}{value|' + this.title + '}'
|
||||||
|
: '',
|
||||||
|
textStyle: {
|
||||||
|
rich: {
|
||||||
|
tip: {
|
||||||
|
width: 6,
|
||||||
|
height: 6,
|
||||||
|
borderRadius: 50,
|
||||||
|
backgroundColor: '#288AFF',
|
||||||
|
},
|
||||||
|
space: {
|
||||||
|
width: 8,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: 'black',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
color: ['#288AFF', '#8EF0AB', '#FFDC94'],
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'cross',
|
||||||
|
crossStyle: {
|
||||||
|
color: '#999',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['投入', '产出', '加工成品率'],
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: 20,
|
||||||
|
right: 30,
|
||||||
|
top:40,
|
||||||
|
bottom: 10,
|
||||||
|
|
||||||
|
containLabel: true,
|
||||||
|
splitArea: {
|
||||||
|
show: false // 关键:关闭网格背景分区(去掉间隔色块)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: this.barData.map((item) => item.lineName),
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: 'rgba(0, 0, 0, 0.45)',
|
||||||
|
width: 1 // 轴线宽度(可选,默认 1,可按需调整)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 2. 控制 X 轴刻度线颜色(与轴线颜色保持一致,视觉统一)
|
||||||
|
axisTick: {
|
||||||
|
lineStyle: {
|
||||||
|
color: 'rgba(0, 0, 0, 0.45)', // 刻度线颜色,需与轴线颜色匹配
|
||||||
|
width: 1 // 刻度线宽度(可选)
|
||||||
|
},
|
||||||
|
alignWithLabel: true // 可选:让刻度线与文字对齐(避免文字偏移时刻度线错位)
|
||||||
|
},
|
||||||
|
// 3. 控制 X 轴文字颜色(如:深灰色 rgba(0, 0, 0, 0.45))
|
||||||
|
axisLabel: {
|
||||||
|
color: 'rgba(0, 0, 0, 0.45)6', // 文字颜色,可自定义
|
||||||
|
fontSize: 12, // 可选:调整文字大小(默认 12,按需修改)
|
||||||
|
// 可选:文字过长时换行/省略(避免文字重叠,按需开启)
|
||||||
|
formatter: (value) => {
|
||||||
|
// 示例:文字超过 6 个字符时换行(可根据需求调整字符数)
|
||||||
|
if (value.length > 6) {
|
||||||
|
return value.slice(0, 6) + '\n' + value.slice(6);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 原有配置(若需保留可解开注释)
|
||||||
|
// axisPointer: {
|
||||||
|
// type: 'shadow',
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
name: '投入/产出 片',
|
||||||
|
min: 0, // 最小值固定为 0
|
||||||
|
max: yMax,
|
||||||
|
interval: yInterval,
|
||||||
|
splitArea: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
formatter: '{value}',
|
||||||
|
color: 'rgba(0, 0, 0, 0.45)'
|
||||||
|
},
|
||||||
|
|
||||||
|
// 可选:修改 Y 轴名称颜色(与文字颜色保持一致)
|
||||||
|
nameTextStyle: {
|
||||||
|
color: 'rgba(0, 0, 0, 0.45)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
name: '加工成品率',
|
||||||
|
min: 0,
|
||||||
|
max: 100, // 成品率固定 0-100%
|
||||||
|
interval: 25, // 100 / 4 = 25,刚好 5 个刻度(0、25、50、75、100)
|
||||||
|
axisLabel: {
|
||||||
|
formatter: '{value} %',
|
||||||
|
color: 'rgba(0, 0, 0, 0.45)'
|
||||||
|
},
|
||||||
|
splitArea: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
// 可选:修改 Y 轴名称颜色
|
||||||
|
nameTextStyle: {
|
||||||
|
color: 'rgba(0, 0, 0, 0.45)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '投入',
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: '20',
|
||||||
|
data: this.barData.map((item) => item.inputNum),
|
||||||
|
tooltip: {
|
||||||
|
valueFormatter: (value) => `${value} 片`,
|
||||||
|
},
|
||||||
|
animationDuration,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '产出',
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: '20',
|
||||||
|
data: this.barData.map((item) => item.outputNum),
|
||||||
|
tooltip: {
|
||||||
|
valueFormatter: (value) => `${value} 片`,
|
||||||
|
},
|
||||||
|
animationDuration,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '加工成品率',
|
||||||
|
type: 'line',
|
||||||
|
yAxisIndex: 1,
|
||||||
|
tooltip: {
|
||||||
|
valueFormatter: (value) => `${value} %`,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'top',
|
||||||
|
distance: 6,
|
||||||
|
fontSize: 11,
|
||||||
|
color: '#333333',
|
||||||
|
formatter: (params) => `${params.value}` // 显示单位
|
||||||
|
},
|
||||||
|
data: this.barData.map((item) => item.processingRatio),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
File diff suppressed because it is too large
Load Diff
350
src/views/core/monitoring/nextClip/hisData.vue
Normal file
350
src/views/core/monitoring/nextClip/hisData.vue
Normal file
@@ -0,0 +1,350 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: Do not edit
|
||||||
|
* @Date: 2023-08-29 14:59:29
|
||||||
|
* @LastEditTime: 2024-12-02 13:44:47
|
||||||
|
* @LastEditors: zwq
|
||||||
|
* @Description:
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<!-- :isFold="true" 控制展开 -->
|
||||||
|
<search-bar
|
||||||
|
:formConfigs="formConfig"
|
||||||
|
ref="searchBarForm"
|
||||||
|
@headBtnClick="buttonClick" />
|
||||||
|
<base-table
|
||||||
|
v-if="showData.length"
|
||||||
|
class="right-aside"
|
||||||
|
v-loading="dataListLoading"
|
||||||
|
:table-props="tableProps"
|
||||||
|
:page="listQuery.pageNo"
|
||||||
|
:limit="listQuery.pageSize"
|
||||||
|
:table-data="showData"
|
||||||
|
>
|
||||||
|
<!-- <method-btn
|
||||||
|
v-if="tableBtn.length"
|
||||||
|
slot="handleBtn"
|
||||||
|
:width="120"
|
||||||
|
label="操作"
|
||||||
|
:method-list="tableBtn"
|
||||||
|
@clickBtn="handleClick" /> -->
|
||||||
|
</base-table>
|
||||||
|
<div v-else class="no-data-bg"></div>
|
||||||
|
<pagination
|
||||||
|
:limit.sync="listQuery.pageSize"
|
||||||
|
:page.sync="listQuery.pageNo"
|
||||||
|
:total="listQuery.total"
|
||||||
|
@pagination="getDataList" />
|
||||||
|
<!-- <el-dialog
|
||||||
|
title="提示"
|
||||||
|
:visible.sync="dialogVisible"
|
||||||
|
width="30%"
|
||||||
|
:before-close="handleClose">
|
||||||
|
<el-button type="primary" @click="exportXlsx">xlsx</el-button>
|
||||||
|
<el-button type="success" @click="exportPdf">pdf</el-button>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog> -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { parseTime } from '../../mixins/code-filter';
|
||||||
|
import { getDownLogHisData, getPdList, getThick } from '@/api/core/monitoring/index'
|
||||||
|
import * as XLSX from 'xlsx'
|
||||||
|
import FileSaver from 'file-saver'
|
||||||
|
import jsPDF from 'jspdf'
|
||||||
|
import html2canvas from 'html2canvas'
|
||||||
|
|
||||||
|
const tableProps = [
|
||||||
|
{
|
||||||
|
prop: 'productionLineName',
|
||||||
|
label: '产线'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'eqName',
|
||||||
|
label: '下片机械手编号'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'pos',
|
||||||
|
label: '工位编号'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'pallet',
|
||||||
|
label: '托数/托'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'palletNum',
|
||||||
|
label: '一托玻璃数量/片'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'startTime',
|
||||||
|
label: '开始时间',
|
||||||
|
filter: parseTime,
|
||||||
|
width: 160
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'endTime',
|
||||||
|
label: '结束时间',
|
||||||
|
filter: parseTime,
|
||||||
|
width: 160
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'length',
|
||||||
|
label: '玻璃长度/mm'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'width',
|
||||||
|
label: '玻璃宽度/mm',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'thick',
|
||||||
|
label: '玻璃长度/mm'
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
urlOptions: {
|
||||||
|
getDataListURL: getDownLogHisData
|
||||||
|
},
|
||||||
|
tableData: [],
|
||||||
|
listQuery: {
|
||||||
|
pageSize: 10,
|
||||||
|
pageNo: 1,
|
||||||
|
total: 1,
|
||||||
|
eqName: undefined,
|
||||||
|
productionLineId: undefined,
|
||||||
|
thick:undefined
|
||||||
|
},
|
||||||
|
exportLoading: false,
|
||||||
|
dataListLoading: false,
|
||||||
|
selectedList: [],
|
||||||
|
dialogVisible: false,
|
||||||
|
addOrEditTitle: '',
|
||||||
|
addOrUpdateVisible: false,
|
||||||
|
tableProps,
|
||||||
|
tableBtn: [
|
||||||
|
{
|
||||||
|
type: 'his',
|
||||||
|
btnName: '历史',
|
||||||
|
},
|
||||||
|
].filter((v) => v),
|
||||||
|
tableData: [],
|
||||||
|
showData: [],
|
||||||
|
fileName: '',
|
||||||
|
formConfig: [
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '产线',
|
||||||
|
selectOptions: [],
|
||||||
|
param: 'productionLineId'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '玻璃型号',
|
||||||
|
selectOptions: [],
|
||||||
|
param: 'thick'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'datePicker',
|
||||||
|
label: '统计开始时间',
|
||||||
|
dateType: 'daterange',
|
||||||
|
format: 'yyyy-MM-dd',
|
||||||
|
valueFormat: "yyyy-MM-dd HH:mm:ss",
|
||||||
|
rangeSeparator: '-',
|
||||||
|
startPlaceholder: '开始时间',
|
||||||
|
endPlaceholder: '结束时间',
|
||||||
|
param: 'timeVal',
|
||||||
|
defaultTime: ['00:00:00', '23:59:59'],
|
||||||
|
defaultSelect: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
btnName: '查询',
|
||||||
|
name: 'search',
|
||||||
|
color: 'primary',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// type: this.$auth.hasPermi('base:factory:export') ? 'button' : '',
|
||||||
|
type: 'button',
|
||||||
|
btnName: '导出',
|
||||||
|
name: 'export',
|
||||||
|
color: 'warning',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$refs.searchBarForm.formInline.productionLineId = this.$route.query.productionLineId
|
||||||
|
this.$refs.searchBarForm.formInline.thick = this.$route.query.thick
|
||||||
|
this.listQuery.productionLineId = this.$route.query.productionLineId
|
||||||
|
this.listQuery.thick = this.$route.query.thick
|
||||||
|
this.getDataList()
|
||||||
|
this.getPdLineList()
|
||||||
|
console.log('this.$route.query', this.$route.query);
|
||||||
|
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleClick(val) {
|
||||||
|
this.addOrUpdateVisible = true;
|
||||||
|
this.addOrEditTitle =
|
||||||
|
val.data?.factoryName + '-' + val.data?.lineName + ' 详情';
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.eqDetail.init(
|
||||||
|
val.data.lineId,
|
||||||
|
this.listQuery.startTime,
|
||||||
|
this.listQuery.endTime
|
||||||
|
);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
exportXlsx() {
|
||||||
|
if (!this.showData.length) {
|
||||||
|
this.$message.warning('暂无数据可导出');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.exportLoading = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 1. 处理导出数据(格式化时间字段)
|
||||||
|
const exportData = this.showData.map(item => {
|
||||||
|
const formatItem = { ...item };
|
||||||
|
// 格式化时间字段
|
||||||
|
if (formatItem.startTime) formatItem.startTime = parseTime(formatItem.startTime);
|
||||||
|
if (formatItem.endTime) formatItem.endTime = parseTime(formatItem.endTime);
|
||||||
|
return formatItem;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. 构建表头映射:{ prop: label },只保留表格配置中存在的列
|
||||||
|
const headerMap = {};
|
||||||
|
this.tableProps.forEach(col => {
|
||||||
|
if (col.prop && col.label) {
|
||||||
|
headerMap[col.prop] = col.label;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// 3. 转换数据:将prop键名替换为label,按tableProps顺序排列列
|
||||||
|
const formattedData = exportData.map(item => {
|
||||||
|
const newItem = {};
|
||||||
|
// 按表格配置顺序遍历列,确保Excel列顺序与表格一致
|
||||||
|
this.tableProps.forEach(col => {
|
||||||
|
const prop = col.prop;
|
||||||
|
const label = col.label;
|
||||||
|
if (prop && label) {
|
||||||
|
// 处理可能的undefined值,避免导出为空字符串
|
||||||
|
newItem[label] = item[prop] ?? '';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return newItem;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 4. 创建工作表(使用处理后的带label表头的数据)
|
||||||
|
const worksheet = XLSX.utils.json_to_sheet(formattedData);
|
||||||
|
|
||||||
|
// 5. 创建工作簿并添加工作表
|
||||||
|
const workbook = XLSX.utils.book_new();
|
||||||
|
XLSX.utils.book_append_sheet(workbook, worksheet, '下片日志数据');
|
||||||
|
|
||||||
|
// 6. 生成Excel文件
|
||||||
|
const excelBuffer = XLSX.write(workbook, {
|
||||||
|
bookType: 'xlsx',
|
||||||
|
type: 'array'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 7. 保存文件
|
||||||
|
const blob = new Blob([excelBuffer], {
|
||||||
|
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
|
||||||
|
});
|
||||||
|
|
||||||
|
// 8. 生成文件名(包含查询条件信息)
|
||||||
|
let fileName = '下片历史';
|
||||||
|
if (this.listQuery.productionLineId) {
|
||||||
|
const lineItem = this.formConfig[0].selectOptions.find(
|
||||||
|
item => item.id === this.listQuery.productionLineId
|
||||||
|
);
|
||||||
|
if (lineItem) fileName += lineItem.name + '_';
|
||||||
|
}
|
||||||
|
if (this.listQuery.thick) {
|
||||||
|
fileName += this.listQuery.thick + '_';
|
||||||
|
}
|
||||||
|
// 添加时间戳避免文件名重复
|
||||||
|
fileName += + '.xlsx';
|
||||||
|
|
||||||
|
FileSaver.saveAs(blob, fileName);
|
||||||
|
this.$message.success('导出成功');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('导出失败:', error);
|
||||||
|
this.$message.error('导出失败,请重试');
|
||||||
|
} finally {
|
||||||
|
this.exportLoading = false;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getPdLineList() {
|
||||||
|
getPdList().then((res) => {
|
||||||
|
this.formConfig[0].selectOptions = res.data || []
|
||||||
|
})
|
||||||
|
getThick().then((res) => {
|
||||||
|
this.formConfig[1].selectOptions = res.data.map((item) => {
|
||||||
|
return {
|
||||||
|
id: item.thick + 'mm',
|
||||||
|
name: item.thick + 'mm'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
selectChange(val) {
|
||||||
|
console.log(val)
|
||||||
|
this.selectedList = val
|
||||||
|
},
|
||||||
|
buttonClick(val) {
|
||||||
|
switch (val.btnName) {
|
||||||
|
case 'search':
|
||||||
|
this.listQuery.pageNo = 1;
|
||||||
|
this.listQuery.pageSize = 10;
|
||||||
|
this.listQuery.productionLineId = val.productionLineId ? val.productionLineId : undefined;
|
||||||
|
this.listQuery.thick = val.thick ? val.thick : undefined;
|
||||||
|
this.listQuery.startTime = val.timeVal ? val.timeVal[0] : undefined;
|
||||||
|
this.listQuery.endTime = val.timeVal ? val.timeVal[1] : undefined;
|
||||||
|
|
||||||
|
//this.listQuery.reportEndTime = val.timeVal ? [new Date(val.timeVal[1]).getTime()] : undefined;
|
||||||
|
this.getDataList();
|
||||||
|
break;
|
||||||
|
case 'export':
|
||||||
|
this.exportXlsx();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log(val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 获取数据列表
|
||||||
|
getDataList() {
|
||||||
|
this.listQuery.eqName = this.$route.query.eqName
|
||||||
|
this.dataListLoading = true;
|
||||||
|
this.urlOptions.getDataListURL(this.listQuery).then(response => {
|
||||||
|
this.tableData = response.data.list
|
||||||
|
this.showData = this.tableData
|
||||||
|
this.listQuery.total = response.data.total;
|
||||||
|
this.dataListLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 每页数
|
||||||
|
sizeChangeHandle(val) {
|
||||||
|
this.listQuery.pageSize = val;
|
||||||
|
this.listQuery.pageNo = 1;
|
||||||
|
this.getDataList();
|
||||||
|
},
|
||||||
|
// 当前页
|
||||||
|
currentChangeHandle(val) {
|
||||||
|
this.listQuery.pageNo = val;
|
||||||
|
this.getDataList();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
373
src/views/core/monitoring/nextClip/index.vue
Normal file
373
src/views/core/monitoring/nextClip/index.vue
Normal file
@@ -0,0 +1,373 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: Do not edit
|
||||||
|
* @Date: 2023-08-29 14:59:29
|
||||||
|
* @LastEditTime: 2024-12-02 13:44:47
|
||||||
|
* @LastEditors: zwq
|
||||||
|
* @Description:
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<!-- :isFold="true" 控制展开 -->
|
||||||
|
<search-bar
|
||||||
|
:formConfigs="formConfig"
|
||||||
|
ref="searchBarForm"
|
||||||
|
@headBtnClick="buttonClick" />
|
||||||
|
<base-table
|
||||||
|
v-if="showData.length"
|
||||||
|
class="right-aside"
|
||||||
|
v-loading="dataListLoading"
|
||||||
|
:table-props="tableProps"
|
||||||
|
:page="listQuery.pageNo"
|
||||||
|
:limit="listQuery.pageSize"
|
||||||
|
:table-data="showData"
|
||||||
|
>
|
||||||
|
<method-btn
|
||||||
|
v-if="tableBtn.length"
|
||||||
|
slot="handleBtn"
|
||||||
|
:width="120"
|
||||||
|
label="操作"
|
||||||
|
:method-list="tableBtn"
|
||||||
|
@clickBtn="handleClick" />
|
||||||
|
</base-table>
|
||||||
|
<div v-else class="no-data-bg"></div>
|
||||||
|
<pagination
|
||||||
|
:limit.sync="listQuery.pageSize"
|
||||||
|
:page.sync="listQuery.pageNo"
|
||||||
|
:total="listQuery.total"
|
||||||
|
@pagination="getDataList" />
|
||||||
|
<!-- <el-dialog
|
||||||
|
title="提示"
|
||||||
|
:visible.sync="dialogVisible"
|
||||||
|
width="30%"
|
||||||
|
:before-close="handleClose">
|
||||||
|
<el-button type="primary" @click="exportXlsx">xlsx</el-button>
|
||||||
|
<el-button type="success" @click="exportPdf">pdf</el-button>
|
||||||
|
<span slot="footer" class="dialog-footer">
|
||||||
|
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||||
|
<el-button type="primary" @click="dialogVisible = false">确 定</el-button>
|
||||||
|
</span>
|
||||||
|
</el-dialog> -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { parseTime } from '../../mixins/code-filter';
|
||||||
|
import { getDownLogPage, getPdList, getThick, exportDownLogData } from '@/api/core/monitoring/index'
|
||||||
|
import * as XLSX from 'xlsx'
|
||||||
|
import FileSaver from 'file-saver'
|
||||||
|
import jsPDF from 'jspdf'
|
||||||
|
import html2canvas from 'html2canvas'
|
||||||
|
|
||||||
|
const tableProps = [
|
||||||
|
{
|
||||||
|
prop: 'productionLineName',
|
||||||
|
label: '产线'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'eqName',
|
||||||
|
label: '下片机械手编号'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'pos',
|
||||||
|
label: '工位编号'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'pallet',
|
||||||
|
label: '托数/托'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'palletNum',
|
||||||
|
label: '一托玻璃数量/片'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'startTime',
|
||||||
|
label: '开始时间',
|
||||||
|
filter: parseTime,
|
||||||
|
width: 160
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'endTime',
|
||||||
|
label: '结束时间',
|
||||||
|
filter: parseTime,
|
||||||
|
width: 160
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'length',
|
||||||
|
label: '玻璃长度/mm'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'width',
|
||||||
|
label: '玻璃宽度/mm',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'thick',
|
||||||
|
label: '玻璃厚度/mm'
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
urlOptions: {
|
||||||
|
getDataListURL: getDownLogPage
|
||||||
|
},
|
||||||
|
tableData: [],
|
||||||
|
listQuery: {
|
||||||
|
pageSize: 10,
|
||||||
|
pageNo: 1,
|
||||||
|
total: 1,
|
||||||
|
productionLineId: undefined,
|
||||||
|
thick: undefined,
|
||||||
|
|
||||||
|
},
|
||||||
|
exportLoading: false,
|
||||||
|
dataListLoading: false,
|
||||||
|
selectedList: [],
|
||||||
|
dialogVisible: false,
|
||||||
|
addOrEditTitle: '',
|
||||||
|
addOrUpdateVisible: false,
|
||||||
|
tableProps,
|
||||||
|
tableBtn: [
|
||||||
|
{
|
||||||
|
type: 'his',
|
||||||
|
btnName: '历史',
|
||||||
|
},
|
||||||
|
].filter((v) => v),
|
||||||
|
tableData: [],
|
||||||
|
showData: [],
|
||||||
|
fileName: '',
|
||||||
|
formConfig: [
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '产线',
|
||||||
|
selectOptions: [],
|
||||||
|
param: 'productionLineId'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '玻璃型号',
|
||||||
|
selectOptions: [],
|
||||||
|
param: 'thick'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'datePicker',
|
||||||
|
label: '统计开始时间',
|
||||||
|
dateType: 'daterange',
|
||||||
|
format: 'yyyy-MM-dd',
|
||||||
|
valueFormat: "yyyy-MM-dd HH:mm:ss",
|
||||||
|
rangeSeparator: '-',
|
||||||
|
startPlaceholder: '开始时间',
|
||||||
|
endPlaceholder: '结束时间',
|
||||||
|
param: 'timeVal',
|
||||||
|
defaultTime: ['00:00:00', '23:59:59'],
|
||||||
|
defaultSelect: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
btnName: '查询',
|
||||||
|
name: 'search',
|
||||||
|
color: 'primary',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// type: this.$auth.hasPermi('base:factory:export') ? 'button' : '',
|
||||||
|
type: 'button',
|
||||||
|
btnName: '导出',
|
||||||
|
name: 'export',
|
||||||
|
color: 'warning',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
this.getDataList()
|
||||||
|
this.getPdLineList()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
handleClick(val) {
|
||||||
|
console.log(val);
|
||||||
|
if (val.type === 'his') {
|
||||||
|
this.$router.push({
|
||||||
|
path: 'nextClipHis',
|
||||||
|
query: {
|
||||||
|
eqName: val.data.eqName,
|
||||||
|
productionLineId: this.listQuery.productionLineId,
|
||||||
|
thick: this.listQuery.thick,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// this.addOrUpdateVisible = true;
|
||||||
|
// this.addOrEditTitle =
|
||||||
|
// val.data?.factoryName + '-' + val.data?.lineName + ' 详情';
|
||||||
|
// this.$nextTick(() => {
|
||||||
|
// this.$refs.eqDetail.init(
|
||||||
|
// val.data.lineId,
|
||||||
|
// this.listQuery.startTime,
|
||||||
|
// this.listQuery.endTime
|
||||||
|
// );
|
||||||
|
// });
|
||||||
|
},
|
||||||
|
test() {
|
||||||
|
var target = document.getElementsByClassName("right-aside")[0]
|
||||||
|
target.style.background = '#FFFFFF'
|
||||||
|
var that = this
|
||||||
|
setTimeout(() => {
|
||||||
|
html2canvas(target).then(function(canvas) {
|
||||||
|
var contentWidth = canvas.width
|
||||||
|
var contentHeight = canvas.height
|
||||||
|
|
||||||
|
// 一页pdf显示html页面生成的canvas高度
|
||||||
|
var pageHeight = contentHeight / 592.28 * 841.89
|
||||||
|
// 未生成pdf的html页面高度
|
||||||
|
var leftHeight = contentHeight
|
||||||
|
// 页面偏移
|
||||||
|
var position = 0
|
||||||
|
// a4纸的尺寸[595.28,841.89],html页面生成的canvas在pdf中图片的高度
|
||||||
|
var imgWidth = 595.28
|
||||||
|
var imgHeight = 592.28 / contentWidth * contentHeight
|
||||||
|
|
||||||
|
var pageData = canvas.toDataURL('image/jpeg', 1.0)
|
||||||
|
|
||||||
|
console.log('nihc URL', leftHeight, pageHeight)
|
||||||
|
|
||||||
|
var pdf = new jsPDF('', 'pt', 'a4')
|
||||||
|
|
||||||
|
if (leftHeight < pageHeight) {
|
||||||
|
pdf.addImage(pageData, 'JPEG', 0, 20, imgWidth, imgHeight)
|
||||||
|
} else {
|
||||||
|
while(leftHeight > 0) {
|
||||||
|
pdf.addImage(pageData, 'JPEG', 0, position, imgWidth, imgHeight)
|
||||||
|
leftHeight -= pageHeight
|
||||||
|
position -= 841.89
|
||||||
|
// 避免空白页
|
||||||
|
if (leftHeight > 0) {
|
||||||
|
pdf.addPage()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pdf.save(that.fileName + '工段统计.pdf')
|
||||||
|
})
|
||||||
|
}, 300)
|
||||||
|
},
|
||||||
|
exportECL() {
|
||||||
|
let tables = document.querySelector('.el-table').cloneNode(true)
|
||||||
|
const fix = tables.querySelector('.el-table__fixed')
|
||||||
|
const fixRight = tables.querySelector('.el-table__fixed-right')
|
||||||
|
if (fix) {
|
||||||
|
tables.removeChild(tables.querySelector('.el-table__fixed'))
|
||||||
|
}
|
||||||
|
if (fixRight) {
|
||||||
|
tables.removeChild(tables.querySelector('.el-table__fixed-right'))
|
||||||
|
}
|
||||||
|
let exportTable = XLSX.utils.table_to_book(tables)
|
||||||
|
|
||||||
|
var exportTableOut = XLSX.write(exportTable, {
|
||||||
|
bookType: 'xlsx', bookSST: true, type: 'array'
|
||||||
|
})
|
||||||
|
// sheetjs.xlsx为导出表格的标题名称
|
||||||
|
try {
|
||||||
|
FileSaver.saveAs(new Blob([exportTableOut], {
|
||||||
|
type: 'application/octet-stream'
|
||||||
|
}), this.fileName + '工段统计.xlsx')
|
||||||
|
} catch (e) {
|
||||||
|
if (typeof console !== 'undefined') console.log(e, exportTableOut)
|
||||||
|
}
|
||||||
|
return exportTableOut
|
||||||
|
},
|
||||||
|
exportPdf() {
|
||||||
|
this.test()
|
||||||
|
setTimeout(() =>{
|
||||||
|
this.dialogVisible = false
|
||||||
|
this.showData = this.tableData
|
||||||
|
}, 600)
|
||||||
|
|
||||||
|
},
|
||||||
|
exportXlsx() {
|
||||||
|
this.exportECL()
|
||||||
|
this.dialogVisible = false
|
||||||
|
this.showData = this.tableData
|
||||||
|
},
|
||||||
|
handleClose(done) {
|
||||||
|
this.$confirm('确认关闭?')
|
||||||
|
.then(_ => {
|
||||||
|
done();
|
||||||
|
})
|
||||||
|
.catch(_ => {});
|
||||||
|
},
|
||||||
|
getPdLineList() {
|
||||||
|
getPdList().then((res) => {
|
||||||
|
this.formConfig[0].selectOptions = res.data || []
|
||||||
|
})
|
||||||
|
getThick().then((res) => {
|
||||||
|
this.formConfig[1].selectOptions = res.data.map((item) => {
|
||||||
|
return {
|
||||||
|
id: item.thick + 'mm',
|
||||||
|
name: item.thick + 'mm'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
},
|
||||||
|
selectChange(val) {
|
||||||
|
console.log(val)
|
||||||
|
this.selectedList = val
|
||||||
|
},
|
||||||
|
buttonClick(val) {
|
||||||
|
switch (val.btnName) {
|
||||||
|
case 'search':
|
||||||
|
this.listQuery.pageNo = 1;
|
||||||
|
this.listQuery.pageSize = 10;
|
||||||
|
this.listQuery.productionLineId = val.productionLineId ? val.productionLineId : undefined;
|
||||||
|
this.listQuery.thick = val.thick ? val.thick : undefined;
|
||||||
|
this.listQuery.startTime = val.timeVal ? val.timeVal[0]: undefined;
|
||||||
|
this.listQuery.endTime = val.timeVal ? val.timeVal[1]: undefined;
|
||||||
|
|
||||||
|
//this.listQuery.reportEndTime = val.timeVal ? [new Date(val.timeVal[1]).getTime()] : undefined;
|
||||||
|
this.getDataList();
|
||||||
|
break;
|
||||||
|
case 'export':
|
||||||
|
this.handleExport();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log(val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 获取数据列表
|
||||||
|
getDataList() {
|
||||||
|
this.dataListLoading = true;
|
||||||
|
this.urlOptions.getDataListURL(this.listQuery).then(response => {
|
||||||
|
this.tableData = response.data.list
|
||||||
|
this.showData = this.tableData
|
||||||
|
this.listQuery.total = response.data.total;
|
||||||
|
this.dataListLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 每页数
|
||||||
|
sizeChangeHandle(val) {
|
||||||
|
this.listQuery.pageSize = val;
|
||||||
|
this.listQuery.pageNo = 1;
|
||||||
|
this.getDataList();
|
||||||
|
},
|
||||||
|
// 当前页
|
||||||
|
currentChangeHandle(val) {
|
||||||
|
this.listQuery.pageNo = val;
|
||||||
|
this.getDataList();
|
||||||
|
},
|
||||||
|
handleExport() {
|
||||||
|
// 处理查询参数
|
||||||
|
let params = { ...this.listQuery };
|
||||||
|
params.pageNo = undefined;
|
||||||
|
params.pageSize = undefined;
|
||||||
|
this.$modal.confirm('是否确认导出下片日志?').then(() => {
|
||||||
|
this.exportLoading = true;
|
||||||
|
return exportDownLogData(params);
|
||||||
|
}).then(response => {
|
||||||
|
this.$download.excel(response, '下片日志.xls');
|
||||||
|
this.exportLoading = false;
|
||||||
|
}).catch(() => { });
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
280
src/views/core/monitoring/productAuto/BarChart.vue
Normal file
280
src/views/core/monitoring/productAuto/BarChart.vue
Normal file
@@ -0,0 +1,280 @@
|
|||||||
|
<template>
|
||||||
|
<div :class="className" :style="{ height: height, width: width, marginLeft: '10px' }" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
require('echarts/theme/macarons'); // 引入主题
|
||||||
|
import resize from '@/utils/chartMixins/resize';
|
||||||
|
|
||||||
|
const animationDuration = 1000;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
mixins: [resize], // 混入 resize 逻辑(自适应窗口)
|
||||||
|
props: {
|
||||||
|
className: {
|
||||||
|
type: String,
|
||||||
|
default: 'chart',
|
||||||
|
},
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: String,
|
||||||
|
default: '100%',
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: String,
|
||||||
|
default: '300px',
|
||||||
|
},
|
||||||
|
barData: {
|
||||||
|
type: Array,
|
||||||
|
default: () => [],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
chart: null, // 图表实例
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
// 监听 barData 变化(深度监听数组内部元素)
|
||||||
|
barData: {
|
||||||
|
deep: true,
|
||||||
|
handler: 'handleBarDataChange', // 调用处理方法
|
||||||
|
},
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// 组件挂载后初始化图表(确保 DOM 已就绪)
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.initChart();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
// 组件销毁前清理图表实例
|
||||||
|
if (this.chart) {
|
||||||
|
this.chart.dispose();
|
||||||
|
this.chart = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
// barData 变化时的处理方法
|
||||||
|
handleBarDataChange() {
|
||||||
|
// 确保 DOM 存在再更新图表
|
||||||
|
this.$nextTick(() => {
|
||||||
|
// 如果图表未初始化,先初始化;否则直接更新数据
|
||||||
|
if (!this.chart) {
|
||||||
|
this.initChart();
|
||||||
|
} else {
|
||||||
|
this.updateChart();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
// 初始化图表
|
||||||
|
initChart() {
|
||||||
|
// 避免重复初始化(先销毁旧实例)
|
||||||
|
if (this.chart) {
|
||||||
|
this.chart.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 确保 DOM 元素存在
|
||||||
|
if (!this.$el) {
|
||||||
|
console.error('图表容器 DOM 元素不存在');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化图表实例
|
||||||
|
this.chart = echarts.init(this.$el, 'macarons');
|
||||||
|
// 设置图表配置
|
||||||
|
this.setChartOption();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 更新图表数据(复用配置逻辑)
|
||||||
|
updateChart() {
|
||||||
|
if (!this.chart) return;
|
||||||
|
this.setChartOption();
|
||||||
|
},
|
||||||
|
|
||||||
|
// 图表配置项(抽离为单独方法,方便初始化和更新复用)
|
||||||
|
setChartOption() {
|
||||||
|
const dataValues = this.barData.flatMap(item => [item.inputNum || 0, item.outputNum || 0]);
|
||||||
|
const maxData = Math.max(...dataValues, 0); // 加 0 确保无数据时 maxData 为 0
|
||||||
|
|
||||||
|
// 2. 计算 Y 轴最大值(留 10% 余量,避免数据顶到顶部)
|
||||||
|
let yMax = 0;
|
||||||
|
if (maxData > 0) {
|
||||||
|
yMax = Math.ceil(maxData * 1.1); // 向上取整,确保刻度为整数
|
||||||
|
} else {
|
||||||
|
yMax = 100; // 无数据时默认最大值为 100,避免 Y 轴消失
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 计算 interval(5 个刻度对应 4 个间隔,向上取整确保间隔为整数)
|
||||||
|
const yInterval = Math.ceil((yMax - 0) / 4); // min 固定为 0,直接减 0
|
||||||
|
|
||||||
|
this.chart.setOption({
|
||||||
|
title: {
|
||||||
|
text: this.title
|
||||||
|
? '{space|}{tip|}{space|}{value|' + this.title + '}'
|
||||||
|
: '',
|
||||||
|
textStyle: {
|
||||||
|
rich: {
|
||||||
|
tip: {
|
||||||
|
width: 6,
|
||||||
|
height: 6,
|
||||||
|
borderRadius: 50,
|
||||||
|
backgroundColor: '#288AFF',
|
||||||
|
},
|
||||||
|
space: {
|
||||||
|
width: 8,
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
fontSize: 14,
|
||||||
|
color: 'black',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
color: ['#288AFF', '#8EF0AB', '#FFDC94'],
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'cross',
|
||||||
|
crossStyle: {
|
||||||
|
color: '#999',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['投入', '产出', '加工成品率'],
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: 20,
|
||||||
|
right: 30,
|
||||||
|
top:40,
|
||||||
|
bottom: 10,
|
||||||
|
|
||||||
|
containLabel: true,
|
||||||
|
splitArea: {
|
||||||
|
show: false // 关键:关闭网格背景分区(去掉间隔色块)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: this.barData.map((item) => item.lineName),
|
||||||
|
axisLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: 'rgba(0, 0, 0, 0.45)',
|
||||||
|
width: 1 // 轴线宽度(可选,默认 1,可按需调整)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 2. 控制 X 轴刻度线颜色(与轴线颜色保持一致,视觉统一)
|
||||||
|
axisTick: {
|
||||||
|
lineStyle: {
|
||||||
|
color: 'rgba(0, 0, 0, 0.45)', // 刻度线颜色,需与轴线颜色匹配
|
||||||
|
width: 1 // 刻度线宽度(可选)
|
||||||
|
},
|
||||||
|
alignWithLabel: true // 可选:让刻度线与文字对齐(避免文字偏移时刻度线错位)
|
||||||
|
},
|
||||||
|
// 3. 控制 X 轴文字颜色(如:深灰色 rgba(0, 0, 0, 0.45))
|
||||||
|
axisLabel: {
|
||||||
|
color: 'rgba(0, 0, 0, 0.45)6', // 文字颜色,可自定义
|
||||||
|
fontSize: 12, // 可选:调整文字大小(默认 12,按需修改)
|
||||||
|
// 可选:文字过长时换行/省略(避免文字重叠,按需开启)
|
||||||
|
formatter: (value) => {
|
||||||
|
// 示例:文字超过 6 个字符时换行(可根据需求调整字符数)
|
||||||
|
if (value.length > 6) {
|
||||||
|
return value.slice(0, 6) + '\n' + value.slice(6);
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 原有配置(若需保留可解开注释)
|
||||||
|
// axisPointer: {
|
||||||
|
// type: 'shadow',
|
||||||
|
// }
|
||||||
|
},
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
name: '投入/产出 片',
|
||||||
|
min: 0, // 最小值固定为 0
|
||||||
|
max: yMax,
|
||||||
|
interval: yInterval,
|
||||||
|
splitArea: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
formatter: '{value}',
|
||||||
|
color: 'rgba(0, 0, 0, 0.45)'
|
||||||
|
},
|
||||||
|
|
||||||
|
// 可选:修改 Y 轴名称颜色(与文字颜色保持一致)
|
||||||
|
nameTextStyle: {
|
||||||
|
color: 'rgba(0, 0, 0, 0.45)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
name: '加工成品率',
|
||||||
|
min: 0,
|
||||||
|
max: 100, // 成品率固定 0-100%
|
||||||
|
interval: 25, // 100 / 4 = 25,刚好 5 个刻度(0、25、50、75、100)
|
||||||
|
axisLabel: {
|
||||||
|
formatter: '{value} %',
|
||||||
|
color: 'rgba(0, 0, 0, 0.45)'
|
||||||
|
},
|
||||||
|
splitArea: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
// 可选:修改 Y 轴名称颜色
|
||||||
|
nameTextStyle: {
|
||||||
|
color: 'rgba(0, 0, 0, 0.45)'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '投入',
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: '20',
|
||||||
|
data: this.barData.map((item) => item.inputNum),
|
||||||
|
tooltip: {
|
||||||
|
valueFormatter: (value) => `${value} 片`,
|
||||||
|
},
|
||||||
|
animationDuration,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '产出',
|
||||||
|
type: 'bar',
|
||||||
|
barWidth: '20',
|
||||||
|
data: this.barData.map((item) => item.outputNum),
|
||||||
|
tooltip: {
|
||||||
|
valueFormatter: (value) => `${value} 片`,
|
||||||
|
},
|
||||||
|
animationDuration,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '加工成品率',
|
||||||
|
type: 'line',
|
||||||
|
yAxisIndex: 1,
|
||||||
|
tooltip: {
|
||||||
|
valueFormatter: (value) => `${value} %`,
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'top',
|
||||||
|
distance: 6,
|
||||||
|
fontSize: 11,
|
||||||
|
color: '#333333',
|
||||||
|
formatter: (params) => `${params.value}` // 显示单位
|
||||||
|
},
|
||||||
|
data: this.barData.map((item) => item.processingRatio),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
273
src/views/core/monitoring/productAuto/baseTable.vue
Normal file
273
src/views/core/monitoring/productAuto/baseTable.vue
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
<template>
|
||||||
|
<div class="baseTable">
|
||||||
|
<el-table
|
||||||
|
:ref="id"
|
||||||
|
:data="renderData"
|
||||||
|
v-bind="$attrs"
|
||||||
|
:border="cancelBorder ? false : true"
|
||||||
|
@current-change="currentChange"
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
|
style="width: 100%"
|
||||||
|
:header-cell-style="{
|
||||||
|
background: '#F2F4F9',
|
||||||
|
color: '#606266',
|
||||||
|
}">
|
||||||
|
<!-- 多选 -->
|
||||||
|
<el-table-column
|
||||||
|
v-if="selectWidth"
|
||||||
|
type="selection"
|
||||||
|
:width="selectWidth" />
|
||||||
|
<!-- 序号 -->
|
||||||
|
<el-table-column
|
||||||
|
v-if="page && limit"
|
||||||
|
prop="_pageIndex"
|
||||||
|
:width="pageWidth"
|
||||||
|
align="center"
|
||||||
|
:fixed="cancelPageFixed ? false : true">
|
||||||
|
<template slot="header">
|
||||||
|
<el-popover placement="bottom-start" width="300" trigger="click">
|
||||||
|
<div
|
||||||
|
class="setting-box"
|
||||||
|
style="max-height: 400px; overflow-y: auto">
|
||||||
|
<el-checkbox
|
||||||
|
v-for="(item, index) in tableProps"
|
||||||
|
:key="'cb' + index"
|
||||||
|
v-model="selectedBox[index]"
|
||||||
|
:label="item.label" />
|
||||||
|
</div>
|
||||||
|
<i slot="reference" class="el-icon-s-tools" />
|
||||||
|
</el-popover>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
|
||||||
|
<el-table-column
|
||||||
|
v-for="item in renderTableHeadList"
|
||||||
|
:key="item.prop"
|
||||||
|
v-bind="item"
|
||||||
|
:label="item.label"
|
||||||
|
:prop="item.prop"
|
||||||
|
:fixed="item.fixed || false"
|
||||||
|
:show-overflow-tooltip="item.showOverflowtooltip || false"
|
||||||
|
:sortable="item.sortable || false">
|
||||||
|
<template slot="header">
|
||||||
|
<span>{{ item.label }}</span>
|
||||||
|
</template>
|
||||||
|
<!-- 多表头 -->
|
||||||
|
<template v-if="item.children">
|
||||||
|
<el-table-column
|
||||||
|
v-for="sub in item.children"
|
||||||
|
:prop="sub.prop"
|
||||||
|
:key="sub.prop"
|
||||||
|
v-bind="sub"
|
||||||
|
:label="sub.label">
|
||||||
|
<template v-if="sub.children">
|
||||||
|
<el-table-column
|
||||||
|
v-for="ssub in sub.children"
|
||||||
|
:prop="ssub.prop"
|
||||||
|
:key="ssub.prop"
|
||||||
|
v-bind="ssub"
|
||||||
|
:label="ssub.label">
|
||||||
|
<template slot-scope="sscopeInner">
|
||||||
|
<component
|
||||||
|
:is="ssub.subcomponent"
|
||||||
|
v-if="ssub.subcomponent"
|
||||||
|
:key="sscopeInner.row.id"
|
||||||
|
:inject-data="{ ...sscopeInner.row, ...ssub }"
|
||||||
|
@emitData="emitData" />
|
||||||
|
<span v-else>
|
||||||
|
{{ sscopeInner.row[ssub.prop] | commonFilter(ssub.filter) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</template>
|
||||||
|
<template slot-scope="scopeInner">
|
||||||
|
<component
|
||||||
|
:is="sub.subcomponent"
|
||||||
|
v-if="sub.subcomponent"
|
||||||
|
:key="scopeInner.row.id"
|
||||||
|
:inject-data="{ ...scopeInner.row, ...sub }"
|
||||||
|
@emitData="emitData" />
|
||||||
|
<span v-else>
|
||||||
|
{{ scopeInner.row[sub.prop] | commonFilter(sub.filter) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</template>
|
||||||
|
<template slot-scope="scope">
|
||||||
|
<component
|
||||||
|
:is="item.subcomponent"
|
||||||
|
v-if="item.subcomponent"
|
||||||
|
:key="scope.row.id"
|
||||||
|
:itemProp="item.prop"
|
||||||
|
:inject-data="{ ...scope.row, ...item }"
|
||||||
|
@emitData="emitData" />
|
||||||
|
<span v-else>
|
||||||
|
{{ scope.row[item.prop] | commonFilter(item.filter) }}
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
<slot name="handleBtn" />
|
||||||
|
</el-table>
|
||||||
|
<!-- 表格底部加号 -->
|
||||||
|
<el-button
|
||||||
|
v-if="addButtonShow"
|
||||||
|
class="addButton"
|
||||||
|
icon="el-icon-plus"
|
||||||
|
@click="emitButtonClick">
|
||||||
|
{{ addButtonShow }}
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'BaseTable',
|
||||||
|
filters: {
|
||||||
|
commonFilter: (source, filterType = (a) => a) => {
|
||||||
|
return filterType(source);
|
||||||
|
},
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
cancelBorder: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
cancelPageFixed: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
tableData: {
|
||||||
|
type: Array,
|
||||||
|
required: true,
|
||||||
|
default: () => {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
tableProps: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return [];
|
||||||
|
},
|
||||||
|
},
|
||||||
|
id: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
page: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
pageWidth: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: 70,
|
||||||
|
},
|
||||||
|
limit: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
selectWidth: {
|
||||||
|
type: Number,
|
||||||
|
required: false,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
addButtonShow: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectedBox: new Array(100).fill(true),
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
renderTableHeadList() {
|
||||||
|
return this.tableProps.filter((item, index) => {
|
||||||
|
return this.selectedBox[index];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
renderData() {
|
||||||
|
return this.tableData.map((item, index) => {
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
_pageIndex: (this.page - 1) * this.limit + index + 1,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
},
|
||||||
|
beforeMount() {
|
||||||
|
this.selectedBox = new Array(100).fill(true);
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
currentChange(newVal, oldVal) {
|
||||||
|
this.$emit('current-change', { newVal, oldVal });
|
||||||
|
},
|
||||||
|
handleSelectionChange(val) {
|
||||||
|
this.$emit('selection-change', val);
|
||||||
|
},
|
||||||
|
emitData(val) {
|
||||||
|
this.$emit('emitFun', val);
|
||||||
|
},
|
||||||
|
emitButtonClick() {
|
||||||
|
this.$emit('emitButtonClick');
|
||||||
|
},
|
||||||
|
setCurrent(name, index) {
|
||||||
|
let _this = this;
|
||||||
|
let obj = _this.$refs[name].data[index];
|
||||||
|
_this.$refs[name].setCurrentRow(obj);
|
||||||
|
},
|
||||||
|
doLayout(name) {
|
||||||
|
this.$refs[name].doLayout();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.baseTable .show-col-btn {
|
||||||
|
margin-right: 5px;
|
||||||
|
line-height: inherit;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.baseTable .el-icon-refresh {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<style>
|
||||||
|
.baseTable .el-table__body tr.current-row > td.el-table__cell {
|
||||||
|
background-color: #eaf1fc;
|
||||||
|
}
|
||||||
|
.baseTable .el-table .el-table__cell {
|
||||||
|
padding: 0;
|
||||||
|
height: 35px;
|
||||||
|
}
|
||||||
|
.baseTable .addButton {
|
||||||
|
width: 100%;
|
||||||
|
height: 35px;
|
||||||
|
border-top: none;
|
||||||
|
color: #0b58ff;
|
||||||
|
border-color: #ebeef5;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.baseTable .addButton:hover {
|
||||||
|
color: #0b58ff;
|
||||||
|
border-color: #ebeef5;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
.baseTable .addButton:focus {
|
||||||
|
border-color: #ebeef5;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tooltip__popper.is-dark {
|
||||||
|
background: rgba(0, 0, 0, 0.6) !important;
|
||||||
|
}
|
||||||
|
.el-tooltip__popper .popper__arrow,
|
||||||
|
.el-tooltip__popper .popper__arrow::after {
|
||||||
|
border-top-color: rgba(0, 0, 0, 0.4) !important;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
File diff suppressed because it is too large
Load Diff
65
src/views/core/monitoring/rawFilmReport/SmallTitle.vue
Normal file
65
src/views/core/monitoring/rawFilmReport/SmallTitle.vue
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: zwq
|
||||||
|
* @Date: 2023-08-01 15:27:31
|
||||||
|
* @LastEditors: zwq
|
||||||
|
* @LastEditTime: 2023-08-01 16:25:54
|
||||||
|
* @Description:
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div :class="[className, { 'p-0': noPadding }]">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
size: {
|
||||||
|
// 取值范围: xl lg md sm
|
||||||
|
type: String,
|
||||||
|
default: 'de',
|
||||||
|
validator: function (val) {
|
||||||
|
return ['xl', 'lg', 'de', 'md', 'sm'].indexOf(val) !== -1;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
noPadding: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
className: function () {
|
||||||
|
return `${this.size}-title`;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
$pxls: (xl, 28px) (lg, 24px) (de, 20px) (md, 18px) (sm, 16px);
|
||||||
|
$mgr: 8px;
|
||||||
|
@each $size, $height in $pxls {
|
||||||
|
.#{$size}-title {
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: $height;
|
||||||
|
color: #000;
|
||||||
|
font-weight: 500;
|
||||||
|
font-family: '微软雅黑', 'Microsoft YaHei', Arial, Helvetica, sans-serif;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
width: 4px;
|
||||||
|
height: $height + 2px;
|
||||||
|
border-radius: 1px;
|
||||||
|
margin-right: $mgr;
|
||||||
|
background-color: #0b58ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-0 {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
221
src/views/core/monitoring/rawFilmReport/add-or-updata.vue
Normal file
221
src/views/core/monitoring/rawFilmReport/add-or-updata.vue
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog :visible.sync="visible" width="40%">
|
||||||
|
<small-title slot="title" :no-padding="true">
|
||||||
|
{{ !dataForm.id ? '新增' : '编辑' }}
|
||||||
|
</small-title>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<div class="visual-part">
|
||||||
|
<el-form ref="dataForm" :model="dataForm" :rules="dataRule" label-width="100px"
|
||||||
|
@keyup.enter.native="dataFormSubmit">
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="维度" prop="statisticType">
|
||||||
|
<el-select v-model="dataForm.statisticType" style="width: 100%" placeholder="请选择维度">
|
||||||
|
<el-option v-for="item in statisticTypeList" :key="item.id" :label="item.name" :value="item.id" />
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="厚度" prop="modifyThick">
|
||||||
|
<el-input v-model="dataForm.modifyThick" placeholder="请输入厚度" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="在线速度" prop="modifySpeed">
|
||||||
|
<el-input v-model="dataForm.modifySpeed" placeholder="请输入在线速度" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="宽度" prop="modifyWidth">
|
||||||
|
<el-input v-model="dataForm.modifyWidth" placeholder="请输入宽度" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="拉引量" prop="modifyInArea">
|
||||||
|
<el-input v-model="dataForm.modifyInArea" placeholder="请输入拉引量" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="下片面积" prop="modifyOutArea">
|
||||||
|
<el-input v-model="dataForm.modifyOutArea" placeholder="请输入下片面积" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-form-item label="良品率" prop="modifyRatio">
|
||||||
|
<el-input v-model="dataForm.modifyRatio" placeholder="请输入良品率" />
|
||||||
|
</el-form-item>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div slot="footer" class="dialog-footer">
|
||||||
|
<el-button style="" @click="goback()">取消</el-button>
|
||||||
|
<el-button type="primary" @click="dataFormSubmit()">
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { editCostOriginRadioHisData } from '@/api/core/monitoring/index'
|
||||||
|
import { parseTime } from '../../mixins/code-filter';
|
||||||
|
import SmallTitle from './SmallTitle';
|
||||||
|
export default {
|
||||||
|
components: { SmallTitle },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
addOrUpdateVisible: false,
|
||||||
|
statisticTypeList: [
|
||||||
|
{
|
||||||
|
id: '0',
|
||||||
|
name: '班组'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
name: '日'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
name: '周'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '3',
|
||||||
|
name: '月'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '4',
|
||||||
|
name: '年'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
dataForm: {
|
||||||
|
id: null,
|
||||||
|
statisticType:undefined,
|
||||||
|
modifyThick: undefined,
|
||||||
|
modifySpeed: undefined,
|
||||||
|
modifyWidth: undefined,
|
||||||
|
modifyInArea: undefined,
|
||||||
|
modifyOutArea: undefined,
|
||||||
|
modifyRatio: undefined,
|
||||||
|
},
|
||||||
|
dataRule: {
|
||||||
|
statisticType: [
|
||||||
|
{
|
||||||
|
required: true,
|
||||||
|
message: '维度不能为空',
|
||||||
|
trigger: 'blur',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// type: 'number',
|
||||||
|
// message: '产品编码为数字类型',
|
||||||
|
// trigger: 'blur',
|
||||||
|
// transfom: 'val => Number(val)',
|
||||||
|
// },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
init(data) {
|
||||||
|
console.log(data,'data');
|
||||||
|
|
||||||
|
this.dataForm.id = data.id || null;
|
||||||
|
this.visible = true;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs['dataForm'].resetFields();
|
||||||
|
this.dataForm = {
|
||||||
|
id: data.id || null,
|
||||||
|
statisticType: data.statisticType || undefined,
|
||||||
|
modifyThick: data.thick || undefined, // 厚度对应
|
||||||
|
modifySpeed: data.speed || undefined, // 在线速度对应
|
||||||
|
modifyWidth: data.width || undefined, // 掰边宽度对应
|
||||||
|
modifyInArea: data.inArea || undefined, // 拉引量对应
|
||||||
|
modifyOutArea: data.outArea || undefined, // 下片面积对应
|
||||||
|
modifyRatio: data.ratio || undefined, // 良品率对应
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 表单提交
|
||||||
|
dataFormSubmit() {
|
||||||
|
this.$refs['dataForm'].validate((valid) => {
|
||||||
|
if (valid) {
|
||||||
|
// 修改的提交
|
||||||
|
if (this.dataForm.id) {
|
||||||
|
editCostOriginRadioHisData(this.dataForm).then((response) => {
|
||||||
|
this.$modal.msgSuccess('修改成功');
|
||||||
|
this.visible = false;
|
||||||
|
this.$emit('refreshDataList');
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
goback() {
|
||||||
|
this.$emit('refreshDataList');
|
||||||
|
this.visible = false;
|
||||||
|
this.initData();
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.drawer >>> .el-drawer {
|
||||||
|
border-radius: 8px 0 0 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer >>> .el-form-item__label {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer >>> .el-drawer__header {
|
||||||
|
margin: 0;
|
||||||
|
padding: 32px 32px 24px;
|
||||||
|
border-bottom: 1px solid #dcdfe6;
|
||||||
|
}
|
||||||
|
.drawer >>> .el-drawer__body {
|
||||||
|
flex: 1;
|
||||||
|
height: 1px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer >>> .content {
|
||||||
|
padding: 30px 24px;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
/* height: 100%; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer >>> .visual-part {
|
||||||
|
flex: 1 auto;
|
||||||
|
max-height: 76vh;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
padding-right: 10px; /* 调整滚动条样式 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer >>> .el-form,
|
||||||
|
.drawer >>> .attr-list {
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-body__footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding: 18px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
536
src/views/core/monitoring/rawFilmReport/index.vue
Normal file
536
src/views/core/monitoring/rawFilmReport/index.vue
Normal file
@@ -0,0 +1,536 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<!-- :isFold="true" 控制展开 -->
|
||||||
|
<search-bar :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick"
|
||||||
|
@select-changed="selectType" />
|
||||||
|
<base-table v-if="tableData.length" class="right-aside" v-loading="dataListLoading" :table-props="tableProps"
|
||||||
|
:page="listQuery.pageNo" :limit="listQuery.pageSize" :table-data="tableData">
|
||||||
|
<method-btn v-if="tableBtn.length" slot="handleBtn" :width="120" label="操作" :method-list="tableBtn"
|
||||||
|
@clickBtn="handleClick" />
|
||||||
|
</base-table>
|
||||||
|
<div v-else class="no-data-bg"></div>
|
||||||
|
<pagination :limit.sync="listQuery.pageSize" :page.sync="listQuery.pageNo" :total="listQuery.total"
|
||||||
|
@pagination="getDataList" />
|
||||||
|
<add-or-update v-if="addOrUpdateVisible" ref="addOrUpdate" @refreshDataList="getDataList" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Vue from 'vue';
|
||||||
|
import AddOrUpdate from './add-or-updata';
|
||||||
|
|
||||||
|
import { parseTime } from '../../mixins/code-filter';
|
||||||
|
import { getCostOriginRadioHisData, getPdList } from '@/api/core/monitoring/index';
|
||||||
|
import { exportCostOriginRadioHisData } from '../../../../api/core/monitoring';
|
||||||
|
|
||||||
|
// Vue2 中注册全局方法(如果需要)
|
||||||
|
Vue.prototype.$download = Vue.prototype.$download || {
|
||||||
|
excel: (response, fileName) => {
|
||||||
|
const blob = new Blob([response.data], { type: 'application/vnd.ms-excel' });
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
const aLink = document.createElement('a');
|
||||||
|
aLink.style.display = 'none';
|
||||||
|
aLink.href = url;
|
||||||
|
aLink.setAttribute('download', fileName);
|
||||||
|
document.body.appendChild(aLink);
|
||||||
|
aLink.click();
|
||||||
|
document.body.removeChild(aLink);
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Vue.prototype.$modal = Vue.prototype.$modal || {
|
||||||
|
confirm: (message) => {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
if (window.confirm(message)) {
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const tableProps = [
|
||||||
|
{
|
||||||
|
prop: 'reportType',
|
||||||
|
label: '报表类型'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'time',
|
||||||
|
label: '日期',
|
||||||
|
width: 160
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'bindObjectName',
|
||||||
|
label: '产线'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'thick',
|
||||||
|
label: '厚度'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'speed',
|
||||||
|
label: '在线速度'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'width',
|
||||||
|
label: '掰边宽度'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'inArea',
|
||||||
|
label: '拉引量/㎡'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'outArea',
|
||||||
|
label: '下片面积/㎡'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'ratio',
|
||||||
|
label: '良品率/%'
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工具函数:获取选择时间所在周的起始和结束时间(Vue2 兼容)
|
||||||
|
* @param {String|Date} selectTime - 选择的时间(支持格式:yyyy-MM-dd、yyyy-MM-dd HH:mm:ss 或 Date 对象)
|
||||||
|
* @returns {Array} [startDate, endDate] - 所在周周一 00:00:00 至 周日 23:59:59(Date 对象)
|
||||||
|
*/
|
||||||
|
function getSelectedWeekRange(selectTime) {
|
||||||
|
// 兼容 String 类型时间和 Date 对象,统一转为 Date 实例
|
||||||
|
const targetDate = new Date(selectTime);
|
||||||
|
// 处理无效日期(若传入非法时间,返回当前时间的本周范围)
|
||||||
|
// if (isNaN(targetDate.getTime())) {
|
||||||
|
// console.warn('传入的时间格式无效,将使用当前时间计算本周范围');
|
||||||
|
// return getCurrentWeekRange(); // 可根据需求改为抛出错误或返回空
|
||||||
|
// }
|
||||||
|
|
||||||
|
const day = targetDate.getDay() || 7; // 周日为 7(避免周日 -0 天仍为周日)
|
||||||
|
const start = new Date(targetDate);
|
||||||
|
start.setDate(targetDate.getDate() - day + 1); // 计算所在周的周一
|
||||||
|
start.setHours(0, 0, 0, 0); // 重置时分秒为 00:00:00.000
|
||||||
|
|
||||||
|
const end = new Date(start);
|
||||||
|
end.setDate(start.getDate() + 6); // 周一 +6 天 = 周日
|
||||||
|
end.setHours(23, 59, 59, 999); // 重置时分秒为 23:59:59.999
|
||||||
|
|
||||||
|
return [start, end];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 工具函数:获取选择时间所在年的起始和结束时间(Vue2 兼容)
|
||||||
|
* @param {String|Date} selectTime - 选择的时间(支持格式:yyyy-MM-dd、yyyy-MM-dd HH:mm:ss 或 Date 对象)
|
||||||
|
* @returns {Array} [startDate, endDate] - 所在年 1月1日 00:00:00 至 12月31日 23:59:59(Date 对象)
|
||||||
|
*/
|
||||||
|
function getSelectedYearRange(selectTime) {
|
||||||
|
// 兼容 String 类型时间和 Date 对象,统一转为 Date 实例
|
||||||
|
const targetDate = new Date(selectTime);
|
||||||
|
// 处理无效日期(若传入非法时间,返回当前时间的本年范围)
|
||||||
|
// if (isNaN(targetDate.getTime())) {
|
||||||
|
// console.warn('传入的时间格式无效,将使用当前时间计算本年范围');
|
||||||
|
// return getCurrentYearRange(); // 可根据需求改为抛出错误或返回空
|
||||||
|
// }
|
||||||
|
|
||||||
|
const year = targetDate.getFullYear(); // 获取选择时间的年份
|
||||||
|
const start = new Date(year, 0, 1); // 所在年 1月1日(月份从 0 开始)
|
||||||
|
start.setHours(0, 0, 0, 0); // 重置时分秒为 00:00:00.000
|
||||||
|
|
||||||
|
const end = new Date(year, 11, 31); // 所在年 12月31日(11 代表 12 月)
|
||||||
|
end.setHours(23, 59, 59, 999); // 重置时分秒为 23:59:59.999
|
||||||
|
|
||||||
|
return [start, end];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 格式化时间为 yyyy-MM-dd HH:mm:ss(Vue2 兼容)
|
||||||
|
function formatDateTime(date) {
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = String(date.getMonth() + 1).padStart(2, '0');
|
||||||
|
const day = String(date.getDate()).padStart(2, '0');
|
||||||
|
const hours = String(date.getHours()).padStart(2, '0');
|
||||||
|
const minutes = String(date.getMinutes()).padStart(2, '0');
|
||||||
|
const seconds = String(date.getSeconds()).padStart(2, '0');
|
||||||
|
|
||||||
|
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
AddOrUpdate
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
urlOptions: {
|
||||||
|
getDataListURL: getCostOriginRadioHisData
|
||||||
|
},
|
||||||
|
tableData: [],
|
||||||
|
listQuery: {
|
||||||
|
pageSize: 10,
|
||||||
|
pageNo: 1,
|
||||||
|
total: 1,
|
||||||
|
bindObjectId: undefined,
|
||||||
|
statisticType: undefined,
|
||||||
|
startTime: undefined,
|
||||||
|
endTime: undefined
|
||||||
|
},
|
||||||
|
pdLineList: [],
|
||||||
|
exportLoading: false,
|
||||||
|
dataListLoading: false,
|
||||||
|
selectedList: [],
|
||||||
|
dialogVisible: false,
|
||||||
|
addOrEditTitle: '',
|
||||||
|
addOrUpdateVisible: false,
|
||||||
|
tableProps,
|
||||||
|
tableBtn: [
|
||||||
|
{
|
||||||
|
type: 'edit',
|
||||||
|
btnName: '编辑',
|
||||||
|
},
|
||||||
|
].filter(v => v),
|
||||||
|
fileName: '',
|
||||||
|
formConfig: [
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '报表类型',
|
||||||
|
onchange: true,
|
||||||
|
selectOptions: [
|
||||||
|
{ id: '0', name: '班组' },
|
||||||
|
{ id: '1', name: '日' },
|
||||||
|
{ id: '2', name: '周' },
|
||||||
|
{ id: '3', name: '月' },
|
||||||
|
{ id: '4', name: '年' }
|
||||||
|
],
|
||||||
|
param: 'statisticType',
|
||||||
|
index: 1,
|
||||||
|
extraOptions: [
|
||||||
|
{
|
||||||
|
parent: 'statisticType',
|
||||||
|
type: 'datePicker',
|
||||||
|
label: '统计时间',
|
||||||
|
dateType: 'daterange',
|
||||||
|
format: 'yyyy-MM-dd',
|
||||||
|
valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
||||||
|
rangeSeparator: '-',
|
||||||
|
startPlaceholder: '开始时间',
|
||||||
|
endPlaceholder: '结束时间',
|
||||||
|
param: 'timeVal',
|
||||||
|
defaultTime: ['00:00:00', '23:59:59'],
|
||||||
|
defaultSelect: [],
|
||||||
|
width: 250,
|
||||||
|
key: 'datePicker-0', // 唯一 key,触发重新渲染
|
||||||
|
appendToBody: true // 优化定位:挂载到 body 下
|
||||||
|
},
|
||||||
|
// 日 - 日期范围选择
|
||||||
|
{
|
||||||
|
parent: 'statisticType',
|
||||||
|
type: 'datePicker',
|
||||||
|
label: '统计时间',
|
||||||
|
dateType: 'daterange',
|
||||||
|
format: 'yyyy-MM-dd',
|
||||||
|
valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
||||||
|
rangeSeparator: '-',
|
||||||
|
startPlaceholder: '开始时间',
|
||||||
|
endPlaceholder: '结束时间',
|
||||||
|
param: 'timeValDay',
|
||||||
|
defaultTime: ['00:00:00', '23:59:59'],
|
||||||
|
defaultSelect: [],
|
||||||
|
width: 250,
|
||||||
|
key: 'datePicker-1', // 唯一 key,触发重新渲染
|
||||||
|
appendToBody: true // 优化定位:挂载到 body 下
|
||||||
|
},
|
||||||
|
// 周 - 单个日期选择(自动获取本周范围)
|
||||||
|
{
|
||||||
|
parent: 'statisticType',
|
||||||
|
type: 'datePicker',
|
||||||
|
label: '统计时间',
|
||||||
|
dateType: 'week',
|
||||||
|
placeholder: '选择日期',
|
||||||
|
format: 'yyyy 第 WW 周',
|
||||||
|
pickerOptions: {
|
||||||
|
firstDayOfWeek: 1 // 数字1表示周一作为周的第一天(0=周日,1=周一,依此类推)
|
||||||
|
},
|
||||||
|
valueFormat: 'yyyy-MM-dd',
|
||||||
|
param: 'timeValWeek',
|
||||||
|
width: 250,
|
||||||
|
key: 'datePicker-2', // 唯一 key,触发重新渲染
|
||||||
|
appendToBody: true // 优化定位:挂载到 body 下
|
||||||
|
},
|
||||||
|
// 月 - 日期范围选择
|
||||||
|
{
|
||||||
|
parent: 'statisticType',
|
||||||
|
type: 'datePicker',
|
||||||
|
label: '统计时间',
|
||||||
|
dateType: 'monthrange',
|
||||||
|
format: 'yyyy-MM-dd',
|
||||||
|
valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
||||||
|
rangeSeparator: '-',
|
||||||
|
startPlaceholder: '开始时间',
|
||||||
|
endPlaceholder: '结束时间',
|
||||||
|
param: 'timeValMonth',
|
||||||
|
defaultTime: ['00:00:00', '23:59:59'],
|
||||||
|
width: 250,
|
||||||
|
key: 'datePicker-3', // 唯一 key,触发重新渲染
|
||||||
|
appendToBody: true // 优化定位:挂载到 body 下
|
||||||
|
},
|
||||||
|
// 年 - 单个日期选择(自动获取本年范围)
|
||||||
|
{
|
||||||
|
parent: 'statisticType',
|
||||||
|
type: 'datePicker',
|
||||||
|
label: '统计时间',
|
||||||
|
dateType: 'year',
|
||||||
|
placeholder: '选择年份',
|
||||||
|
format: 'yyyy-MM-dd',
|
||||||
|
valueFormat: 'yyyy-MM-dd',
|
||||||
|
param: 'timeValYear',
|
||||||
|
width: 250,
|
||||||
|
key: 'datePicker-4', // 唯一 key,触发重新渲染
|
||||||
|
appendToBody: true // 优化定位:挂载到 body 下
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '产线',
|
||||||
|
selectOptions: [],
|
||||||
|
param: 'bindObjectId'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
btnName: '查询',
|
||||||
|
name: 'search',
|
||||||
|
color: 'primary',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'separate',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
btnName: '导出',
|
||||||
|
name: 'export',
|
||||||
|
color: 'warning',
|
||||||
|
}
|
||||||
|
],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
// 监听报表类型变化,强制刷新日期选择器
|
||||||
|
'listQuery.statisticType'(newVal, oldVal) {
|
||||||
|
if (newVal !== oldVal && this.$refs.searchBarForm) {
|
||||||
|
// 触发 search-bar 组件重新渲染(如果 search-bar 支持)
|
||||||
|
if (this.$refs.searchBarForm.$forceUpdate) {
|
||||||
|
this.$refs.searchBarForm.$forceUpdate();
|
||||||
|
}
|
||||||
|
// 延迟重置定位,确保 DOM 已更新
|
||||||
|
setTimeout(() => {
|
||||||
|
const datePickerEl = this.$refs.searchBarForm.$el.querySelector('.el-date-picker');
|
||||||
|
if (datePickerEl) {
|
||||||
|
// 触发 Element UI 日期选择器重新计算定位(内部方法)
|
||||||
|
const datePickerInstance = datePickerEl.__vue__;
|
||||||
|
if (datePickerInstance && datePickerInstance.updatePopper) {
|
||||||
|
datePickerInstance.updatePopper();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 100);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
// Vue2 中 $refs 需在 $nextTick 中访问(确保 DOM 渲染完成)
|
||||||
|
this.$nextTick(() => {
|
||||||
|
if (this.$refs.searchBarForm) {
|
||||||
|
this.$refs.searchBarForm.formInline.statisticType = '1';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.listQuery.statisticType = '1';
|
||||||
|
this.getDataList();
|
||||||
|
this.getPdLineList();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
selectType(val) {
|
||||||
|
// 报表类型切换时的回调(如需扩展可在此添加逻辑)
|
||||||
|
console.log('报表类型切换:', val);
|
||||||
|
},
|
||||||
|
handleClick(val) {
|
||||||
|
console.log('操作按钮点击:', val);
|
||||||
|
if (val.type === 'edit') {
|
||||||
|
this.addOrUpdateVisible = true;
|
||||||
|
// Vue2 中 $nextTick 确保子组件已渲染
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.addOrUpdate.init(val.data);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getPdLineList() {
|
||||||
|
getPdList().then(res => {
|
||||||
|
// Vue2 中数组赋值需确保响应式
|
||||||
|
this.$set(this.formConfig[1], 'selectOptions', res.data || []);
|
||||||
|
this.pdLineList = res.data || [];
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('获取产线列表失败:', err);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
selectChange(val) {
|
||||||
|
console.log('选择变更:', val);
|
||||||
|
this.selectedList = val;
|
||||||
|
},
|
||||||
|
buttonClick(val) {
|
||||||
|
console.log('头部按钮点击:', val);
|
||||||
|
switch (val.btnName) {
|
||||||
|
case 'search':
|
||||||
|
this.listQuery.pageNo = 1;
|
||||||
|
this.listQuery.pageSize = 10;
|
||||||
|
this.listQuery.bindObjectId = val.bindObjectId ? val.bindObjectId : undefined;
|
||||||
|
this.listQuery.statisticType = val.statisticType ? val.statisticType : undefined;
|
||||||
|
|
||||||
|
// 处理不同时间维度的时间范围
|
||||||
|
this.handleTimeRange(val);
|
||||||
|
|
||||||
|
this.getDataList();
|
||||||
|
break;
|
||||||
|
case 'export':
|
||||||
|
this.handleExport();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
console.log('未知按钮:', val);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 处理不同时间维度的时间范围
|
||||||
|
handleTimeRange(val) {
|
||||||
|
const statisticType = val.statisticType;
|
||||||
|
const timeVal = val.timeVal;
|
||||||
|
|
||||||
|
const timeValDay = val.timeValDay;
|
||||||
|
|
||||||
|
const timeValWeek = val.timeValWeek;
|
||||||
|
const timeValMonth = val.timeValMonth;
|
||||||
|
const timeValYear = val.timeValYear;
|
||||||
|
|
||||||
|
|
||||||
|
// 重置时间参数
|
||||||
|
this.listQuery.startTime = undefined;
|
||||||
|
this.listQuery.endTime = undefined;
|
||||||
|
|
||||||
|
switch (statisticType) {
|
||||||
|
case '0': // 班组 - 沿用原时间范围
|
||||||
|
if (timeVal && timeVal.length === 2) {
|
||||||
|
this.listQuery.startTime = timeVal[0];
|
||||||
|
this.listQuery.endTime = timeVal[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '1': // 日 - 沿用原时间范围
|
||||||
|
if (timeValDay && timeValDay.length === 2) {
|
||||||
|
this.listQuery.startTime = timeValDay[0];
|
||||||
|
this.listQuery.endTime = timeValDay[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '3': // 月 - 沿用原时间范围
|
||||||
|
if (timeValMonth && timeValMonth.length === 2) {
|
||||||
|
this.listQuery.startTime = timeValMonth[0];
|
||||||
|
this.listQuery.endTime = timeValMonth[1];
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '2': // 周 - 自动计算本周范围
|
||||||
|
if (timeValWeek) {
|
||||||
|
const [start, end] = getSelectedWeekRange(timeValWeek);
|
||||||
|
this.listQuery.startTime = formatDateTime(start);
|
||||||
|
this.listQuery.endTime = formatDateTime(end);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '4': // 年 - 自动计算本年范围
|
||||||
|
if (timeValYear) {
|
||||||
|
const [start, end] = getSelectedYearRange(timeValYear);
|
||||||
|
this.listQuery.startTime = formatDateTime(start);
|
||||||
|
this.listQuery.endTime = formatDateTime(end);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// 获取数据列表
|
||||||
|
getDataList() {
|
||||||
|
this.dataListLoading = true;
|
||||||
|
this.urlOptions.getDataListURL(this.listQuery)
|
||||||
|
.then(response => {
|
||||||
|
const arr = ['班组', '日', '周', '月', '年'];
|
||||||
|
// Vue2 中数组赋值确保响应式
|
||||||
|
this.tableData = (response.data?.list || []).map(item => {
|
||||||
|
item.reportType = arr[this.listQuery.statisticType] || '';
|
||||||
|
item.statisticType = this.listQuery.statisticType;
|
||||||
|
|
||||||
|
// 匹配产线名称
|
||||||
|
// const targetLine = this.pdLineList.find(line => line.id === item.bindObjectId);
|
||||||
|
// item.bindObjectName = targetLine ? targetLine.name : ''
|
||||||
|
return item;
|
||||||
|
})
|
||||||
|
this.listQuery.total = response.data?.total || 0;
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('获取数据失败:', err);
|
||||||
|
this.tableData = [];
|
||||||
|
this.listQuery.total = 0;
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.dataListLoading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
// 每页数变更
|
||||||
|
sizeChangeHandle(val) {
|
||||||
|
this.listQuery.pageSize = val;
|
||||||
|
this.listQuery.pageNo = 1;
|
||||||
|
this.getDataList();
|
||||||
|
},
|
||||||
|
// 当前页变更
|
||||||
|
currentChangeHandle(val) {
|
||||||
|
this.listQuery.pageNo = val;
|
||||||
|
this.getDataList();
|
||||||
|
},
|
||||||
|
// 导出处理
|
||||||
|
handleExport() {
|
||||||
|
const params = { ...this.listQuery };
|
||||||
|
// 移除分页参数
|
||||||
|
delete params.pageNo;
|
||||||
|
delete params.pageSize;
|
||||||
|
delete params.total;
|
||||||
|
|
||||||
|
this.$modal.confirm('是否确认导出原片报表?')
|
||||||
|
.then(() => {
|
||||||
|
this.exportLoading = true;
|
||||||
|
return exportCostOriginRadioHisData(params);
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
this.$download.excel(response, '原片报表.xls');
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('导出失败:', err);
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
this.exportLoading = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// Vue2 中监听数据变化(如需)
|
||||||
|
watch: {
|
||||||
|
'listQuery.statisticType'(newVal) {
|
||||||
|
console.log('报表类型变更:', newVal);
|
||||||
|
// 可添加类型变更后的额外逻辑
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.app-container {
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-data-bg {
|
||||||
|
height: 400px;
|
||||||
|
background-color: #f5f7fa;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: #999;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-aside {
|
||||||
|
margin-bottom: 16px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
274
src/views/core/monitoring/rawFilmReport/searchBar.vue
Normal file
274
src/views/core/monitoring/rawFilmReport/searchBar.vue
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
<template>
|
||||||
|
<div class="searchBarBox divHeight" ref="searchBarRef" :style="{ paddingRight: isFold ? '55px' : '0px' }">
|
||||||
|
<el-form :inline="true" ref="searchBarForm" :model="formInline" class="searchBar">
|
||||||
|
<span class="blue-block" v-if="removeBlue ? false : true"></span>
|
||||||
|
<template v-for="item in formConfig">
|
||||||
|
<el-form-item v-if="item.type !== ''" :key="item.param" :label="item.label ? item.label : ''"
|
||||||
|
:required="item.required ? item.required : false">
|
||||||
|
<el-input v-if="item.type === 'input'" v-model="formInline[item.param]"
|
||||||
|
:size="item.size ? item.size : 'small'" clearable :disabled="item.disabled ? item.disabled : false"
|
||||||
|
:style="item.width ? 'width:' + item.width + 'px' : 'width:200px'"
|
||||||
|
:placeholder="item.placeholder ? item.placeholder : ''" />
|
||||||
|
<el-select v-if="item.type === 'select'" v-model="formInline[item.param]"
|
||||||
|
:size="item.size ? item.size : 'small'" :filterable="item.filterable ? item.filterable : false"
|
||||||
|
:multiple="item.multiple ? item.multiple : false" :clearable="item.clearable === false ? false : true"
|
||||||
|
:style="item.width ? 'width:' + item.width + 'px' : 'width:200px'" :placeholder="item.label" @change="
|
||||||
|
item.onchange
|
||||||
|
? $emit('select-changed', {
|
||||||
|
param: item.param,
|
||||||
|
value: formInline[item.param]
|
||||||
|
})
|
||||||
|
: null
|
||||||
|
">
|
||||||
|
<el-option v-for="(sub, i) in item.selectOptions" :key="i"
|
||||||
|
:label="item.labelField ? sub[item.labelField] : sub['name']"
|
||||||
|
:value="item.valueField ? sub[item.valueField] : sub['id']" />
|
||||||
|
</el-select>
|
||||||
|
<el-date-picker v-if="item.type === 'datePicker'" :key="item.param" :size="item.size ? item.size : 'small'"
|
||||||
|
v-model="formInline[item.param]" :type="item.dateType" :format="item.format ? item.format : 'yyyy-MM-dd'"
|
||||||
|
:value-format="item.valueFormat ? item.valueFormat : null" :default-time="item.defaultTime || null"
|
||||||
|
:range-separator="item.rangeSeparator || null" :start-placeholder="item.startPlaceholder || null"
|
||||||
|
:end-placeholder="item.endPlaceholder || null" :placeholder="item.placeholder"
|
||||||
|
:picker-options="item.pickerOptions ? item.pickerOptions : null"
|
||||||
|
:clearable="item.clearable === false ? false : true"
|
||||||
|
:style="item.width ? 'width:' + item.width + 'px' : (item.dateType === 'datetimerange' ? 'width:340px' : (item.dateType === 'daterange' ? 'width:220px' : 'width:140px'))" />
|
||||||
|
<el-autocomplete v-if="item.type === 'autocomplete'" v-model="formInline[item.param]"
|
||||||
|
:value-key="item.valueKey ? item.valueKey : 'value'" :size="item.size ? item.size : 'small'"
|
||||||
|
:fetch-suggestions="item.querySearch" :placeholder="item.placeholder"
|
||||||
|
:clearable="item.clearable === false ? false : true"
|
||||||
|
:style="item.width ? 'width:' + item.width + 'px' : 'width:200px'" filterable />
|
||||||
|
<el-cascader v-if="item.type === 'cascader'" v-model="formInline[item.param]" :options="item.selectOptions"
|
||||||
|
:props="item.cascaderProps" :size="item.size ? item.size : 'small'"
|
||||||
|
:clearable="item.clearable === false ? false : true"
|
||||||
|
:show-all-levels="item.showAllLevels === false ? false : true"
|
||||||
|
:collapse-tags="item.collapseTags === true ? true : false"
|
||||||
|
:style="item.width ? 'width:' + item.width + 'px' : 'width:200px'" @change="
|
||||||
|
item.onChange
|
||||||
|
? $emit('cascader-change', {
|
||||||
|
param: item.param,
|
||||||
|
value: formInline[item.param]
|
||||||
|
})
|
||||||
|
: null
|
||||||
|
"></el-cascader>
|
||||||
|
<el-button v-if="item.type === 'button'" :type="item.color" :size="item.size ? item.size : 'small'"
|
||||||
|
:plain="item.plain ? item.plain : false" :round="item.round ? item.round : false"
|
||||||
|
@click="headBtnClick(item.name)">{{ item.btnName }}</el-button>
|
||||||
|
<span v-if="item.type === 'separate'" class="separateStyle"></span>
|
||||||
|
<!-- 可用于显示其他按钮 -->
|
||||||
|
</el-form-item>
|
||||||
|
</template>
|
||||||
|
<el-form-item>
|
||||||
|
<slot></slot>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
<span v-if="isFold" class="foldClass" @click='switchMode'>
|
||||||
|
{{ isExpand ? '收起' : '展开' }}
|
||||||
|
<i class="iconfont" :class="isExpand ? 'icon-upward' : 'icon-downward'"></i>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'SearchBar',
|
||||||
|
props: {
|
||||||
|
formConfigs: {
|
||||||
|
type: Array,
|
||||||
|
default: () => {
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
removeBlue: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
},
|
||||||
|
isFold: {// 多行模式(默认否)
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
const formInline = {}
|
||||||
|
const formConfig = this.formConfigs
|
||||||
|
let hasExtraOptions = false
|
||||||
|
for (const obj of formConfig) {
|
||||||
|
if (obj.type !== 'button') {
|
||||||
|
if (obj.defaultSelect === false || obj.defaultSelect === 0) {
|
||||||
|
formInline[obj.param] = obj.defaultSelect
|
||||||
|
} else {
|
||||||
|
formInline[obj.param] = obj.defaultSelect || '' // defaultSelect下拉框默认选中项
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (obj.extraOptions) {
|
||||||
|
hasExtraOptions = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
formInline,
|
||||||
|
formConfig,
|
||||||
|
hasExtraOptions,
|
||||||
|
isExpand: false // 是否展开(默认否)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
formConfig: {
|
||||||
|
handler() {
|
||||||
|
for (const obj of this.formConfig) {
|
||||||
|
if (obj.defaultSelect) {
|
||||||
|
this.formInline[obj.param] = obj.defaultSelect
|
||||||
|
} else if (obj.defaultSelect === null) {
|
||||||
|
// 需要手动从外部清除选项缓存的情况,确保在外部配置项中可直接设置null
|
||||||
|
this.formInline[obj.param] = ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
},
|
||||||
|
formInline: {
|
||||||
|
handler: function () {
|
||||||
|
this.$forceUpdate()
|
||||||
|
},
|
||||||
|
deep: true,
|
||||||
|
immediate: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.init()
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
init() {
|
||||||
|
if (this.hasExtraOptions) {
|
||||||
|
// 如果有额外参数就处理,如果没有就算了
|
||||||
|
for (const obj of this.formConfig) {
|
||||||
|
if (obj.extraOptions) {
|
||||||
|
// 注: 对obj.extraOptions的选择是互斥的!
|
||||||
|
this.$watch(
|
||||||
|
`formInline.${obj.param}`,
|
||||||
|
function (newVal) {
|
||||||
|
let deleteCount = 0
|
||||||
|
if (obj.index + 1 < this.formConfig.length) {
|
||||||
|
// 如果obj不是最后一个配置
|
||||||
|
const nextConfig = this.formConfig[obj.index + 1]
|
||||||
|
if (nextConfig.parent && nextConfig.parent === obj.param)
|
||||||
|
deleteCount = 1
|
||||||
|
}
|
||||||
|
const currentConfig = Object.assign(
|
||||||
|
{},
|
||||||
|
obj.extraOptions[newVal]
|
||||||
|
)
|
||||||
|
this.formConfig.splice(
|
||||||
|
obj.index + 1,
|
||||||
|
deleteCount,
|
||||||
|
currentConfig
|
||||||
|
)
|
||||||
|
// 修改 formInline
|
||||||
|
this.$set(this.formInline, currentConfig.param, '')
|
||||||
|
},
|
||||||
|
{ immediate: true }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
headBtnClick(btnName) {
|
||||||
|
this.formInline.btnName = btnName
|
||||||
|
this.$emit('headBtnClick', this.formInline)
|
||||||
|
},
|
||||||
|
resetForm() {
|
||||||
|
this.$refs.searchBarForm.resetFields()
|
||||||
|
const formInline = {}
|
||||||
|
const formConfig = this.formConfigs
|
||||||
|
for (const obj of formConfig) {
|
||||||
|
if (obj.type !== 'button') {
|
||||||
|
if (obj.defaultSelect === false || obj.defaultSelect === 0) {
|
||||||
|
formInline[obj.param] = obj.defaultSelect
|
||||||
|
} else {
|
||||||
|
formInline[obj.param] = obj.defaultSelect || '' // defaultSelect下拉框默认选中项
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.formInline = formInline
|
||||||
|
},
|
||||||
|
switchMode() {// 展开和收起切换
|
||||||
|
this.isExpand = !this.isExpand
|
||||||
|
const element = this.$refs.searchBarRef
|
||||||
|
if (this.isExpand) {
|
||||||
|
element.classList.remove('divHeight')
|
||||||
|
} else {
|
||||||
|
element.classList.add('divHeight')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
.searchBarBox {
|
||||||
|
width: 100%;
|
||||||
|
position: relative;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchBarBox::after {
|
||||||
|
content: "";
|
||||||
|
display: block;
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divHeight {
|
||||||
|
height: 45px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchBar .blue-block {
|
||||||
|
display: inline-block;
|
||||||
|
float: left;
|
||||||
|
width: 4px;
|
||||||
|
height: 16px;
|
||||||
|
background-color: #0B58FF;
|
||||||
|
border-radius: 1px;
|
||||||
|
margin-right: 8px;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchBar .el-form-item {
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchBar .el-date-editor .el-range__icon {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #0B58FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchBar .el-input__prefix .el-icon-date {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #0B58FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchBar .el-input__prefix .el-icon-time {
|
||||||
|
font-size: 16px;
|
||||||
|
color: #0B58FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchBar .separateStyle {
|
||||||
|
display: inline-block;
|
||||||
|
width: 1px;
|
||||||
|
height: 24px;
|
||||||
|
background: #E8E8E8;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchBarBox .foldClass {
|
||||||
|
position: absolute;
|
||||||
|
top: 14px;
|
||||||
|
right: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 12px;
|
||||||
|
color: #0B58FF;
|
||||||
|
}
|
||||||
|
|
||||||
|
.searchBarBox .foldClass .iconfont {
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
65
src/views/equipment/equipmentOverview/SmallTitle.vue
Normal file
65
src/views/equipment/equipmentOverview/SmallTitle.vue
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: zwq
|
||||||
|
* @Date: 2023-08-01 15:27:31
|
||||||
|
* @LastEditors: zwq
|
||||||
|
* @LastEditTime: 2023-08-01 16:25:54
|
||||||
|
* @Description:
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<div :class="[className, { 'p-0': noPadding }]">
|
||||||
|
<slot />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
size: {
|
||||||
|
// 取值范围: xl lg md sm
|
||||||
|
type: String,
|
||||||
|
default: 'de',
|
||||||
|
validator: function (val) {
|
||||||
|
return ['xl', 'lg', 'de', 'md', 'sm'].indexOf(val) !== -1;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
noPadding: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
className: function () {
|
||||||
|
return `${this.size}-title`;
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
$pxls: (xl, 28px) (lg, 24px) (de, 20px) (md, 18px) (sm, 16px);
|
||||||
|
$mgr: 8px;
|
||||||
|
@each $size, $height in $pxls {
|
||||||
|
.#{$size}-title {
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: $height;
|
||||||
|
color: #000;
|
||||||
|
font-weight: 500;
|
||||||
|
font-family: '微软雅黑', 'Microsoft YaHei', Arial, Helvetica, sans-serif;
|
||||||
|
|
||||||
|
&::before {
|
||||||
|
content: '';
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: top;
|
||||||
|
width: 4px;
|
||||||
|
height: $height + 2px;
|
||||||
|
border-radius: 1px;
|
||||||
|
margin-right: $mgr;
|
||||||
|
background-color: #0b58ff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-0 {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
134
src/views/equipment/equipmentOverview/add-or-updata.vue
Normal file
134
src/views/equipment/equipmentOverview/add-or-updata.vue
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog :visible.sync="visible" width="40%">
|
||||||
|
<small-title slot="title" :no-padding="true">
|
||||||
|
{{ this.dataForm.lineId + '·' + this.dataForm.equipmentName }}
|
||||||
|
</small-title>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<div class="visual-part">
|
||||||
|
<base-table :table-props="tableProps"
|
||||||
|
:page="listQuery.pageNo" :limit="listQuery.pageSize" :table-data="tableData">
|
||||||
|
<!-- <method-btn v-if="tableBtn.length" slot="handleBtn" :width="120" label="操作" :method-list="tableBtn"
|
||||||
|
@clickBtn="handleClick" /> -->
|
||||||
|
</base-table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<!-- <div slot="footer" class="dialog-footer">
|
||||||
|
<el-button style="" @click="goback()">取消</el-button>
|
||||||
|
<el-button type="primary" @click="dataFormSubmit()">
|
||||||
|
确定
|
||||||
|
</el-button>
|
||||||
|
</div> -->
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
const tableProps = [
|
||||||
|
|
||||||
|
{
|
||||||
|
prop: 'paramName',
|
||||||
|
label: '参数名称'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'paramValue',
|
||||||
|
label: '当前值',
|
||||||
|
// filter: parseTime,
|
||||||
|
// width: 160
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
import { getParamMonitor } from '@/api/base/equipment';
|
||||||
|
// import { parseTime } from '../../mixins/code-filter';
|
||||||
|
import SmallTitle from './SmallTitle';
|
||||||
|
export default {
|
||||||
|
components: { SmallTitle },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
tableProps,
|
||||||
|
tableData:[],
|
||||||
|
listQuery: {
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize:100,
|
||||||
|
},
|
||||||
|
addOrUpdateVisible: false,
|
||||||
|
dataForm: {
|
||||||
|
equipmentId:undefined,
|
||||||
|
equipmentName: undefined,
|
||||||
|
lineId: undefined,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
init(data) {
|
||||||
|
console.log(data.paramMonitors,'data');
|
||||||
|
|
||||||
|
this.dataForm.equipmentId = data.equipmentId || '';
|
||||||
|
this.dataForm.equipmentName = data.equipmentName || '';
|
||||||
|
this.dataForm.lineId = data.lineId || '';
|
||||||
|
|
||||||
|
|
||||||
|
this.visible = true;
|
||||||
|
this.$nextTick(() => {
|
||||||
|
// this.$refs['dataForm'].resetFields();
|
||||||
|
// getParamMonitor({
|
||||||
|
// equipmentId:this.dataForm.equipmentId
|
||||||
|
// }).then((res) => {
|
||||||
|
this.tableData = data.paramMonitors
|
||||||
|
// })
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.drawer >>> .el-drawer {
|
||||||
|
border-radius: 8px 0 0 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer >>> .el-form-item__label {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer >>> .el-drawer__header {
|
||||||
|
margin: 0;
|
||||||
|
padding: 32px 32px 24px;
|
||||||
|
border-bottom: 1px solid #dcdfe6;
|
||||||
|
}
|
||||||
|
.drawer >>> .el-drawer__body {
|
||||||
|
flex: 1;
|
||||||
|
height: 1px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer >>> .content {
|
||||||
|
padding: 30px 24px;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
/* height: 100%; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer >>> .visual-part {
|
||||||
|
flex: 1 auto;
|
||||||
|
max-height: 76vh;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-y: scroll;
|
||||||
|
padding-right: 10px; /* 调整滚动条样式 */
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer >>> .el-form,
|
||||||
|
.drawer >>> .attr-list {
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-body__footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding: 18px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
563
src/views/equipment/equipmentOverview/alarm-or-updata.vue
Normal file
563
src/views/equipment/equipmentOverview/alarm-or-updata.vue
Normal file
@@ -0,0 +1,563 @@
|
|||||||
|
<template>
|
||||||
|
<el-dialog :visible.sync="visible" width="80%" @close="handleClose" title-class="dialog-title">
|
||||||
|
<small-title slot="title" :no-padding="true">
|
||||||
|
{{ dataForm.lineId + '·' + dataForm.equipmentName }}
|
||||||
|
</small-title>
|
||||||
|
<search-bar removeBlue :formConfigs="formConfig" ref="searchBarForm" @headBtnClick="buttonClick" />
|
||||||
|
<el-tabs class="custom-tabs" v-model="activeLabel" :stretch="true" @tab-click="handleTabClick">
|
||||||
|
<el-tab-pane :label="'\u3000报警时长\u3000'" name="duration"></el-tab-pane>
|
||||||
|
<el-tab-pane :label="'\u3000报警次数\u3000'" name="times"></el-tab-pane>
|
||||||
|
</el-tabs>
|
||||||
|
<div class="content">
|
||||||
|
<div class="visual-part">
|
||||||
|
<div v-if="hasData" style="display: flex; justify-content: space-around; gap: 20px; padding: 10px 0;">
|
||||||
|
<!-- 移除 v-if,始终渲染两个图表容器 -->
|
||||||
|
<div id="barChart" style="width: 48%; height: 400px;"></div>
|
||||||
|
<div id="pieChart" style="width: 48%; height: 400px;"></div>
|
||||||
|
</div>
|
||||||
|
<div v-if="!hasData" class="no-data">
|
||||||
|
<el-empty description="暂无相关报警数据"></el-empty>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</el-dialog>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getAlarmDet } from '@/api/base/equipment';
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
import SmallTitle from './SmallTitle';
|
||||||
|
|
||||||
|
const CHART_CONFIG = {
|
||||||
|
barColor: '#288AFF',
|
||||||
|
pieColors: [
|
||||||
|
'#288AFF', '#4096FF', '#69B1FF', '#91CFFF', '#B8E0FF',
|
||||||
|
'#E0F2FF', '#1890FF', '#096DD9', '#0050B3', '#003A8C'
|
||||||
|
],
|
||||||
|
fontColor: '#333',
|
||||||
|
lightFontColor: '#666',
|
||||||
|
borderRadius: 4
|
||||||
|
};
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: { SmallTitle },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
hasData: false,
|
||||||
|
listQuery: {
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 100,
|
||||||
|
equipmentId: undefined,
|
||||||
|
startTime: undefined,
|
||||||
|
endTime: undefined
|
||||||
|
},
|
||||||
|
formConfig: [
|
||||||
|
{
|
||||||
|
type: 'datePicker',
|
||||||
|
label: '时间段',
|
||||||
|
dateType: 'daterange',
|
||||||
|
format: 'yyyy-MM-dd',
|
||||||
|
valueFormat: 'timestamp',
|
||||||
|
rangeSeparator: '-',
|
||||||
|
startPlaceholder: '开始时间',
|
||||||
|
endPlaceholder: '结束时间',
|
||||||
|
param: 'timeVal',
|
||||||
|
defaultTime: ['00:00:00', '23:59:59'],
|
||||||
|
defaultSelect: []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
btnName: '查询',
|
||||||
|
name: 'search',
|
||||||
|
color: 'primary'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
activeLabel: 'duration', // 默认选中「报警时长」
|
||||||
|
dataForm: {
|
||||||
|
equipmentId: undefined,
|
||||||
|
equipmentName: undefined,
|
||||||
|
lineId: undefined
|
||||||
|
},
|
||||||
|
chartInstances: {
|
||||||
|
bar: null,
|
||||||
|
pie: null
|
||||||
|
},
|
||||||
|
isDomReady: false,
|
||||||
|
originData: null // 存储原始数据
|
||||||
|
};
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.isDomReady = true;
|
||||||
|
if (this.listQuery.equipmentId) {
|
||||||
|
this.getDataList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
// Tab 切换时自动刷新图表(无需额外操作,依赖 handleTabClick 触发查询)
|
||||||
|
activeLabel() {
|
||||||
|
if (this.isDomReady && this.originData) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.renderBothCharts(); // 切换 Tab 后重新渲染两个图表
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initDefaultDate() {
|
||||||
|
const today = new Date();
|
||||||
|
const start = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 0, 0, 0, 0).getTime();
|
||||||
|
const end = new Date(today.getFullYear(), today.getMonth(), today.getDate(), 23, 59, 59, 0).getTime();
|
||||||
|
|
||||||
|
this.formConfig[0].defaultSelect = [start, end];
|
||||||
|
this.listQuery.startTime = start;
|
||||||
|
this.listQuery.endTime = end;
|
||||||
|
|
||||||
|
// 修复点1:增加多层判断,确保对象存在后再赋值
|
||||||
|
if (this.$refs.searchBarForm && this.$refs.searchBarForm.form) {
|
||||||
|
this.$refs.searchBarForm.form.timeVal = [start, end];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
handleTabClick() {
|
||||||
|
// 切换 Tab 时重新查询数据(或直接复用已有数据渲染)
|
||||||
|
this.getDataList();
|
||||||
|
},
|
||||||
|
|
||||||
|
buttonClick(val) {
|
||||||
|
switch (val.btnName) {
|
||||||
|
case 'search':
|
||||||
|
this.listQuery.startTime = val.timeVal?.[0];
|
||||||
|
this.listQuery.endTime = val.timeVal?.[1];
|
||||||
|
this.getDataList();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
async getDataList() {
|
||||||
|
try {
|
||||||
|
if (!this.listQuery.equipmentId) {
|
||||||
|
console.warn('设备ID不能为空');
|
||||||
|
this.hasData = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const queryParams = {
|
||||||
|
equipmentId: this.listQuery.equipmentId,
|
||||||
|
startTime: this.listQuery.startTime,
|
||||||
|
endTime: this.listQuery.endTime,
|
||||||
|
};
|
||||||
|
|
||||||
|
const res = await getAlarmDet(queryParams);
|
||||||
|
const originData = res.data || [];
|
||||||
|
this.originData = originData;
|
||||||
|
this.hasData = originData.length > 0;
|
||||||
|
|
||||||
|
if (this.hasData && this.isDomReady) {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.renderBothCharts(); // 数据查询成功后,同时渲染两个图表
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.destroyAllCharts();
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('获取报警数据失败:', error);
|
||||||
|
this.hasData = false;
|
||||||
|
this.destroyAllCharts();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 核心方法:同时渲染柱状图和饼图(根据当前 Tab 类型)
|
||||||
|
renderBothCharts() {
|
||||||
|
if (this.activeLabel === 'duration') {
|
||||||
|
// 报警时长:柱状图(时长排序)+ 饼图(时长占比)
|
||||||
|
this.renderBarChart('duration');
|
||||||
|
this.renderPieChart('duration');
|
||||||
|
} else {
|
||||||
|
// 报警次数:柱状图(次数排序)+ 饼图(次数占比)
|
||||||
|
this.renderBarChart('times');
|
||||||
|
this.renderPieChart('times');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 渲染柱状图(支持两种数据类型)
|
||||||
|
renderBarChart(type) {
|
||||||
|
this.destroyChart('bar');
|
||||||
|
const chartDom = document.getElementById('barChart');
|
||||||
|
if (!chartDom || !this.originData.length) return;
|
||||||
|
|
||||||
|
// 根据类型排序和提取数据
|
||||||
|
let sortedData, xData, seriesData, yAxisName;
|
||||||
|
if (type === 'duration') {
|
||||||
|
// 报警时长:按时长降序
|
||||||
|
sortedData = [...this.originData].sort((a, b) => b.alarmDuration - a.alarmDuration);
|
||||||
|
seriesData = sortedData.map(item => item.alarmDuration);
|
||||||
|
yAxisName = '报警时长';
|
||||||
|
} else {
|
||||||
|
// 报警次数:按次数降序
|
||||||
|
sortedData = [...this.originData].sort((a, b) => b.alarmCount - a.alarmCount);
|
||||||
|
seriesData = sortedData.map(item => item.alarmCount);
|
||||||
|
yAxisName = '报警次数';
|
||||||
|
}
|
||||||
|
|
||||||
|
xData = sortedData.map(item => this.truncateText(item.alarmContent, 8));
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.chartInstances.bar = echarts.init(chartDom);
|
||||||
|
const option = {
|
||||||
|
title: {
|
||||||
|
text: `${yAxisName}统计(柱状图)`,
|
||||||
|
left: 'center',
|
||||||
|
textStyle: { fontSize: 14, color: CHART_CONFIG.fontColor }
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: { type: 'shadow' },
|
||||||
|
padding: 10,
|
||||||
|
textStyle: { fontSize: 11 },
|
||||||
|
formatter: (params) => {
|
||||||
|
const index = params[0].dataIndex;
|
||||||
|
const item = sortedData[index];
|
||||||
|
return `
|
||||||
|
<div style="text-align: left;">
|
||||||
|
<div>${item.alarmContent}</div>
|
||||||
|
<div>${yAxisName}:${type === 'duration' ? item.alarmDuration : item.alarmCount}</div>
|
||||||
|
<div>占比:${type === 'duration' ? item.alarmDurationRatio.toFixed(2) : item.alarmCountRatio.toFixed(2)}%</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '5%',
|
||||||
|
right: '5%',
|
||||||
|
bottom: '18%',
|
||||||
|
top: '15%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
data: xData,
|
||||||
|
axisTick: { alignWithLabel: true },
|
||||||
|
axisLabel: {
|
||||||
|
interval: 0,
|
||||||
|
fontSize: 12,
|
||||||
|
color: CHART_CONFIG.lightFontColor
|
||||||
|
},
|
||||||
|
axisLine: { lineStyle: { color: '#e8e8e8' } }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'value',
|
||||||
|
name: yAxisName,
|
||||||
|
nameTextStyle: { fontSize: 11, color: CHART_CONFIG.lightFontColor },
|
||||||
|
axisLabel: {
|
||||||
|
fontSize: 11,
|
||||||
|
color: CHART_CONFIG.lightFontColor,
|
||||||
|
},
|
||||||
|
axisLine: { lineStyle: { color: '#e8e8e8' } },
|
||||||
|
splitLine: { lineStyle: { color: '#f5f5f5' } },
|
||||||
|
max: (value) => value.max * 1.2
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: yAxisName,
|
||||||
|
type: 'bar',
|
||||||
|
itemStyle: {
|
||||||
|
color: CHART_CONFIG.barColor,
|
||||||
|
borderRadius: [CHART_CONFIG.borderRadius, CHART_CONFIG.borderRadius, 0, 0],
|
||||||
|
shadowBlur: 3,
|
||||||
|
shadowColor: 'rgba(40, 138, 255, 0.2)',
|
||||||
|
shadowOffsetY: 2
|
||||||
|
},
|
||||||
|
barWidth: '16',
|
||||||
|
data: seriesData,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'top',
|
||||||
|
distance: 6,
|
||||||
|
fontSize: 11,
|
||||||
|
color: CHART_CONFIG.fontColor,
|
||||||
|
formatter: (params) => `${params.value}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
this.chartInstances.bar.setOption(option);
|
||||||
|
this.addResizeListener('bar');
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`${yAxisName}柱状图初始化失败:`, error);
|
||||||
|
setTimeout(() => this.renderBarChart(type), 200);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 渲染饼图(支持两种数据类型)
|
||||||
|
renderPieChart(type) {
|
||||||
|
this.destroyChart('pie');
|
||||||
|
const chartDom = document.getElementById('pieChart');
|
||||||
|
if (!chartDom || !this.originData.length) return;
|
||||||
|
|
||||||
|
// 根据类型处理饼图数据
|
||||||
|
let pieData, seriesName;
|
||||||
|
if (type === 'duration') {
|
||||||
|
// 报警时长:按时长占比处理
|
||||||
|
seriesName = '报警时长';
|
||||||
|
pieData = this.handlePieData(this.originData, 'alarmDuration', 'alarmDurationRatio');
|
||||||
|
} else {
|
||||||
|
// 报警次数:按次数占比处理
|
||||||
|
seriesName = '报警次数';
|
||||||
|
pieData = this.handlePieData(this.originData, 'alarmCount', 'alarmCountRatio');
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
this.chartInstances.pie = echarts.init(chartDom);
|
||||||
|
const option = {
|
||||||
|
title: {
|
||||||
|
text: `${seriesName}统计(饼图)`,
|
||||||
|
left: 'center',
|
||||||
|
textStyle: { fontSize: 14, color: CHART_CONFIG.fontColor }
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
padding: 10,
|
||||||
|
textStyle: { fontSize: 11 },
|
||||||
|
formatter: (params) => {
|
||||||
|
return `
|
||||||
|
<div style="text-align: left;">
|
||||||
|
<div>${params.name}</div>
|
||||||
|
<div>${seriesName}:${params.value}${type === 'duration' ? '' : '次'}</div>
|
||||||
|
<div>占比:${params.percent.toFixed(2)}%</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: seriesName,
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['50%', '70%'],
|
||||||
|
center: ['50%', '55%'],
|
||||||
|
color: CHART_CONFIG.pieColors,
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
position: 'outside',
|
||||||
|
distance: 15,
|
||||||
|
fontSize: 11,
|
||||||
|
color: CHART_CONFIG.lightFontColor,
|
||||||
|
formatter: (params) => {
|
||||||
|
const truncatedName = this.truncateText(params.name, 8);
|
||||||
|
return `${truncatedName}(${params.value}${type === 'duration' ? '' : '次'}, ${params.percent.toFixed(1)}%)`;
|
||||||
|
},
|
||||||
|
align: 'center',
|
||||||
|
baseline: 'middle'
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: true,
|
||||||
|
length: 15,
|
||||||
|
length2: 20,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#ccc',
|
||||||
|
width: 1,
|
||||||
|
type: 'solid'
|
||||||
|
},
|
||||||
|
smooth: 0.2
|
||||||
|
},
|
||||||
|
data: pieData,
|
||||||
|
emphasis: {
|
||||||
|
itemStyle: {
|
||||||
|
shadowBlur: 10,
|
||||||
|
shadowColor: 'rgba(0, 0, 0, 0.1)'
|
||||||
|
},
|
||||||
|
label: {
|
||||||
|
color: CHART_CONFIG.fontColor,
|
||||||
|
fontSize: 12,
|
||||||
|
fontWeight: 500
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: CHART_CONFIG.barColor,
|
||||||
|
width: 1.5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
this.chartInstances.pie.setOption(option);
|
||||||
|
this.addResizeListener('pie');
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`${seriesName}饼图初始化失败:`, error);
|
||||||
|
setTimeout(() => this.renderPieChart(type), 200);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// 通用饼图数据处理(支持动态字段)
|
||||||
|
handlePieData(data, valueKey, ratioKey) {
|
||||||
|
const threshold = 5; // 占比低于5%合并为「其他」
|
||||||
|
let otherCount = 0;
|
||||||
|
const mainData = data.filter(item => {
|
||||||
|
if (item[ratioKey] >= threshold) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
otherCount += item[valueKey];
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}).map(item => ({
|
||||||
|
name: item.alarmContent,
|
||||||
|
value: item[valueKey],
|
||||||
|
ratio: item[ratioKey]
|
||||||
|
}));
|
||||||
|
|
||||||
|
if (otherCount > 0) {
|
||||||
|
mainData.push({
|
||||||
|
name: '其他',
|
||||||
|
value: otherCount,
|
||||||
|
ratio: 100 - mainData.reduce((sum, item) => sum + item.ratio, 0)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return mainData;
|
||||||
|
},
|
||||||
|
|
||||||
|
truncateText(text, maxLength) {
|
||||||
|
if (!text) return '';
|
||||||
|
return text.length > maxLength ? text.slice(0, maxLength) + '...' : text;
|
||||||
|
},
|
||||||
|
|
||||||
|
addResizeListener(type) {
|
||||||
|
const chart = this.chartInstances[type];
|
||||||
|
if (chart) {
|
||||||
|
const resizeHandler = () => chart.resize();
|
||||||
|
window.addEventListener('resize', resizeHandler);
|
||||||
|
chart.resizeHandler = resizeHandler;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
destroyChart(type) {
|
||||||
|
const chart = this.chartInstances[type];
|
||||||
|
if (chart) {
|
||||||
|
window.removeEventListener('resize', chart.resizeHandler);
|
||||||
|
chart.dispose();
|
||||||
|
this.chartInstances[type] = null;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
destroyAllCharts() {
|
||||||
|
Object.keys(this.chartInstances).forEach(type => {
|
||||||
|
this.destroyChart(type);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
handleClose() {
|
||||||
|
this.destroyAllCharts();
|
||||||
|
this.formConfig[0].defaultSelect = [];
|
||||||
|
this.listQuery.startTime = undefined;
|
||||||
|
this.listQuery.endTime = undefined;
|
||||||
|
this.originData = null;
|
||||||
|
this.hasData = true;
|
||||||
|
// 修复点2:增加多层判断,确保对象存在后再赋值
|
||||||
|
if (this.$refs.searchBarForm && this.$refs.searchBarForm.form) {
|
||||||
|
this.$refs.searchBarForm.form.timeVal = [];
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
init(data) {
|
||||||
|
this.dataForm = {
|
||||||
|
equipmentId: data.equipmentId || '',
|
||||||
|
equipmentName: data.equipmentName || '',
|
||||||
|
lineId: data.lineId || ''
|
||||||
|
};
|
||||||
|
this.activeLabel = 'duration'
|
||||||
|
this.listQuery.equipmentId = data.equipmentId || undefined;
|
||||||
|
this.visible = true;
|
||||||
|
this.originData = null;
|
||||||
|
this.hasData = false;
|
||||||
|
|
||||||
|
this.initDefaultDate();
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.isDomReady = true;
|
||||||
|
this.getDataList();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy() {
|
||||||
|
this.destroyAllCharts();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* 保持原有样式,优化图表容器布局 */
|
||||||
|
.drawer>>>.el-drawer {
|
||||||
|
border-radius: 8px 0 0 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer>>>.el-form-item__label {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer>>>.el-drawer__header {
|
||||||
|
margin: 0;
|
||||||
|
padding: 32px 32px 24px;
|
||||||
|
border-bottom: 1px solid #dcdfe6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer>>>.el-drawer__body {
|
||||||
|
flex: 1;
|
||||||
|
height: 1px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer>>>.content {
|
||||||
|
padding: 30px 24px;
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer>>>.visual-part {
|
||||||
|
flex: 1 auto;
|
||||||
|
max-height: 76vh;
|
||||||
|
overflow: hidden;
|
||||||
|
padding: 10px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 优化图表容器响应式布局 */
|
||||||
|
@media (max-width: 1200px) {
|
||||||
|
.visual-part>div {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
#barChart,
|
||||||
|
#pieChart {
|
||||||
|
width: 100% !important;
|
||||||
|
height: 350px !important;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer>>>.el-form,
|
||||||
|
.drawer>>>.attr-list {
|
||||||
|
padding: 0 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.drawer-body__footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
padding: 18px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
1308
src/views/equipment/equipmentOverview/index.vue
Normal file
1308
src/views/equipment/equipmentOverview/index.vue
Normal file
File diff suppressed because it is too large
Load Diff
309
src/views/quality/dpdda/defectAnalysis.vue
Normal file
309
src/views/quality/dpdda/defectAnalysis.vue
Normal file
@@ -0,0 +1,309 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<!-- 搜索工作栏 -->
|
||||||
|
<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" label="操作" :width="120" :method-list="tableBtn"
|
||||||
|
@clickBtn="handleTableBtnClick" /> -->
|
||||||
|
</base-table>
|
||||||
|
|
||||||
|
<!-- 分页组件 -->
|
||||||
|
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||||
|
@pagination="getList" />
|
||||||
|
|
||||||
|
<!-- 对话框(添加 / 修改) -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getPdList,
|
||||||
|
} from '@/api/core/monitoring/auto';
|
||||||
|
import { getFactoryPage } from '@/api/core/base/factory';
|
||||||
|
import basicPageMixin from '@/mixins/lb/basicPageMixin';
|
||||||
|
import { getDefectAnalysis } from '@/api/monitoring/defectSummary';
|
||||||
|
import * as XLSX from 'xlsx'
|
||||||
|
import FileSaver from 'file-saver'
|
||||||
|
export default {
|
||||||
|
name: 'QualityInspectionType',
|
||||||
|
mixins: [basicPageMixin],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// tableBtn: [
|
||||||
|
// this.$auth.hasPermi('base:quality-inspection-type:update')
|
||||||
|
// ? {
|
||||||
|
// type: 'edit',
|
||||||
|
// btnName: '修改',
|
||||||
|
// }
|
||||||
|
// : undefined,
|
||||||
|
// this.$auth.hasPermi('base:quality-inspection-type: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: 'factoryName', label: '工厂' },
|
||||||
|
{ prop: 'lineName', label: '产线' },
|
||||||
|
{ prop: 'remark', label: '玻璃编号' },
|
||||||
|
{
|
||||||
|
prop: 'checkTime',
|
||||||
|
label: '检测时间',
|
||||||
|
fixed: true,
|
||||||
|
width: 180,
|
||||||
|
filter: (val) => moment(val).format('yyyy-MM-DD HH:mm:ss'),
|
||||||
|
},
|
||||||
|
{ prop: 'checkNum', label: '缺陷数' },
|
||||||
|
{
|
||||||
|
prop: 'glassGrade',
|
||||||
|
label: '等级',
|
||||||
|
filter: (val) => val === 0 ? '合格' : val === 1 ? '提示' : val === 2 ? '返修' : val === 3 ? '报废' : ''
|
||||||
|
},
|
||||||
|
{ prop: 'reason', label: '判等原因' },
|
||||||
|
{ prop: 'specifications', label: '规格' },
|
||||||
|
|
||||||
|
|
||||||
|
// {
|
||||||
|
// label: '操作',
|
||||||
|
// alignt: 'center',
|
||||||
|
// subcomponent: {
|
||||||
|
// render: function (h) {
|
||||||
|
// return h('div', null, [
|
||||||
|
// h(
|
||||||
|
// 'el-button',
|
||||||
|
// {
|
||||||
|
// props: {
|
||||||
|
// icon: 'el-icon-edit',
|
||||||
|
// size: 'mini',
|
||||||
|
// type: 'text',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// ' 修改'
|
||||||
|
// ),
|
||||||
|
// h(
|
||||||
|
// 'el-button',
|
||||||
|
// {
|
||||||
|
// props: {
|
||||||
|
// icon: 'el-icon-edit',
|
||||||
|
// size: 'mini',
|
||||||
|
// type: 'text',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// ' 修改'
|
||||||
|
// ),
|
||||||
|
// ]);
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
],
|
||||||
|
//
|
||||||
|
searchBarFormConfig: [
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '工厂',
|
||||||
|
selectOptions: [],
|
||||||
|
param: 'factoryId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '产线',
|
||||||
|
selectOptions: [],
|
||||||
|
param: 'lineId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'input',
|
||||||
|
label: '缺陷数>',
|
||||||
|
// selectOptions: [],
|
||||||
|
param: 'checkNum',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'datePicker',
|
||||||
|
label: '时间范围',
|
||||||
|
dateType: 'datetimerange',
|
||||||
|
format: 'yyyy-MM-dd HH:mm:ss',
|
||||||
|
// valueFormat: 'timestamp',
|
||||||
|
valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
||||||
|
rangeSeparator: '-',
|
||||||
|
startPlaceholder: '开始时间',
|
||||||
|
endPlaceholder: '结束时间',
|
||||||
|
param: 'timeVal',
|
||||||
|
width: 350
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
btnName: '查询',
|
||||||
|
name: 'search',
|
||||||
|
color: 'primary',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// type: 'button',
|
||||||
|
// btnName: '重置',
|
||||||
|
// name: 'reset',
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
type: 'separate',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// type: this.$auth.hasPermi('base:quality-inspection-type:create')
|
||||||
|
// ? 'button'
|
||||||
|
// : '',
|
||||||
|
// btnName: '新增',
|
||||||
|
// name: 'add',
|
||||||
|
// plain: true,
|
||||||
|
// color: 'success',
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
type: this.$auth.hasPermi('base:quality-inspection-type:export')
|
||||||
|
? 'button'
|
||||||
|
: '',
|
||||||
|
btnName: '导出',
|
||||||
|
name: 'export',
|
||||||
|
color: 'warning',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
// 表单配置
|
||||||
|
// formRows: [
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// input: true,
|
||||||
|
// label: '检测类型名称',
|
||||||
|
// prop: 'name',
|
||||||
|
// rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||||
|
// // bind: {
|
||||||
|
// // disabled: true, // some condition, like detail mode...
|
||||||
|
// // }
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// [{ input: true, label: '检测类型编码', prop: 'code' }],
|
||||||
|
// [{ input: true, label: '备注', prop: 'remark' }],
|
||||||
|
// ],
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
lineId: undefined,
|
||||||
|
factoryId: undefined,
|
||||||
|
checkNum: undefined,
|
||||||
|
startTime: undefined,
|
||||||
|
endTime: undefined,
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// watch: {
|
||||||
|
// form: {
|
||||||
|
// handler: (val) => {
|
||||||
|
// console.log('form changed', val);
|
||||||
|
// },
|
||||||
|
// deep: true
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
created() {
|
||||||
|
this.getList();
|
||||||
|
this.getDict()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getDict() {
|
||||||
|
getPdList().then(res => {
|
||||||
|
this.searchBarFormConfig[1].selectOptions = res.data || [];
|
||||||
|
});
|
||||||
|
|
||||||
|
getFactoryPage({ pageSize: 100, pageNo: 1 }).then(res => {
|
||||||
|
this.searchBarFormConfig[0].selectOptions = res.data.list || [];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** base table related */
|
||||||
|
handleTableBtnClick({ data, type }) {
|
||||||
|
switch (type) {
|
||||||
|
case 'edit':
|
||||||
|
this.handleUpdate(data);
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
this.handleDelete(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** search bar related */
|
||||||
|
handleSearchBarBtnClick(btn) {
|
||||||
|
// const keys = ['name'];
|
||||||
|
switch (btn.btnName) {
|
||||||
|
case 'search':
|
||||||
|
this.queryParams.lineId = btn.lineId ? btn.lineId : undefined
|
||||||
|
this.queryParams.factoryId = btn.factoryId ? btn.factoryId : undefined
|
||||||
|
this.queryParams.startTime = btn.timeVal ? btn.timeVal[0] : undefined
|
||||||
|
this.queryParams.endTime = btn.timeVal ? btn.timeVal[1] : undefined
|
||||||
|
this.queryParams.checkNum = btn.checkNum ? btn.checkNum : undefined
|
||||||
|
|
||||||
|
|
||||||
|
// keys.forEach((key) => {
|
||||||
|
// this.queryParams[key] = btn[key] || null;
|
||||||
|
// });
|
||||||
|
this.getList();
|
||||||
|
break;
|
||||||
|
case 'add':
|
||||||
|
this.handleAdd();
|
||||||
|
break;
|
||||||
|
case 'export':
|
||||||
|
this.handleExport();
|
||||||
|
break;
|
||||||
|
// case 'reset':
|
||||||
|
// this.$refs['search-bar'].resetForm();
|
||||||
|
// this.resetQuery();
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 查询列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true;
|
||||||
|
// 执行查询
|
||||||
|
getDefectAnalysis(this.queryParams).then((response) => {
|
||||||
|
this.list = response.data.list;
|
||||||
|
this.total = response.data.total;
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
handleExport() {
|
||||||
|
// 处理查询参数
|
||||||
|
let tables = document.querySelector('.el-table').cloneNode(true)
|
||||||
|
const fix = tables.querySelector('.el-table__fixed')
|
||||||
|
const fixRight = tables.querySelector('.el-table__fixed-right')
|
||||||
|
if (fix) {
|
||||||
|
tables.removeChild(tables.querySelector('.el-table__fixed'))
|
||||||
|
}
|
||||||
|
if (fixRight) {
|
||||||
|
tables.removeChild(tables.querySelector('.el-table__fixed-right'))
|
||||||
|
}
|
||||||
|
let exportTable = XLSX.utils.table_to_book(tables)
|
||||||
|
|
||||||
|
var exportTableOut = XLSX.write(exportTable, {
|
||||||
|
bookType: 'xlsx', bookSST: true, type: 'array'
|
||||||
|
})
|
||||||
|
// sheetjs.xlsx为导出表格的标题名称
|
||||||
|
try {
|
||||||
|
FileSaver.saveAs(new Blob([exportTableOut], {
|
||||||
|
type: 'application/octet-stream'
|
||||||
|
}),'缺陷分析.xlsx')
|
||||||
|
} catch (e) {
|
||||||
|
if (typeof console !== 'undefined') console.log(e, exportTableOut)
|
||||||
|
}
|
||||||
|
return exportTableOut
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
560
src/views/quality/dpdda/defectSummary.vue
Normal file
560
src/views/quality/dpdda/defectSummary.vue
Normal file
@@ -0,0 +1,560 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<!-- 搜索工作栏 -->
|
||||||
|
<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" label="操作" :width="120" :method-list="tableBtn"
|
||||||
|
@clickBtn="handleTableBtnClick" />
|
||||||
|
</base-table>
|
||||||
|
|
||||||
|
<!-- 分页组件 -->
|
||||||
|
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||||
|
@pagination="getList" />
|
||||||
|
<div v-if="chartData" class="charts-container">
|
||||||
|
<div v-for="(lineData, lineName) in chartData" :key="lineName" class="chart-wrapper">
|
||||||
|
<div class="blue-block"></div>
|
||||||
|
<h3 class="chart-title">{{ lineName }}</h3>
|
||||||
|
<div :id="`chart-${lineName}`" class="chart" style="width: 100%; height: 300px;"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<defect-summary-det ref="defectSummaryDetRef" v-if="defectVis" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import moment from 'moment';
|
||||||
|
|
||||||
|
import {
|
||||||
|
getPdList,
|
||||||
|
} from '@/api/core/monitoring/auto';
|
||||||
|
import { getFactoryPage } from '@/api/core/base/factory';
|
||||||
|
import { getDefectSummaryTable, getDefectSummaryChart } from '@/api/monitoring/defectSummary';
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
import basicPageMixin from '@/mixins/lb/basicPageMixin';
|
||||||
|
import defectSummaryDet from './defectSummaryDet.vue'
|
||||||
|
export default {
|
||||||
|
name: 'QualityInspectionType',
|
||||||
|
mixins: [basicPageMixin],
|
||||||
|
components: {
|
||||||
|
defectSummaryDet
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tableBtn: [
|
||||||
|
this.$auth.hasPermi('base:quality-inspection-type:update')
|
||||||
|
? {
|
||||||
|
type: 'detail',
|
||||||
|
btnName: '缺陷详情',
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
// this.$auth.hasPermi('base:quality-inspection-type: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: 'factoryName', label: '工厂' },
|
||||||
|
{ prop: 'lineName', label: '产线' },
|
||||||
|
{ prop: 'glassNum', label: '玻璃总数' },
|
||||||
|
{
|
||||||
|
prop: 'okNum',
|
||||||
|
label: '合格品数',
|
||||||
|
},
|
||||||
|
{ prop: 'okRate', label: '合格百分比' },
|
||||||
|
{ prop: 'repairNum', label: '返修品数' },
|
||||||
|
{ prop: 'repairRate', label: '返修百分比' },
|
||||||
|
{ prop: 'ngNum', label: '废片数' },
|
||||||
|
{ prop: 'ngRate', label: '废片百分比' },
|
||||||
|
{ prop: 'oneNgNum', label: '1类缺陷玻璃数量' },
|
||||||
|
{ prop: 'twoNgNum', label: '2类缺陷玻璃数量' },
|
||||||
|
{ prop: 'threeNgNum', label: '3类缺陷玻璃数量' },
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// {
|
||||||
|
// label: '操作',
|
||||||
|
// alignt: 'center',
|
||||||
|
// subcomponent: {
|
||||||
|
// render: function (h) {
|
||||||
|
// return h('div', null, [
|
||||||
|
// h(
|
||||||
|
// 'el-button',
|
||||||
|
// {
|
||||||
|
// props: {
|
||||||
|
// icon: 'el-icon-edit',
|
||||||
|
// size: 'mini',
|
||||||
|
// type: 'text',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// ' 修改'
|
||||||
|
// ),
|
||||||
|
// h(
|
||||||
|
// 'el-button',
|
||||||
|
// {
|
||||||
|
// props: {
|
||||||
|
// icon: 'el-icon-edit',
|
||||||
|
// size: 'mini',
|
||||||
|
// type: 'text',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// ' 修改'
|
||||||
|
// ),
|
||||||
|
// ]);
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
],
|
||||||
|
//
|
||||||
|
searchBarFormConfig: [
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '工厂',
|
||||||
|
selectOptions: [],
|
||||||
|
param: 'factoryId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '产线',
|
||||||
|
selectOptions: [],
|
||||||
|
multiple: true,
|
||||||
|
param: 'lineId',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// type: 'input',
|
||||||
|
// label: '缺陷数>',
|
||||||
|
// // selectOptions: [],
|
||||||
|
// param: 'number',
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
type: 'datePicker',
|
||||||
|
label: '时间范围',
|
||||||
|
dateType: 'datetimerange',
|
||||||
|
format: 'yyyy-MM-dd HH:mm:ss',
|
||||||
|
// valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
||||||
|
valueFormat: 'timestamp',
|
||||||
|
defaultTime: ['00:00:00', '23:59:59'],
|
||||||
|
rangeSeparator: '-',
|
||||||
|
startPlaceholder: '开始时间',
|
||||||
|
endPlaceholder: '结束时间',
|
||||||
|
param: 'timeVal',
|
||||||
|
width: 350
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
btnName: '查询',
|
||||||
|
name: 'search',
|
||||||
|
color: 'primary',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// type: 'button',
|
||||||
|
// btnName: '重置',
|
||||||
|
// name: 'reset',
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
type: 'separate',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// type: this.$auth.hasPermi('base:quality-inspection-type:create')
|
||||||
|
// ? 'button'
|
||||||
|
// : '',
|
||||||
|
// btnName: '新增',
|
||||||
|
// name: 'add',
|
||||||
|
// plain: true,
|
||||||
|
// color: 'success',
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
type: this.$auth.hasPermi('base:quality-inspection-type:export')
|
||||||
|
? 'button'
|
||||||
|
: '',
|
||||||
|
btnName: '导出',
|
||||||
|
name: 'export',
|
||||||
|
color: 'warning',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
// 表单配置
|
||||||
|
// formRows: [
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// input: true,
|
||||||
|
// label: '检测类型名称',
|
||||||
|
// prop: 'name',
|
||||||
|
// rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||||
|
// // bind: {
|
||||||
|
// // disabled: true, // some condition, like detail mode...
|
||||||
|
// // }
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// [{ input: true, label: '检测类型编码', prop: 'code' }],
|
||||||
|
// [{ input: true, label: '备注', prop: 'remark' }],
|
||||||
|
// ],
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
chartData: {},
|
||||||
|
charts: {},
|
||||||
|
defectVis:false,
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
lineId: undefined,
|
||||||
|
factoryId: undefined,
|
||||||
|
checkNum: undefined,
|
||||||
|
startTime: undefined,
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// watch: {
|
||||||
|
// form: {
|
||||||
|
// handler: (val) => {
|
||||||
|
// console.log('form changed', val);
|
||||||
|
// },
|
||||||
|
// deep: true
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
created() {
|
||||||
|
this.getList();
|
||||||
|
this.getDict()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getDict() {
|
||||||
|
getPdList().then(res => {
|
||||||
|
this.searchBarFormConfig[1].selectOptions = res.data || [];
|
||||||
|
});
|
||||||
|
|
||||||
|
getFactoryPage({ pageSize: 100, pageNo: 1 }).then(res => {
|
||||||
|
this.searchBarFormConfig[0].selectOptions = res.data.list || [];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** base table related */
|
||||||
|
handleTableBtnClick({ data, type }) {
|
||||||
|
switch (type) {
|
||||||
|
case 'detail':
|
||||||
|
this.defectVis = true
|
||||||
|
this.$nextTick(() => {
|
||||||
|
this.$refs.defectSummaryDetRef.init({
|
||||||
|
factoryId:data.factoryId,
|
||||||
|
lineId: [data.lineId],
|
||||||
|
factoryName: data.factoryName,
|
||||||
|
lineName: data.lineName,
|
||||||
|
startTime: this.queryParams.startTime,
|
||||||
|
endTime: this.queryParams.endTime,
|
||||||
|
|
||||||
|
})
|
||||||
|
})
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
this.handleDelete(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
beforeDestroy() {
|
||||||
|
// 销毁所有 ECharts 实例
|
||||||
|
Object.values(this.charts).forEach(chart => {
|
||||||
|
if (chart && chart.dispose) {
|
||||||
|
chart.dispose();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.charts = {};
|
||||||
|
},
|
||||||
|
/**
|
||||||
|
* 初始化单个图表
|
||||||
|
* @param {string} lineName - 产线名称
|
||||||
|
* @param {Array} lineData - 该产线的原始数据
|
||||||
|
*/
|
||||||
|
initSingleChart(lineName, lineData) {
|
||||||
|
// 如果已有实例,先销毁
|
||||||
|
if (this.charts[lineName]) {
|
||||||
|
this.charts[lineName].dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
const chartDom = document.getElementById(`chart-${lineName}`);
|
||||||
|
if (!chartDom || !lineData || lineData.length === 0) {
|
||||||
|
console.warn(`图表容器 chart-${lineName} 未找到或数据为空`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const myChart = echarts.init(chartDom);
|
||||||
|
|
||||||
|
// --- 动态处理数据逻辑 ---
|
||||||
|
const startTime = this.queryParams.startTime;
|
||||||
|
const endTime = this.queryParams.endTime;
|
||||||
|
|
||||||
|
if (!startTime || !endTime) {
|
||||||
|
console.error("起始时间或结束时间为空,无法计算时间差。");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const durationDays = (endTime - startTime) / (1000 * 60 * 60 * 24);
|
||||||
|
const isHourly = durationDays < 7;
|
||||||
|
|
||||||
|
// 使用Map来保证顺序,并能存储聚合后的数据和原始显示标签
|
||||||
|
const aggregatedMap = new Map();
|
||||||
|
|
||||||
|
lineData.forEach(item => {
|
||||||
|
let groupKey; // 用于分组的键
|
||||||
|
let displayLabel; // 用于显示的标签
|
||||||
|
|
||||||
|
if (isHourly) {
|
||||||
|
// --- 方法一:使用字符串分割 ---
|
||||||
|
const timePart = item.timePoint.split('T')[1];
|
||||||
|
groupKey = timePart ? timePart : item.timePoint; // 安全处理
|
||||||
|
|
||||||
|
displayLabel = item.timePoint.replace('T', ' ');
|
||||||
|
} else {
|
||||||
|
// 按天聚合:分组键和显示标签都到天
|
||||||
|
groupKey = item.timePoint.split('T')[0];
|
||||||
|
displayLabel = groupKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!aggregatedMap.has(groupKey)) {
|
||||||
|
aggregatedMap.set(groupKey, {
|
||||||
|
displayLabel: displayLabel,
|
||||||
|
okNum: 0,
|
||||||
|
repairNum: 0,
|
||||||
|
ngNum: 0
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const aggregatedItem = aggregatedMap.get(groupKey);
|
||||||
|
aggregatedItem.okNum += item.okNum || 0;
|
||||||
|
aggregatedItem.repairNum += item.repairNum || 0;
|
||||||
|
aggregatedItem.ngNum += item.ngNum || 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 准备 ECharts 所需的数据格式
|
||||||
|
const xAxisData = [];
|
||||||
|
const okNumData = [];
|
||||||
|
const repairNumData = [];
|
||||||
|
const ngNumData = [];
|
||||||
|
|
||||||
|
aggregatedMap.forEach(item => {
|
||||||
|
xAxisData.push(item.displayLabel);
|
||||||
|
okNumData.push(item.okNum);
|
||||||
|
repairNumData.push(item.repairNum);
|
||||||
|
ngNumData.push(item.ngNum);
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- ECharts 配置项 ---
|
||||||
|
const option = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: { type: 'cross' },
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['合格品数', '返修品数', '废片数'],
|
||||||
|
itemHeight: 2,
|
||||||
|
itemWidth: 20,
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '20%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: xAxisData,
|
||||||
|
axisLabel: {
|
||||||
|
rotate: 45,
|
||||||
|
interval: 0, // 强制显示所有标签
|
||||||
|
formatter: function (value) {
|
||||||
|
if (isHourly) {
|
||||||
|
// 从 "2025-10-30 00:00" 中提取 "00:00" 进行显示
|
||||||
|
return value.split(' ')[1];
|
||||||
|
} else {
|
||||||
|
// 天级别,显示 "MM-DD"
|
||||||
|
const dateParts = value.split('-');
|
||||||
|
return `${dateParts[1]}-${dateParts[2]}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
min: 0
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '合格品数',
|
||||||
|
type: 'line',
|
||||||
|
showSymbol: false,
|
||||||
|
data: okNumData,
|
||||||
|
itemStyle: { color: 'rgba(40, 138, 255, 1)' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '返修品数',
|
||||||
|
type: 'line',
|
||||||
|
showSymbol: false,
|
||||||
|
data: repairNumData,
|
||||||
|
itemStyle: { color: 'rgba(115, 222, 147, 1)' },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '废片数',
|
||||||
|
type: 'line',
|
||||||
|
showSymbol: false,
|
||||||
|
data: ngNumData,
|
||||||
|
itemStyle: { color: 'rgba(255, 206, 106, 1)' },
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
myChart.setOption(option);
|
||||||
|
this.charts[lineName] = myChart;
|
||||||
|
|
||||||
|
// 监听容器大小变化
|
||||||
|
const resizeObserver = new ResizeObserver(() => {
|
||||||
|
myChart.resize();
|
||||||
|
});
|
||||||
|
resizeObserver.observe(chartDom);
|
||||||
|
myChart._resizeObserver = resizeObserver;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据获取到的 chartData 更新所有图表
|
||||||
|
*/
|
||||||
|
updateAllCharts() {
|
||||||
|
if (!this.chartData) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 nextTick 确保 v-for 生成的 DOM 已存在
|
||||||
|
this.$nextTick(() => {
|
||||||
|
const lineNames = Object.keys(this.chartData);
|
||||||
|
lineNames.forEach(lineName => {
|
||||||
|
this.initSingleChart(lineName, this.chartData[lineName]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** search bar related */
|
||||||
|
handleSearchBarBtnClick(btn) {
|
||||||
|
switch (btn.btnName) {
|
||||||
|
case 'search':
|
||||||
|
this.queryParams.lineId = btn.lineId ? btn.lineId : undefined
|
||||||
|
this.queryParams.factoryId = btn.factoryId ? btn.factoryId : undefined
|
||||||
|
this.queryParams.startTime = btn.timeVal ? btn.timeVal[0] : undefined
|
||||||
|
this.queryParams.endTime = btn.timeVal ? btn.timeVal[1] : undefined
|
||||||
|
this.getList();
|
||||||
|
break;
|
||||||
|
case 'add':
|
||||||
|
this.handleAdd();
|
||||||
|
break;
|
||||||
|
case 'export':
|
||||||
|
this.handleExport();
|
||||||
|
break;
|
||||||
|
// case 'reset':
|
||||||
|
// this.$refs['search-bar'].resetForm();
|
||||||
|
// this.resetQuery();
|
||||||
|
// break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 查询列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true;
|
||||||
|
// 执行查询
|
||||||
|
getDefectSummaryTable(this.queryParams).then((response) => {
|
||||||
|
this.list = response.data;
|
||||||
|
// this.total = response.data.total;
|
||||||
|
this.loading = false;
|
||||||
|
})
|
||||||
|
getDefectSummaryChart(this.queryParams).then((res) => {
|
||||||
|
console.log('res.data', res.data);
|
||||||
|
|
||||||
|
this.chartData = res.data || {};
|
||||||
|
// 手动调用更新图表的方法
|
||||||
|
this.updateAllCharts();
|
||||||
|
// // this.total = response.data.total;
|
||||||
|
// this.loading = false;
|
||||||
|
})
|
||||||
|
},
|
||||||
|
/** 表单重置 */
|
||||||
|
reset() {
|
||||||
|
this.form = {
|
||||||
|
id: undefined,
|
||||||
|
name: undefined,
|
||||||
|
code: undefined,
|
||||||
|
remark: undefined,
|
||||||
|
};
|
||||||
|
this.resetForm('form');
|
||||||
|
},
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
handleExport() {
|
||||||
|
// 处理查询参数
|
||||||
|
let tables = document.querySelector('.el-table').cloneNode(true)
|
||||||
|
const fix = tables.querySelector('.el-table__fixed')
|
||||||
|
const fixRight = tables.querySelector('.el-table__fixed-right')
|
||||||
|
if (fix) {
|
||||||
|
tables.removeChild(tables.querySelector('.el-table__fixed'))
|
||||||
|
}
|
||||||
|
if (fixRight) {
|
||||||
|
tables.removeChild(tables.querySelector('.el-table__fixed-right'))
|
||||||
|
}
|
||||||
|
let exportTable = XLSX.utils.table_to_book(tables)
|
||||||
|
|
||||||
|
var exportTableOut = XLSX.write(exportTable, {
|
||||||
|
bookType: 'xlsx', bookSST: true, type: 'array'
|
||||||
|
})
|
||||||
|
// sheetjs.xlsx为导出表格的标题名称
|
||||||
|
try {
|
||||||
|
FileSaver.saveAs(new Blob([exportTableOut], {
|
||||||
|
type: 'application/octet-stream'
|
||||||
|
}), '缺陷汇总.xlsx')
|
||||||
|
} catch (e) {
|
||||||
|
if (typeof console !== 'undefined') console.log(e, exportTableOut)
|
||||||
|
}
|
||||||
|
return exportTableOut
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
.charts-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-wrapper {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 300px;
|
||||||
|
margin-top: 10px;
|
||||||
|
/* 最小宽度,防止缩得太小 */
|
||||||
|
/* box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
border-radius: 4px; */
|
||||||
|
/* padding: 10px; */
|
||||||
|
}
|
||||||
|
|
||||||
|
.blue-block {
|
||||||
|
display: inline-block;
|
||||||
|
float: left;
|
||||||
|
width: 4px;
|
||||||
|
height: 16px;
|
||||||
|
background-color: #0B58FF;
|
||||||
|
border-radius: 1px;
|
||||||
|
margin-right: 8px;
|
||||||
|
margin-top: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.chart-title {
|
||||||
|
text-align: left;
|
||||||
|
color: #333;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
224
src/views/quality/dpdda/defectSummaryDet.vue
Normal file
224
src/views/quality/dpdda/defectSummaryDet.vue
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<el-drawer title="详情" :visible.sync="visible" size="70%" @close='closeD'>
|
||||||
|
<div class="box">
|
||||||
|
<!-- 顶部信息展示区域 -->
|
||||||
|
<div class="info-header">
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="label">工厂:</span>
|
||||||
|
<span class="value">{{ factoryName }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="label">产线:</span>
|
||||||
|
<span class="value">{{ lineName }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<span class="label">时间范围:</span>
|
||||||
|
<span class="value">{{ timeRange }}</span>
|
||||||
|
</div>
|
||||||
|
<div class="info-item">
|
||||||
|
<el-button type="primary" @click="handleExport">导出</el-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 表格 -->
|
||||||
|
<base-table :page="queryParams.pageNo" :limit="queryParams.pageSize" :table-props="tableProps"
|
||||||
|
:table-data="tableData" :span-method="spanMethod" :max-height="tableH">
|
||||||
|
</base-table>
|
||||||
|
</div>
|
||||||
|
</el-drawer>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import moment from 'moment';
|
||||||
|
import * as XLSX from 'xlsx';
|
||||||
|
import { getDefectSummaryDet } from '@/api/monitoring/defectSummary';
|
||||||
|
// import { publicFormatter } from '@/utils/dict'
|
||||||
|
|
||||||
|
const tableProps = [
|
||||||
|
{ prop: 'defectLevel', label: '缺陷等级' },
|
||||||
|
{ prop: 'defectName', label: '缺陷类型' },
|
||||||
|
{ prop: 'defectNum', label: '玻璃数量' }
|
||||||
|
]
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'EnergyStatisticsDet',
|
||||||
|
props: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
visible: false,
|
||||||
|
tableProps,
|
||||||
|
tableData: [],
|
||||||
|
tableBtn: [],
|
||||||
|
tableH: this.tableHeight(115),
|
||||||
|
total: 0,
|
||||||
|
queryParams: { pageNo: 1, pageSize: 30 },
|
||||||
|
factoryName: '',
|
||||||
|
lineName: '',
|
||||||
|
timeRange: '',
|
||||||
|
name: '',
|
||||||
|
energyType: '',
|
||||||
|
energyTypeId: '',
|
||||||
|
addOrEditTitle: "",
|
||||||
|
centervisible: false,
|
||||||
|
collectionList: [
|
||||||
|
{ value: 0, label: '否' },
|
||||||
|
{ value: 1, label: '是' }
|
||||||
|
],
|
||||||
|
showBtn: true,
|
||||||
|
selectedList: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
created() {
|
||||||
|
window.addEventListener('resize', () => {
|
||||||
|
this.tableH = this.tableHeight(115)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
spanMethod({ row, column, rowIndex, columnIndex }) {
|
||||||
|
const fields = ['defectLevel']
|
||||||
|
const cellValue = row[column.property]
|
||||||
|
if (cellValue && fields.includes(column.property)) {
|
||||||
|
const prevRow = this.tableData[rowIndex - 1]
|
||||||
|
let nextRow = this.tableData[rowIndex + 1]
|
||||||
|
if (prevRow && prevRow[column.property] === cellValue) {
|
||||||
|
return { rowspan: 0, colspan: 0 }
|
||||||
|
} else {
|
||||||
|
let countRowspan = 1
|
||||||
|
while (nextRow && nextRow[column.property] === cellValue) {
|
||||||
|
nextRow = this.tableData[++countRowspan + rowIndex]
|
||||||
|
}
|
||||||
|
if (countRowspan > 1) {
|
||||||
|
return { rowspan: countRowspan, colspan: 1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
init(data) {
|
||||||
|
this.visible = true;
|
||||||
|
this.factoryName = data.factoryName || '未知工厂';
|
||||||
|
this.lineName = data.lineName || '未知产线';
|
||||||
|
|
||||||
|
if (data.startTime && data.endTime) {
|
||||||
|
const start = moment(data.startTime).format('yyyy-MM-DD HH:mm:ss');
|
||||||
|
const end = moment(data.endTime).format('yyyy-MM-DD HH:mm:ss');
|
||||||
|
this.timeRange = `${start} - ${end}`;
|
||||||
|
} else {
|
||||||
|
this.timeRange = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
this.queryParams.factoryId = data.factoryId;
|
||||||
|
this.queryParams.lineId = data.lineId;
|
||||||
|
this.queryParams.startTime = data.startTime;
|
||||||
|
this.queryParams.endTime = data.endTime;
|
||||||
|
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
|
||||||
|
getList() {
|
||||||
|
getDefectSummaryDet({ ...this.queryParams }).then((res) => {
|
||||||
|
this.tableData = res.data || [];
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
closeD() {
|
||||||
|
this.$emit('closeDrawer');
|
||||||
|
},
|
||||||
|
|
||||||
|
closeDet() {
|
||||||
|
this.getList();
|
||||||
|
},
|
||||||
|
|
||||||
|
// --- 重写的导出方法 ---
|
||||||
|
// --- 修改后的导出方法 ---
|
||||||
|
handleExport() {
|
||||||
|
console.log("开始执行导出...");
|
||||||
|
this.$modal.confirm('确定要导出表格数据吗?').then(() => {
|
||||||
|
console.log("用户确认导出");
|
||||||
|
|
||||||
|
// 1. 准备数据
|
||||||
|
console.log("tableProps:", this.tableProps);
|
||||||
|
console.log("tableData:", this.tableData);
|
||||||
|
|
||||||
|
// 1.1 准备表头 (新增了 '工厂', '产线', '时间范围')
|
||||||
|
const headers = ['工厂', '产线', '时间范围', ...this.tableProps.map(prop => prop.label)];
|
||||||
|
console.log("生成的表头:", headers);
|
||||||
|
|
||||||
|
// 1.2 准备表格数据
|
||||||
|
const exportData = [];
|
||||||
|
this.tableData.forEach((row) => {
|
||||||
|
const newRow = [];
|
||||||
|
// 先添加顶部信息列
|
||||||
|
newRow.push(this.factoryName);
|
||||||
|
newRow.push(this.lineName);
|
||||||
|
newRow.push(this.timeRange);
|
||||||
|
|
||||||
|
// 再添加表格数据列
|
||||||
|
this.tableProps.forEach((prop) => {
|
||||||
|
// 直接填入所有数据,不再对 defectLevel 进行合并判断
|
||||||
|
newRow.push(row[prop.prop] !== undefined ? row[prop.prop] : '');
|
||||||
|
});
|
||||||
|
exportData.push(newRow);
|
||||||
|
});
|
||||||
|
console.log("处理后的数据:", exportData);
|
||||||
|
|
||||||
|
// 2. 创建工作簿和工作表
|
||||||
|
try {
|
||||||
|
const worksheet = XLSX.utils.aoa_to_sheet([headers, ...exportData]);
|
||||||
|
console.log("工作表创建成功");
|
||||||
|
const workbook = XLSX.utils.book_new();
|
||||||
|
XLSX.utils.book_append_sheet(workbook, worksheet, '缺陷详情数据');
|
||||||
|
console.log("工作簿创建成功");
|
||||||
|
|
||||||
|
// 3. 触发下载
|
||||||
|
const fileName = `${this.factoryName}-${this.lineName}-缺陷汇总详情-${moment().format('YYYYMMDDHHmmss')}.xlsx`;
|
||||||
|
console.log("准备下载文件:", fileName);
|
||||||
|
XLSX.writeFile(workbook, fileName);
|
||||||
|
console.log("下载触发成功");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("生成Excel文件时出错:", error);
|
||||||
|
this.$modal.msgError('导出失败,生成文件时出错!');
|
||||||
|
}
|
||||||
|
|
||||||
|
}).catch((error) => {
|
||||||
|
console.log("用户取消导出或发生错误:", error);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.box {
|
||||||
|
padding: 0 32px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.info-header {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: space-around;
|
||||||
|
padding: 16px 0;
|
||||||
|
border-bottom: 1px solid #ebeef5;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
|
||||||
|
.info-item {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-right: 32px;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: #606266;
|
||||||
|
margin-right: 8px;
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
color: #303133;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
416
src/views/quality/dpdda/sectionDefect.vue
Normal file
416
src/views/quality/dpdda/sectionDefect.vue
Normal file
@@ -0,0 +1,416 @@
|
|||||||
|
<template>
|
||||||
|
<div style="background: #f2f4f9; flex: 1; display: flex; flex-direction: column">
|
||||||
|
<el-row class="" style="
|
||||||
|
margin-bottom: 12px;
|
||||||
|
background: #fff;
|
||||||
|
padding: 16px 16px 0;
|
||||||
|
border-radius: 8px;
|
||||||
|
">
|
||||||
|
<SearchBar :formConfigs="searchBarFormConfig" ref="search-bar" @headBtnClick="handleSearchBarBtnClick" />
|
||||||
|
<base-table :max-height="tableH" :table-props="tableProps" :page="queryParams.pageNo"
|
||||||
|
:limit="queryParams.pageSize" :table-data="list" @emitFun="handleEmitFun" />
|
||||||
|
</el-row>
|
||||||
|
<!-- 搜索工作栏 -->
|
||||||
|
|
||||||
|
<!-- 用一个 div 包裹表格和图表,并使用 flex 布局 -->
|
||||||
|
<el-row class="" style="
|
||||||
|
height: 1px;
|
||||||
|
flex: 1;
|
||||||
|
margin-bottom: 12px;
|
||||||
|
background: #fff;
|
||||||
|
padding: 16px 16px 32px;
|
||||||
|
border-radius: 8px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
">
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :span="24">
|
||||||
|
<div id="chart" style="width: 100%; height: 300px;"></div>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import {
|
||||||
|
getPdList,
|
||||||
|
} from '@/api/core/monitoring/auto';
|
||||||
|
import { getFactoryPage } from '@/api/core/base/factory';
|
||||||
|
import basicPageMixin from '@/mixins/lb/basicPageMixin';
|
||||||
|
import { getSectionDefect } from '@/api/monitoring/defectSummary';
|
||||||
|
import * as echarts from 'echarts';
|
||||||
|
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
|
||||||
|
export default {
|
||||||
|
name: 'QualityInspectionType',
|
||||||
|
mixins: [basicPageMixin, tableHeightMixin],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tableBtn: [
|
||||||
|
this.$auth.hasPermi('base:quality-inspection-type:update')
|
||||||
|
? {
|
||||||
|
type: 'edit',
|
||||||
|
btnName: '修改',
|
||||||
|
}
|
||||||
|
: undefined,
|
||||||
|
this.$auth.hasPermi('base:quality-inspection-type: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: 'factoryName', label: '工厂' },
|
||||||
|
{ prop: 'lineName', label: '产线' },
|
||||||
|
{ prop: 'checkCount', label: '检测片数' },
|
||||||
|
{
|
||||||
|
prop: 'ngCount',
|
||||||
|
label: '不良合计',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: 'ngRate',
|
||||||
|
label: '不良率',
|
||||||
|
},
|
||||||
|
{ prop: 'originalNgCount', label: '原片不良' },
|
||||||
|
{ prop: 'edgeNgCount', label: '磨边不良' },
|
||||||
|
{ prop: 'silkNgCount', label: '丝印不良' },
|
||||||
|
{ prop: 'drillNgCount', label: '打孔不良' },
|
||||||
|
{ prop: 'coatingNgCount', label: '镀膜不良' },
|
||||||
|
{ prop: 'packNgCount', label: '钢包不良' },
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// {
|
||||||
|
// label: '操作',
|
||||||
|
// alignt: 'center',
|
||||||
|
// subcomponent: {
|
||||||
|
// render: function (h) {
|
||||||
|
// return h('div', null, [
|
||||||
|
// h(
|
||||||
|
// 'el-button',
|
||||||
|
// {
|
||||||
|
// props: {
|
||||||
|
// icon: 'el-icon-edit',
|
||||||
|
// size: 'mini',
|
||||||
|
// type: 'text',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// ' 修改'
|
||||||
|
// ),
|
||||||
|
// h(
|
||||||
|
// 'el-button',
|
||||||
|
// {
|
||||||
|
// props: {
|
||||||
|
// icon: 'el-icon-edit',
|
||||||
|
// size: 'mini',
|
||||||
|
// type: 'text',
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// ' 修改'
|
||||||
|
// ),
|
||||||
|
// ]);
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
],
|
||||||
|
//
|
||||||
|
searchBarFormConfig: [
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '工厂',
|
||||||
|
selectOptions: [],
|
||||||
|
param: 'factoryId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '产线',
|
||||||
|
selectOptions: [],
|
||||||
|
multiple: true,
|
||||||
|
param: 'lineId',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// type: 'input',
|
||||||
|
// label: '缺陷数>',
|
||||||
|
// // selectOptions: [],
|
||||||
|
// param: 'number',
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
type: 'datePicker',
|
||||||
|
label: '时间范围',
|
||||||
|
dateType: 'datetimerange',
|
||||||
|
format: 'yyyy-MM-dd HH:mm:ss',
|
||||||
|
valueFormat: 'timestamp',
|
||||||
|
rangeSeparator: '-',
|
||||||
|
startPlaceholder: '开始时间',
|
||||||
|
endPlaceholder: '结束时间',
|
||||||
|
param: 'timeVal',
|
||||||
|
width: 350
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
btnName: '查询',
|
||||||
|
name: 'search',
|
||||||
|
color: 'primary',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// type: 'button',
|
||||||
|
// btnName: '重置',
|
||||||
|
// name: 'reset',
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
type: 'separate',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// type: this.$auth.hasPermi('base:quality-inspection-type:create')
|
||||||
|
// ? 'button'
|
||||||
|
// : '',
|
||||||
|
// btnName: '新增',
|
||||||
|
// name: 'add',
|
||||||
|
// plain: true,
|
||||||
|
// color: 'success',
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
type: this.$auth.hasPermi('base:quality-inspection-type:export')
|
||||||
|
? 'button'
|
||||||
|
: '',
|
||||||
|
btnName: '导出',
|
||||||
|
name: 'export',
|
||||||
|
color: 'warning',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
// 表单配置
|
||||||
|
// formRows: [
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// input: true,
|
||||||
|
// label: '检测类型名称',
|
||||||
|
// prop: 'name',
|
||||||
|
// rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||||
|
// // bind: {
|
||||||
|
// // disabled: true, // some condition, like detail mode...
|
||||||
|
// // }
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// [{ input: true, label: '检测类型编码', prop: 'code' }],
|
||||||
|
// [{ input: true, label: '备注', prop: 'remark' }],
|
||||||
|
// ],
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
lineId: undefined,
|
||||||
|
factoryId: undefined,
|
||||||
|
startTime: undefined,
|
||||||
|
endTime: undefined,
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// watch: {
|
||||||
|
// form: {
|
||||||
|
// handler: (val) => {
|
||||||
|
// console.log('form changed', val);
|
||||||
|
// },
|
||||||
|
// deep: true
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
created() {
|
||||||
|
this.getList();
|
||||||
|
this.getDict()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getDict() {
|
||||||
|
getPdList().then(res => {
|
||||||
|
this.searchBarFormConfig[1].selectOptions = res.data || [];
|
||||||
|
});
|
||||||
|
|
||||||
|
getFactoryPage({ pageSize: 100, pageNo: 1 }).then(res => {
|
||||||
|
this.searchBarFormConfig[0].selectOptions = res.data.list || [];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** base table related */
|
||||||
|
handleTableBtnClick({ data, type }) {
|
||||||
|
switch (type) {
|
||||||
|
case 'edit':
|
||||||
|
this.handleUpdate(data);
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
this.handleDelete(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** search bar related */
|
||||||
|
handleSearchBarBtnClick(btn) {
|
||||||
|
switch (btn.btnName) {
|
||||||
|
case 'search':
|
||||||
|
this.queryParams.lineId = btn.lineId ? btn.lineId : undefined
|
||||||
|
this.queryParams.factoryId = btn.factoryId ? btn.factoryId : undefined
|
||||||
|
this.queryParams.startTime = btn.timeVal ? btn.timeVal[0] : undefined
|
||||||
|
this.queryParams.endTime = btn.timeVal ? btn.timeVal[1] : undefined
|
||||||
|
this.getList();
|
||||||
|
break;
|
||||||
|
case 'add':
|
||||||
|
this.handleAdd();
|
||||||
|
break;
|
||||||
|
case 'export':
|
||||||
|
this.handleExport();
|
||||||
|
break;
|
||||||
|
case 'reset':
|
||||||
|
this.$refs['search-bar'].resetForm();
|
||||||
|
this.resetQuery();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 查询列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true;
|
||||||
|
// 执行查询
|
||||||
|
getSectionDefect(this.queryParams).then((response) => {
|
||||||
|
this.list = response.data;
|
||||||
|
// 定义颜色数组,与你提供的顺序一致
|
||||||
|
const colors = [
|
||||||
|
'rgba(99, 189, 255, 1)',
|
||||||
|
'rgba(113, 100, 255, 1)',
|
||||||
|
'rgba(255, 104, 96, 1)',
|
||||||
|
'rgba(255, 151, 71, 1)',
|
||||||
|
'rgba(176, 235, 66, 1)',
|
||||||
|
'rgba(214, 128, 255, 1)',
|
||||||
|
'rgba(0, 67, 210, 1)'
|
||||||
|
];
|
||||||
|
|
||||||
|
const series = response.data.map((item, index) => {
|
||||||
|
// 为每个系列分配颜色,index 从 0 开始,依次对应 colors 数组
|
||||||
|
const color = colors[index % colors.length]; // 使用取模确保不越界
|
||||||
|
|
||||||
|
return {
|
||||||
|
name: item.lineName,
|
||||||
|
type: 'bar',
|
||||||
|
stack: 'Ad',
|
||||||
|
barWidth: '20',
|
||||||
|
emphasis: {
|
||||||
|
focus: 'series'
|
||||||
|
},
|
||||||
|
itemStyle: {
|
||||||
|
color: color // 指定当前系列的颜色
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
item.originalNgCount,
|
||||||
|
item.edgeNgCount,
|
||||||
|
item.silkNgCount,
|
||||||
|
item.drillNgCount,
|
||||||
|
item.coatingNgCount,
|
||||||
|
item.packNgCount
|
||||||
|
]
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
this.loading = false;
|
||||||
|
this.getChart(series);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getChart(series) {
|
||||||
|
var chartDom = document.getElementById('chart');
|
||||||
|
var myChart = echarts.init(chartDom);
|
||||||
|
var option;
|
||||||
|
option = {
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: 30,
|
||||||
|
top: 20,
|
||||||
|
right: 30,
|
||||||
|
bottom:20
|
||||||
|
},
|
||||||
|
legend: {},
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
data: ['原片不良', '磨边不良', '丝印不良', '打孔不良', '镀膜不良', ' 钢包不良']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'value'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: series
|
||||||
|
};
|
||||||
|
|
||||||
|
option && myChart.setOption(option);
|
||||||
|
},
|
||||||
|
/** 导出按钮操作 */
|
||||||
|
handleExport() {
|
||||||
|
// 处理查询参数
|
||||||
|
let tables = document.querySelector('.el-table').cloneNode(true)
|
||||||
|
const fix = tables.querySelector('.el-table__fixed')
|
||||||
|
const fixRight = tables.querySelector('.el-table__fixed-right')
|
||||||
|
if (fix) {
|
||||||
|
tables.removeChild(tables.querySelector('.el-table__fixed'))
|
||||||
|
}
|
||||||
|
if (fixRight) {
|
||||||
|
tables.removeChild(tables.querySelector('.el-table__fixed-right'))
|
||||||
|
}
|
||||||
|
let exportTable = XLSX.utils.table_to_book(tables)
|
||||||
|
|
||||||
|
var exportTableOut = XLSX.write(exportTable, {
|
||||||
|
bookType: 'xlsx', bookSST: true, type: 'array'
|
||||||
|
})
|
||||||
|
// sheetjs.xlsx为导出表格的标题名称
|
||||||
|
try {
|
||||||
|
FileSaver.saveAs(new Blob([exportTableOut], {
|
||||||
|
type: 'application/octet-stream'
|
||||||
|
}), '工段不良.xlsx')
|
||||||
|
} catch (e) {
|
||||||
|
if (typeof console !== 'undefined') console.log(e, exportTableOut)
|
||||||
|
}
|
||||||
|
return exportTableOut
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
<style scoped>
|
||||||
|
/* 添加 scoped 以避免样式污染 */
|
||||||
|
.app-container {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.content-wrapper {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
/* 垂直排列 */
|
||||||
|
gap: 20px;
|
||||||
|
}
|
||||||
|
.table-container,
|
||||||
|
.chart-container {
|
||||||
|
flex: 1;
|
||||||
|
/* 让两个容器平分父容器的空间 */
|
||||||
|
min-height: 300px;
|
||||||
|
/* 设置最小高度,防止内容过少时变形 */
|
||||||
|
border: 1px solid #ebeef5;
|
||||||
|
/* 添加一个边框,方便看清分隔 */
|
||||||
|
border-radius: 4px;
|
||||||
|
padding: 10px;
|
||||||
|
background-color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 确保图表容器的父元素也有高度,ECharts 才能正确渲染 */
|
||||||
|
.chart-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
305
src/views/quality/transmittanceTesting.vue
Normal file
305
src/views/quality/transmittanceTesting.vue
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
<template>
|
||||||
|
<div class="app-container">
|
||||||
|
<!-- 搜索工作栏 -->
|
||||||
|
<SearchBar :formConfigs="searchBarFormConfig" ref="search-bar" @headBtnClick="handleSearchBarBtnClick" />
|
||||||
|
|
||||||
|
<!-- 列表 -->
|
||||||
|
<base-table :max-height="tableH" :table-props="tableProps" :page="queryParams.pageNo" :limit="queryParams.pageSize"
|
||||||
|
:table-data="list" @emitFun="handleEmitFun">
|
||||||
|
<!-- <method-btn v-if="tableBtn.length" slot="handleBtn" label="操作" :width="120" :method-list="tableBtn"
|
||||||
|
@clickBtn="handleTableBtnClick" /> -->
|
||||||
|
</base-table>
|
||||||
|
|
||||||
|
<!-- 分页组件 -->
|
||||||
|
<pagination v-show="total > 0" :total="total" :page.sync="queryParams.pageNo" :limit.sync="queryParams.pageSize"
|
||||||
|
@pagination="getList" />
|
||||||
|
|
||||||
|
<!-- 对话框(添加 / 修改) -->
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import moment from 'moment';
|
||||||
|
import { getPdList,} from '@/api/core/monitoring/auto';
|
||||||
|
import { getFactoryPage } from '@/api/core/base/factory';
|
||||||
|
import basicPageMixin from '@/mixins/lb/basicPageMixin';
|
||||||
|
import { getTranslucentPage, exportTranslucent } from '@/api/monitoring/defectSummary';
|
||||||
|
import tableHeightMixin from '@/mixins/lb/tableHeightMixin';
|
||||||
|
export default {
|
||||||
|
name: 'QualityInspectionType',
|
||||||
|
mixins: [basicPageMixin, tableHeightMixin],
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
// tableBtn: [
|
||||||
|
// this.$auth.hasPermi('base:quality-inspection-type:update')
|
||||||
|
// ? {
|
||||||
|
// type: 'edit',
|
||||||
|
// btnName: '修改',
|
||||||
|
// }
|
||||||
|
// : undefined,
|
||||||
|
// this.$auth.hasPermi('base:quality-inspection-type: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: 'factoryName', label: '工厂' },
|
||||||
|
{ prop: 'lineName', label: '产线' },
|
||||||
|
{ prop: 'timeVal', label: '时间段' },
|
||||||
|
{ prop: 'totalNum', label: '玻璃总数' },
|
||||||
|
{ prop: 'goodNum', label: '一等品数量' },
|
||||||
|
{ prop: 'passNum', label: '二等品数量' },
|
||||||
|
{ prop: 'scrapNum', label: '废片数' },
|
||||||
|
{ prop: 'passRate', label: '合格率' },
|
||||||
|
],
|
||||||
|
//
|
||||||
|
searchBarFormConfig: [
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '工厂',
|
||||||
|
selectOptions: [],
|
||||||
|
param: 'factoryId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'select',
|
||||||
|
label: '产线',
|
||||||
|
selectOptions: [],
|
||||||
|
param: 'lineId',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'datePicker',
|
||||||
|
label: '时间范围',
|
||||||
|
dateType: 'datetimerange',
|
||||||
|
format: 'yyyy-MM-dd HH:mm:ss',
|
||||||
|
valueFormat: 'yyyy-MM-dd HH:mm:ss',
|
||||||
|
rangeSeparator: '-',
|
||||||
|
startPlaceholder: '开始时间',
|
||||||
|
endPlaceholder: '结束时间',
|
||||||
|
param: 'timeVal',
|
||||||
|
width: 350
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: 'button',
|
||||||
|
btnName: '查询',
|
||||||
|
name: 'search',
|
||||||
|
color: 'primary',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// type: 'button',
|
||||||
|
// btnName: '重置',
|
||||||
|
// name: 'reset',
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
type: 'separate',
|
||||||
|
},
|
||||||
|
// {
|
||||||
|
// type: this.$auth.hasPermi('base:quality-inspection-type:create')
|
||||||
|
// ? 'button'
|
||||||
|
// : '',
|
||||||
|
// btnName: '新增',
|
||||||
|
// name: 'add',
|
||||||
|
// plain: true,
|
||||||
|
// color: 'success',
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
type: this.$auth.hasPermi('monitoring:translucent:export')
|
||||||
|
? 'button'
|
||||||
|
: '',
|
||||||
|
btnName: '导出',
|
||||||
|
name: 'export',
|
||||||
|
color: 'warning',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
// 表单配置
|
||||||
|
// formRows: [
|
||||||
|
// [
|
||||||
|
// {
|
||||||
|
// input: true,
|
||||||
|
// label: '检测类型名称',
|
||||||
|
// prop: 'name',
|
||||||
|
// rules: [{ required: true, message: '不能为空', trigger: 'blur' }],
|
||||||
|
// // bind: {
|
||||||
|
// // disabled: true, // some condition, like detail mode...
|
||||||
|
// // }
|
||||||
|
// },
|
||||||
|
// ],
|
||||||
|
// [{ input: true, label: '检测类型编码', prop: 'code' }],
|
||||||
|
// [{ input: true, label: '备注', prop: 'remark' }],
|
||||||
|
// ],
|
||||||
|
// 是否显示弹出层
|
||||||
|
open: false,
|
||||||
|
// 查询参数
|
||||||
|
queryParams: {
|
||||||
|
pageNo: 1,
|
||||||
|
pageSize: 10,
|
||||||
|
lineId: undefined,
|
||||||
|
factoryId: undefined,
|
||||||
|
startTime: undefined,
|
||||||
|
endTime: undefined,
|
||||||
|
},
|
||||||
|
// 表单参数
|
||||||
|
form: {},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
// watch: {
|
||||||
|
// form: {
|
||||||
|
// handler: (val) => {
|
||||||
|
// console.log('form changed', val);
|
||||||
|
// },
|
||||||
|
// deep: true
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
created() {
|
||||||
|
this.getList();
|
||||||
|
this.getDict()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getDict() {
|
||||||
|
getPdList().then(res => {
|
||||||
|
this.searchBarFormConfig[1].selectOptions = res.data || [];
|
||||||
|
});
|
||||||
|
getFactoryPage({ pageSize: 100, pageNo: 1 }).then(res => {
|
||||||
|
this.searchBarFormConfig[0].selectOptions = res.data.list || [];
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** base table related */
|
||||||
|
handleTableBtnClick({ data, type }) {
|
||||||
|
switch (type) {
|
||||||
|
case 'edit':
|
||||||
|
this.handleUpdate(data);
|
||||||
|
break;
|
||||||
|
case 'delete':
|
||||||
|
this.handleDelete(data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** search bar related */
|
||||||
|
handleSearchBarBtnClick(btn) {
|
||||||
|
console.log('btn',btn);
|
||||||
|
|
||||||
|
// const keys = ['name'];
|
||||||
|
switch (btn.btnName) {
|
||||||
|
case 'search':
|
||||||
|
this.queryParams.lineId = btn.lineId ? btn.lineId : undefined
|
||||||
|
this.queryParams.factoryId = btn.factoryId ? btn.factoryId : undefined
|
||||||
|
this.queryParams.startTime = btn.timeVal ? btn.timeVal[0] : undefined
|
||||||
|
this.queryParams.endTime = btn.timeVal ? btn.timeVal[1] : undefined
|
||||||
|
// keys.forEach((key) => {
|
||||||
|
// this.queryParams[key] = btn[key] || null;
|
||||||
|
// });
|
||||||
|
this.getList();
|
||||||
|
break;
|
||||||
|
case 'add':
|
||||||
|
this.handleAdd();
|
||||||
|
break;
|
||||||
|
case 'export':
|
||||||
|
this.handleExport();
|
||||||
|
break;
|
||||||
|
case 'reset':
|
||||||
|
this.$refs['search-bar'].resetForm();
|
||||||
|
this.resetQuery();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
/** 查询列表 */
|
||||||
|
getList() {
|
||||||
|
this.loading = true;
|
||||||
|
// 执行查询
|
||||||
|
getTranslucentPage(this.queryParams).then((res) => {
|
||||||
|
this.list = res.data.list ? res.data.list.map((item) => {
|
||||||
|
const startTime = item.startTime ? moment(item.startTime).format('YYYY-MM-DD HH:mm:ss') : '';
|
||||||
|
const endTime = item.endTime ? moment(item.endTime).format('YYYY-MM-DD HH:mm:ss') : '';
|
||||||
|
|
||||||
|
// 拼接开始时间和结束时间,中间用“至”连接
|
||||||
|
const timeVal = startTime && endTime ? `${startTime} 至 ${endTime}` : '';
|
||||||
|
|
||||||
|
return {
|
||||||
|
...item,
|
||||||
|
timeVal: timeVal
|
||||||
|
};
|
||||||
|
}) :[]
|
||||||
|
this.total = res.data.total;
|
||||||
|
this.loading = false;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
/** 表单重置 */
|
||||||
|
// reset() {
|
||||||
|
// this.form = {
|
||||||
|
// id: undefined,
|
||||||
|
// name: undefined,
|
||||||
|
// code: undefined,
|
||||||
|
// remark: undefined,
|
||||||
|
// };
|
||||||
|
// this.resetForm('form');
|
||||||
|
// },
|
||||||
|
/** 新增按钮操作 */
|
||||||
|
// handleAdd() {
|
||||||
|
// this.reset();
|
||||||
|
// this.open = true;
|
||||||
|
// this.title = '添加质量检测类型基础';
|
||||||
|
// },
|
||||||
|
/** 修改按钮操作 */
|
||||||
|
// handleUpdate(row) {
|
||||||
|
// this.reset();
|
||||||
|
// const id = row.id;
|
||||||
|
// getQualityInspectionType(id).then((response) => {
|
||||||
|
// this.form = response.data;
|
||||||
|
// this.open = true;
|
||||||
|
// this.title = '修改质量检测类型基础';
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
/** 提交按钮 */
|
||||||
|
// submitForm() {
|
||||||
|
// // console.log('this.$refs.form', this.$refs.form);
|
||||||
|
// // return;
|
||||||
|
// this.$refs['form'].validate((valid) => {
|
||||||
|
// if (!valid) {
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// console.log('final form', JSON.stringify(this.form));
|
||||||
|
// // 修改的提交
|
||||||
|
// if (this.form.id != null) {
|
||||||
|
// updateQualityInspectionType(this.form).then((response) => {
|
||||||
|
// this.$modal.msgSuccess('修改成功');
|
||||||
|
// this.open = false;
|
||||||
|
// this.getList();
|
||||||
|
// });
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// // 添加的提交
|
||||||
|
// createQualityInspectionType(this.form).then((response) => {
|
||||||
|
// this.$modal.msgSuccess('新增成功');
|
||||||
|
// this.open = false;
|
||||||
|
// this.getList();
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// },
|
||||||
|
handleExport() {
|
||||||
|
// 处理查询参数
|
||||||
|
let params = { ...this.queryParams };
|
||||||
|
// params.pageNo = undefined;
|
||||||
|
// params.pageSize = undefined;
|
||||||
|
this.$modal
|
||||||
|
.confirm('是否确认导出透光率检测?')
|
||||||
|
.then(() => {
|
||||||
|
this.exportLoading = true;
|
||||||
|
return exportTranslucent(params);
|
||||||
|
})
|
||||||
|
.then((response) => {
|
||||||
|
this.$download.excel(response, '透光率检测.xls');
|
||||||
|
this.exportLoading = false;
|
||||||
|
})
|
||||||
|
.catch(() => { });
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user