添加工程信息管理 页面

This commit is contained in:
guanj
2026-02-02 13:56:50 +08:00
parent cf4291ed9a
commit dd0dab7643
20 changed files with 1152 additions and 470 deletions

View File

@@ -1,41 +1,82 @@
import request from '@/utils/request' import request from '@/utils/request'
// 新增程序版本 // 新增程序版本
export const addEdData = (data) => { export const addEdData = data => {
return request({ return request({
url: '/cs-device-boot/edData/addEdData', url: '/cs-device-boot/edData/addEdData',
method: 'post', method: 'post',
headers: { headers: {
'Content-Type': 'multipart/form-data', 'Content-Type': 'multipart/form-data'
}, },
data: data, data: data
}) })
} }
export const auditEdData = (data) => { export const auditEdData = data => {
return request({ return request({
url: '/cs-device-boot/edData/auditEdData', url: '/cs-device-boot/edData/auditEdData',
method: 'post', method: 'post',
headers: { headers: {
'Content-Type': 'multipart/form-data', 'Content-Type': 'multipart/form-data'
}, },
data: data, data: data
}) })
} }
// 修改-删除工程 // 修改-删除工程
export const auditEngineering = (data:any)=> { export const auditEngineering = (data: any) => {
return request({ return request({
url: '/cs-device-boot/engineering/auditEngineering', url: '/cs-device-boot/engineering/auditEngineering',
method: 'post', method: 'post',
data: data, data: data
}) })
} }
// 修改项目 // 修改项目
export const updateProject = (data:any) => { export const updateProject = (data: any) => {
return request({ return request({
url: '/cs-device-boot/project/updateProject', url: '/cs-device-boot/project/updateProject',
method: 'post', method: 'post',
data: data, data: data
}) })
} }
// 新增工程
export const addEngineering = (data: any) => {
return request({
url: '/cs-device-boot/engineeringProjectRelation/addEngineering',
method: 'post',
data: data
})
}
// 修改工程
export const updateEngineering = (data: any) => {
return request({
url: '/cs-device-boot/engineeringProjectRelation/updateEngineering',
method: 'post',
data: data
})
}
// 刪除工程
export const deleteEngineering = (data: any) => {
return request({
url: '/cs-device-boot/engineeringProjectRelation/deleteEngineering',
method: 'post',
params: data
})
}
// 刪除項目
export const deleteProject = (data: any) => {
return request({
url: '/cs-device-boot/engineeringProjectRelation/deleteProject',
method: 'post',
params: data
})
}
// 新增项目
export const addProject = (data: any) => {
return request({
url: '/cs-device-boot/engineeringProjectRelation/addProject',
method: 'post',
data: data
})
}

View File

@@ -143,7 +143,7 @@ const tableStore: any = new TableStore({
}, },
loadCallback: () => { loadCallback: () => {
// 定义 x 轴标签顺序 // 定义 x 轴标签顺序
const xAxisLabels = ['闪变', '谐波电压', '谐波电流', '电压偏差', '三相不平衡'] const xAxisLabels = ['长时闪变', '谐波电压', '谐波电流', '电压偏差', '三相不平衡']
// 根据指标名称顺序提取对应的 extent 数据 // 根据指标名称顺序提取对应的 extent 数据
const chartData = xAxisLabels.map(label => { const chartData = xAxisLabels.map(label => {

View File

@@ -85,7 +85,7 @@ const tableStore: any = new TableStore({
width: '150' width: '150'
}, },
{ {
title: '闪变越限(%)', title: '长时闪变越限(%)',
field: 'flickerOvertime', field: 'flickerOvertime',
width: '90', width: '90',
render: 'customTemplate', render: 'customTemplate',

View File

@@ -88,7 +88,7 @@ const initEcharts = () => {
xAxis: { xAxis: {
// name: '(区域)', // name: '(区域)',
data: ['闪变', '谐波电压', '谐波电流', '电压偏差', '三相不平衡'] data: ['长时闪变', '谐波电压', '谐波电流', '电压偏差', '三相不平衡']
}, },
yAxis: { yAxis: {
@@ -149,7 +149,7 @@ const tableStore: any = new TableStore({
title: '越限占比(%)', title: '越限占比(%)',
children: [ children: [
{ {
title: '闪变', title: '长时闪变',
field: 'flicker', field: 'flicker',
minWidth: '70', minWidth: '70',
render: 'customTemplate', render: 'customTemplate',

View File

@@ -136,7 +136,7 @@ const initProbabilityData = () => {
// 处理接口返回的数据,转换为图表所需格式 // 处理接口返回的数据,转换为图表所需格式
if (res.data && Array.isArray(res.data)) { if (res.data && Array.isArray(res.data)) {
// 定义指标类型顺序 // 定义指标类型顺序
const indicatorOrder = ['闪变', '谐波电压', '谐波电流', '电压偏差', '三相电压不平衡度', '频率偏差'] const indicatorOrder = ['长时闪变', '谐波电压', '谐波电流', '电压偏差', '三相电压不平衡度', '频率偏差']
// 按照指定顺序排序数据 // 按照指定顺序排序数据
const sortedData = [...res.data].sort((a, b) => { const sortedData = [...res.data].sort((a, b) => {
return indicatorOrder.indexOf(a.indexName) - indicatorOrder.indexOf(b.indexName) return indicatorOrder.indexOf(a.indexName) - indicatorOrder.indexOf(b.indexName)

View File

@@ -135,7 +135,7 @@ const initProbabilityData = () => {
// 处理接口返回的数据,转换为图表所需格式 // 处理接口返回的数据,转换为图表所需格式
if (res.data && Array.isArray(res.data)) { if (res.data && Array.isArray(res.data)) {
// 定义指标类型顺序 // 定义指标类型顺序
const indicatorOrder = ['闪变', '谐波电压', '谐波电流', '电压偏差', '三相电压不平衡度', '频率偏差'] const indicatorOrder = ['长时闪变', '谐波电压', '谐波电流', '电压偏差', '三相电压不平衡度', '频率偏差']
// 按照指定顺序排序数据 // 按照指定顺序排序数据
const sortedData = [...res.data].sort((a, b) => { const sortedData = [...res.data].sort((a, b) => {
return indicatorOrder.indexOf(a.indexName) - indicatorOrder.indexOf(b.indexName) return indicatorOrder.indexOf(a.indexName) - indicatorOrder.indexOf(b.indexName)

View File

@@ -66,7 +66,7 @@
<el-option <el-option
v-for="vv in item.countOptions" v-for="vv in item.countOptions"
:key="vv" :key="vv"
:label="item.name.includes('间谐波') ? vv - 0.5 : vv" :label="item.name.includes('间谐波') ? vv - 0.5 : vv"
:value="vv" :value="vv"
></el-option> ></el-option>
</el-select> </el-select>
@@ -81,12 +81,8 @@
</template> </template>
</TableHeader> </TableHeader>
</div> </div>
<div class="history_chart" :style="pageHeight" v-loading="loading"> <div class="history_chart" :style="pageHeight" v-loading="loading">
<MyEchart <MyEchart ref="historyChart" :options="echartsData" v-if="showEchart" />
ref="historyChart"
:options="echartsData"
v-if="showEchart"
/>
<el-empty :style="pageHeight" v-else description="暂无数据" /> <el-empty :style="pageHeight" v-else description="暂无数据" />
</div> </div>
</el-dialog> </el-dialog>
@@ -160,28 +156,40 @@ const countOptions: any = ref([])
const legendDictList: any = ref([]) const legendDictList: any = ref([])
const initCode = (field: string, title: string) => { const initCode = (field: string, title: string) => {
queryByCode('steady_state_limit_trend').then(res => { queryByCode('gridSide_exceedTheLimit').then(res => {
queryCsDictTree(res.data.id).then(item => { queryCsDictTree(res.data.id).then(item => {
//排序 //排序
indexOptions.value = item.data.sort((a: any, b: any) => { indexOptions.value = item.data.sort((a: any, b: any) => {
return a.sort - b.sort return a.sort - b.sort
}) })
const titleMap: Record<string, number> = { // const titleMap: Record<string, number> = {
flickerOvertime: 0, // flickerOvertime: 0,
uaberranceOvertime: 3, // uaberranceOvertime: 3,
ubalanceOvertime: 4, // ubalanceOvertime: 4,
freqDevOvertime: 5 // freqDevOvertime: 5
} // }
let defaultIndex = 0 // 默认值 // let defaultIndex = 0 // 默认值
if (field in titleMap) { // if (field in titleMap) {
defaultIndex = titleMap[field] // defaultIndex = titleMap[field]
} else if (field.includes('uharm')) { // } else if (field.includes('uharm')) {
defaultIndex = 1 // defaultIndex = 1
} else if (field.includes('iharm')) { // } else if (field.includes('iharm')) {
defaultIndex = 2 // defaultIndex = 2
} // }
let codeKey = field.includes('flickerOvertime')
? '闪变'
: field.includes('uharm')
? '谐波电压'
: field.includes('iharm')
? '谐波电流'
: field.includes('voltageDevOvertime')
? '电压偏差'
: field.includes('ubalanceOvertime')
? '不平衡'
: ''
let defaultIndex = indexOptions.value.findIndex((item: any) => item.name.includes(codeKey)) || 0
searchForm.value.index[0] = indexOptions.value[defaultIndex].id searchForm.value.index[0] = indexOptions.value[defaultIndex].id
}) })
@@ -294,7 +302,7 @@ const init = async () => {
} }
lists[index] = { lists[index] = {
statisticalId: item.index, statisticalId: item.index,
frequency: frequencys !== null && frequencys !== undefined ? String(frequencys) : '' frequency: frequencys !== null && frequencys !== undefined ? String(frequencys) : ''
} }
}) })
let obj = { let obj = {
@@ -579,7 +587,6 @@ const setTimeControl = () => {
} }
const selectChange = (flag: boolean, height: any) => { const selectChange = (flag: boolean, height: any) => {
pageHeight.value = mainHeight(height * 1.6, 1.6) pageHeight.value = mainHeight(height * 1.6, 1.6)
} }
//导出 //导出

View File

@@ -86,7 +86,7 @@ const tableStore: any = new TableStore({
width: '150' width: '150'
}, },
{ {
title: '闪变越限(分钟)', title: '越限(分钟)',
field: 'flickerOvertime', field: 'flickerOvertime',
width: '90', width: '90',
render: 'customTemplate', render: 'customTemplate',
@@ -101,6 +101,14 @@ const tableStore: any = new TableStore({
{ {
title: '谐波电流越限(分钟)', title: '谐波电流越限(分钟)',
children: loop50('iharm') children: loop50('iharm')
}, {
title: '电压偏差越限(分钟)',
field: 'uaberranceOvertime',
width: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.uaberranceOvertime}</span>`
}
}, },
{ {
title: '三相不平衡度越限(分钟)', title: '三相不平衡度越限(分钟)',
@@ -111,24 +119,16 @@ const tableStore: any = new TableStore({
return `<span style='cursor: pointer;text-decoration: underline;'>${row.ubalanceOvertime}</span>` return `<span style='cursor: pointer;text-decoration: underline;'>${row.ubalanceOvertime}</span>`
} }
}, },
{
title: '电压偏差越限(分钟)', // {
field: 'uaberranceOvertime', // title: '频率偏差越限(分钟)',
width: '100', // field: 'freqDevOvertime',
render: 'customTemplate', // width: '100',
customTemplate: (row: any) => { // render: 'customTemplate',
return `<span style='cursor: pointer;text-decoration: underline;'>${row.uaberranceOvertime}</span>` // customTemplate: (row: any) => {
} // return `<span style='cursor: pointer;text-decoration: underline;'>${row.freqDevOvertime}</span>`
}, // }
{ // }
title: '频率偏差越限(分钟)',
field: 'freqDevOvertime',
width: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.freqDevOvertime}</span>`
}
}
], ],
beforeSearchFun: () => { beforeSearchFun: () => {
}, },

View File

@@ -69,7 +69,7 @@ const tableStore: any = new TableStore({
width: '150' width: '150'
}, },
{ {
title: '闪变越限(分钟)', title: '长时闪变越限(分钟)',
field: 'flicker', field: 'flicker',
width: '80' width: '80'
}, },
@@ -99,26 +99,7 @@ const tableStore: any = new TableStore({
], ],
beforeSearchFun: () => {}, beforeSearchFun: () => {},
loadCallback: () => { loadCallback: () => {
tableStore.table.data = [
{
time: '2024-01-01 00:00:00',
name: '35kV进线',
flicker: '0',
},
{
time: '2024-01-01 00:00:00',
name: '35kV进线',
flicker: '0',
},
{
time: '2024-01-01 00:00:00',
name: '35kV进线',
flicker: '0',
},
]
} }
}) })

View File

@@ -84,7 +84,7 @@ const tableStore: any = new TableStore({
width: '150' width: '150'
}, },
{ {
title: '闪变越限(分钟)', title: '长时闪变越限(分钟)',
field: 'flicker', field: 'flicker',
width: '80', width: '80',
render: 'customTemplate', render: 'customTemplate',

View File

@@ -85,7 +85,7 @@ const tableStore: any = new TableStore({
width: '150' width: '150'
}, },
{ {
title: '闪变越限(%)', title: '长时闪变越限(%)',
field: 'flickerOvertime', field: 'flickerOvertime',
width: '90', width: '90',
render: 'customTemplate', render: 'customTemplate',
@@ -101,16 +101,7 @@ const tableStore: any = new TableStore({
title: '谐波电流越限(%)', title: '谐波电流越限(%)',
children: loop50('iharm') children: loop50('iharm')
}, },
{ {
title: '三相不平衡度越限(%)',
field: 'ubalanceOvertime',
width: '100',
render: 'customTemplate',
customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.ubalanceOvertime}</span>`
}
},
{
title: '电压偏差越限(%)', title: '电压偏差越限(%)',
field: 'voltageDevOvertime', field: 'voltageDevOvertime',
width: '100', width: '100',
@@ -120,14 +111,24 @@ const tableStore: any = new TableStore({
} }
}, },
{ {
title: '频率偏差越限(%)', title: '三相不平衡度越限(%)',
field: 'freqDevOvertime', field: 'ubalanceOvertime',
width: '100', width: '100',
render: 'customTemplate', render: 'customTemplate',
customTemplate: (row: any) => { customTemplate: (row: any) => {
return `<span style='cursor: pointer;text-decoration: underline;'>${row.freqDevOvertime}</span>` return `<span style='cursor: pointer;text-decoration: underline;'>${row.ubalanceOvertime}</span>`
} }
} },
// {
// title: '频率偏差越限(%)',
// field: 'freqDevOvertime',
// width: '100',
// render: 'customTemplate',
// customTemplate: (row: any) => {
// return `<span style='cursor: pointer;text-decoration: underline;'>${row.freqDevOvertime}</span>`
// }
// }
], ],
beforeSearchFun: () => { beforeSearchFun: () => {
}, },

View File

@@ -85,7 +85,7 @@ const tableStore: any = new TableStore({
width: '150' width: '150'
}, },
{ {
title: '闪变越限(%)', title: '长时闪变越限(%)',
field: 'flickerOvertime', field: 'flickerOvertime',
width: '90', width: '90',
render: 'customTemplate', render: 'customTemplate',

View File

@@ -89,7 +89,7 @@ const initEcharts = () => {
xAxis: { xAxis: {
// name: '(区域)', // name: '(区域)',
data: ['闪变', '谐波电压', '谐波电流', '电压偏差', '三相不平衡'] data: ['长时闪变', '谐波电压', '谐波电流', '电压偏差', '三相不平衡']
}, },
yAxis: { yAxis: {
@@ -150,7 +150,7 @@ const tableStore: any = new TableStore({
title: '越限占比(%)', title: '越限占比(%)',
children: [ children: [
{ {
title: '闪变', title: '长时闪变',
field: 'flicker', field: 'flicker',
minWidth: '70', minWidth: '70',
render: 'customTemplate', render: 'customTemplate',

View File

@@ -481,7 +481,33 @@
:disabled="true" :disabled="true"
></el-input> ></el-input>
</el-form-item> </el-form-item>
<el-form-item
class="form-item"
label="日志等级:"
:prop="'deviceInfoList[' + bIndex + '].devLogLevel'"
>
<el-select
clearable
filterable
v-model="busItem.devLogLevel"
placeholder="请选择日志等级"
style="width: 100%"
:disabled="
!(
(nodeLevel == 3 && pageStatus == 3) ||
((nodeLevel == 2 || (nodeLevel == 1 && pageStatus == 2)) &&
pageStatus == 2)
)
"
>
<el-option
v-for="value in logList"
:key="value.value"
:label="value.label"
:value="value.value"
></el-option>
</el-select>
</el-form-item>
<el-form-item <el-form-item
class="form-item" class="form-item"
label="排序:" label="排序:"
@@ -939,7 +965,7 @@
class="form-item" class="form-item"
label="是否治理:" label="是否治理:"
:prop="'lineInfoList[' + lIndex + '].govern'" :prop="'lineInfoList[' + lIndex + '].govern'"
:rules="{ required: true, message: '请选择是否治理', trigger: 'blur' }" :rules="{ required: true, message: '请选择是否治理', trigger: 'change' }"
> >
<el-select <el-select
clearable clearable
@@ -985,6 +1011,35 @@
<el-option label="退运" :value="4" /> <el-option label="退运" :value="4" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item
class="form-item"
label="日志等级:"
:prop="'lineInfoList[' + lIndex + '].lineLogLevel'"
:rules="{ required: true, message: '请选择日志等级', trigger: 'change' }"
>
<!-- 0运行1检修2停运3调试4退运 -->
<el-select
clearable
filterable
v-model="lineItem.lineLogLevel"
placeholder="请选择日志等级"
:disabled="
!(
(nodeLevel == 4 && pageStatus == 3) ||
((nodeLevel == 3 || (nodeLevel == 2 && pageStatus == 2)) &&
pageStatus == 2)
)
"
>
<el-option
v-for="value in logList"
:key="value.value"
:label="value.label"
:value="value.value"
></el-option>
</el-select>
</el-form-item>
</div> </div>
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
@@ -1159,6 +1214,24 @@ const lineSpaceArr = ref([
{ name: '5分钟', value: 5 }, { name: '5分钟', value: 5 },
{ name: '10分钟', value: 10 } { name: '10分钟', value: 10 }
]) ])
const logList = ref([
{
value: 'DEBUG',
label: 'DEBUG'
},
{
value: 'NORMAL',
label: 'NORMAL'
},
{
value: 'WARN',
label: 'WARN'
},
{
value: 'ERROR',
label: 'ERROR'
}
])
//工程 //工程
// const engineeringParam = ref({ // const engineeringParam = ref({
// city: '', // city: '',
@@ -1179,6 +1252,7 @@ interface DeviceInfo {
devModel: string devModel: string
devType: string devType: string
devAccessMethod: string devAccessMethod: string
devLogLevel: string
mac: string mac: string
ndid: string ndid: string
nodeId: string nodeId: string
@@ -1203,6 +1277,7 @@ interface LineInfo {
monitorObj: string monitorObj: string
position: string position: string
govern: string | number govern: string | number
lineLogLevel: string
runStatus: string | number runStatus: string | number
basicCapacity: number basicCapacity: number
shortCircuitCapacity: number shortCircuitCapacity: number
@@ -1555,6 +1630,7 @@ const add = () => {
devModel: '', devModel: '',
devType: '', devType: '',
devAccessMethod: 'CLD', devAccessMethod: 'CLD',
devLogLevel: 'WARN',
mac: '', mac: '',
ndid: '', ndid: '',
nodeId: '', nodeId: '',
@@ -1583,6 +1659,7 @@ const add = () => {
monitorObj: '', monitorObj: '',
position: '', position: '',
govern: 0, govern: 0,
lineLogLevel: 'WARN',
runStatus: 0, runStatus: 0,
basicCapacity: 0, basicCapacity: 0,
shortCircuitCapacity: 0, shortCircuitCapacity: 0,
@@ -1697,6 +1774,7 @@ const updateEquipmentFunc = (id: any) => {
devModel: currentDevice.devModel, devModel: currentDevice.devModel,
devType: currentDevice.devType, devType: currentDevice.devType,
devAccessMethod: currentDevice.devAccessMethod, devAccessMethod: currentDevice.devAccessMethod,
devLogLevel: currentDevice.devLogLevel,
mac: currentDevice.mac, mac: currentDevice.mac,
nodeId: currentDevice.nodeId, nodeId: currentDevice.nodeId,
cntractNo: currentDevice.cntractNo, cntractNo: currentDevice.cntractNo,
@@ -1760,6 +1838,7 @@ const updateLineFunc = (id: any) => {
monitorObj: currentLine.monitorObj || '', monitorObj: currentLine.monitorObj || '',
position: currentLine.position || '', position: currentLine.position || '',
govern: currentLine.govern, govern: currentLine.govern,
lineLogLevel: currentLine.lineLogLevel,
runStatus: currentLine.runStatus, runStatus: currentLine.runStatus,
basicCapacity: currentLine.basicCapacity || 0, basicCapacity: currentLine.basicCapacity || 0,
shortCircuitCapacity: currentLine.shortCircuitCapacity || 0, shortCircuitCapacity: currentLine.shortCircuitCapacity || 0,
@@ -1925,6 +2004,7 @@ const next = async () => {
devModel: '', devModel: '',
devType: '', devType: '',
devAccessMethod: 'CLD', devAccessMethod: 'CLD',
devLogLevel: 'WARN',
mac: '', mac: '',
ndid: '', ndid: '',
nodeId: '', nodeId: '',
@@ -1957,6 +2037,7 @@ const next = async () => {
monitorObj: '', monitorObj: '',
position: '', position: '',
govern: 0, govern: 0,
lineLogLevel:'WARN',
runStatus: 0, runStatus: 0,
basicCapacity: 0, basicCapacity: 0,
shortCircuitCapacity: 0, shortCircuitCapacity: 0,
@@ -2361,6 +2442,8 @@ const resetAllForms = () => {
device.devModel = '' device.devModel = ''
device.devType = '' device.devType = ''
device.devAccessMethod = 'CLD' device.devAccessMethod = 'CLD'
device.devLogLevel = 'WARN'
device.mac = '' device.mac = ''
device.nodeId = '' device.nodeId = ''
device.cntractNo = '' device.cntractNo = ''
@@ -2382,6 +2465,7 @@ const resetAllForms = () => {
line.monitorObj = '' line.monitorObj = ''
line.position = '' line.position = ''
line.govern = 0 line.govern = 0
line.lineLogLevel = 'WARN'
line.runStatus = 0 line.runStatus = 0
line.basicCapacity = 0 line.basicCapacity = 0
line.shortCircuitCapacity = 0 line.shortCircuitCapacity = 0
@@ -2480,6 +2564,7 @@ const submitData = () => {
devModel: currentDevice.devModel, devModel: currentDevice.devModel,
devType: currentDevice.devType, devType: currentDevice.devType,
devAccessMethod: currentDevice.devAccessMethod, devAccessMethod: currentDevice.devAccessMethod,
devLogLevel: currentDevice.devLogLevel,
mac: currentDevice.mac, mac: currentDevice.mac,
nodeId: currentDevice.nodeId, nodeId: currentDevice.nodeId,
cntractNo: currentDevice.cntractNo, cntractNo: currentDevice.cntractNo,
@@ -2550,6 +2635,7 @@ const submitData = () => {
monitorObj: currentLine.monitorObj, monitorObj: currentLine.monitorObj,
position: currentLine.position, position: currentLine.position,
govern: currentLine.govern, govern: currentLine.govern,
lineLogLevel: currentLine.lineLogLevel,
runStatus: currentLine.runStatus, runStatus: currentLine.runStatus,
basicCapacity: currentLine.basicCapacity, basicCapacity: currentLine.basicCapacity,
shortCircuitCapacity: currentLine.shortCircuitCapacity, shortCircuitCapacity: currentLine.shortCircuitCapacity,
@@ -2664,6 +2750,7 @@ const handleBusBarTabsEdit = (targetName: any, action: any) => {
devModel: '', devModel: '',
devType: '', devType: '',
devAccessMethod: 'CLD', devAccessMethod: 'CLD',
devLogLevel: 'WARN',
mac: '', mac: '',
ndid: '', ndid: '',
nodeId: '', nodeId: '',
@@ -2740,6 +2827,7 @@ const handleLineTabsEdit = (targetName: any, action: any) => {
monitorObj: '', monitorObj: '',
position: '', position: '',
govern: 0, govern: 0,
lineLogLevel: 'WARN',
runStatus: 0, runStatus: 0,
basicCapacity: 0, basicCapacity: 0,
shortCircuitCapacity: 0, shortCircuitCapacity: 0,

View File

@@ -106,7 +106,6 @@ const rules = ref({
area: [{ required: true, message: '请输入区域', trigger: 'blur' }], area: [{ required: true, message: '请输入区域', trigger: 'blur' }],
description: [{ required: true, message: '请输入描述', trigger: 'blur' }] description: [{ required: true, message: '请输入描述', trigger: 'blur' }]
}) })
console.log("🚀 ~ dictData.state.areaTree:", dictData.state)
const areaTree: any = tree const areaTree: any = tree
const props = { const props = {
@@ -202,7 +201,6 @@ const save = () => {
} }
}) })
} }
</script> </script>
<style lang="scss"> <style lang="scss">
.customInput { .customInput {

View File

@@ -0,0 +1,221 @@
<template>
<el-dialog draggable class="cn-operate-dialog" width="520px" v-model.trim="dialogVisible" :title="title">
<el-form :inline="false" ref="formRef" :model="form" label-width="auto" class="form-one" :rules="rules">
<el-form-item label="项目名称" prop="name">
<el-input maxlength="32" show-word-limit v-model.trim="form.name" placeholder="请输入项目名称" />
</el-form-item>
<el-form-item label="所属工程" prop="engineeringId">
<el-select v-model="form.engineeringId" filterable placeholder="请选择工程" clearable>
<el-option
v-for="item in engineeringList"
:key="item.engineeringId"
:label="item.engineeringName"
:value="item.engineeringId"
/>
</el-select>
</el-form-item>
<el-form-item label="区域" prop="area">
<el-input v-model="form.area" clearable placeholder="请输入区域" />
</el-form-item>
<el-form-item label="备注" prop="description">
<el-input v-model="form.description" :rows="2" type="textarea" clearable placeholder="请输入备注" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input maxlength="32" show-word-limit-number v-model.number="form.sort" :min="0" />
</el-form-item>
<el-form-item label="拓扑图" prop="sort">
<div class="image-radio-group">
<div
class="image-radio-item"
v-for="item in images"
:key="item.id"
@click="handleSelect(item.id)"
>
<el-radio :label="item.id" v-model="form.topoIds" class="hidden-radio">
{{ item.name }}
</el-radio>
<div class="image-container" :class="{ selected: form.topoIds === item.id }">
<img :src="item.url" v-if="item.url" class="image-preview" />
<div v-else style="width: 120px; height: 90px; text-align: center; line-height: 90px">
暂无图片
</div>
<div class="image-overlay" v-if="form.topoIds === item.id">
<el-icon class="check-icon"><Check /></el-icon>
</div>
</div>
<div class="image-name">{{ item.name }}</div>
</div>
</div>
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submit">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, inject } from 'vue'
import { reactive } from 'vue'
import TableStore from '@/utils/tableStore'
import { ElMessage } from 'element-plus'
import { add, update } from '@/api/user-boot/role'
import { useAdminInfo } from '@/stores/adminInfo'
import { addProject, updateProject } from '@/api/cs-device-boot/edData'
import { getTopoTemplate } from '@/api/cs-device-boot/topologyTemplate'
import { getFileUrl } from '@/api/system-boot/file'
const adminInfo = useAdminInfo()
const tableStore = inject('tableStore') as TableStore
// do not use same name with ref
const form = reactive({
name: '',
id: '',
engineeringId: '',
area: '',
sort: 100,
description: '',
topoIds: ''
})
const engineeringList: any = ref([])
const rules = {
name: [{ required: true, message: '请输入项目名称', trigger: 'blur' }],
area: [{ required: true, message: '请输入区域', trigger: 'blur' }],
engineeringId: [{ required: true, message: '请输入工程', trigger: 'blur' }],
description: [{ required: true, message: '请输入描述', trigger: 'blur' }],
sort: [{ required: true, message: '请输入排序', trigger: 'blur' }]
}
const dialogVisible = ref(false)
const title = ref('新增菜单')
const formRef = ref()
const props = {
label: 'text',
value: 'value',
children: 'children'
// checkStrictly: true
}
const open = (text: string, List: any, data?: anyObj, id?: string) => {
getImageList().catch(() => {})
formRef.value?.resetFields()
title.value = text
dialogVisible.value = true
engineeringList.value = List
if (data) {
form.id = data.projectId
form.name = data.projectName
form.area = data.projectArea
form.description = data.projectRemark
form.sort = data.projectSort
form.engineeringId = id || ''
form.topoIds = data.topologyInfoId || ''
} else {
form.id = ''
form.name = ''
form.area = ''
form.description = ''
form.engineeringId = ''
form.topoIds = ''
form.sort = 100
}
}
const submit = async () => {
formRef.value.validate(async valid => {
console.log("🚀 ~ submit ~ form.topoIds:", form.topoIds)
if (valid) {
if (form.id) {
await updateProject({ ...form ,topoIds:[form.topoIds]})
} else {
await addProject({ ...form,topoIds:[form.topoIds] })
}
ElMessage.success('保存成功')
tableStore.index()
dialogVisible.value = false
}
})
}
const images: any = ref([])
const getImageList = async () => {
getTopoTemplate().then(res => {
images.value = res.data
images.value.forEach(async item => {
let row = await getFileUrl({ filePath: item.filePath })
item.url = row.data
})
})
}
const handleSelect = (filePath: any) => {
form.topoIds = filePath
}
defineExpose({ open })
</script>
<style scoped>
.image-radio-group {
display: flex;
gap: 20px;
flex-wrap: wrap;
}
.image-radio-item {
cursor: pointer;
text-align: center;
}
.hidden-radio {
display: none;
}
.image-container {
position: relative;
border: 2px solid #dcdfe6;
border-radius: 8px;
overflow: hidden;
transition: all 0.3s;
}
.image-container:hover {
border-color: var(--el-color-primary);
}
.image-container.selected {
border-color: var(--el-color-primary);
/* box-shadow: 0 0 8px rgba(64, 158, 255, 0.3); */
}
.image-preview {
width: 120px;
height: 90px;
}
.image-overlay {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
/* background-color: rgba(64, 158, 255, 0.1); */
display: flex;
align-items: center;
justify-content: center;
}
.check-icon {
color: var(--el-color-primary);
font-size: 24px;
}
.image-name {
margin-top: 8px;
font-size: 14px;
width: 120px;
white-space: nowrap; /* 强制文字单行显示,不换行 */
overflow: hidden; /* 隐藏超出容器的文字 */
text-overflow: ellipsis; /* 超出部分显示省略号(点点点) */
}
</style>

View File

@@ -0,0 +1,106 @@
<template>
<el-dialog draggable class="cn-operate-dialog" width="500px" v-model.trim="dialogVisible" :title="title">
<el-form :inline="false" ref="formRef" :model="form" label-width="auto" class="form-one" :rules="rules">
<el-form-item label="工程名称" prop="name">
<el-input maxlength="32" show-word-limit v-model.trim="form.name" placeholder="请输入工程名称" />
</el-form-item>
<el-form-item label="区域" prop="city">
<el-cascader
v-model="form.city"
style="width: 100%"
:options="areaTree"
:props="props"
clearable
filterable
placeholder="请选择区域"
/>
</el-form-item>
<el-form-item label="备注" prop="description">
<el-input v-model="form.description" :rows="2" type="textarea" clearable placeholder="请输入备注" />
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input maxlength="32" show-word-limit-number v-model.number="form.sort" :min="0" />
</el-form-item>
</el-form>
<template #footer>
<span class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="submit">确认</el-button>
</span>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref, inject } from 'vue'
import { reactive } from 'vue'
import TableStore from '@/utils/tableStore'
import { ElMessage } from 'element-plus'
import { add, update } from '@/api/user-boot/role'
import { useAdminInfo } from '@/stores/adminInfo'
import { addEngineering, updateEngineering } from '@/api/cs-device-boot/edData'
const adminInfo = useAdminInfo()
const tableStore = inject('tableStore') as TableStore
import tree from '@/assets/map/area.json'
// do not use same name with ref
const form = reactive({
name: '',
id: '',
pid: 0,
city: '',
sort: 100,
description: ''
})
const areaTree: any = tree
const rules = {
name: [{ required: true, message: '请输入工程名称', trigger: 'blur' }],
city: [{ required: true, message: '请输入区域', trigger: 'blur' }],
area: [{ required: true, message: '请输入区域', trigger: 'blur' }],
description: [{ required: true, message: '请输入描述', trigger: 'blur' }],
sort: [{ required: true, message: '请输入排序', trigger: 'blur' }]
}
const dialogVisible = ref(false)
const title = ref('新增菜单')
const formRef = ref()
const props = {
label: 'text',
value: 'value',
children: 'children',
// checkStrictly: true
}
const open = (text: string, data?: anyObj) => {
formRef.value?.resetFields()
title.value = text
dialogVisible.value = true
if (data) {
form.id = data.engineeringId
form.name = data.engineeringName
form.city = [data.provinceId,data.cityId]
form.description = data.engineeringRemark
form.sort = data.engineeringSort
} else {
form.id = ''
form.name = ''
form.city = ''
form.description = ''
form.sort = 100
}
}
const submit = async () => {
formRef.value.validate(async valid => {
if (valid) {
if (form.id) {
await updateEngineering({ ...form, province: form.city[0], city: form.city[1] || '' })
} else {
await addEngineering({ ...form, province: form.city[0], city: form.city[1]||'' })
}
ElMessage.success('保存成功')
tableStore.index()
dialogVisible.value = false
}
})
}
defineExpose({ open })
</script>

View File

@@ -0,0 +1,239 @@
<template>
<div class="default-main">
<div style="display: flex">
<div style="width: 800px">
<div class="custom-table-header">
<div class="title">工程列表</div>
<el-button :icon="Plus" type="primary" @click="addRole" class="ml10">新增工程</el-button>
</div>
<Table ref="tableRef" @currentChange="currentChange" />
</div>
<div style="flex: 1">
<div class="custom-table-header">
<div class="title">項目列表</div>
<el-button type="primary" icon="el-icon-Plus" @click="add">新增項目</el-button>
</div>
<div :style="height">
<vxe-table
ref="tableRef1"
v-bind="defaultAttribute"
:data="itemList"
height="auto"
style="width: 100%"
>
<vxe-column field="projectName" title="项目名称"></vxe-column>
<vxe-column field="projectArea" title="地址"></vxe-column>
<vxe-column title="拓扑图">
<template #default="{ row }">
<el-image
:hide-on-click-modal="true"
:preview-teleported="true"
:preview-src-list="[row.topologyImageUrl]"
:src="getUrl(row) ? row.topologyImageUrl : ''"
></el-image>
</template>
</vxe-column>
<vxe-column field="projectRemark" title="备注"></vxe-column>
<vxe-column field="projectSort" title="排序" width="80px"></vxe-column>
<vxe-column title="操作" width="180px">
<template #default="{ row }">
<el-button
style="margin-left: 4px"
type="primary"
link
size="small"
@click="itemModification(row)"
class="ml10 mr10"
>
编辑
</el-button>
<el-popconfirm
@confirm="itemeRemove(row)"
title="确定删除吗?"
confirm-button-type="danger"
>
<template #reference>
<el-button style="margin-left: 4px" type="danger" size="small" link>
刪除
</el-button>
</template>
</el-popconfirm>
</template>
</vxe-column>
</vxe-table>
</div>
</div>
</div>
<!-- 新增工程 -->
<popup ref="popupRef" @save="save" />
<!-- 新增項目 -->
<itemAdd ref="itemAddRef" @save="save" />
</div>
</template>
<script setup lang="ts">
import { ref, onMounted, provide, nextTick } from 'vue'
import { Plus } from '@element-plus/icons-vue'
import TableStore from '@/utils/tableStore'
import Table from '@/components/table/index.vue'
import { delTemplate, deleteSysExcel, bandRelation, queryList } from '@/api/harmonic-boot/luckyexcel'
import { deleteProject ,deleteEngineering} from '@/api/cs-device-boot/edData'
import { useDictData } from '@/stores/dictData'
import { ElMessage } from 'element-plus'
import { defaultAttribute } from '@/components/table/defaultAttribute'
import { mainHeight } from '@/utils/layout'
import popup from './components/popup.vue'
import itemAdd from './components/itemAdd.vue'
const dictData = useDictData()
defineOptions({
name: 'govern/manage/engineering'
})
const height = mainHeight(80)
const volConTypeList: any = dictData.getBasicData('Dev_Connect')
import { getFileUrl } from '@/api/system-boot/file'
const popupRef = ref()
const tableRef = ref()
const tableRef1 = ref()
const itemList = ref([])
const menuListId = ref([])
const itemAddRef = ref()
const engineeringId = ref('')
const tableStore: any = new TableStore({
url: '/cs-device-boot/engineeringProjectRelation/list',
method: 'POST',
publicHeight: 60,
showPage: false,
column: [
{ field: 'engineeringName', title: '工程名称' },
{
field: 'engineeringAreaName',
title: '区域'
},
{
field: 'engineeringRemark',
title: '备注'
},
{
field: 'engineeringSort',
title: '排序',
width: '80px'
},
{
title: '操作',
fixed: 'right',
width: '150',
render: 'buttons',
buttons: [
{
name: 'edit',
title: '编辑',
type: 'primary',
icon: 'el-icon-Plus',
render: 'basicButton',
click: row => {
popupRef.value.open('编辑工程', row)
}
},
{
name: 'del',
text: '删除',
type: 'danger',
icon: 'el-icon-Delete',
render: 'confirmButton',
popconfirm: {
confirmButtonText: '确认',
cancelButtonText: '取消',
confirmButtonType: 'danger',
title: '确定删除?'
},
click: row => {
deleteEngineering({ id: row.engineeringId }).then(res => {
engineeringId.value = ''
ElMessage.success('删除成功')
tableStore.index()
})
}
}
]
}
],
loadCallback: () => {
if (engineeringId.value == '') {
engineeringId.value = tableStore.table.data[0].engineeringId
}
let list = tableStore.table.data.filter((item: any) => item.engineeringId == engineeringId.value)
tableRef.value.getRef().setCurrentRow(list[0])
itemList.value = list[0].projectInfoList
}
})
provide('tableStore', tableStore)
// 修改模版
const itemModification = (row: any) => {
itemAddRef.value.open('新增项目', tableStore.table.data, row, engineeringId.value)
}
// 删除模版
const itemeRemove = (row: any) => {
deleteProject({ id: row.projectId }).then(res => {
ElMessage.success('删除成功')
tableStore.index()
})
}
const addRole = () => {
// add()
popupRef.value.open('新增工程')
}
const add = () => {
itemAddRef.value.open('新增项目', tableStore.table.data)
}
// 查询绑定模版
const currentChange = (data: any) => {
engineeringId.value = data.row.engineeringId
itemList.value = data.row.projectInfoList
}
// 保存模版
const save = () => {
bandRelation({
modelIds: tableRef1.value.getCheckboxRecords().map(item => item.id),
id: menuListId.value
})
.then(() => {
ElMessage.success('操作成功!')
})
.catch(() => {})
}
const imgList = ref([])
// 获取拓扑图
const getUrl = async (row: any) => {
if (!row.topologyInfo || row.topologyInfo === '/') return false
try {
const res = await getFileUrl({ filePath: row.topologyInfo })
row.topologyImageUrl = res.data
return true
} catch (error) {
return false
}
}
onMounted(() => {
tableStore.index()
})
</script>
<style scoped>
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
.el-image {
height: 36px;
}
</style>

View File

@@ -6,7 +6,7 @@
maxlength="32" maxlength="32"
show-word-limit show-word-limit
v-model.trim="form.modelTypeName" v-model.trim="form.modelTypeName"
placeholder="请输入菜单名称" placeholder="请输入报表名称"
/> />
</el-form-item> </el-form-item>
<el-form-item label="报表类型" prop="modelType"> <el-form-item label="报表类型" prop="modelType">

View File

@@ -75,7 +75,7 @@ const tableStore = new TableStore({
{ field: 'freqDev', title: '频率(Hz)', width: 120 }, { field: 'freqDev', title: '频率(Hz)', width: 120 },
{ field: 'ubalance', title: '三相电压不平衡度(%)', width: 190 }, { field: 'ubalance', title: '三相电压不平衡度(%)', width: 190 },
{ field: 'ineg', title: '负序电流(A)', width: 120 }, { field: 'ineg', title: '负序电流(A)', width: 120 },
{ field: 'flicker', title: '长时闪变', width: 120 }, { field: 'flicker', title: '长时闪变', width: 120 },
{ field: 'uaberrance', title: '电压总谐波畸变率(%)', width: 190 }, { field: 'uaberrance', title: '电压总谐波畸变率(%)', width: 190 },
{ field: 'oddHarm', title: '奇数次谐波电压(%)', width: 180 }, { field: 'oddHarm', title: '奇数次谐波电压(%)', width: 180 },
{ field: 'evenHarm', title: '偶数次谐波电压(%)', width: 180 } { field: 'evenHarm', title: '偶数次谐波电压(%)', width: 180 }