mirror of
https://gitee.com/js-yhsec/energy_storage.git
synced 2026-05-28 03:09:24 +08:00
feat(web): 新增预测管理和策略表单功能
- 添加预测管理页面和相关组件 - 实现策略表单组件,支持创建和编辑策略 - 优化表格组件,增加分页和数据加载功能 - 调整视频监控组件布局 - 修复部分组件样式问题
This commit is contained in:
BIN
doc/.~充站控系统-HTTP管理接口.docx
Normal file
BIN
doc/.~充站控系统-HTTP管理接口.docx
Normal file
Binary file not shown.
@@ -26,5 +26,6 @@ const locale = ref(zhCN)
|
|||||||
right: 0;
|
right: 0;
|
||||||
min-width: 1440px;
|
min-width: 1440px;
|
||||||
min-height: 900px;
|
min-height: 900px;
|
||||||
|
color: #fff;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -39,13 +39,13 @@
|
|||||||
:data-source="record.currentLimitList"
|
:data-source="record.currentLimitList"
|
||||||
:pagination="false"
|
:pagination="false"
|
||||||
>
|
>
|
||||||
<template #bodyCell="{ column, record_ }">
|
<!-- <template #bodyCell="{ column, record_ }">
|
||||||
<template v-if="column.key === 'type'">
|
<template v-if="column.key === 'type'">
|
||||||
<span>
|
<span>
|
||||||
{{ getType(record_.type) }}
|
{{ getType(record_.type) }}
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
</template>
|
</template> -->
|
||||||
</a-table>
|
</a-table>
|
||||||
</template>
|
</template>
|
||||||
</a-table>
|
</a-table>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="search">
|
<div class="search">
|
||||||
|
|
||||||
<div class="top" v-if="searchOptions.length">
|
<div class="top" v-if="searchOptions.length">
|
||||||
<div class="top-left">
|
<div class="top-left">
|
||||||
<template v-for="item in searchOptions" :key="item.key">
|
<template v-for="item in searchOptions" :key="item.key">
|
||||||
@@ -9,9 +8,10 @@
|
|||||||
<span class="label"> {{ item.label }}</span>
|
<span class="label"> {{ item.label }}</span>
|
||||||
<div class="select" v-if="item.type == 'select'">
|
<div class="select" v-if="item.type == 'select'">
|
||||||
<a-select
|
<a-select
|
||||||
:dropdown-match-select-width="false" v-model:value="formData[item.key]"
|
:dropdown-match-select-width="false"
|
||||||
|
v-model:value="formData[item.key]"
|
||||||
allow-clear
|
allow-clear
|
||||||
:max-tag-count='2'
|
:max-tag-count="2"
|
||||||
:placeholder="item.label"
|
:placeholder="item.label"
|
||||||
:mode="item.mode ? item.mode : 'combobox'"
|
:mode="item.mode ? item.mode : 'combobox'"
|
||||||
>
|
>
|
||||||
@@ -75,7 +75,6 @@
|
|||||||
@click="handelClick(item.type)"
|
@click="handelClick(item.type)"
|
||||||
:disabled="item.disabled ? item.disabled : false"
|
:disabled="item.disabled ? item.disabled : false"
|
||||||
>
|
>
|
||||||
|
|
||||||
{{ item.label }}
|
{{ item.label }}
|
||||||
</a-button>
|
</a-button>
|
||||||
</div>
|
</div>
|
||||||
@@ -234,7 +233,7 @@ input:-internal-autofill-selected {
|
|||||||
|
|
||||||
.ant-picker {
|
.ant-picker {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: 1px solid #00B9D0;
|
border: 1px solid #00b9d0;
|
||||||
.ant-picker-input > input {
|
.ant-picker-input > input {
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
}
|
}
|
||||||
@@ -323,19 +322,13 @@ input:-internal-autofill-selected {
|
|||||||
}
|
}
|
||||||
.bottom {
|
.bottom {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-top: 15px;
|
margin-top: 20px;
|
||||||
margin-bottom: 15px;
|
margin-bottom: 20px;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
.button {
|
.button {
|
||||||
margin-left: 10px;
|
margin-left: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="device">
|
<div class="device">
|
||||||
<div class="device-item" v-for="item in 8" :key="item">
|
<div class="device-item" v-for="item in deviceList" :key="item">
|
||||||
<div class="item-header">
|
<div class="item-header">
|
||||||
<div style="display: flex;width: 50%;">
|
<div style="display: flex; width: 50%">
|
||||||
<div class="icon-bg"></div>
|
<div class="icon-bg"></div>
|
||||||
<div class="title">
|
<div class="title">
|
||||||
<span class="number">521245786665412</span>
|
<span class="number">521245786665412</span>
|
||||||
@@ -29,7 +29,13 @@
|
|||||||
<div class="item-content">
|
<div class="item-content">
|
||||||
<div v-for="info in chunengInfo" :key="info.key">
|
<div v-for="info in chunengInfo" :key="info.key">
|
||||||
<span class="text">{{ info.label }}:</span>
|
<span class="text">{{ info.label }}:</span>
|
||||||
<a-button v-if="info.key === 'realTimeData'" type="primary" size="small" @click="openModal">查看</a-button>
|
<a-button
|
||||||
|
v-if="info.key === 'realTimeData'"
|
||||||
|
type="primary"
|
||||||
|
size="small"
|
||||||
|
@click="openModal"
|
||||||
|
>查看</a-button
|
||||||
|
>
|
||||||
<span v-else class="value">{{ info.value }}</span>
|
<span v-else class="value">{{ info.value }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -43,13 +49,24 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
import { postReq, getReq } from '@/request/api'
|
||||||
export default {
|
export default {
|
||||||
name: '',
|
name: '',
|
||||||
components: {},
|
components: {},
|
||||||
props: {},
|
props: {
|
||||||
|
stationId: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
systemType: {
|
||||||
|
type: Number,
|
||||||
|
default: 1
|
||||||
|
}
|
||||||
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
modalOpen: false,
|
modalOpen: false,
|
||||||
|
deviceList: [],
|
||||||
chunengInfo: [
|
chunengInfo: [
|
||||||
{ label: '运行模式', key: 'operationMode', value: '并网运行' },
|
{ label: '运行模式', key: 'operationMode', value: '并网运行' },
|
||||||
{ label: '电池储能容量', key: 'batteryCapacity', value: '100kWh' },
|
{ label: '电池储能容量', key: 'batteryCapacity', value: '100kWh' },
|
||||||
@@ -62,26 +79,48 @@ export default {
|
|||||||
{ label: '实时数据', key: 'realTimeData', value: '0.01kWh' },
|
{ label: '实时数据', key: 'realTimeData', value: '0.01kWh' },
|
||||||
{ label: '额定功率', key: 'ratedPower', value: '0.01kW' },
|
{ label: '额定功率', key: 'ratedPower', value: '0.01kW' },
|
||||||
{ label: '冷却方式', key: 'coolingMethod', value: '风冷' }
|
{ label: '冷却方式', key: 'coolingMethod', value: '风冷' }
|
||||||
|
]
|
||||||
],
|
|
||||||
// guangfuInfo: [
|
|
||||||
// { label: '实时电压', key: 'voltage', value: '232.5V' },
|
|
||||||
// { label: '额定电压', key: 'ratedVoltage', value: '232.5V' },
|
|
||||||
// { label: '实时电流', key: 'current', value: '0.01A' },
|
|
||||||
// { label: '额定电流', key: 'ratedCurrent', value: '0.01A' },
|
|
||||||
// { label: '实时功率', key: 'power', value: '0.01kW' },
|
|
||||||
// { label: '额定功率', key: 'ratedPower', value: '0.01kW' },
|
|
||||||
// { label: '实时数据', key: 'realTimeData', value: '0.01kWh' }
|
|
||||||
// ]
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {},
|
watch: {
|
||||||
|
// 监听父组件数据变化
|
||||||
|
stationId(newVal) {
|
||||||
|
if (newVal) {
|
||||||
|
this.getDeviceList()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
systemType(newVal, oldVal) {
|
||||||
|
if (newVal !== oldVal) {
|
||||||
|
this.getDeviceList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getDeviceList()
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
async getDeviceList() {
|
||||||
|
const data = {
|
||||||
|
category: this.systemType,
|
||||||
|
'station_id': this.stationId,
|
||||||
|
page: 0,
|
||||||
|
'page_size': 1000
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const res = await getReq('/queryDeviceList', data)
|
||||||
|
|
||||||
|
console.log(res)
|
||||||
|
this.deviceList = res.data
|
||||||
|
// this.selectStation=this.stations[0]['station_id']
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error)
|
||||||
|
}
|
||||||
|
},
|
||||||
openModal() {
|
openModal() {
|
||||||
this.modalOpen=true;
|
this.modalOpen = true
|
||||||
},
|
},
|
||||||
handleOk() {
|
handleOk() {
|
||||||
this.modalOpen=false;
|
this.modalOpen = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,35 +21,26 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="environment">
|
<div class="environment">
|
||||||
<div class="item">
|
<div class="tab-header">
|
||||||
<div class="title">环境温湿度信息</div>
|
<div v-for="item in tabList" :key="item.key" class="tab">
|
||||||
<img src="@/assets/images/titleLine.png" alt="" width="100%" />
|
<span
|
||||||
<div class="content">
|
:class="[activeTab == item.key ? 'actived' : 'uactived']"
|
||||||
<div class="header">
|
@click="activeTab = item.key"
|
||||||
<div>点位</div>
|
>{{ item.name }}</span
|
||||||
<div>温度</div>
|
>
|
||||||
<div>湿度</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
|
||||||
<div>#1</div>
|
|
||||||
<div>20 ℃</div>
|
|
||||||
<div>20%</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="item" style="margin-top: 40px">
|
|
||||||
<div class="title">消防信息</div>
|
|
||||||
<img src="@/assets/images/titleLine.png" alt="" width="100%" />
|
|
||||||
<div class="content">
|
|
||||||
<div class="header">
|
|
||||||
<div>点位</div>
|
|
||||||
<div>烟感状态</div>
|
|
||||||
</div>
|
|
||||||
<div class="row" v-for="value in 6" :key="value">
|
|
||||||
<div>#{{ value }}</div>
|
|
||||||
<div>xxx</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="table-content">
|
||||||
|
<ComTable
|
||||||
|
:columns="columns"
|
||||||
|
:table-data="tableData"
|
||||||
|
@handlePagesizeChange="handlePagesizeChange"
|
||||||
|
ref="comTable"
|
||||||
|
:table-option="tableOption"
|
||||||
|
:page-option="pageOption"
|
||||||
|
:table-h="tableH"
|
||||||
|
>
|
||||||
|
</ComTable>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -60,7 +51,51 @@ export default {
|
|||||||
components: {},
|
components: {},
|
||||||
props: {},
|
props: {},
|
||||||
data() {
|
data() {
|
||||||
return {}
|
return {
|
||||||
|
activeTab: '0',
|
||||||
|
tabList: [
|
||||||
|
{
|
||||||
|
key: '0',
|
||||||
|
name: '环境温湿度信息'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '1',
|
||||||
|
name: '安防信息'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '2',
|
||||||
|
name: '空调信息'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: '3',
|
||||||
|
name: '冷机信息'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: '点位',
|
||||||
|
dataIndex: 'policyId',
|
||||||
|
key: 'policyId',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '温度',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '湿度',
|
||||||
|
dataIndex: 'type',
|
||||||
|
key: 'type',
|
||||||
|
ellipsis: true
|
||||||
|
}
|
||||||
|
],
|
||||||
|
tableOption: {
|
||||||
|
select: false,
|
||||||
|
page: false
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
mounted() {},
|
mounted() {},
|
||||||
methods: {}
|
methods: {}
|
||||||
@@ -69,11 +104,11 @@ export default {
|
|||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.videos {
|
.videos {
|
||||||
width: calc(100% - 240px);
|
width: 60%;
|
||||||
margin-left: 20px;
|
margin-left: 20px;
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-gap: 20px;
|
grid-gap: 20px;
|
||||||
grid-template-columns: 1fr 1fr 1fr;
|
grid-template-columns: 1fr 1fr;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
.video-item {
|
.video-item {
|
||||||
// width: 410px;
|
// width: 410px;
|
||||||
@@ -95,9 +130,10 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
.environment {
|
.environment {
|
||||||
width: 220px;
|
width: calc(40% - 20px);
|
||||||
margin-left: 10px;
|
margin-left: 20px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
@@ -125,5 +161,39 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.tab-header {
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.tab {
|
||||||
|
& > span {
|
||||||
|
font-size: 14px;
|
||||||
|
margin-right: 15px;
|
||||||
|
display: inline-block;
|
||||||
|
padding: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
border: 1px solid $tab-border;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.actived {
|
||||||
|
color: #ffffff;
|
||||||
|
|
||||||
|
background-color: $green;
|
||||||
|
}
|
||||||
|
.uactived {
|
||||||
|
color: #a6b8dd;
|
||||||
|
background-color: $bg2-color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.table-content {
|
||||||
|
margin-top: 20px;
|
||||||
|
:deep(.ant-table) {
|
||||||
|
border-radius: 10px 10px 0 0 !important;
|
||||||
|
overflow: hidden; /* 确保圆角生效 */
|
||||||
|
}
|
||||||
|
:deep(.ant-table-body) {
|
||||||
|
border-radius: 0px 0px 10px 10px !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
187
web/src/components/predict/predictEcharts.vue
Normal file
187
web/src/components/predict/predictEcharts.vue
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
<template>
|
||||||
|
<div class="echarts">
|
||||||
|
<div class="chart-container">
|
||||||
|
<div class="content-header">
|
||||||
|
<div class="verline"></div>
|
||||||
|
<span>{{ chartOptions.title }}</span>
|
||||||
|
</div>
|
||||||
|
<div ref="chartContainer" class="echarts-content"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import { postReq } from '@/request/api'
|
||||||
|
export default {
|
||||||
|
name: 'PredictEcharts',
|
||||||
|
props: {
|
||||||
|
chartOptions: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}, // 默认空对象
|
||||||
|
required: false // 非必须
|
||||||
|
},
|
||||||
|
chartData: {
|
||||||
|
type: Array,
|
||||||
|
default: () => ([]), // 默认空对象
|
||||||
|
required: false // 非必须
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
chartInstances: [] // 存储 ECharts 实例
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
|
||||||
|
|
||||||
|
this.$nextTick(() => {
|
||||||
|
// 确保 DOM 完全渲染
|
||||||
|
this.initCharts()
|
||||||
|
window.addEventListener('resize', this.handleResize)
|
||||||
|
})
|
||||||
|
},
|
||||||
|
beforeUnmount() {
|
||||||
|
window.removeEventListener('resize', this.handleResize)
|
||||||
|
this.chartInstances.forEach((chart) => chart && chart.dispose())
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
initCharts() {
|
||||||
|
// this.chartOptions.forEach((option, index) => {
|
||||||
|
const {title,infoKeys,dataKey,type,smooth}=this.chartOptions
|
||||||
|
|
||||||
|
const dom = this.$refs.chartContainer
|
||||||
|
if (!dom) return
|
||||||
|
|
||||||
|
const chart = this.$echarts.init(dom)
|
||||||
|
this.chartInstances.push(chart) // 存储实例
|
||||||
|
|
||||||
|
// 设置图表配置
|
||||||
|
chart.setOption({
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'shadow'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
top: 20,
|
||||||
|
textStyle: {
|
||||||
|
color: '#fff'
|
||||||
|
},
|
||||||
|
data: infoKeys.map((info) => info.label)
|
||||||
|
},
|
||||||
|
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '3%',
|
||||||
|
bottom: '1%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
xAxis: {
|
||||||
|
type: 'category',
|
||||||
|
data: this.chartData.map((item) => item.date),
|
||||||
|
axisLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#fff' // x轴线颜色
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
axisLabel: {
|
||||||
|
color: '#fff'
|
||||||
|
},
|
||||||
|
|
||||||
|
axisTick: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#fff' // x 轴刻度线颜色
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
},
|
||||||
|
yAxis: {
|
||||||
|
type: 'value',
|
||||||
|
axisLine: {
|
||||||
|
show: true,
|
||||||
|
lineStyle: {
|
||||||
|
color: '#fff' // y轴线颜色
|
||||||
|
}
|
||||||
|
},
|
||||||
|
axisLabel: {
|
||||||
|
color: '#fff'
|
||||||
|
},
|
||||||
|
|
||||||
|
splitLine: {
|
||||||
|
lineStyle: {
|
||||||
|
color: '#A6B8DD', // 网格线颜色,
|
||||||
|
type: 'dashed'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
series: infoKeys.map((info, i) => {
|
||||||
|
return {
|
||||||
|
name: info.label,
|
||||||
|
smooth: smooth || false,
|
||||||
|
type: type,
|
||||||
|
data: this.chartData.map((item) => item[info.key]),
|
||||||
|
...info.seriesOptions,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
// })
|
||||||
|
},
|
||||||
|
|
||||||
|
handleResize() {
|
||||||
|
this.chartInstances.forEach((chart) => chart && chart.resize())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.content {
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.echarts {
|
||||||
|
display: flex;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
color: #fff;
|
||||||
|
.chart-container {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
& > div {
|
||||||
|
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.content-header {
|
||||||
|
height: 20px;
|
||||||
|
font-size: 12px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-left: 3%;
|
||||||
|
.verline {
|
||||||
|
margin-right: 10px;
|
||||||
|
background: linear-gradient(
|
||||||
|
180deg,
|
||||||
|
rgba(0, 230, 172, 1) 0%,
|
||||||
|
rgba(0, 210, 255, 1) 98.78%,
|
||||||
|
rgba(0, 210, 255, 1) 100%
|
||||||
|
),
|
||||||
|
rgba(1, 223, 239, 1);
|
||||||
|
width: 4px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 6px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.echarts-content{
|
||||||
|
height: calc(100% - 20px);
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
156
web/src/components/system/policyForm copy.vue
Normal file
156
web/src/components/system/policyForm copy.vue
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
<template>
|
||||||
|
<div class="policyForm">
|
||||||
|
<div class="title">
|
||||||
|
<div>基础信息</div>
|
||||||
|
<img src="@/assets/images/titleLine.png" alt="" />
|
||||||
|
</div>
|
||||||
|
<a-form
|
||||||
|
:model="formState"
|
||||||
|
layout="inline"
|
||||||
|
label-align="right"
|
||||||
|
:label-col="{ style: { width: '100px' } }"
|
||||||
|
>
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="名称" :label-col="{ span: 3 }" :wrapper-col="{ span: 18}">
|
||||||
|
<a-input v-model:value="formState.name" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="类型" :label-col="{ span: 3 }" :wrapper-col="{ span: 18 }">
|
||||||
|
<a-select v-model:value="formState.region" placeholder="please select your zone">
|
||||||
|
<a-select-option value="shanghai">Zone one</a-select-option>
|
||||||
|
<a-select-option value="beijing">Zone two</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-form-item label="低谷电价" :label-col="{ span: 12 }" :wrapper-col="{ span: 12 }">
|
||||||
|
<a-input v-model:value="formState.name" suffix="元/kWh" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-form-item label="平段电价" :label-col="{ span: 12 }" :wrapper-col="{ span: 12 }">
|
||||||
|
<a-input v-model:value="formState.name" suffix="元/kWh" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-form-item label="高峰电价" :label-col="{ span: 12 }" :wrapper-col="{ span: 12 }">
|
||||||
|
<a-input v-model:value="formState.name" suffix="元/kWh" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="6">
|
||||||
|
<a-form-item label="尖峰电价" :label-col="{ span: 12 }" :wrapper-col="{ span: 12 }">
|
||||||
|
<a-input v-model:value="formState.name" suffix="元/kWh" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
|
||||||
|
<!-- <a-row :gutter="24">
|
||||||
|
<a-col :span="24">
|
||||||
|
<a-form-item label="时段表">
|
||||||
|
<a-radio-group v-model:value="formState.resource">
|
||||||
|
<a-radio value="1">Sponsor</a-radio>
|
||||||
|
<a-radio value="2">Venue</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="24">
|
||||||
|
<a-form-item label="充放策略">
|
||||||
|
<a-radio-group v-model:value="formState.resource">
|
||||||
|
<a-radio value="1">一充一放</a-radio>
|
||||||
|
<a-radio value="2">两充两放</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="24">
|
||||||
|
<a-form-item label="充放策略"> 休息休息休息休息、 </a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row>
|
||||||
|
<a-row :gutter="24">
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="策略描述">
|
||||||
|
<a-textarea v-model:value="formState.desc" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
<a-col :span="12">
|
||||||
|
<a-form-item label="是否启用">
|
||||||
|
<a-switch v-model:checked="formState.delivery" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-col>
|
||||||
|
</a-row> -->
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { styleProviderProps } from 'ant-design-vue/es/_util/cssinjs/StyleContext'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: '',
|
||||||
|
components: {},
|
||||||
|
props: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
formState: {
|
||||||
|
name: '',
|
||||||
|
delivery: false,
|
||||||
|
type: [],
|
||||||
|
resource: '',
|
||||||
|
desc: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {},
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.policyForm {
|
||||||
|
color: #fff;
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
font-weight: 700;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 232px;
|
||||||
|
height: 6px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-form {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ant-form-item {
|
||||||
|
margin-inline-end: 0 !important;
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
.ant-form {
|
||||||
|
.ant-form-item-label > label {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
:deep(.ant-row) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.ant-input,
|
||||||
|
.ant-select,
|
||||||
|
.ant-input-affix-wrapper {
|
||||||
|
// max-width: 240px;
|
||||||
|
// min-width: 120px;
|
||||||
|
}
|
||||||
|
textarea{
|
||||||
|
.ant-input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
227
web/src/components/system/policyForm.vue
Normal file
227
web/src/components/system/policyForm.vue
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
<template>
|
||||||
|
<div class="policyForm">
|
||||||
|
<div class="title">
|
||||||
|
<div>基础信息</div>
|
||||||
|
<img src="@/assets/images/titleLine.png" alt="" />
|
||||||
|
</div>
|
||||||
|
<a-form
|
||||||
|
:model="formState"
|
||||||
|
layout="inline"
|
||||||
|
label-align="left"
|
||||||
|
:label-col="{ style: { width: '85px' } }"
|
||||||
|
>
|
||||||
|
<a-form-item label="名称" class="col2">
|
||||||
|
<a-input v-model:value="formState.name" />
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="类型" class="col2">
|
||||||
|
<a-select v-model:value="formState.type" placeholder="">
|
||||||
|
<a-select-option v-for="item in policyTypes" :value="item.value">{{
|
||||||
|
item.label
|
||||||
|
}}</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="低谷电价" class="col4">
|
||||||
|
<a-input v-model:value="formState.name" suffix="元/kWh" />
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="平段电价" class="col4">
|
||||||
|
<a-input v-model:value="formState.name" suffix="元/kWh" />
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="高峰电价" class="col4">
|
||||||
|
<a-input v-model:value="formState.name" suffix="元/kWh" />
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="尖峰电价" class="col4">
|
||||||
|
<a-input v-model:value="formState.name" suffix="元/kWh" />
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="时段表" class="col1">
|
||||||
|
<a-table :columns="columns" :data-source="data" size="small">
|
||||||
|
<template #bodyCell="{ column, record }">
|
||||||
|
<template v-if="column.dataIndex === 'action'">
|
||||||
|
<span>
|
||||||
|
<a @click="edit(record.key)">操作</a>
|
||||||
|
</span>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</a-table>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="充放策略" class="col1">
|
||||||
|
<a-radio-group v-model:value="formState.resource">
|
||||||
|
<a-radio value="1">一充一放</a-radio>
|
||||||
|
<a-radio value="2">两充两放</a-radio>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="" class="col1">
|
||||||
|
<div class="charge">
|
||||||
|
<div class="box">
|
||||||
|
<span>第一次充放过程</span>
|
||||||
|
<a-form
|
||||||
|
:model="formState"
|
||||||
|
layout="inline"
|
||||||
|
label-align="left"
|
||||||
|
:label-col="{ style: { width: '85px' } }"
|
||||||
|
>
|
||||||
|
<a-form-item label="充电时间" class="col2">
|
||||||
|
<a-time-range-picker v-model:value="formState.name" format="HH:mm" />
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="放电时间" class="col2">
|
||||||
|
<a-select v-model:value="formState.type" placeholder="">
|
||||||
|
<a-select-option v-for="item in policyTypes" :value="item.value">{{
|
||||||
|
item.label
|
||||||
|
}}</a-select-option>
|
||||||
|
</a-select>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="充电功率" class="col2">
|
||||||
|
<a-radio-group v-model:value="formState.resource">
|
||||||
|
<a-radio value="1">自动</a-radio>
|
||||||
|
<a-radio value="2">自定义</a-radio>
|
||||||
|
<a-input style="width: 60px"></a-input>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
|
||||||
|
<a-form-item label="放电功率" class="col2">
|
||||||
|
<a-radio-group v-model:value="formState.resource">
|
||||||
|
<a-radio value="1">自动</a-radio>
|
||||||
|
<a-radio value="2">自定义</a-radio>
|
||||||
|
<a-input style="width: 60px"></a-input>
|
||||||
|
</a-radio-group>
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
<div class="box">222</div>
|
||||||
|
</div>
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="策略描述" class="col2">
|
||||||
|
<a-textarea v-model:value="formState.desc" />
|
||||||
|
</a-form-item>
|
||||||
|
<a-form-item label="是否启用" class="col2">
|
||||||
|
<a-switch v-model:checked="formState.delivery" />
|
||||||
|
</a-form-item>
|
||||||
|
</a-form>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { policyTypes } from '@/utils/config'
|
||||||
|
export default {
|
||||||
|
name: '',
|
||||||
|
components: {},
|
||||||
|
props: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
policyTypes,
|
||||||
|
formState: {
|
||||||
|
name: '',
|
||||||
|
delivery: false,
|
||||||
|
type: [],
|
||||||
|
resource: '',
|
||||||
|
desc: ''
|
||||||
|
},
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: '月份',
|
||||||
|
dataIndex: 'month',
|
||||||
|
key: 'month'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '开始时间',
|
||||||
|
dataIndex: 'startTime',
|
||||||
|
key: 'startTime'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '时段类型',
|
||||||
|
dataIndex: 'type',
|
||||||
|
key: 'type'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'action',
|
||||||
|
key: 'action'
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {},
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.policyForm {
|
||||||
|
color: #fff;
|
||||||
|
.title {
|
||||||
|
display: flex;
|
||||||
|
font-weight: 700;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
img {
|
||||||
|
width: 232px;
|
||||||
|
height: 6px;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-form {
|
||||||
|
.charge {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: 1fr 1fr;
|
||||||
|
gap: 10px;
|
||||||
|
.box {
|
||||||
|
border: 1px solid $table-border;
|
||||||
|
margin-left: 10px;
|
||||||
|
border-radius: 10px;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-form-item {
|
||||||
|
margin-inline-end: 0 !important;
|
||||||
|
margin-top: 15px;
|
||||||
|
:deep(.ant-form-item-label) {
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-form {
|
||||||
|
.ant-form-item-label {
|
||||||
|
> label {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.ant-row) {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
input,
|
||||||
|
.ant-picker,
|
||||||
|
.ant-select,
|
||||||
|
.ant-input-affix-wrapper {
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
textarea {
|
||||||
|
.ant-input {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.col2 {
|
||||||
|
width: 50%;
|
||||||
|
}
|
||||||
|
.col4 {
|
||||||
|
width: 25%;
|
||||||
|
}
|
||||||
|
.col1 {
|
||||||
|
width: 100%;
|
||||||
|
:deep(textarea.ant-input) {
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
:deep(.ant-form-item-row){
|
||||||
|
// border: 1px solid red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -9,8 +9,14 @@ import '@/style/index.scss'
|
|||||||
// import '@/assets/iconfont/iconfont.css'
|
// import '@/assets/iconfont/iconfont.css'
|
||||||
import * as echarts from 'echarts'
|
import * as echarts from 'echarts'
|
||||||
import VueTianditu from 'vue-tianditu'
|
import VueTianditu from 'vue-tianditu'
|
||||||
|
import SearchBox from '@/components/SearchBox.vue'
|
||||||
|
import ComTable from '@/components/ComTable.vue'
|
||||||
|
|
||||||
const app = createApp(App)
|
const app = createApp(App)
|
||||||
|
|
||||||
|
app.component('SearchBox', SearchBox)
|
||||||
|
app.component('ComTable', ComTable)
|
||||||
|
|
||||||
app.config.globalProperties.$echarts = echarts // 挂载到全局属性
|
app.config.globalProperties.$echarts = echarts // 挂载到全局属性
|
||||||
|
|
||||||
app.use(store).use(router).use(Antd).use(VueTianditu).mount('#app')
|
app.use(store).use(router).use(Antd).use(VueTianditu).mount('#app')
|
||||||
|
|||||||
@@ -1,16 +1,26 @@
|
|||||||
import request from "@/request/index.js";
|
import request from '@/request/index.js'
|
||||||
export function postReq(data, url) {
|
import qs from 'qs'
|
||||||
|
export function postReq(url, data) {
|
||||||
return request({
|
return request({
|
||||||
method: "post",
|
method: 'post',
|
||||||
url,
|
url,
|
||||||
data,
|
data: {
|
||||||
});
|
...data,
|
||||||
|
token: localStorage.getItem('token')
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getReq(data, url) {
|
export function getReq(url, data) {
|
||||||
// const query = qs.stringify(data, { indices: false })
|
const query = qs.stringify(
|
||||||
|
{
|
||||||
|
...data,
|
||||||
|
token: localStorage.getItem('token')
|
||||||
|
},
|
||||||
|
{ indices: false }
|
||||||
|
)
|
||||||
return request({
|
return request({
|
||||||
method: "get",
|
method: 'get',
|
||||||
url: url + "?" + data,
|
url: url + '?' + query
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,42 +1,42 @@
|
|||||||
import axios from "axios";
|
import axios from 'axios'
|
||||||
// import openNotification from "../utils/notification";
|
// import openNotification from "../utils/notification";
|
||||||
// let { config } = window;
|
// let { config } = window;
|
||||||
// let { baseUrl } = config;
|
// let { baseUrl } = config;
|
||||||
|
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
// baseURL: baseUrl,
|
// baseURL: baseUrl,
|
||||||
baseURL: "",
|
baseURL: '/api',
|
||||||
timeout: 120000,
|
timeout: 120000
|
||||||
});
|
})
|
||||||
|
|
||||||
service.interceptors.request.use((config) => {
|
service.interceptors.request.use((config) => {
|
||||||
const webConfig = config;
|
const webConfig = config
|
||||||
// if (!["/user/login", "/config/getConfig"].includes(config.url)) {
|
// if (!['/login'].includes(config.url)) {
|
||||||
// if (localStorage.getItem("token")) {
|
// if (localStorage.getItem('token')) {
|
||||||
// webConfig.headers = {
|
// webConfig.headers = {
|
||||||
// Authorization: localStorage.getItem("token"),
|
// token: localStorage.getItem('token')
|
||||||
// };
|
// }
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return webConfig;
|
return webConfig
|
||||||
});
|
})
|
||||||
service.interceptors.response.use(
|
service.interceptors.response.use(
|
||||||
(response) => {
|
(response) => {
|
||||||
// 排除以下接口的错误提示
|
// 排除以下接口的错误提示
|
||||||
const { url } = response.config;
|
const { url } = response.config
|
||||||
const urls = ["/light/", "/serve/delete", "/user/checkRandom"];
|
const urls = ['/light/', '/serve/delete', '/user/checkRandom']
|
||||||
const urlFlag = urls.map((item) => {
|
const urlFlag = urls.map((item) => {
|
||||||
return url.includes(item);
|
return url.includes(item)
|
||||||
});
|
})
|
||||||
|
|
||||||
const res = response.data;
|
const res = response.data
|
||||||
|
|
||||||
if (res.code !== 200) {
|
if (res.code !== 200) {
|
||||||
if (res.code == 401 || res.tip == "校验token过期") {
|
if (res.code == 401 || res.tip == '校验token过期') {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
window.$wujie?.props.jump({ path: "/login" });
|
window.$wujie?.props.jump({ path: '/login' })
|
||||||
}, 1000);
|
}, 1000)
|
||||||
} else if (urlFlag.every((item) => item === false)) {
|
} else if (urlFlag.every((item) => item === false)) {
|
||||||
// openNotification({
|
// openNotification({
|
||||||
// status: "error",
|
// status: "error",
|
||||||
@@ -44,18 +44,18 @@ service.interceptors.response.use(
|
|||||||
// });
|
// });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return res;
|
return res
|
||||||
},
|
},
|
||||||
(error) => {
|
(error) => {
|
||||||
// console.log(error, 'error 此处添加监控超时处理')
|
// console.log(error, 'error 此处添加监控超时处理')
|
||||||
if (
|
if (
|
||||||
error.name === "AxiosError" &&
|
error.name === 'AxiosError' &&
|
||||||
error.message === "timeout of 120000ms exceeded" &&
|
error.message === 'timeout of 120000ms exceeded' &&
|
||||||
error.code === "ECONNABORTED"
|
error.code === 'ECONNABORTED'
|
||||||
) {
|
) {
|
||||||
return error;
|
return error
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
);
|
)
|
||||||
|
|
||||||
export default service;
|
export default service
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
import { createRouter, createWebHistory } from 'vue-router'
|
import { createRouter, createWebHistory } from 'vue-router'
|
||||||
|
|
||||||
export const routes = [
|
export const routes = [
|
||||||
{
|
// {
|
||||||
path: '/',
|
// path: '/',
|
||||||
redirect: '/main/Home'
|
// redirect: '/main/Home'
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
path: '/login',
|
path: '/login',
|
||||||
name: 'login',
|
name: 'login',
|
||||||
component: () => import(/* webpackChunkName: "login" */ '@/views/LoginView.vue')
|
component: () => import(/* webpackChunkName: "login" */ '@/views/LoginView.vue')
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: '/main',
|
path: '/',
|
||||||
name: 'main',
|
name: '/',
|
||||||
redirect: '/main/Home',
|
redirect: '/Home',
|
||||||
component: () => import(/* webpackChunkName: "main" */ '@/views/MainView.vue'),
|
component: () => import(/* webpackChunkName: "main" */ '@/views/MainView.vue'),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
@@ -26,6 +26,12 @@ export const routes = [
|
|||||||
title: '运行监控',
|
title: '运行监控',
|
||||||
component: () => import(/* webpackChunkName: "monitor" */ '@/views/monitor.vue')
|
component: () => import(/* webpackChunkName: "monitor" */ '@/views/monitor.vue')
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: 'predict',
|
||||||
|
name: 'predict',
|
||||||
|
title: '预测管理',
|
||||||
|
component: () => import(/* webpackChunkName: "predict" */ '@/views/predict.vue')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: 'statisticalAnalysis',
|
path: 'statisticalAnalysis',
|
||||||
name: 'statisticalAnalysis',
|
name: 'statisticalAnalysis',
|
||||||
@@ -35,7 +41,7 @@ export const routes = [
|
|||||||
{
|
{
|
||||||
path: 'system',
|
path: 'system',
|
||||||
name: 'system',
|
name: 'system',
|
||||||
redirect: '/system/policy',
|
redirect: '/system/user',
|
||||||
component: () => import(/* webpackChunkName: "system" */ '@/views/system/index.vue'),
|
component: () => import(/* webpackChunkName: "system" */ '@/views/system/index.vue'),
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,26 @@
|
|||||||
$border-color: #12fbff;
|
$border-color: #12fbff;
|
||||||
$btn-confirm: #1C918A;
|
$btn-confirm: #1c918a;
|
||||||
$btn-del:#D43030;
|
$btn-del: #d43030;
|
||||||
//级联器样式
|
$btn-edit: #ff8d1a;
|
||||||
|
$bg1-color: #052f4d;
|
||||||
|
$bg2-color: #2169c31f;
|
||||||
|
$bg3-color: #00d2ff1f;
|
||||||
|
|
||||||
|
$text-color: #a6b8dd;
|
||||||
|
|
||||||
|
$green: #27a188;
|
||||||
|
$tab-border: #1489c0;
|
||||||
|
|
||||||
|
$table-border: #1c797a;
|
||||||
|
$table-bg: #072e4a;
|
||||||
|
$page-border: #cad2dd;
|
||||||
|
//级联器样式,下拉选择器样式输入框等。。。
|
||||||
|
.ant-select,
|
||||||
.ant-cascader {
|
.ant-cascader {
|
||||||
.ant-select-selector {
|
.ant-select-selector {
|
||||||
background: none !important;
|
background: none !important;
|
||||||
border: 1px solid $border-color !important;
|
border: 1px solid $border-color !important;
|
||||||
|
color: #fff;
|
||||||
}
|
}
|
||||||
.ant-select-arrow {
|
.ant-select-arrow {
|
||||||
color: $border-color;
|
color: $border-color;
|
||||||
@@ -14,6 +29,37 @@ $btn-del:#D43030;
|
|||||||
color: #ffffff3b;
|
color: #ffffff3b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.ant-input,
|
||||||
|
.ant-input-affix-wrapper,
|
||||||
|
.ant-picker
|
||||||
|
{
|
||||||
|
background: none !important;
|
||||||
|
border: 1px solid $border-color !important;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
:deep(.ant-picker){
|
||||||
|
.ant-picker-input >input,.ant-picker-separator{
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
.ant-picker-input::placeholder{
|
||||||
|
color: #ffffff3b !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-input-affix-wrapper {
|
||||||
|
.ant-input {
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.ant-radio-wrapper {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
//表单
|
||||||
|
.ant-form {
|
||||||
|
.ant-form-item-label > label {
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//按钮样式
|
//按钮样式
|
||||||
// .ant-btn{
|
// .ant-btn{
|
||||||
// padding: 4px 8px;
|
// padding: 4px 8px;
|
||||||
@@ -26,7 +72,6 @@ $btn-del:#D43030;
|
|||||||
}
|
}
|
||||||
&:active {
|
&:active {
|
||||||
background: #0f6f6a;
|
background: #0f6f6a;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.btn-del {
|
.btn-del {
|
||||||
@@ -37,7 +82,16 @@ $btn-del:#D43030;
|
|||||||
}
|
}
|
||||||
&:active {
|
&:active {
|
||||||
background: $btn-del;
|
background: $btn-del;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.btn-edit {
|
||||||
|
background: $btn-edit;
|
||||||
|
&:hover {
|
||||||
|
background: $btn-edit;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
&:active {
|
||||||
|
background: $btn-edit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//modal样式
|
//modal样式
|
||||||
@@ -47,3 +101,34 @@ $btn-del:#D43030;
|
|||||||
background-color: #ffffff00 !important;
|
background-color: #ffffff00 !important;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
}
|
}
|
||||||
|
.ant-modal .ant-modal-footer {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
//表单中的表格样式
|
||||||
|
.ant-form{
|
||||||
|
.ant-table-thead {
|
||||||
|
background: rgba(30, 85, 95, 1) !important;
|
||||||
|
}
|
||||||
|
:deep(.ant-table-thead > tr > th) {
|
||||||
|
border-inline: 1px solid transparent !important;
|
||||||
|
background: transparent;
|
||||||
|
color: #fff !important;
|
||||||
|
border-bottom: none !important; /* 可选:去除底部边框 */
|
||||||
|
}
|
||||||
|
:deep(.ant-table-tbody){
|
||||||
|
color: #fff;
|
||||||
|
background: $table-bg ;
|
||||||
|
border: 1px solid $table-border !important;
|
||||||
|
border-radius: 0px 0px 20px 20px;
|
||||||
|
|
||||||
|
}
|
||||||
|
:deep(.ant-table-wrapper .ant-table-tbody>tr.ant-table-placeholder:hover>td){
|
||||||
|
background: transparent !important;
|
||||||
|
}
|
||||||
|
:deep(.ant-empty-description){
|
||||||
|
color: #fff !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,39 +1,14 @@
|
|||||||
const copyRight =
|
export const policyTypes = [
|
||||||
'Copyright © 2016-2024 Jiangsu YuHong.All Rights Reserved.江苏禹弘科技有限公司 版权所有'
|
{
|
||||||
const companyName1 = '江苏禹弘科技有限公司'
|
value: 1,
|
||||||
const copyRight1 = 'Copyright © 2016 - 2024'
|
label: '削峰套利'
|
||||||
const themeColor = {
|
},
|
||||||
'--theme-bg-default': { light: '#fff', dark: '#111111' },
|
{
|
||||||
'--theme-bg': { light: '#eceff4', dark: '#2c2c2c' },
|
value: 2,
|
||||||
'--theme-bg1': { light: '#065758', dark: '#065758' },
|
label: '需求响应'
|
||||||
'--theme-bg2': { light: '#0657584d', dark: '#CDDDDE' },
|
},
|
||||||
'--theme-bg3': { light: '#00968826', dark: '#00968826' },
|
{
|
||||||
'--theme-bg4': { light: 'rgba(6, 87, 88, 0.75)', dark: 'rgba(6, 87, 88, 0.75)' },
|
value: 3,
|
||||||
|
label: '自发自用'
|
||||||
// 字体颜色
|
|
||||||
'--theme-text-default': { light: '#000000', dark: '#ffffff' },
|
|
||||||
'--theme-text': { light: '#065758', dark: '#065758' },
|
|
||||||
'--theme-text1': { light: 'rgba(0,0,0,0.5)', dark: '#040909FF' },
|
|
||||||
'--theme-text2': { light: '#ffffff', dark: '#ffffff' },
|
|
||||||
'--theme-text3': { light: 'rgba(0,0,0,0.5)', dark: 'rgba(255,255,255,0.5)' },
|
|
||||||
'--theme-text4': { light: 'rgba(0,0,0,0.75)', dark: 'rgba(255,255,255,0.75)' },
|
|
||||||
'--theme-text5': { light: 'rgba(0,0,0,0.65)', dark: 'rgba(255,255,255,0.65)' },
|
|
||||||
'--theme-text6': { light: 'rgba(0,0,0,0.3)', dark: 'rgba(255,255,255,0.3)' }, // placeholder颜色
|
|
||||||
|
|
||||||
// 按钮颜色
|
|
||||||
'--theme-btn1': { light: '#FF921B', dark: '#FF921B' },
|
|
||||||
'--theme-btn2': { light: '#ca4d2a', dark: '#ca4d2a' },
|
|
||||||
'--theme-btn3': { light: '#065758', dark: '#065758' },
|
|
||||||
|
|
||||||
// 阴影颜色
|
|
||||||
'--shadow-color1': { light: '#0657584d', dark: '#065758a6' },
|
|
||||||
'--shadow-color': { light: 'rgba(0, 0, 0, 0.25)', dark: 'rgba(255, 255, 255, 0.25)' },
|
|
||||||
|
|
||||||
// 表格颜色
|
|
||||||
'--table-header-bg': { light: '#5d9292', dark: '#065253' }, // 65%
|
|
||||||
'--table-tag': { light: '#D6DEEB', dark: '#D6DEEB' },
|
|
||||||
'--theme-opert-bg': { light: '#FFFFFF', dark: '#2c2c2c' },
|
|
||||||
'--table-select': { light: '#c4d4d9', dark: '#384846' }
|
|
||||||
}
|
}
|
||||||
|
]
|
||||||
export { copyRight, copyRight1, themeColor, companyName1 }
|
|
||||||
|
|||||||
@@ -11,8 +11,8 @@
|
|||||||
<div class="login-content">
|
<div class="login-content">
|
||||||
<div class="title" style="">账号登录</div>
|
<div class="title" style="">账号登录</div>
|
||||||
<a-form ref="ruleForm" :model="form" :rules="rules" >
|
<a-form ref="ruleForm" :model="form" :rules="rules" >
|
||||||
<a-form-item label="" name="user">
|
<a-form-item label="" name="account">
|
||||||
<a-input v-model:value="form.user" placeholder="请输入账号" autocomplete>
|
<a-input v-model:value="form.account" placeholder="请输入账号" autocomplete>
|
||||||
<template #prefix>
|
<template #prefix>
|
||||||
<user-outlined />
|
<user-outlined />
|
||||||
</template>
|
</template>
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
import { UserOutlined, LockOutlined } from '@ant-design/icons-vue'
|
import { UserOutlined, LockOutlined } from '@ant-design/icons-vue'
|
||||||
|
import { postReq,getReq } from '@/request/api.js'
|
||||||
export default {
|
export default {
|
||||||
name: 'LoginView',
|
name: 'LoginView',
|
||||||
components: {
|
components: {
|
||||||
@@ -49,11 +49,11 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
form: {
|
form: {
|
||||||
user: 'admin',
|
account: 'admin',
|
||||||
passwd: '123456'
|
passwd: '123456'
|
||||||
},
|
},
|
||||||
rules: {
|
rules: {
|
||||||
user: [
|
account: [
|
||||||
{
|
{
|
||||||
required: true,
|
required: true,
|
||||||
message: '请输入账号'
|
message: '请输入账号'
|
||||||
@@ -71,27 +71,30 @@ export default {
|
|||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async login() {
|
async login() {
|
||||||
this.$refs.ruleForm.validate(async (valid) => {
|
|
||||||
if (valid) {
|
|
||||||
this.loading = true
|
|
||||||
try {
|
try {
|
||||||
const res = await this.$http.post('/login', this.form)
|
const values = await this.$refs.ruleForm.validateFields()
|
||||||
|
const res = await getReq('/login',this.form )
|
||||||
this.loading = false
|
this.loading = false
|
||||||
if (res.code === 200) {
|
console.log(res);
|
||||||
|
|
||||||
|
// if (res.code === 200) {
|
||||||
this.$message.success('登录成功')
|
this.$message.success('登录成功')
|
||||||
localStorage.setItem('token', res.token)
|
localStorage.setItem('token', res.token)
|
||||||
this.$router.push('/main')
|
this.$router.push('/')
|
||||||
} else {
|
// } else {
|
||||||
this.$message.error(res.message || '登录失败')
|
// this.$message.error(res.message || '登录失败')
|
||||||
}
|
// }
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
this.loading = false
|
this.loading = false
|
||||||
this.$message.error('请求失败,请稍后重试')
|
this.$message.error('请求失败,请稍后重试')
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// console.log("表单验证失败");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -47,15 +47,20 @@ export default {
|
|||||||
menuList: [
|
menuList: [
|
||||||
{
|
{
|
||||||
name: '系统总览',
|
name: '系统总览',
|
||||||
icon: 'icon-xitongguanli'
|
path:'/home'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '运行监控',
|
name: '运行监控',
|
||||||
path: '/main/monitor'
|
path: '/monitor'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
name: '预测管理',
|
||||||
|
path: '/predict'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '统计分析',
|
name: '统计分析',
|
||||||
path: '/main/statisticalAnalysis'
|
path: '/statisticalAnalysis'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '系统管理',
|
name: '系统管理',
|
||||||
|
|||||||
@@ -4,36 +4,43 @@
|
|||||||
<div class="left">
|
<div class="left">
|
||||||
<div class="search-item">
|
<div class="search-item">
|
||||||
<span>场站切换</span>
|
<span>场站切换</span>
|
||||||
<a-cascader v-model:value="value" :options="options" placeholder="Please select" />
|
<a-select v-model:value="selectStation" style="width: 220px">
|
||||||
|
<a-select-option v-for="station in stations" :value="station['station_id']"
|
||||||
|
>{{ station.name }}
|
||||||
|
</a-select-option>
|
||||||
|
</a-select>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="right">
|
<div class="right">
|
||||||
<div class="search-item">
|
<div class="search-item">
|
||||||
<span>运行模式</span>
|
<span>运行模式</span>
|
||||||
<a-cascader v-model:value="value" :options="options" placeholder="Please select" />
|
<a-select v-model:value="value" style="width: 220px">
|
||||||
|
<a-select-option value="lucy">Lucy</a-select-option>
|
||||||
|
</a-select>
|
||||||
</div>
|
</div>
|
||||||
<div class="search-item">
|
<div class="search-item">
|
||||||
<span>策略名称</span>
|
<a-button type="primary">下发</a-button>
|
||||||
<a-cascader v-model:value="value" :options="options" placeholder="Please select" />
|
|
||||||
</div>
|
|
||||||
<div class="search-item">
|
|
||||||
<a-button type="primary">调控</a-button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="content">
|
<div class="content">
|
||||||
<div class="stations">
|
<div class="stations">
|
||||||
<div class="station-item" v-for="station in stations" :key="station.name" @click="()=>currentKey=station.name" :class="currentKey==station.name?'active':''">
|
<div
|
||||||
<span class="name">{{ station.name }}</span>
|
class="station-item"
|
||||||
<span class="des">总功率:{{ station.power }} W</span>
|
v-for="system in systems"
|
||||||
<span class="des">数量:{{ station.num }}</span>
|
:key="system.name"
|
||||||
|
@click="chooseStation(system)"
|
||||||
|
:class="systemType == system.systemType ? 'active' : ''"
|
||||||
|
>
|
||||||
|
<span class="name">{{ system.name }}</span>
|
||||||
|
<span class="des">边缘网关:{{ system.power }} W</span>
|
||||||
|
<span class="des">总有功功率(台区):{{ system.num }}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<device v-if="stationType" />
|
<videos v-if="systemType == 4" />
|
||||||
<videos v-else />
|
<device v-else :station-id="selectStation" :system-type="systemType"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -41,6 +48,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import device from '@/components/monitor/device.vue'
|
import device from '@/components/monitor/device.vue'
|
||||||
import videos from '@/components/monitor/videos.vue'
|
import videos from '@/components/monitor/videos.vue'
|
||||||
|
import { postReq, getReq } from '@/request/api'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'MonitorView',
|
name: 'MonitorView',
|
||||||
@@ -50,63 +58,64 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
currentKey:'储能系统1',
|
// currentKey: '储能系统',
|
||||||
stationType: 1,
|
systemType: 1,
|
||||||
value: [],
|
value: [],
|
||||||
options: [
|
stations: [],
|
||||||
|
selectStation:'',
|
||||||
|
systems: [
|
||||||
{
|
{
|
||||||
value: 'zhejiang',
|
name: '储能系统',
|
||||||
label: 'Zhejiang',
|
power: 60,
|
||||||
children: [
|
num: 62,
|
||||||
{
|
systemType: 1
|
||||||
value: 'hangzhou',
|
|
||||||
label: 'Hangzhou',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
value: 'xihu',
|
|
||||||
label: 'West Lake'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
value: 'jiangsu',
|
name: '充电系统',
|
||||||
label: 'Jiangsu',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
value: 'nanjing',
|
|
||||||
label: 'Nanjing',
|
|
||||||
children: [
|
|
||||||
{
|
|
||||||
value: 'zhonghuamen'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
stations: [
|
|
||||||
{
|
|
||||||
name: '储能系统1',
|
|
||||||
power: 60,
|
power: 60,
|
||||||
num: 62
|
num: 62,
|
||||||
|
systemType: 2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: '储能系统2',
|
name: '光伏系统',
|
||||||
power: 60,
|
power: 60,
|
||||||
num: 62
|
num: 62,
|
||||||
|
systemType: 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: '安防系统',
|
||||||
|
power: 60,
|
||||||
|
num: 62,
|
||||||
|
systemType: 4
|
||||||
}
|
}
|
||||||
// {
|
// {
|
||||||
// name: "储能系统3",
|
|
||||||
// power: 60,
|
|
||||||
// num: 62
|
|
||||||
// },
|
|
||||||
// {
|
|
||||||
// name: "储能系统4",
|
// name: "储能系统4",
|
||||||
// }
|
// }
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getStations()
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
//查询场站列表
|
||||||
|
async getStations() {
|
||||||
|
try {
|
||||||
|
const res = await getReq('/queryStationList', { page: 0, 'page_size': 10000 })
|
||||||
|
|
||||||
|
console.log(res)
|
||||||
|
this.stations = res.data
|
||||||
|
this.selectStation=this.stations[0]['station_id']
|
||||||
|
} catch (error) {
|
||||||
|
this.stations = []
|
||||||
|
this.selectStation=''
|
||||||
|
this.$message.error(error.message)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
chooseStation(system) {
|
||||||
|
this.systemType = system.systemType
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
293
web/src/views/predict.vue
Normal file
293
web/src/views/predict.vue
Normal file
@@ -0,0 +1,293 @@
|
|||||||
|
<template>
|
||||||
|
<div class="predict">
|
||||||
|
<div class="top">
|
||||||
|
<predictEcharts :chart-options="chartOptions[0]" :chart-data="chartData"/>
|
||||||
|
</div>
|
||||||
|
<div class="bottom">
|
||||||
|
<div class="item">
|
||||||
|
<predictEcharts :chart-options="chartOptions[1]" :chart-data="chartData"/>
|
||||||
|
</div>
|
||||||
|
<div class="item">
|
||||||
|
<predictEcharts :chart-options="chartOptions[2]" :chart-data="chartData"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import predictEcharts from '@/components/predict/predictEcharts.vue';
|
||||||
|
export default {
|
||||||
|
name: '',
|
||||||
|
components: {predictEcharts},
|
||||||
|
props: {},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
chartOptions:[ {
|
||||||
|
title: '储能充放电预测',
|
||||||
|
type: 'line',
|
||||||
|
smooth:false,
|
||||||
|
dataKey: 'chargeDischarge',
|
||||||
|
infoKeys: [
|
||||||
|
|
||||||
|
{
|
||||||
|
key: 'key1',
|
||||||
|
label: '电压',
|
||||||
|
seriesOptions:{
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 8,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#00FDF9' // 充电电量线条颜色
|
||||||
|
},
|
||||||
|
lineStyle: {
|
||||||
|
color: '#00FDF9' // 充电电量线条颜色
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'key2',
|
||||||
|
label: '电流',
|
||||||
|
|
||||||
|
seriesOptions:{
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 8,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#3E7EEF' // 充电电量线条颜色
|
||||||
|
},
|
||||||
|
lineStyle: {
|
||||||
|
color: '#3E7EEF' // 充电电量线条颜色
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
title: '充电负荷预测',
|
||||||
|
type: 'line',
|
||||||
|
smooth:false,
|
||||||
|
dataKey: 'chargeDischarge',
|
||||||
|
infoKeys: [
|
||||||
|
|
||||||
|
{
|
||||||
|
key: 'key1',
|
||||||
|
label: '电压',
|
||||||
|
seriesOptions:{
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 8,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#00FDF9' // 充电电量线条颜色
|
||||||
|
},
|
||||||
|
lineStyle: {
|
||||||
|
color: '#00FDF9' // 充电电量线条颜色
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'key2',
|
||||||
|
label: '电流',
|
||||||
|
|
||||||
|
seriesOptions:{
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 8,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#3E7EEF' // 充电电量线条颜色
|
||||||
|
},
|
||||||
|
lineStyle: {
|
||||||
|
color: '#3E7EEF' // 充电电量线条颜色
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
|
||||||
|
title: '光伏发电预测',
|
||||||
|
type: 'line',
|
||||||
|
smooth:false,
|
||||||
|
dataKey: 'chargeDischarge',
|
||||||
|
infoKeys: [
|
||||||
|
|
||||||
|
{
|
||||||
|
key: 'key1',
|
||||||
|
label: '电压',
|
||||||
|
seriesOptions:{
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 8,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#00FDF9' // 充电电量线条颜色
|
||||||
|
},
|
||||||
|
lineStyle: {
|
||||||
|
color: '#00FDF9' // 充电电量线条颜色
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: 'key2',
|
||||||
|
label: '电流',
|
||||||
|
|
||||||
|
seriesOptions:{
|
||||||
|
symbol: 'circle',
|
||||||
|
symbolSize: 8,
|
||||||
|
itemStyle: {
|
||||||
|
color: '#3E7EEF' // 充电电量线条颜色
|
||||||
|
},
|
||||||
|
lineStyle: {
|
||||||
|
color: '#3E7EEF' // 充电电量线条颜色
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
],
|
||||||
|
|
||||||
|
chartData: [
|
||||||
|
{
|
||||||
|
date: '2025-08-30',
|
||||||
|
key1: 10,
|
||||||
|
key2: 10,
|
||||||
|
key3: 15,
|
||||||
|
key4: 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2025-08-29',
|
||||||
|
key1: 8,
|
||||||
|
key2: 5,
|
||||||
|
key3: 5,
|
||||||
|
key4: 7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2025-08-28',
|
||||||
|
key1: 10,
|
||||||
|
key2: 10,
|
||||||
|
key3: 20,
|
||||||
|
key4: 4
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2025-08-27',
|
||||||
|
key1: 10,
|
||||||
|
key2: 10,
|
||||||
|
key3: 15,
|
||||||
|
key4: 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2025-08-26',
|
||||||
|
key1: 10,
|
||||||
|
key2: 5,
|
||||||
|
key3: 15,
|
||||||
|
key4: 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2025-08-25',
|
||||||
|
key1: 10,
|
||||||
|
key2: 5,
|
||||||
|
key3: 15,
|
||||||
|
key4: 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2025-08-24',
|
||||||
|
key1: 10,
|
||||||
|
key2: 6,
|
||||||
|
key3: 15,
|
||||||
|
key4: 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2025-08-23',
|
||||||
|
key1: 10,
|
||||||
|
key2: 7,
|
||||||
|
key3: 15,
|
||||||
|
key4: 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2025-08-22',
|
||||||
|
key1: 10,
|
||||||
|
key2: 0,
|
||||||
|
key3: 15,
|
||||||
|
key4: 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2025-08-21',
|
||||||
|
key1: 10,
|
||||||
|
key2: 0,
|
||||||
|
key3: 15,
|
||||||
|
key4: 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2025-08-20',
|
||||||
|
key1: 10,
|
||||||
|
key2: 0,
|
||||||
|
key3: 15,
|
||||||
|
key4: 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2025-08-19',
|
||||||
|
key1: 10,
|
||||||
|
key2: 0,
|
||||||
|
key3: 15,
|
||||||
|
key4: 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2025-08-18',
|
||||||
|
key1: 10,
|
||||||
|
key2: 0,
|
||||||
|
key3: 15,
|
||||||
|
key4: 5
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2025-08-17',
|
||||||
|
key1: 10,
|
||||||
|
key2: 0,
|
||||||
|
key3: 15,
|
||||||
|
key4: 5
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {},
|
||||||
|
methods: {}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.predict {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background: $bg1-color;
|
||||||
|
border-radius: 15px;
|
||||||
|
padding: 20px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 20px;
|
||||||
|
|
||||||
|
.top,
|
||||||
|
.bottom {
|
||||||
|
flex: 1;
|
||||||
|
width: 100%;
|
||||||
|
height: calc(50% - 10px);
|
||||||
|
|
||||||
|
}
|
||||||
|
.bottom {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
.top{
|
||||||
|
background-color: rgba(33, 105, 195, 0.12);
|
||||||
|
padding: 20px 5px;
|
||||||
|
border-radius: 15px;
|
||||||
|
}
|
||||||
|
.item{
|
||||||
|
background-color: rgba(33, 105, 195, 0.12);
|
||||||
|
padding: 20px 5px;
|
||||||
|
flex: 1;
|
||||||
|
border-radius: 15px;
|
||||||
|
|
||||||
|
&:nth-child(2){
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,38 +1,197 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="policy">
|
<div class="policy">
|
||||||
<searchBox :btn-option-list="btnOptionList" @onSearch="onSearch" @operateForm="operateForm" />
|
<searchBox :btn-option-list="btnOptionList" @onSearch="onSearch" @operateForm="operateForm" />
|
||||||
|
<div class="content-table">
|
||||||
|
|
||||||
|
<ComTable
|
||||||
|
:columns="columns"
|
||||||
|
:table-data="tableData"
|
||||||
|
@handlePagesizeChange="handlePagesizeChange"
|
||||||
|
ref="comTable"
|
||||||
|
:table-option="tableOption"
|
||||||
|
:page-option="pageOption"
|
||||||
|
:table-h="tableH"
|
||||||
|
>
|
||||||
|
<template #type="record">
|
||||||
|
<div>{{record.type}}</div>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
<template #action >
|
||||||
|
<a-button type="primary" size="small" @click="operateForm('edit')" style="margin-left: 10px">查看</a-button>
|
||||||
|
<a-button type="primary" size="small" @click="operateForm('edit')" class="btn-edit" style="margin-left: 10px">修改</a-button>
|
||||||
|
<a-button type="primary" size="small" @click="operateForm('edit')" class="btn-del" style="margin-left: 10px">删除</a-button>
|
||||||
|
|
||||||
|
|
||||||
|
</template>
|
||||||
|
</ComTable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<a-modal v-model:open="formModal" @ok="handleOk" width="70%">
|
||||||
|
<policyForm/>
|
||||||
|
</a-modal>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import searchBox from '@/components/SearchBox.vue'
|
import policyForm from '@/components/system/policyForm.vue'
|
||||||
|
import {getReq} from '@/request/api'
|
||||||
export default {
|
export default {
|
||||||
name: '',
|
name: '',
|
||||||
components:{searchBox
|
components: { policyForm },
|
||||||
},
|
props: {},
|
||||||
props: {
|
|
||||||
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
|
formModal:true,
|
||||||
btnOptionList: [
|
btnOptionList: [
|
||||||
{ label: '新增', icon: 'icon-tianjia', type: 'add' },
|
{ label: '新增', icon: 'icon-tianjia', type: 'add' },
|
||||||
{ label: '删除', icon: 'icon-tianjia', type: 'del' }
|
{ label: '删除', icon: 'icon-tianjia', type: 'del' }
|
||||||
|
],
|
||||||
|
columns: [
|
||||||
|
{
|
||||||
|
title: '策略ID',
|
||||||
|
dataIndex: 'policyId',
|
||||||
|
key: 'policyId',
|
||||||
|
width: 120,
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '策略名称',
|
||||||
|
dataIndex: 'name',
|
||||||
|
key: 'name',
|
||||||
|
width: 120,
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '策略类型',
|
||||||
|
dataIndex: 'type',//策略类型:1:削峰套利;2:需求响应;3:自发自用
|
||||||
|
key: 'type',
|
||||||
|
width: 120,
|
||||||
|
ellipsis: true,
|
||||||
|
scopedSlots: { customRender: 'type' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '策略描述',
|
||||||
|
dataIndex: 'describe',
|
||||||
|
key: 'describe',
|
||||||
|
width: 120,
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '策略参数',
|
||||||
|
dataIndex: 'value',
|
||||||
|
key: 'value',
|
||||||
|
width: 120,
|
||||||
|
ellipsis: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: '是否启用',
|
||||||
|
dataIndex: 'isOpen',
|
||||||
|
key: 'isOpen',
|
||||||
|
width: 120,
|
||||||
|
ellipsis: true,
|
||||||
|
scopedSlots: { customRender: 'isOpen' }
|
||||||
|
},
|
||||||
|
|
||||||
]
|
{
|
||||||
|
title: '操作',
|
||||||
|
dataIndex: 'action',
|
||||||
|
key: 'action',
|
||||||
|
width: 150,
|
||||||
|
ellipsis: true,
|
||||||
|
scopedSlots: { customRender: 'action' }
|
||||||
|
}
|
||||||
|
],
|
||||||
|
tableData:[{
|
||||||
|
policyId: 'P001',
|
||||||
|
name: '峰谷套利策略',
|
||||||
|
type: 1, // 削峰套利
|
||||||
|
describe: '利用峰谷电价差进行储能充放电优化',
|
||||||
|
value: '峰时段: 08:00-22:00, 谷时段: 22:00-08:00',
|
||||||
|
isOpen: true,
|
||||||
|
action: 'edit|delete'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
policyId: 'P002',
|
||||||
|
name: '需求响应策略',
|
||||||
|
type: 2, // 需求响应
|
||||||
|
describe: '参与电网调峰的需求侧响应方案',
|
||||||
|
value: '响应阈值: 80%, 持续时间: 2小时',
|
||||||
|
isOpen: false,
|
||||||
|
action: 'edit|delete'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
policyId: 'P003',
|
||||||
|
name: '光伏自发自用',
|
||||||
|
type: 3, // 自发自用
|
||||||
|
describe: '优先使用光伏发电,余电上网',
|
||||||
|
value: '自用比例: 90%, 上网比例: 10%',
|
||||||
|
isOpen: true,
|
||||||
|
action: 'edit|delete'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
policyId: 'P004',
|
||||||
|
name: '工业削峰策略',
|
||||||
|
type: 1, // 削峰套利
|
||||||
|
describe: '通过储能系统平抑工业用电高峰',
|
||||||
|
value: '削峰容量: 500kWh, 持续时间: 4小时',
|
||||||
|
isOpen: true,
|
||||||
|
action: 'edit|delete'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
policyId: 'P005',
|
||||||
|
name: '商业综合体响应',
|
||||||
|
type: 2, // 需求响应
|
||||||
|
describe: '商业建筑参与电网需求响应',
|
||||||
|
value: '可中断负荷: 200kW, 响应次数: 3次/月',
|
||||||
|
isOpen: false,
|
||||||
|
action: 'edit|delete'
|
||||||
|
}],
|
||||||
|
tableOption:{},
|
||||||
|
pageOption:{
|
||||||
|
page:1,
|
||||||
|
pageSize:10,
|
||||||
|
},
|
||||||
|
tableH:''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
|
this.getTableList()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
|
async getTableList(){
|
||||||
|
try {
|
||||||
|
const res = await getReq('/queryPolicyList', {
|
||||||
|
page: this.pageOption.page,
|
||||||
|
'page_size': this.pageOption.pageSize
|
||||||
|
})
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
handleOk(){
|
||||||
|
this.formModal=false
|
||||||
|
},
|
||||||
onSearch(data) {
|
onSearch(data) {
|
||||||
console.log(data)
|
console.log(data)
|
||||||
},
|
},
|
||||||
operateForm(type) {
|
operateForm(type) {
|
||||||
console.log(type)
|
console.log(type)
|
||||||
|
switch (type){
|
||||||
|
case 'add':
|
||||||
|
this.formModal= true
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
},
|
},
|
||||||
|
handlePagesizeChange(data) {
|
||||||
|
console.log(data)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -42,5 +201,9 @@ export default {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 0 15px;
|
padding: 0 15px;
|
||||||
|
.content-table {
|
||||||
|
width: 100%;
|
||||||
|
height: calc(100% - 92px );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -32,6 +32,15 @@ module.exports = defineConfig({
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
proxy: {
|
||||||
|
'/api': {
|
||||||
|
target: 'http://192.168.0.187:19801', // 目标服务器地址
|
||||||
|
changeOrigin: true, // 修改请求头中的host
|
||||||
|
pathRewrite: {
|
||||||
|
'^/api': '' // 重写路径,去掉/api前缀
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
css: {
|
css: {
|
||||||
@@ -44,8 +53,7 @@ module.exports = defineConfig({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
extract: {
|
extract: {
|
||||||
filename: `css/.[contenthash:8].css`,
|
ignoreOrder: true // 忽略 CSS 顺序警告
|
||||||
chunkFilename: `css/.[contenthash:8].chunk.css`
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// webpack相关配置
|
// webpack相关配置
|
||||||
|
|||||||
Reference in New Issue
Block a user