|
@@ -1,3 +1,698 @@
|
|
|
+<script setup lang="ts">
|
|
|
+import { onMounted, ref, useTemplateRef } from 'vue';
|
|
|
+import dayjs, { Dayjs } from 'dayjs';
|
|
|
+
|
|
|
+import DeviceGroupSelect from '@/components/DeviceGroupSelect.vue';
|
|
|
+import SvgIcon from '@/components/SvgIcon.vue';
|
|
|
+import { useDictData } from '@/hooks/dict-data';
|
|
|
+import { useRequest } from '@/hooks/request';
|
|
|
+import { t } from '@/i18n';
|
|
|
+import { addAlgorithmConfigUpdate, getAlgorithmConfigInfo } from '@/api';
|
|
|
+import { DictCode } from '@/constants';
|
|
|
+
|
|
|
+import EquipmentControl from './EquipmentControl.vue';
|
|
|
+import MonthSetting from './MonthSetting.vue';
|
|
|
+import SetInterval from './SetInterval.vue';
|
|
|
+
|
|
|
+import type { FormInstance, Rule } from 'ant-design-vue/es/form';
|
|
|
+import type { AlgorithmForm, ChillersItem, TemperatureRange, TemperatureRangeItem } from '@/types';
|
|
|
+
|
|
|
+const { dictData: algTempCtrlMinStep, getDictData: getAlgTempCtrlMinStep } = useDictData(DictCode.AlgTempCtrlMinStep);
|
|
|
+const { dictData: algTempHumCollectPeriod, getDictData: getAlgTempHumCollectPeriod } = useDictData(
|
|
|
+ DictCode.AlgTempHumCollectPeriod,
|
|
|
+);
|
|
|
+const { dictData: algWtTempCtrlMode, getDictData: getAlgWtTempCtrlMode } = useDictData(DictCode.AlgWtTempCtrlMode);
|
|
|
+const { dictData: algAlways, getDictData: getAlgAlways } = useDictData(DictCode.AlgAlways);
|
|
|
+const { dictData: algWtTempSetStep, getDictData: getAlgWtTempSetStep } = useDictData(DictCode.AlgWtTempSetStep);
|
|
|
+
|
|
|
+const formRef = ref<FormInstance>();
|
|
|
+const monthSettingRefs = useTemplateRef('monthSetting');
|
|
|
+const setIntervalRefs = ref<InstanceType<typeof SetInterval>[]>([]);
|
|
|
+const equipmentControlRefs = ref<InstanceType<typeof EquipmentControl>[]>([]);
|
|
|
+
|
|
|
+const { handleRequest } = useRequest();
|
|
|
+const activeKey = ref<string[]>(['1', '2', '3']);
|
|
|
+const customStyle = 'border-radius: 4px;;border: 0;background: #F5F6F7;';
|
|
|
+const analysisOpen = ref<boolean>(false);
|
|
|
+const setOpen = ref<boolean>(false);
|
|
|
+const temperatureSettingValue = ref<string>('');
|
|
|
+const analysisTypeDisplay = ref<number>(0);
|
|
|
+const coolingPipeDynamicOffsetDisplay = ref<number>(0);
|
|
|
+const coolingPipeDynamicSetDisplay = ref<number>(0);
|
|
|
+const coolingPipeDynamicDeadZoneDisplay = ref<number>(0);
|
|
|
+const coolingPipeDynamicLowerDisplay = ref<number>(0);
|
|
|
+const coolingPipeDynamicUpperDisplay = ref<number>(0);
|
|
|
+const temperatureRangeList = ref<TemperatureRange[]>([]);
|
|
|
+const chillersList = ref<ChillersItem[]>([]);
|
|
|
+const algorithmId = ref<number>();
|
|
|
+const algorithmForm = ref<AlgorithmForm>({
|
|
|
+ enabled: false,
|
|
|
+ sendCtrlCmd: true,
|
|
|
+ msgBox: true,
|
|
|
+ tempRiseCtrlPeriod: 10,
|
|
|
+ tempReductionCtrlPeriod: 3,
|
|
|
+ minCtrlStep: '',
|
|
|
+ intelligentMode: 0,
|
|
|
+ controlBasis: 0,
|
|
|
+ period: 0,
|
|
|
+ tempSafetyMargin: 0,
|
|
|
+ humiditySafetyMargin: 0,
|
|
|
+ tempHumidityCollectPeriod: '',
|
|
|
+ waterSupplyTempSource: 0,
|
|
|
+ analysis: true,
|
|
|
+ analysisType: 0,
|
|
|
+ enableRefrigerationPipeDynamicSet: true,
|
|
|
+ enableCoolingPipeDynamicSet: false,
|
|
|
+ coolingPipeDynamicOffset: 0,
|
|
|
+ coolingPipeDynamicSet: 0,
|
|
|
+ coolingPipeDynamicDeadZone: 0,
|
|
|
+ coolingPipeDynamicLower: 0,
|
|
|
+ coolingPipeDynamicUpper: 0,
|
|
|
+});
|
|
|
+const addClick = () => {
|
|
|
+ temperatureRangeList.value.push({
|
|
|
+ time: undefined,
|
|
|
+ lower: 0,
|
|
|
+ upper: 0,
|
|
|
+ });
|
|
|
+};
|
|
|
+const deleteClick = (index: number) => {
|
|
|
+ temperatureRangeList.value.splice(index, 1);
|
|
|
+};
|
|
|
+const rules: Record<string, Rule[]> = {
|
|
|
+ sendCtrlCmd: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
|
|
|
+ msgBox: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
|
|
|
+ tempRiseCtrlPeriod: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
|
|
|
+ tempReductionCtrlPeriod: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
|
|
|
+ minCtrlStep: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
|
|
|
+ intelligentMode: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
|
|
|
+ controlBasis: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
|
|
|
+ period: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
|
|
|
+ tempSafetyMargin: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
|
|
|
+ humiditySafetyMargin: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
|
|
|
+ tempHumidityCollectPeriod: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
|
|
|
+ waterSupplyTempSource: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
|
|
|
+};
|
|
|
+const handleDevGroupChange = (groupingId: number) => {
|
|
|
+ temperatureRangeList.value = [];
|
|
|
+ chillersList.value = [];
|
|
|
+ handleRequest(async () => {
|
|
|
+ const {
|
|
|
+ id: algId,
|
|
|
+ enabled,
|
|
|
+ sendCtrlCmd,
|
|
|
+ msgBox,
|
|
|
+ tempRiseCtrlPeriod,
|
|
|
+ minCtrlStep,
|
|
|
+ intelligentMode,
|
|
|
+ controlBasis,
|
|
|
+ period,
|
|
|
+ tempSafetyMargin,
|
|
|
+ humiditySafetyMargin,
|
|
|
+ tempHumidityCollectPeriod,
|
|
|
+ waterSupplyTempSource,
|
|
|
+ tempReductionCtrlPeriod,
|
|
|
+ analysis,
|
|
|
+ analysisType,
|
|
|
+ enableRefrigerationPipeDynamicSet,
|
|
|
+ enableCoolingPipeDynamicSet,
|
|
|
+ coolingPipeDynamicOffset,
|
|
|
+ coolingPipeDynamicSet,
|
|
|
+ coolingPipeDynamicDeadZone,
|
|
|
+ coolingPipeDynamicLower,
|
|
|
+ coolingPipeDynamicUpper,
|
|
|
+ chillers,
|
|
|
+ chilledWaterOutletTempRangeList,
|
|
|
+ chilledWaterOutletTempSet,
|
|
|
+ } = await getAlgorithmConfigInfo(groupingId);
|
|
|
+ algorithmId.value = algId;
|
|
|
+ Object.assign(algorithmForm.value, {
|
|
|
+ enabled,
|
|
|
+ sendCtrlCmd,
|
|
|
+ msgBox,
|
|
|
+ tempRiseCtrlPeriod,
|
|
|
+ tempReductionCtrlPeriod,
|
|
|
+ minCtrlStep: String(minCtrlStep),
|
|
|
+ intelligentMode,
|
|
|
+ controlBasis,
|
|
|
+ period,
|
|
|
+ tempSafetyMargin,
|
|
|
+ humiditySafetyMargin,
|
|
|
+ tempHumidityCollectPeriod: String(tempHumidityCollectPeriod),
|
|
|
+ waterSupplyTempSource,
|
|
|
+ analysis,
|
|
|
+ analysisType,
|
|
|
+ enableRefrigerationPipeDynamicSet,
|
|
|
+ enableCoolingPipeDynamicSet,
|
|
|
+ coolingPipeDynamicOffset,
|
|
|
+ coolingPipeDynamicSet,
|
|
|
+ coolingPipeDynamicDeadZone,
|
|
|
+ coolingPipeDynamicLower,
|
|
|
+ coolingPipeDynamicUpper,
|
|
|
+ });
|
|
|
+
|
|
|
+ analysisTypeDisplay.value = analysisType;
|
|
|
+ coolingPipeDynamicOffsetDisplay.value = coolingPipeDynamicOffset;
|
|
|
+ coolingPipeDynamicSetDisplay.value = coolingPipeDynamicSet;
|
|
|
+ coolingPipeDynamicDeadZoneDisplay.value = coolingPipeDynamicDeadZone;
|
|
|
+ coolingPipeDynamicLowerDisplay.value = coolingPipeDynamicLower;
|
|
|
+ coolingPipeDynamicUpperDisplay.value = coolingPipeDynamicUpper;
|
|
|
+ temperatureSettingValue.value = chilledWaterOutletTempSet;
|
|
|
+ chilledWaterOutletTempRangeList.forEach((item) => {
|
|
|
+ const { startTime, endTime, lower, upper } = item;
|
|
|
+ temperatureRangeList.value.push({
|
|
|
+ time: [dayjs(startTime, 'HH:mm'), dayjs(endTime, 'HH:mm')],
|
|
|
+ lower,
|
|
|
+ upper,
|
|
|
+ });
|
|
|
+ });
|
|
|
+ chillers.forEach((item) => {
|
|
|
+ const {
|
|
|
+ id,
|
|
|
+ devId,
|
|
|
+ waterTempControlMode,
|
|
|
+ continuous,
|
|
|
+ stopCompensate,
|
|
|
+ restartCompensate,
|
|
|
+ safeDiffPressureLower,
|
|
|
+ safeLoadLower,
|
|
|
+ waterTempStep,
|
|
|
+ deviceName,
|
|
|
+ } = item;
|
|
|
+ chillersList.value.push({
|
|
|
+ id,
|
|
|
+ algId,
|
|
|
+ devId,
|
|
|
+ waterTempControlMode: String(waterTempControlMode),
|
|
|
+ continuous: String(continuous),
|
|
|
+ stopCompensate,
|
|
|
+ restartCompensate,
|
|
|
+ safeDiffPressureLower,
|
|
|
+ safeLoadLower,
|
|
|
+ waterTempStep: String(waterTempStep),
|
|
|
+ deviceName,
|
|
|
+ });
|
|
|
+ });
|
|
|
+ });
|
|
|
+};
|
|
|
+const analysisEditor = () => {
|
|
|
+ analysisTypeDisplay.value = algorithmForm.value.analysisType;
|
|
|
+ analysisOpen.value = true;
|
|
|
+};
|
|
|
+const setEditor = () => {
|
|
|
+ const {
|
|
|
+ coolingPipeDynamicOffset,
|
|
|
+ coolingPipeDynamicSet,
|
|
|
+ coolingPipeDynamicDeadZone,
|
|
|
+ coolingPipeDynamicLower,
|
|
|
+ coolingPipeDynamicUpper,
|
|
|
+ } = algorithmForm.value;
|
|
|
+ coolingPipeDynamicOffsetDisplay.value = coolingPipeDynamicOffset;
|
|
|
+ coolingPipeDynamicSetDisplay.value = coolingPipeDynamicSet;
|
|
|
+ coolingPipeDynamicDeadZoneDisplay.value = coolingPipeDynamicDeadZone;
|
|
|
+ coolingPipeDynamicLowerDisplay.value = coolingPipeDynamicLower;
|
|
|
+ coolingPipeDynamicUpperDisplay.value = coolingPipeDynamicUpper;
|
|
|
+ setOpen.value = true;
|
|
|
+};
|
|
|
+const okConfirm = () => {
|
|
|
+ algorithmForm.value.analysisType = analysisTypeDisplay.value;
|
|
|
+ analysisOpen.value = false;
|
|
|
+};
|
|
|
+const okSetConfirm = () => {
|
|
|
+ algorithmForm.value.coolingPipeDynamicOffset = coolingPipeDynamicOffsetDisplay.value;
|
|
|
+ algorithmForm.value.coolingPipeDynamicSet = coolingPipeDynamicSetDisplay.value;
|
|
|
+ algorithmForm.value.coolingPipeDynamicDeadZone = coolingPipeDynamicDeadZoneDisplay.value;
|
|
|
+ algorithmForm.value.coolingPipeDynamicLower = coolingPipeDynamicLowerDisplay.value;
|
|
|
+ algorithmForm.value.coolingPipeDynamicUpper = coolingPipeDynamicUpperDisplay.value;
|
|
|
+ setOpen.value = false;
|
|
|
+};
|
|
|
+
|
|
|
+// 添加格式转换
|
|
|
+const formatDate = (date: Dayjs) => date.format('HH:mm');
|
|
|
+
|
|
|
+const addAlgorithm = async () => {
|
|
|
+ try {
|
|
|
+ // 创建校验任务队列(包含所有子组件+父组件自身)
|
|
|
+ const allTasks = [
|
|
|
+ ...setIntervalRefs.value.map((c) => c.formRefSubmit()),
|
|
|
+ ...equipmentControlRefs.value.map((c) => c.formRefSubmit()),
|
|
|
+ formRef.value?.validate() || Promise.resolve(),
|
|
|
+ monthSettingRefs.value?.formRefSubmit(),
|
|
|
+ ];
|
|
|
+ // 并行执行所有校验(父+子)
|
|
|
+ await Promise.all(allTasks);
|
|
|
+ handleRequest(async () => {
|
|
|
+ const timeList: TemperatureRangeItem[] = [];
|
|
|
+ temperatureRangeList.value.forEach((item) => {
|
|
|
+ const { time, lower, upper } = item;
|
|
|
+
|
|
|
+ const data = time?.map(formatDate) || [];
|
|
|
+
|
|
|
+ timeList.push({
|
|
|
+ startTime: data[0],
|
|
|
+ endTime: data[1],
|
|
|
+ lower,
|
|
|
+ upper,
|
|
|
+ });
|
|
|
+ });
|
|
|
+
|
|
|
+ await addAlgorithmConfigUpdate({
|
|
|
+ ...algorithmForm.value,
|
|
|
+ id: algorithmId.value,
|
|
|
+ chillers: chillersList.value,
|
|
|
+ chilledWaterOutletTempRangeList: timeList,
|
|
|
+ chilledWaterOutletTempSet: monthSettingRefs.value ? monthSettingRefs.value.stringConversion() : '',
|
|
|
+ });
|
|
|
+ });
|
|
|
+ } catch {
|
|
|
+ console.log('存在验证未通过的表单');
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+onMounted(() => {
|
|
|
+ handleRequest(async () => {
|
|
|
+ await getAlgTempCtrlMinStep();
|
|
|
+ algorithmForm.value.minCtrlStep = algTempCtrlMinStep.value[0].dictEngValue;
|
|
|
+ await getAlgTempHumCollectPeriod();
|
|
|
+ algorithmForm.value.tempHumidityCollectPeriod = algTempHumCollectPeriod.value[0].dictEngValue;
|
|
|
+ await getAlgWtTempCtrlMode();
|
|
|
+ await getAlgAlways();
|
|
|
+ await getAlgWtTempSetStep();
|
|
|
+ });
|
|
|
+});
|
|
|
+</script>
|
|
|
+
|
|
|
<template>
|
|
|
- <div>算法管理</div>
|
|
|
+ <div>
|
|
|
+ <AFlex justify="space-between">
|
|
|
+ <div class="title-text">算法配置</div>
|
|
|
+ <DeviceGroupSelect @change="handleDevGroupChange" />
|
|
|
+ </AFlex>
|
|
|
+ <div class="algorithm-content">
|
|
|
+ <ACollapse v-model:active-key="activeKey" style="border: 0" collapsible="icon">
|
|
|
+ <ACollapsePanel key="1" :style="customStyle">
|
|
|
+ <template #header>
|
|
|
+ <AFlex align="center" class="header-heigth">
|
|
|
+ <span class="header-text">主机冷冻水智控</span>
|
|
|
+ <ASwitch v-model:checked="algorithmForm.enabled" />
|
|
|
+ </AFlex>
|
|
|
+ </template>
|
|
|
+ <div>
|
|
|
+ <AForm
|
|
|
+ ref="formRef"
|
|
|
+ class="algorithm-form"
|
|
|
+ :model="algorithmForm"
|
|
|
+ label-align="left"
|
|
|
+ layout="vertical"
|
|
|
+ :rules="rules"
|
|
|
+ >
|
|
|
+ <AFlex class="flex-bottom" :gap="40">
|
|
|
+ <AFormItem label="是否下发控制指令" name="sendCtrlCmd">
|
|
|
+ <ARadioGroup v-model:value="algorithmForm.sendCtrlCmd">
|
|
|
+ <ARadio class="radio-right" :value="true">是</ARadio>
|
|
|
+ <ARadio :value="false">否</ARadio>
|
|
|
+ </ARadioGroup>
|
|
|
+ </AFormItem>
|
|
|
+ <AFormItem label="是否弹窗提醒" name="msgBox">
|
|
|
+ <ARadioGroup v-model:value="algorithmForm.msgBox">
|
|
|
+ <ARadio class="radio-right" :value="true">是</ARadio>
|
|
|
+ <ARadio :value="false">否</ARadio>
|
|
|
+ </ARadioGroup>
|
|
|
+ </AFormItem>
|
|
|
+ <AFormItem label="智控策略升温调控周期" name="tempRiseCtrlPeriod">
|
|
|
+ <AInputNumber
|
|
|
+ v-model:value="algorithmForm.tempRiseCtrlPeriod"
|
|
|
+ class="input-width"
|
|
|
+ addon-after="min"
|
|
|
+ :min="1"
|
|
|
+ :max="99999"
|
|
|
+ />
|
|
|
+ </AFormItem>
|
|
|
+ <AFormItem label="智控策略降温调控周期" name="tempReductionCtrlPeriod">
|
|
|
+ <AInputNumber
|
|
|
+ v-model:value="algorithmForm.tempReductionCtrlPeriod"
|
|
|
+ class="input-width"
|
|
|
+ addon-after="min"
|
|
|
+ :min="1"
|
|
|
+ :max="99999"
|
|
|
+ />
|
|
|
+ </AFormItem>
|
|
|
+ <AFormItem class="input-width" label="最小控制步长(℃)" name="minCtrlStep">
|
|
|
+ <ASelect
|
|
|
+ v-model:value="algorithmForm.minCtrlStep"
|
|
|
+ :options="algTempCtrlMinStep"
|
|
|
+ :field-names="{ label: 'dictValue', value: 'dictEngValue' }"
|
|
|
+ :placeholder="$t('common.plzSelect')"
|
|
|
+ />
|
|
|
+ </AFormItem>
|
|
|
+ </AFlex>
|
|
|
+ <div class="analysis-style interval-style"><span>* </span>冷冻水出水温度设定区间</div>
|
|
|
+
|
|
|
+ <div v-for="(item, index) in temperatureRangeList" :key="index">
|
|
|
+ <SetInterval
|
|
|
+ ref="setIntervalRefs"
|
|
|
+ :index="index"
|
|
|
+ :form="item"
|
|
|
+ @addClick="addClick"
|
|
|
+ @deleteClick="deleteClick"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="analysis-style"><span>* </span>初始冷冻水出水温度设定值</div>
|
|
|
+ <MonthSetting ref="monthSetting" :temperature-setting-value="temperatureSettingValue" />
|
|
|
+ <AFlex class="flex-bottom" wrap="wrap" :gap="40">
|
|
|
+ <AFormItem label="智能模式" name="intelligentMode">
|
|
|
+ <ARadioGroup v-model:value="algorithmForm.intelligentMode">
|
|
|
+ <ARadio class="radio-right" :value="0">
|
|
|
+ <AFlex align="center">
|
|
|
+ <div>智能节能</div>
|
|
|
+ <SvgIcon class="icon-style" name="question-circle-o" />
|
|
|
+ </AFlex>
|
|
|
+ </ARadio>
|
|
|
+ <ARadio :value="1">
|
|
|
+ <AFlex align="center">
|
|
|
+ <div>需求优先</div>
|
|
|
+ <SvgIcon class="icon-style" name="question-circle-o" />
|
|
|
+ </AFlex>
|
|
|
+ </ARadio>
|
|
|
+ </ARadioGroup>
|
|
|
+ </AFormItem>
|
|
|
+ <AFormItem label="控制依据" name="controlBasis">
|
|
|
+ <ARadioGroup v-model:value="algorithmForm.controlBasis">
|
|
|
+ <ARadio class="radio-right" :value="0">温度</ARadio>
|
|
|
+ <ARadio class="radio-right" :value="1">湿度</ARadio>
|
|
|
+ <ARadio :value="2">温湿度</ARadio>
|
|
|
+ </ARadioGroup>
|
|
|
+ </AFormItem>
|
|
|
+ <AFormItem label="计算周期" name="period">
|
|
|
+ <AInputNumber v-model:value="algorithmForm.period" class="input-width" addon-after="min" />
|
|
|
+ </AFormItem>
|
|
|
+ <AFormItem label="温度安全余量" name="tempSafetyMargin">
|
|
|
+ <AInputNumber v-model:value="algorithmForm.tempSafetyMargin" class="input-width" addon-after="℃" />
|
|
|
+ </AFormItem>
|
|
|
+
|
|
|
+ <AFormItem label="湿度安全余量" name="humiditySafetyMargin">
|
|
|
+ <AInputNumber
|
|
|
+ v-model:value="algorithmForm.humiditySafetyMargin"
|
|
|
+ class="input-width"
|
|
|
+ addon-after="%"
|
|
|
+ />
|
|
|
+ </AFormItem>
|
|
|
+ <AFormItem label="温湿度采集周期(min)" name="tempHumidityCollectPeriod">
|
|
|
+ <ASelect
|
|
|
+ class="input-width"
|
|
|
+ v-model:value="algorithmForm.tempHumidityCollectPeriod"
|
|
|
+ :options="algTempHumCollectPeriod"
|
|
|
+ :field-names="{ label: 'dictValue', value: 'dictEngValue' }"
|
|
|
+ :placeholder="$t('common.plzSelect')"
|
|
|
+ />
|
|
|
+ </AFormItem>
|
|
|
+ <AFormItem label="供水温度来源" name="waterSupplyTempSource">
|
|
|
+ <ARadioGroup v-model:value="algorithmForm.waterSupplyTempSource">
|
|
|
+ <ARadio class="radio-right" :value="0">加权 </ARadio>
|
|
|
+ <ARadio :value="1"> 读取 </ARadio>
|
|
|
+ </ARadioGroup>
|
|
|
+ </AFormItem>
|
|
|
+ </AFlex>
|
|
|
+ </AForm>
|
|
|
+ </div>
|
|
|
+ </ACollapsePanel>
|
|
|
+
|
|
|
+ <ACollapsePanel
|
|
|
+ v-show="chillersList.length > 0"
|
|
|
+ :style="customStyle"
|
|
|
+ v-for="item in chillersList"
|
|
|
+ :key="item.id"
|
|
|
+ >
|
|
|
+ <template #header>
|
|
|
+ <AFlex align="center" class="header-heigth">
|
|
|
+ <span class="header-text">{{ item.deviceName }}</span>
|
|
|
+ </AFlex>
|
|
|
+ </template>
|
|
|
+ <EquipmentControl
|
|
|
+ ref="equipmentControlRefs"
|
|
|
+ :alg-wt-temp-ctrl-mode="algWtTempCtrlMode"
|
|
|
+ :alg-always="algAlways"
|
|
|
+ :alg-wt-temp-set-step="algWtTempSetStep"
|
|
|
+ :form="item"
|
|
|
+ />
|
|
|
+ </ACollapsePanel>
|
|
|
+
|
|
|
+ <ACollapsePanel key="3" :style="customStyle">
|
|
|
+ <template #header>
|
|
|
+ <AFlex align="center" class="header-heigth">
|
|
|
+ <span class="header-text">系统功能设置</span>
|
|
|
+ </AFlex>
|
|
|
+ </template>
|
|
|
+ <div>
|
|
|
+ <AFlex align="center" class="analysis-bottom">
|
|
|
+ <div class="text">能效分析</div>
|
|
|
+ <ASwitch class="analysis-margin" v-model:checked="algorithmForm.analysis" />
|
|
|
+ <div @click="analysisEditor" class="editor-style">编辑</div>
|
|
|
+ </AFlex>
|
|
|
+ <AFlex align="center">
|
|
|
+ <div class="div-width">动态调整</div>
|
|
|
+ <AFlex align="center" class="adjustment-div">
|
|
|
+ <div class="adjustment-text">动态调整冷冻总管出水温度设定值</div>
|
|
|
+ <ASwitch v-model:checked="algorithmForm.enableRefrigerationPipeDynamicSet" />
|
|
|
+ <div class="adjustment-text adjustment-left">动态调整冷却总管回水温度设定值</div>
|
|
|
+ <ASwitch v-model:checked="algorithmForm.enableCoolingPipeDynamicSet" />
|
|
|
+ <div @click="setEditor" class="editor-style editor-left">编辑</div>
|
|
|
+ </AFlex>
|
|
|
+ </AFlex>
|
|
|
+ </div>
|
|
|
+ </ACollapsePanel>
|
|
|
+ </ACollapse>
|
|
|
+ <AFlex justify="space-between" class="bottom-style">
|
|
|
+ <AButton type="text">取消</AButton>
|
|
|
+ <AButton type="primary" class="button-width" @click="addAlgorithm">确定</AButton>
|
|
|
+ </AFlex>
|
|
|
+ </div>
|
|
|
+ <AModal v-model:open="analysisOpen" title="能效分析设置" width="460px" :mask-closable="false" @ok="okConfirm">
|
|
|
+ <div class="analysis-style"><span>* </span>能效分析计算方式</div>
|
|
|
+ <ARadioGroup v-model:value="analysisTypeDisplay">
|
|
|
+ <ARadio class="radio-right" :value="0">冷量表</ARadio>
|
|
|
+ <ARadio class="radio-right" :value="1">流量表</ARadio>
|
|
|
+ <ARadio :value="2">COP算法</ARadio>
|
|
|
+ </ARadioGroup>
|
|
|
+ </AModal>
|
|
|
+ <AModal v-model:open="setOpen" title="设置" width="460px" :mask-closable="false" @ok="okSetConfirm">
|
|
|
+ <AFlex align="center" class="set-top set-bottom">
|
|
|
+ <div class="text">冷却总管回水温度设定值(℃) = 室外湿球温度 +</div>
|
|
|
+
|
|
|
+ <AInputNumber v-model:value="coolingPipeDynamicOffsetDisplay" :min="-99999.99999" :max="99999" />
|
|
|
+ </AFlex>
|
|
|
+ <AFlex align="center" class="set-bottom">
|
|
|
+ <div class="text set-text">初始值(℃)</div>
|
|
|
+ <AInputNumber
|
|
|
+ class="set-input-width set-input-right"
|
|
|
+ v-model:value="coolingPipeDynamicSetDisplay"
|
|
|
+ :min="-99999.99999"
|
|
|
+ :max="99999"
|
|
|
+ />
|
|
|
+ <div class="set-text text">死区(℃)</div>
|
|
|
+ <AInputNumber
|
|
|
+ class="set-input-width"
|
|
|
+ v-model:value="coolingPipeDynamicDeadZoneDisplay"
|
|
|
+ :min="-99999.99999"
|
|
|
+ :max="99999"
|
|
|
+ />
|
|
|
+ </AFlex>
|
|
|
+
|
|
|
+ <AFlex align="center" class="set-bottom">
|
|
|
+ <div class="text lower-limit">下限(℃)</div>
|
|
|
+ <AInputNumber
|
|
|
+ class="set-input-width set-input-right"
|
|
|
+ v-model:value="coolingPipeDynamicLowerDisplay"
|
|
|
+ :min="-99999.99999"
|
|
|
+ :max="99999"
|
|
|
+ />
|
|
|
+ <div class="set-text text">上限(℃)</div>
|
|
|
+ <AInputNumber
|
|
|
+ class="set-input-width"
|
|
|
+ v-model:value="coolingPipeDynamicUpperDisplay"
|
|
|
+ :min="-99999.99999"
|
|
|
+ :max="99999"
|
|
|
+ />
|
|
|
+ </AFlex>
|
|
|
+ </AModal>
|
|
|
+ </div>
|
|
|
</template>
|
|
|
+
|
|
|
+<style lang="scss" scoped>
|
|
|
+.button-width {
|
|
|
+ width: 128px;
|
|
|
+ height: 40px;
|
|
|
+}
|
|
|
+
|
|
|
+.bottom-style {
|
|
|
+ width: 55%;
|
|
|
+ padding-left: 28px;
|
|
|
+ margin-top: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.set-top {
|
|
|
+ margin-top: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.set-bottom {
|
|
|
+ margin-bottom: 24px;
|
|
|
+}
|
|
|
+
|
|
|
+.lower-limit {
|
|
|
+ margin-right: 26px;
|
|
|
+}
|
|
|
+
|
|
|
+.set-input-right {
|
|
|
+ margin-right: 40px;
|
|
|
+}
|
|
|
+
|
|
|
+.algorithm-form :deep(.ant-form-item-label > label) {
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+
|
|
|
+.set-text {
|
|
|
+ margin-right: 12px;
|
|
|
+}
|
|
|
+
|
|
|
+.text {
|
|
|
+ font-size: 14px;
|
|
|
+ font-style: normal;
|
|
|
+ font-weight: 400;
|
|
|
+ line-height: 22px;
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+
|
|
|
+.set-input-width {
|
|
|
+ width: 96px;
|
|
|
+}
|
|
|
+
|
|
|
+.editor-left {
|
|
|
+ margin-left: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.adjustment-left {
|
|
|
+ margin-left: 82px;
|
|
|
+}
|
|
|
+
|
|
|
+.adjustment-text {
|
|
|
+ margin-right: 16px;
|
|
|
+ font-size: 14px;
|
|
|
+ font-style: normal;
|
|
|
+ font-weight: 400;
|
|
|
+ line-height: 22px;
|
|
|
+ color: #666;
|
|
|
+ text-align: left;
|
|
|
+}
|
|
|
+
|
|
|
+.analysis-style {
|
|
|
+ margin-top: 16px;
|
|
|
+ margin-bottom: 13px;
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+
|
|
|
+.analysis-style span {
|
|
|
+ color: red;
|
|
|
+}
|
|
|
+
|
|
|
+.analysis-bottom {
|
|
|
+ margin-bottom: 24px;
|
|
|
+}
|
|
|
+
|
|
|
+.div-width {
|
|
|
+ width: 72px;
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+
|
|
|
+.adjustment-div {
|
|
|
+ width: 100%;
|
|
|
+ height: 72px;
|
|
|
+ padding-left: 16px;
|
|
|
+ background: #f5f7fa;
|
|
|
+ border-radius: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.editor-style {
|
|
|
+ color: #32bac0;
|
|
|
+ text-decoration: underline;
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+
|
|
|
+.analysis-margin {
|
|
|
+ margin: 0 18px 0 17px;
|
|
|
+}
|
|
|
+
|
|
|
+.header-heigth {
|
|
|
+ height: 32px;
|
|
|
+}
|
|
|
+
|
|
|
+.icon-style {
|
|
|
+ margin-left: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+.flex-margin {
|
|
|
+ margin: 16px 0;
|
|
|
+}
|
|
|
+
|
|
|
+.radio-right {
|
|
|
+ margin-right: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.flex-bottom {
|
|
|
+ row-gap: 0 !important;
|
|
|
+}
|
|
|
+
|
|
|
+.input-width {
|
|
|
+ width: 192px;
|
|
|
+}
|
|
|
+
|
|
|
+.header-text {
|
|
|
+ margin-right: 18px;
|
|
|
+ font-size: 16px;
|
|
|
+ font-style: normal;
|
|
|
+ font-weight: 500;
|
|
|
+ line-height: 24px;
|
|
|
+ color: #000;
|
|
|
+ text-align: left;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.algorithm-content) {
|
|
|
+ .ant-collapse > .ant-collapse-item > .ant-collapse-header .ant-collapse-expand-icon {
|
|
|
+ margin-top: 6px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .ant-input-number-group .ant-input-number-group-addon {
|
|
|
+ background-color: #fff;
|
|
|
+ }
|
|
|
+
|
|
|
+ .ant-collapse .ant-collapse-content {
|
|
|
+ border: 0;
|
|
|
+
|
|
|
+ .ant-collapse-content-box {
|
|
|
+ padding: 16px 0;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.algorithm-content {
|
|
|
+ width: 100%;
|
|
|
+ height: 100%;
|
|
|
+ padding: 24px;
|
|
|
+ margin-top: 16px;
|
|
|
+ background: #fff;
|
|
|
+ border-radius: 16px;
|
|
|
+}
|
|
|
+
|
|
|
+.title-text {
|
|
|
+ font-size: 20px;
|
|
|
+ font-style: normal;
|
|
|
+ font-weight: 500;
|
|
|
+ line-height: 32px;
|
|
|
+ color: rgb(0 0 0 / 85%);
|
|
|
+ text-align: left;
|
|
|
+}
|
|
|
+
|
|
|
+.interval-style {
|
|
|
+ margin-top: 0;
|
|
|
+}
|
|
|
+</style>
|