Browse Source

2026-07-13

异常规则配置
master
fengyuan_yang 2 weeks ago
parent
commit
3b18c4baa4
  1. 13
      src/api/sys/sceneExceptionRule.js
  2. 712
      src/views/modules/sys/sceneExceptionRuleConfig.vue

13
src/api/sys/sceneExceptionRule.js

@ -0,0 +1,13 @@
import { createAPI } from '@/utils/httpRequest'
// 主信息
export const searchSceneExceptionRule = data => createAPI('/sysSceneExceptionRule/searchRule', 'post', data)
export const saveSceneExceptionRule = data => createAPI('/sysSceneExceptionRule/saveRule', 'post', data)
export const updateSceneExceptionRule = data => createAPI('/sysSceneExceptionRule/updateRule', 'post', data)
export const deleteSceneExceptionRule = data => createAPI('/sysSceneExceptionRule/deleteRule', 'post', data)
// 触发条件
export const getSceneExceptionRuleConditionList = data => createAPI('/sysSceneExceptionRule/getConditionList', 'post', data)
export const saveSceneExceptionRuleCondition = data => createAPI('/sysSceneExceptionRule/saveCondition', 'post', data)
export const updateSceneExceptionRuleCondition = data => createAPI('/sysSceneExceptionRule/updateCondition', 'post', data)
export const deleteSceneExceptionRuleCondition = data => createAPI('/sysSceneExceptionRule/deleteCondition', 'post', data)

712
src/views/modules/sys/sceneExceptionRuleConfig.vue

@ -0,0 +1,712 @@
<template>
<div class="mod-config">
<el-form :inline="true" label-position="top" :model="searchData" @keyup.enter.native="queryRule">
<el-form-item label="规则编码">
<el-input v-model="searchData.ruleCode" clearable style="width: 140px"></el-input>
</el-form-item>
<el-form-item label="规则名称">
<el-input v-model="searchData.ruleName" clearable style="width: 180px"></el-input>
</el-form-item>
<el-form-item label=" ">
<el-button type="primary" @click="queryRule">查询</el-button>
<el-button type="primary" @click="openMainDialog()">新增</el-button>
<el-button type="danger" @click="deleteMain">删除</el-button>
</el-form-item>
</el-form>
<el-table
class="exception-rule-main-table"
:height="tableHeight"
:data="dataList"
border
:cell-style="mainCellStyle"
v-loading="dataListLoading"
@selection-change="handleMainSelection"
style="width: 100%;">
<el-table-column
type="selection"
header-align="center"
align="center"
width="50">
</el-table-column>
<el-table-column prop="site" label="Site" header-align="center" align="center" min-width="100"></el-table-column>
<el-table-column prop="buNo" label="BU" header-align="center" align="center" min-width="100"></el-table-column>
<el-table-column prop="ruleCode" label="规则编码" header-align="center" align="center" min-width="140"></el-table-column>
<el-table-column prop="ruleName" label="规则名称" header-align="center" align="left" min-width="200"></el-table-column>
<el-table-column prop="applyPage" label="应用页面" header-align="center" align="center" min-width="140"></el-table-column>
<el-table-column prop="applyButton" label="应用按钮" header-align="center" align="center" min-width="140"></el-table-column>
<el-table-column label="是否启用" header-align="center" align="center" min-width="100">
<template slot-scope="scope">
<el-tag v-if="scope.row.enableFlag === 'Y'" type="success">启用</el-tag>
<el-tag v-else type="info">禁用</el-tag>
</template>
</el-table-column>
<el-table-column prop="updateBy" label="更新人" header-align="center" align="center" min-width="120"></el-table-column>
<el-table-column prop="updateDate" label="更新时间" header-align="center" align="center" min-width="170"></el-table-column>
<el-table-column
fixed="right"
header-align="center"
align="center"
width="140"
label="操作">
<template slot-scope="scope">
<el-link style="cursor: pointer" @click="openConditionDialog(scope.row)">触发条件</el-link>
<el-link style="cursor: pointer; margin-left: 8px" @click="openMainDialog(scope.row)">编辑</el-link>
</template>
</el-table-column>
</el-table>
<el-pagination
style="margin-top: 0px"
@size-change="sizeChangeHandle"
@current-change="currentChangeHandle"
:current-page="pageIndex"
:page-sizes="[20, 50, 100, 200, 500]"
:page-size="pageSize"
:total="totalPage"
layout="total, sizes, prev, pager, next, jumper">
</el-pagination>
<el-dialog
:title="mainDialogTitle"
:close-on-click-modal="false"
v-drag
:visible.sync="mainDialogVisible"
width="460px">
<el-form :inline="true" label-position="top">
<el-form-item label="BU">
<el-select v-model="mainForm.bu" :disabled="mainForm.mode === 'edit'" style="width: 160px" placeholder="请选择">
<el-option
v-for="item in buList"
:key="item.buNo"
:label="(item.sitename || item.site || '') + '-' + (item.buDesc || item.buNo || '')"
:value="item.buNo">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="规则编码">
<el-input v-model="mainForm.ruleCode" disabled placeholder="保存后自动生成" style="width: 120px"></el-input>
</el-form-item>
<el-form-item label="是否启用">
<el-select v-model="mainForm.enableFlag" style="width: 120px">
<el-option label="启用" value="Y"></el-option>
<el-option label="禁用" value="N"></el-option>
</el-select>
</el-form-item>
</el-form>
<el-form :inline="true" label-position="top">
<el-form-item label="规则名称">
<el-input v-model="mainForm.ruleName" maxlength="100" style="width: 428px"></el-input>
</el-form-item>
</el-form>
<el-form :inline="true" label-position="top">
<el-form-item label="应用页面">
<el-select v-model="mainForm.applyPage" style="width: 207px" placeholder="请选择">
<el-option
v-for="item in applyPageOptions"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="应用按钮">
<el-select v-model="mainForm.applyButton" style="width: 207px" placeholder="请选择">
<el-option
v-for="item in applyButtonOptions"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
</el-form-item>
</el-form>
<el-footer style="height: 35px; margin-top: 10px; text-align: center">
<el-button type="primary" @click="saveMain">保存</el-button>
<el-button type="primary" @click="mainDialogVisible = false">关闭</el-button>
</el-footer>
</el-dialog>
<el-dialog
title="触发条件"
:close-on-click-modal="false"
v-drag
:visible.sync="conditionDialogVisible"
width="1250px">
<el-form :inline="true" label-position="top" style="margin-top: -20px">
<el-form-item label=" ">
<el-button type="primary" @click="openConditionAdd">新增</el-button>
<el-button type="danger" @click="deleteCondition">删除</el-button>
</el-form-item>
</el-form>
<el-table
:data="conditionList"
border
row-key="conditionNo"
:tree-props="{ children: 'children' }"
default-expand-all
@selection-change="handleConditionSelection"
style="width: 100%;">
<el-table-column type="selection" header-align="center" align="center" width="50"></el-table-column>
<el-table-column prop="conditionNo" label="条件编号" header-align="center" align="center" min-width="120"></el-table-column>
<el-table-column prop="parentConditionNo" label="父条件编号" header-align="center" align="center" min-width="120"></el-table-column>
<el-table-column prop="relationField" label="关系字段" header-align="center" align="center" min-width="120"></el-table-column>
<el-table-column prop="compareSymbol" label="比较符" header-align="center" align="center" min-width="80"></el-table-column>
<el-table-column prop="conditionParam" label="条件参数" header-align="center" align="right" min-width="100"></el-table-column>
<el-table-column prop="forceType" label="是否强制" header-align="center" align="center" min-width="100"></el-table-column>
<el-table-column prop="warningLevel" label="预警等级" header-align="center" align="center" min-width="100"></el-table-column>
<el-table-column prop="animationEffect" label="动画效果" header-align="center" align="center" min-width="100"></el-table-column>
<el-table-column prop="responsibilityDept" label="责任部门" header-align="center" align="center" min-width="120"></el-table-column>
<el-table-column prop="triggerEvent" label="触发异常事件" header-align="center" align="center" min-width="110"></el-table-column>
<el-table-column label="操作" header-align="center" align="center" min-width="80">
<template slot-scope="scope">
<el-link style="cursor: pointer" @click="openConditionEdit(scope.row)">编辑</el-link>
</template>
</el-table-column>
</el-table>
<el-footer style="height: 35px; margin-top: 10px; text-align: center">
<el-button type="primary" @click="conditionDialogVisible = false">关闭</el-button>
</el-footer>
</el-dialog>
<el-dialog
:title="conditionEditTitle"
:close-on-click-modal="false"
v-drag
:visible.sync="conditionEditVisible"
width="700px">
<el-form :inline="true" label-position="top">
<el-form-item label="条件编号">
<el-input v-model="conditionForm.conditionNo" :disabled="conditionForm.mode === 'edit'" style="width: 100px"></el-input>
</el-form-item>
<el-form-item label="父条件编号">
<el-select v-model="conditionForm.parentConditionNo" clearable style="width: 100px" placeholder="根条件" @change="onParentConditionChange">
<el-option
v-for="item in rootConditionList"
:key="item.conditionNo"
:label="item.conditionNo"
:value="item.conditionNo">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="关系字段">
<el-select v-model="conditionForm.relationField" style="width: 150px" placeholder="请选择">
<el-option
v-for="item in relationFieldOptions"
:key="item"
:label="item"
:value="item">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="比较符">
<el-select v-model="conditionForm.compareSymbol" style="width: 120px">
<el-option v-for="item in compareSymbolOptions" :key="item" :label="item" :value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="条件参数">
<el-input-number v-model="conditionForm.conditionParam" :precision="4" :controls="false" style="width: 120px"></el-input-number>
</el-form-item>
</el-form>
<el-form :inline="true" label-position="top">
<el-form-item label="是否强制">
<el-select v-model="conditionForm.forceType" style="width: 100px">
<el-option v-for="item in forceTypeOptions" :key="item" :label="item" :value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="预警等级">
<el-select v-model="conditionForm.warningLevel" style="width: 100px">
<el-option v-for="item in warningLevelOptions" :key="item" :label="item" :value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="动画效果">
<el-select v-model="conditionForm.animationEffect" style="width: 150px">
<el-option v-for="item in animationEffectOptions" :key="item" :label="item" :value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item label="责任部门">
<el-select v-model="conditionForm.responsibilityDept" clearable filterable style="width: 120px">
<el-option
v-for="item in roleList"
:key="item.roleId"
:label="item.roleName"
:value="item.roleName">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="触发异常事件">
<el-select v-model="conditionForm.triggerEvent" style="width: 120px">
<el-option v-for="item in triggerEventOptions" :key="item" :label="item" :value="item"></el-option>
</el-select>
</el-form-item>
</el-form>
<el-footer style="height: 35px; margin-top: 10px; text-align: center">
<el-button type="primary" @click="saveCondition">保存</el-button>
<el-button type="primary" @click="conditionEditVisible = false">关闭</el-button>
</el-footer>
</el-dialog>
</div>
</template>
<script>
import {
searchSceneExceptionRule,
saveSceneExceptionRule,
updateSceneExceptionRule,
deleteSceneExceptionRule,
getSceneExceptionRuleConditionList,
saveSceneExceptionRuleCondition,
updateSceneExceptionRuleCondition,
deleteSceneExceptionRuleCondition
} from '@/api/sys/sceneExceptionRule'
import { getSiteAndBuByUserName, getUserRoleList } from '@/api/qc/qc'
export default {
data () {
return {
tableHeight: 200,
dataListLoading: false,
dataList: [],
mainSelection: [],
pageIndex: 1,
pageSize: 20,
totalPage: 0,
searchData: {
site: this.$store.state.user.site,
userName: this.$store.state.user.name,
ruleCode: '',
ruleName: '',
page: 1,
limit: 20
},
buList: [],
roleList: [],
mainDialogVisible: false,
mainDialogTitle: '新增异常规则',
mainForm: {
mode: 'add',
site: '',
buNo: '',
bu: '',
ruleCode: '',
ruleName: '',
applyPage: '过站采集',
applyButton: '创建分卷',
enableFlag: 'Y'
},
conditionDialogVisible: false,
currentRule: {},
conditionList: [],
conditionSelection: [],
conditionEditVisible: false,
conditionEditTitle: '新增触发条件',
conditionForm: {
mode: 'add',
site: '',
buNo: '',
ruleCode: '',
conditionNo: '',
parentConditionNo: '',
relationField: '',
compareSymbol: '>',
conditionParam: null,
forceType: '强制',
warningLevel: '一般',
animationEffect: '系统默认',
responsibilityDept: '',
triggerEvent: '异常代码'
},
relationFieldOptions: ['排数', '分切卷数', '良品数', '面损', '性能不良', '不良数', '良率', '不良率', '总数'],
compareSymbolOptions: ['>', '=', '<', '>=', '<='],
forceTypeOptions: ['强制', '提示'],
applyPageOptions: ['过站采集'],
applyButtonOptions: ['创建分卷'],
warningLevelOptions: ['轻微', '一般', '严重'],
animationEffectOptions: ['系统默认'],
triggerEventOptions: ['异常代码', '异常单']
}
},
computed: {
rootConditionList () {
return this.conditionList || []
}
},
created () {
this.loadBuList()
this.loadRoleList()
this.getDataList()
},
mounted () {
this.$nextTick(() => {
this.calculateTableHeight()
window.addEventListener('resize', this.calculateTableHeight)
})
},
beforeDestroy () {
window.removeEventListener('resize', this.calculateTableHeight)
},
methods: {
calculateTableHeight () {
this.tableHeight = window.innerHeight - 170
},
loadBuList () {
const params = { username: this.$store.state.user.name }
getSiteAndBuByUserName(params).then(({ data }) => {
if (data && data.code === 0) {
this.buList = data.rows || []
}
})
},
loadRoleList () {
getUserRoleList({}).then(({ data }) => {
if (data && data.code === 0) {
this.roleList = data.rows || []
} else {
this.roleList = []
}
})
},
queryRule () {
this.pageIndex = 1
this.getDataList()
},
getDataList () {
this.searchData.page = this.pageIndex
this.searchData.limit = this.pageSize
this.dataListLoading = true
searchSceneExceptionRule(this.searchData).then(({ data }) => {
if (data && data.code === 0) {
this.dataList = (data.page && data.page.list) || []
this.pageIndex = (data.page && data.page.currPage) || 1
this.pageSize = (data.page && data.page.pageSize) || this.pageSize
this.totalPage = (data.page && data.page.totalCount) || 0
} else {
this.dataList = []
this.totalPage = 0
}
}).finally(() => {
this.dataListLoading = false
})
},
sizeChangeHandle (val) {
this.pageSize = val
this.pageIndex = 1
this.getDataList()
},
currentChangeHandle (val) {
this.pageIndex = val
this.getDataList()
},
mainCellStyle () {
return {
paddingTop: '9px',
paddingBottom: '9px'
}
},
handleMainSelection (val) {
this.mainSelection = val
},
openMainDialog (row) {
if (row) {
this.mainDialogTitle = '编辑异常规则'
this.mainForm = {
mode: 'edit',
site: row.site,
buNo: row.buNo,
bu: row.site + '_' + row.buNo,
ruleCode: row.ruleCode,
ruleName: row.ruleName,
applyPage: row.applyPage || this.applyPageOptions[0],
applyButton: row.applyButton || this.applyButtonOptions[0],
enableFlag: row.enableFlag || 'Y'
}
} else {
this.mainDialogTitle = '新增异常规则'
const defaultBu = this.buList.length > 0 ? this.buList[0].buNo : ''
this.mainForm = {
mode: 'add',
site: this.$store.state.user.site,
buNo: '',
bu: defaultBu,
ruleCode: '',
ruleName: '',
applyPage: this.applyPageOptions[0],
applyButton: this.applyButtonOptions[0],
enableFlag: 'Y'
}
}
this.mainDialogVisible = true
},
saveMain () {
if (!this.mainForm.bu && this.mainForm.mode === 'add') {
this.$message.warning('请选择BU')
return
}
if (!this.mainForm.ruleName) {
this.$message.warning('请输入规则名称')
return
}
if (!this.mainForm.applyPage) {
this.$message.warning('请选择应用页面')
return
}
if (!this.mainForm.applyButton) {
this.$message.warning('请选择应用按钮')
return
}
if (this.mainForm.mode === 'add') {
saveSceneExceptionRule(this.mainForm).then(({ data }) => {
if (data && data.code === 0) {
this.mainDialogVisible = false
this.$message.success('新增成功,规则编码:' + (data.ruleCode || ''))
this.getDataList()
} else {
this.$message.error(data.msg)
}
})
} else {
updateSceneExceptionRule(this.mainForm).then(({ data }) => {
if (data && data.code === 0) {
this.mainDialogVisible = false
this.$message.success('操作成功')
this.getDataList()
} else {
this.$message.error(data.msg)
}
})
}
},
deleteMain () {
if (this.mainSelection.length === 0) {
this.$message.warning('请勾选要删除的记录')
return
}
this.$confirm('是否删除选中的规则及其触发条件?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteSceneExceptionRule({ submitList: this.mainSelection }).then(({ data }) => {
if (data && data.code === 0) {
this.$message.success('操作成功')
this.mainSelection = []
this.getDataList()
} else {
this.$message.error(data.msg)
}
})
})
},
openConditionDialog (row) {
this.currentRule = {
site: row.site,
buNo: row.buNo,
ruleCode: row.ruleCode
}
this.conditionDialogVisible = true
this.getConditionList()
},
getConditionList () {
if (!this.currentRule.ruleCode) {
return
}
getSceneExceptionRuleConditionList(this.currentRule).then(({ data }) => {
if (data && data.code === 0) {
this.conditionList = data.rows || []
} else {
this.conditionList = []
}
})
},
handleConditionSelection (val) {
this.conditionSelection = val
},
openConditionAdd () {
if (!this.currentRule.ruleCode) {
this.$message.warning('请先选择规则')
return
}
let selected = null
if (this.conditionSelection.length === 1) {
selected = this.conditionSelection[0]
}
if (selected && selected.parentConditionNo) {
this.$message.warning('仅支持一层树结构,不能在子条件下继续新增')
return
}
const parentConditionNo = selected ? selected.conditionNo : ''
this.conditionEditTitle = '新增触发条件'
this.conditionForm = {
mode: 'add',
site: this.currentRule.site,
buNo: this.currentRule.buNo,
ruleCode: this.currentRule.ruleCode,
conditionNo: this.generateConditionNo(parentConditionNo),
parentConditionNo: parentConditionNo,
relationField: '',
compareSymbol: '>',
conditionParam: null,
forceType: '强制',
warningLevel: '一般',
animationEffect: '系统默认',
responsibilityDept: '',
triggerEvent: '异常代码'
}
this.conditionEditVisible = true
},
onParentConditionChange (parentConditionNo) {
if (this.conditionForm.mode !== 'add') {
return
}
this.conditionForm.conditionNo = this.generateConditionNo(parentConditionNo || '')
},
openConditionEdit (row) {
this.conditionEditTitle = '编辑触发条件'
this.conditionForm = {
mode: 'edit',
site: row.site,
buNo: row.buNo,
ruleCode: row.ruleCode,
conditionNo: row.conditionNo,
parentConditionNo: row.parentConditionNo,
relationField: row.relationField,
compareSymbol: row.compareSymbol,
conditionParam: row.conditionParam,
forceType: row.forceType,
warningLevel: row.warningLevel,
animationEffect: row.animationEffect,
responsibilityDept: row.responsibilityDept,
triggerEvent: row.triggerEvent
}
this.conditionEditVisible = true
},
saveCondition () {
if (!this.conditionForm.conditionNo) {
this.$message.warning('请输入条件编号')
return
}
if (this.conditionForm.parentConditionNo && this.conditionForm.parentConditionNo === this.conditionForm.conditionNo) {
this.$message.warning('父条件编号不能等于条件编号')
return
}
if (!this.conditionForm.relationField) {
this.$message.warning('请选择关系字段')
return
}
if (!this.conditionForm.compareSymbol) {
this.$message.warning('请选择比较符')
return
}
if (this.conditionForm.conditionParam === null || this.conditionForm.conditionParam === '' || this.conditionForm.conditionParam === undefined) {
this.$message.warning('请输入条件参数')
return
}
if (!this.conditionForm.forceType) {
this.$message.warning('请选择是否强制')
return
}
if (!this.conditionForm.triggerEvent) {
this.$message.warning('请选择触发异常事件')
return
}
if (this.conditionForm.mode === 'add') {
saveSceneExceptionRuleCondition(this.conditionForm).then(({ data }) => {
if (data && data.code === 0) {
this.conditionEditVisible = false
this.$message.success('操作成功')
this.getConditionList()
} else {
this.$message.error(data.msg)
}
})
} else {
updateSceneExceptionRuleCondition(this.conditionForm).then(({ data }) => {
if (data && data.code === 0) {
this.conditionEditVisible = false
this.$message.success('操作成功')
this.getConditionList()
} else {
this.$message.error(data.msg)
}
})
}
},
deleteCondition () {
if (this.conditionSelection.length === 0) {
this.$message.warning('请勾选要删除的触发条件')
return
}
this.$confirm('是否删除选中的触发条件?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
deleteSceneExceptionRuleCondition({ submitList: this.conditionSelection }).then(({ data }) => {
if (data && data.code === 0) {
this.$message.success('操作成功')
this.conditionSelection = []
this.getConditionList()
} else {
this.$message.error(data.msg)
}
})
})
},
generateConditionNo (parentConditionNo) {
const flatList = this.flatConditionList(this.conditionList)
if (!parentConditionNo) {
let maxNo = 0
flatList.forEach(item => {
if (!item.parentConditionNo) {
const currentNo = parseInt(item.conditionNo, 10)
if (!isNaN(currentNo) && currentNo > maxNo) {
maxNo = currentNo
}
}
})
return String(maxNo + 1)
}
let maxChildNo = 0
flatList.forEach(item => {
if (item.parentConditionNo === parentConditionNo) {
const splitArr = (item.conditionNo || '').split('-')
const lastNo = parseInt(splitArr[splitArr.length - 1], 10)
if (!isNaN(lastNo) && lastNo > maxChildNo) {
maxChildNo = lastNo
}
}
})
return parentConditionNo + '-' + (maxChildNo + 1)
},
flatConditionList (list) {
let flatList = []
;(list || []).forEach(item => {
flatList.push(item)
if (item.children && item.children.length > 0) {
flatList = flatList.concat(item.children)
}
})
return flatList
}
}
}
</script>
<style scoped>
.mod-config /deep/ .exception-rule-main-table td {
padding-top: 8px !important;
padding-bottom: 8px !important;
}
.mod-config /deep/ .exception-rule-main-table .cell {
height: auto !important;
line-height: 20px !important;
}
.mod-config /deep/ .exception-rule-main-table .el-tag {
height: 20px;
line-height: 18px;
display: inline-flex;
align-items: center;
}
</style>
Loading…
Cancel
Save