RiskList.vue 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. <template>
  2. <div class="risk-container">
  3. <el-card class="search-card">
  4. <el-form :inline="true" :model="searchForm">
  5. <el-form-item label="管网ID">
  6. <el-input v-model="searchForm.networkId" placeholder="请输入管网ID" clearable />
  7. </el-form-item>
  8. <el-form-item label="风险等级">
  9. <el-select v-model="searchForm.riskLevel" placeholder="请选择" clearable>
  10. <el-option v-for="d in riskLevelDict" :key="d.dictValue" :label="d.dictLabel" :value="d.dictValue" />
  11. </el-select>
  12. </el-form-item>
  13. <el-form-item>
  14. <el-button type="primary" @click="handleSearch">查询</el-button>
  15. <el-button @click="handleReset">重置</el-button>
  16. <el-button type="success" @click="handleAdd">新增评估</el-button>
  17. </el-form-item>
  18. </el-form>
  19. </el-card>
  20. <el-card class="table-card">
  21. <el-table :data="tableData" border stripe v-loading="loading">
  22. <el-table-column prop="networkId" label="管网ID" min-width="130" />
  23. <el-table-column prop="riskLevel" label="风险等级" width="100">
  24. <template #default="{ row }">
  25. <el-tag :color="getRiskColorValue(row.riskColor)" effect="dark" size="small">{{ getDictLabel(riskLevelDict, row.riskLevel) }}</el-tag>
  26. </template>
  27. </el-table-column>
  28. <el-table-column prop="riskScore" label="风险评分" width="100" />
  29. <el-table-column prop="riskColor" label="风险颜色" width="90">
  30. <template #default="{ row }">
  31. <span :style="{ display: 'inline-block', width: 16, height: 16, background: getRiskColorValue(row.riskColor), borderRadius: 4, verticalAlign: 'middle' }"></span>
  32. <span style="margin-left: 6px">{{ getDictLabel(riskColorDict, row.riskColor) }}</span>
  33. </template>
  34. </el-table-column>
  35. <el-table-column prop="assessmentModel" label="评估模型" width="120" />
  36. <el-table-column prop="assessmentTime" label="评估时间" width="160" />
  37. <el-table-column prop="assessmentPerson" label="评估人" width="100" />
  38. <el-table-column label="操作" width="200" fixed="right">
  39. <template #default="{ row }">
  40. <el-button type="primary" size="small" @click="handleDetail(row)">详情</el-button>
  41. <el-button type="success" size="small" @click="handleEdit(row)">编辑</el-button>
  42. <el-button type="danger" size="small" @click="handleDelete(row)">删除</el-button>
  43. </template>
  44. </el-table-column>
  45. </el-table>
  46. <el-pagination
  47. v-model:current-page="pageNum" v-model:page-size="pageSize" :total="total"
  48. layout="total, prev, pager, next, sizes" :page-sizes="[10, 20, 50]"
  49. @change="loadData" style="margin-top: 16px; justify-content: flex-end"
  50. />
  51. </el-card>
  52. <el-drawer title="风险评估详情" v-model="detailVisible" size="700px" class="detail-drawer" direction="rtl">
  53. <el-descriptions :column="2" border v-if="detailData">
  54. <el-descriptions-item label="风险ID">{{ detailData.riskId }}</el-descriptions-item>
  55. <el-descriptions-item label="管网ID">{{ detailData.networkId }}</el-descriptions-item>
  56. <el-descriptions-item label="风险等级">{{ getDictLabel(riskLevelDict, detailData.riskLevel) }}</el-descriptions-item>
  57. <el-descriptions-item label="风险评分">{{ detailData.riskScore }}</el-descriptions-item>
  58. <el-descriptions-item label="评估模型">{{ detailData.assessmentModel }}</el-descriptions-item>
  59. <el-descriptions-item label="评估人">{{ detailData.assessmentPerson }}</el-descriptions-item>
  60. <el-descriptions-item label="风险构成要素" :span="2">{{ detailData.riskFactors }}</el-descriptions-item>
  61. <el-descriptions-item label="防护目标" :span="2">{{ detailData.protectiveTargets }}</el-descriptions-item>
  62. <el-descriptions-item label="危险源" :span="2">{{ detailData.hazardSources }}</el-descriptions-item>
  63. <el-descriptions-item label="维修历史" :span="2">{{ detailData.repairHistorySummary }}</el-descriptions-item>
  64. <el-descriptions-item label="备注" :span="2">{{ detailData.remark }}</el-descriptions-item>
  65. </el-descriptions>
  66. </el-drawer>
  67. <el-dialog :title="dialogTitle" v-model="dialogVisible" width="650px" destroy-on-close>
  68. <el-form :model="formData" ref="formRef" label-width="100px">
  69. <el-form-item label="管网ID" prop="networkId">
  70. <el-input v-model="formData.networkId" placeholder="请输入管网ID" />
  71. </el-form-item>
  72. <el-form-item label="风险等级" prop="riskLevel">
  73. <el-select v-model="formData.riskLevel" style="width: 100%">
  74. <el-option v-for="d in riskLevelDict" :key="d.dictValue" :label="d.dictLabel" :value="d.dictValue" />
  75. </el-select>
  76. </el-form-item>
  77. <el-form-item label="风险评分">
  78. <el-input-number v-model="formData.riskScore" :precision="2" style="width: 100%" />
  79. </el-form-item>
  80. <el-form-item label="风险颜色">
  81. <el-select v-model="formData.riskColor" style="width: 100%">
  82. <el-option v-for="d in riskColorDict" :key="d.dictValue" :label="d.dictLabel" :value="d.dictValue" />
  83. </el-select>
  84. </el-form-item>
  85. <el-form-item label="评估模型">
  86. <el-input v-model="formData.assessmentModel" />
  87. </el-form-item>
  88. <el-form-item label="评估人">
  89. <el-input v-model="formData.assessmentPerson" />
  90. </el-form-item>
  91. <el-form-item label="评估时间">
  92. <el-date-picker v-model="formData.assessmentTime" type="datetime" style="width: 100%" />
  93. </el-form-item>
  94. <el-form-item label="风险要素">
  95. <el-input v-model="formData.riskFactors" type="textarea" :rows="2" />
  96. </el-form-item>
  97. <el-form-item label="防护目标">
  98. <el-input v-model="formData.protectiveTargets" type="textarea" :rows="2" />
  99. </el-form-item>
  100. <el-form-item label="危险源">
  101. <el-input v-model="formData.hazardSources" type="textarea" :rows="2" />
  102. </el-form-item>
  103. <el-form-item label="备注">
  104. <el-input v-model="formData.remark" type="textarea" :rows="2" />
  105. </el-form-item>
  106. </el-form>
  107. <template #footer>
  108. <el-button @click="dialogVisible = false">取消</el-button>
  109. <el-button type="primary" @click="handleSave">确定</el-button>
  110. </template>
  111. </el-dialog>
  112. </div>
  113. </template>
  114. <script setup>
  115. import { ref, reactive, onMounted } from 'vue'
  116. import { ElMessage, ElMessageBox } from 'element-plus'
  117. import { getRiskPage, getRiskById, addRisk, updateRisk, deleteRisk } from '@/api/pipeNetwork/hazard'
  118. import { getDicts } from '@/api/system/dict/data'
  119. const loading = ref(false)
  120. const tableData = ref([])
  121. const pageNum = ref(1)
  122. const pageSize = ref(10)
  123. const total = ref(0)
  124. const searchForm = reactive({ networkId: '', riskLevel: '' })
  125. const dialogVisible = ref(false)
  126. const dialogTitle = ref('新增')
  127. const formRef = ref(null)
  128. const detailVisible = ref(false)
  129. const detailData = ref(null)
  130. const formData = reactive({
  131. riskId: '', networkId: '', riskLevel: '', riskScore: null, riskColor: '',
  132. assessmentModel: '', assessmentTime: '', assessmentPerson: '',
  133. riskFactors: '', protectiveTargets: '', hazardSources: '', repairHistorySummary: '', remark: ''
  134. })
  135. const riskLevelDict = ref([])
  136. const riskColorDict = ref([])
  137. const riskColorValueMap = { '0': '#F56C6C', '1': '#E6A23C', '2': '#F4D03F', '3': '#409EFF' }
  138. function getDictLabel(dict, value) {
  139. const item = dict.find(d => d.dictValue === value)
  140. return item ? item.dictLabel : value
  141. }
  142. function getRiskColorValue(value) {
  143. return riskColorValueMap[value] || '#909399'
  144. }
  145. async function loadDicts() {
  146. const [levelRes, colorRes] = await Promise.all([
  147. getDicts('risk_level'),
  148. getDicts('risk_color')
  149. ])
  150. riskLevelDict.value = levelRes.data
  151. riskColorDict.value = colorRes.data
  152. }
  153. async function loadData() {
  154. loading.value = true
  155. try {
  156. const res = await getRiskPage(pageNum.value, pageSize.value, searchForm)
  157. tableData.value = res.data.records || []
  158. total.value = res.data.total || 0
  159. } catch (e) { console.error(e) } finally { loading.value = false }
  160. }
  161. function handleSearch() { pageNum.value = 1; loadData() }
  162. function handleReset() { Object.assign(searchForm, { networkId: '', riskLevel: '' }); handleSearch() }
  163. function handleAdd() {
  164. dialogTitle.value = '新增评估'
  165. Object.assign(formData, { riskId: '', networkId: '', riskLevel: '', riskScore: null, riskColor: '', assessmentModel: '', assessmentTime: '', assessmentPerson: '', riskFactors: '', protectiveTargets: '', hazardSources: '', repairHistorySummary: '', remark: '' })
  166. dialogVisible.value = true
  167. }
  168. function handleEdit(row) { dialogTitle.value = '编辑'; Object.assign(formData, row); dialogVisible.value = true }
  169. async function handleSave() {
  170. try {
  171. if (formData.riskId) { await updateRisk(formData); ElMessage.success('修改成功') }
  172. else { await addRisk(formData); ElMessage.success('新增成功') }
  173. dialogVisible.value = false; loadData()
  174. } catch (e) { console.error(e) }
  175. }
  176. function handleDelete(row) {
  177. ElMessageBox.confirm('确认删除该评估记录?', '提示', { type: 'warning' }).then(async () => {
  178. await deleteRisk(row.riskId); ElMessage.success('删除成功'); loadData()
  179. }).catch(() => {})
  180. }
  181. async function handleDetail(row) {
  182. try {
  183. const res = await getRiskById(row.riskId)
  184. detailData.value = res.data
  185. detailVisible.value = true
  186. } catch (e) { console.error(e) }
  187. }
  188. onMounted(async () => { await loadDicts(); loadData() })
  189. </script>
  190. <style scoped>
  191. .risk-container { padding: 16px; }
  192. .search-card { margin-bottom: 16px; }
  193. </style>