完成 电能质量问题管理页面 修改 谐波普测管理页面

This commit is contained in:
GGJ
2024-04-10 20:33:20 +08:00
parent 926112d2a7
commit 071ee4d2b5
23 changed files with 1242 additions and 524 deletions

View File

@@ -1,45 +1,54 @@
<template>
<div>
<div>
<TableHeader area datePicker ref="TableHeaderRef">
<template #select>
<el-form-item label="问题来源">
<el-select
v-model="tableStore.table.params.problemSources"
clearable
placeholder="请选择问题来源"
>
<el-option
v-for="item in problemData"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="填报进度">
<el-select v-model="tableStore.table.params.reportProcess" clearable placeholder="请选择填报进度">
<el-option
v-for="item in fillingProgress"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<TableHeader area datePicker ref="TableHeaderRef">
<template #select>
<el-form-item label="问题来源">
<el-select v-model="tableStore.table.params.problemSources" clearable placeholder="请选择问题来源">
<el-option
v-for="item in problemData"
:key="item.code"
:label="item.name"
:value="item.code"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="填报进度">
<el-select v-model="tableStore.table.params.reportProcess" clearable placeholder="请选择填报进度">
<el-option
v-for="item in fillingProgress"
:key="item.id"
:label="item.name"
:value="item.id"
></el-option>
</el-select>
</el-form-item>
<el-form-item label="问题名称">
<el-input
v-model="tableStore.table.params.problemName"
clearable
placeholder="请输入问题名称"
style="width: 100%"
></el-input>
</el-form-item>
</template>
</TableHeader>
<Table ref="tableRef" />
</div>
<el-form-item label="问题名称">
<el-input
v-model="tableStore.table.params.problemName"
clearable
placeholder="请输入问题名称"
style="width: 100%"
></el-input>
</el-form-item>
</template>
</TableHeader>
<Table ref="tableRef" />
<!-- 审核 -->
<el-dialog draggable title="问题审核" v-model="dialogVisible" width="1400px" :before-close="beforeClose">
<Filling
ref="FillingRef"
v-if="dialogVisible"
:isDisabled="true"
:audit="true"
:flag="true"
@beforeClose="beforeClose"
/>
</el-dialog>
<!-- 审核记录 -->
<recording ref="recordingRef" />
</div>
</template>
<script setup lang="ts">
@@ -47,23 +56,25 @@ import { ref, onMounted, provide, nextTick } from 'vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import TableHeader from '@/components/table/header/index.vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { mainHeight } from '@/utils/layout'
import { useDictData } from '@/stores/dictData'
import { addUse, updateUse, removeUse } from '@/api/advance-boot/bearingCapacity'
import Filling from './filling.vue'
import recording from './recording.vue'
const dictData = useDictData()
const problemData = dictData.getBasicData('Problem_Sources')
const fillingProgress = dictData.getBasicData('Fill_Progress')
const TableHeaderRef = ref()
const FillingRef = ref()
const ruleFormRef = ref()
const list: any = ref({})
const recordingRef = ref(false)
const dialogVisible = ref(false)
const tableStore = new TableStore({
url: '/process-boot/electricityQuality/getIssues',
publicHeight: 65,
method: 'POST',
column: [
// { width: '60', type: 'checkbox' },
{
field: 'index',
title: '序号',
@@ -99,7 +110,13 @@ const tableStore = new TableStore({
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: async row => {}
click: async row => {
dialogVisible.value = true
setTimeout(() => {
list.value = row
FillingRef.value.open(row)
}, 10)
}
},
{
name: 'edit',
@@ -107,7 +124,9 @@ const tableStore = new TableStore({
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: async row => {}
click: async row => {
recordingRef.value.open(row)
}
}
]
}
@@ -124,7 +143,12 @@ tableStore.table.params.reportProcess = ''
tableStore.table.params.problemName = ''
tableStore.table.params.reportProcessStatus = 'Auditt'
const beforeClose = () => {
tableStore.index()
dialogVisible.value = false
}
provide('tableStore', tableStore)
onMounted(() => {
tableStore.index()
})

View File

@@ -166,7 +166,7 @@
</el-form>
</el-tab-pane>
<el-tab-pane label="流程" name="2">
<Filling v-if="dialogVisible" :isDisabled="true" ref="FillingRef" />
<Filling v-if="dialogVisible" :isDisabled="true" :audit="true" ref="FillingRef" />
</el-tab-pane>
</el-tabs>
</el-dialog>

View File

@@ -72,10 +72,37 @@
@handleClose="handleClose"
/>
<!-- 填报 -->
<div style="display: flex; justify-content: center; margin-top: 10px" v-show="!disabled">
<el-button type="primary" @click="Submit">提交审核</el-button>
<el-button @click="handleClose">取消</el-button>
</div>
<!-- 审核 -->
<el-form
label-width="100px"
:model="form"
ref="ruleFormRef"
:rules="rules"
v-if="disabled && audit && flag && control == active"
>
<el-form-item prop="checkComment" label="审核意见:">
<el-input
type="textarea"
style="width: 400px"
:autosize="{ minRows: 2, maxRows: 4 }"
placeholder="请输入内容"
v-model="form.checkComment"
></el-input>
</el-form-item>
</el-form>
<div
style="display: flex; justify-content: center; margin-top: 10px"
v-if="disabled && audit && flag && control == active"
>
<el-button type="primary" @click="adopt(1)">通过</el-button>
<el-button type="primary" @click="adopt(0)">不通过</el-button>
<el-button @click="handleClose">取消</el-button>
</div>
</template>
<script setup lang="ts">
import { ref, onMounted } from 'vue'
@@ -84,11 +111,13 @@ import process1 from './process1.vue'
import process2 from './process2.vue'
import process3 from './process3.vue'
import process4 from './process4.vue'
import { ElMessage } from 'element-plus'
import {
getAbnormalDetail,
getComplaintDetail,
getGeneralSurveyDetail,
getExcessiveDetail
getExcessiveDetail,
checkPowerQuality
} from '@/api/process-boot/electricitymanagement'
const emit = defineEmits(['beforeClose'])
const dictData = useDictData()
@@ -96,18 +125,31 @@ const addData: any = ref({})
const List: any = ref({})
const active = ref(4)
const control = ref()
const ruleFormRef = ref()
const stepTitle = ['原因分析', '计划整改措施', '实际采取措施', '成效分析']
const process0Ref = ref()
const process1Ref = ref()
const process2Ref = ref()
const process3Ref = ref()
const form = ref({
checkComment: ''
})
const disabled = ref(false)
const prop = defineProps({
isDisabled: {
type: Boolean,
default: false
},
audit: {
type: Boolean,
default: false
},
flag: {
type: Boolean,
default: false
}
})
const problemData = dictData.getBasicData('Problem_Sources')
const open = async (row: any) => {
addData.value = row
@@ -124,7 +166,6 @@ const open = async (row: any) => {
setTimeout(() => {
List.value = res.data
if (res.data.filePathYyfx == null) {
active.value = 0
} else if (res.data.filePathJhzg == null) {
@@ -143,9 +184,18 @@ const open = async (row: any) => {
active.value = 2
}
}
// 审核判断
if (prop.audit) {
active.value == 0 ? 0 : (active.value = active.value - 1)
}
control.value = active.value == 4 ? 3 : active.value
}, 0)
}
const rules = {
checkComment: [{ required: true, message: '请输入审核意见', trigger: 'blur' }]
}
const step = (e: number) => {
if (active.value >= e) {
@@ -176,8 +226,31 @@ const Submit = () => {
}
// 取消
const handleClose = () => {
form.value.checkComment = ''
emit('beforeClose')
}
// 审核
const adopt = (type: number) => {
ruleFormRef.value.validate((valid: any) => {
if (valid) {
const adminInfo = window.localStorage.getItem('adminInfo')
const adminName = adminInfo ? JSON.parse(adminInfo).name : ''
checkPowerQuality({
checkComment: form.value.checkComment,
checkPerson: adminName,
checkResult: type,
powerQualityProblemNo: addData.value.powerQualityProblemNo,
reportProcess: addData.value.reportProcess
}).then((res: any) => {
ElMessage.success(res.message)
handleClose()
})
}
})
}
defineExpose({ open })
</script>
<style lang="scss" scoped>

View File

@@ -15,9 +15,9 @@
<el-select v-model="tableStore.table.params.reportProcess" clearable placeholder="请选择填报进度">
<el-option
v-for="item in fillingProgress"
:key="item.id"
:key="item.code"
:label="item.name"
:value="item.id"
:value="item.code"
></el-option>
</el-select>
</el-form-item>
@@ -25,9 +25,9 @@
<el-select v-model="tableStore.table.params.reportProcessStatus" clearable placeholder="请选择审核状态">
<el-option
v-for="item in auditStatus"
:key="item.id"
:key="item.code"
:label="item.name"
:value="item.id"
:value="item.code"
></el-option>
</el-select>
</el-form-item>
@@ -49,11 +49,14 @@
<NewlyAdd v-if="showNewlyAdded" @handleClose="handleClose" @onSubmit="beforeClose" />
<!-- 填报 -->
<el-dialog draggable title="填报" v-model="dialogVisible" width="1400px" :before-close="beforeClose">
<Filling ref="FillingRef" v-if="dialogVisible"@beforeClose="beforeClose" />
<Filling ref="FillingRef" v-if="dialogVisible" @beforeClose="beforeClose" />
</el-dialog>
<!-- 详情 -->
<Detail ref="detailRef" />
<!-- 审核记录 -->
<recording ref="recordingRef" />
</template>
<script setup lang="ts">
import { ref, onMounted, provide, nextTick } from 'vue'
@@ -66,11 +69,13 @@ import { useDictData } from '@/stores/dictData'
import NewlyAdd from './NewlyAdd.vue'
import Filling from './filling.vue'
import Detail from './detail.vue'
import recording from './recording.vue'
const dictData = useDictData()
const FillingRef = ref()
const showNewlyAdded = ref(false)
const dialogVisible = ref(false)
const recordingRef = ref(false)
const TableHeaderRef = ref()
const detailRef = ref()
const problemData = dictData.getBasicData('Problem_Sources')
@@ -82,7 +87,7 @@ const tableStore: any = new TableStore({
publicHeight: 65,
method: 'POST',
column: [
{ width: '60', type: 'checkbox' },
// { width: '60', type: 'checkbox' },
{
field: 'index',
title: '序号',
@@ -182,7 +187,9 @@ const tableStore: any = new TableStore({
},
icon: 'el-icon-PieChart',
render: 'basicButton',
click: async row => {}
click: row => {
recordingRef.value.open(row)
}
},
{
name: 'del',

View File

@@ -153,7 +153,6 @@ onMounted(() => {
if (prop.List.filePathYyfx != null) {
causeAnalysisData.value = prop.List
}
console.log(prop.disabled)
})
const submit = (num: number) => {
console.log(prop.addData.problemSources)

View File

@@ -1,16 +1,43 @@
<template>
<div>
<vxe-table v-bind="defaultAttribute" height="350" ref="xTable1Ref" :data="list">
<vxe-column field="sustationName" title="变电站"></vxe-column>
<vxe-column field="barName" title="母线"></vxe-column>
<vxe-column field="measurementPointName" title="监测点名称"></vxe-column>
<el-dialog draggable v-model="dialogVisible" title="历史审核记录" width="1000px">
<vxe-table v-bind="defaultAttribute" height="500" ref="xTable1Ref" :data="list">
<vxe-column field="reportProcess" title="审核节点" :formatter="formatter"></vxe-column>
<vxe-column field="type" title="审核结果" :formatter="formatter"></vxe-column>
<vxe-column field="checker" title="审核人"></vxe-column>
<vxe-column field="orgName" title="审核人单位"></vxe-column>
<vxe-column field="dataDate" title="审核时间" min-width="100px"></vxe-column>
<vxe-column field="description" title="审核意见" min-width="180px"></vxe-column>
</vxe-table>
</div>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { queryCheckTrack } from '@/api/process-boot/electricitymanagement'
import { useDictData } from '@/stores/dictData'
const dictData = useDictData()
const problemData = dictData.getBasicData('Fill_Progress')
const auditStatus = dictData.getBasicData('Audit_Status')
const list = ref([])
const dialogVisible = ref(false)
const formatter = (row: any) => {
if (row.column.field == 'reportProcess') {
return problemData.filter((item: any) => item.code == row.cellValue)[0]?.name
} else if (row.column.field == 'type') {
return auditStatus.filter((item: any) => item.code == row.cellValue)[0]?.name
} else {
return row.cellValue
}
}
const open = (row: any) => {
dialogVisible.value = true
queryCheckTrack(row.powerQualityProblemNo).then((res: any) => {
list.value = res.data
})
}
defineExpose({ open })
</script>
<style lang="scss" scoped></style>

View File

@@ -2,20 +2,37 @@
<TableHeader area datePicker ref="TableHeaderRef">
<template #select>
<el-form-item label="计划状态">
<el-select v-model="tableStore.table.params.status" placeholder="请选择计划状态">
<el-select v-model="tableStore.table.params.status" clearable placeholder="请选择计划状态">
<el-option v-for="item in list" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
</el-form-item>
</template>
<template #operation>
<el-button icon="el-icon-Plus" type="primary" @click="add">新增计划</el-button>
<el-button icon="el-icon-Stamp" type="primary" @click="planReviewFn">提交审核</el-button>
<el-button icon="el-icon-Download" type="primary">导出</el-button>
<el-button icon="el-icon-Stamp" type="primary" @click="submit">提交审核</el-button>
<el-button icon="el-icon-Download" type="primary" @click="exportFn">导出</el-button>
</template>
</TableHeader>
</TableHeader ref="tableRef">
<Table ref="tableRef" />
<!-- 新增 -->
<planAdd ref="planAddRef" @onsubmit="tableStore.index()" />
<!-- 选择审核人 -->
<el-dialog v-model="dialogVisible" title="审核" width="300" :before-close="handleClose">
选择审核人: <el-select v-model="auditUser" clearable placeholder="请选择计划状态">
<el-option v-for="item in auditList" :key="item.id" :label="item.name" :value="item.id"></el-option>
</el-select>
<template #footer>
<span class="dialog-footer">
<el-button type="primary" @click="planReviewFn">确定</el-button>
<el-button @click="handleClose">取消</el-button>
</span>
</template>
</el-dialog>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, nextTick } from 'vue'
@@ -27,8 +44,11 @@ import { planStatus } from '@/api/process-boot/generalTest'
import planAdd from './planAdd.vue'
import { useDictData } from '@/stores/dictData'
import { initDetpStataionTree } from '@/api/process-boot/generalTest'
import { queryPlan,deletePlan } from '@/api/process-boot/generalTest'
import { getUserByRoleType } from '@/api/user-boot/user'
const dictData = useDictData()
const dialogVisible=ref(false)
const tableRef = ref()
const list = [
{
id: 0,
@@ -50,6 +70,8 @@ const list = [
const planAddRef = ref()
const TableHeaderRef = ref()
const auditList:any = ref([])
const auditUser = ref('')
const ruleFormRef = ref()
const tableStore = new TableStore({
@@ -113,6 +135,28 @@ const tableStore = new TableStore({
click: async row => {
planAddRef.value.open('编辑计划', row)
}
},
{
name: 'del',
title: '删除',
type: 'danger',
icon: 'el-icon-Delete',
render: 'confirmButton',
disabled: row => {
return !(row.status == 0 || row.status == 2)
},
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'danger',
title: '确定删除吗?'
},
click: row => {
deletePlan([row.planNo]).then(res => {
ElMessage.success('删除成功')
tableStore.index()
})
}
}
]
}
@@ -131,31 +175,61 @@ const add = () => {
// title.value = '普测计划新增'
planAddRef.value.open('普测计划新增')
}
const submit = () => {
if(tableStore.table.selection.length == 0){
return ElMessage.warning('请选择计划进行审核')
}
const flag = !tableStore.table.selection.some(item => item.status !== 0 && item.status !== 2);
if (flag) {
dialogVisible.value = true
} else {
ElMessage.warning('请选择新建、未通过的计划进行审核!')
}
}
// 提交审核
const planReviewFn = () => {
let planNo: any = []
let flag = true
tableStore.table.selection.forEach(item => {
if (item.status == 0 || item.status == 2) {
planNo.push(item.planNo)
} else {
flag = false
}
}
})
if (flag) {
planStatus(planNo).then(res => {
ElMessage.success('提交成功!')
tableStore.index()
})
} else {
ElMessage.warning('请选择新建、未通过的计划进行审核!')
}
}
const exportFn = () => {
let form = JSON.parse(JSON.stringify(tableStore.table.params))
form.pageNum = 1
form.pageSize = tableStore.table.total
queryPlan(form).then(res => {
tableRef.value.getRef().exportData({
filename: '普测计划', // 文件名字
sheetName: 'Sheet1',
type: 'xlsx', //导出文件类型 xlsx 和 csv
useStyle: true,
data: res.data.records, // 数据源 // 过滤那个字段导出
columnFilterMethod: function (column: any) {
return !(column.$columnIndex === 0)
}
})
})
}
const handleClose = () => {
dialogVisible.value = false
auditUser.value = ''
}
// 取消
onMounted(() => {
tableStore.index()
getUserByRoleType(3).then(res => {
auditList.value = res.data
})
})
</script>

View File

@@ -7,8 +7,8 @@
<el-tab-pane label="普测计划审批" name="2">
<planAudits v-if="activeName == '2'"/>
</el-tab-pane>
<el-tab-pane label="普测结果管理" name="3"><outcome v-if="activeName == '3'"/></el-tab-pane>
<el-tab-pane label="普测计划占比配置" name="4"><occupancy v-if="activeName == '4'"/></el-tab-pane>
<!-- <el-tab-pane label="普测结果管理" name="3"><outcome v-if="activeName == '3'"/></el-tab-pane>
<el-tab-pane label="普测计划占比配置" name="4"><occupancy v-if="activeName == '4'"/></el-tab-pane> -->
</el-tabs>
</div>
</template>

View File

@@ -59,20 +59,20 @@
<el-divider content-position="left" style="font-weight: bolder; font-size: 18px">
入网评估结论填报
</el-divider>
<el-form-item label="是否超标:" style="margin-top: 10px" prop="iIsOverLimit">
<el-form-item label="是否超标:" style="margin-top: 10px" prop="iIsOverLimit" @change="changeOverLimit">
<el-radio v-model="addForm.iIsOverLimit" :label="1"></el-radio>
<el-radio v-model="addForm.iIsOverLimit" :label="0"></el-radio>
</el-form-item>
<br />
<el-form-item label="超标指标:" style="margin-top: 10px" prop="IOverLimitTarget">
<br v-if="show"/>
<el-form-item label="超标指标:" style="margin-top: 10px" prop="IOverLimitTarget" v-if="show">
<el-checkbox-group v-model="addForm.IOverLimitTarget">
<el-checkbox v-for="(item, ind) in exceeded" :label="item.id">
{{ item.name }}
</el-checkbox>
</el-checkbox-group>
</el-form-item>
<br />
<el-form-item label="计划采取措施:" style="margin-top: 10px" prop="IPlanStep">
<br v-if="show"/>
<el-form-item label="计划采取措施:" style="margin-top: 10px" prop="IPlanStep" v-if="show">
<el-select v-model="addForm.IPlanStep" placeholder="请选择">
<el-option
v-for="item in takeMeasures"
@@ -94,7 +94,7 @@
</el-form-item>
</el-form>
<div style="display: flex; justify-content: center; margin-top: 30px" v-if="title != '未建档干扰源用户详情'">
<el-button type="primary" class="ml20" @click="submit(1)">提交</el-button>
<el-button type="primary" class="ml20" @click="submit(1)">审核</el-button>
<el-button type="primary" class="ml20" @click="submit(2)">保存</el-button>
<el-button type="primary" class="ml20" @click="cancel">取消</el-button>
</div>
@@ -115,7 +115,7 @@ const interferenceType = dictData.getBasicData('Interference_Source')
const emit = defineEmits(['onSubmit'])
const uploadConclusions = ref(false)
const show = ref(false)
const addForm: any = ref({
id: '',
orgNo: '',
@@ -143,7 +143,7 @@ const submit = (flag: any) => {
if (valid) {
const formData = new FormData()
addForm.value.fileList.forEach(item => {
addForm.value.fileList.forEach((item: any) => {
if (item.raw == undefined) {
} else {
formData.append('file', item.raw)
@@ -211,6 +211,15 @@ const open = (text: string, row: any) => {
uploadConclusions.value = true
}
const changeOverLimit = (e: any) => {
if (e.target.value == 0) {
show.value = false
} else {
show.value = true
}
addForm.value.IOverLimitTarget = []
addForm.value.IPlanStep = ''
}
defineExpose({ open })
</script>

View File

@@ -28,8 +28,8 @@
</template>
<template #operation>
<el-button icon="el-icon-Plus" type="primary" @click="addList">新增</el-button>
<el-button icon="el-icon-Download" type="primary">导出</el-button>
<el-button icon="el-icon-Download" @click="exportEvent" type="primary">导出</el-button>
</template>
</TableHeader>
<Table ref="tableRef" />
@@ -47,9 +47,11 @@ import { mainHeight } from '@/utils/layout'
import Add from './add.vue'
import Audit from './audit.vue'
import { useDictData } from '@/stores/dictData'
import { getLoadTypeUserList } from '@/api/process-boot/interference'
const dictData = useDictData()
const TableHeaderRef = ref()
const tableRef = ref()
const interferenceType = dictData.getBasicData('Interference_Source')
const istatusList = dictData.getBasicData('On-network_Status')
@@ -102,7 +104,7 @@ const tableStore = new TableStore({
buttons: [
{
name: 'edit',
title: '上传',
title: '审核',
type: 'primary',
disabled: row => {
return !(
@@ -152,13 +154,25 @@ provide('tableStore', tableStore)
const addList = () => {
addRef.value.open()
}
// 提交
const submit = () => {
console.log(123, fileList.value)
}
// 保存
const preservation = () => {}
// 导出
const exportEvent = () => {
let form = JSON.parse(JSON.stringify(tableStore.table.params))
form.pageNum = 1
form.pageSize = tableStore.table.total
getLoadTypeUserList(form).then(res => {
tableRef.value.getRef().exportData({
filename: '未建档非线性用户', // 文件名字
sheetName: 'Sheet1',
type: 'xlsx', //导出文件类型 xlsx 和 csv
useStyle: true,
data: res.data.records, // 数据源 // 过滤那个字段导出
columnFilterMethod: function (column: any) {
return !(column.$columnIndex === 0)
}
})
})
}
onMounted(() => {
tableStore.index()
})

View File

@@ -1,12 +1,12 @@
<template>
<div class="default-main" :style="layout">
<work />
<!-- <work /> -->
</div>
</template>
<script setup lang="ts">
import { onMounted, reactive, ref, provide } from 'vue'
import work from './work.vue'
// import work from './work.vue'
import { mainHeight } from '@/utils/layout'
defineOptions({

View File

@@ -1,416 +1,11 @@
<template>
<div v-loading.fullscreen.lock="loading" class="bpmn-dialog">
<el-dialog v-model="dialogVisible" :fullscreen="true" draggable @close="close">
<template #header>
<el-space>
<el-button icon="FolderChecked" @click="saveModeler">保存</el-button>
<el-button icon="Download" @click="downloadProcess('xml')">导出xml</el-button>
<el-button icon="Download" @click="downloadProcess('bpmn')">导出bpmn</el-button>
<el-upload
ref="uploadRef"
:auto-upload="false"
:show-file-list="false"
:limit="1"
accept="text/xml"
@change="openProcess"
>
<template #trigger>
<el-button icon="Upload">导入</el-button>
</template>
</el-upload>
</el-space>
<ul class="icon-btn">
<li v-for="item in iconBtn1" :key="item.key" :title="item.name" @click="handlerAlign(item)">
<el-icon>
<component :is="item.icon"></component>
</el-icon>
</li>
</ul>
<div> </div>
<ul class="icon-btn">
<li v-for="item in iconBtn2" :key="item.key" :title="item.name" @click="handlerReset(item)">
<el-icon>
<component :is="item.icon"></component>
</el-icon>
</li>
</ul>
</template>
<splitpanes class="default-theme bpmn-body">
<pane min-size="20">
<div ref="canvasRef" class="canvas"></div>
</pane>
<!--属性面板将通过该元素呈现到其中-->
<pane :size="25" min-size="15" style="overflow-y: auto">
<div id="js-properties-panel" class="panel"></div>
</pane>
</splitpanes>
</el-dialog>
</div>
</template>
<script lang="ts" setup name="ActDefinitionPage">
import { computed, watch, ref, nextTick } from 'vue'
import { ElMessage, type UploadFile } from 'element-plus'
import BpmnModeler from 'bpmn-js/lib/Modeler' // 引入 bpmn-js
import type { ModdleElement } from 'bpmn-js/lib/BaseModeler'
// 导入一下有关于bpmn-js的字体库以及样式文件
import 'bpmn-js/dist/assets/diagram-js.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-codes.css'
import 'bpmn-js/dist/assets/bpmn-font/css/bpmn-embedded.css'
// // 右侧属性面包样式
// import "bpmn-js-properties-panel/dist/assets/properties-panel.css";
// import "bpmn-js-properties-panel/dist/assets/element-templates.css";
// 属性面板相关模块
import {
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
CamundaPlatformPropertiesProviderModule
} from 'bpmn-js-properties-panel'
import CamundaBpmnModdle from 'camunda-bpmn-moddle/resources/camunda.json'
// 汉化包
import customTranslate from '@/assets/bpmn/translate'
// 注意这个xml文件
import createBpmnXml, { activitiToCamundaXml, camundaToActivitiXml } from './xml' // 放在下面了
// 窗格拆分器插件
import { Splitpanes, Pane } from 'splitpanes'
import 'splitpanes/dist/splitpanes.css'
import saveAs from 'file-saver'
import type CommandStack from 'diagram-js/lib/command/CommandStack'
import { getModelerDetail, updateModeler, type ActModelerObj, type XmlMetaInfo } from '@/api/activiti/modeler'
//外部参数 ################################################
const props = withDefaults(
defineProps<{
modelValue: boolean
modelId: string
}>(),
{}
)
//ref对象 ################################################
const loading = ref(false)
const iconBtn1 = ref([
{ name: '左对齐', key: 'left', icon: 'myAlignStartVertical' },
{ name: '水平居中', key: 'center', icon: 'myAlignCenterVertical' },
{ name: '右对齐', key: 'right', icon: 'myAlignEndVertical' },
{ name: '上对齐', key: 'top', icon: 'myAlignStartHorizontal' },
{ name: '垂直居中', key: 'middle', icon: 'myAlignCenterHorizontal' },
{ name: '下对齐', key: 'bottom', icon: 'myAlignEndHorizontal' }
])
const iconBtn2 = ref([
{ name: '撤销', key: 'undo', icon: 'myUndo' },
{ name: '恢复', key: 'redo', icon: 'myRedo' },
{ name: '擦除重做', key: 'restart', icon: 'myEraser' }
])
//elment ################################################
const canvasRef = ref()
const uploadRef = ref()
//emit
const emit = defineEmits<{ (event: 'update:modelValue', value: boolean): void; (event: 'close'): void }>()
//内部变量 ################################################
let bpmnModeler: BpmnModeler | undefined = undefined
let modelData: ActModelerObj = { id: '' }
//computed ################################################
const dialogVisible = computed({
get() {
return props.modelValue
},
set(value) {
emit('update:modelValue', value)
}
})
// watch ################################################
watch(dialogVisible, value => {
nextTick(() => {
if (value && !bpmnModeler) {
initModeler()
}
if (value) {
refuseModelerData()
}
})
})
// Function ################################################
/**
* 初始化 BpmnModeler
*/
const initModeler = () => {
// 将汉化包装成一个模块
const customTranslateModule = {
translate: ['value', customTranslate]
}
// 生成实例
bpmnModeler = new BpmnModeler({
container: canvasRef.value, // 获取到属性ref为“canvasRef”的dom节点
propertiesPanel: {
parent: '#js-properties-panel'
},
additionalModules: [
BpmnPropertiesPanelModule,
BpmnPropertiesProviderModule,
CamundaPlatformPropertiesProviderModule,
customTranslateModule // 汉化模块
],
moddleExtensions: {
camunda: CamundaBpmnModdle
}
})
}
/**刷新视图数据 */
const refuseModelerData = () => {
loading.value = true
getModelerDetail(props.modelId)
.then(({ data }) => {
data && (modelData = data)
const xml = data?.bpmnXml
createNewDiagram(xml ? activitiToCamundaXml(xml) : undefined)
})
.finally(() => {
loading.value = false
})
}
/**
* 对齐操作
*/
const handlerAlign = ({ key }: { key: string }) => {
if (bpmnModeler) {
const modeling = bpmnModeler.get('modeling')
const selection = bpmnModeler.get<{ get: () => ModdleElement[] }>('selection')
const align = bpmnModeler.get<ModdleElement>('alignElements')
if (modeling && selection) {
const SelectedElements = selection.get()
if (!SelectedElements || SelectedElements.length <= 1) {
return ElMessage.warning('请按住 Shift 键选择多个元素对齐')
}
align.trigger(SelectedElements, key)
}
}
}
/**
* 重置操作
*/
const handlerReset = ({ key }: { key: string }) => {
if (bpmnModeler) {
const command = bpmnModeler.get<CommandStack>('commandStack')
switch (key) {
case 'undo':
command && command.canUndo() && command.undo()
break
case 'redo':
command && command.canRedo() && command.redo()
break
case 'restart':
command && command.clear()
createNewDiagram()
break
}
}
}
/**
* 打开文件
*/
const openProcess = (rawFile: UploadFile) => {
if (!rawFile.raw) {
return false
}
loading.value = true
const reader = new FileReader()
reader.readAsText(rawFile.raw, 'utf8')
reader.onload = () => {
if (typeof reader.result === 'string' && bpmnModeler) {
if (reader.result.indexOf('bpmn2:definitions') <= 0) {
ElMessage.error('请选择bpmn20标准的流程文件')
loading.value = false
} else {
bpmnModeler
.importXML(reader.result)
.then(({ warnings }) => {
warnings && warnings.length > 0 && console.warn(warnings)
warnings && warnings.length > 0 && ElMessage.warning(warnings.toString())
})
.finally(() => {
loading.value = false
})
}
} else {
loading.value = false
}
uploadRef.value.clearFiles()
}
}
/**
* 加载bpmn.xml配置文件
*/
const createNewDiagram = (xml?: string) => {
loading.value = true
let bpmnXml = xml
if (!bpmnXml) {
const metaInfo = modelData.metaInfo ? (JSON.parse(modelData.metaInfo) as XmlMetaInfo) : {}
const param = {
key: modelData.key,
name: modelData.name,
description: metaInfo?.description,
version: metaInfo?.version
}
bpmnXml = createBpmnXml(param)
}
bpmnModeler &&
bpmnModeler
.importXML(bpmnXml)
.then(({ warnings }) => {
warnings && warnings.length > 0 && ElMessage.warning(warnings.toString())
})
.finally(() => {
loading.value = false
})
}
/**
* 保存模型
*/
const saveModeler = () => {
loading.value = true
if (!bpmnModeler) {
return
}
// 读取xml、svg
Promise.all([bpmnModeler.saveXML({}), bpmnModeler.saveSVG()])
.then(([rsp1, rsp2]) => {
const { error, xml } = rsp1
const { svg } = rsp2
if (error) {
return { code: 500, msg: error.message }
}
if (!xml) {
return { code: 500, msg: 'xml文件不存在' }
}
if (!svg) {
return { code: 500, msg: 'svg文件不存在' }
}
return updateModeler({
id: modelData.id,
name: modelData.name,
description: modelData.description,
bpmnXml: camundaToActivitiXml(xml),
svgXml: svg
})
})
.then(rsp => {
if (rsp.code === 200) {
ElMessage.success('保存成功')
} else {
ElMessage.success(rsp.msg)
}
})
.finally(() => {
loading.value = false
})
}
// 下载流程图到本地
/**
* @param {string} type
* @param {string} name
*/
const downloadProcess = (type = 'xml', name = 'diagram') => {
loading.value = true
bpmnModeler &&
bpmnModeler
.saveXML({})
.then(({ error, xml }) => {
// 读取异常时抛出异常
if (error || !xml) {
console.error(`[Process Designer Warn ]:`, error)
} else {
const blob = new Blob([camundaToActivitiXml(xml)], {
type: type === 'xml' ? 'text/xml' : 'bpmn20-xml'
})
saveAs(blob, `${name}.${type}`)
}
})
.finally(() => {
loading.value = false
})
}
const close = () => {
emit('close')
}
<script setup lang='ts'>
import { ref, reactive } from 'vue'
</script>
<style lang="scss" scoped>
<style lang="less" scoped>
.bpmn-dialog {
:deep(.el-dialog__body) {
padding: 0;
width: 100%;
height: calc(100vh - 65px);
overflow-y: auto;
}
.bpmn-body {
width: 100%;
height: 100%;
min-height: 600px;
.canvas {
width: 100%;
height: 100%;
background: url('data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDAiIGhlaWdodD0iNDAiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PHBhdHRlcm4gaWQ9ImEiIHdpZHRoPSI0MCIgaGVpZ2h0PSI0MCIgcGF0dGVyblVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHBhdGggZD0iTTAgMTBoNDBNMTAgMHY0ME0wIDIwaDQwTTIwIDB2NDBNMCAzMGg0ME0zMCAwdjQwIiBmaWxsPSJub25lIiBzdHJva2U9IiNlMGUwZTAiIG9wYWNpdHk9Ii4yIi8+PHBhdGggZD0iTTQwIDBIMHY0MCIgZmlsbD0ibm9uZSIgc3Ryb2tlPSIjZTBlMGUwIi8+PC9wYXR0ZXJuPjwvZGVmcz48cmVjdCB3aWR0aD0iMTAwJSIgaGVpZ2h0PSIxMDAlIiBmaWxsPSJ1cmwoI2EpIi8+PC9zdmc+')
repeat !important;
}
.panel {
width: 100%;
}
}
}
.icon-btn {
margin: 0;
padding: 0;
display: inline-flex;
margin-left: 30px;
li {
border-left: 1px solid var(--el-border-color);
border-top: 1px solid var(--el-border-color);
border-bottom: 1px solid var(--el-border-color);
color: var(--el-text-color-regular);
list-style: none;
font-size: 24px;
text-align: center;
cursor: pointer;
padding: 3px 8px 0 8px;
height: 32px;
}
li:hover {
background-color: #ecf5ff;
}
li:first-child {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
li:last-child {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
border-right: 1px solid var(--el-border-color);
}
.icon-popper {
width: 60px;
}
}
</style>

View File

@@ -93,12 +93,9 @@ const map = (res: any) => {
tooltip: {
formatter: function (params) {
var tips = ''
if (params.color != undefined) {
if (params.value >= 0) {
tips += params.name + '</br/>'
tips += '暂降次数' + ':' + params.value + '次' + '<br/>'
} else if (params.color == undefined) {
tips += params.name + '</br/>'
tips += '暂降次数' + ':' + '暂无数据' + '<br/>'
}
return tips
}

View File

@@ -128,7 +128,21 @@ const map = (res: any) => {
title: {
text: '区域暂降评估'
},
tooltip: {
formatter: function (params: any) {
var tips = ''
console.log('🚀 ~ map ~ params:', params)
if (Number.isNaN(params.value) == true) {
tips += params.name + '</br>'
tips += '评估值:暂无数据'
} else {
tips += params.name + '</br>'
tips += '评估值:' + params.value
}
return tips
}
},
visualMap: {
min: 0,
max: 2,

View File

@@ -59,14 +59,14 @@ import { useDictData } from '@/stores/dictData'
import Area from '@/components/form/area/index.vue'
defineOptions({
name: 'voltage/sags/operationsManagement/index'
name: 'Operationmanagement/terminalmanagement'
})
const dictData = useDictData()
const manufacturer = dictData.getBasicData('Dev_Manufacturers')
const manufacturerForm = ref<string[]>([])
const tableStore = new TableStore({
isWebPaging: true,
url: 'Operationmanagement/terminalmanagement',
url: '/device-boot/runManage/getRuntimeData',
method: 'POST',
column: [
{

View File

@@ -171,7 +171,7 @@ const tableStore = new TableStore({
type: 'bar'
},
{
name: '热备用',
name: '停运',
stack: 'one',
barMaxWidth: 30,
barMinHeight: 5,
@@ -306,7 +306,7 @@ const tableStore = new TableStore({
type: 'bar'
},
{
name: '热备用',
name: '停运',
stack: 'one',
barMaxWidth: 30,
barMinHeight: 5,