AlgorithmEditing.vue 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. <script setup lang="ts">
  2. import { onMounted, ref, useTemplateRef } from 'vue';
  3. import dayjs, { Dayjs } from 'dayjs';
  4. import SvgIcon from '@/components/SvgIcon.vue';
  5. import { useDictData } from '@/hooks/dict-data';
  6. import { useRequest } from '@/hooks/request';
  7. import { t } from '@/i18n';
  8. import { addAlgorithmConfigUpdate } from '@/api';
  9. import { DictCode } from '@/constants';
  10. import EquipmentControl from './EquipmentControl.vue';
  11. import MonthSetting from './MonthSetting.vue';
  12. import SetInterval from './SetInterval.vue';
  13. import type { FormInstance, Rule } from 'ant-design-vue/es/form';
  14. import type {
  15. AlgorithmConfigInfo,
  16. AlgorithmForm,
  17. ChillersItem,
  18. DeviceCop,
  19. TemperatureRange,
  20. TemperatureRangeItem,
  21. } from '@/types';
  22. const { dictData: algTempCtrlMinStep, getDictData: getAlgTempCtrlMinStep } = useDictData(DictCode.AlgTempCtrlMinStep);
  23. const { dictData: algTempHumCollectPeriod, getDictData: getAlgTempHumCollectPeriod } = useDictData(
  24. DictCode.AlgTempHumCollectPeriod,
  25. );
  26. const { dictData: algWtTempCtrlMode, getDictData: getAlgWtTempCtrlMode } = useDictData(DictCode.AlgWtTempCtrlMode);
  27. const { dictData: algAlways, getDictData: getAlgAlways } = useDictData(DictCode.AlgAlways);
  28. const { dictData: algWtTempSetStep, getDictData: getAlgWtTempSetStep } = useDictData(DictCode.AlgWtTempSetStep);
  29. const formRef = ref<FormInstance>();
  30. const monthSettingRefs = useTemplateRef('monthSetting');
  31. const emit = defineEmits(['confirmClick', 'cancelClick']);
  32. const setIntervalRefs = ref<InstanceType<typeof SetInterval>[]>([]);
  33. const equipmentControlRefs = ref<InstanceType<typeof EquipmentControl>[]>([]);
  34. const { handleRequest } = useRequest();
  35. const activeKey = ref<string[]>(['intelligentControl', 'functionSettings']);
  36. const customStyle = 'border-radius: 4px;;border: 0;background: #F5F6F7;margin-bottom: 4px';
  37. const analysisOpen = ref<boolean>(false);
  38. const setOpen = ref<boolean>(false);
  39. const temperatureSettingValue = ref<string>('');
  40. const analysisTypeDisplay = ref<number>(0);
  41. const coolingPipeDynamicOffsetDisplay = ref<number>(0);
  42. const coolingPipeDynamicSetDisplay = ref<number>(0);
  43. const coolingPipeDynamicDeadZoneDisplay = ref<number>(0);
  44. const coolingPipeDynamicLowerDisplay = ref<number>(0);
  45. const coolingPipeDynamicUpperDisplay = ref<number>(0);
  46. const temperatureRangeList = ref<TemperatureRange[]>([]);
  47. const chillersList = ref<ChillersItem[]>([]);
  48. const algorithmId = ref<number>();
  49. const groupId = ref<number>();
  50. const deviceCopItem = ref<DeviceCop[]>([]);
  51. const algorithmForm = ref<AlgorithmForm>({
  52. enabled: false,
  53. sendCtrlCmd: true,
  54. msgBox: true,
  55. tempRiseCtrlPeriod: 10,
  56. tempReductionCtrlPeriod: 3,
  57. minCtrlStep: '',
  58. intelligentMode: 0,
  59. controlBasis: 0,
  60. period: 0,
  61. tempSafetyMargin: 0,
  62. humiditySafetyMargin: 0,
  63. tempHumidityCollectPeriod: '',
  64. waterSupplyTempSource: 0,
  65. analysis: true,
  66. analysisType: 0,
  67. enableRefrigerationPipeDynamicSet: true,
  68. enableCoolingPipeDynamicSet: false,
  69. coolingPipeDynamicOffset: 0,
  70. coolingPipeDynamicSet: 0,
  71. coolingPipeDynamicDeadZone: 0,
  72. coolingPipeDynamicLower: 0,
  73. coolingPipeDynamicUpper: 0,
  74. });
  75. const addClick = () => {
  76. temperatureRangeList.value.push({
  77. time: undefined,
  78. lower: 0,
  79. upper: 0,
  80. });
  81. };
  82. const deleteClick = (index: number) => {
  83. temperatureRangeList.value.splice(index, 1);
  84. };
  85. const rules: Record<string, Rule[]> = {
  86. sendCtrlCmd: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  87. msgBox: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  88. tempRiseCtrlPeriod: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  89. tempReductionCtrlPeriod: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  90. minCtrlStep: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  91. intelligentMode: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  92. controlBasis: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  93. period: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  94. tempSafetyMargin: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  95. humiditySafetyMargin: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  96. tempHumidityCollectPeriod: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  97. waterSupplyTempSource: [{ required: true, message: t('common.cannotEmpty'), trigger: 'change' }],
  98. };
  99. const editorAlgorithmChange = (info: AlgorithmConfigInfo) => {
  100. temperatureRangeList.value = [];
  101. chillersList.value = [];
  102. deviceCopItem.value = [];
  103. const {
  104. id: algId,
  105. enabled,
  106. sendCtrlCmd,
  107. msgBox,
  108. tempRiseCtrlPeriod,
  109. minCtrlStep,
  110. intelligentMode,
  111. controlBasis,
  112. period,
  113. tempSafetyMargin,
  114. humiditySafetyMargin,
  115. tempHumidityCollectPeriod,
  116. waterSupplyTempSource,
  117. tempReductionCtrlPeriod,
  118. analysis,
  119. analysisType,
  120. enableRefrigerationPipeDynamicSet,
  121. enableCoolingPipeDynamicSet,
  122. coolingPipeDynamicOffset,
  123. coolingPipeDynamicSet,
  124. coolingPipeDynamicDeadZone,
  125. coolingPipeDynamicLower,
  126. coolingPipeDynamicUpper,
  127. chillers,
  128. chilledWaterOutletTempRangeList,
  129. chilledWaterOutletTempSet,
  130. devGroupId,
  131. deviceCOPList,
  132. } = info;
  133. deviceCOPList.forEach((item) => {
  134. const { id, enableCopSet, deviceName } = item;
  135. deviceCopItem.value.push({
  136. id,
  137. enableCopSet,
  138. deviceName,
  139. });
  140. });
  141. groupId.value = devGroupId;
  142. algorithmId.value = algId;
  143. Object.assign(algorithmForm.value, {
  144. enabled,
  145. sendCtrlCmd,
  146. msgBox,
  147. tempRiseCtrlPeriod,
  148. tempReductionCtrlPeriod,
  149. minCtrlStep: String(minCtrlStep),
  150. intelligentMode,
  151. controlBasis,
  152. period,
  153. tempSafetyMargin,
  154. humiditySafetyMargin,
  155. tempHumidityCollectPeriod: String(tempHumidityCollectPeriod),
  156. waterSupplyTempSource,
  157. analysis,
  158. analysisType,
  159. enableRefrigerationPipeDynamicSet,
  160. enableCoolingPipeDynamicSet,
  161. coolingPipeDynamicOffset,
  162. coolingPipeDynamicSet,
  163. coolingPipeDynamicDeadZone,
  164. coolingPipeDynamicLower,
  165. coolingPipeDynamicUpper,
  166. });
  167. analysisTypeDisplay.value = analysisType;
  168. coolingPipeDynamicOffsetDisplay.value = coolingPipeDynamicOffset;
  169. coolingPipeDynamicSetDisplay.value = coolingPipeDynamicSet;
  170. coolingPipeDynamicDeadZoneDisplay.value = coolingPipeDynamicDeadZone;
  171. coolingPipeDynamicLowerDisplay.value = coolingPipeDynamicLower;
  172. coolingPipeDynamicUpperDisplay.value = coolingPipeDynamicUpper;
  173. if (chilledWaterOutletTempSet.length) {
  174. temperatureSettingValue.value = chilledWaterOutletTempSet;
  175. } else {
  176. temperatureSettingValue.value = '0,0,0,0,0,0,0,0,0,0,0,0';
  177. }
  178. if (chilledWaterOutletTempRangeList.length) {
  179. chilledWaterOutletTempRangeList.forEach((item) => {
  180. const { startTime, endTime, lower, upper } = item;
  181. temperatureRangeList.value.push({
  182. time: [dayjs(startTime, 'HH:mm'), dayjs(endTime, 'HH:mm')],
  183. lower,
  184. upper,
  185. });
  186. });
  187. } else {
  188. temperatureRangeList.value.push({
  189. time: undefined,
  190. lower: 0,
  191. upper: 0,
  192. });
  193. }
  194. chillers.forEach((item) => {
  195. const {
  196. id,
  197. devId,
  198. waterTempControlMode,
  199. continuous,
  200. stopCompensate,
  201. restartCompensate,
  202. safeDiffPressureLower,
  203. safeLoadLower,
  204. waterTempStep,
  205. deviceName,
  206. } = item;
  207. chillersList.value.push({
  208. id,
  209. algId,
  210. devId,
  211. waterTempControlMode: String(waterTempControlMode),
  212. continuous: String(continuous),
  213. stopCompensate,
  214. restartCompensate,
  215. safeDiffPressureLower,
  216. safeLoadLower,
  217. waterTempStep: String(waterTempStep),
  218. deviceName,
  219. });
  220. });
  221. };
  222. const analysisEditor = () => {
  223. analysisTypeDisplay.value = algorithmForm.value.analysisType;
  224. analysisOpen.value = true;
  225. };
  226. const setEditor = () => {
  227. const {
  228. coolingPipeDynamicOffset,
  229. coolingPipeDynamicSet,
  230. coolingPipeDynamicDeadZone,
  231. coolingPipeDynamicLower,
  232. coolingPipeDynamicUpper,
  233. } = algorithmForm.value;
  234. coolingPipeDynamicOffsetDisplay.value = coolingPipeDynamicOffset;
  235. coolingPipeDynamicSetDisplay.value = coolingPipeDynamicSet;
  236. coolingPipeDynamicDeadZoneDisplay.value = coolingPipeDynamicDeadZone;
  237. coolingPipeDynamicLowerDisplay.value = coolingPipeDynamicLower;
  238. coolingPipeDynamicUpperDisplay.value = coolingPipeDynamicUpper;
  239. setOpen.value = true;
  240. };
  241. const okConfirm = () => {
  242. algorithmForm.value.analysisType = analysisTypeDisplay.value;
  243. analysisOpen.value = false;
  244. };
  245. const okSetConfirm = () => {
  246. algorithmForm.value.coolingPipeDynamicOffset = coolingPipeDynamicOffsetDisplay.value;
  247. algorithmForm.value.coolingPipeDynamicSet = coolingPipeDynamicSetDisplay.value;
  248. algorithmForm.value.coolingPipeDynamicDeadZone = coolingPipeDynamicDeadZoneDisplay.value;
  249. algorithmForm.value.coolingPipeDynamicLower = coolingPipeDynamicLowerDisplay.value;
  250. algorithmForm.value.coolingPipeDynamicUpper = coolingPipeDynamicUpperDisplay.value;
  251. setOpen.value = false;
  252. };
  253. // 添加格式转换
  254. const formatDate = (date: Dayjs) => date.format('HH:mm');
  255. const addAlgorithm = async () => {
  256. try {
  257. // 创建校验任务队列(包含所有子组件+父组件自身)
  258. const allTasks = [
  259. ...setIntervalRefs.value.map((c) => c.formRefSubmit()),
  260. ...equipmentControlRefs.value.map((c) => c.formRefSubmit()),
  261. formRef.value?.validate() || Promise.resolve(),
  262. monthSettingRefs.value?.formRefSubmit(),
  263. ];
  264. // 并行执行所有校验(父+子)
  265. await Promise.all(allTasks);
  266. handleRequest(async () => {
  267. const timeList: TemperatureRangeItem[] = [];
  268. temperatureRangeList.value.forEach((item) => {
  269. const { time, lower, upper } = item;
  270. const data = time?.map(formatDate) || [];
  271. timeList.push({
  272. startTime: data[0],
  273. endTime: data[1],
  274. lower,
  275. upper,
  276. });
  277. });
  278. const deviceCopList: { deviceId: number; enableCopSet: boolean }[] = [];
  279. deviceCopItem.value.forEach((item) => {
  280. const { id, enableCopSet } = item;
  281. deviceCopList.push({
  282. deviceId: id,
  283. enableCopSet,
  284. });
  285. });
  286. await addAlgorithmConfigUpdate({
  287. ...algorithmForm.value,
  288. id: algorithmId.value,
  289. chillers: chillersList.value,
  290. chilledWaterOutletTempRangeList: timeList,
  291. chilledWaterOutletTempSet: monthSettingRefs.value ? monthSettingRefs.value.stringConversion() : '',
  292. deviceCopUpdateDTOS: deviceCopList,
  293. });
  294. if (groupId.value) {
  295. emit('confirmClick', groupId.value);
  296. }
  297. });
  298. } catch {
  299. console.log('存在验证未通过的表单');
  300. }
  301. };
  302. const canceladd = () => {
  303. emit('cancelClick');
  304. };
  305. defineExpose({
  306. editorAlgorithmChange,
  307. });
  308. onMounted(() => {
  309. handleRequest(async () => {
  310. await getAlgTempCtrlMinStep();
  311. algorithmForm.value.minCtrlStep = algTempCtrlMinStep.value[0].dictEngValue;
  312. await getAlgTempHumCollectPeriod();
  313. algorithmForm.value.tempHumidityCollectPeriod = algTempHumCollectPeriod.value[0].dictEngValue;
  314. await getAlgWtTempCtrlMode();
  315. await getAlgAlways();
  316. await getAlgWtTempSetStep();
  317. });
  318. });
  319. </script>
  320. <template>
  321. <div>
  322. <!-- <AFlex justify="space-between">
  323. <div class="title-text">{{ $t('algorithmManage.algorithmConfiguration') }}</div>
  324. <DeviceGroupSelect @change="handleDevGroupChange" />
  325. </AFlex> -->
  326. <div class="algorithm-content">
  327. <ACollapse v-model:active-key="activeKey" style="border: 0" collapsible="icon">
  328. <ACollapsePanel key="intelligentControl" :style="customStyle">
  329. <template #header>
  330. <AFlex align="center" class="header-heigth">
  331. <span class="header-text">{{ $t('algorithmManage.intelligentControlChilledWater') }}</span>
  332. <ASwitch v-model:checked="algorithmForm.enabled" />
  333. </AFlex>
  334. </template>
  335. <div>
  336. <AForm
  337. ref="formRef"
  338. class="algorithm-form"
  339. :model="algorithmForm"
  340. label-align="left"
  341. layout="vertical"
  342. :rules="rules"
  343. >
  344. <AFlex class="flex-bottom" :gap="40">
  345. <AFormItem :label="t('algorithmManage.controlInstruction')" name="sendCtrlCmd">
  346. <ARadioGroup v-model:value="algorithmForm.sendCtrlCmd">
  347. <ARadio class="radio-right" :value="true">{{ $t('common.yes') }}</ARadio>
  348. <ARadio :value="false">{{ $t('common.no') }}</ARadio>
  349. </ARadioGroup>
  350. </AFormItem>
  351. <AFormItem :label="$t('algorithmManage.popupReminder')" name="msgBox">
  352. <ARadioGroup v-model:value="algorithmForm.msgBox">
  353. <ARadio class="radio-right" :value="true">{{ $t('common.yes') }}</ARadio>
  354. <ARadio :value="false">{{ $t('common.no') }}</ARadio>
  355. </ARadioGroup>
  356. </AFormItem>
  357. <AFormItem :label="t('algorithmManage.regulationCycle')" name="tempRiseCtrlPeriod">
  358. <AInputNumber
  359. v-model:value="algorithmForm.tempRiseCtrlPeriod"
  360. class="input-width"
  361. addon-after="min"
  362. :min="1"
  363. :max="99999"
  364. :placeholder="t('common.pleaseEnter')"
  365. />
  366. </AFormItem>
  367. <AFormItem :label="t('algorithmManage.coolingOffPeriod')" name="tempReductionCtrlPeriod">
  368. <AInputNumber
  369. v-model:value="algorithmForm.tempReductionCtrlPeriod"
  370. class="input-width"
  371. addon-after="min"
  372. :min="1"
  373. :max="99999"
  374. :placeholder="t('common.pleaseEnter')"
  375. />
  376. </AFormItem>
  377. <AFormItem
  378. class="input-width"
  379. :label="t('algorithmManage.controlStepSize') + '(℃)'"
  380. name="minCtrlStep"
  381. >
  382. <ASelect
  383. v-model:value="algorithmForm.minCtrlStep"
  384. :options="algTempCtrlMinStep"
  385. :field-names="{ label: 'dictValue', value: 'dictEngValue' }"
  386. :placeholder="$t('common.plzSelect')"
  387. />
  388. </AFormItem>
  389. </AFlex>
  390. <div class="analysis-style interval-style">
  391. <span>* </span>{{ $t('algorithmManage.effluentInterval') }}
  392. </div>
  393. <div v-for="(item, index) in temperatureRangeList" :key="index">
  394. <SetInterval
  395. ref="setIntervalRefs"
  396. :index="index"
  397. :form="item"
  398. @addClick="addClick"
  399. @deleteClick="deleteClick"
  400. />
  401. </div>
  402. <div class="analysis-style"><span>* </span>{{ $t('algorithmManage.waterOutletSetting') }}</div>
  403. <MonthSetting ref="monthSetting" :temperature-setting-value="temperatureSettingValue" />
  404. <AFlex class="flex-bottom" wrap="wrap" :gap="40">
  405. <AFormItem :label="t('algorithmManage.intelligentMode')" name="intelligentMode">
  406. <ARadioGroup v-model:value="algorithmForm.intelligentMode">
  407. <ARadio class="radio-right" :value="0">
  408. <AFlex align="center">
  409. <div>{{ $t('algorithmManage.intelligentEnergyConservation') }}</div>
  410. <SvgIcon class="icon-style" name="question-circle-o" />
  411. </AFlex>
  412. </ARadio>
  413. <ARadio :value="1">
  414. <AFlex align="center">
  415. <div>{{ $t('algorithmManage.prioritizeRequirements') }}</div>
  416. <SvgIcon class="icon-style" name="question-circle-o" />
  417. </AFlex>
  418. </ARadio>
  419. </ARadioGroup>
  420. </AFormItem>
  421. <AFormItem :label="t('algorithmManage.controlBasis')" name="controlBasis">
  422. <ARadioGroup v-model:value="algorithmForm.controlBasis">
  423. <ARadio class="radio-right" :value="0">{{ $t('envMonitor.temperature') }}</ARadio>
  424. <ARadio class="radio-right" :value="1">{{ $t('envMonitor.humidity') }}</ARadio>
  425. <ARadio :value="2">{{ $t('algorithmManage.temperatureHumidity') }}</ARadio>
  426. </ARadioGroup>
  427. </AFormItem>
  428. <AFormItem :label="t('algorithmManage.computingCycle')" name="period">
  429. <AInputNumber
  430. :placeholder="t('common.pleaseEnter')"
  431. v-model:value="algorithmForm.period"
  432. class="input-width"
  433. addon-after="min"
  434. />
  435. </AFormItem>
  436. <AFormItem :label="t('algorithmManage.temperatureSafetyMargin')" name="tempSafetyMargin">
  437. <AInputNumber
  438. :placeholder="t('common.pleaseEnter')"
  439. v-model:value="algorithmForm.tempSafetyMargin"
  440. class="input-width"
  441. addon-after="℃"
  442. />
  443. </AFormItem>
  444. <AFormItem :label="t('algorithmManage.humiditySafetyMargin')" name="humiditySafetyMargin">
  445. <AInputNumber
  446. v-model:value="algorithmForm.humiditySafetyMargin"
  447. class="input-width"
  448. addon-after="%"
  449. :placeholder="t('common.pleaseEnter')"
  450. />
  451. </AFormItem>
  452. <AFormItem
  453. :label="t('algorithmManage.temperatureHumidityAcquisitionCycle') + '(min)'"
  454. name="tempHumidityCollectPeriod"
  455. >
  456. <ASelect
  457. class="input-width"
  458. v-model:value="algorithmForm.tempHumidityCollectPeriod"
  459. :options="algTempHumCollectPeriod"
  460. :field-names="{ label: 'dictValue', value: 'dictEngValue' }"
  461. :placeholder="$t('common.plzSelect')"
  462. />
  463. </AFormItem>
  464. <AFormItem :label="t('algorithmManage.sourceTemperature')" name="waterSupplyTempSource">
  465. <ARadioGroup v-model:value="algorithmForm.waterSupplyTempSource">
  466. <ARadio class="radio-right" :value="0">{{ $t('algorithmManage.weighted') }} </ARadio>
  467. <ARadio :value="1"> {{ $t('algorithmManage.read') }} </ARadio>
  468. </ARadioGroup>
  469. </AFormItem>
  470. </AFlex>
  471. </AForm>
  472. </div>
  473. </ACollapsePanel>
  474. <ACollapsePanel
  475. v-show="chillersList.length > 0"
  476. :style="customStyle"
  477. v-for="item in chillersList"
  478. :key="item.id"
  479. >
  480. <template #header>
  481. <AFlex align="center" class="header-heigth">
  482. <span class="header-text">{{ item.deviceName }}</span>
  483. </AFlex>
  484. </template>
  485. <EquipmentControl
  486. ref="equipmentControlRefs"
  487. :alg-wt-temp-ctrl-mode="algWtTempCtrlMode"
  488. :alg-always="algAlways"
  489. :alg-wt-temp-set-step="algWtTempSetStep"
  490. :form="item"
  491. />
  492. </ACollapsePanel>
  493. <ACollapsePanel key="functionSettings" :style="customStyle">
  494. <template #header>
  495. <AFlex align="center" class="header-heigth">
  496. <span class="header-text">{{ $t('algorithmManage.systemFunctionSettings') }}</span>
  497. </AFlex>
  498. </template>
  499. <div>
  500. <AFlex align="center" class="analysis-bottom">
  501. <div class="text">{{ $t('energyAnalysis.energyEfficiencyAnalysis') }}</div>
  502. <ASwitch class="analysis-margin" v-model:checked="algorithmForm.analysis" />
  503. <div @click="analysisEditor" class="editor-style">{{ $t('common.editor') }}</div>
  504. </AFlex>
  505. <AFlex align="center" class="system-functions">
  506. <div class="div-width">{{ $t('algorithmManage.dynamicAdjustment') }}</div>
  507. <AFlex align="center" class="adjustment-div">
  508. <div class="adjustment-text">{{ $t('algorithmManage.freezingSetValue') }}</div>
  509. <ASwitch v-model:checked="algorithmForm.enableRefrigerationPipeDynamicSet" />
  510. <div class="adjustment-text adjustment-left">{{ $t('algorithmManage.coolingSetValue') }}</div>
  511. <ASwitch v-model:checked="algorithmForm.enableCoolingPipeDynamicSet" />
  512. <div @click="setEditor" class="editor-style editor-left">{{ $t('common.editor') }}</div>
  513. </AFlex>
  514. </AFlex>
  515. <AFlex align="center">
  516. <div class="div-width">{{ t('algorithmManage.copAlgorithm') }}</div>
  517. <AFlex align="center" class="adjustment-div" wrap="wrap">
  518. <AFlex v-for="item in deviceCopItem" :key="item.id" class="adjustment-right">
  519. <div>{{ item.deviceName }}:&nbsp;&nbsp;&nbsp;</div>
  520. <ASwitch v-model:checked="item.enableCopSet" />
  521. </AFlex>
  522. </AFlex>
  523. </AFlex>
  524. </div>
  525. </ACollapsePanel>
  526. </ACollapse>
  527. <AFlex justify="space-between" class="bottom-style">
  528. <AButton type="text" @click="canceladd">{{ $t('common.cancel') }}</AButton>
  529. <AButton type="primary" class="button-width" @click="addAlgorithm">{{ $t('common.certain') }}</AButton>
  530. </AFlex>
  531. </div>
  532. <AModal
  533. v-model:open="analysisOpen"
  534. :title="t('algorithmManage.energyEfficiencyAnalysisSettings')"
  535. width="460px"
  536. :mask-closable="false"
  537. @ok="okConfirm"
  538. >
  539. <div class="analysis-style">
  540. <span>* </span>{{ $t('algorithmManage.energyEfficiencyAnalysisCalculationMethod') }}
  541. </div>
  542. <ARadioGroup v-model:value="analysisTypeDisplay">
  543. <ARadio class="radio-right" :value="0">{{ $t('algorithmManage.thermometer') }}</ARadio>
  544. <ARadio class="radio-right" :value="1">{{ $t('algorithmManage.flowChart') }}</ARadio>
  545. <ARadio :value="2">{{ $t('algorithmManage.copAlgorithm') }}</ARadio>
  546. </ARadioGroup>
  547. </AModal>
  548. <AModal
  549. v-model:open="setOpen"
  550. :title="t('common.settings')"
  551. width="460px"
  552. :mask-closable="false"
  553. @ok="okSetConfirm"
  554. >
  555. <AFlex align="center" class="set-top set-bottom">
  556. <div class="text">
  557. {{ $t('algorithmManage.backwaterTemperatureSettingValue') }} &nbsp;=&nbsp;
  558. {{ $t('algorithmManage.outdoorWetBulbTemperature') }} +
  559. </div>
  560. &nbsp;&nbsp;
  561. <AInputNumber v-model:value="coolingPipeDynamicOffsetDisplay" :min="-99999.99999" :max="99999" />
  562. </AFlex>
  563. <AFlex align="center" class="set-bottom">
  564. <div class="text set-text">{{ $t('algorithmManage.initialValue') }}(℃)</div>
  565. <AInputNumber
  566. class="set-input-width set-input-right"
  567. v-model:value="coolingPipeDynamicSetDisplay"
  568. :min="-99999.99999"
  569. :max="99999"
  570. />
  571. <div class="set-text text">{{ $t('algorithmManage.deadZone') }}(℃)</div>
  572. <AInputNumber
  573. class="set-input-width"
  574. v-model:value="coolingPipeDynamicDeadZoneDisplay"
  575. :min="-99999.99999"
  576. :max="99999"
  577. />
  578. </AFlex>
  579. <AFlex align="center" class="set-bottom">
  580. <div class="text lower-limit">{{ $t('algorithmManage.lowerLimit') }}(℃)</div>
  581. <AInputNumber
  582. class="set-input-width set-input-right"
  583. v-model:value="coolingPipeDynamicLowerDisplay"
  584. :min="-99999.99999"
  585. :max="99999"
  586. />
  587. <div class="set-text text">{{ $t('algorithmManage.upperLimit') }}(℃)</div>
  588. <AInputNumber
  589. class="set-input-width"
  590. v-model:value="coolingPipeDynamicUpperDisplay"
  591. :min="-99999.99999"
  592. :max="99999"
  593. />
  594. </AFlex>
  595. </AModal>
  596. </div>
  597. </template>
  598. <style lang="scss" scoped>
  599. .system-functions {
  600. margin-bottom: 16px;
  601. }
  602. .adjustment-right {
  603. margin-right: 40px;
  604. }
  605. .button-width {
  606. width: 128px;
  607. height: 40px;
  608. }
  609. .bottom-style {
  610. width: 55%;
  611. padding-left: 28px;
  612. margin-top: 8px;
  613. }
  614. .set-top {
  615. margin-top: 20px;
  616. }
  617. .set-bottom {
  618. margin-bottom: 24px;
  619. }
  620. .lower-limit {
  621. margin-right: 26px;
  622. }
  623. .set-input-right {
  624. margin-right: 40px;
  625. }
  626. .algorithm-form :deep(.ant-form-item-label > label) {
  627. color: #666;
  628. }
  629. .set-text {
  630. margin-right: 12px;
  631. }
  632. .text {
  633. font-size: 14px;
  634. font-style: normal;
  635. font-weight: 400;
  636. line-height: 22px;
  637. color: #666;
  638. }
  639. .set-input-width {
  640. width: 96px;
  641. }
  642. .editor-left {
  643. margin-left: 16px;
  644. }
  645. .adjustment-left {
  646. margin-left: 82px;
  647. }
  648. .adjustment-text {
  649. margin-right: 16px;
  650. font-size: 14px;
  651. font-style: normal;
  652. font-weight: 400;
  653. line-height: 22px;
  654. color: #666;
  655. text-align: left;
  656. }
  657. .analysis-style {
  658. margin-top: 16px;
  659. margin-bottom: 13px;
  660. color: #666;
  661. }
  662. .analysis-style span {
  663. color: red;
  664. }
  665. .analysis-bottom {
  666. margin-bottom: 24px;
  667. }
  668. .div-width {
  669. width: 72px;
  670. color: #666;
  671. }
  672. .adjustment-div {
  673. width: 100%;
  674. height: 72px;
  675. padding-left: 16px;
  676. background: #f5f7fa;
  677. border-radius: 4px;
  678. }
  679. .editor-style {
  680. color: var(--antd-color-primary-hover);
  681. text-decoration: underline;
  682. cursor: pointer;
  683. }
  684. .analysis-margin {
  685. margin: 0 18px 0 17px;
  686. }
  687. .header-heigth {
  688. height: 32px;
  689. }
  690. .icon-style {
  691. margin-left: 4px;
  692. }
  693. .flex-margin {
  694. margin: 16px 0;
  695. }
  696. .radio-right {
  697. margin-right: 16px;
  698. }
  699. .flex-bottom {
  700. row-gap: 0 !important;
  701. }
  702. .input-width {
  703. width: 192px;
  704. }
  705. .header-text {
  706. margin-right: 18px;
  707. font-size: 16px;
  708. font-style: normal;
  709. font-weight: 500;
  710. line-height: 24px;
  711. color: #000;
  712. text-align: left;
  713. }
  714. :deep(.algorithm-content) {
  715. .ant-collapse > .ant-collapse-item > .ant-collapse-header .ant-collapse-expand-icon {
  716. margin-top: 6px;
  717. }
  718. .ant-input-number-group .ant-input-number-group-addon {
  719. background-color: #fff;
  720. }
  721. .ant-collapse .ant-collapse-content {
  722. border: 0;
  723. .ant-collapse-content-box {
  724. padding: 16px 0;
  725. }
  726. }
  727. }
  728. .algorithm-content {
  729. width: 100%;
  730. height: 100%;
  731. padding: 24px;
  732. margin-top: 16px;
  733. background: #fff;
  734. border-radius: 16px;
  735. }
  736. .title-text {
  737. font-size: 20px;
  738. font-style: normal;
  739. font-weight: 500;
  740. line-height: 32px;
  741. color: rgb(0 0 0 / 85%);
  742. text-align: left;
  743. }
  744. .interval-style {
  745. margin-top: 0;
  746. }
  747. </style>