You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

141 lines
3.2 KiB

  1. <script setup lang="ts">
  2. import { ref } from 'vue'
  3. withDefaults(defineProps<{ data: Home.HeatArea }>(), {
  4. data: () => ({ label: 'A-1', value: 'heat_module_01', selected: false, temperature: undefined }),
  5. })
  6. const emits = defineEmits(['selectChange'])
  7. const mousedownHandle = (e: Event) => {
  8. let event
  9. if ('touches' in e) {
  10. event = (e.touches as TouchList)[0]
  11. }
  12. else {
  13. event = e
  14. }
  15. if (event.target!.classList!.contains('tube-inner')) {
  16. activeTubeNum.value = event.target!.getAttribute('index')
  17. }
  18. }
  19. const activeTubeNum = ref(0)
  20. const activeTubeBox = ref(false)
  21. const tubeSelect = () => {
  22. emits('selectChange')
  23. }
  24. defineExpose({
  25. activeTubeBox,
  26. })
  27. </script>
  28. <template>
  29. <div class="tube" :class="{ 'tube-active': data.selected }">
  30. <div class="header">
  31. <span>{{ data.label }}</span>
  32. <span>已放置</span>
  33. </div>
  34. <div class="tube-item" @mousedown.prevent="mousedownHandle" @touchstart.prevent="mousedownHandle">
  35. <div v-if="false" class="tube-disable" />
  36. <span v-for="item in 16" :key="item" class="tube-inner" :class="{ 'tube-inner-active': item <= activeTubeNum }" :index="item" />
  37. </div>
  38. <div v-if="data.temperature" class="temperature-box">
  39. <span>
  40. <span>目标温度: </span>
  41. <span>{{ data.temperature }}</span>
  42. <span></span>
  43. </span>
  44. <span>加热中</span>
  45. </div>
  46. <div v-else class="temperature-box" style="justify-content: center">
  47. 点击设置目标温度
  48. </div>
  49. <div class="footer">
  50. <span :class="{ 'active-footer': data.selected }"> 200</span>
  51. <ft-button size="small" :type="data.selected ? 'primary' : 'default'" @click="tubeSelect">
  52. 选择
  53. </ft-button>
  54. </div>
  55. </div>
  56. </template>
  57. <style scoped lang="scss">
  58. .tube-active {
  59. border-color: #275EFB !important;
  60. }
  61. .tube {
  62. box-sizing: border-box;
  63. width: 100%;
  64. height: 95%;
  65. background: #E9F3FF;
  66. border-radius: 10px;
  67. padding: 10px;
  68. font-size: 14px;
  69. display: flex;
  70. flex-direction: column;
  71. justify-content: space-between;
  72. border: 2px solid #E9F3FF;
  73. transition: border 0.3s;
  74. .header {
  75. display: flex;
  76. justify-content: space-between;
  77. align-items: center;
  78. color: #4D6882;
  79. }
  80. .tube-item {
  81. padding: 5px;
  82. background: #384D5D;
  83. border-radius: 10px;
  84. display: grid;
  85. grid-template-columns: repeat(4, 1fr);
  86. grid-template-rows: repeat(4, 1fr);
  87. grid-gap: 5px;
  88. position: relative;
  89. .tube-disable {
  90. position: absolute;
  91. width: 100%;
  92. height: 100%;
  93. top: 0;
  94. left: 0;
  95. background: rgba(255,255,255,0.9);
  96. border-radius: 9px;
  97. }
  98. .tube-inner {
  99. display: inline-block;
  100. width: 25px;
  101. height: 25px;
  102. border-radius: 50%;
  103. background: #fff;
  104. margin: 2px;
  105. transition: background 0.5s;
  106. }
  107. .tube-inner-active {
  108. background: #26D574;
  109. }
  110. }
  111. .temperature-box {
  112. display: flex;
  113. justify-content: space-between;
  114. background: #fff;
  115. padding: 5px;
  116. border-radius: 5px;
  117. font-size: 12px;
  118. }
  119. .footer {
  120. display: flex;
  121. justify-content: space-between;
  122. align-items: center;
  123. font-weight: bold;
  124. color: #4D6882;
  125. .active-footer {
  126. color: #1562B7;
  127. }
  128. .ft-button {
  129. margin-right: 0;
  130. }
  131. }
  132. }
  133. </style>