EmotionAlertManage.vue 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. <template>
  2. <div class="emotion-alert-manage admin-page">
  3. <div class="header">
  4. <h2>情绪告警管理</h2>
  5. <el-input v-model="keyword" placeholder="搜索..." prefix-icon="el-icon-search" style="width:200px" clearable @keyup.enter.native="handleSearch" @clear="handleSearch" />
  6. <el-radio-group v-model="resolvedFilter" @change="onFilterChange">
  7. <el-radio-button label="">全部</el-radio-button>
  8. <el-radio-button label="false">未处理</el-radio-button>
  9. <el-radio-button label="true">已处理</el-radio-button>
  10. </el-radio-group>
  11. </div>
  12. <div class="table-scroll-wrap">
  13. <el-table :max-height="tableHeight" :data="list" v-loading="loading" border stripe>
  14. <el-table-column prop="id" label="ID" width="70" />
  15. <el-table-column prop="childId" label="孩子ID" width="90" />
  16. <el-table-column label="告警类型" width="140">
  17. <template slot-scope="{ row }">
  18. {{ alertTypeLabel(row.alertType) }}
  19. </template>
  20. </el-table-column>
  21. <el-table-column label="严重程度" width="100">
  22. <template slot-scope="{ row }">
  23. <el-tag :type="severityType(row.severity)">{{ severityLabel(row.severity) }}</el-tag>
  24. </template>
  25. </el-table-column>
  26. <el-table-column prop="title" label="标题" width="180" show-overflow-tooltip />
  27. <el-table-column prop="message" label="详情" min-width="220" show-overflow-tooltip />
  28. <el-table-column label="状态" width="80">
  29. <template slot-scope="{ row }">
  30. <el-tag :type="row.resolved ? 'success' : 'danger'" size="small">
  31. {{ row.resolved ? '已处理' : '未处理' }}
  32. </el-tag>
  33. </template>
  34. </el-table-column>
  35. <el-table-column label="创建时间" width="160" sortable="custom" :sort-orders="['ascending','descending']"
  36. <template slot-scope="{ row }" sortable="custom" :sort-orders="['ascending','descending']"
  37. {{ formatTime(row.createdAt) }}
  38. </template>
  39. </el-table-column>
  40. <el-table-column label="处理时间" width="160">
  41. <template slot-scope="{ row }">
  42. {{ row.resolvedAt ? formatTime(row.resolvedAt) : '-' }}
  43. </template>
  44. </el-table-column>
  45. <el-table-column label="操作" width="160" fixed="right">
  46. <template slot-scope="{ row }">
  47. <el-button
  48. v-if="!row.resolved"
  49. type="primary"
  50. size="mini"
  51. @click="handleResolve(row)"
  52. >标记已处理</el-button>
  53. <span v-else class="resolved-text">-</span>
  54. </template>
  55. </el-table-column>
  56. </el-table>
  57. </el-table>
  58. </div><el-pagination
  59. @size-change="onSizeChange"
  60. @current-change="onPageChange"
  61. :current-page="page"
  62. :page-size="size"
  63. :total="total"
  64. layout="total, prev, pager, next"
  65. style="margin-top: 20px; text-align: right;"
  66. />
  67. </div>
  68. </template>
  69. <script>
  70. import { getEmotionAlertList, resolveEmotionAlert } from '@/api/admin'
  71. export default {
  72. name: 'EmotionAlertManage',
  73. computed: {
  74. tableHeight() {
  75. return window.innerHeight - 300
  76. }
  77. },
  78. data() {
  79. return {
  80. list: [],
  81. loading: false,
  82. page: 1,
  83. size: 20,
  84. total: 0,
  85. keyword: '',
  86. resolvedFilter: ''
  87. sortProp: '' ,
  88. sortOrder: '' ,
  89. }
  90. },
  91. mounted() {
  92. this.loadList()
  93. },
  94. methods: {
  95. async loadList() {
  96. this.loading = true
  97. try {
  98. var params = { page: this.page, size: this.size }
  99. if (this.resolvedFilter !== '') {
  100. params.resolved = this.resolvedFilter
  101. handleSortChange({ prop, order }) {
  102. this.sortProp = prop
  103. this.sortOrder = order
  104. this.page = 1
  105. this.fetchList && this.fetchList()
  106. },
  107. }
  108. if (this.keyword) {
  109. params.keyword = this.keyword
  110. }
  111. var res = await getEmotionAlertList(params)
  112. this.list = res.data && res.data.list ? res.data.list : []
  113. this.total = res.data && res.data.total ? res.data.total : 0
  114. } catch (e) {
  115. this.$message.error('加载失败')
  116. } finally {
  117. this.loading = false
  118. }
  119. },
  120. onFilterChange() {
  121. this.page = 1
  122. this.loadList()
  123. },
  124. handleSearch() {
  125. this.page = 1
  126. this.loadList()
  127. },
  128. onSizeChange(val) {
  129. this.size = val
  130. this.page = 1
  131. this.loadList()
  132. },
  133. onPageChange(val) {
  134. this.page = val
  135. this.loadList()
  136. },
  137. async handleResolve(row) {
  138. try {
  139. await this.$confirm('确认将该告警标记为已处理?', '提示', {
  140. confirmButtonText: '确定',
  141. cancelButtonText: '取消',
  142. type: 'warning'
  143. })
  144. await resolveEmotionAlert(row.id)
  145. this.$message.success('操作成功')
  146. this.loadList()
  147. } catch (e) {
  148. if (e !== 'cancel') {
  149. this.$message.error('操作失败')
  150. }
  151. }
  152. },
  153. alertTypeLabel(type) {
  154. var map = {
  155. consecutive_low_mood: '连续低情绪',
  156. crisis_keyword: '危机关键词',
  157. sharp_decline: '情绪锐降'
  158. }
  159. return map[type] || type
  160. },
  161. severityType(severity) {
  162. var map = { high: 'danger', medium: 'warning', low: 'info' }
  163. return map[severity] || 'info'
  164. },
  165. severityLabel(severity) {
  166. var map = { high: '高', medium: '中', low: '低' }
  167. return map[severity] || severity
  168. },
  169. formatTime(t) {
  170. if (!t) return '-'
  171. return t.replace ? t.replace('T', ' ').substring(0, 19) : t
  172. }
  173. }
  174. }
  175. </script>
  176. <style scoped>
  177. .emotion-alert-manage {
  178. padding: 20px;
  179. }
  180. .header {
  181. display: flex;
  182. justify-content: space-between;
  183. align-items: center;
  184. margin-bottom: 20px;
  185. }
  186. .header h2 {
  187. margin: 0;
  188. }
  189. .resolved-text {
  190. color: #909399;
  191. }
  192. </style>