AIOptimization.vue 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. <script setup lang="ts">
  2. import { computed, ref, shallowRef } from 'vue';
  3. import { message, Modal } from 'ant-design-vue';
  4. import SvgIcon from '@/components/SvgIcon.vue';
  5. import { useViewVisible } from '@/hooks/view-visible';
  6. import { t } from '@/i18n';
  7. import ChillerUnitOptimize from '../device-optimize/ChillerUnitOptimize.vue';
  8. import CoolingTowerOptimize from '../device-optimize/CoolingTowerOptimize.vue';
  9. import type { Component } from 'vue';
  10. import type { ColumnType } from 'ant-design-vue/es/table';
  11. interface OptimizeAlgorithmItem {
  12. algorithm: string;
  13. setValue: number;
  14. isEnabled: boolean;
  15. unit?: string;
  16. modalWidth?: number;
  17. modalComponent?: Component;
  18. }
  19. const dataSource = ref<OptimizeAlgorithmItem[]>([
  20. {
  21. algorithm: '冷机水温寻优',
  22. setValue: 10,
  23. isEnabled: false,
  24. unit: '°C',
  25. modalComponent: shallowRef(ChillerUnitOptimize),
  26. },
  27. {
  28. algorithm: '塔出水温度寻优',
  29. setValue: 10,
  30. isEnabled: true,
  31. unit: '°C',
  32. modalWidth: 460,
  33. modalComponent: shallowRef(CoolingTowerOptimize),
  34. },
  35. {
  36. algorithm: '冷冻泵寻优',
  37. setValue: 10,
  38. isEnabled: true,
  39. },
  40. {
  41. algorithm: '冷却泵寻优',
  42. setValue: 10,
  43. isEnabled: true,
  44. },
  45. ]);
  46. const columns = computed<ColumnType<OptimizeAlgorithmItem>[]>(() => [
  47. {
  48. title: t('realTimeMonitor.optimizationAlgorithm'),
  49. dataIndex: 'algorithm',
  50. key: 'algorithm',
  51. },
  52. {
  53. title: t('realTimeMonitor.setValue'),
  54. dataIndex: 'setValue',
  55. key: 'setValue',
  56. },
  57. {
  58. title: t('realTimeMonitor.isEnabled'),
  59. dataIndex: 'isEnabled',
  60. key: 'isEnabled',
  61. },
  62. {
  63. title: t('common.operation'),
  64. dataIndex: 'operation',
  65. key: 'operation',
  66. },
  67. ]);
  68. const handleSwitchClick = (record: OptimizeAlgorithmItem) => {
  69. const titlePrefix = record.isEnabled ? t('common.confirmClose') : t('common.confirmOpen');
  70. Modal.confirm({
  71. title: titlePrefix + record.algorithm,
  72. closable: true,
  73. async onOk() {
  74. try {
  75. record.isEnabled = !record.isEnabled;
  76. } catch (err) {
  77. message.error((err as Error).message);
  78. console.error(err);
  79. }
  80. },
  81. });
  82. };
  83. const selectedAlgorithm = ref<OptimizeAlgorithmItem>();
  84. const handleSettingClick = (record: OptimizeAlgorithmItem) => {
  85. selectedAlgorithm.value = record;
  86. showView();
  87. };
  88. const { visible, showView } = useViewVisible();
  89. const modalTitle = computed(() => {
  90. return selectedAlgorithm.value?.algorithm + t('common.settings');
  91. });
  92. const handleOk = () => {
  93. // 实际场景中处理确定逻辑
  94. };
  95. </script>
  96. <template>
  97. <div>
  98. <ATable class="ai-optimize-table" :columns="columns" :data-source="dataSource" :pagination="false">
  99. <template #bodyCell="{ column, record }">
  100. <template v-if="column.key === 'algorithm'">
  101. <span>{{ record.algorithm }}</span>
  102. <span v-if="record.unit">({{ record.unit }})</span>
  103. </template>
  104. <template v-if="column.key === 'setValue'">
  105. <AInput class="ai-optimize-input" v-model:value="record.setValue" />
  106. </template>
  107. <template v-if="column.key === 'isEnabled'">
  108. <ASwitch
  109. :checked="record.isEnabled"
  110. :checked-children="$t('common.on')"
  111. :un-checked-children="$t('common.off')"
  112. @click="handleSwitchClick(record as OptimizeAlgorithmItem)"
  113. />
  114. </template>
  115. <template v-else-if="column.key === 'operation'">
  116. <div class="ai-optimize-setting">
  117. <SvgIcon name="setting" @click="handleSettingClick(record as OptimizeAlgorithmItem)" />
  118. </div>
  119. </template>
  120. </template>
  121. </ATable>
  122. <AModal
  123. v-model:open="visible"
  124. wrap-class-name="hvac-modal ai-optimize-modal"
  125. :title="modalTitle"
  126. :width="selectedAlgorithm?.modalWidth || 920"
  127. destroy-on-close
  128. @ok="handleOk"
  129. >
  130. <component :is="selectedAlgorithm?.modalComponent" />
  131. </AModal>
  132. </div>
  133. </template>
  134. <style lang="scss">
  135. .ai-optimize-modal {
  136. .ant-modal-body {
  137. max-height: 638px;
  138. overflow-y: auto;
  139. }
  140. }
  141. </style>
  142. <style lang="scss" scoped>
  143. :deep(.ai-optimize-table).ant-table-wrapper .ant-table {
  144. color: rgba(255 255 255 / 85%);
  145. background: transparent;
  146. .ant-table-thead > tr > th {
  147. padding: 12px;
  148. font-size: 14px;
  149. font-weight: 500;
  150. color: rgba(255 255 255 / 85%);
  151. background: rgba(255 255 255 / 8%);
  152. border-bottom: none;
  153. }
  154. .ant-table-header {
  155. border-radius: 0;
  156. }
  157. table > thead > tr:first-child > {
  158. *:first-child {
  159. border-start-start-radius: 0;
  160. }
  161. *:last-child {
  162. border-start-end-radius: 0;
  163. }
  164. }
  165. .ant-table-thead
  166. > tr
  167. > th.ant-table-cell:not(:last-child, .ant-table-selection-column, .ant-table-row-expand-icon-cell, [colspan]) {
  168. &::before {
  169. background-color: transparent;
  170. }
  171. }
  172. .ant-table-tbody > tr {
  173. > td {
  174. padding-inline: 12px;
  175. border-top-color: rgba(255 255 255 / 8%);
  176. }
  177. &:last-child > td {
  178. border-bottom-color: rgba(255 255 255 / 8%);
  179. }
  180. &.ant-table-row:hover > td,
  181. > td.ant-table-cell-row-hover {
  182. background: rgba(255 255 255 / 8%);
  183. }
  184. }
  185. }
  186. .ai-optimize-input {
  187. width: 96px;
  188. color: #fff;
  189. background: rgb(30 37 48 / 32%);
  190. border-color: rgb(255 255 255 / 24%);
  191. border-radius: 4px;
  192. &.ant-input:hover,
  193. &.ant-input:focus,
  194. &.ant-input-focused {
  195. border-color: var(--antd-color-primary-hover);
  196. }
  197. }
  198. .ai-optimize-setting {
  199. display: flex;
  200. align-items: center;
  201. justify-content: center;
  202. font-size: 24px;
  203. color: var(--antd-color-primary);
  204. cursor: pointer;
  205. }
  206. </style>