index.vue 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192
  1. <template>
  2. <div class="alarm-container">
  3. <div class="alarm-header">
  4. <span class="alarm-title">{{t('alarm_settings.title')}}</span>
  5. </div>
  6. <div class="alarm-buttons">
  7. <el-button
  8. type="primary"
  9. size="large"
  10. @click="handleAlarm"
  11. class="btn-alarm"
  12. :loading="loading"
  13. >
  14. {{ t('alarm_settings.open_manual_alarm') }}
  15. </el-button>
  16. <el-button
  17. type="info"
  18. size="large"
  19. @click="handleCloseAlarm"
  20. class="btn-close"
  21. :loading="loading"
  22. >
  23. {{ t('alarm_settings.close_manual_alarm') }}
  24. </el-button>
  25. </div>
  26. <div class="alarm-tip">
  27. <span class="tip-icon">ℹ️</span>
  28. <span> {{ t('alarm_settings.tip') }}</span>
  29. </div>
  30. </div>
  31. </template>
  32. <script setup lang="ts">
  33. import { ref } from 'vue'
  34. import { ElMessage } from 'element-plus'
  35. import { cameraAlarm } from '@/api/setting'
  36. import { useI18n } from 'vue-i18n'
  37. const { t } = useI18n()
  38. const loading = ref(false)
  39. async function handleCloseAlarm() {
  40. if (loading.value) return
  41. loading.value = true
  42. try {
  43. const res = await cameraAlarm({
  44. AlarmSettings: 0
  45. })
  46. if (res.data === 'ok\n') {
  47. ElMessage.success('Manual Alarm Deactivated Successfully')
  48. } else {
  49. ElMessage.warning('Manual Alarm Deactivation Error')
  50. }
  51. } catch (error) {
  52. ElMessage.error('Manual Alarm Deactivation Error')
  53. } finally {
  54. loading.value = false
  55. }
  56. }
  57. async function handleAlarm() {
  58. if (loading.value) return
  59. loading.value = true
  60. try {
  61. const res = await cameraAlarm({
  62. AlarmSettings: 1
  63. })
  64. if (res.data === 'ok\n') {
  65. ElMessage.success('Manual alarm activated successfully. It will remain active for 1 minute.')
  66. } else {
  67. ElMessage.warning('Manual Alarm Activation Error')
  68. }
  69. } catch (error) {
  70. ElMessage.error('Failed to Activate Manual Alarm.')
  71. } finally {
  72. loading.value = false
  73. }
  74. }
  75. </script>
  76. <style scoped lang="scss">
  77. .alarm-container {
  78. background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
  79. border-radius: 12px;
  80. padding: 24px;
  81. box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
  82. border-left: 4px solid #ff6b6b;
  83. transition: all 0.3s ease;
  84. &:hover {
  85. box-shadow: 0 4px 20px rgba(0, 0, 0, 0.12);
  86. transform: translateY(-2px);
  87. }
  88. }
  89. .alarm-header {
  90. margin-bottom: 20px;
  91. padding-bottom: 12px;
  92. border-bottom: 2px solid rgba(255, 107, 107, 0.2);
  93. }
  94. .alarm-title {
  95. font-size: 16px;
  96. font-weight: 600;
  97. color: #333;
  98. display: flex;
  99. align-items: center;
  100. gap: 8px;
  101. &::before {
  102. content: '';
  103. width: 4px;
  104. height: 4px;
  105. background: #ff6b6b;
  106. border-radius: 50%;
  107. animation: pulse 2s ease-in-out infinite;
  108. }
  109. }
  110. .alarm-buttons {
  111. display: flex;
  112. gap: 16px;
  113. margin-bottom: 16px;
  114. flex-wrap: wrap;
  115. @media (max-width: 600px) {
  116. flex-direction: column;
  117. gap: 12px;
  118. }
  119. }
  120. .btn-alarm,
  121. .btn-close {
  122. flex: 1;
  123. min-width: 160px;
  124. height: 44px;
  125. font-weight: 500;
  126. letter-spacing: 0.5px;
  127. border-radius: 8px;
  128. transition: all 0.3s ease;
  129. border: none;
  130. font-size: 14px;
  131. @media (max-width: 600px) {
  132. width: 100%;
  133. }
  134. &:hover:not(:disabled) {
  135. transform: translateY(-2px);
  136. box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
  137. }
  138. &:active:not(:disabled) {
  139. transform: translateY(0);
  140. }
  141. }
  142. .btn-icon {
  143. margin-right: 6px;
  144. font-size: 16px;
  145. }
  146. .alarm-tip {
  147. display: flex;
  148. align-items: center;
  149. gap: 8px;
  150. padding: 12px;
  151. background: rgba(255, 193, 7, 0.1);
  152. border-radius: 6px;
  153. border-left: 3px solid #ffc107;
  154. font-size: 13px;
  155. color: #666;
  156. line-height: 1.5;
  157. }
  158. .tip-icon {
  159. font-size: 16px;
  160. flex-shrink: 0;
  161. }
  162. @keyframes pulse {
  163. 0%, 100% {
  164. opacity: 1;
  165. }
  166. 50% {
  167. opacity: 0.5;
  168. }
  169. }
  170. </style>